diff options
author | Norbert Lange | 2009-07-01 14:45:24 +0000 |
---|---|---|
committer | Norbert Lange | 2009-07-01 14:45:24 +0000 |
commit | abef70f4e14f495b20097cb46411d1fafbafdd53 (patch) | |
tree | 27462f82f352b303ac059dd275466930c88b2de6 /common | |
parent | 3b94e2488df9a699a899727515ac69af6a0a1a6e (diff) | |
parent | f9298ff40310149779b37ccdecc873afba7adf2f (diff) | |
download | scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.gz scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.bz2 scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.zip |
Merging in changes from trunk
svn-id: r41989
Diffstat (limited to 'common')
-rw-r--r-- | common/debug.cpp | 26 | ||||
-rw-r--r-- | common/debug.h | 23 | ||||
-rw-r--r-- | common/hashmap.cpp | 7 | ||||
-rw-r--r-- | common/hashmap.h | 150 | ||||
-rw-r--r-- | common/iff_container.h | 198 | ||||
-rw-r--r-- | common/system.h | 38 | ||||
-rw-r--r-- | common/util.cpp | 1 | ||||
-rw-r--r-- | common/util.h | 1 |
8 files changed, 310 insertions, 134 deletions
diff --git a/common/debug.cpp b/common/debug.cpp index cc358596f7..ff17959cbf 100644 --- a/common/debug.cpp +++ b/common/debug.cpp @@ -227,6 +227,19 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) { va_end(va); } +void debugCN(int level, uint32 debugChannels, const char *s, ...) { + va_list va; + + // Debug level 11 turns on all special debug level messages + if (gDebugLevel != 11) + if (level > gDebugLevel || !(Common::gDebugLevelsEnabled & debugChannels)) + return; + + va_start(va, s); + debugHelper(s, va, false); + va_end(va); +} + void debugC(uint32 debugChannels, const char *s, ...) { va_list va; @@ -240,4 +253,17 @@ void debugC(uint32 debugChannels, const char *s, ...) { va_end(va); } +void debugCN(uint32 debugChannels, const char *s, ...) { + va_list va; + + // Debug level 11 turns on all special debug level messages + if (gDebugLevel != 11) + if (!(Common::gDebugLevelsEnabled & debugChannels)) + return; + + va_start(va, s); + debugHelper(s, va, false); + va_end(va); +} + #endif diff --git a/common/debug.h b/common/debug.h index 43fe297859..95779af617 100644 --- a/common/debug.h +++ b/common/debug.h @@ -106,6 +106,8 @@ inline void debug(int level, const char *s, ...) {} inline void debugN(int level, const char *s, ...) {} inline void debugC(int level, uint32 engine_level, const char *s, ...) {} inline void debugC(uint32 engine_level, const char *s, ...) {} +inline void debugCN(int level, uint32 engine_level, const char *s, ...) {} +inline void debugCN(uint32 engine_level, const char *s, ...) {} #else @@ -135,7 +137,7 @@ void debugN(int level, const char *s, ...) GCC_PRINTF(2, 3); /** * Print a debug message to the text console (stdout), but only if - * the specified level does not exceed the value of gDebugLevel OR + * the specified level does not exceed the value of gDebugLevel AND * if the specified special debug level is active. * As a rule of thumb, the more important the message, the lower the level. * Automatically appends a newline. @@ -146,6 +148,17 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4 /** * Print a debug message to the text console (stdout), but only if + * the specified level does not exceed the value of gDebugLevel AND + * if the specified special debug level is active. + * As a rule of thumb, the more important the message, the lower the level. + * Does not append a newline automatically. + * + * @see enableDebugChannel + */ +void debugCN(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4); + +/** + * Print a debug message to the text console (stdout), but only if * the specified special debug level is active. * Automatically appends a newline. * @@ -153,6 +166,14 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4 */ void debugC(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); +/** + * Print a debug message to the text console (stdout), but only if + * the specified special debug level is active. + * Does not append a newline automatically. + * + * @see enableDebugChannel + */ +void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); #endif diff --git a/common/hashmap.cpp b/common/hashmap.cpp index 0fb03ec3f8..d8b84f61a5 100644 --- a/common/hashmap.cpp +++ b/common/hashmap.cpp @@ -58,6 +58,7 @@ uint hashit_lower(const char *p) { #ifdef DEBUG_HASH_COLLISIONS static double g_collisions = 0, + g_dummyHits = 0, g_lookups = 0, g_collPerLook = 0, g_capacity = 0, @@ -66,9 +67,10 @@ static int g_max_capacity = 0, g_max_size = 0; static int g_totalHashmaps = 0; static int g_stats[4] = {0,0,0,0}; -void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) { +void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int arrsize, int nele) { g_collisions += collisions; g_lookups += lookups; + g_dummyHits += dummyHits; if (lookups) g_collPerLook += (double)collisions / (double)lookups; g_capacity += arrsize; @@ -87,9 +89,10 @@ void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele g_max_capacity = MAX(g_max_capacity, arrsize); g_max_size = MAX(g_max_size, nele); - fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", + fprintf(stdout, "%d hashmaps: colls %.1f; dummies hit %.1f, lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", g_totalHashmaps, g_collisions / g_totalHashmaps, + g_dummyHits / g_totalHashmaps, g_lookups / g_totalHashmaps, 100 * g_collPerLook / g_totalHashmaps, g_size / g_totalHashmaps, g_max_size, diff --git a/common/hashmap.h b/common/hashmap.h index 16de7cdf54..fa613782cf 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -24,8 +24,7 @@ */ // The hash map (associative array) implementation in this file is -// based on the PyDict implementation of CPython. The erase() method -// is based on example code in the Wikipedia article on Hash tables. +// based on the PyDict implementation of CPython. #ifndef COMMON_HASHMAP_H #define COMMON_HASHMAP_H @@ -72,7 +71,8 @@ public: struct Node { const Key _key; Val _value; - Node(const Key &key) : _key(key), _value() {} + explicit Node(const Key &key) : _key(key), _value() {} + Node() : _key(), _value() {} }; enum { @@ -98,12 +98,14 @@ public: } void freeNode(Node *node) { - _nodePool.deleteChunk(node); + if (node && node != &_dummyNode) + _nodePool.deleteChunk(node); } 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) HashFunc _hash; EqualFunc _equal; @@ -111,8 +113,11 @@ public: // Default value, returned by the const getVal. const Val _defaultVal; + // Dummy node, used as marker for erased objects. + Node _dummyNode; + #ifdef DEBUG_HASH_COLLISIONS - mutable int _collisions, _lookups; + mutable int _collisions, _lookups, _dummyHits; #endif void assign(const HM_t &map); @@ -269,7 +274,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() #ifdef __PLAYSTATION2__ { #else - : _defaultVal() { + : _defaultVal(), _dummyNode() { #endif _mask = HASHMAP_MIN_CAPACITY - 1; _storage = new Node *[HASHMAP_MIN_CAPACITY]; @@ -277,10 +282,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *)); _size = 0; + _deleted = 0; #ifdef DEBUG_HASH_COLLISIONS _collisions = 0; _lookups = 0; + _dummyHits = 0; #endif } @@ -291,7 +298,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() */ template<class Key, class Val, class HashFunc, class EqualFunc> HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : - _defaultVal() { + _defaultVal(), _dummyNode() { +#ifdef DEBUG_HASH_COLLISIONS + _collisions = 0; + _lookups = 0; + _dummyHits = 0; +#endif assign(map); } @@ -301,13 +313,12 @@ 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) - if (_storage[ctr] != NULL) - freeNode(_storage[ctr]); + freeNode(_storage[ctr]); delete[] _storage; #ifdef DEBUG_HASH_COLLISIONS - extern void updateHashCollisionStats(int, int, int, int); - updateHashCollisionStats(_collisions, _lookups, _mask+1, _size); + extern void updateHashCollisionStats(int, int, int, int, int); + updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size); #endif } @@ -327,8 +338,12 @@ 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) { - if (map._storage[ctr] != NULL) { + if (map._storage[ctr] == &map._dummyNode) { + _storage[ctr] = &_dummyNode; + _deleted++; + } else if (map._storage[ctr] != NULL) { _storage[ctr] = allocNode(map._storage[ctr]->_key); _storage[ctr]->_value = map._storage[ctr]->_value; _size++; @@ -336,16 +351,15 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { } // Perform a sanity check (to help track down hashmap corruption) assert(_size == map._size); + assert(_deleted == map._deleted); } 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) { - if (_storage[ctr] != NULL) { - freeNode(_storage[ctr]); - _storage[ctr] = NULL; - } + freeNode(_storage[ctr]); + _storage[ctr] = NULL; } #ifdef USE_HASHMAP_MEMORY_POOL @@ -362,6 +376,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { } _size = 0; + _deleted = 0; } template<class Key, class Val, class HashFunc, class EqualFunc> @@ -374,6 +389,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // allocate a new array _size = 0; + _deleted = 0; _mask = newCapacity - 1; _storage = new Node *[newCapacity]; assert(_storage != NULL); @@ -381,7 +397,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // rehash all the old elements for (uint ctr = 0; ctr <= old_mask; ++ctr) { - if (old_storage[ctr] == NULL) + if (old_storage[ctr] == NULL || old_storage[ctr] == &_dummyNode) continue; // Insert the element from the old table into the new table. @@ -390,7 +406,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // 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; perturb >>= HASHMAP_PERTURB_SHIFT) { + for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != &_dummyNode; perturb >>= HASHMAP_PERTURB_SHIFT) { idx = (5 * idx + perturb + 1) & _mask; } @@ -412,7 +428,13 @@ int 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) { - if (_storage[ctr] == NULL || _equal(_storage[ctr]->_key, key)) + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == &_dummyNode) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + } else if (_equal(_storage[ctr]->_key, key)) break; ctr = (5 * ctr + perturb + 1) & _mask; @@ -424,8 +446,8 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { #ifdef DEBUG_HASH_COLLISIONS _lookups++; - fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", - _collisions, _lookups, ((double) _collisions / (double)_lookups), + fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), (const void *)this, _mask+1, _size); #endif @@ -434,16 +456,54 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { template<class Key, class Val, class HashFunc, class EqualFunc> int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { - uint ctr = lookup(key); + const uint hash = _hash(key); + uint ctr = hash & _mask; + const uint NONE_FOUND = _mask + 1; + uint first_free = NONE_FOUND; + bool found = false; + for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == &_dummyNode) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + if (first_free != _mask + 1) + first_free = ctr; + } else if (_equal(_storage[ctr]->_key, key)) { + found = true; + break; + } - if (_storage[ctr] == NULL) { + ctr = (5 * ctr + perturb + 1) & _mask; + +#ifdef DEBUG_HASH_COLLISIONS + _collisions++; +#endif + } + +#ifdef DEBUG_HASH_COLLISIONS + _lookups++; + fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), + (const void *)this, _mask+1, _size); +#endif + + if (!found && first_free != _mask + 1) + ctr = first_free; + + if (!found) { + if (_storage[ctr]) + _deleted--; _storage[ctr] = allocNode(key); assert(_storage[ctr] != NULL); _size++; // Keep the load factor below a certain threshold. + // Deleted nodes are also counted uint capacity = _mask + 1; - if (_size * HASHMAP_LOADFACTOR_DENOMINATOR > capacity * HASHMAP_LOADFACTOR_NUMERATOR) { + if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR > + capacity * HASHMAP_LOADFACTOR_NUMERATOR) { capacity = capacity < 500 ? (capacity * 4) : (capacity * 2); expandStorage(capacity); ctr = lookup(key); @@ -496,44 +556,16 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &v template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { - // This is based on code in the Wikipedia article on Hash tables. - - const uint hash = _hash(key); - uint i = hash & _mask; - uint perturb; - - for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { - if (_storage[i] == NULL || _equal(_storage[i]->_key, key)) - break; - i = (5 * i + perturb + 1) & _mask; - } + uint ctr = lookup(key); + if (_storage[ctr] == NULL) + return; - if (_storage[i] == NULL) - return; // key wasn't present, so no work has to be done - - // If we remove a key, we must check all subsequent keys and possibly - // reinsert them. - uint j = i; - freeNode(_storage[i]); - _storage[i] = NULL; - for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { - // Look at the next table slot - j = (5 * j + perturb + 1) & _mask; - // If the next slot is empty, we are done - if (_storage[j] == NULL) - break; - // Compute the slot where the content of the next slot should normally be, - // assuming an empty table, and check whether we have to move it. - uint k = _hash(_storage[j]->_key) & _mask; - if ((j > i && (k <= i || k > j)) || - (j < i && (k <= i && k > j)) ) { - _storage[i] = _storage[j]; - i = j; - } - } - _storage[i] = NULL; + // If we remove a key, we replace it with a dummy node. + freeNode(_storage[ctr]); + _storage[ctr] = &_dummyNode; _size--; + _deleted++; return; } diff --git a/common/iff_container.h b/common/iff_container.h index 617bdde690..ebcf9ba803 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -27,6 +27,7 @@ #include "common/scummsys.h" #include "common/endian.h" +#include "common/func.h" #include "common/stream.h" #include "common/util.h" @@ -145,90 +146,159 @@ page 376) */ char * ID2string(Common::IFF_ID id); -class IFFChunk : public Common::ReadStream { - -protected: - Common::ReadStream *_input; - uint32 bytesRead; - -public: - IFF_ID id; - uint32 size; - - IFFChunk(Common::ReadStream *input): _input(input) { - size = bytesRead = 0; - } - - void incBytesRead(uint32 inc) { - bytesRead += inc; - if (bytesRead > size) { - error("Chunk '%s' overread", ID2string(id)); - } - } +/** + * Represents a IFF chunk available to client code. + * + * Client code must *not* deallocate _stream when done. + */ +struct IFFChunk { + Common::IFF_ID _type; + uint32 _size; + Common::ReadStream *_stream; - void readHeader() { - id = _input->readUint32BE(); - size = _input->readUint32BE(); - bytesRead = 0; + IFFChunk(Common::IFF_ID type, uint32 size, Common::ReadStream *stream) : _type(type), _size(size), _stream(stream) { + assert(_stream); } +}; - bool hasReadAll() const { - return (size - bytesRead) == 0; - } +/** + * Parser for IFF containers. + */ +class IFFParser { - void feed() { - if (size % 2) { - size++; + /** + * This private class implements IFF chunk navigation. + */ + class IFFChunkNav : public Common::ReadStream { + protected: + Common::ReadStream *_input; + uint32 _bytesRead; + public: + Common::IFF_ID id; + uint32 size; + + IFFChunkNav() : _input(0) { } - while (!hasReadAll()) { - readByte(); + void setInputStream(Common::ReadStream *input) { + _input = input; + size = _bytesRead = 0; } - } + void incBytesRead(uint32 inc) { + _bytesRead += inc; + if (_bytesRead > size) { + error("Chunk overread"); + } + } + void readHeader() { + id = _input->readUint32BE(); + size = _input->readUint32BE(); + _bytesRead = 0; + } + bool hasReadAll() const { + return (size - _bytesRead) == 0; + } + void feed() { + if (size % 2) { + size++; + } + while (!hasReadAll()) { + readByte(); + } + } + // Common::ReadStream implementation + bool eos() const { return _input->eos(); } + bool err() const { return _input->err(); } + void clearErr() { _input->clearErr(); } + + uint32 read(void *dataPtr, uint32 dataSize) { + incBytesRead(dataSize); + return _input->read(dataPtr, dataSize); + } + }; - // Common::ReadStream implementation - bool eos() const { return _input->eos(); } - bool err() const { return _input->err(); } - void clearErr() { _input->clearErr(); } +protected: + IFFChunkNav _formChunk; //!< The root chunk of the file. + IFFChunkNav _chunk; //!< The current chunk. - uint32 read(void *dataPtr, uint32 dataSize) { - incBytesRead(dataSize); - return _input->read(dataPtr, dataSize); - } + uint32 _formSize; + Common::IFF_ID _formType; -}; + Common::ReadStream *_stream; + bool _disposeStream; + + void setInputStream(Common::ReadStream *stream) { + assert(stream); + _formChunk.setInputStream(stream); + _chunk.setInputStream(stream); -class IFFParser { -public: - IFFParser(Common::ReadStream &input) : _formChunk(&input), _chunk(&input) { _formChunk.readHeader(); if (_formChunk.id != ID_FORM) { error("IFFParser input is not a FORM type IFF file"); } - _typeId = _formChunk.readUint32BE(); + _formSize = _formChunk.size; + _formType = _formChunk.readUint32BE(); } - virtual ~IFFParser() {} - - IFFChunk *nextChunk() { - _chunk.feed(); - _formChunk.incBytesRead(_chunk.size); - - if (_formChunk.hasReadAll()) - return 0; - - _formChunk.incBytesRead(8); - _chunk.readHeader(); - - return &_chunk; +public: + IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(disposeStream) { + setInputStream(stream); + } + ~IFFParser() { + if (_disposeStream) { + delete _stream; + } + _stream = 0; } - IFF_ID _typeId; - -protected: - IFFChunk _formChunk; - IFFChunk _chunk; + /** + * Returns the IFF FORM type. + * @return the IFF FORM type of the stream, or 0 if FORM header is not found. + */ + Common::IFF_ID getFORMType() const; + + /** + * Returns the size of the data. + * @return the size of the data in file, or -1 if FORM header is not found. + */ + uint32 getFORMSize() const; + + /** + * Callback type for the parser. + */ + typedef Common::Functor1< IFFChunk&, bool > IFFCallback; + + /** + * Parse the IFF container, invoking the callback on each chunk encountered. + * The callback can interrupt the parsing by returning 'true'. + */ + void parse(IFFCallback &callback) { + bool stop; + do { + _chunk.feed(); + _formChunk.incBytesRead(_chunk.size); + + if (_formChunk.hasReadAll()) { + break; + } + + _formChunk.incBytesRead(8); + _chunk.readHeader(); + + // invoke the callback + Common::SubReadStream stream(&_chunk, _chunk.size); + IFFChunk chunk(_chunk.id, _chunk.size, &stream); + stop = callback(chunk); + + // eats up all the remaining data in the chunk + while (!stream.eos()) { + stream.readByte(); + } + + } while (!stop); + } }; + } // namespace Common #endif diff --git a/common/system.h b/common/system.h index 5b72dab7c1..5b3c208661 100644 --- a/common/system.h +++ b/common/system.h @@ -148,6 +148,10 @@ public: * It is currently used only by some Macintosh versions of Humongous * Entertainment games. If the backend doesn't implement this feature then * the engine switches to b/w versions of cursors. + * The GUI also relies on this feature for mouse cursors. + * + * To enable the cursor palette call "disableCursorPalette" with false. + * @see disableCursorPalette */ kFeatureCursorHasPalette, @@ -662,10 +666,25 @@ public: - /** @name Mouse */ + /** @name Mouse + * This is the lower level implementation as provided by the + * backends. The engines should use the Graphics::CursorManager + * class instead of using it directly. + */ //@{ - /** Show or hide the mouse cursor. */ + /** + * Show or hide the mouse cursor. + * + * Currently the backend is not required to immediately draw the + * mouse cursor on showMouse(true). + * + * TODO: We might want to reconsider this fact, + * check Graphics::CursorManager::showMouse for some details about + * this. + * + * @see Graphics::CursorManager::showMouse + */ virtual bool showMouse(bool visible) = 0; /** @@ -830,6 +849,9 @@ public: * @name Audio CD * The methods in this group deal with Audio CD playback. * The default implementation simply does nothing. + * This is the lower level implementation as provided by the + * backends. The engines should use the Audio::AudioCDManager + * class instead of using it directly. */ //@{ @@ -875,13 +897,11 @@ public: /** * Set a window caption or any other comparable status display to the - * given value. The caption must be a pure ASCII string. Passing a - * non-ASCII string may lead to unexpected behavior, even crashes. + * given value. The caption must be a pure ISO LATIN 1 string. Passing a + * string with a different encoding may lead to unexpected behavior, + * even crashes. * - * In a future revision of this API, this may be changed to allowing - * UTF-8 or UTF-16 encoded data, or maybe ISO LATIN 1. - * - * @param caption the window caption to use, as an ASCII string + * @param caption the window caption to use, as an ISO LATIN 1 string */ virtual void setWindowCaption(const char *caption) {} @@ -891,6 +911,8 @@ public: * rectangle over the regular screen content; or in a message box beneath * it; etc.). * + * Currently, only pure ASCII messages can be expected to show correctly. + * * @note There is a default implementation which uses a TimedMessageDialog * to display the message. Hence implementing this is optional. * diff --git a/common/util.cpp b/common/util.cpp index ff665468af..e99bbeb12d 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -211,6 +211,7 @@ const LanguageDescription g_languages[] = { {"ru", "Russian", RU_RUS}, {"es", "Spanish", ES_ESP}, {"se", "Swedish", SE_SWE}, + {"hu", "Hungarian", HU_HUN}, {0, 0, UNK_LANG} }; diff --git a/common/util.h b/common/util.h index ea4d280fbc..e50dcebff0 100644 --- a/common/util.h +++ b/common/util.h @@ -172,6 +172,7 @@ enum Language { RU_RUS, ES_ESP, SE_SWE, + HU_HUN, UNK_LANG = -1 // Use default language (i.e. none specified) }; |