diff options
author | Matthew Hoops | 2012-03-20 14:18:57 -0400 |
---|---|---|
committer | Matthew Hoops | 2012-03-20 14:49:16 -0400 |
commit | 71756bdf4eae5ba9cc3f329b85e894f04640aaef (patch) | |
tree | 40d464262da107ab5eed82f198685209161ebac1 /common | |
parent | 03eba05b09e5c9e5a351f8111185934b92a3fed3 (diff) | |
parent | 3c3576a224b92c703b4e8ea20008ac8a069980dd (diff) | |
download | scummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.tar.gz scummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.tar.bz2 scummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.zip |
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'common')
56 files changed, 1532 insertions, 698 deletions
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index 4e3f671cfd..012a2dfce5 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -48,26 +48,24 @@ void EventDispatcher::dispatch() { dispatchPoll(); for (List<SourceEntry>::iterator i = _sources.begin(); i != _sources.end(); ++i) { - const bool allowMapping = i->source->allowMapping(); - while (i->source->pollEvent(event)) { // We only try to process the events via the setup event mapper, when // we have a setup mapper and when the event source allows mapping. - if (_mapper && allowMapping) { - if (_mapper->notifyEvent(event)) { - // We allow the event mapper to create multiple events, when - // eating an event. - while (_mapper->pollEvent(event)) - dispatchEvent(event); - - // Try getting another event from the current EventSource. - continue; - } - } + assert(_mapper); + List<Event> mappedEvents = _mapper->mapEvent(event, i->source); - dispatchEvent(event); + for (List<Event>::iterator j = mappedEvents.begin(); j != mappedEvents.end(); ++j) { + const Event mappedEvent = *j; + dispatchEvent(mappedEvent); + } } } + + List<Event> delayedEvents = _mapper->getDelayedEvents(); + for (List<Event>::iterator k = delayedEvents.begin(); k != delayedEvents.end(); ++k) { + const Event delayedEvent = *k; + dispatchEvent(delayedEvent); + } } void EventDispatcher::registerMapper(EventMapper *mapper) { diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp new file mode 100644 index 0000000000..5f6771a71d --- /dev/null +++ b/common/EventMapper.cpp @@ -0,0 +1,92 @@ +/* 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. + * + */ + +#include "common/events.h" + +#include "common/system.h" +#include "common/textconsole.h" + +namespace Common { + +List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { + List<Event> events; + Event mappedEvent; + if (ev.type == EVENT_KEYDOWN) { + if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F5) { + mappedEvent.type = EVENT_MAINMENU; + } +#ifdef ENABLE_VKEYBD + else if (ev.kbd.keycode == KEYCODE_F7 && ev.kbd.hasFlags(0)) { + mappedEvent.type = EVENT_VIRTUAL_KEYBOARD; + } +#endif +#ifdef ENABLE_KEYMAPPER + else if (ev.kbd.keycode == KEYCODE_F8 && ev.kbd.hasFlags(0)) { + mappedEvent.type = EVENT_KEYMAPPER_REMAP; + } +#endif + } + + // if it didn't get mapped, just pass it through + if (mappedEvent.type == EVENT_INVALID) + mappedEvent = ev; + +#ifdef ENABLE_KEYMAPPER + // TODO: this check is not needed post-split + if (mappedEvent.type == EVENT_CUSTOM_BACKEND_HARDWARE) { + warning("EVENT_CUSTOM_BACKEND_HARDWARE was not mapped"); + return List<Event>(); + } +#endif + + events.push_back(mappedEvent); + return events; +} + + +void DefaultEventMapper::addDelayedEvent(uint32 millis, Event ev) { + if (_delayedEvents.empty()) { + _delayedEffectiveTime = g_system->getMillis() + millis; + millis = 0; + } + DelayedEventsEntry entry = DelayedEventsEntry(millis, ev); + _delayedEvents.push(entry); +} + +List<Event> DefaultEventMapper::getDelayedEvents() { + List<Event> events; + + if (_delayedEvents.empty()) + return events; + + uint32 now = g_system->getMillis(); + + while (!_delayedEvents.empty() && now >= _delayedEffectiveTime) { + DelayedEventsEntry entry = _delayedEvents.pop(); + if (!_delayedEvents.empty()) + _delayedEffectiveTime += _delayedEvents.front().timerOffset; + events.push_back(entry.event); + } + return events; +} + +} // namespace Common diff --git a/common/archive.cpp b/common/archive.cpp index 954de8bcaa..1323f14805 100644 --- a/common/archive.cpp +++ b/common/archive.cpp @@ -27,7 +27,7 @@ namespace Common { -GenericArchiveMember::GenericArchiveMember(String name, Archive *parent) +GenericArchiveMember::GenericArchiveMember(const String &name, const Archive *parent) : _parent(parent), _name(name) { } @@ -40,14 +40,14 @@ SeekableReadStream *GenericArchiveMember::createReadStream() const { } -int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { +int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern) const { // Get all "names" (TODO: "files" ?) ArchiveMemberList allNames; listMembers(allNames); int matches = 0; - ArchiveMemberList::iterator it = allNames.begin(); + ArchiveMemberList::const_iterator it = allNames.begin(); for ( ; it != allNames.end(); ++it) { // TODO: We match case-insenstivie for now, our API does not define whether that's ok or not though... // For our use case case-insensitive is probably what we want to have though. @@ -206,11 +206,11 @@ void SearchSet::setPriority(const String &name, int priority) { insert(node); } -bool SearchSet::hasFile(const String &name) { +bool SearchSet::hasFile(const String &name) const { if (name.empty()) return false; - ArchiveNodeList::iterator it = _list.begin(); + ArchiveNodeList::const_iterator it = _list.begin(); for ( ; it != _list.end(); ++it) { if (it->_arc->hasFile(name)) return true; @@ -219,31 +219,31 @@ bool SearchSet::hasFile(const String &name) { return false; } -int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { +int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &pattern) const { int matches = 0; - ArchiveNodeList::iterator it = _list.begin(); + ArchiveNodeList::const_iterator it = _list.begin(); for ( ; it != _list.end(); ++it) matches += it->_arc->listMatchingMembers(list, pattern); return matches; } -int SearchSet::listMembers(ArchiveMemberList &list) { +int SearchSet::listMembers(ArchiveMemberList &list) const { int matches = 0; - ArchiveNodeList::iterator it = _list.begin(); + ArchiveNodeList::const_iterator it = _list.begin(); for ( ; it != _list.end(); ++it) matches += it->_arc->listMembers(list); return matches; } -ArchiveMemberPtr SearchSet::getMember(const String &name) { +const ArchiveMemberPtr SearchSet::getMember(const String &name) const { if (name.empty()) return ArchiveMemberPtr(); - ArchiveNodeList::iterator it = _list.begin(); + ArchiveNodeList::const_iterator it = _list.begin(); for ( ; it != _list.end(); ++it) { if (it->_arc->hasFile(name)) return it->_arc->getMember(name); diff --git a/common/archive.h b/common/archive.h index c8e78f9bc8..ffd86d786d 100644 --- a/common/archive.h +++ b/common/archive.h @@ -65,10 +65,10 @@ class Archive; * is destroyed. */ class GenericArchiveMember : public ArchiveMember { - Archive *_parent; - String _name; + const Archive *_parent; + const String _name; public: - GenericArchiveMember(String name, Archive *parent); + GenericArchiveMember(const String &name, const Archive *parent); String getName() const; SeekableReadStream *createReadStream() const; }; @@ -88,7 +88,7 @@ public: * Patterns are not allowed, as this is meant to be a quick File::exists() * replacement. */ - virtual bool hasFile(const String &name) = 0; + virtual bool hasFile(const String &name) const = 0; /** * Add all members of the Archive matching the specified pattern to list. @@ -96,7 +96,7 @@ public: * * @return the number of members added to list */ - virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); + virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern) const; /** * Add all members of the Archive to list. @@ -104,12 +104,12 @@ public: * * @return the number of names added to list */ - virtual int listMembers(ArchiveMemberList &list) = 0; + virtual int listMembers(ArchiveMemberList &list) const = 0; /** * Returns a ArchiveMember representation of the given file. */ - virtual ArchiveMemberPtr getMember(const String &name) = 0; + virtual const ArchiveMemberPtr getMember(const String &name) const = 0; /** * Create a stream bound to a member with the specified name in the @@ -230,11 +230,11 @@ public: */ void setPriority(const String& name, int priority); - virtual bool hasFile(const String &name); - virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); - virtual int listMembers(ArchiveMemberList &list); + virtual bool hasFile(const String &name) const; + virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern) const; + virtual int listMembers(ArchiveMemberList &list) const; - virtual ArchiveMemberPtr getMember(const String &name); + virtual const ArchiveMemberPtr getMember(const String &name) const; /** * Implements createReadStreamForMember from Archive base class. The current policy is diff --git a/common/array.h b/common/array.h index ef0ee27f24..a2c3023362 100644 --- a/common/array.h +++ b/common/array.h @@ -24,7 +24,7 @@ #include "common/scummsys.h" #include "common/algorithm.h" -#include "common/textconsole.h" // For error() +#include "common/textconsole.h" // For error() #include "common/memory.h" namespace Common { @@ -42,17 +42,19 @@ namespace Common { */ template<class T> class Array { -protected: - uint _capacity; - uint _size; - T *_storage; - public: typedef T *iterator; typedef const T *const_iterator; typedef T value_type; + typedef uint size_type; + +protected: + size_type _capacity; + size_type _size; + T *_storage; + public: Array() : _capacity(0), _size(0), _storage(0) {} @@ -67,7 +69,7 @@ public: * Construct an array by copying data from a regular array. */ template<class T2> - Array(const T2 *data, int n) { + Array(const T2 *data, size_type n) { _size = n; allocCapacity(n); uninitialized_copy(data, data + _size, _storage); @@ -128,19 +130,19 @@ public: } - void insert_at(int idx, const T &element) { - assert(idx >= 0 && (uint)idx <= _size); + void insert_at(size_type idx, const T &element) { + assert(idx <= _size); insert_aux(_storage + idx, &element, &element + 1); } - void insert_at(int idx, const Array<T> &array) { - assert(idx >= 0 && (uint)idx <= _size); + void insert_at(size_type idx, const Array<T> &array) { + assert(idx <= _size); insert_aux(_storage + idx, array.begin(), array.end()); } - T remove_at(int idx) { - assert(idx >= 0 && (uint)idx < _size); + T remove_at(size_type idx) { + assert(idx < _size); T tmp = _storage[idx]; copy(_storage + idx + 1, _storage + _size, _storage + idx); _size--; @@ -151,17 +153,17 @@ public: // TODO: insert, remove, ... - T& operator[](int idx) { - assert(idx >= 0 && (uint)idx < _size); + T &operator[](size_type idx) { + assert(idx < _size); return _storage[idx]; } - const T& operator[](int idx) const { - assert(idx >= 0 && (uint)idx < _size); + const T &operator[](size_type idx) const { + assert(idx < _size); return _storage[idx]; } - Array<T>& operator=(const Array<T> &array) { + Array<T> &operator=(const Array<T> &array) { if (this == &array) return *this; @@ -173,7 +175,7 @@ public: return *this; } - uint size() const { + size_type size() const { return _size; } @@ -193,34 +195,34 @@ public: return true; if (_size != other._size) return false; - for (uint i = 0; i < _size; ++i) { + for (size_type i = 0; i < _size; ++i) { if (_storage[i] != other._storage[i]) return false; } return true; } + bool operator!=(const Array<T> &other) const { return !(*this == other); } - - iterator begin() { + iterator begin() { return _storage; } - iterator end() { + iterator end() { return _storage + _size; } - const_iterator begin() const { + const_iterator begin() const { return _storage; } - const_iterator end() const { + const_iterator end() const { return _storage + _size; } - void reserve(uint newCapacity) { + void reserve(size_type newCapacity) { if (newCapacity <= _capacity) return; @@ -234,9 +236,9 @@ public: } } - void resize(uint newSize) { + void resize(size_type newSize) { reserve(newSize); - for (uint i = _size; i < newSize; ++i) + for (size_type i = _size; i < newSize; ++i) new ((void *)&_storage[i]) T(); _size = newSize; } @@ -249,28 +251,28 @@ public: } protected: - static uint roundUpCapacity(uint capacity) { + static size_type roundUpCapacity(size_type capacity) { // Round up capacity to the next power of 2; // we use a minimal capacity of 8. - uint capa = 8; + size_type capa = 8; while (capa < capacity) capa <<= 1; return capa; } - void allocCapacity(uint capacity) { + void allocCapacity(size_type capacity) { _capacity = capacity; if (capacity) { _storage = (T *)malloc(sizeof(T) * capacity); if (!_storage) - ::error("Common::Array: failure to allocate %u bytes", capacity * (uint)sizeof(T)); + ::error("Common::Array: failure to allocate %u bytes", capacity * (size_type)sizeof(T)); } else { _storage = 0; } } - void freeStorage(T *storage, const uint elements) { - for (uint i = 0; i < elements; ++i) + void freeStorage(T *storage, const size_type elements) { + for (size_type i = 0; i < elements; ++i) storage[i].~T(); free(storage); } @@ -291,9 +293,9 @@ protected: iterator insert_aux(iterator pos, const_iterator first, const_iterator last) { assert(_storage <= pos && pos <= _storage + _size); assert(first <= last); - const uint n = last - first; + const size_type n = last - first; if (n) { - const uint idx = pos - _storage; + const size_type idx = pos - _storage; if (_size + n > _capacity || (_storage <= first && first <= _storage + _size)) { T *const oldStorage = _storage; diff --git a/common/config-file.cpp b/common/config-file.cpp index 81e0ae6b45..4224d7491d 100644 --- a/common/config-file.cpp +++ b/common/config-file.cpp @@ -30,7 +30,7 @@ namespace Common { bool ConfigFile::isValidName(const String &name) { const char *p = name.c_str(); - while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_' || *p == '.')) + while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.')) p++; return *p == 0; } @@ -108,7 +108,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { // is, verify that it only consists of alphanumerics, // periods, dashes and underscores). Mohawk Living Books games // can have periods in their section names. - while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_' || *p == '.')) + while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.')) p++; if (*p == '\0') @@ -131,7 +131,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { // Skip leading whitespaces const char *t = line.c_str(); - while (isspace(static_cast<unsigned char>(*t))) + while (isSpace(*t)) t++; // Skip empty lines / lines with only whitespace diff --git a/common/config-manager.cpp b/common/config-manager.cpp index c62dee8bea..aaa812bc94 100644 --- a/common/config-manager.cpp +++ b/common/config-manager.cpp @@ -29,7 +29,7 @@ static bool isValidDomainName(const Common::String &domName) { const char *p = domName.c_str(); - while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_')) + while (*p && (Common::isAlnum(*p) || *p == '-' || *p == '_')) p++; return *p == 0; } @@ -187,7 +187,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) { // Get the domain name, and check whether it's valid (that // is, verify that it only consists of alphanumerics, // dashes and underscores). - while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_')) + while (*p && (isAlnum(*p) || *p == '-' || *p == '_')) p++; if (*p == '\0') @@ -205,7 +205,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) { // Skip leading whitespaces const char *t = line.c_str(); - while (isspace(static_cast<unsigned char>(*t))) + while (isSpace(*t)) t++; // Skip empty lines / lines with only whitespace diff --git a/common/endian.h b/common/endian.h index 9cb703858a..394437ec67 100644 --- a/common/endian.h +++ b/common/endian.h @@ -86,7 +86,7 @@ } // Test for GCC >= 4.3.0 as this version added the bswap builtin -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#elif GCC_ATLEAST(4, 3) FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { return __builtin_bswap32(a); @@ -156,7 +156,7 @@ // // Moreover, we activate this code for GCC >= 3.3 but *only* if unaligned access // is allowed. -#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3 && !defined(SCUMM_NEED_ALIGNMENT))) +#if GCC_ATLEAST(4, 0) || (GCC_ATLEAST(3, 3) && !defined(SCUMM_NEED_ALIGNMENT)) FORCEINLINE uint16 READ_UINT16(const void *ptr) { struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); @@ -396,4 +396,10 @@ inline uint32 READ_BE_UINT24(const void *ptr) { return (b[0] << 16) | (b[1] << 8) | (b[2]); } +#ifdef SCUMM_LITTLE_ENDIAN +#define READ_UINT24(a) READ_LE_UINT24(a) +#else +#define READ_UINT24(a) READ_BE_UINT24(a) +#endif + #endif diff --git a/common/events.h b/common/events.h index f5ace7481b..7366c51d36 100644 --- a/common/events.h +++ b/common/events.h @@ -73,8 +73,23 @@ enum EventType { * An associated enumerated type can accomplish this. **/ EVENT_PREDICTIVE_DIALOG = 12 + +#ifdef ENABLE_KEYMAPPER + , + // IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use + // this, please talk to tsoliman and/or LordHoto. + EVENT_CUSTOM_BACKEND_ACTION = 18, + EVENT_CUSTOM_BACKEND_HARDWARE = 21, + EVENT_GUI_REMAP_COMPLETE_ACTION = 22, + EVENT_KEYMAPPER_REMAP = 19 +#endif +#ifdef ENABLE_VKEYBD + , + EVENT_VIRTUAL_KEYBOARD = 20 +#endif }; +typedef uint32 CustomEventType; /** * Data structure for an event. A pointer to an instance of Event * can be passed to pollEvent. @@ -99,7 +114,17 @@ struct Event { */ Point mouse; - Event() : type(EVENT_INVALID), synthetic(false) {} +#ifdef ENABLE_KEYMAPPER + // IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use + // this, please talk to tsoliman and/or LordHoto. + CustomEventType customType; +#endif + + Event() : type(EVENT_INVALID), synthetic(false) { +#ifdef ENABLE_KEYMAPPER + customType = 0; +#endif + } }; /** @@ -175,7 +200,7 @@ public: * * An observer is supposed to eat the event, with returning true, when * it wants to prevent other observers from receiving the event. - * An usage example here is the keymapper: + * A usage example here is the keymapper: * If it processes an Event, it should 'eat' it and create a new * event, which the EventDispatcher will then catch. * @@ -199,10 +224,35 @@ public: * * An example for this is the Keymapper. */ -class EventMapper : public EventSource, public EventObserver { +class EventMapper { public: - /** For event mappers resulting events should never be mapped */ - bool allowMapping() const { return false; } + virtual ~EventMapper() {} + + /** + * Map an incoming event to one or more action events + */ + virtual List<Event> mapEvent(const Event &ev, EventSource *source) = 0; + + virtual List<Event> getDelayedEvents() = 0; +}; + +class DefaultEventMapper : public EventMapper { +public: + DefaultEventMapper() : _delayedEvents(), _delayedEffectiveTime(0) {} + // EventMapper interface + virtual List<Event> mapEvent(const Event &ev, EventSource *source); + virtual List<Event> getDelayedEvents(); +protected: + virtual void addDelayedEvent(uint32 millis, Event ev); + + struct DelayedEventsEntry { + const uint32 timerOffset; + const Event event; + DelayedEventsEntry(const uint32 offset, const Event ev) : timerOffset(offset), event(ev) { } + }; + + Queue<DelayedEventsEntry> _delayedEvents; + uint32 _delayedEffectiveTime; }; /** diff --git a/common/fft.cpp b/common/fft.cpp index 5852698b61..034570964f 100644 --- a/common/fft.cpp +++ b/common/fft.cpp @@ -231,7 +231,7 @@ DECL_FFT(14, 16384, 8192, 4096) DECL_FFT(15, 32768, 16384, 8192) DECL_FFT(16, 65536, 32768, 16384) -static void (* const fft_dispatch[])(Complex*) = { +static void (* const fft_dispatch[])(Complex *) = { fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024, fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, }; diff --git a/common/forbidden.h b/common/forbidden.h index 95c1a47d65..eec80bba59 100644 --- a/common/forbidden.h +++ b/common/forbidden.h @@ -182,7 +182,8 @@ #define putchar(a) FORBIDDEN_SYMBOL_REPLACEMENT #endif - +// mingw-w64 uses [set|long]jmp in system headers +#ifndef __MINGW64__ #ifndef FORBIDDEN_SYMBOL_EXCEPTION_setjmp #undef setjmp #define setjmp(a) FORBIDDEN_SYMBOL_REPLACEMENT @@ -192,6 +193,7 @@ #undef longjmp #define longjmp(a,b) FORBIDDEN_SYMBOL_REPLACEMENT #endif +#endif // __MINGW64__ #ifndef FORBIDDEN_SYMBOL_EXCEPTION_system #undef system @@ -315,6 +317,49 @@ #endif // FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +// +// Disable various symbols from ctype.h +// +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_ctype_h + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isalnum + #undef isalnum + #define isalnum(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isalpha + #undef isalpha + #define isalpha(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isdigit + #undef isdigit + #define isdigit(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isnumber + #undef isnumber + #define isnumber(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_islower + #undef islower + #define islower(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isspace + #undef isspace + #define isspace(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_isupper + #undef isupper + #define isupper(a) FORBIDDEN_SYMBOL_REPLACEMENT + #endif + +#endif // FORBIDDEN_SYMBOL_EXCEPTION_ctype_h + #ifndef FORBIDDEN_SYMBOL_EXCEPTION_mkdir #undef mkdir #define mkdir(a,b) FORBIDDEN_SYMBOL_REPLACEMENT diff --git a/common/fs.cpp b/common/fs.cpp index 4b56cc4594..0143c936d4 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -130,10 +130,10 @@ SeekableReadStream *FSNode::createReadStream() const { if (!_realNode->exists()) { warning("FSNode::createReadStream: '%s' does not exist", getName().c_str()); - return false; + return 0; } else if (_realNode->isDirectory()) { warning("FSNode::createReadStream: '%s' is a directory", getName().c_str()); - return false; + return 0; } return _realNode->createReadStream(); @@ -197,7 +197,7 @@ FSNode *FSDirectory::lookupCache(NodeCache &cache, const String &name) const { return 0; } -bool FSDirectory::hasFile(const String &name) { +bool FSDirectory::hasFile(const String &name) const { if (name.empty() || !_node.isDirectory()) return false; @@ -205,7 +205,7 @@ bool FSDirectory::hasFile(const String &name) { return node && node->exists(); } -ArchiveMemberPtr FSDirectory::getMember(const String &name) { +const ArchiveMemberPtr FSDirectory::getMember(const String &name) const { if (name.empty() || !_node.isDirectory()) return ArchiveMemberPtr(); @@ -295,7 +295,7 @@ void FSDirectory::ensureCached() const { _cached = true; } -int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { +int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &pattern) const { if (!_node.isDirectory()) return 0; @@ -308,7 +308,7 @@ int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &patt lowercasePattern.toLowercase(); int matches = 0; - NodeCache::iterator it = _fileCache.begin(); + NodeCache::const_iterator it = _fileCache.begin(); for ( ; it != _fileCache.end(); ++it) { if (it->_key.matchString(lowercasePattern, false, true)) { list.push_back(ArchiveMemberPtr(new FSNode(it->_value))); @@ -318,7 +318,7 @@ int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &patt return matches; } -int FSDirectory::listMembers(ArchiveMemberList &list) { +int FSDirectory::listMembers(ArchiveMemberList &list) const { if (!_node.isDirectory()) return 0; @@ -326,7 +326,7 @@ int FSDirectory::listMembers(ArchiveMemberList &list) { ensureCached(); int files = 0; - for (NodeCache::iterator it = _fileCache.begin(); it != _fileCache.end(); ++it) { + for (NodeCache::const_iterator it = _fileCache.begin(); it != _fileCache.end(); ++it) { list.push_back(ArchiveMemberPtr(new FSNode(it->_value))); ++files; } diff --git a/common/fs.h b/common/fs.h index aeaa14718e..fadd672bb1 100644 --- a/common/fs.h +++ b/common/fs.h @@ -318,23 +318,23 @@ public: * Checks for existence in the cache. A full match of relative path and filename is needed * for success. */ - virtual bool hasFile(const String &name); + virtual bool hasFile(const String &name) const; /** * Returns a list of matching file names. Pattern can use GLOB wildcards. */ - virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); + virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern) const; /** * Returns a list of all the files in the cache. */ - virtual int listMembers(ArchiveMemberList &list); + virtual int listMembers(ArchiveMemberList &list) const; /** * Get a ArchiveMember representation of the specified file. A full match of relative * path and filename is needed for success. */ - virtual ArchiveMemberPtr getMember(const String &name); + virtual const ArchiveMemberPtr getMember(const String &name) const; /** * Open the specified file. A full match of relative path and filename is needed diff --git a/common/gui_options.cpp b/common/gui_options.cpp new file mode 100644 index 0000000000..32a7cc9c41 --- /dev/null +++ b/common/gui_options.cpp @@ -0,0 +1,115 @@ +/* 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. + * + */ + +#include "common/gui_options.h" + +#include "common/config-manager.h" +#include "common/str.h" + +namespace Common { + +const struct GameOpt { + const char *option; + const char *desc; +} g_gameOptions[] = { + { GUIO_NOSUBTITLES, "sndNoSubs" }, + { GUIO_NOMUSIC, "sndNoMusic" }, + { GUIO_NOSPEECH, "sndNoSpeech" }, + { GUIO_NOSFX, "sndNoSFX" }, + { GUIO_NOMIDI, "sndNoMIDI" }, + + { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, + + { GUIO_MIDIPCSPK, "midiPCSpk" }, + { GUIO_MIDICMS, "midiCMS" }, + { GUIO_MIDIPCJR, "midiPCJr" }, + { GUIO_MIDIADLIB, "midiAdLib" }, + { GUIO_MIDIC64, "midiC64" }, + { GUIO_MIDIAMIGA, "midiAmiga" }, + { GUIO_MIDIAPPLEIIGS,"midiAppleIIgs" }, + { GUIO_MIDITOWNS, "midiTowns" }, + { GUIO_MIDIPC98, "midiPC98" }, + { GUIO_MIDIMT32, "midiMt32" }, + { GUIO_MIDIGM, "midiGM" }, + + { GUIO_NOASPECT, "noAspect" }, + { GUIO_EGAUNDITHER, "egaUndither" }, + + { GUIO_RENDERHERCGREEN, "hercGreen" }, + { GUIO_RENDERHERCAMBER, "hercAmber" }, + { GUIO_RENDERCGA, "cga" }, + { GUIO_RENDEREGA, "ega" }, + { GUIO_RENDERVGA, "vga" }, + { GUIO_RENDERAMIGA, "amiga" }, + { GUIO_RENDERFMTOWNS, "fmtowns" }, + { GUIO_RENDERPC9821, "pc9821" }, + { GUIO_RENDERPC9801, "pc9801" }, + + { GUIO_NONE, 0 } +}; + +bool checkGameGUIOption(const String &option, const String &str) { + for (int i = 0; g_gameOptions[i].desc; i++) { + if (option.contains(g_gameOptions[i].option)) { + if (str.contains(g_gameOptions[i].desc)) + return true; + else + return false; + } + } + return false; +} + +String parseGameGUIOptions(const String &str) { + String res; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (str.contains(g_gameOptions[i].desc)) + res += g_gameOptions[i].option; + + return res; +} + +const String getGameGUIOptionsDescription(const String &options) { + String res; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (options.contains(g_gameOptions[i].option[0])) + res += String(g_gameOptions[i].desc) + " "; + + res.trim(); + + return res; +} + +void updateGameGUIOptions(const String &options, const String &langOption) { + const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption; + + if ((!options.empty() && !ConfMan.hasKey("guioptions")) || + (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) { + ConfMan.set("guioptions", newOptionString); + ConfMan.flushToDisk(); + } +} + + +} // End of namespace Common diff --git a/common/gui_options.h b/common/gui_options.h new file mode 100644 index 0000000000..33ecccad63 --- /dev/null +++ b/common/gui_options.h @@ -0,0 +1,85 @@ +/* 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. + * + */ + +#ifndef COMMON_GUI_OPTIONS_H +#define COMMON_GUI_OPTIONS_H + +#define GUIO_NONE "\000" +#define GUIO_NOSUBTITLES "\001" +#define GUIO_NOMUSIC "\002" +#define GUIO_NOSPEECH "\003" +#define GUIO_NOSFX "\004" +#define GUIO_NOMIDI "\005" +#define GUIO_NOLAUNCHLOAD "\006" + +#define GUIO_MIDIPCSPK "\007" +#define GUIO_MIDICMS "\010" +#define GUIO_MIDIPCJR "\011" +#define GUIO_MIDIADLIB "\012" +#define GUIO_MIDIC64 "\013" +#define GUIO_MIDIAMIGA "\014" +#define GUIO_MIDIAPPLEIIGS "\015" +#define GUIO_MIDITOWNS "\016" +#define GUIO_MIDIPC98 "\017" +#define GUIO_MIDIMT32 "\020" +#define GUIO_MIDIGM "\021" + +#define GUIO_NOASPECT "\022" +#define GUIO_EGAUNDITHER "\023" + +#define GUIO_RENDERHERCGREEN "\030" +#define GUIO_RENDERHERCAMBER "\031" +#define GUIO_RENDERCGA "\032" +#define GUIO_RENDEREGA "\033" +#define GUIO_RENDERVGA "\034" +#define GUIO_RENDERAMIGA "\035" +#define GUIO_RENDERFMTOWNS "\036" +#define GUIO_RENDERPC9821 "\037" +#define GUIO_RENDERPC9801 "\040" + +#define GUIO0() (GUIO_NONE) +#define GUIO1(a) (a) +#define GUIO2(a,b) (a b) +#define GUIO3(a,b,c) (a b c) +#define GUIO4(a,b,c,d) (a b c d) +#define GUIO5(a,b,c,d,e) (a b c d e) +#define GUIO6(a,b,c,d,e,f) (a b c d e f) + +namespace Common { + +class String; + +bool checkGameGUIOption(const String &option, const String &str); +String parseGameGUIOptions(const String &str); +const String getGameGUIOptionsDescription(const String &options); + +/** + * Updates the GUI options of the current config manager + * domain, when they differ to the ones passed as + * parameter. + */ +void updateGameGUIOptions(const String &options, const String &langOption); + + +} // End of namespace Common + +#endif diff --git a/common/hash-str.h b/common/hash-str.h index 1b8a57827a..08f0558bfd 100644 --- a/common/hash-str.h +++ b/common/hash-str.h @@ -60,14 +60,14 @@ struct IgnoreCase_Hash { // case insensitve hashing, then only because one wants to use // IgnoreCase_EqualTo, and then one has to specify a custom // hash anyway. -template <> +template<> struct Hash<String> { uint operator()(const String& s) const { return hashit(s.c_str()); } }; -template <> +template<> struct Hash<const char *> { uint operator()(const char *s) const { return hashit(s); diff --git a/common/hashmap.h b/common/hashmap.h index 347ac1fd25..7cf54997e8 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -67,7 +67,7 @@ template<class T> class IteratorImpl; /** * HashMap<Key,Val> maps objects of type Key to objects of type Val. - * For each used Key type, we need an "uint hashit(Key,uint)" function + * For each used Key type, we need an "size_type hashit(Key,size_type)" function * that computes a hash for the given Key object and returns it as an * an integer from 0 to hashsize-1, and also an "equality functor". * that returns true if if its two arguments are to be considered @@ -80,6 +80,9 @@ template<class T> class IteratorImpl; */ template<class Key, class Val, class HashFunc = Hash<Key>, class EqualFunc = EqualTo<Key> > class HashMap { +public: + typedef uint size_type; + private: typedef HashMap<Key, Val, HashFunc, EqualFunc> HM_t; @@ -111,9 +114,9 @@ private: #endif Node **_storage; ///< hashtable of size arrsize. - uint _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one - uint _size; - uint _deleted; ///< Number of deleted elements (_dummyNodes) + size_type _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one + size_type _size; + size_type _deleted; ///< Number of deleted elements (_dummyNodes) HashFunc _hash; EqualFunc _equal; @@ -146,9 +149,9 @@ private: } void assign(const HM_t &map); - uint lookup(const Key &key) const; - uint lookupAndCreateIfMissing(const Key &key); - void expandStorage(uint newCapacity); + size_type lookup(const Key &key) const; + size_type lookupAndCreateIfMissing(const Key &key); + void expandStorage(size_type newCapacity); #if !defined(__sgi) || defined(__GNUC__) template<class T> friend class IteratorImpl; @@ -168,11 +171,11 @@ private: protected: typedef const HashMap hashmap_t; - uint _idx; + size_type _idx; hashmap_t *_hashmap; protected: - IteratorImpl(uint idx, hashmap_t *hashmap) : _idx(idx), _hashmap(hashmap) {} + IteratorImpl(size_type idx, hashmap_t *hashmap) : _idx(idx), _hashmap(hashmap) {} NodeType *deref() const { assert(_hashmap != 0); @@ -200,7 +203,7 @@ private: _idx++; } while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == 0 || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE)); if (_idx > _hashmap->_mask) - _idx = (uint)-1; + _idx = (size_type)-1; return *this; } @@ -247,41 +250,41 @@ public: void erase(iterator entry); void erase(const Key &key); - uint size() const { return _size; } + size_type size() const { return _size; } iterator begin() { // Find and return the first non-empty entry - for (uint ctr = 0; ctr <= _mask; ++ctr) { + for (size_type ctr = 0; ctr <= _mask; ++ctr) { if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE) return iterator(ctr, this); } return end(); } iterator end() { - return iterator((uint)-1, this); + return iterator((size_type)-1, this); } const_iterator begin() const { // Find and return the first non-empty entry - for (uint ctr = 0; ctr <= _mask; ++ctr) { + for (size_type ctr = 0; ctr <= _mask; ++ctr) { if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE) return const_iterator(ctr, this); } return end(); } const_iterator end() const { - return const_iterator((uint)-1, this); + return const_iterator((size_type)-1, this); } iterator find(const Key &key) { - uint ctr = lookup(key); + size_type ctr = lookup(key); if (_storage[ctr]) return iterator(ctr, this); return end(); } const_iterator find(const Key &key) const { - uint ctr = lookup(key); + size_type ctr = lookup(key); if (_storage[ctr]) return const_iterator(ctr, this); return end(); @@ -346,7 +349,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : */ template<class Key, class Val, class HashFunc, class EqualFunc> HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { - for (uint ctr = 0; ctr <= _mask; ++ctr) + for (size_type ctr = 0; ctr <= _mask; ++ctr) freeNode(_storage[ctr]); delete[] _storage; @@ -373,7 +376,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { // Simply clone the map given to us, one by one. _size = 0; _deleted = 0; - for (uint ctr = 0; ctr <= _mask; ++ctr) { + for (size_type ctr = 0; ctr <= _mask; ++ctr) { if (map._storage[ctr] == HASHMAP_DUMMY_NODE) { _storage[ctr] = HASHMAP_DUMMY_NODE; _deleted++; @@ -391,7 +394,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { - for (uint ctr = 0; ctr <= _mask; ++ctr) { + for (size_type ctr = 0; ctr <= _mask; ++ctr) { freeNode(_storage[ctr]); _storage[ctr] = NULL; } @@ -414,13 +417,13 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { } template<class Key, class Val, class HashFunc, class EqualFunc> -void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { +void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity) { assert(newCapacity > _mask+1); #ifndef NDEBUG - const uint old_size = _size; + const size_type old_size = _size; #endif - const uint old_mask = _mask; + const size_type old_mask = _mask; Node **old_storage = _storage; // allocate a new array @@ -432,7 +435,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { memset(_storage, 0, newCapacity * sizeof(Node *)); // rehash all the old elements - for (uint ctr = 0; ctr <= old_mask; ++ctr) { + for (size_type ctr = 0; ctr <= old_mask; ++ctr) { if (old_storage[ctr] == NULL || old_storage[ctr] == HASHMAP_DUMMY_NODE) continue; @@ -440,9 +443,9 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // Since we know that no key exists twice in the old table, we // can do this slightly better than by calling lookup, since we // don't have to call _equal(). - const uint hash = _hash(old_storage[ctr]->_key); - uint idx = hash & _mask; - for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) { + const size_type hash = _hash(old_storage[ctr]->_key); + size_type idx = hash & _mask; + for (size_type perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) { idx = (5 * idx + perturb + 1) & _mask; } @@ -460,10 +463,10 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { } template<class Key, class Val, class HashFunc, class EqualFunc> -uint HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { - const uint hash = _hash(key); - uint ctr = hash & _mask; - for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { +typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { + const size_type hash = _hash(key); + size_type ctr = hash & _mask; + for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { if (_storage[ctr] == NULL) break; if (_storage[ctr] == HASHMAP_DUMMY_NODE) { @@ -491,13 +494,13 @@ uint HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { } template<class Key, class Val, class HashFunc, class EqualFunc> -uint HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { - const uint hash = _hash(key); - uint ctr = hash & _mask; - const uint NONE_FOUND = _mask + 1; - uint first_free = NONE_FOUND; +typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { + const size_type hash = _hash(key); + size_type ctr = hash & _mask; + const size_type NONE_FOUND = _mask + 1; + size_type first_free = NONE_FOUND; bool found = false; - for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { + for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { if (_storage[ctr] == NULL) break; if (_storage[ctr] == HASHMAP_DUMMY_NODE) { @@ -537,7 +540,7 @@ uint HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key // Keep the load factor below a certain threshold. // Deleted nodes are also counted - uint capacity = _mask + 1; + size_type capacity = _mask + 1; if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR > capacity * HASHMAP_LOADFACTOR_NUMERATOR) { capacity = capacity < 500 ? (capacity * 4) : (capacity * 2); @@ -553,7 +556,7 @@ uint HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key template<class Key, class Val, class HashFunc, class EqualFunc> bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const { - uint ctr = lookup(key); + size_type ctr = lookup(key); return (_storage[ctr] != NULL); } @@ -569,7 +572,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) co template<class Key, class Val, class HashFunc, class EqualFunc> Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) { - uint ctr = lookupAndCreateIfMissing(key); + size_type ctr = lookupAndCreateIfMissing(key); assert(_storage[ctr] != NULL); return _storage[ctr]->_value; } @@ -581,7 +584,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const template<class Key, class Val, class HashFunc, class EqualFunc> const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const Val &defaultVal) const { - uint ctr = lookup(key); + size_type ctr = lookup(key); if (_storage[ctr] != NULL) return _storage[ctr]->_value; else @@ -590,7 +593,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) { - uint ctr = lookupAndCreateIfMissing(key); + size_type ctr = lookupAndCreateIfMissing(key); assert(_storage[ctr] != NULL); _storage[ctr]->_value = val; } @@ -599,7 +602,7 @@ template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::erase(iterator entry) { // Check whether we have a valid iterator assert(entry._hashmap == this); - const uint ctr = entry._idx; + const size_type ctr = entry._idx; assert(ctr <= _mask); Node * const node = _storage[ctr]; assert(node != NULL); @@ -615,7 +618,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::erase(iterator entry) { template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { - uint ctr = lookup(key); + size_type ctr = lookup(key); if (_storage[ctr] == NULL) return; diff --git a/common/huffman.h b/common/huffman.h index 4175d0d309..3b23340b2e 100644 --- a/common/huffman.h +++ b/common/huffman.h @@ -68,7 +68,7 @@ private: typedef List<Symbol> CodeList; typedef Array<CodeList> CodeLists; - typedef Array<Symbol*> SymbolList; + typedef Array<Symbol *> SymbolList; /** Lists of codes and their symbols, sorted by code length. */ CodeLists _codes; diff --git a/common/keyboard.h b/common/keyboard.h index ead6ed427b..e6db086598 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -224,11 +224,14 @@ enum { KBD_CTRL = 1 << 0, KBD_ALT = 1 << 1, KBD_SHIFT = 1 << 2, + KBD_NON_STICKY = (KBD_CTRL|KBD_ALT|KBD_SHIFT), // Sticky modifier flags KBD_NUM = 1 << 3, KBD_CAPS = 1 << 4, - KBD_SCRL = 1 << 5 + KBD_SCRL = 1 << 5, + KBD_STICKY = (KBD_NUM|KBD_CAPS|KBD_SCRL) + }; /** @@ -281,19 +284,27 @@ struct KeyState { /** * Check whether the non-sticky flags are *exactly* as specified by f. - * This ignors the sticky flags (KBD_NUM, KBD_CAPS, KBD_SCRL). + * This ignores the sticky flags (KBD_NUM, KBD_CAPS, KBD_SCRL). + * Sticky flags should never be passed to this function. * If you just want to check whether a modifier flag is set, just bit-and * the flag. E.g. to check whether the control key modifier is set, * you can write * if (keystate.flags & KBD_CTRL) { ... } */ bool hasFlags(byte f) const { - return f == (flags & ~(KBD_NUM|KBD_CAPS|KBD_SCRL)); + assert(!(f & KBD_STICKY)); + return f == (flags & ~KBD_STICKY); } + /** + * Check if two key states are equal. This implementation ignores the state + * of the sticky flags (caps lock, num lock, scroll lock) completely. This + * functionality is currently only used by the keymapper. + */ bool operator==(const KeyState &x) const { - // intentionally ignore ascii - return keycode == x.keycode && flags == x.flags; + // Intentionally ignore ASCII, as the keycode and non-sticky flag + // combination should suffice. + return keycode == x.keycode && hasFlags(x.flags & ~KBD_STICKY); } }; diff --git a/common/language.cpp b/common/language.cpp new file mode 100644 index 0000000000..898adf8d0e --- /dev/null +++ b/common/language.cpp @@ -0,0 +1,125 @@ +/* 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. + */ + +#include "common/language.h" +#include "common/gui_options.h" +#include "common/str.h" + +namespace Common { + +const LanguageDescription g_languages[] = { + { "zh-cn", "zh_CN", "Chinese (China)", ZH_CNA }, + { "zh", "zh_TW", "Chinese (Taiwan)", ZH_TWN }, + { "cz", "cs_CZ", "Czech", CZ_CZE }, + { "nl", "nl_NL", "Dutch", NL_NLD }, + { "en", "en", "English", EN_ANY }, // Generic English (when only one game version exist) + { "gb", "en_GB", "English (GB)", EN_GRB }, + { "us", "en_US", "English (US)", EN_USA }, + { "fr", "fr_FR", "French", FR_FRA }, + { "de", "de_DE", "German", DE_DEU }, + { "gr", "el_GR", "Greek", GR_GRE }, + { "he", "he_IL", "Hebrew", HE_ISR }, + { "hb", "he_IL", "Hebrew", HE_ISR }, // Deprecated + { "hr", "hr_HR", "Croatian", HR_HRV }, + { "hu", "hu_HU", "Hungarian", HU_HUN }, + { "it", "it_IT", "Italian", IT_ITA }, + { "jp", "ja_JP", "Japanese", JA_JPN }, + { "kr", "ko_KR", "Korean", KO_KOR }, + { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale + { "pl", "pl_PL", "Polish", PL_POL }, + { "br", "pt_BR", "Portuguese", PT_BRA }, + { "ru", "ru_RU", "Russian", RU_RUS }, + { "es", "es_ES", "Spanish", ES_ESP }, + { "se", "sv_SE", "Swedish", SE_SWE }, + { 0, 0, 0, UNK_LANG } +}; + +Language parseLanguage(const String &str) { + if (str.empty()) + return UNK_LANG; + + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code)) + return l->id; + } + + return UNK_LANG; +} + +Language parseLanguageFromLocale(const char *locale) { + if (!locale || !*locale) + return UNK_LANG; + + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (!strcmp(l->unixLocale, locale)) + return l->id; + } + + return UNK_LANG; +} + +const char *getLanguageCode(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getLanguageLocale(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->unixLocale; + } + return 0; +} + +const char *getLanguageDescription(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return 0; +} + +bool checkGameGUIOptionLanguage(Language lang, const String &str) { + if (!str.contains("lang_")) // If no languages are specified + return true; + + if (str.contains(getGameGUIOptionsDescriptionLanguage(lang))) + return true; + + return false; +} + +const String getGameGUIOptionsDescriptionLanguage(Language lang) { + if (lang == UNK_LANG) + return ""; + + return String("lang_") + getLanguageDescription(lang); +} + +} // End of namespace Common diff --git a/common/language.h b/common/language.h new file mode 100644 index 0000000000..db552fc9c4 --- /dev/null +++ b/common/language.h @@ -0,0 +1,86 @@ +/* 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. + */ + +#ifndef COMMON_LANGUAGE_H +#define COMMON_LANGUAGE_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of game language. + */ +enum Language { + ZH_CNA, + ZH_TWN, + CZ_CZE, + NL_NLD, + EN_ANY, // Generic English (when only one game version exist) + EN_GRB, + EN_USA, + FR_FRA, + DE_DEU, + GR_GRE, + HE_ISR, + HR_HRV, + HU_HUN, + IT_ITA, + JA_JPN, + KO_KOR, + NB_NOR, + PL_POL, + PT_BRA, + RU_RUS, + ES_ESP, + SE_SWE, + + UNK_LANG = -1 // Use default language (i.e. none specified) +}; + +struct LanguageDescription { + const char *code; + const char *unixLocale; + const char *description; + Language id; +}; + +extern const LanguageDescription g_languages[]; + + +/** Convert a string containing a language name into a Language enum value. */ +extern Language parseLanguage(const String &str); +extern Language parseLanguageFromLocale(const char *locale); +extern const char *getLanguageCode(Language id); +extern const char *getLanguageLocale(Language id); +extern const char *getLanguageDescription(Language id); + +// TODO: Document this GUIO related function +const String getGameGUIOptionsDescriptionLanguage(Common::Language lang); + +// TODO: Document this GUIO related function +bool checkGameGUIOptionLanguage(Common::Language lang, const String &str); + +} // End of namespace Common + +#endif diff --git a/common/list.h b/common/list.h index a1e761f55d..9792042239 100644 --- a/common/list.h +++ b/common/list.h @@ -43,6 +43,7 @@ public: typedef ListInternal::ConstIterator<t_T> const_iterator; typedef t_T value_type; + typedef uint size_type; public: List() { @@ -181,8 +182,8 @@ public: return *this; } - uint size() const { - uint n = 0; + size_type size() const { + size_type n = 0; for (const NodeBase *cur = _anchor._next; cur != &_anchor; cur = cur->_next) ++n; return n; @@ -226,7 +227,7 @@ public: } const_iterator end() const { - return const_iterator(const_cast<NodeBase*>(&_anchor)); + return const_iterator(const_cast<NodeBase *>(&_anchor)); } protected: diff --git a/common/list_intern.h b/common/list_intern.h index daa7446781..fef32fbe1e 100644 --- a/common/list_intern.h +++ b/common/list_intern.h @@ -35,7 +35,7 @@ namespace ListInternal { NodeBase *_next; }; - template <typename T> + template<typename T> struct Node : public NodeBase { T _data; diff --git a/common/localization.h b/common/localization.h index 3945cf5fab..e908485b99 100644 --- a/common/localization.h +++ b/common/localization.h @@ -22,7 +22,7 @@ #ifndef COMMON_LOCALIZATION_H #define COMMON_LOCALIZATION_H -#include "common/util.h" +#include "common/language.h" #include "common/keyboard.h" namespace Common { diff --git a/common/macresman.cpp b/common/macresman.cpp index 1317600cb7..14bdfa7080 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -238,6 +238,27 @@ bool MacResManager::open(FSNode path, String filename) { return false; } +bool MacResManager::exists(const String &filename) { + // Try the file name by itself + if (Common::File::exists(filename)) + return true; + + // Try the .rsrc extension + if (Common::File::exists(filename + ".rsrc")) + return true; + + // Check if we have a MacBinary file + Common::File tempFile; + if (tempFile.open(filename + ".bin") && isMacBinary(tempFile)) + return true; + + // Check if we have an AppleDouble file + if (tempFile.open("._" + filename) && tempFile.readUint32BE() == 0x00051607) + return true; + + return false; +} + bool MacResManager::loadFromAppleDouble(SeekableReadStream &stream) { if (stream.readUint32BE() != 0x00051607) // tag return false; diff --git a/common/macresman.h b/common/macresman.h index 4d86e46d11..6820106925 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -69,6 +69,13 @@ public: bool open(FSNode path, String filename); /** + * See if a Mac data/resource fork pair exists. + * @param filename The base file name of the file + * @return True if either a data fork or resource fork with this name exists + */ + static bool exists(const String &filename); + + /** * Close the Mac data/resource fork pair. */ void close(); diff --git a/common/math.h b/common/math.h index f787b84fa6..b85ec0d22a 100644 --- a/common/math.h +++ b/common/math.h @@ -75,7 +75,7 @@ struct Complex { float re, im; }; -#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#if GCC_ATLEAST(3, 4) inline int intLog2(uint32 v) { // This is a slightly optimized implementation of log2 for natural numbers // targeting gcc. It also saves some binary size over our fallback diff --git a/common/memorypool.cpp b/common/memorypool.cpp index 19adc54d00..e3742eeae0 100644 --- a/common/memorypool.cpp +++ b/common/memorypool.cpp @@ -33,7 +33,7 @@ static size_t adjustChunkSize(size_t chunkSize) { // You must at least fit the pointer in the node (technically unneeded considering the next rounding statement) chunkSize = MAX(chunkSize, sizeof(void *)); // There might be an alignment problem on some platforms when trying to load a void* on a non natural boundary - // so we round to the next sizeof(void*) + // so we round to the next sizeof(void *) chunkSize = (chunkSize + sizeof(void *) - 1) & (~(sizeof(void *) - 1)); return chunkSize; diff --git a/common/memorypool.h b/common/memorypool.h index 5ba09cebed..9a4e523d53 100644 --- a/common/memorypool.h +++ b/common/memorypool.h @@ -105,7 +105,7 @@ template<size_t CHUNK_SIZE, size_t NUM_INTERNAL_CHUNKS = 32> class FixedSizeMemoryPool : public MemoryPool { private: enum { - REAL_CHUNK_SIZE = (CHUNK_SIZE + sizeof(void*) - 1) & (~(sizeof(void*) - 1)) + REAL_CHUNK_SIZE = (CHUNK_SIZE + sizeof(void *) - 1) & (~(sizeof(void *) - 1)) }; byte _storage[NUM_INTERNAL_CHUNKS * REAL_CHUNK_SIZE]; diff --git a/common/module.mk b/common/module.mk index 7434df7052..b4928fabda 100644 --- a/common/module.mk +++ b/common/module.mk @@ -8,19 +8,24 @@ MODULE_OBJS := \ debug.o \ error.o \ EventDispatcher.o \ + EventMapper.o \ EventRecorder.o \ file.o \ fs.o \ + gui_options.o \ hashmap.o \ iff_container.o \ + language.o \ localization.o \ macresman.o \ memorypool.o \ md5.o \ mutex.o \ + platform.o \ quicktime.o \ random.o \ rational.o \ + rendermode.o \ str.o \ stream.o \ system.o \ diff --git a/common/platform.cpp b/common/platform.cpp new file mode 100644 index 0000000000..9986048b48 --- /dev/null +++ b/common/platform.cpp @@ -0,0 +1,107 @@ +/* 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. + */ + +#include "common/platform.h" +#include "common/str.h" + +namespace Common { + +const PlatformDescription g_platforms[] = { + { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, + { "3do", "3do", "3do", "3DO", kPlatform3DO }, + { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn }, + { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga }, + { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST }, + { "c64", "c64", "c64", "Commodore 64", kPlatformC64 }, + { "pc", "dos", "ibm", "DOS", kPlatformPC }, + { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 }, + { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii }, + { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 }, + + // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). + // However, on the net many variations can be seen, like "FMTOWNS", + // "FM TOWNS", "FmTowns", etc. + { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns }, + + { "linux", "linux", "linux", "Linux", kPlatformLinux }, + { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh }, + { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine }, + { "nes", "nes", "nes", "NES", kPlatformNES }, + { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD }, + { "windows", "win", "win", "Windows", kPlatformWindows }, + { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX }, + { "cdi", "cdi", "cdi", "Philips CD-i", kPlatformCDi }, + { "ios", "ios", "ios", "Apple iOS", kPlatformIOS }, + + { 0, 0, 0, "Default", kPlatformUnknown } +}; + +Platform parsePlatform(const String &str) { + if (str.empty()) + return kPlatformUnknown; + + // Handle some special case separately, for compatibility with old config + // files. + if (str == "1") + return kPlatformAmiga; + else if (str == "2") + return kPlatformAtariST; + else if (str == "3") + return kPlatformMacintosh; + + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev)) + return l->id; + } + + return kPlatformUnknown; +} + + +const char *getPlatformCode(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getPlatformAbbrev(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->abbrev; + } + return 0; +} + +const char *getPlatformDescription(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return l->description; +} + +} // End of namespace Common diff --git a/common/platform.h b/common/platform.h new file mode 100644 index 0000000000..1891c7096d --- /dev/null +++ b/common/platform.h @@ -0,0 +1,80 @@ +/* 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. + */ + +#ifndef COMMON_PLATFORM_H +#define COMMON_PLATFORM_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of game platforms. Specifying a platform for a target can be used to + * give the game engines a hint for which platform the game data file are. + * This may be optional or required, depending on the game engine and the + * game in question. + */ +enum Platform { + kPlatformPC, + kPlatformAmiga, + kPlatformAtariST, + kPlatformMacintosh, + kPlatformFMTowns, + kPlatformWindows, + kPlatformNES, + kPlatformC64, + kPlatformCoCo3, + kPlatformLinux, + kPlatformAcorn, + kPlatformSegaCD, + kPlatform3DO, + kPlatformPCEngine, + kPlatformApple2GS, + kPlatformPC98, + kPlatformWii, + kPlatformPSX, + kPlatformCDi, + kPlatformIOS, + + kPlatformUnknown = -1 +}; + +struct PlatformDescription { + const char *code; + const char *code2; + const char *abbrev; + const char *description; + Platform id; +}; + +extern const PlatformDescription g_platforms[]; + +/** Convert a string containing a platform name into a Platform enum value. */ +extern Platform parsePlatform(const String &str); +extern const char *getPlatformCode(Platform id); +extern const char *getPlatformAbbrev(Platform id); +extern const char *getPlatformDescription(Platform id); + +} // End of namespace Common + +#endif diff --git a/common/ptr.h b/common/ptr.h index 2b0670caae..f734ec133f 100644 --- a/common/ptr.h +++ b/common/ptr.h @@ -103,7 +103,7 @@ private: */ template<class T> class SharedPtr { -#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) +#if !defined(__GNUC__) || GCC_ATLEAST(3, 0) template<class T2> friend class SharedPtr; #endif public: @@ -200,7 +200,7 @@ public: * This should just be used for debugging purposes. */ RefValue refCount() const { return _refCount ? *_refCount : 0; } -#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) +#if !defined(__GNUC__) || GCC_ATLEAST(3, 0) private: #endif void decRef() { diff --git a/common/quicktime.cpp b/common/quicktime.cpp index e16d3f2652..fb01e8de28 100644 --- a/common/quicktime.cpp +++ b/common/quicktime.cpp @@ -66,7 +66,7 @@ bool QuickTimeParser::parseFile(const String &filename) { _foundMOOV = false; _disposeFileHandle = DisposeAfterUse::YES; - Atom atom = { 0, 0, 0xffffffff }; + Atom atom = { 0, 0, 0 }; if (_resFork->hasResFork()) { // Search for a 'moov' resource @@ -80,14 +80,12 @@ bool QuickTimeParser::parseFile(const String &filename) { if (readDefault(atom) < 0 || !_foundMOOV) return false; } - delete _fd; - atom.type = 0; - atom.offset = 0; - atom.size = 0xffffffff; + delete _fd; } _fd = _resFork->getDataFork(); + atom.size = _fd->size(); if (readDefault(atom) < 0 || !_foundMOOV) return false; @@ -113,19 +111,29 @@ bool QuickTimeParser::parseStream(SeekableReadStream *stream, DisposeAfterUse::F } void QuickTimeParser::init() { - // Remove unknown/unhandled tracks for (uint32 i = 0; i < _tracks.size(); i++) { + // Remove unknown/unhandled tracks if (_tracks[i]->codecType == CODEC_TYPE_MOV_OTHER) { delete _tracks[i]; _tracks.remove_at(i); i--; + } else { + // If this track doesn't have a declared scale, use the movie scale + if (_tracks[i]->timeScale == 0) + _tracks[i]->timeScale = _timeScale; + + // If this track doesn't have an edit list (like in MPEG-4 files), + // fake an entry of one edit that takes up the entire sample + if (_tracks[i]->editCount == 0) { + _tracks[i]->editCount = 1; + _tracks[i]->editList = new EditListEntry[1]; + _tracks[i]->editList[0].trackDuration = _tracks[i]->duration; + _tracks[i]->editList[0].timeOffset = 0; + _tracks[i]->editList[0].mediaTime = 0; + _tracks[i]->editList[0].mediaRate = 1; + } } } - - // Adjust time scale - for (uint32 i = 0; i < _tracks.size(); i++) - if (!_tracks[i]->timeScale) - _tracks[i]->timeScale = _timeScale; } void QuickTimeParser::initParseTable() { @@ -135,7 +143,7 @@ void QuickTimeParser::initParseTable() { { &QuickTimeParser::readDefault, MKTAG('e', 'd', 't', 's') }, { &QuickTimeParser::readELST, MKTAG('e', 'l', 's', 't') }, { &QuickTimeParser::readHDLR, MKTAG('h', 'd', 'l', 'r') }, - { &QuickTimeParser::readDefault, MKTAG('m', 'd', 'a', 't') }, + { &QuickTimeParser::readLeaf, MKTAG('m', 'd', 'a', 't') }, { &QuickTimeParser::readMDHD, MKTAG('m', 'd', 'h', 'd') }, { &QuickTimeParser::readDefault, MKTAG('m', 'd', 'i', 'a') }, { &QuickTimeParser::readDefault, MKTAG('m', 'i', 'n', 'f') }, diff --git a/common/quicktime.h b/common/quicktime.h index d7e2691c2b..efd2adbd21 100644 --- a/common/quicktime.h +++ b/common/quicktime.h @@ -155,7 +155,7 @@ protected: uint16 height; CodecType codecType; - Array<SampleDesc*> sampleDescs; + Array<SampleDesc *> sampleDescs; uint32 editCount; EditListEntry *editList; @@ -180,7 +180,7 @@ protected: uint32 _duration; Rational _scaleFactorX; Rational _scaleFactorY; - Array<Track*> _tracks; + Array<Track *> _tracks; uint32 _beginOffset; MacResManager *_resFork; diff --git a/common/rect.h b/common/rect.h index 1106ec1714..e48ca53667 100644 --- a/common/rect.h +++ b/common/rect.h @@ -258,11 +258,12 @@ struct Rect { /** * Create a rectangle around the given center. + * @note the center point is rounded up and left when given an odd width and height */ static Rect center(int16 cx, int16 cy, int16 w, int16 h) { - w /= 2; - h /= 2; - return Rect(cx - w, cy - h, cx + w, cy + h); + int dx = w / 2; + int dy = h / 2; + return Rect(cx - dx, cy - dy, cx + dx + (w & 1), cy + dy + (h & 1)); } }; diff --git a/common/rendermode.cpp b/common/rendermode.cpp new file mode 100644 index 0000000000..e8f3146630 --- /dev/null +++ b/common/rendermode.cpp @@ -0,0 +1,122 @@ +/* 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. + * + */ + +#include "common/rendermode.h" + +#include "common/gui_options.h" +#include "common/str.h" +#include "common/translation.h" + + +namespace Common { + + +const RenderModeDescription g_renderModes[] = { + // I18N: Hercules is graphics card name + { "hercGreen", _s("Hercules Green"), kRenderHercG }, + { "hercAmber", _s("Hercules Amber"), kRenderHercA }, + { "cga", "CGA", kRenderCGA }, + { "ega", "EGA", kRenderEGA }, + { "vga", "VGA", kRenderVGA }, + { "amiga", "Amiga", kRenderAmiga }, + { "fmtowns", "FM-Towns", kRenderFMTowns }, + { "pc9821", "PC-9821 (256 Colors)", kRenderPC9821 }, + { "pc9801", "PC-9801 (16 Colors)", kRenderPC9801 }, + {0, 0, kRenderDefault} +}; + +struct RenderGUIOMapping { + RenderMode id; + const char *guio; +}; + +// TODO: Merge s_renderGUIOMapping into g_renderModes? the kRenderDefault +// could be used to indicate "any" mode when passed to renderMode2GUIO (if +// we wanted to merge allRenderModesGUIOs back into) +static const RenderGUIOMapping s_renderGUIOMapping[] = { + { kRenderHercG, GUIO_RENDERHERCGREEN }, + { kRenderHercA, GUIO_RENDERHERCAMBER }, + { kRenderCGA, GUIO_RENDERCGA }, + { kRenderEGA, GUIO_RENDEREGA }, + { kRenderVGA, GUIO_RENDERVGA }, + { kRenderAmiga, GUIO_RENDERAMIGA }, + { kRenderFMTowns, GUIO_RENDERFMTOWNS }, + { kRenderPC9821, GUIO_RENDERPC9821 }, + { kRenderPC9801, GUIO_RENDERPC9801 } +}; + +DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres") +DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Amber", "lowres") + +RenderMode parseRenderMode(const String &str) { + if (str.empty()) + return kRenderDefault; + + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code)) + return l->id; + } + + return kRenderDefault; +} + +const char *getRenderModeCode(RenderMode id) { + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getRenderModeDescription(RenderMode id) { + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return 0; +} + +String renderMode2GUIO(RenderMode id) { + String res; + + for (int i = 0; i < ARRAYSIZE(s_renderGUIOMapping); i++) { + if (id == s_renderGUIOMapping[i].id) + res += s_renderGUIOMapping[i].guio; + } + + return res; +} + +String allRenderModesGUIOs() { + String res; + + for (int i = 0; i < ARRAYSIZE(s_renderGUIOMapping); i++) { + res += s_renderGUIOMapping[i].guio; + } + + return res; +} + +} // End of namespace Common diff --git a/common/rendermode.h b/common/rendermode.h new file mode 100644 index 0000000000..945c4e7d9d --- /dev/null +++ b/common/rendermode.h @@ -0,0 +1,73 @@ +/* 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. + * + */ + +#ifndef COMMON_RENDERMODE_H +#define COMMON_RENDERMODE_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of render modes. It specifies which original graphics mode + * to use. Some targets used postprocessing dithering routines for + * reducing color depth of final image which let it to be rendered on + * such low-level adapters as CGA or Hercules. + */ +enum RenderMode { + kRenderDefault = 0, + kRenderVGA = 1, + kRenderEGA = 2, + kRenderCGA = 3, + kRenderHercG = 4, + kRenderHercA = 5, + kRenderAmiga = 6, + kRenderFMTowns = 7, + kRenderPC9821 = 8, + kRenderPC9801 = 9 +}; + +struct RenderModeDescription { + const char *code; + const char *description; + RenderMode id; +}; + +extern const RenderModeDescription g_renderModes[]; + +/** Convert a string containing a render mode name into a RenderingMode enum value. */ +extern RenderMode parseRenderMode(const String &str); +extern const char *getRenderModeCode(RenderMode id); +extern const char *getRenderModeDescription(RenderMode id); + +// TODO: Rename the following to something better; also, document it +extern String renderMode2GUIO(RenderMode id); + +// TODO: Rename the following to something better; also, document it +extern String allRenderModesGUIOs(); + + +} // End of namespace Common + +#endif diff --git a/common/scummsys.h b/common/scummsys.h index 6baab7c16f..2f4efe702f 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -23,6 +23,9 @@ #ifndef COMMON_SCUMMSYS_H #define COMMON_SCUMMSYS_H +// This is a convenience macro to test whether the compiler used is a GCC +// version, which is at least major.minor. +#define GCC_ATLEAST(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))) #if defined(_WIN32_WCE) && _WIN32_WCE < 300 #define NONSTANDARD_PORT @@ -268,7 +271,7 @@ #ifndef FORCEINLINE #if defined(_MSC_VER) #define FORCEINLINE __forceinline - #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) + #elif GCC_ATLEAST(3, 1) #define FORCEINLINE inline __attribute__((__always_inline__)) #else #define FORCEINLINE inline @@ -316,7 +319,7 @@ #define scumm_va_copy va_copy #elif defined(__va_copy) #define scumm_va_copy __va_copy - #elif defined(_MSC_VER) || defined (__SYMBIAN32__) + #elif defined(_MSC_VER) || defined(__SYMBIAN32__) #define scumm_va_copy(dst, src) ((dst) = (src)) #else #error scumm_va_copy undefined for this port diff --git a/common/serializer.h b/common/serializer.h index 5b08a9a9fa..4d97c9e930 100644 --- a/common/serializer.h +++ b/common/serializer.h @@ -30,7 +30,7 @@ namespace Common { #define SYNC_AS(SUFFIX,TYPE,SIZE) \ - template <typename T> \ + template<typename T> \ void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \ if (_version < minVersion || _version > maxVersion) \ return; \ diff --git a/common/singleton.h b/common/singleton.h index 43f1c0c4d0..d7078360f3 100644 --- a/common/singleton.h +++ b/common/singleton.h @@ -43,8 +43,8 @@ private: * singleton class might be pure virtual (or "abstract" in Java terminology), * and you specialise makeInstance to return an instance of a subclass. */ - //template <class T> -#if defined (_WIN32_WCE) || defined (_MSC_VER) || defined (__WINS__) + //template<class T> +#if defined(_WIN32_WCE) || defined(_MSC_VER) || defined(__WINS__) //FIXME evc4 and msvc7 doesn't like it as private member public: #endif diff --git a/common/stack.h b/common/stack.h index 0d13049f2e..bc5de9ac7f 100644 --- a/common/stack.h +++ b/common/stack.h @@ -30,48 +30,59 @@ namespace Common { /** * Extremly simple fixed size stack class. */ -template<class T, int MAX_SIZE = 10> +template<class T, uint MAX_SIZE = 10> class FixedStack { -protected: - T _stack[MAX_SIZE]; - int _size; public: + typedef uint size_type; + FixedStack<T, MAX_SIZE>() : _size(0) {} bool empty() const { return _size <= 0; } + void clear() { _size = 0; } + void push(const T &x) { assert(_size < MAX_SIZE); _stack[_size++] = x; } + const T &top() const { assert(_size > 0); return _stack[_size - 1]; } + T &top() { assert(_size > 0); return _stack[_size - 1]; } + T pop() { T tmp = top(); --_size; return tmp; } - int size() const { + + size_type size() const { return _size; } - T &operator[](int i) { - assert(0 <= i && i < MAX_SIZE); + + T &operator[](size_type i) { + assert(i < MAX_SIZE); return _stack[i]; } - const T &operator[](int i) const { - assert(0 <= i && i < MAX_SIZE); + + const T &operator[](size_type i) const { + assert(i < MAX_SIZE); return _stack[i]; } + +protected: + T _stack[MAX_SIZE]; + size_type _size; }; @@ -81,39 +92,49 @@ public: template<class T> class Stack { private: - Array<T> _stack; + Array<T> _stack; public: + typedef typename Array<T>::size_type size_type; + Stack<T>() {} Stack<T>(const Array<T> &stackContent) : _stack(stackContent) {} bool empty() const { return _stack.empty(); } + void clear() { _stack.clear(); } + void push(const T &x) { _stack.push_back(x); } + T &top() { return _stack.back(); } + const T &top() const { return _stack.back(); } + T pop() { T tmp = _stack.back(); _stack.pop_back(); return tmp; } - int size() const { + + size_type size() const { return _stack.size(); } - T &operator[](int i) { + + T &operator[](size_type i) { return _stack[i]; } - const T &operator[](int i) const { + + const T &operator[](size_type i) const { return _stack[i]; } }; diff --git a/common/str.cpp b/common/str.cpp index 32f4b44e79..84805082ac 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -405,13 +405,13 @@ void String::trim() { makeUnique(); // Trim trailing whitespace - while (_size >= 1 && isspace(static_cast<unsigned char>(_str[_size - 1]))) + while (_size >= 1 && isSpace(_str[_size - 1])) --_size; _str[_size] = 0; // Trim leading whitespace char *t = _str; - while (isspace((unsigned char)*t)) + while (isSpace(*t)) t++; if (t != _str) { @@ -606,14 +606,14 @@ String operator+(const String &x, char y) { } char *ltrim(char *t) { - while (isspace(static_cast<unsigned char>(*t))) + while (isSpace(*t)) t++; return t; } char *rtrim(char *t) { int l = strlen(t) - 1; - while (l >= 0 && isspace(static_cast<unsigned char>(t[l]))) + while (l >= 0 && isSpace(t[l])) t[l--] = 0; return t; } @@ -793,7 +793,7 @@ size_t strlcpy(char *dst, const char *src, size_t size) { } // Move to the terminating zero of the source - // string, we need this to determin the length + // string, we need this to determine the length // of the source string. while (*src) ++src; @@ -841,7 +841,7 @@ size_t strlcat(char *dst, const char *src, size_t size) { *dst = 0; // Move to the terminating zero of the source - // string, we need this to determin the length + // string, we need this to determine the length // of the source string. while (*src) ++src; diff --git a/common/stream.cpp b/common/stream.cpp index 30b3bca497..85647bfe3a 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -240,7 +240,7 @@ bool SeekableSubReadStream::seek(int32 offset, int whence) { return ret; } -uint32 SafeSubReadStream::read(void *dataPtr, uint32 dataSize) { +uint32 SafeSeekableSubReadStream::read(void *dataPtr, uint32 dataSize) { // Make sure the parent stream is at the right position seek(0, SEEK_CUR); diff --git a/common/substream.h b/common/substream.h index 7e67389da1..01686529aa 100644 --- a/common/substream.h +++ b/common/substream.h @@ -99,21 +99,24 @@ public: * normal SeekableSubReadStream, at the cost of seek()ing the parent stream * before each read(). * - * More than one SafeSubReadStream to the same parent stream can be used + * More than one SafeSeekableSubReadStream to the same parent stream can be used * at the same time; they won't mess up each other. They will, however, * reposition the parent stream, so don't depend on its position to be - * the same after a read() or seek() on one of its SafeSubReadStream. + * the same after a read() or seek() on one of its SafeSeekableSubReadStream. + * + * Note that this stream is *not* threading safe. Calling read from the audio + * thread and from the main thread might mess up the data retrieved. */ -class SafeSubReadStream : public SeekableSubReadStream { +class SafeSeekableSubReadStream : public SeekableSubReadStream { public: - SafeSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) : - SeekableSubReadStream(parentStream, begin, end, disposeParentStream) { + SafeSeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) + : SeekableSubReadStream(parentStream, begin, end, disposeParentStream) { } - virtual uint32 read(void *dataPtr, uint32 dataSize); + virtual uint32 read(void *dataPtr, uint32 dataSize); }; -} // End of namespace Common +} // End of namespace Common #endif diff --git a/common/system.h b/common/system.h index 413fe326a7..dc74533861 100644 --- a/common/system.h +++ b/common/system.h @@ -51,7 +51,11 @@ class UpdateManager; class TimerManager; class SeekableReadStream; class WriteStream; -class HardwareKeySet; +#ifdef ENABLE_KEYMAPPER +class HardwareInputSet; +class Keymap; +class KeymapperDefaultBindings; +#endif } class AudioCDManager; @@ -932,15 +936,42 @@ public: return _eventManager; } +#ifdef ENABLE_KEYMAPPER + /** + * Register hardware inputs with keymapper + * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use + * this, please talk to tsoliman and/or LordHoto. + * + * @return HardwareInputSet with all keys and recommended mappings + * + * See keymapper documentation for further reference. + */ + virtual Common::HardwareInputSet *getHardwareInputSet() { return 0; } + /** - * Register hardware keys with keymapper + * Return a platform-specific global keymap + * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use + * this, please talk to tsoliman and/or LordHoto. * - * @return HardwareKeySet with all keys and recommended mappings + * @return Keymap with actions appropriate for the platform + * + * The caller will use and delete the return object. * * See keymapper documentation for further reference. */ - virtual Common::HardwareKeySet *getHardwareKeySet() { return 0; } + virtual Common::Keymap *getGlobalKeymap() { return 0; } + /** + * Return platform-specific default keybindings + * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use + * this, please talk to tsoliman and/or LordHoto. + * + * @return KeymapperDefaultBindings populated with keybindings + * + * See keymapper documentation for further reference. + */ + virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return 0; } +#endif //@} diff --git a/common/translation.cpp b/common/translation.cpp index 081bde987d..2bc31c617b 100644 --- a/common/translation.cpp +++ b/common/translation.cpp @@ -26,7 +26,7 @@ #undef ARRAYSIZE #endif -#define TRANSLATIONS_DAT_VER 2 +#define TRANSLATIONS_DAT_VER 3 #include "common/translation.h" #include "common/config-manager.h" @@ -45,7 +45,7 @@ bool operator<(const TLanguage &l, const TLanguage &r) { return strcmp(l.name, r.name) < 0; } -TranslationManager::TranslationManager() : _currentLang(-1) { +TranslationManager::TranslationManager() : _currentLang(-1), _charmap(0) { loadTranslationsInfoDat(); // Set the default language @@ -53,6 +53,7 @@ TranslationManager::TranslationManager() : _currentLang(-1) { } TranslationManager::~TranslationManager() { + delete[] _charmap; } int32 TranslationManager::findMatchingLanguage(const String &lang) { @@ -231,8 +232,9 @@ bool TranslationManager::openTranslationsFile(File &inFile) { ArchiveMemberList fileList; SearchMan.listMatchingMembers(fileList, "translations.dat"); for (ArchiveMemberList::iterator it = fileList.begin(); it != fileList.end(); ++it) { - SeekableReadStream *stream = it->get()->createReadStream(); - if (stream && inFile.open(stream, it->get()->getName())) { + ArchiveMember const &m = **it; + SeekableReadStream *const stream = m.createReadStream(); + if (stream && inFile.open(stream, m.getName())) { if (checkHeader(inFile)) return true; inFile.close(); @@ -289,9 +291,14 @@ void TranslationManager::loadTranslationsInfoDat() { // Get number of translations int nbTranslations = in.readUint16BE(); - // Skip all the block sizes - for (int i = 0; i < nbTranslations + 2; ++i) - in.readUint16BE(); + // Get number of codepages + int nbCodepages = in.readUint16BE(); + + // Determine where the codepages start + _charmapStart = 0; + for (int i = 0; i < nbTranslations + 3; ++i) + _charmapStart += in.readUint16BE(); + _charmapStart += in.pos(); // Read list of languages _langs.resize(nbTranslations); @@ -305,6 +312,14 @@ void TranslationManager::loadTranslationsInfoDat() { _langNames[i] = String(buf, len - 1); } + // Read list of codepages + _charmaps.resize(nbCodepages); + for (int i = 0; i < nbCodepages; ++i) { + len = in.readUint16BE(); + in.read(buf, len); + _charmaps[i] = String(buf, len - 1); + } + // Read messages int numMessages = in.readUint16BE(); _messageIds.resize(numMessages); @@ -344,9 +359,16 @@ void TranslationManager::loadLanguageDat(int index) { return; } + // Get the number of codepages + int nbCodepages = in.readUint16BE(); + if (nbCodepages != (int)_charmaps.size()) { + warning("The 'translations.dat' file has changed since starting ScummVM. GUI translation will not be available"); + return; + } + // Get size of blocks to skip. int skipSize = 0; - for (int i = 0; i < index + 2; ++i) + for (int i = 0; i < index + 3; ++i) skipSize += in.readUint16BE(); // We also need to skip the remaining block sizes skipSize += 2 * (nbTranslations - index); @@ -380,6 +402,29 @@ void TranslationManager::loadLanguageDat(int index) { _currentTranslationMessages[i].msgctxt = String(buf, len - 1); } } + + // Find the charset + int charmapNum = -1; + for (uint i = 0; i < _charmaps.size(); ++i) { + if (_charmaps[i].equalsIgnoreCase(_currentCharset)) { + charmapNum = i; + break; + } + } + + // Setup the new charset mapping + if (charmapNum == -1) { + delete[] _charmap; + _charmap = 0; + } else { + if (!_charmap) + _charmap = new uint32[256]; + + in.seek(_charmapStart + charmapNum * 256 * 4, SEEK_SET); + for (int i = 0; i < 256; ++i) + _charmap[i] = in.readUint32BE(); + } + } bool TranslationManager::checkHeader(File &in) { diff --git a/common/translation.h b/common/translation.h index 71cf2b0981..77e2fdfc07 100644 --- a/common/translation.h +++ b/common/translation.h @@ -154,6 +154,21 @@ public: String getCurrentCharset() const; /** + * Returns a pointer to the current charset mapping. This mapping is a + * codepage encoding -> unicode mapping and always 256 entries long. + * + * The MSB of the individual mapped (i.e. unicode) character states + * whether the character is required for this charset. If it is set, the + * character needs to be present in order to have the text displayed. + * This is used in the font loading code to detect whether the font is + * able of supporting this language. + * + * The return value might be 0 in case it's a default ASCII/ISO-8859-1 + * map. + */ + const uint32 *getCharsetMapping() const { return _charmap; } + + /** * Returns currently selected translation language */ String getCurrentLanguage() const; @@ -200,11 +215,15 @@ private: StringArray _langs; StringArray _langNames; + StringArray _charmaps; StringArray _messageIds; Array<PoMessageEntry> _currentTranslationMessages; String _currentCharset; int _currentLang; + + uint32 _charmapStart; + uint32 *_charmap; }; } // End of namespace Common diff --git a/common/unarj.cpp b/common/unarj.cpp index cccc330bb5..fe3c17a2ac 100644 --- a/common/unarj.cpp +++ b/common/unarj.cpp @@ -701,9 +701,9 @@ public: virtual ~ArjArchive(); // Archive implementation - virtual bool hasFile(const String &name); - virtual int listMembers(ArchiveMemberList &list); - virtual ArchiveMemberPtr getMember(const String &name); + virtual bool hasFile(const String &name) const; + virtual int listMembers(ArchiveMemberList &list) const; + virtual const ArchiveMemberPtr getMember(const String &name) const; virtual SeekableReadStream *createReadStreamForMember(const String &name) const; }; @@ -745,14 +745,14 @@ ArjArchive::~ArjArchive() { } } -bool ArjArchive::hasFile(const String &name) { +bool ArjArchive::hasFile(const String &name) const { return _headers.contains(name); } -int ArjArchive::listMembers(ArchiveMemberList &list) { +int ArjArchive::listMembers(ArchiveMemberList &list) const { int matches = 0; - ArjHeadersMap::iterator it = _headers.begin(); + ArjHeadersMap::const_iterator it = _headers.begin(); for ( ; it != _headers.end(); ++it) { list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(it->_value->filename, this))); matches++; @@ -761,7 +761,7 @@ int ArjArchive::listMembers(ArchiveMemberList &list) { return matches; } -ArchiveMemberPtr ArjArchive::getMember(const String &name) { +const ArchiveMemberPtr ArjArchive::getMember(const String &name) const { if (!hasFile(name)) return ArchiveMemberPtr(); diff --git a/common/unzip.cpp b/common/unzip.cpp index 8650c91866..8cfcd605fa 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -111,7 +111,7 @@ typedef struct { #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ + from (void *) without cast */ typedef struct TagunzFile__ { int unused; } unzFile__; typedef unzFile__ *unzFile; #else @@ -1062,7 +1062,7 @@ int unzOpenCurrentFile (unzFile file) { if (pfile_in_zip_read_info==NULL) return UNZ_INTERNALERROR; - pfile_in_zip_read_info->read_buffer=(char*)malloc(UNZ_BUFSIZE); + pfile_in_zip_read_info->read_buffer=(char *)malloc(UNZ_BUFSIZE); pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; @@ -1151,7 +1151,7 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { if (len==0) return 0; - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + pfile_in_zip_read_info->stream.next_out = (Bytef *)buf; pfile_in_zip_read_info->stream.avail_out = (uInt)len; @@ -1177,7 +1177,7 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->read_buffer; pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; } @@ -1426,9 +1426,9 @@ public: ~ZipArchive(); - virtual bool hasFile(const String &name); - virtual int listMembers(ArchiveMemberList &list); - virtual ArchiveMemberPtr getMember(const String &name); + virtual bool hasFile(const String &name) const; + virtual int listMembers(ArchiveMemberList &list) const; + virtual const ArchiveMemberPtr getMember(const String &name) const; virtual SeekableReadStream *createReadStreamForMember(const String &name) const; }; @@ -1458,11 +1458,11 @@ ZipArchive::~ZipArchive() { unzClose(_zipFile); } -bool ZipArchive::hasFile(const String &name) { +bool ZipArchive::hasFile(const String &name) const { return (unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK); } -int ZipArchive::listMembers(ArchiveMemberList &list) { +int ZipArchive::listMembers(ArchiveMemberList &list) const { int matches = 0; int err = unzGoToFirstFile(_zipFile); @@ -1481,7 +1481,7 @@ int ZipArchive::listMembers(ArchiveMemberList &list) { return matches; } -ArchiveMemberPtr ZipArchive::getMember(const String &name) { +const ArchiveMemberPtr ZipArchive::getMember(const String &name) const { if (!hasFile(name)) return ArchiveMemberPtr(); diff --git a/common/util.cpp b/common/util.cpp index 1c4df8b6cd..4d9ff11c5c 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -19,9 +19,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define FORBIDDEN_SYMBOL_EXCEPTION_isalnum +#define FORBIDDEN_SYMBOL_EXCEPTION_isalpha +#define FORBIDDEN_SYMBOL_EXCEPTION_isdigit +#define FORBIDDEN_SYMBOL_EXCEPTION_isnumber +#define FORBIDDEN_SYMBOL_EXCEPTION_islower +#define FORBIDDEN_SYMBOL_EXCEPTION_isspace +#define FORBIDDEN_SYMBOL_EXCEPTION_isupper + + #include "common/util.h" -#include "common/translation.h" -#include "common/config-manager.h" #include "common/debug.h" namespace Common { @@ -103,307 +110,38 @@ bool parseBool(const String &val, bool &valAsBool) { #pragma mark - -const LanguageDescription g_languages[] = { - { "zh-cn", "zh_CN", "Chinese (China)", ZH_CNA }, - { "zh", "zh_TW", "Chinese (Taiwan)", ZH_TWN }, - { "cz", "cs_CZ", "Czech", CZ_CZE }, - { "nl", "nl_NL", "Dutch", NL_NLD }, - { "en", "en", "English", EN_ANY }, // Generic English (when only one game version exist) - { "gb", "en_GB", "English (GB)", EN_GRB }, - { "us", "en_US", "English (US)", EN_USA }, - { "fr", "fr_FR", "French", FR_FRA }, - { "de", "de_DE", "German", DE_DEU }, - { "gr", "el_GR", "Greek", GR_GRE }, - { "he", "he_IL", "Hebrew", HE_ISR }, - { "hb", "he_IL", "Hebrew", HE_ISR }, // Deprecated - { "hr", "hr_HR", "Croatian", HR_HRV }, - { "hu", "hu_HU", "Hungarian", HU_HUN }, - { "it", "it_IT", "Italian", IT_ITA }, - { "jp", "ja_JP", "Japanese", JA_JPN }, - { "kr", "ko_KR", "Korean", KO_KOR }, - { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale - { "pl", "pl_PL", "Polish", PL_POL }, - { "br", "pt_BR", "Portuguese", PT_BRA }, - { "ru", "ru_RU", "Russian", RU_RUS }, - { "es", "es_ES", "Spanish", ES_ESP }, - { "se", "sv_SE", "Swedish", SE_SWE }, - { 0, 0, 0, UNK_LANG } -}; - -Language parseLanguage(const String &str) { - if (str.empty()) - return UNK_LANG; +#define ENSURE_ASCII_CHAR(c) \ + if (c < 0 || c > 127) \ + return false - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code)) - return l->id; - } - - return UNK_LANG; +bool isAlnum(int c) { + ENSURE_ASCII_CHAR(c); + return isalnum((byte)c); } -Language parseLanguageFromLocale(const char *locale) { - if (!locale || !*locale) - return UNK_LANG; - - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (!strcmp(l->unixLocale, locale)) - return l->id; - } - - return UNK_LANG; -} - -const char *getLanguageCode(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; -} - -const char *getLanguageLocale(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->unixLocale; - } - return 0; -} - -const char *getLanguageDescription(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return 0; -} - - -#pragma mark - - - -const PlatformDescription g_platforms[] = { - { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, - { "3do", "3do", "3do", "3DO", kPlatform3DO }, - { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn }, - { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga }, - { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST }, - { "c64", "c64", "c64", "Commodore 64", kPlatformC64 }, - { "pc", "dos", "ibm", "DOS", kPlatformPC }, - { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 }, - { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii }, - { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 }, - - // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). - // However, on the net many variations can be seen, like "FMTOWNS", - // "FM TOWNS", "FmTowns", etc. - { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns }, - - { "linux", "linux", "linux", "Linux", kPlatformLinux }, - { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh }, - { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine }, - { "nes", "nes", "nes", "NES", kPlatformNES }, - { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD }, - { "windows", "win", "win", "Windows", kPlatformWindows }, - { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX }, - { "cdi", "cdi", "cdi", "Philips CD-i", kPlatformCDi }, - { "ios", "ios", "ios", "Apple iOS", kPlatformIOS }, - - { 0, 0, 0, "Default", kPlatformUnknown } -}; - -Platform parsePlatform(const String &str) { - if (str.empty()) - return kPlatformUnknown; - - // Handle some special case separately, for compatibility with old config - // files. - if (str == "1") - return kPlatformAmiga; - else if (str == "2") - return kPlatformAtariST; - else if (str == "3") - return kPlatformMacintosh; - - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev)) - return l->id; - } - - return kPlatformUnknown; +bool isAlpha(int c) { + ENSURE_ASCII_CHAR(c); + return isalpha((byte)c); } - -const char *getPlatformCode(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; +bool isDigit(int c) { + ENSURE_ASCII_CHAR(c); + return isdigit((byte)c); } -const char *getPlatformAbbrev(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->abbrev; - } - return 0; +bool isLower(int c) { + ENSURE_ASCII_CHAR(c); + return islower((byte)c); } -const char *getPlatformDescription(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return l->description; +bool isSpace(int c) { + ENSURE_ASCII_CHAR(c); + return isspace((byte)c); } - -#pragma mark - - - -const RenderModeDescription g_renderModes[] = { - // I18N: Hercules is graphics card name - { "hercGreen", _s("Hercules Green"), kRenderHercG }, - { "hercAmber", _s("Hercules Amber"), kRenderHercA }, - { "cga", "CGA", kRenderCGA }, - { "ega", "EGA", kRenderEGA }, - { "amiga", "Amiga", kRenderAmiga }, - {0, 0, kRenderDefault} -}; - -DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres") -DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Amber", "lowres") - -RenderMode parseRenderMode(const String &str) { - if (str.empty()) - return kRenderDefault; - - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code)) - return l->id; - } - - return kRenderDefault; -} - -const char *getRenderModeCode(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; -} - -const char *getRenderModeDescription(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return 0; -} - -const struct GameOpt { - const char *option; - const char *desc; -} g_gameOptions[] = { - { GUIO_NOSUBTITLES, "sndNoSubs" }, - { GUIO_NOMUSIC, "sndNoMusic" }, - { GUIO_NOSPEECH, "sndNoSpeech" }, - { GUIO_NOSFX, "sndNoSFX" }, - { GUIO_NOMIDI, "sndNoMIDI" }, - - { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, - - { GUIO_MIDIPCSPK, "midiPCSpk" }, - { GUIO_MIDICMS, "midiCMS" }, - { GUIO_MIDIPCJR, "midiPCJr" }, - { GUIO_MIDIADLIB, "midiAdLib" }, - { GUIO_MIDIC64, "midiC64" }, - { GUIO_MIDIAMIGA, "midiAmiga" }, - { GUIO_MIDIAPPLEIIGS,"midiAppleIIgs" }, - { GUIO_MIDITOWNS, "midiTowns" }, - { GUIO_MIDIPC98, "midiPC98" }, - { GUIO_MIDIMT32, "midiMt32" }, - { GUIO_MIDIGM, "midiGM" }, - - { GUIO_NOASPECT, "noAspect" }, - { GUIO_EGAUNDITHER, "egaUndither" }, - - { GUIO_NONE, 0 } -}; - -bool checkGameGUIOption(const String &option, const String &str) { - for (int i = 0; g_gameOptions[i].desc; i++) { - if (option.contains(g_gameOptions[i].option)) { - if (str.contains(g_gameOptions[i].desc)) - return true; - else - return false; - } - } - return false; -} - -bool checkGameGUIOptionLanguage(Language lang, const String &str) { - if (!str.contains("lang_")) // If no languages are specified - return true; - - if (str.contains(getGameGUIOptionsDescriptionLanguage(lang))) - return true; - - return false; -} - -const String getGameGUIOptionsDescriptionLanguage(Language lang) { - if (lang == UNK_LANG) - return ""; - - return String(String("lang_") + getLanguageDescription(lang)); -} - -String parseGameGUIOptions(const String &str) { - Common::String res; - - for (int i = 0; g_gameOptions[i].desc; i++) - if (str.contains(g_gameOptions[i].desc)) - res += g_gameOptions[i].option; - - return res; -} - -const String getGameGUIOptionsDescription(const String &options) { - String res; - - for (int i = 0; g_gameOptions[i].desc; i++) - if (options.contains(g_gameOptions[i].option[0])) - res += String(g_gameOptions[i].desc) + " "; - - res.trim(); - - return res; -} - -void updateGameGUIOptions(const String &options, const String &langOption) { - const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption; - - if ((!options.empty() && !ConfMan.hasKey("guioptions")) || - (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) { - ConfMan.set("guioptions", newOptionString); - ConfMan.flushToDisk(); - } +bool isUpper(int c) { + ENSURE_ASCII_CHAR(c); + return isupper((byte)c); } } // End of namespace Common diff --git a/common/util.h b/common/util.h index dfa57d7259..b90be0675b 100644 --- a/common/util.h +++ b/common/util.h @@ -25,7 +25,6 @@ #include "common/scummsys.h" #include "common/str.h" - /** * Check whether a given pointer is aligned correctly. * Note that 'alignment' must be a power of two! @@ -78,36 +77,6 @@ template<typename T> inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; } # define SCUMMVM_CURRENT_FUNCTION "<unknown>" #endif -#define GUIO_NONE "\000" -#define GUIO_NOSUBTITLES "\001" -#define GUIO_NOMUSIC "\002" -#define GUIO_NOSPEECH "\003" -#define GUIO_NOSFX "\004" -#define GUIO_NOMIDI "\005" -#define GUIO_NOLAUNCHLOAD "\006" - -#define GUIO_MIDIPCSPK "\007" -#define GUIO_MIDICMS "\010" -#define GUIO_MIDIPCJR "\011" -#define GUIO_MIDIADLIB "\012" -#define GUIO_MIDIC64 "\013" -#define GUIO_MIDIAMIGA "\014" -#define GUIO_MIDIAPPLEIIGS "\015" -#define GUIO_MIDITOWNS "\016" -#define GUIO_MIDIPC98 "\017" -#define GUIO_MIDIMT32 "\020" -#define GUIO_MIDIGM "\021" - -#define GUIO_NOASPECT "\022" -#define GUIO_EGAUNDITHER "\023" - -#define GUIO0() (GUIO_NONE) -#define GUIO1(a) (a) -#define GUIO2(a,b) (a b) -#define GUIO3(a,b,c) (a b c) -#define GUIO4(a,b,c,d) (a b c d) -#define GUIO5(a,b,c,d,e) (a b c d e) - namespace Common { /** @@ -133,140 +102,68 @@ extern void hexdump(const byte * data, int len, int bytesPerLine = 16, int start */ bool parseBool(const String &val, bool &valAsBool); + /** - * List of game language. + * Test whether the given character is alphanumeric (a-z, A-Z, 0-9). + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is alphanumeric, false otherwise. */ -enum Language { - ZH_CNA, - ZH_TWN, - CZ_CZE, - NL_NLD, - EN_ANY, // Generic English (when only one game version exist) - EN_GRB, - EN_USA, - FR_FRA, - DE_DEU, - GR_GRE, - HE_ISR, - HR_HRV, - HU_HUN, - IT_ITA, - JA_JPN, - KO_KOR, - NB_NOR, - PL_POL, - PT_BRA, - RU_RUS, - ES_ESP, - SE_SWE, - - UNK_LANG = -1 // Use default language (i.e. none specified) -}; - -struct LanguageDescription { - const char *code; - const char *unixLocale; - const char *description; - Language id; -}; - -extern const LanguageDescription g_languages[]; - - -/** Convert a string containing a language name into a Language enum value. */ -extern Language parseLanguage(const String &str); -extern Language parseLanguageFromLocale(const char *locale); -extern const char *getLanguageCode(Language id); -extern const char *getLanguageLocale(Language id); -extern const char *getLanguageDescription(Language id); +bool isAlnum(int c); /** - * List of game platforms. Specifying a platform for a target can be used to - * give the game engines a hint for which platform the game data file are. - * This may be optional or required, depending on the game engine and the - * game in question. + * Test whether the given character is an alphabetic letter (a-z, A-Z). + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is TODO, false otherwise. */ -enum Platform { - kPlatformPC, - kPlatformAmiga, - kPlatformAtariST, - kPlatformMacintosh, - kPlatformFMTowns, - kPlatformWindows, - kPlatformNES, - kPlatformC64, - kPlatformCoCo3, - kPlatformLinux, - kPlatformAcorn, - kPlatformSegaCD, - kPlatform3DO, - kPlatformPCEngine, - kPlatformApple2GS, - kPlatformPC98, - kPlatformWii, - kPlatformPSX, - kPlatformCDi, - kPlatformIOS, - - kPlatformUnknown = -1 -}; - -struct PlatformDescription { - const char *code; - const char *code2; - const char *abbrev; - const char *description; - Platform id; -}; - -extern const PlatformDescription g_platforms[]; - -/** Convert a string containing a platform name into a Platform enum value. */ -extern Platform parsePlatform(const String &str); -extern const char *getPlatformCode(Platform id); -extern const char *getPlatformAbbrev(Platform id); -extern const char *getPlatformDescription(Platform id); +bool isAlpha(int c); /** - * List of render modes. It specifies which original graphics mode - * to use. Some targets used postprocessing dithering routines for - * reducing color depth of final image which let it to be rendered on - * such low-level adapters as CGA or Hercules. + * Test whether the given character is a decimal-digit (0-9). + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is a decimal-digit, false otherwise. */ -enum RenderMode { - kRenderDefault = 0, - kRenderEGA = 1, - kRenderCGA = 2, - kRenderHercG = 3, - kRenderHercA = 4, - kRenderAmiga = 5 -}; +bool isDigit(int c); -struct RenderModeDescription { - const char *code; - const char *description; - RenderMode id; -}; - -extern const RenderModeDescription g_renderModes[]; - -/** Convert a string containing a render mode name into a RenderingMode enum value. */ -extern RenderMode parseRenderMode(const String &str); -extern const char *getRenderModeCode(RenderMode id); -extern const char *getRenderModeDescription(RenderMode id); +/** + * Test whether the given character is a lower-case letter (a-z). + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is a lower-case letter, false otherwise. + */ +bool isLower(int c); -bool checkGameGUIOption(const String &option, const String &str); -bool checkGameGUIOptionLanguage(Language lang, const String &str); -String parseGameGUIOptions(const String &str); -const String getGameGUIOptionsDescription(const String &options); -const String getGameGUIOptionsDescriptionLanguage(Language lang); +/** + * Test whether the given character is a white-space. + * White-space characters are ' ', '\t', '\r', '\n', '\v', '\f'. + * + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is a white-space, false otherwise. + */ +bool isSpace(int c); /** - * Updates the GUI options of the current config manager - * domain, when they differ to the ones passed as - * parameter. + * Test whether the given character is an upper-case letter (A-Z). + * If the parameter is outside the range of a signed or unsigned char, then + * false is returned. + * + * @param c the character to test + * @return true if the character is an upper-case letter, false otherwise. */ -void updateGameGUIOptions(const String &options, const String &langOption); +bool isUpper(int c); } // End of namespace Common diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index f768e44382..ea3d44cf87 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -39,7 +39,7 @@ XMLParser::~XMLParser() { delete _XMLkeys; delete _stream; - for (List<XMLKeyLayout*>::iterator i = _layoutList.begin(); + for (List<XMLKeyLayout *>::iterator i = _layoutList.begin(); i != _layoutList.end(); ++i) delete *i; @@ -263,7 +263,7 @@ bool XMLParser::vparseIntegerKey(const char *key, int count, va_list args) { int *num_ptr; while (count--) { - while (isspace(static_cast<unsigned char>(*key))) + while (isSpace(*key)) key++; num_ptr = va_arg(args, int*); @@ -271,7 +271,7 @@ bool XMLParser::vparseIntegerKey(const char *key, int count, va_list args) { key = parseEnd; - while (isspace(static_cast<unsigned char>(*key))) + while (isSpace(*key)) key++; if (count && *key++ != ',') @@ -463,10 +463,10 @@ bool XMLParser::parse() { } bool XMLParser::skipSpaces() { - if (!isspace(static_cast<unsigned char>(_char))) + if (!isSpace(_char)) return false; - while (_char && isspace(static_cast<unsigned char>(_char))) + while (_char && isSpace(_char)) _char = _stream->readByte(); return true; @@ -516,7 +516,7 @@ bool XMLParser::parseToken() { _char = _stream->readByte(); } - return isspace(static_cast<unsigned char>(_char)) != 0 || _char == '>' || _char == '=' || _char == '/'; + return isSpace(_char) != 0 || _char == '>' || _char == '=' || _char == '/'; } } // End of namespace Common diff --git a/common/xmlparser.h b/common/xmlparser.h index 93433b7132..1e474b596c 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -68,9 +68,9 @@ class SeekableReadStream; struct CustomXMLKeyLayout : public XMLKeyLayout {\ typedef bool (parserName::*ParserCallback)(ParserNode *node);\ ParserCallback callback;\ - bool doCallback(XMLParser *parent, ParserNode *node) {return ((kLocalParserName*)parent->*callback)(node);} };\ + bool doCallback(XMLParser *parent, ParserNode *node) {return ((kLocalParserName *)parent->*callback)(node);} };\ virtual void buildLayout() { \ - Common::Stack<XMLKeyLayout*> layout; \ + Common::Stack<XMLKeyLayout *> layout; \ CustomXMLKeyLayout *lay = 0; \ XMLKeyLayout::XMLKeyProperty prop; \ _XMLkeys = new CustomXMLKeyLayout; \ @@ -295,7 +295,7 @@ protected: * in their name. */ virtual inline bool isValidNameChar(char c) { - return isalnum(static_cast<unsigned char>(c)) || c == '_'; + return isAlnum(c) || c == '_'; } /** @@ -334,7 +334,7 @@ protected: */ virtual void cleanup() {} - List<XMLKeyLayout*> _layoutList; + List<XMLKeyLayout *> _layoutList; private: char _char; @@ -346,7 +346,7 @@ private: String _error; /** Current error message */ String _token; /** Current text token */ - Stack<ParserNode*> _activeKey; /** Node stack of the parsed keys */ + Stack<ParserNode *> _activeKey; /** Node stack of the parsed keys */ }; } // End of namespace Common diff --git a/common/zlib.cpp b/common/zlib.cpp index 70133fea30..7d765fc539 100644 --- a/common/zlib.cpp +++ b/common/zlib.cpp @@ -49,7 +49,7 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long return Z_OK == ::uncompress(dst, dstLen, src, srcLen); } -bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen) { +bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict, uint dictLen) { if (!dst || !dstLen || !src || !srcLen) return false; @@ -68,6 +68,13 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen) if (err != Z_OK) return false; + // Set the dictionary, if provided + if (dict != 0) { + err = inflateSetDictionary(&stream, const_cast<byte *>(dict), dictLen); + if (err != Z_OK) + return false; + } + err = inflate(&stream, Z_SYNC_FLUSH); if (err != Z_OK && err != Z_STREAM_END) { inflateEnd(&stream); diff --git a/common/zlib.h b/common/zlib.h index 7af7df0da8..61322c286a 100644 --- a/common/zlib.h +++ b/common/zlib.h @@ -37,7 +37,19 @@ class WriteStream; * it possible to uncompress data in engines without being forced to link * them against zlib, thus simplifying the build system. * - * @return true on success (i.e. Z_OK), false otherwise + * Taken from the zlib manual: + * Decompresses the src buffer into the dst buffer. + * srcLen is the byte length of the source buffer. Upon entry, dstLen is the + * total size of the destination buffer, which must be large enough to hold + * the entire uncompressed data. Upon exit, dstLen is the actual size of the + * compressed buffer. + * + * @param dst the buffer to store into. + * @param dstLen a pointer to the size of the destination buffer. + * @param src the data to be decompressed. + * @param srcLen the size of the compressed data. + * + * @return true on success (i.e. Z_OK), false otherwise. */ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen); @@ -46,9 +58,24 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long * necessary inflate functions to uncompress data compressed with deflate * but *not* with the standard zlib header. * - * @return true on success (Z_OK or Z_STREAM_END), false otherwise + * Decompresses the src buffer into the dst buffer. + * srcLen is the byte length of the source buffer, dstLen is the byte + * length of the output buffer. + * It decompress as much data as possible, up to dstLen bytes. + * If a dictionary is provided through the dict buffer, uses it to initializes + * the internal decompression dictionary, before the decompression takes place. + * + * @param dst the buffer to store into. + * @param dstLen the size of the destination buffer. + * @param src the data to be decompressed. + * @param dstLen the size of the compressed data. + * @param dict (optional) a decompress dictionary. + * @param dictLen (optional) the size of the dictionary. + * Mandatory if dict is not 0. + * + * @return true on success (Z_OK or Z_STREAM_END), false otherwise. */ -bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen); +bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict = 0, uint dictLen = 0); #endif |