@@ -343,10 +343,41 @@ char *copy = (char *)OFAllocMemory(1, length + 1); memcpy(copy, string, length + 1); return copy; } + +#ifdef OF_HAVE_UNICODE_TABLES +static OFString * +decomposedString(OFString *self, const char *const *const *table, size_t size) +{ + OFMutableString *ret = [OFMutableString string]; + void *pool = objc_autoreleasePoolPush(); + const OFUnichar *characters = self.characters; + size_t length = self.length; + + for (size_t i = 0; i < length; i++) { + OFUnichar c = characters[i]; + const char *const *page; + + if (c >= size) { + [ret appendCharacters: &c length: 1]; + continue; + } + + page = table[c >> 8]; + if (page != NULL && page[c & 0xFF] != NULL) + [ret appendUTF8String: page[c & 0xFF]]; + else + [ret appendCharacters: &c length: 1]; + } + + objc_autoreleasePoolPop(pool); + + return ret; +} +#endif @implementation OFPlaceholderString #ifdef __clang__ /* We intentionally don't call into super, so silence the warning. */ # pragma clang diagnostic push @@ -2581,10 +2612,24 @@ objc_autoreleasePoolPop(pool); return [data autorelease]; } + +#ifdef OF_HAVE_UNICODE_TABLES +- (OFString *)decomposedStringWithCanonicalMapping +{ + return decomposedString(self, OFUnicodeDecompositionTable, + OFUnicodeDecompositionTableSize); +} + +- (OFString *)decomposedStringWithCompatibilityMapping +{ + return decomposedString(self, OFUnicodeDecompositionCompatTable, + OFUnicodeDecompositionCompatTableSize); +} +#endif #ifdef OF_WINDOWS - (OFString *)stringByExpandingWindowsEnvironmentStrings { if ([OFSystemInfo isWindowsNT]) {