diff options
author | Einar Johan Trøan Sømåen | 2012-06-02 02:31:59 +0200 |
---|---|---|
committer | Einar Johan Trøan Sømåen | 2012-06-02 13:09:41 +0200 |
commit | b02b3ebb217473f670570860d0914aee59b1e656 (patch) | |
tree | d69fdffaa04678a4dd705668287f3015b0359011 /engines/wintermute/utils | |
parent | 221490a93df13fb6b17589c48c536c73ef6576b5 (diff) | |
download | scummvm-rg350-b02b3ebb217473f670570860d0914aee59b1e656.tar.gz scummvm-rg350-b02b3ebb217473f670570860d0914aee59b1e656.tar.bz2 scummvm-rg350-b02b3ebb217473f670570860d0914aee59b1e656.zip |
WINTERMUTE: Add folders for utils and video
Diffstat (limited to 'engines/wintermute/utils')
-rw-r--r-- | engines/wintermute/utils/ConvertUTF.c | 612 | ||||
-rw-r--r-- | engines/wintermute/utils/ConvertUTF.h | 149 | ||||
-rw-r--r-- | engines/wintermute/utils/PathUtil.cpp | 204 | ||||
-rw-r--r-- | engines/wintermute/utils/PathUtil.h | 56 | ||||
-rw-r--r-- | engines/wintermute/utils/StringUtil.cpp | 393 | ||||
-rw-r--r-- | engines/wintermute/utils/StringUtil.h | 70 | ||||
-rw-r--r-- | engines/wintermute/utils/crc.cpp | 234 | ||||
-rw-r--r-- | engines/wintermute/utils/crc.h | 81 | ||||
-rw-r--r-- | engines/wintermute/utils/utils.cpp | 342 | ||||
-rw-r--r-- | engines/wintermute/utils/utils.h | 71 |
10 files changed, 2212 insertions, 0 deletions
diff --git a/engines/wintermute/utils/ConvertUTF.c b/engines/wintermute/utils/ConvertUTF.c new file mode 100644 index 0000000000..8f7d6d2124 --- /dev/null +++ b/engines/wintermute/utils/ConvertUTF.c @@ -0,0 +1,612 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "ConvertUTF.h" +#ifdef CVTUTF_DEBUG +#include <stdio.h> +#endif + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; + break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF32 *target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; + break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG + if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); + } +#endif + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL + }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source + length; + switch (length) { + default: + return false; + /* Everything else falls through when "true"... */ + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: + if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: + if (a < 0xA0) return false; + break; + case 0xED: + if (a > 0x9F) return false; + break; + case 0xF0: + if (a < 0x90) return false; + break; + case 0xF4: + if (a > 0x8F) return false; + break; + default: + if (a < 0x80) return false; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source] + 1; + if (source + length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 4: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead + 1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF32 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; + case 4: + ch += *source++; + ch <<= 6; + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up the source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/ConvertUTF.h b/engines/wintermute/utils/ConvertUTF.h new file mode 100644 index 0000000000..03a8bb2bae --- /dev/null +++ b/engines/wintermute/utils/ConvertUTF.h @@ -0,0 +1,149 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + + ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + + Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/PathUtil.cpp b/engines/wintermute/utils/PathUtil.cpp new file mode 100644 index 0000000000..dc722e2389 --- /dev/null +++ b/engines/wintermute/utils/PathUtil.cpp @@ -0,0 +1,204 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include <algorithm>
+#include <fstream>
+#include "PathUtil.h"
+#include "StringUtil.h"
+
+
+#ifdef __WIN32__
+# include <shlobj.h>
+#endif
+
+#ifdef __MACOSX__
+# include <CoreServices/CoreServices.h>
+#endif
+
+#ifdef __IPHONEOS__
+# include "ios_utils.h"
+#endif
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::UnifySeparators(const AnsiString &path) {
+ AnsiString newPath = path;
+
+ std::replace(newPath.begin(), newPath.end(), L'\\', L'/');
+ return newPath;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::NormalizeFileName(const AnsiString &path) {
+ AnsiString newPath = UnifySeparators(path);
+ StringUtil::ToLowerCase(newPath);
+ return newPath;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::Combine(const AnsiString &path1, const AnsiString &path2) {
+ AnsiString newPath1 = UnifySeparators(path1);
+ AnsiString newPath2 = UnifySeparators(path2);
+
+ if (!StringUtil::EndsWith(newPath1, "/", true) && !StringUtil::StartsWith(newPath2, "/", true))
+ newPath1 += "/";
+
+ return newPath1 + newPath2;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetDirectoryName(const AnsiString &path) {
+ AnsiString newPath = UnifySeparators(path);
+
+ //size_t pos = newPath.find_last_of(L'/');
+ Common::String filename = GetFileName(path);
+ return Common::String(path.c_str(), path.size() - filename.size());
+ //if (pos == AnsiString::npos) return "";
+ //else return newPath.substr(0, pos + 1);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetFileName(const AnsiString &path) {
+ AnsiString newPath = UnifySeparators(path);
+
+ //size_t pos = newPath.find_last_of(L'/'); TODO REMOVE.
+ Common::String lastPart = Common::lastPathComponent(path, '/');
+ if (lastPart[lastPart.size() - 1 ] != '/')
+ return lastPart;
+ else
+ return path;
+ //if (pos == AnsiString::npos) return path;
+ //else return newPath.substr(pos + 1);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetFileNameWithoutExtension(const AnsiString &path) {
+ AnsiString fileName = GetFileName(path);
+
+ //size_t pos = fileName.find_last_of('.'); //TODO REMOVE!
+ // TODO: Prettify this.
+ Common::String extension = Common::lastPathComponent(path, '.');
+ Common::String filename = Common::String(path.c_str(), path.size() - extension.size());
+ return filename;
+ //if (pos == AnsiString::npos) return fileName;
+ //else return fileName.substr(0, pos);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetExtension(const AnsiString &path) {
+ AnsiString fileName = GetFileName(path);
+
+ //size_t pos = fileName.find_last_of('.');
+ return Common::lastPathComponent(path, '.');
+ //if (pos == AnsiString::npos) return "";
+ //else return fileName.substr(pos);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetSafeLogFileName() {
+ AnsiString logFileName = GetUserDirectory();
+
+#ifdef __WIN32__
+ char moduleName[MAX_PATH];
+ ::GetModuleFileName(NULL, moduleName, MAX_PATH);
+
+ AnsiString fileName = GetFileNameWithoutExtension(moduleName) + ".log";
+ fileName = Combine("/Wintermute Engine/Logs/", fileName);
+ logFileName = Combine(logFileName, fileName);
+
+#else
+ // !PORTME
+ logFileName = Combine(logFileName, "/Wintermute Engine/wme.log");
+#endif
+
+ CreateDirectory(GetDirectoryName(logFileName));
+ return logFileName;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PathUtil::CreateDirectory(const AnsiString &path) {
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PathUtil::MatchesMask(const AnsiString &fileName, const AnsiString &mask) {
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PathUtil::FileExists(const AnsiString &fileName) {
+ std::ifstream stream;
+
+ stream.open(fileName.c_str());
+ bool ret = stream.is_open();
+ stream.close();
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString PathUtil::GetUserDirectory() {
+ AnsiString userDir = "./";
+
+#ifdef __WIN32__
+ char buffer[MAX_PATH];
+ buffer[0] = '\0';
+ LPITEMIDLIST pidl = NULL;
+ LPMALLOC pMalloc;
+ if (SUCCEEDED(SHGetMalloc(&pMalloc))) {
+ SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
+ if (pidl) {
+ SHGetPathFromIDList(pidl, buffer);
+ }
+ pMalloc->Free(pidl);
+ userDir = AnsiString(buffer);
+ }
+#elif __MACOSX__
+ FSRef fileRef;
+ OSStatus error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
+ if (error == noErr) {
+ char buffer[MAX_PATH];
+ error = FSRefMakePath(&fileRef, (UInt8 *)buffer, sizeof(buffer));
+ if (error == noErr)
+ userDir = buffer;
+
+ }
+#elif __IPHONEOS__
+ char path[MAX_PATH];
+ IOS_GetDataDir(path);
+ userDir = AnsiString(path);
+#endif
+
+ return userDir;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/utils/PathUtil.h b/engines/wintermute/utils/PathUtil.h new file mode 100644 index 0000000000..0bc883a1fa --- /dev/null +++ b/engines/wintermute/utils/PathUtil.h @@ -0,0 +1,56 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_PATHUTILS_H
+#define WINTERMUTE_PATHUTILS_H
+
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+class PathUtil {
+public:
+ static AnsiString UnifySeparators(const AnsiString &path);
+ static AnsiString NormalizeFileName(const AnsiString &path);
+ static AnsiString Combine(const AnsiString &path1, const AnsiString &path2);
+ static AnsiString GetDirectoryName(const AnsiString &path);
+ static AnsiString GetFileName(const AnsiString &path);
+ static AnsiString GetFileNameWithoutExtension(const AnsiString &path);
+ static AnsiString GetExtension(const AnsiString &path);
+ static bool CreateDirectory(const AnsiString &path);
+ static bool MatchesMask(const AnsiString &fileName, const AnsiString &mask);
+
+ static bool FileExists(const AnsiString &fileName);
+
+ static AnsiString GetSafeLogFileName();
+ static AnsiString GetUserDirectory();
+};
+
+} // end of namespace WinterMute
+
+#endif // WINTERMUTE_PATHUTILS_H
diff --git a/engines/wintermute/utils/StringUtil.cpp b/engines/wintermute/utils/StringUtil.cpp new file mode 100644 index 0000000000..cd4f99e034 --- /dev/null +++ b/engines/wintermute/utils/StringUtil.cpp @@ -0,0 +1,393 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include <algorithm>
+#include <string>
+#include <sstream>
+#include "common/tokenizer.h"
+#include "StringUtil.h"
+#include "ConvertUTF.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////////
+void StringUtil::ToLowerCase(AnsiString &str) {
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/*void StringUtil::ToLowerCase(WideString &str) {
+ std::transform(str.begin(), str.end(), str.begin(), ::towlower);
+}*/
+
+//////////////////////////////////////////////////////////////////////////
+void StringUtil::ToUpperCase(AnsiString &str) {
+ std::transform(str.begin(), str.end(), str.begin(), ::toupper);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/*void StringUtil::ToUpperCase(WideString &str) {
+ std::transform(str.begin(), str.end(), str.begin(), ::towupper);
+}*/
+
+//////////////////////////////////////////////////////////////////////////
+bool StringUtil::CompareNoCase(const AnsiString &str1, const AnsiString &str2) {
+ AnsiString str1lc = str1;
+ AnsiString str2lc = str2;
+
+ ToLowerCase(str1lc);
+ ToLowerCase(str2lc);
+
+ return (str1lc == str2lc);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) {
+ WideString str1lc = str1;
+ WideString str2lc = str2;
+
+ ToLowerCase(str1lc);
+ ToLowerCase(str2lc);
+
+ return (str1lc == str2lc);
+}*/
+
+//////////////////////////////////////////////////////////////////////////
+WideString StringUtil::Utf8ToWide(const Utf8String &Utf8Str) {
+ error("StringUtil::Utf8ToWide - WideString not supported yet");
+ /* size_t WideSize = Utf8Str.size();
+
+ if (sizeof(wchar_t) == 2) {
+ wchar_t *WideStringNative = new wchar_t[WideSize + 1];
+
+ const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
+ const UTF8 *SourceEnd = SourceStart + WideSize;
+
+ UTF16 *TargetStart = reinterpret_cast<UTF16 *>(WideStringNative);
+ UTF16 *TargetEnd = TargetStart + WideSize + 1;
+
+ ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete [] WideStringNative;
+ return L"";
+ }
+ *TargetStart = 0;
+ WideString ResultString(WideStringNative);
+ delete [] WideStringNative;
+
+ return ResultString;
+ } else if (sizeof(wchar_t) == 4) {
+ wchar_t *WideStringNative = new wchar_t[WideSize + 1];
+
+ const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
+ const UTF8 *SourceEnd = SourceStart + WideSize;
+
+ UTF32 *TargetStart = reinterpret_cast<UTF32 *>(WideStringNative);
+ UTF32 *TargetEnd = TargetStart + WideSize;
+
+ ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete [] WideStringNative;
+ return L"";
+ }
+ *TargetStart = 0;
+ WideString ResultString(WideStringNative);
+ delete [] WideStringNative;
+
+ return ResultString;
+ } else {
+ return L"";
+ }*/
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////
+Utf8String StringUtil::WideToUtf8(const WideString &WideStr) {
+ error("StringUtil::WideToUtf8 - Widestring not supported yet");
+ /* size_t WideSize = WideStr.length();
+
+ if (sizeof(wchar_t) == 2) {
+ size_t Utf8Size = 3 * WideSize + 1;
+ char *Utf8StringNative = new char[Utf8Size];
+
+ const UTF16 *SourceStart = reinterpret_cast<const UTF16 *>(WideStr.c_str());
+ const UTF16 *SourceEnd = SourceStart + WideSize;
+
+ UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
+ UTF8 *TargetEnd = TargetStart + Utf8Size;
+
+ ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete [] Utf8StringNative;
+ return (Utf8String)"";
+ }
+ *TargetStart = 0;
+ Utf8String ResultString(Utf8StringNative);
+ delete [] Utf8StringNative;
+ return ResultString;
+ } else if (sizeof(wchar_t) == 4) {
+ size_t Utf8Size = 4 * WideSize + 1;
+ char *Utf8StringNative = new char[Utf8Size];
+
+ const UTF32 *SourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
+ const UTF32 *SourceEnd = SourceStart + WideSize;
+
+ UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
+ UTF8 *TargetEnd = TargetStart + Utf8Size;
+
+ ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete [] Utf8StringNative;
+ return (Utf8String)"";
+ }
+ *TargetStart = 0;
+ Utf8String ResultString(Utf8StringNative);
+ delete [] Utf8StringNative;
+ return ResultString;
+ } else {
+ return (Utf8String)"";
+ }*/
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////
+WideString StringUtil::AnsiToWide(const AnsiString &str) {
+ // using default os locale!
+ error("StringUtil::AnsiToWide - WideString not supported yet");
+ /* setlocale(LC_CTYPE, "");
+ size_t WideSize = mbstowcs(NULL, str.c_str(), 0) + 1;
+ wchar_t *wstr = new wchar_t[WideSize];
+ mbstowcs(wstr, str.c_str(), WideSize);
+ WideString ResultString(wstr);
+ delete [] wstr;
+ return ResultString;*/
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::WideToAnsi(const WideString &wstr) {
+ // using default os locale!
+ error("StringUtil::WideToAnsi - WideString not supported yet");
+ /* setlocale(LC_CTYPE, "");
+ size_t WideSize = wcstombs(NULL, wstr.c_str(), 0) + 1;
+ char *str = new char[WideSize];
+ wcstombs(str, wstr.c_str(), WideSize);
+ AnsiString ResultString(str);
+ delete [] str;
+ return ResultString;*/
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool StringUtil::StartsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) {
+ /* size_t strLength = str.size();
+ size_t patternLength = pattern.size();
+
+ if (strLength < patternLength || patternLength == 0)
+ return false;
+
+ AnsiString startPart = str.substr(0, patternLength);
+
+ if (ignoreCase) return CompareNoCase(startPart, pattern);
+ else return (startPart == pattern);*/
+ if (!ignoreCase)
+ return str.hasPrefix(pattern);
+ else {
+ size_t strLength = str.size();
+ size_t patternLength = pattern.size();
+
+ if (strLength < patternLength || patternLength == 0)
+ return false;
+
+ AnsiString startPart(str.c_str(), patternLength);
+ uint32 likeness = str.compareToIgnoreCase(pattern.c_str());
+ return (likeness == 0);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool StringUtil::EndsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) {
+ /* size_t strLength = str.size(); // TODO: Remove
+ size_t patternLength = pattern.size();
+
+ if (strLength < patternLength || patternLength == 0)
+ return false;
+
+ AnsiString endPart = str.substr(strLength - patternLength, patternLength);
+
+ if (ignoreCase) return CompareNoCase(endPart, pattern);
+ else return (endPart == pattern);*/
+ if (!ignoreCase) {
+ return str.hasSuffix(pattern);
+ } else {
+ size_t strLength = str.size();
+ size_t patternLength = pattern.size();
+
+ if (strLength < patternLength || patternLength == 0)
+ return false;
+
+ Common::String endPart(str.c_str() + (strLength - patternLength), patternLength);
+ uint32 likeness = str.compareToIgnoreCase(pattern.c_str());
+ return (likeness != 0);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool StringUtil::IsUtf8BOM(const byte *Buffer, uint32 BufferSize) {
+ if (BufferSize > 3 && Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) return true;
+ else return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::Replace(const AnsiString &str, const AnsiString &from, const AnsiString &to) {
+ if (from.empty() || from == to) return str;
+
+ AnsiString result = str;
+ /*size_t pos = 0;*/
+
+ while (result.contains(from)) {
+ const char *startPtr = strstr(result.c_str(), from.c_str());
+ uint32 index = startPtr - result.c_str();
+
+ Common::String tail(result.c_str() + index + to.size());
+ result = Common::String(result.c_str(), index);
+ result += to;
+ result += tail;
+
+ /* pos = result.find(from, pos);
+ if (pos == result.npos) break;
+
+ result.replace(pos, from.size(), to);
+ pos += to.size();*/
+ }
+
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::Trim(const AnsiString &str, bool fromLeft, bool fromRight, const AnsiString &chars) {
+ AnsiString trimmedStr = str;
+
+ if (fromRight) {
+ //trimmedStr.erase(trimmedStr.find_last_not_of(chars) + 1); // TODO
+ warning("fromRight-trim not implemented yet, %s", chars.c_str());
+ }
+ if (fromLeft) {
+ uint32 lastOf = LastIndexOf(str, chars, 0);
+ trimmedStr = Common::String(trimmedStr.c_str() + lastOf);
+ //trimmedStr.erase(0, trimmedStr.find_first_not_of(chars));
+ }
+ return trimmedStr;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int StringUtil::IndexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
+ /*size_t pos = str.find(toFind, startFrom);
+ if (pos == str.npos) return -1;
+ else return pos;*/
+ const char *index = strstr(str.c_str(), toFind.c_str());
+ if (index == NULL)
+ return -1;
+ else
+ return index - str.c_str();
+}
+
+//////////////////////////////////////////////////////////////////////////
+int StringUtil::LastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
+ /*size_t pos = str.rfind(toFind, startFrom);
+ if (pos == str.npos) return -1;
+ else return pos;*/
+ int32 lastIndex = -1;
+ bool found = false;
+ for (size_t i = startFrom; i < str.size(); i++) {
+ found = false;
+ for (size_t j = 0; j < toFind.size(); j++) {
+ if (str[i + j] != toFind[j]) {
+ found = false;
+ break;
+ } else {
+ found = true;
+ }
+ }
+ if (found)
+ lastIndex = i;
+ }
+ return lastIndex;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::ToString(size_t val) {
+ /* std::ostringstream str;
+ str << val;
+ return str.str();*/
+ return Common::String::format("%u", (uint32)val);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::ToString(int val) {
+ /* std::ostringstream str;
+ str << val;
+ return str.str();*/
+ return Common::String::format("%d", val);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::ToString(float val) {
+ /* std::ostringstream str;
+ str << val;
+ return str.str();*/
+ return Common::String::format("%f", val);
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString StringUtil::ToString(double val) {
+ /* std::ostringstream str;
+ str << val;
+ return str.str();*/
+ return Common::String::format("%f", val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void StringUtil::Split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems) {
+ result.clear();
+//TODO: Verify this, wrt keepEmptyItems.
+ Common::StringTokenizer tokenizer(list.c_str(), delimiters.c_str());
+ //typedef boost::char_separator<char> separator_t;
+ //typedef boost::tokenizer<separator_t, AnsiString::const_iterator, AnsiString> tokenizer_t;
+
+ //separator_t del(delimiters.c_str(), "", keepEmptyItems ? boost::keep_empty_tokens : boost::drop_empty_tokens);
+ //tokenizer_t tokens(list, del);
+ while (!tokenizer.empty()) {
+ Common::String copy(tokenizer.nextToken().c_str());
+ result.push_back(copy);
+ }
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/utils/StringUtil.h b/engines/wintermute/utils/StringUtil.h new file mode 100644 index 0000000000..a4727fabbe --- /dev/null +++ b/engines/wintermute/utils/StringUtil.h @@ -0,0 +1,70 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_STRINGUTIL_H
+#define WINTERMUTE_STRINGUTIL_H
+
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+class StringUtil {
+public:
+ static void ToLowerCase(AnsiString &str);
+ //static void ToLowerCase(WideString &str);
+ static void ToUpperCase(AnsiString &str);
+ //static void ToUpperCase(WideString &str);
+ static bool CompareNoCase(const AnsiString &str1, const AnsiString &str2);
+ //static bool CompareNoCase(const WideString &str1, const WideString &str2);
+ static WideString Utf8ToWide(const Utf8String &Utf8Str);
+ static Utf8String WideToUtf8(const WideString &WideStr);
+ static WideString AnsiToWide(const AnsiString &str);
+ static AnsiString WideToAnsi(const WideString &str);
+
+ static bool StartsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false);
+ static bool EndsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false);
+
+ static bool IsUtf8BOM(const byte *buffer, uint32 bufferSize);
+
+ static AnsiString Replace(const AnsiString &str, const AnsiString &from, const AnsiString &to);
+ static AnsiString Trim(const AnsiString &str, bool fromLeft = true, bool fromRight = true, const AnsiString &chars = " \n\r\t");
+
+ static int IndexOf(const WideString &str, const WideString &toFind, size_t startFrom);
+ static int LastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom);
+
+ static AnsiString ToString(size_t val);
+ static AnsiString ToString(int val);
+ static AnsiString ToString(float val);
+ static AnsiString ToString(double val);
+
+ static void Split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems = false);
+};
+
+} // end of namespace WinterMute
+
+#endif // WINTERMUTE_STRINGUTIL_H
diff --git a/engines/wintermute/utils/crc.cpp b/engines/wintermute/utils/crc.cpp new file mode 100644 index 0000000000..adfd5da624 --- /dev/null +++ b/engines/wintermute/utils/crc.cpp @@ -0,0 +1,234 @@ +/**********************************************************************
+ *
+ * Filename: crc.c
+ *
+ * Description: Slow and fast implementations of the CRC standards.
+ *
+ * Notes: The parameters for each supported CRC standard are
+ * defined in the header file crc.h. The implementations
+ * here should stand up to further additions to that list.
+ *
+ *
+ * Copyright (c) 2000 by Michael Barr. This software is placed into
+ * the public domain and may be used for any purpose. However, this
+ * notice must not be changed or removed and no warranty is either
+ * expressed or implied by its publication or distribution.
+ **********************************************************************/
+
+#include "crc.h"
+
+
+/*
+ * Derive parameters from the standard-specific parameters in crc.h.
+ */
+#define WIDTH (8 * sizeof(crc))
+#define TOPBIT (1 << (WIDTH - 1))
+
+#if (REFLECT_DATA == TRUE)
+#undef REFLECT_DATA
+#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))
+#else
+#undef REFLECT_DATA
+#define REFLECT_DATA(X) (X)
+#endif
+
+#if (REFLECT_REMAINDER == TRUE)
+#undef REFLECT_REMAINDER
+#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))
+#else
+#undef REFLECT_REMAINDER
+#define REFLECT_REMAINDER(X) (X)
+#endif
+
+
+/*********************************************************************
+ *
+ * Function: reflect()
+ *
+ * Description: Reorder the bits of a binary sequence, by reflecting
+ * them about the middle position.
+ *
+ * Notes: No checking is done that nBits <= 32.
+ *
+ * Returns: The reflection of the original data.
+ *
+ *********************************************************************/
+static unsigned long
+reflect(unsigned long data, unsigned char nBits) {
+ unsigned long reflection = 0x00000000;
+ unsigned char bit;
+
+ /*
+ * Reflect the data about the center bit.
+ */
+ for (bit = 0; bit < nBits; ++bit) {
+ /*
+ * If the LSB bit is set, set the reflection of it.
+ */
+ if (data & 0x01) {
+ reflection |= (1 << ((nBits - 1) - bit));
+ }
+
+ data = (data >> 1);
+ }
+
+ return (reflection);
+
+} /* reflect() */
+
+
+/*********************************************************************
+ *
+ * Function: crcSlow()
+ *
+ * Description: Compute the CRC of a given message.
+ *
+ * Notes:
+ *
+ * Returns: The CRC of the message.
+ *
+ *********************************************************************/
+crc
+crcSlow(unsigned char const message[], int nBytes) {
+ crc remainder = INITIAL_REMAINDER;
+ int byte;
+ unsigned char bit;
+
+
+ /*
+ * Perform modulo-2 division, a byte at a time.
+ */
+ for (byte = 0; byte < nBytes; ++byte) {
+ /*
+ * Bring the next byte into the remainder.
+ */
+ remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));
+
+ /*
+ * Perform modulo-2 division, a bit at a time.
+ */
+ for (bit = 8; bit > 0; --bit) {
+ /*
+ * Try to divide the current data bit.
+ */
+ if (remainder & TOPBIT) {
+ remainder = (remainder << 1) ^ POLYNOMIAL;
+ } else {
+ remainder = (remainder << 1);
+ }
+ }
+ }
+
+ /*
+ * The final remainder is the CRC result.
+ */
+ return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
+
+} /* crcSlow() */
+
+
+crc crcTable[256];
+
+
+/*********************************************************************
+ *
+ * Function: crcInit()
+ *
+ * Description: Populate the partial CRC lookup table.
+ *
+ * Notes: This function must be rerun any time the CRC standard
+ * is changed. If desired, it can be run "offline" and
+ * the table results stored in an embedded system's ROM.
+ *
+ * Returns: None defined.
+ *
+ *********************************************************************/
+void
+crcInit(void) {
+ crc remainder;
+ int dividend;
+ unsigned char bit;
+
+
+ /*
+ * Compute the remainder of each possible dividend.
+ */
+ for (dividend = 0; dividend < 256; ++dividend) {
+ /*
+ * Start with the dividend followed by zeros.
+ */
+ remainder = dividend << (WIDTH - 8);
+
+ /*
+ * Perform modulo-2 division, a bit at a time.
+ */
+ for (bit = 8; bit > 0; --bit) {
+ /*
+ * Try to divide the current data bit.
+ */
+ if (remainder & TOPBIT) {
+ remainder = (remainder << 1) ^ POLYNOMIAL;
+ } else {
+ remainder = (remainder << 1);
+ }
+ }
+
+ /*
+ * Store the result into the table.
+ */
+ crcTable[dividend] = remainder;
+ }
+
+} /* crcInit() */
+
+
+/*********************************************************************
+ *
+ * Function: crcFast()
+ *
+ * Description: Compute the CRC of a given message.
+ *
+ * Notes: crcInit() must be called first.
+ *
+ * Returns: The CRC of the message.
+ *
+ *********************************************************************/
+crc
+crcFast(unsigned char const message[], int nBytes) {
+ crc remainder = INITIAL_REMAINDER;
+ unsigned char data;
+ int byte;
+
+
+ /*
+ * Divide the message by the polynomial, a byte at a time.
+ */
+ for (byte = 0; byte < nBytes; ++byte) {
+ data = (unsigned char)(REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)));
+ remainder = crcTable[data] ^ (remainder << 8);
+ }
+
+ /*
+ * The final remainder is the CRC.
+ */
+ return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
+
+} /* crcFast() */
+
+
+
+crc crc_initialize(void) {
+ crcInit();
+ return INITIAL_REMAINDER;
+}
+
+crc crc_process_byte(unsigned char byte, crc remainder) {
+ unsigned char data;
+ data = (unsigned char)(REFLECT_DATA(byte) ^ (remainder >> (WIDTH - 8)));
+ remainder = crcTable[data] ^ (remainder << 8);
+ return remainder;
+}
+
+crc crc_finalize(crc remainder) {
+ return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
+}
diff --git a/engines/wintermute/utils/crc.h b/engines/wintermute/utils/crc.h new file mode 100644 index 0000000000..578b423de8 --- /dev/null +++ b/engines/wintermute/utils/crc.h @@ -0,0 +1,81 @@ +/**********************************************************************
+ *
+ * Filename: crc.h
+ *
+ * Description: A header file describing the various CRC standards.
+ *
+ * Notes:
+ *
+ *
+ * Copyright (c) 2000 by Michael Barr. This software is placed into
+ * the public domain and may be used for any purpose. However, this
+ * notice must not be changed or removed and no warranty is either
+ * expressed or implied by its publication or distribution.
+ **********************************************************************/
+
+#ifndef _crc_h
+#define _crc_h
+
+#ifndef TRUE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+/*
+ * Select the CRC standard from the list that follows.
+ */
+#define CRC32
+
+
+#if defined(CRC_CCITT)
+
+typedef unsigned short crc;
+
+#define CRC_NAME "CRC-CCITT"
+#define POLYNOMIAL 0x1021
+#define INITIAL_REMAINDER 0xFFFF
+#define FINAL_XOR_VALUE 0x0000
+#define REFLECT_DATA FALSE
+#define REFLECT_REMAINDER FALSE
+#define CHECK_VALUE 0x29B1
+
+#elif defined(CRC16)
+
+typedef unsigned short crc;
+
+#define CRC_NAME "CRC-16"
+#define POLYNOMIAL 0x8005
+#define INITIAL_REMAINDER 0x0000
+#define FINAL_XOR_VALUE 0x0000
+#define REFLECT_DATA TRUE
+#define REFLECT_REMAINDER TRUE
+#define CHECK_VALUE 0xBB3D
+
+#elif defined(CRC32)
+
+typedef unsigned long crc;
+
+#define CRC_NAME "CRC-32"
+#define POLYNOMIAL 0x04C11DB7
+#define INITIAL_REMAINDER 0xFFFFFFFF
+#define FINAL_XOR_VALUE 0xFFFFFFFF
+#define REFLECT_DATA TRUE
+#define REFLECT_REMAINDER TRUE
+#define CHECK_VALUE 0xCBF43926
+
+#else
+
+#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd."
+
+#endif
+
+void crcInit(void);
+crc crcSlow(unsigned char const message[], int nBytes);
+crc crcFast(unsigned char const message[], int nBytes);
+
+extern "C" crc crc_initialize(void);
+extern "C" crc crc_process_byte(unsigned char byte, crc remainder);
+extern "C" crc crc_finalize(crc remainder);
+
+
+#endif /* _crc_h */
diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp new file mode 100644 index 0000000000..d1ce280639 --- /dev/null +++ b/engines/wintermute/utils/utils.cpp @@ -0,0 +1,342 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "utils.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/wintypes.h"
+#include "PathUtil.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "common/str.h"
+#include "common/textconsole.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////
+static inline unsigned Sqr(int x) {
+ return (x * x);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+void CBUtils::Clip(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect) {
+ // If it's partly off the right side of the screen
+ if (*DestX + (SrcRect->right - SrcRect->left) > DestRect->right)
+ SrcRect->right -= *DestX + (SrcRect->right - SrcRect->left) - DestRect->right;
+
+ if (SrcRect->right < 0) SrcRect->right = 0;
+
+ // Partly off the left side of the screen
+ if (*DestX < DestRect->left) {
+ SrcRect->left += DestRect->left - *DestX;
+ *DestX = DestRect->left;
+ }
+
+ // Partly off the top of the screen
+ if (*DestY < DestRect->top) {
+ SrcRect->top += DestRect->top - *DestY;
+ *DestY = DestRect->top;
+ }
+
+ // If it's partly off the bottom side of the screen
+ if (*DestY + (SrcRect->bottom - SrcRect->top) > DestRect->bottom)
+ SrcRect->bottom -= ((SrcRect->bottom - SrcRect->top) + *DestY) - DestRect->bottom;
+
+ if (SrcRect->bottom < 0) SrcRect->bottom = 0;
+
+ return;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// Swap - swaps two integers
+//////////////////////////////////////////////////////////////////////////////////
+void CBUtils::Swap(int *a, int *b) {
+ int Temp = *a;
+ *a = *b;
+ *b = Temp;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBUtils::StrBeginsI(const char *String, const char *Fragment) {
+ return (scumm_strnicmp(String, Fragment, strlen(Fragment)) == 0);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+float CBUtils::NormalizeAngle(float Angle) {
+ while (Angle > 360) Angle -= 360;
+ while (Angle < 0) Angle += 360;
+
+ return Angle;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+void CBUtils::CreatePath(const char *Path, bool PathOnly) {
+ AnsiString path;
+
+ if (!PathOnly) path = PathUtil::GetDirectoryName(Path);
+ else path = Path;
+
+// try {
+ warning("CBUtils::CreatePath - not implemented: %s", Path);
+// boost::filesystem::create_directories(path);
+// } catch (...) {
+ return;
+// }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CBUtils::DebugMessage(HWND hWnd, const char *Text) {
+ //MessageBox(hWnd, Text, "WME", MB_OK|MB_ICONINFORMATION);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CBUtils::SetString(char **String, const char *Value) {
+ delete[] *String;
+ *String = new char[strlen(Value) + 1];
+ if (*String) strcpy(*String, Value);
+ return *String;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int CBUtils::StrNumEntries(const char *Str, const char Delim) {
+ int NumEntries = 1;
+ for (uint32 i = 0; i < strlen(Str); i++) {
+ if (Str[i] == Delim) NumEntries++;
+ }
+ return NumEntries;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CBUtils::StrEntry(int Entry, const char *Str, const char Delim) {
+ int NumEntries = 0;
+
+ const char *Start = NULL;
+ int Len = 0;
+
+ for (uint32 i = 0; i <= strlen(Str); i++) {
+ if (NumEntries == Entry) {
+ if (!Start) Start = Str + i;
+ else Len++;
+ }
+ if (Str[i] == Delim || Str[i] == '\0') {
+ NumEntries++;
+ if (Start) {
+ char *Ret = new char[Len + 1];
+ memset(Ret, 0, Len + 1);
+ strncpy(Ret, Start, Len);
+ return Ret;
+ }
+ }
+ }
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int CBUtils::RandomInt(int From, int To) {
+ if (To < From) {
+ int i = To;
+ To = From;
+ From = i;
+ }
+ return (rand() % (To - From + 1)) + From;
+}
+
+//////////////////////////////////////////////////////////////////////////
+float CBUtils::RandomFloat(float From, float To) {
+ float RandNum = (float)rand() / (float)RAND_MAX;
+ return From + (To - From) * RandNum;
+}
+
+//////////////////////////////////////////////////////////////////////////
+float CBUtils::RandomAngle(float From, float To) {
+ while (To < From) {
+ To += 360;
+ }
+ return NormalizeAngle(RandomFloat(From, To));
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBUtils::MatchesPattern(const char *Pattern, const char *String) {
+ char stringc, patternc;
+
+ for (;; ++String) {
+ stringc = toupper(*String);
+ patternc = toupper(*Pattern++);
+
+ switch (patternc) {
+ case 0:
+ return (stringc == 0);
+
+ case '?':
+ if (stringc == 0) return false;
+ break;
+
+ case '*':
+ if (!*Pattern) return true;
+
+ if (*Pattern == '.') {
+ char *dot;
+ if (Pattern[1] == '*' && Pattern[2] == 0) return true;
+ dot = (char *)strchr(String, '.');
+ if (Pattern[1] == 0) return (dot == NULL || dot[1] == 0);
+ if (dot != NULL) {
+ String = dot;
+ if (strpbrk(Pattern, "*?[") == NULL && strchr(String + 1, '.') == NULL)
+ return(scumm_stricmp(Pattern + 1, String + 1) == 0);
+ }
+ }
+
+ while (*String)
+ if (CBUtils::MatchesPattern(Pattern, String++))
+ return true;
+ return false;
+
+ default:
+ if (patternc != stringc)
+ if (patternc == '.' && stringc == 0)
+ return(CBUtils::MatchesPattern(Pattern, String));
+ else
+ return false;
+ break;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+char *CBUtils::GetPath(const char *Filename) {
+ AnsiString path = PathUtil::GetDirectoryName(Filename);
+ //path = boost::filesystem::syste_complete(path).string();
+ warning("CBUtils::GetPath: (%s), not implemented", Filename);
+ char *ret = new char[path.size() + 1];
+ strcpy(ret, path.c_str());
+
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+char *CBUtils::GetFilename(const char *Filename) {
+ AnsiString path = PathUtil::GetFileName(Filename);
+ char *ret = new char[path.size() + 1];
+ strcpy(ret, path.c_str());
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBUtils::RGBtoHSL(uint32 RGBColor, byte *OutH, byte *OutS, byte *OutL) {
+ float var_R = (D3DCOLGetR(RGBColor) / 255.0f);
+ float var_G = (D3DCOLGetG(RGBColor) / 255.0f);
+ float var_B = (D3DCOLGetB(RGBColor) / 255.0f);
+
+ //Min. value of RGB
+ float var_Min = MIN(var_R, var_G);
+ var_Min = MIN(var_Min, var_B);
+
+ //Max. value of RGB
+ float var_Max = MAX(var_R, var_G);
+ var_Max = MAX(var_Max, var_B);
+
+ //Delta RGB value
+ float del_Max = var_Max - var_Min;
+
+ float H, S, L;
+
+ L = (var_Max + var_Min) / 2.0f;
+
+ //This is a gray, no chroma...
+ if (del_Max == 0) {
+ H = 0;
+ S = 0;
+ }
+ //Chromatic data...
+ else {
+ if (L < 0.5f) S = del_Max / (var_Max + var_Min);
+ else S = del_Max / (2.0f - var_Max - var_Min);
+
+ float del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ float del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ float del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+
+ if (var_R == var_Max) H = del_B - del_G;
+ else if (var_G == var_Max) H = (1.0f / 3.0f) + del_R - del_B;
+ else if (var_B == var_Max) H = (2.0f / 3.0f) + del_G - del_R;
+
+ if (H < 0) H += 1;
+ if (H > 1) H -= 1;
+ }
+
+ *OutH = (byte)(H * 255);
+ *OutS = (byte)(S * 255);
+ *OutL = (byte)(L * 255);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 CBUtils::HSLtoRGB(byte InH, byte InS, byte InL) {
+ float H = InH / 255.0f;
+ float S = InS / 255.0f;
+ float L = InL / 255.0f;
+
+ byte R, G, B;
+
+
+ if (S == 0) {
+ R = (byte)(L * 255);
+ G = (byte)(L * 255);
+ B = (byte)(L * 255);
+ } else {
+ float var_1, var_2;
+
+ if (L < 0.5) var_2 = L * (1.0 + S);
+ else var_2 = (L + S) - (S * L);
+
+ var_1 = 2.0f * L - var_2;
+
+ R = (byte)(255 * Hue2RGB(var_1, var_2, H + (1.0f / 3.0f)));
+ G = (byte)(255 * Hue2RGB(var_1, var_2, H));
+ B = (byte)(255 * Hue2RGB(var_1, var_2, H - (1.0f / 3.0f)));
+ }
+ return DRGBA(255, R, G, B);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+float CBUtils::Hue2RGB(float v1, float v2, float vH) {
+ if (vH < 0.0f) vH += 1.0f;
+ if (vH > 1.0f) vH -= 1.0f;
+ if ((6.0f * vH) < 1.0f) return (v1 + (v2 - v1) * 6.0f * vH);
+ if ((2.0f * vH) < 1.0f) return (v2);
+ if ((3.0f * vH) < 2.0f) return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
+ return (v1);
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h new file mode 100644 index 0000000000..46e895ff4d --- /dev/null +++ b/engines/wintermute/utils/utils.h @@ -0,0 +1,71 @@ +/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UTILS_H
+#define WINTERMUTE_UTILS_H
+
+#include "engines/wintermute/wintypes.h"
+
+namespace WinterMute {
+
+class CBGame;
+
+class CBUtils {
+public:
+ static void Clip(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect);
+ static void Swap(int *a, int *b);
+ static bool StrBeginsI(const char *String, const char *Fragment);
+ static float NormalizeAngle(float Angle);
+
+ static void CreatePath(const char *Path, bool PathOnly = false);
+
+ static void DebugMessage(HWND hWnd, const char *Text);
+ static char *SetString(char **String, const char *Value);
+
+ static int StrNumEntries(const char *Str, const char Delim = ',');
+ static char *StrEntry(int Entry, const char *Str, const char Delim = ',');
+
+ static int RandomInt(int From, int To);
+ static float RandomFloat(float From, float To);
+ static float RandomAngle(float From, float To);
+
+ static bool MatchesPattern(const char *pattern, const char *string);
+
+ static char *GetPath(const char *Filename);
+ static char *GetFilename(const char *Filename);
+
+ static void RGBtoHSL(uint32 RGBColor, byte *OutH, byte *OutS, byte *OutL);
+ static uint32 HSLtoRGB(byte H, byte S, byte L);
+
+private:
+ static float Hue2RGB(float v1, float v2, float vH);
+};
+
+} // end of namespace WinterMute
+
+#endif
|