diff options
-rw-r--r-- | common/polygon.cpp | 6 | ||||
-rw-r--r-- | common/polygon.h | 28 | ||||
-rw-r--r-- | common/shape.h | 2 | ||||
-rw-r--r-- | common/xmlparser.cpp | 2 | ||||
-rw-r--r-- | common/xmlparser.h | 9 | ||||
-rw-r--r-- | dists/msvc8/scummvm.vcproj | 46 | ||||
-rw-r--r-- | gui/Copy of virtualKeyboard.cpp | 102 | ||||
-rw-r--r-- | gui/Copy of virtualKeyboard.h (renamed from gui/virtualKeyboard.h) | 41 | ||||
-rw-r--r-- | gui/virtualKeyboard.cpp | 50 | ||||
-rw-r--r-- | gui/virtualKeyboardParser.cpp | 226 | ||||
-rw-r--r-- | gui/virtualKeyboardParser.h | 15 |
11 files changed, 453 insertions, 74 deletions
diff --git a/common/polygon.cpp b/common/polygon.cpp index 4a41d127d5..c1332b0bc4 100644 --- a/common/polygon.cpp +++ b/common/polygon.cpp @@ -33,11 +33,11 @@ bool Polygon::contains(int16 x, int16 y) const { bool inside_flag = false; unsigned int pt; - const Point *vtx0 = &points[points.size() - 1]; - const Point *vtx1 = &points[0]; + const Point *vtx0 = &_points[_points.size() - 1]; + const Point *vtx1 = &_points[0]; yflag0 = (vtx0->y >= y); - for (pt = 0; pt < points.size(); pt++, vtx1++) { + for (pt = 0; pt < _points.size(); pt++, vtx1++) { yflag1 = (vtx1->y >= y); if (yflag0 != yflag1) { if (((vtx1->y - y) * (vtx0->x - vtx1->x) >= diff --git a/common/polygon.h b/common/polygon.h index af3e2fb900..e4a518193e 100644 --- a/common/polygon.h +++ b/common/polygon.h @@ -34,15 +34,14 @@ namespace Common { struct Polygon : public Shape { - Array<Point> points; Polygon() {} - Polygon(const Polygon& p) : Shape(), points(p.points), bound(p.bound) {} - Polygon(Array<Point> p) : points(p) { + Polygon(const Polygon& p) : Shape(), _points(p._points), _bound(p._bound) {} + Polygon(Array<Point> p) : _points(p) { if (p.empty()) return; - bound = Rect(p[0].x, p[0].y, p[0].x, p[0].y); + _bound = Rect(p[0].x, p[0].y, p[0].x, p[0].y); for (uint i = 1; i < p.size(); i++) { - bound.extend(Rect(p[i].x, p[i].y, p[i].x, p[i].y)); + _bound.extend(Rect(p[i].x, p[i].y, p[i].x, p[i].y)); } } Polygon(Point *p, int n) { @@ -53,14 +52,18 @@ struct Polygon : public Shape { virtual ~Polygon() {} void addPoint(const Point& p) { - points.push_back(p); - bound.extend(Rect(p.x, p.y, p.x, p.y)); + _points.push_back(p); + _bound.extend(Rect(p.x, p.y, p.x, p.y)); } void addPoint(int16 x, int16 y) { addPoint(Point(x,y)); } + uint getPointCount() { + return _points.size(); + } + /*! @brief check if given position is inside this polygon @param x the horizontal position to check @@ -81,8 +84,8 @@ struct Polygon : public Shape { } virtual void moveTo(int16 x, int16 y) { - int16 dx = x - ((bound.right + bound.left) / 2); - int16 dy = y - ((bound.bottom + bound.top) / 2); + int16 dx = x - ((_bound.right + _bound.left) / 2); + int16 dy = y - ((_bound.bottom + _bound.top) / 2); translate(dx, dy); } @@ -92,18 +95,19 @@ struct Polygon : public Shape { virtual void translate(int16 dx, int16 dy) { Array<Point>::iterator it; - for (it = points.begin(); it != points.end(); it++) { + for (it = _points.begin(); it != _points.end(); it++) { it->x += dx; it->y += dy; } } virtual Rect getBoundingRect() const { - return bound; + return _bound; } private: - Rect bound; + Array<Point> _points; + Rect _bound; }; } // end of namespace Common diff --git a/common/shape.h b/common/shape.h index 34df476718..981241eee5 100644 --- a/common/shape.h +++ b/common/shape.h @@ -31,7 +31,7 @@ namespace Common { -class Rect; +struct Rect; /*! @brief simple class for handling both 2D position and size diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 8ff93a4c59..3452db9e00 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -134,6 +134,8 @@ bool XMLParser::parse() { if (_text.ready() == false) return parserError("XML stream not ready for reading."); + cleanup(); + bool activeClosure = false; bool selfClosure = false; diff --git a/common/xmlparser.h b/common/xmlparser.h index fa1f10061a..167d04249c 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -63,7 +63,7 @@ public: _pos = idx; - return _stream->readSByte(); + return _stream->readByte(); } void loadStream(SeekableReadStream *s) { @@ -331,6 +331,13 @@ protected: return (*key == 0); } + /** + * Overload if your parser needs to support parsing the same file + * several times, so you can clean up the internal state of the + * parser before each parse. + */ + virtual void cleanup() {} + int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj index b144dc0b79..f288cf0583 100644 --- a/dists/msvc8/scummvm.vcproj +++ b/dists/msvc8/scummvm.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="windows-1252"?> <VisualStudioProject ProjectType="Visual C++" - Version="8,00" + Version="8.00" Name="scummvm" ProjectGUID="{8434CB15-D08F-427D-9E6D-581AE5B28440}" RootNamespace="scummvm" @@ -335,6 +335,14 @@ > </File> <File + RelativePath="..\..\common\imageMap.cpp" + > + </File> + <File + RelativePath="..\..\common\imageMap.h" + > + </File> + <File RelativePath="..\..\common\keyboard.h" > </File> @@ -379,6 +387,14 @@ > </File> <File + RelativePath="..\..\common\polygon.cpp" + > + </File> + <File + RelativePath="..\..\common\polygon.h" + > + </File> + <File RelativePath="..\..\common\ptr.h" > </File> @@ -395,6 +411,10 @@ > </File> <File + RelativePath="..\..\common\shape.h" + > + </File> + <File RelativePath="..\..\common\singleton.h" > </File> @@ -455,6 +475,14 @@ > </File> <File + RelativePath="..\..\common\xmlparser.cpp" + > + </File> + <File + RelativePath="..\..\common\xmlparser.h" + > + </File> + <File RelativePath="..\..\common\zlib.cpp" > </File> @@ -1218,6 +1246,22 @@ > </File> <File + RelativePath="..\..\gui\virtualKeyboard.cpp" + > + </File> + <File + RelativePath="..\..\gui\virtualKeyboard.h" + > + </File> + <File + RelativePath="..\..\gui\virtualKeyboardParser.cpp" + > + </File> + <File + RelativePath="..\..\gui\virtualKeyboardParser.h" + > + </File> + <File RelativePath="..\..\gui\widget.cpp" > </File> diff --git a/gui/Copy of virtualKeyboard.cpp b/gui/Copy of virtualKeyboard.cpp new file mode 100644 index 0000000000..b90f87edb9 --- /dev/null +++ b/gui/Copy of virtualKeyboard.cpp @@ -0,0 +1,102 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "gui/virtualKeyboard.h" +#include "gui/virtualKeyboardParser.h" +#include "common/config-manager.h" +#include "graphics/imageman.h" +#include "common/unzip.h" + +namespace GUI { + +VirtualKeyboard::VirtualKeyboard() { + assert(g_system); + _system = g_system; + + _parser = new VirtualKeyboardParser(this); + +} + +VirtualKeyboard::~VirtualKeyboard() { + +} + +bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { + if (ConfMan.hasKey("extrapath")) + Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + + if (Common::File::exists(packName + ".xml")) { + // uncompressed keyboard pack + if (!_parser->loadFile(packName + ".xml")) + return false; + + } else if (Common::File::exists(packName + ".zip")) { + // compressed keyboard pack +#ifdef USE_ZLIB + unzFile zipFile = unzOpen((packName + ".zip").c_str()); + if (zipFile && unzLocateFile(zipFile, (packName + ".xml").c_str(), 2) == UNZ_OK) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + byte *buffer = new byte[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + if (!_parser->loadBuffer(buffer, true)) { + unzClose(zipFile); + return false; + } + } else { + unzClose(zipFile); + return false; + } + unzClose(zipFile); + + ImageMan.addArchive(packName + ".zip"); +#else + return false; +#endif + } else { + warning("Keyboard pack not found"); + return false; + } + + return _parser->parse(); +} + +void VirtualKeyboard::show() { + +} + +void VirtualKeyboard::runLoop() { + +} + +void VirtualKeyboard::draw() { + +} + +} // end of namespace GUI diff --git a/gui/virtualKeyboard.h b/gui/Copy of virtualKeyboard.h index a26f01222b..ad426d4efd 100644 --- a/gui/virtualKeyboard.h +++ b/gui/Copy of virtualKeyboard.h @@ -28,6 +28,8 @@ class OSystem; +#include "common/hashmap.h" +#include "common/hash-str.h" #include "common/imagemap.h" #include "common/singleton.h" #include "common/str.h" @@ -35,25 +37,54 @@ class OSystem; namespace GUI { +class VirtualKeyboardParser; + + + class VirtualKeyboard : public Common::Singleton<VirtualKeyboard> { +private: + /** Type of key event */ + enum EventType { + kEventKey, + kEventSwitchMode, + + kEventMax + }; + + struct Event { + Common::String name; + EventType type; + void *data; + }; + + 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; + Common::ImageMap imageMap; + EventMap events; + }; public: - VirtualKeyboard(); virtual ~VirtualKeyboard(); + bool loadKeyboardPack(Common::String packName); void show(); private: OSystem *_system; + + friend class VirtualKeyboardParser; + VirtualKeyboardParser *_parser; void runLoop(); void draw(); - Common::String *_stateNames; - const Graphics::Surface **_images; - Common::ImageMap *_imageMaps; - + Common::HashMap<Common::String, Mode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _modes; }; diff --git a/gui/virtualKeyboard.cpp b/gui/virtualKeyboard.cpp deleted file mode 100644 index b3f61dbf43..0000000000 --- a/gui/virtualKeyboard.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "gui/virtualKeyboard.h" - -namespace GUI { - -VirtualKeyboard::VirtualKeyboard() { - -} - -VirtualKeyboard::~VirtualKeyboard() { - -} - -void VirtualKeyboard::show() { - -} - -void VirtualKeyboard::runLoop() { - -} - -void VirtualKeyboard::draw() { - -} - -} // end of namespace GUI diff --git a/gui/virtualKeyboardParser.cpp b/gui/virtualKeyboardParser.cpp index 40a681bee7..a3aa61c866 100644 --- a/gui/virtualKeyboardParser.cpp +++ b/gui/virtualKeyboardParser.cpp @@ -25,14 +25,238 @@ #include "gui/virtualKeyboardParser.h" +#include "common/keyboard.h" +#include "graphics/imageman.h" +#include "common/util.h" + namespace GUI { VirtualKeyboardParser::VirtualKeyboardParser(VirtualKeyboard *kbd) : XMLParser() { _keyboard = kbd; + + _callbacks["keyboard"] = &VirtualKeyboardParser::parserCallback_Keyboard; + _callbacks["mode"] = &VirtualKeyboardParser::parserCallback_Mode; + _callbacks["event"] = &VirtualKeyboardParser::parserCallback_Event; + _callbacks["layout"] = &VirtualKeyboardParser::parserCallback_Layout; + _callbacks["map"] = &VirtualKeyboardParser::parserCallback_Map; + _callbacks["area"] = &VirtualKeyboardParser::parserCallback_Area; } bool VirtualKeyboardParser::keyCallback(Common::String keyName) { - return false; + if (!_callbacks.contains(_activeKey.top()->name)) + return parserError("%s is not a valid key name.", keyName.c_str()); + + return (this->*(_callbacks[_activeKey.top()->name]))(); +} + +bool VirtualKeyboardParser::parserCallback_Keyboard() { + ParserNode *kbdNode = getActiveNode(); + + assert(kbdNode->name == "keyboard"); + + if (getParentNode(kbdNode) != 0) + return parserError("Keyboard element must be root"); + + if (_kbdParsed) + return parserError("Only a single keyboard element is allowed"); + + _kbdParsed = true; + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Mode() { + ParserNode *modeNode = getActiveNode(); + + assert(modeNode->name == "mode"); + + if (getParentNode(modeNode) == 0 || getParentNode(modeNode)->name != "keyboard") + return parserError("Mode element must be child of keyboard element"); + + if (!modeNode->values.contains("name") || !modeNode->values.contains("resolutions")) + return parserError("Mode element must contain name and resolutions attributes"); + + Common::String name = modeNode->values["name"]; + + if (_keyboard->_modes.contains(name)) + return parserError("Mode '%s' has already been defined", name); + + VirtualKeyboard::Mode mode; + mode.name = name; + _keyboard->_modes[name] = mode; + _currentMode = &(_keyboard->_modes[name]); + + Common::String resolutions = modeNode->values["resolutions"]; + Common::StringTokenizer tok(resolutions, " ,"); + + uint16 scrX = g_system->getOverlayWidth(), scrY = g_system->getOverlayHeight(); + uint16 diff = 0xFFFF; + + for (Common::String res = tok.nextToken(); res.size() > 0; res = tok.nextToken()) { + uint16 resX, resY; + if (sscanf(res.c_str(), "%dx%d", &resX, &resY) != 2) + parserError("Invalid resolution specification"); + else { + if (resX == scrX && resY == scrY) { + _currentMode->resolution = res; + break; + } else if (resX < scrX && resY < scrY) { + uint16 newDiff = (scrX - resX) + (scrY - resY); + if (newDiff < diff) { + diff = newDiff; + _currentMode->resolution = res; + } + } + } + } + + if (_currentMode->resolution.empty()) + return parserError("No acceptable resolution was found"); + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Event() { + ParserNode *evtNode = getActiveNode(); + + assert(evtNode->name == "event"); + + if (getParentNode(evtNode) == 0 || getParentNode(evtNode)->name != "mode") + return parserError("Event element must be child of mode element"); + + if (!evtNode->values.contains("name") || !evtNode->values.contains("type")) + return parserError("Event element must contain name and type attributes"); + + assert(_currentMode); + + Common::String name = evtNode->values["name"]; + if (_currentMode->events.contains(name)) + return parserError("Event '%s' has already been defined", name); + + VirtualKeyboard::Event evt; + evt.name = name; + + Common::String type = evtNode->values["type"]; + if (type == "key") { + if (!evtNode->values.contains("code") || !evtNode->values.contains("ascii")) + return parserError("Key event element must contain code and ascii attributes"); + + evt.type = VirtualKeyboard::kEventKey; + + Common::KeyCode code = (Common::KeyCode)atoi(evtNode->values["code"].c_str()); + 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; + } + } + + evt.data = new Common::KeyState(code, ascii, flags); + + } else if (type == "switch_mode") { + if (!evtNode->values.contains("mode")) + return parserError("Switch mode event element must contain mode attribute"); + + evt.type = VirtualKeyboard::kEventSwitchMode; + evt.data = new Common::String(evtNode->values["mode"]); + } else + return parserError("Event type '%s' not known", type); + + _currentMode->events[name] = evt; + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Layout() { + ParserNode *layoutNode = getActiveNode(); + + assert(layoutNode->name == "layout"); + + if (getParentNode(layoutNode) == 0 || getParentNode(layoutNode)->name != "mode") + return parserError("Layout element must be child of mode element"); + + if (!layoutNode->values.contains("resolution") || !layoutNode->values.contains("bitmap")) + return parserError("Layout element must contain resolution and bitmap attributes"); + + assert(!_currentMode->resolution.empty()); + + Common::String res = layoutNode->values["resolution"]; + + if (res != _currentMode->resolution) { + layoutNode->ignore = true; + return true; + } + + _currentMode->bitmapName = layoutNode->values["bitmap"]; + + + if (!ImageMan.registerSurface(_currentMode->bitmapName, 0)) + return parserError("Error loading bitmap '%s'", _currentMode->bitmapName.c_str()); + + _currentMode->image = ImageMan.getSurface(_currentMode->bitmapName); + if (!_currentMode->image) + return parserError("Error loading bitmap '%s'", _currentMode->bitmapName.c_str()); + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Map() { + ParserNode *mapNode = getActiveNode(); + + assert(mapNode->name == "map"); + + if (getParentNode(mapNode) == 0 || getParentNode(mapNode)->name != "layout") + return parserError("Map element must be child of layout element"); + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Area() { + ParserNode *areaNode = getActiveNode(); + + assert(areaNode->name == "area"); + + if (getParentNode(areaNode) == 0 || getParentNode(areaNode)->name != "map") + return parserError("Area element must be child of map element"); + + 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") { + int16 x1, y1, x2, y2; + if (!parseIntegerKey(areaNode->values["coords"].c_str(), 4, &x1, &y1, &x2, &y2)) + return parserError("Invalid coords for rect area"); + + Common::Rect rect(x1, y1, x2, y2); + _currentMode->imageMap.addRectMapArea(rect, areaNode->values["target"]); + } else if (shape == "poly") { + Common::StringTokenizer tok (areaNode->values["coords"], ", "); + Common::Polygon poly; + for (Common::String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { + int16 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) + return parserError("Invalid coords for polygon area"); + _currentMode->imageMap.addPolygonMapArea(poly, areaNode->values["target"]); + } else + return parserError("Area shape '%s' not known", shape); + + return true; } } // end of namespace GUI diff --git a/gui/virtualKeyboardParser.h b/gui/virtualKeyboardParser.h index 54bc398bd0..b5ed59877f 100644 --- a/gui/virtualKeyboardParser.h +++ b/gui/virtualKeyboardParser.h @@ -41,7 +41,22 @@ public: protected: VirtualKeyboard *_keyboard; + VirtualKeyboard::Mode *_currentMode; + + bool _kbdParsed; + bool keyCallback(Common::String keyName); + void cleanup() { + _currentMode = 0; + _kbdParsed = false; + } + + bool parserCallback_Keyboard(); + bool parserCallback_Mode(); + bool parserCallback_Event(); + bool parserCallback_Layout(); + bool parserCallback_Map(); + bool parserCallback_Area(); Common::HashMap<Common::String, ParserCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _callbacks; }; |