diff options
| -rw-r--r-- | backends/common/virtual-keyboard-parser.cpp | 97 | ||||
| -rw-r--r-- | backends/common/virtual-keyboard-parser.h | 4 | ||||
| -rw-r--r-- | backends/common/virtual-keyboard.cpp | 106 | ||||
| -rw-r--r-- | backends/common/virtual-keyboard.h | 67 | 
4 files changed, 220 insertions, 54 deletions
diff --git a/backends/common/virtual-keyboard-parser.cpp b/backends/common/virtual-keyboard-parser.cpp index 7b1e79e937..ed77bc215c 100644 --- a/backends/common/virtual-keyboard-parser.cpp +++ b/backends/common/virtual-keyboard-parser.cpp @@ -240,20 +240,20 @@ bool VirtualKeyboardParser::parserCallback_Event() {  		uint16 ascii = atoi(evtNode->values["ascii"].c_str());  		byte flags = 0; -		if (evtNode->values.contains("flags")) { -			Common::StringTokenizer tok(evtNode->values["flags"], ", "); -			for (Common::String fl = tok.nextToken(); !fl.empty(); fl = tok.nextToken()) { -				if (fl == "ctrl" || fl == "control") -					flags &= Common::KBD_CTRL; -				else if (fl == "alt") -					flags &= Common::KBD_ALT; -				else if (fl == "shift") -					flags &= Common::KBD_SHIFT; -			} -		} +		if (evtNode->values.contains("flags")) +			flags = parseFlags(evtNode->values["flags"]);  		evt.data = new Common::KeyState(code, ascii, flags); +	} else if (type == "modifier") { +		if (!evtNode->values.contains("flags")) +			return parserError("Key modifier element must contain modifier attributes"); +		 +		evt.type = VirtualKeyboard::kEventModifier; +		byte *flags = new byte; +		*(flags) = parseFlags(evtNode->values["flags"]); +		evt.data = flags; +  	} else if (type == "switch_mode") {  		if (!evtNode->values.contains("mode"))  			return parserError("Switch mode event element must contain mode attribute"); @@ -335,29 +335,62 @@ bool VirtualKeyboardParser::parserCallback_Area() {  	if (!areaNode->values.contains("shape") || !areaNode->values.contains("coords") || !areaNode->values.contains("target"))  		return parserError("Area element must contain shape, coords and target attributes"); -	Common::String shape = areaNode->values["shape"]; -	if (shape == "rect") { -		Common::Rect *rect = _mode->imageMap.createRectArea(areaNode->values["target"]); -		int x1, y1, x2, y2; -		if (!parseIntegerKey(areaNode->values["coords"].c_str(), 4, &x1, &y1, &x2, &y2)) -			return parserError("Invalid coords for rect area"); -		rect->left = x1; rect->top = y1; rect->right = x2; rect->bottom = y2; +	Common::String& shape = areaNode->values["shape"]; +	Common::String& target = areaNode->values["target"]; +	Common::String& coords = areaNode->values["coords"]; + +	if (target == "preview_area") { +		if (shape != "rect") +			return parserError("preview_area must be a rect area"); +		_mode->previewArea = new Common::Rect(); +		return parseRect(_mode->previewArea, coords); +	} else if (shape == "rect") { +		Common::Rect *rect = _mode->imageMap.createRectArea(target); +		return parseRect(rect, coords);  	} else if (shape == "poly") { -		Common::StringTokenizer tok (areaNode->values["coords"], ", "); -		Common::Polygon *poly = _mode->imageMap.createPolygonArea(areaNode->values["target"]); -		for (Common::String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { -			int x, y; -			if (sscanf(st.c_str(), "%d", &x) != 1) -				return parserError("Invalid coords for polygon area"); -			st = tok.nextToken(); -			if (sscanf(st.c_str(), "%d", &y) != 1) -				return parserError("Invalid coords for polygon area"); -			poly->addPoint(x, y); -		} -		if (poly->getPointCount() < 3) +		Common::Polygon *poly = _mode->imageMap.createPolygonArea(target); +		return parsePolygon(poly, coords); +	} +	return parserError("Area shape '%s' not known", shape.c_str()); +} + +byte VirtualKeyboardParser::parseFlags(const String& flags) { +	Common::StringTokenizer tok(flags, ", "); +	byte val = 0; +	for (Common::String fl = tok.nextToken(); !fl.empty(); fl = tok.nextToken()) { +		if (fl == "ctrl" || fl == "control") +			val &= Common::KBD_CTRL; +		else if (fl == "alt") +			val &= Common::KBD_ALT; +		else if (fl == "shift") +			val &= Common::KBD_SHIFT; +	} +	return val; +} + +bool VirtualKeyboardParser::parseRect(Common::Rect *rect, const String& coords) { +	int x1, y1, x2, y2; +	if (!parseIntegerKey(coords.c_str(), 4, &x1, &y1, &x2, &y2)) +		return parserError("Invalid coords for rect area"); +	rect->left = x1; rect->top = y1; rect->right = x2; rect->bottom = y2; +	if (!rect->isValidRect()) +		return parserError("Rect area is not a valid rectangle"); +	return true; +} + +bool VirtualKeyboardParser::parsePolygon(Common::Polygon *poly, const String& coords) { +	Common::StringTokenizer tok (coords, ", "); +	for (Common::String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { +		int x, y; +		if (sscanf(st.c_str(), "%d", &x) != 1)  			return parserError("Invalid coords for polygon area"); -	} else -		return parserError("Area shape '%s' not known", shape.c_str()); +		st = tok.nextToken(); +		if (sscanf(st.c_str(), "%d", &y) != 1) +			return parserError("Invalid coords for polygon area"); +		poly->addPoint(x, y); +	} +	if (poly->getPointCount() < 3) +		return parserError("Invalid coords for polygon area");  	return true;  } diff --git a/backends/common/virtual-keyboard-parser.h b/backends/common/virtual-keyboard-parser.h index cd2ea28faf..dfb7286191 100644 --- a/backends/common/virtual-keyboard-parser.h +++ b/backends/common/virtual-keyboard-parser.h @@ -203,6 +203,10 @@ protected:  	bool parserCallback_KeyboardClosed();  	bool parserCallback_ModeClosed(); +	byte parseFlags(const String& flags); +	bool parseRect(Common::Rect *rect, const String& coords); +	bool parsePolygon(Common::Polygon *poly, const String& coords); +  	Common::HashMap<Common::String, ParserCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _callbacks;  	Common::HashMap<Common::String, ParserCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _closedCallbacks;  }; diff --git a/backends/common/virtual-keyboard.cpp b/backends/common/virtual-keyboard.cpp index 0a061df545..e6ef87b946 100644 --- a/backends/common/virtual-keyboard.cpp +++ b/backends/common/virtual-keyboard.cpp @@ -63,6 +63,7 @@ void VirtualKeyboard::reset() {  	_vAlignment = kAlignBottom;  	_keyQueue.clear();  	_keyDown = 0; +	_keyFlags = 0;  	_displaying = _drag = false;  	_firstRun = true;  	_lastScreenChanged = _system->getScreenChangeID(); @@ -196,13 +197,23 @@ void VirtualKeyboard::processClick(const Common::String& area) {  	Event evt = _currentMode->events[area];  	switch (evt.type) { -	case kEventKey: +	case kEventKey: {  		// add virtual keypress to queue -		_keyQueue.push(*(Common::KeyState*)evt.data); +		Common::KeyState key = *(Common::KeyState*)evt.data; +		key.flags ^= _keyFlags; +		if ((key.keycode >= Common::KEYCODE_a) && (key.keycode <= Common::KEYCODE_z)) +			key.ascii = (key.flags & Common::KBD_SHIFT) ? key.keycode - 32 : key.keycode; +		_keyQueue.insertKey(key); +		_keyFlags = 0; +		break; +	} +	case kEventModifier: +		_keyFlags ^= *(byte*)(evt.data);  		break;  	case kEventSwitchMode:  		// switch to new mode  		switchMode(*(Common::String *)evt.data); +		_keyFlags = 0;  		break;  	case kEventClose:  		// close virtual keyboard @@ -247,7 +258,6 @@ void VirtualKeyboard::show() {  		_system->showOverlay();  		_system->clearOverlay();  	} -  	_overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor));  	_system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w);  	setupCursor(); @@ -382,4 +392,94 @@ void VirtualKeyboard::removeCursor() {  	CursorMan.popCursorPalette();  } +VirtualKeyboard::Queue::Queue() { +	_keyPos = _keys.begin(); +	_strPos = 0; +} + +void VirtualKeyboard::Queue::insertKey(KeyState key) { +	switch (key.keycode) { +	case KEYCODE_LEFT: +		moveLeft(); +		return; +	case KEYCODE_RIGHT: +		moveRight(); +		return; +	case KEYCODE_BACKSPACE: +		deleteKey(); +		return; +	} + +	String keyStr; +	if (key.keycode >= 32 && key.keycode <= 126) { +		if (key.flags & KBD_CTRL) +			keyStr += "Ctrl+"; +		if (key.flags & KBD_ALT) +			keyStr += "Alt+"; +		if (key.flags & KBD_SHIFT && (key.ascii < 65 || key.ascii > 90)) +			keyStr += "Shift+"; +		keyStr += (char)key.ascii; +	} + +	const char *k = keyStr.c_str(); +	while (char ch = *k++) +		_str.insertChar(ch, _strPos++); + +	VirtualKeyPress kp; +	kp.key = key; +	kp.strLen = keyStr.size(); +	_keys.insert(_keyPos, kp); +	_keyPos++; +} + +void VirtualKeyboard::Queue::deleteKey() { +	if (_keyPos == _keys.begin()) +		return; +	List<VirtualKeyPress>::iterator it = _keyPos; +	it--; +	_strPos -= it->strLen; +	while((it->strLen)-- > 0) +		_str.deleteChar(_strPos); +	_keys.erase(it); +} + +void VirtualKeyboard::Queue::moveLeft() { +	if (_keyPos == _keys.begin()) +		return; +	_keyPos--; +	_strPos -= _keyPos->strLen; +} + +void VirtualKeyboard::Queue::moveRight() { +	List<VirtualKeyPress>::iterator it = _keyPos; +	it++; +	if (it == _keys.end()) +		return; +	_strPos += _keyPos->strLen; +	_keyPos	= it; +} + +KeyState VirtualKeyboard::Queue::pop() { +	KeyState ret = _keys.begin()->key; +	_keys.pop_front(); +	return ret; +} + +void VirtualKeyboard::Queue::clear() { +	_keys.clear(); +	_keyPos = _keys.begin(); +	_str.clear(); +	_strPos = 0; +} + +bool VirtualKeyboard::Queue::empty() +{  +	return _keys.empty(); +} + +String VirtualKeyboard::Queue::getString() +{ +	return _str; +} +  } // end of namespace Common diff --git a/backends/common/virtual-keyboard.h b/backends/common/virtual-keyboard.h index fc2300c24c..3494de1e47 100644 --- a/backends/common/virtual-keyboard.h +++ b/backends/common/virtual-keyboard.h @@ -33,7 +33,7 @@ class OSystem;  #include "common/hash-str.h"  #include "common/image-map.h"  #include "common/keyboard.h" -#include "common/queue.h" +#include "common/list.h"  #include "common/str.h"  #include "graphics/surface.h" @@ -42,9 +42,10 @@ namespace Common {  class VirtualKeyboardParser;  class VirtualKeyboard { - +protected:  	enum EventType {  		kEventKey, +		kEventModifier,  		kEventSwitchMode,  		kEventClose  	}; @@ -59,14 +60,16 @@ class VirtualKeyboard {  	typedef Common::HashMap<Common::String, Event, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> EventMap;   	struct Mode { -		Common::String     name; -		Common::String     resolution; -		Common::String     bitmapName; -		Graphics::Surface *image; -		OverlayColor	   transparentColor; -		Common::ImageMap   imageMap; -		EventMap           events; -		Mode() : image(0) {} +		Common::String		name; +		Common::String		resolution; +		Common::String		bitmapName; +		Graphics::Surface	*image; +		OverlayColor		transparentColor; +		Common::ImageMap	imageMap; +		EventMap			events; +		Common::Rect		*previewArea; + +		Mode() : image(0), previewArea(0) {}  	};  	typedef Common::HashMap<Common::String, Mode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ModeMap; @@ -83,6 +86,31 @@ class VirtualKeyboard {  		kAlignBottom  	}; +	struct VirtualKeyPress { +		Common::KeyState key; +		uint strLen; +	}; + +	class Queue { +	public: +		Queue(); +		void insertKey(KeyState key); +		void deleteKey(); +		void moveLeft(); +		void moveRight(); +		KeyState pop(); +		void clear(); +		bool empty(); +		String getString(); + +	private: +		List<VirtualKeyPress> _keys; +		List<VirtualKeyPress>::iterator _keyPos; + +		String _str; +		uint _strPos; +	}; +  public:  	VirtualKeyboard();  	virtual ~VirtualKeyboard(); @@ -122,15 +150,19 @@ public:  		return _loaded;  	} -protected: +protected:	// TODO : clean up all this stuff  	OSystem	*_system; +	byte _keyFlags; +	Queue _keyQueue; +	KeyState *_keyDown; + +  	static const int SNAP_WIDTH = 10;  	friend class VirtualKeyboardParser;  	VirtualKeyboardParser *_parser; -	// TODO : sort order of all this stuff  	void reset();  	void deleteEventData();  	void screenChanged(); @@ -139,7 +171,7 @@ protected:  	void move(int16 x, int16 y);  	void switchMode(Mode *newMode);  	void switchMode(const Common::String& newMode); -	Common::String findArea(int16 x, int16 y); +	String findArea(int16 x, int16 y);  	void processClick(const Common::String &area);  	void runLoop();  	void redraw(); @@ -156,18 +188,15 @@ protected:  	Mode *_currentMode;  	int _lastScreenChanged; -	Common::Rect _kbdBound; +	Rect _kbdBound;  	HorizontalAlignment  _hAlignment;  	VerticalAlignment    _vAlignment; -	Common::String _areaDown; -	Common::Point _dragPoint; +	String _areaDown; +	Point _dragPoint;  	bool _drag; -	Common::Queue<Common::KeyState> _keyQueue; -	Common::KeyState *_keyDown; -  	static const int kCursorAnimateDelay = 250;  	int		_cursorAnimateCounter;  	int		_cursorAnimateTimer;  | 
