@@ -14,10 +14,11 @@ * file. */ #include "config.h" +#include #include #include #include #include @@ -33,10 +34,25 @@ #import "unicode.h" static struct { Class isa; } placeholder; + +#ifndef OF_HAVE_UNICODE_TABLES +/* Wrap these, as they can be macros. */ +static int +toupperWrapper(int c) +{ + return toupper(c); +} + +static int +tolowerWrapper(int c) +{ + return tolower(c); +} +#endif @interface OFMutableString_placeholder: OFMutableString @end @implementation OFMutableString_placeholder @@ -238,10 +254,11 @@ return (id)&placeholder; return [super alloc]; } +#ifdef OF_HAVE_UNICODE_TABLES - (void)OF_convertWithWordStartTable: (const of_unichar_t *const[])startTable wordMiddleTable: (const of_unichar_t *const[])middleTable wordStartTableSize: (size_t)startTableSize wordMiddleTableSize: (size_t)middleTableSize { @@ -280,10 +297,44 @@ } } objc_autoreleasePoolPop(pool); } +#else +- (void)OF_convertWithWordStartFunction: (int (*)(int))startFunction + wordMiddleFunction: (int (*)(int))middleFunction +{ + void *pool = objc_autoreleasePoolPush(); + const of_unichar_t *characters = [self characters]; + size_t length = [self length]; + bool isStart = true; + + for (size_t i = 0; i < length; i++) { + int (*function)(int) = + (isStart ? startFunction : middleFunction);; + of_unichar_t c = characters[i]; + + if (c <= 0x7F) + [self setCharacter: (int)function(c) + atIndex: i]; + + switch (c) { + case ' ': + case '\t': + case '\n': + case '\r': + isStart = true; + break; + default: + isStart = false; + break; + } + } + + objc_autoreleasePoolPop(pool); +} +#endif - (void)setCharacter: (of_unichar_t)character atIndex: (size_t)index { void *pool = objc_autoreleasePoolPush(); @@ -407,10 +458,11 @@ [self setCharacter: tmp atIndex: i]; } } +#ifdef OF_HAVE_UNICODE_TABLES - (void)uppercase { [self OF_convertWithWordStartTable: of_unicode_uppercase_table wordMiddleTable: of_unicode_uppercase_table wordStartTableSize: OF_UNICODE_UPPERCASE_TABLE_SIZE @@ -430,10 +482,29 @@ [self OF_convertWithWordStartTable: of_unicode_titlecase_table wordMiddleTable: of_unicode_lowercase_table wordStartTableSize: OF_UNICODE_TITLECASE_TABLE_SIZE wordMiddleTableSize: OF_UNICODE_LOWERCASE_TABLE_SIZE]; } +#else +- (void)uppercase +{ + [self OF_convertWithWordStartFunction: toupperWrapper + wordMiddleFunction: toupperWrapper]; +} + +- (void)lowercase +{ + [self OF_convertWithWordStartFunction: tolowerWrapper + wordMiddleFunction: tolowerWrapper]; +} + +- (void)capitalize +{ + [self OF_convertWithWordStartFunction: toupperWrapper + wordMiddleFunction: tolowerWrapper]; +} +#endif - (void)insertString: (OFString*)string atIndex: (size_t)index { [self replaceCharactersInRange: of_range(index, 0)