diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 8a964f03b2..e70a33b152 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -232,7 +232,17 @@ uint QZ_ListModes(OTTD_Point *modes, uint max_modes, CGDirectDisplayID display_i @end /** Subclass of NSView to fix Quartz rendering and mouse awareness */ -@interface OTTD_CocoaView : NSView { +@interface OTTD_CocoaView : NSView +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +# else + +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 */ +#else + +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */ +{ CocoaSubdriver *driver; NSTrackingRectTag trackingtag; } diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 69af4786db..2b6e9616df 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -829,29 +829,62 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) } -/** Insert the given text at the caret. */ -- (void)insertText:(id)aString +/** Insert the given text at the given range. */ +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { + if (!EditBoxInGlobalFocus()) return; + NSString *s = [ aString isKindOfClass:[ NSAttributedString class ] ] ? [ aString string ] : (NSString *)aString; + const char *insert_point = NULL; + const char *replace_range = NULL; + if (replacementRange.location != NSNotFound) { + /* Calculate the part to be replaced. */ + insert_point = Utf8AdvanceByUtf16Units(_focused_window->GetFocusedText(), replacementRange.location); + replace_range = Utf8AdvanceByUtf16Units(insert_point, replacementRange.length); + } + HandleTextInput(NULL, true); - HandleTextInput([ s UTF8String ]); + HandleTextInput([ s UTF8String ], false, NULL, insert_point, replace_range); +} + +/** Insert the given text at the caret. */ +- (void)insertText:(id)aString +{ + [ self insertText:aString replacementRange:NSMakeRange(NSNotFound, 0) ]; } /** Set a new marked text and reposition the caret. */ -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange replacementRange:(NSRange)replacementRange { + if (!EditBoxInGlobalFocus()) return; + NSString *s = [ aString isKindOfClass:[ NSAttributedString class ] ] ? [ aString string ] : (NSString *)aString; const char *utf8 = [ s UTF8String ]; if (utf8 != NULL) { + const char *insert_point = NULL; + const char *replace_range = NULL; + if (replacementRange.location != NSNotFound) { + /* Calculate the part to be replaced. */ + NSRange marked = [ self markedRange ]; + insert_point = Utf8AdvanceByUtf16Units(_focused_window->GetFocusedText(), replacementRange.location + (marked.location != NSNotFound ? marked.location : 0u)); + replace_range = Utf8AdvanceByUtf16Units(insert_point, replacementRange.length); + } + /* Convert caret index into a pointer in the UTF-8 string. */ const char *selection = Utf8AdvanceByUtf16Units(utf8, selRange.location); - HandleTextInput(utf8, true, selection); + HandleTextInput(utf8, true, selection, insert_point, replace_range); } } +/** Set a new marked text and reposition the caret. */ +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange +{ + [ self setMarkedText:aString selectedRange:selRange replacementRange:NSMakeRange(NSNotFound, 0) ]; +} + /** Unmark the current marked text. */ - (void)unmarkText { @@ -894,18 +927,33 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) } /** Get a string corresponding to the given range. */ -- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange { if (!EditBoxInGlobalFocus()) return nil; NSString *s = [ NSString stringWithUTF8String:_focused_window->GetFocusedText() ]; NSRange valid_range = NSIntersectionRange(NSMakeRange(0, [ s length ]), theRange); + if (actualRange != NULL) *actualRange = valid_range; if (valid_range.length == 0) return nil; return [ [ [ NSAttributedString alloc ] initWithString:[ s substringWithRange:valid_range ] ] autorelease ]; } +/** Get a string corresponding to the given range. */ +- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange +{ + return [ self attributedSubstringForProposedRange:theRange actualRange:NULL ]; +} + +/** Get the current edit box string. */ +- (NSAttributedString *)attributedString +{ + if (!EditBoxInGlobalFocus()) return [ [ [ NSAttributedString alloc ] initWithString:@"" ] autorelease ]; + + return [ [ [ NSAttributedString alloc ] initWithString:[ NSString stringWithUTF8String:_focused_window->GetFocusedText() ] ] autorelease ]; +} + /** Get the character that is rendered at the given point. */ - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint { @@ -945,6 +993,12 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) return NSMakeRect(origin.x, origin.y, window_rect.size.width, window_rect.size.height); } +/** Get the bounding rect for the given range. */ +- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange +{ + return [ self firstRectForCharacterRange:aRange ]; +} + /** Get all string attributes that we can process for marked text. */ - (NSArray*)validAttributesForMarkedText {