diff options
Diffstat (limited to 'common')
54 files changed, 1543 insertions, 740 deletions
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index 4e3f671cfd..4c7286bbb5 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -48,24 +48,16 @@ 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); + } } } } diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp new file mode 100644 index 0000000000..2808a7b5fd --- /dev/null +++ b/common/EventMapper.cpp @@ -0,0 +1,54 @@ +/* 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" + +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; + events.push_back(mappedEvent); + return events; +} + + +} // namespace Common diff --git a/common/algorithm.h b/common/algorithm.h index e7ccef4840..7a0eed89ce 100644 --- a/common/algorithm.h +++ b/common/algorithm.h @@ -73,25 +73,25 @@ Out copy_if(In first, In last, Out dst, Op op) { return dst; } -// Our 'specialized' 'set_to' template for char, signed char and unsigned char arrays. +// Our 'specialized' 'fill' template for char, signed char and unsigned char arrays. // Since C++ doesn't support partial specialized template functions (currently) we // are going this way... // With this we assure the usage of memset for those, which should be -// faster than a simple loop like for the generic 'set_to'. +// faster than a simple loop like for the generic 'fill'. template<class Value> -signed char *set_to(signed char *first, signed char *last, Value val) { +signed char *fill(signed char *first, signed char *last, Value val) { memset(first, (val & 0xFF), last - first); return last; } template<class Value> -unsigned char *set_to(unsigned char *first, unsigned char *last, Value val) { +unsigned char *fill(unsigned char *first, unsigned char *last, Value val) { memset(first, (val & 0xFF), last - first); return last; } template<class Value> -char *set_to(char *first, char *last, Value val) { +char *fill(char *first, char *last, Value val) { memset(first, (val & 0xFF), last - first); return last; } @@ -100,7 +100,7 @@ char *set_to(char *first, char *last, Value val) { * Sets all elements in the range [first, last) to val. */ template<class In, class Value> -In set_to(In first, In last, Value val) { +In fill(In first, In last, const Value &val) { while (first != last) *first++ = val; return first; 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 18cecfb98f..a2c3023362 100644 --- a/common/array.h +++ b/common/array.h @@ -24,7 +24,8 @@ #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 { @@ -37,44 +38,30 @@ namespace Common { * proportional to the number of elements in the array. * * The container class closest to this in the C++ standard library is - * std::vector. However, there are some differences. The most important one is - * that std::vector has a far more sophisticated (and complicated) memory - * management scheme. There, only elements that 'live' are actually constructed - * (i.e., have their constructor called), and objects that are removed are - * immediately destructed (have their destructor called). - * With Array, this is not the case; instead, it simply uses new[] and - * delete[] to allocate whole blocks of objects, possibly more than are - * currently 'alive'. This simplifies memory management, but may have - * undesirable side effects when one wants to use an Array of complex - * data types. - * - * @todo Improve the storage management of this class. - * In particular, don't use new[] and delete[], but rather - * construct/destruct objects manually. This way, we can - * ensure that storage which is not currently used does not - * correspond to a live active object. - * (This is only of interest for array of non-POD objects). + * std::vector. However, there are some differences. */ 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) {} Array(const Array<T> &array) : _capacity(array._size), _size(array._size), _storage(0) { if (array._storage) { allocCapacity(_size); - copy(array._storage, array._storage + _size, _storage); + uninitialized_copy(array._storage, array._storage + _size, _storage); } } @@ -82,14 +69,14 @@ 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); - copy(data, data + _size, _storage); + uninitialized_copy(data, data + _size, _storage); } ~Array() { - delete[] _storage; + freeStorage(_storage, _size); _storage = 0; _capacity = _size = 0; } @@ -97,14 +84,14 @@ public: /** Appends element to the end of the array. */ void push_back(const T &element) { if (_size + 1 <= _capacity) - _storage[_size++] = element; + new ((void *)&_storage[_size++]) T(element); else insert_aux(end(), &element, &element + 1); } void push_back(const Array<T> &array) { if (_size + array.size() <= _capacity) { - copy(array.begin(), array.end(), end()); + uninitialized_copy(array.begin(), array.end(), end()); _size += array.size(); } else insert_aux(end(), array.begin(), array.end()); @@ -114,6 +101,8 @@ public: void pop_back() { assert(_size > 0); _size--; + // We also need to destroy the last object properly here. + _storage[_size].~T(); } /** Returns a reference to the first element of the array. */ @@ -141,55 +130,57 @@ 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--; + // We also need to destroy the last object properly here. + _storage[_size].~T(); return tmp; } // 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; - delete[] _storage; + freeStorage(_storage, _size); _size = array._size; allocCapacity(_size); - copy(array._storage, array._storage + _size, _storage); + uninitialized_copy(array._storage, array._storage + _size, _storage); return *this; } - uint size() const { + size_type size() const { return _size; } void clear() { - delete[] _storage; + freeStorage(_storage, _size); _storage = 0; _size = 0; _capacity = 0; @@ -204,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; @@ -240,15 +231,15 @@ public: if (oldStorage) { // Copy old data - copy(oldStorage, oldStorage + _size, _storage); - delete[] oldStorage; + uninitialized_copy(oldStorage, oldStorage + _size, _storage); + freeStorage(oldStorage, _size); } } - void resize(uint newSize) { + void resize(size_type newSize) { reserve(newSize); - for (uint i = _size; i < newSize; ++i) - _storage[i] = T(); + for (size_type i = _size; i < newSize; ++i) + new ((void *)&_storage[i]) T(); _size = newSize; } @@ -260,26 +251,32 @@ 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 = new T[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 size_type elements) { + for (size_type i = 0; i < elements; ++i) + storage[i].~T(); + free(storage); + } + /** * Insert a range of elements coming from this or another array. * Unlike std::vector::insert, this method does not accept @@ -296,32 +293,52 @@ 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; - T *oldStorage = _storage; - if (_size + n > _capacity || (_storage <= first && first <= _storage + _size) ) { - // If there is not enough space, allocate more and - // copy old elements over. + const size_type idx = pos - _storage; + if (_size + n > _capacity || (_storage <= first && first <= _storage + _size)) { + T *const oldStorage = _storage; + + // If there is not enough space, allocate more. // Likewise, if this is a self-insert, we allocate new - // storage to avoid conflicts. This is not the most efficient - // way to ensure that, but probably the simplest on. + // storage to avoid conflicts. allocCapacity(roundUpCapacity(_size + n)); - copy(oldStorage, oldStorage + idx, _storage); - pos = _storage + idx; - } - - // Make room for the new elements by shifting back - // existing ones. - copy_backward(oldStorage + idx, oldStorage + _size, _storage + _size + n); - // Insert the new elements. - copy(first, last, pos); + // Copy the data from the old storage till the position where + // we insert new data + uninitialized_copy(oldStorage, oldStorage + idx, _storage); + // Copy the data we insert + uninitialized_copy(first, last, _storage + idx); + // Afterwards copy the old data from the position where we + // insert. + uninitialized_copy(oldStorage + idx, oldStorage + _size, _storage + idx + n); + + freeStorage(oldStorage, _size); + } else if (idx + n <= _size) { + // Make room for the new elements by shifting back + // existing ones. + // 1. Move a part of the data to the uninitialized area + uninitialized_copy(_storage + _size - n, _storage + _size, _storage + _size); + // 2. Move a part of the data to the initialized area + copy_backward(pos, _storage + _size - n, _storage + _size); + + // Insert the new elements. + copy(first, last, pos); + } else { + // Copy the old data from the position till the end to the new + // place. + uninitialized_copy(pos, _storage + _size, _storage + idx + n); + + // Copy a part of the new data to the position inside the + // initialized space. + copy(first, first + (_size - idx), pos); + + // Copy a part of the new data to the position inside the + // uninitialized space. + uninitialized_copy(first + (_size - idx), last, _storage + _size); + } // Finally, update the internal state - if (_storage != oldStorage) { - delete[] oldStorage; - } _size += n; } return pos; 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/events.h b/common/events.h index f5ace7481b..4efdd67b91 100644 --- a/common/events.h +++ b/common/events.h @@ -73,8 +73,21 @@ 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_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 +112,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 +198,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 +222,20 @@ public: * * An example for this is the Keymapper. */ -class EventMapper : public EventSource, public EventObserver { +class EventMapper { +public: + virtual ~EventMapper() {} + + /** + * Map an incoming event to one or more action events + */ + virtual List<Event> mapEvent(const Event &ev, EventSource *source) = 0; +}; + +class DefaultEventMapper : public EventMapper { public: - /** For event mappers resulting events should never be mapped */ - bool allowMapping() const { return false; } + // EventMapper interface + virtual List<Event> mapEvent(const Event &ev, EventSource *source); }; /** 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..5b7d939dc4 --- /dev/null +++ b/common/gui_options.cpp @@ -0,0 +1,132 @@ +/* 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; +} + +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); +} + +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..5649f1103d --- /dev/null +++ b/common/gui_options.h @@ -0,0 +1,88 @@ +/* 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 + +#include "common/language.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 { + + +bool checkGameGUIOption(const String &option, const String &str); +bool checkGameGUIOptionLanguage(Common::Language lang, const String &str); +String parseGameGUIOptions(const String &str); +const String getGameGUIOptionsDescription(const String &options); +const String getGameGUIOptionsDescriptionLanguage(Common::Language lang); + +/** + * 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 bdd0a2d4af..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,18 +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 { - return keycode == x.keycode && ascii == x.ascii && 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..1de01b0207 --- /dev/null +++ b/common/language.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/language.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; +} + +} // End of namespace Common diff --git a/common/language.h b/common/language.h new file mode 100644 index 0000000000..b83f0d34fd --- /dev/null +++ b/common/language.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_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); + +} // 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 2b9c68ade9..14bdfa7080 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -110,7 +110,7 @@ bool MacResManager::open(String filename) { String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();; + SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = filename; @@ -173,7 +173,7 @@ bool MacResManager::open(FSNode path, String filename) { String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();; + SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = filename; @@ -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/memory.h b/common/memory.h new file mode 100644 index 0000000000..0e5a97c20b --- /dev/null +++ b/common/memory.h @@ -0,0 +1,65 @@ +/* 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_MEMORY_H +#define COMMON_MEMORY_H + +#include "common/scummsys.h" + +namespace Common { + +/** + * Copies data from the range [first, last) to [dst, dst + (last - first)). + * It requires the range [dst, dst + (last - first)) to be valid and + * uninitialized. + */ +template<class In, class Type> +Type *uninitialized_copy(In first, In last, Type *dst) { + while (first != last) + new ((void *)dst++) Type(*first++); + return dst; +} + +/** + * Initializes the memory [first, first + (last - first)) with the value x. + * It requires the range [first, first + (last - first)) to be valid and + * uninitialized. + */ +/*template<class Type, class Value> +void uninitialized_fill(Type *first, Type *last, const Value &x) { + while (first != last) + new ((void *)first++) Type(x); +}*/ + +/** + * Initializes the memory [dst, dst + n) with the value x. + * It requires the range [dst, dst + n) to be valid and + * uninitialized. + */ +/*template<class Type, class Value> +void uninitialized_fill_n(Type *dst, size_t n, const Value &x) { + while (n--) + new ((void *)dst++) Type(x); +}*/ + +} // End of namespace Common + +#endif 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/quicktime.cpp b/common/quicktime.cpp index 9ea8c229ea..248d8b2b3a 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; @@ -135,7 +133,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') }, @@ -386,8 +384,7 @@ int QuickTimeParser::readTKHD(Atom atom) { /* track->id = */_fd->readUint32BE(); // track id (NOT 0 !) _fd->readUint32BE(); // reserved - //track->startTime = 0; // check - (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // highlevel (considering edits) duration in movie timebase + track->duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // highlevel (considering edits) duration in movie timebase _fd->readUint32BE(); // reserved _fd->readUint32BE(); // reserved @@ -410,8 +407,8 @@ int QuickTimeParser::readTKHD(Atom atom) { track->scaleFactorY.debugPrint(1, "readTKHD(): scaleFactorY ="); // these are fixed-point, 16:16 - // uint32 tkWidth = _fd->readUint32BE() >> 16; // track width - // uint32 tkHeight = _fd->readUint32BE() >> 16; // track height + //_fd->readUint32BE() >> 16; // track width + //_fd->readUint32BE() >> 16; // track height return 0; } @@ -428,17 +425,18 @@ int QuickTimeParser::readELST(Atom atom) { debug(2, "Track %d edit list count: %d", _tracks.size() - 1, track->editCount); + uint32 offset = 0; + for (uint32 i = 0; i < track->editCount; i++){ track->editList[i].trackDuration = _fd->readUint32BE(); track->editList[i].mediaTime = _fd->readSint32BE(); track->editList[i].mediaRate = Rational(_fd->readUint32BE(), 0x10000); - debugN(3, "\tDuration = %d, Media Time = %d, ", track->editList[i].trackDuration, track->editList[i].mediaTime); + track->editList[i].timeOffset = offset; + debugN(3, "\tDuration = %d (Offset = %d), Media Time = %d, ", track->editList[i].trackDuration, offset, track->editList[i].mediaTime); track->editList[i].mediaRate.debugPrint(3, "Media Rate ="); + offset += track->editList[i].trackDuration; } - if (track->editCount != 1) - warning("Multiple edit list entries. Things may go awry"); - return 0; } @@ -500,7 +498,7 @@ int QuickTimeParser::readMDHD(Atom atom) { } track->timeScale = _fd->readUint32BE(); - track->duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // duration + track->mediaDuration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // duration _fd->readUint16BE(); // language _fd->readUint16BE(); // quality @@ -793,6 +791,7 @@ QuickTimeParser::Track::Track() { duration = 0; startTime = 0; objectTypeMP4 = 0; + mediaDuration = 0; } QuickTimeParser::Track::~Track() { diff --git a/common/quicktime.h b/common/quicktime.h index e4c821e209..efd2adbd21 100644 --- a/common/quicktime.h +++ b/common/quicktime.h @@ -109,6 +109,7 @@ protected: struct EditListEntry { uint32 trackDuration; + uint32 timeOffset; int32 mediaTime; Rational mediaRate; }; @@ -154,7 +155,7 @@ protected: uint16 height; CodecType codecType; - Array<SampleDesc*> sampleDescs; + Array<SampleDesc *> sampleDescs; uint32 editCount; EditListEntry *editList; @@ -163,6 +164,7 @@ protected: uint32 frameCount; uint32 duration; + uint32 mediaDuration; uint32 startTime; Rational scaleFactorX; Rational scaleFactorY; @@ -178,7 +180,7 @@ protected: uint32 _duration; Rational _scaleFactorX; Rational _scaleFactorY; - Array<Track*> _tracks; + Array<Track *> _tracks; uint32 _beginOffset; MacResManager *_resFork; diff --git a/common/rendermode.cpp b/common/rendermode.cpp new file mode 100644 index 0000000000..62b67faee5 --- /dev/null +++ b/common/rendermode.cpp @@ -0,0 +1,81 @@ +/* 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/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} +}; + +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; +} + + +} // End of namespace Common diff --git a/common/rendermode.h b/common/rendermode.h new file mode 100644 index 0000000000..c2fece77ee --- /dev/null +++ b/common/rendermode.h @@ -0,0 +1,67 @@ +/* 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); + + +} // End of namespace Common + +#endif diff --git a/common/scummsys.h b/common/scummsys.h index fbd5bb5273..6baab7c16f 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -130,6 +130,15 @@ #define _USE_MATH_DEFINES #include <math.h> + // FIXME: We sadly can't assume standard C++ headers to be present on every + // system we support, so we should get rid of this. The solution should be to + // write a simple placement new on our own. It might be noteworthy we can't + // easily do that for systems which do have a <new>, since it might clash with + // the default definition otherwise! + // Symbian does not have <new> but the new operator + #if !defined(__SYMBIAN32__) + #include <new> + #endif #endif 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..a4f106c9d3 100644 --- a/common/singleton.h +++ b/common/singleton.h @@ -43,7 +43,7 @@ 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> + //template<class T> #if defined (_WIN32_WCE) || defined (_MSC_VER) || defined (__WINS__) //FIXME evc4 and msvc7 doesn't like it as private member public: 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 3570e8c5ae..219fce8794 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) { @@ -130,14 +131,14 @@ const char *TranslationManager::getTranslation(const char *message, const char * // Get the range of messages with the same ID (but different context) leftIndex = rightIndex = midIndex; while ( - leftIndex > 0 && - _currentTranslationMessages[leftIndex - 1].msgid == m->msgid + leftIndex > 0 && + _currentTranslationMessages[leftIndex - 1].msgid == m->msgid ) { --leftIndex; } while ( - rightIndex < (int)_currentTranslationMessages.size() - 1 && - _currentTranslationMessages[rightIndex + 1].msgid == m->msgid + rightIndex < (int)_currentTranslationMessages.size() - 1 && + _currentTranslationMessages[rightIndex + 1].msgid == m->msgid ) { ++rightIndex; } @@ -222,7 +223,7 @@ String TranslationManager::getLangById(int id) const { return ""; } -bool TranslationManager::openTranslationsFile(File& inFile) { +bool TranslationManager::openTranslationsFile(File &inFile) { // First look in the Themepath if we can find the file. if (ConfMan.hasKey("themepath") && openTranslationsFile(FSNode(ConfMan.get("themepath")), inFile)) return true; @@ -242,7 +243,7 @@ bool TranslationManager::openTranslationsFile(File& inFile) { return false; } -bool TranslationManager::openTranslationsFile(const FSNode &node, File& inFile, int depth) { +bool TranslationManager::openTranslationsFile(const FSNode &node, File &inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; @@ -289,9 +290,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 +311,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 +358,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 +401,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) { @@ -390,7 +434,7 @@ bool TranslationManager::checkHeader(File &in) { buf[12] = '\0'; // Check header - if (strcmp(buf, "TRANSLATIONS")) { + if (strcmp(buf, "TRANSLATIONS") != 0) { warning("File '%s' is not a valid translations data file. Skipping this file", in.getName()); return false; } diff --git a/common/translation.h b/common/translation.h index 9e5245702e..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; @@ -173,13 +188,13 @@ private: * then if needed using the Themepath. If found it opens the given File * to read the translations.dat file. */ - bool openTranslationsFile(File&); + bool openTranslationsFile(File &); /** * Find the translations.dat file in the given directory node. * If found it opens the given File to read the translations.dat file. */ - bool openTranslationsFile(const FSNode &node, File&, int depth = -1); + bool openTranslationsFile(const FSNode &node, File &, int depth = -1); /** * Load the list of languages from the translations.dat file @@ -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 bd2ebc4937..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,303 +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 - { "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; -} - - -#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; -} - - -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; -} - - -#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; +#define ENSURE_ASCII_CHAR(c) \ + if (c < 0 || c > 127) \ + return false - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code)) - return l->id; - } - - return kRenderDefault; +bool isAlnum(int c) { + ENSURE_ASCII_CHAR(c); + return isalnum((byte)c); } -const char *getRenderModeCode(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; +bool isAlpha(int c) { + ENSURE_ASCII_CHAR(c); + return isalpha((byte)c); } -const char *getRenderModeDescription(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return 0; +bool isDigit(int c) { + ENSURE_ASCII_CHAR(c); + return isdigit((byte)c); } -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_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; +bool isLower(int c) { + ENSURE_ASCII_CHAR(c); + return islower((byte)c); } -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; +bool isSpace(int c) { + ENSURE_ASCII_CHAR(c); + return isspace((byte)c); } -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 bad07d4cb2..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,32 +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 "\003" -#define GUIO_NOMIDI "\004" -#define GUIO_NOLAUNCHLOAD "\005" - -#define GUIO_MIDIPCSPK "\006" -#define GUIO_MIDICMS "\007" -#define GUIO_MIDIPCJR "\010" -#define GUIO_MIDIADLIB "\011" -#define GUIO_MIDIC64 "\012" -#define GUIO_MIDIAMIGA "\013" -#define GUIO_MIDIAPPLEIIGS "\014" -#define GUIO_MIDITOWNS "\015" -#define GUIO_MIDIPC98 "\016" -#define GUIO_MIDIMT32 "\017" -#define GUIO_MIDIGM "\020" - -#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 { /** @@ -129,139 +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, - 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 -}; - -struct RenderModeDescription { - const char *code; - const char *description; - RenderMode id; -}; +bool isDigit(int c); -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 |