diff options
author | culler <culler> | 2020-05-17 22:08:09 (GMT) |
---|---|---|
committer | culler <culler> | 2020-05-17 22:08:09 (GMT) |
commit | 8fe8aab16504c4e9b91e295e0ee2a537797d0316 (patch) | |
tree | 833c96abacc4d8a988e5ea3b8172bdabb3e60fdc /macosx | |
parent | 5fbfe2a7ea51ec68286bee8b30c89059022279ba (diff) | |
download | tk-8fe8aab16504c4e9b91e295e0ee2a537797d0316.zip tk-8fe8aab16504c4e9b91e295e0ee2a537797d0316.tar.gz tk-8fe8aab16504c4e9b91e295e0ee2a537797d0316.tar.bz2 |
Simplify Aqua text handling by moving encoding/decoding into the TKNSString class.
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXClipboard.c | 25 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 144 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 26 |
3 files changed, 73 insertions, 122 deletions
diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index 529b5fa..be1f16c 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -137,26 +137,19 @@ TkSelGetSelection( string = [pb stringForType:type]; } if (string) { - - /* - * Encode the string using the encoding which is used in Tcl - * when TCL_UTF_MAX = 3. This replaces each UTF-16 surrogate with - * a 3-byte sequence generated using the UTF-8 algorithm. (Even - * though UTF-8 does not allow encoding surrogates, the algorithm - * does produce a 3-byte sequence.) - */ - - char *bytes = TkNSStringToUtf(string, NULL); - result = proc(clientData, interp, bytes); - if (bytes) { - ckfree(bytes); + if (target == dispPtr->utf8Atom) { + result = proc(clientData, interp, string.UTF8String); + } else if (target == XA_STRING) { + const char *latin1 = [string + cStringUsingEncoding:NSISOLatin1StringEncoding]; + result = proc(clientData, interp, latin1); } } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s selection doesn't exist or form \"%s\" not defined", - Tk_GetAtomName(tkwin, selection), - Tk_GetAtomName(tkwin, target))); + "%s selection doesn't exist or form \"%s\" not defined", + Tk_GetAtomName(tkwin, selection), + Tk_GetAtomName(tkwin, target))); Tcl_SetErrorCode(interp, "TK", "SELECTION", "EXISTS", NULL); } return result; diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 6bd5c55..7fc0113 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -103,7 +103,9 @@ static void DrawCharsInContext(Display *display, Drawable drawable, /* * To avoid an extra copy, a TKNSString object wraps a Tcl_DString with an - * NSString that uses the DString's buffer as its character buffer. + * NSString that uses the DString's buffer as its character buffer. It can be + * constructed from a Tcl_DString and it has a DString property that handles + * converting from an NSString to a Tcl_DString */ @implementation TKNSString @@ -124,6 +126,17 @@ static void DrawCharsInContext(Display *display, Drawable drawable, return self; } +- (instancetype)initWithString:(NSString *)aString +{ + self = [self init]; + if (self) { + _string = [[NSString alloc] initWithString:aString]; + self.UTF8String = _string.UTF8String; + } + printf("Initialized with string %s\n", self.UTF8String); + return self; +} + - (void)dealloc { Tcl_DStringFree(&_ds); @@ -140,104 +153,53 @@ static void DrawCharsInContext(Display *display, Drawable drawable, { return [_string characterAtIndex:index]; } -#ifndef __clang__ -@synthesize UTF8String = _UTF8String; -#endif -@end -/* - *--------------------------------------------------------------------------- - * - * TkUtfAtIndex -- - * - * Write a sequence of bytes up to length 6 which is an encoding of a UTF-16 - * character in an NSString. Also record the unicode code point of the character. - * this may be a non-BMP character constructed by reading two surrogates from - * the NSString. See the documentation for TKNSString in tkMacOSXPrivate.h. - * - * Results: - * Returns the number of bytes written. - * - * Side effects: - * Bytes are written to the char array referenced by the pointer uni and - * the unicode code point is written to the integer referenced by the - * pointer code. - * - */ +# ifndef __clang__ +@synthesize DString = _ds; +#endif -MODULE_SCOPE int -TkUtfAtIndex( - NSString *string, - int index, - char *uni, - unsigned int *code) +- (Tcl_DString)DString { - char *ptr = uni; - UniChar uniChar = [string characterAtIndex: index]; - if (CFStringIsSurrogateHighCharacter(uniChar)) { - UniChar lowChar = [string characterAtIndex: ++index]; - *code = CFStringGetLongCharacterForSurrogatePair( - uniChar, lowChar); - ptr += Tcl_UniCharToUtf(uniChar, ptr); - ptr += Tcl_UniCharToUtf(lowChar, ptr); - return ptr - uni; - } else { - *code = (int) uniChar; - [[string substringWithRange: NSMakeRange(index, 1)] - getCString: uni - maxLength: 7 - encoding: NSUTF8StringEncoding]; - return strlen(uni); - } -} - -/* - *--------------------------------------------------------------------------- - * - * TkNSStringToUtf -- - * - * Encodes the unicode string represented by an NSString object with the - * internal encoding that Tcl uses when TCL_UTF_MAX = 3. This encoding - * is similar to UTF-8 except that non-BMP characters are encoded as two - * successive 3-byte sequences which are constructed from UTF-16 surrogates - * by applying the UTF-8 algorithm. Even though the UTF-8 encoding does not - * allow encoding surrogates, the algorithm does produce a well-defined - * 3-byte sequence. - * - * Results: - * Returns a pointer to a null-terminated byte array which encodes the - * NSString. - * - * Side effects: - * Memory is allocated to hold the byte array, which must be freed with - * ckalloc. If the pointer numBytes is not NULL the number of non-null - * bytes written to the array is stored in the integer it references. - */ + if ( _ds.string == NULL) { -MODULE_SCOPE char* -TkNSStringToUtf( - NSString *string, - int *numBytes) -{ - unsigned int code; - int i; - char *ptr, *bytes = ckalloc(6*[string length] + 1); - - ptr = bytes; - if (ptr) { - for (i = 0; i < [string length]; i++) { - ptr += TkUtfAtIndex(string, i, ptr, &code); - if (code > 0xffff){ - i++; + /* + * The DString has not been initialized. Construct it from + * our string's unicode characters. + */ + + char buffer[2*TCL_UTF_MAX]; + unsigned int index, length, ch; + + Tcl_DStringInit(&_ds); +#if TCL_UTF_MAX == 3 + for (index = 0; index < [_string length]; index++) { + UniChar uni = [_string characterAtIndex: index]; + + if (CFStringIsSurrogateHighCharacter(uni)) { + UniChar low = [_string characterAtIndex: ++index]; + ch = CFStringGetLongCharacterForSurrogatePair(uni, low); + } else { + ch = uni; } + length = TkUniCharToUtf(ch, buffer); + Tcl_DStringAppend(&_ds, buffer, length); } - *ptr = '\0'; - } - if (numBytes) { - *numBytes = ptr - bytes; +#else + for (index = 0; index < [_string length]; index++) { + ch = (int) [_string characterAtIndex: index]; + length = Tcl_UniCharToUtf(ch, buffer); + Tcl_DStringAppend(&_ds, buffer, length); + } + +#endif } - return bytes; + return _ds; } + +#ifndef __clang__ +@synthesize UTF8String = _UTF8String; +#endif +@end #define GetNSFontTraitsFromTkFontAttributes(faPtr) \ ((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \ diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 963eb6e..a0645f7 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -306,10 +306,6 @@ MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp); MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -MODULE_SCOPE NSString* TkUtfToNSString(const char *source, size_t numBytes); -MODULE_SCOPE int TkUtfAtIndex(NSString *string, int index, char *uni, - unsigned int *code); -MODULE_SCOPE char* TkNSStringToUtf(NSString *string, int *numBytes); MODULE_SCOPE unsigned TkMacOSXAddVirtual(unsigned int keycode); #pragma mark Private Objective-C Classes @@ -522,17 +518,16 @@ VISIBILITY_HIDDEN * * When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot * deal directly with UTF-8 encoded non-BMP characters, since their UTF-8 - * encoding requires 4 bytes. - * - * As a workaround, these versions of Tcl encode non-BMP characters as a string - * of length 6 in which the high and low UTF-16 surrogates have been encoded - * using the UTF-8 algorithm. The UTF-8 encoding does not allow encoding - * surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's - * NString class will refuse to instantiate an NSString from the 6-byte - * encoding. - * - * This subclass of NSString adds a new initialization method which accepts - * a C string encoded with the scheme described above. + * encoding requires 4 bytes. Instead, when using these versions of Tcl, Tk + * uses the CESU-8 encoding internally. This encoding is similar to UTF-8 + * except that it allows encoding surrogate characters as 3-byte sequences + * using the same algorithm which UTF-8 uses for non-surrogates. This means + * that a non-BMP character is encoded as a string of length 6. Apple's + * NSString class does not provide a constructor which accepts a CESU-8 encoded + * byte sequence as initial data. So we add a new class which does provide + * such a constructor. It also has a DString property which is a DString whose + * string pointer is a byte sequence encoding the NSString with the current Tk + * encoding, namely UTF-8 if TCL_MAX >= 4 or CESU-8 if TCL_MAX = 3. * *--------------------------------------------------------------------------- */ @@ -543,6 +538,7 @@ VISIBILITY_HIDDEN NSString *_string; } @property const char *UTF8String; +@property (readonly) Tcl_DString DString; - (instancetype)initWithTclUtfBytes:(const void *)bytes length:(NSUInteger)len; @end |