diff options
-rw-r--r-- | src/console_gui.cpp | 18 | ||||
-rw-r--r-- | src/querystring_gui.h | 31 | ||||
-rw-r--r-- | src/video/cocoa/cocoa_v.mm | 69 | ||||
-rw-r--r-- | src/window.cpp | 40 | ||||
-rw-r--r-- | src/window_gui.h | 3 |
5 files changed, 159 insertions, 2 deletions
diff --git a/src/console_gui.cpp b/src/console_gui.cpp index 69cf7a4d7..d7ef57a44 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -320,6 +320,24 @@ struct IConsoleWindow : Window } } + virtual const char *GetFocusedText() const + { + return _iconsole_cmdline.buf; + } + + virtual const char *GetCaret() const + { + return _iconsole_cmdline.buf + _iconsole_cmdline.caretpos; + } + + virtual const char *GetMarkedText(size_t *length) const + { + if (_iconsole_cmdline.markend == 0) return NULL; + + *length = _iconsole_cmdline.markend - _iconsole_cmdline.markpos; + return _iconsole_cmdline.buf + _iconsole_cmdline.markpos; + } + virtual Point GetCaretPosition() const { int delta = min(this->width - this->line_offset - _iconsole_cmdline.pixels - ICON_RIGHT_BORDERWIDTH, 0); diff --git a/src/querystring_gui.h b/src/querystring_gui.h index a652b382d..db6e33076 100644 --- a/src/querystring_gui.h +++ b/src/querystring_gui.h @@ -55,6 +55,37 @@ public: void HandleEditBox(Window *w, int wid); Point GetCaretPosition(const Window *w, int wid) const; + + /** + * Get the current text. + * @return Current text. + */ + const char *GetText() const + { + return this->text.buf; + } + + /** + * Get the position of the caret in the text buffer. + * @return Pointer to the caret in the text buffer. + */ + const char *GetCaret() const + { + return this->text.buf + this->text.caretpos; + } + + /** + * Get the currently marked text. + * @param[out] length Length of the marked text. + * @return Begining of the marked area or NULL if no text is marked. + */ + const char *GetMarkedText(size_t *length) const + { + if (this->text.markend == 0) return NULL; + + *length = this->text.markend - this->text.markpos; + return this->text.buf + this->text.markpos; + } }; void ShowOnScreenKeyboard(Window *parent, int button); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 1a0ea1a60..16069bb24 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -33,6 +33,8 @@ #include "../../blitter/factory.hpp" #include "../../fileio_func.h" #include "../../gfx_func.h" +#include "../../window_func.h" +#include "../../window_gui.h" #import <sys/param.h> /* for MAXPATHLEN */ @@ -693,6 +695,43 @@ void cocoaReleaseAutoreleasePool() +/** + * Count the number of UTF-16 code points in a range of an UTF-8 string. + * @param from Start of the range. + * @param to End of the range. + * @return Number of UTF-16 code points in the range. + */ +static NSUInteger CountUtf16Units(const char *from, const char *to) +{ + NSUInteger i = 0; + + while (from < to) { + WChar c; + size_t len = Utf8Decode(&c, from); + i += len < 4 ? 1 : 2; // Watch for surrogate pairs. + from += len; + } + + return i; +} + +/** + * Advance an UTF-8 string by a number of equivalent UTF-16 code points. + * @param str UTF-8 string. + * @param count Number of UTF-16 code points to advance the string by. + * @return Advanced string pointer. + */ +static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) +{ + for (NSUInteger i = 0; i < count && *str != '\0'; ) { + WChar c; + size_t len = Utf8Decode(&c, str); + i += len < 4 ? 1 : 2; // Watch for surrogates. + str += len; + } + + return str; +} @implementation OTTD_CocoaView /** @@ -802,6 +841,15 @@ void cocoaReleaseAutoreleasePool() /** Set a new marked text and reposition the caret. */ - (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange { + NSString *s = [ aString isKindOfClass:[ NSAttributedString class ] ] ? [ aString string ] : (NSString *)aString; + + const char *utf8 = [ s UTF8String ]; + if (utf8 != NULL) { + /* Convert caret index into a pointer in the UTF-8 string. */ + const char *selection = Utf8AdvanceByUtf16Units(utf8, selRange.location); + + HandleTextInput(utf8, true, selection); + } } /** Unmark the current marked text. */ @@ -813,19 +861,36 @@ void cocoaReleaseAutoreleasePool() /** Get the caret position. */ - (NSRange)selectedRange { - return NSMakeRange(NSNotFound, 0); + if (!EditBoxInGlobalFocus()) return NSMakeRange(NSNotFound, 0); + + NSUInteger start = CountUtf16Units(_focused_window->GetFocusedText(), _focused_window->GetCaret()); + return NSMakeRange(start, 0); } /** Get the currently marked range. */ - (NSRange)markedRange { + if (!EditBoxInGlobalFocus()) return NSMakeRange(NSNotFound, 0); + + size_t mark_len; + const char *mark = _focused_window->GetMarkedText(&mark_len); + if (mark != NULL) { + NSUInteger start = CountUtf16Units(_focused_window->GetFocusedText(), mark); + NSUInteger len = CountUtf16Units(mark, mark + mark_len); + + return NSMakeRange(start, len); + } + return NSMakeRange(NSNotFound, 0); } /** Is any text marked? */ - (BOOL)hasMarkedText { - return NO; + if (!EditBoxInGlobalFocus()) return NO; + + size_t len; + return _focused_window->GetMarkedText(&len) != NULL; } /** Get a string corresponding to the given range. */ diff --git a/src/window.cpp b/src/window.cpp index 1197b0c6e..907f575c6 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -324,6 +324,46 @@ QueryString *Window::GetQueryString(uint widnum) } /** + * Get the current input text if an edit box has the focus. + * @return The currently focused input text or NULL if no input focused. + */ +/* virtual */ const char *Window::GetFocusedText() const +{ + if (this->nested_focus != NULL && this->nested_focus->type == WWT_EDITBOX) { + return this->GetQueryString(this->nested_focus->index)->GetText(); + } + + return NULL; +} + +/** + * Get the string at the caret if an edit box has the focus. + * @return The text at the caret or NULL if no edit box is focused. + */ +/* virtual */ const char *Window::GetCaret() const +{ + if (this->nested_focus != NULL && this->nested_focus->type == WWT_EDITBOX) { + return this->GetQueryString(this->nested_focus->index)->GetCaret(); + } + + return NULL; +} + +/** + * Get the range of the currently marked input text. + * @param[out] length Length of the marked text. + * @return Pointer to the start of the marked text or NULL if no text is marked. + */ +/* virtual */ const char *Window::GetMarkedText(size_t *length) const +{ + if (this->nested_focus != NULL && this->nested_focus->type == WWT_EDITBOX) { + return this->GetQueryString(this->nested_focus->index)->GetMarkedText(length); + } + + return NULL; +} + +/** * Get the current caret position if an edit box has the focus. * @return Top-left location of the caret, relative to the window. */ diff --git a/src/window_gui.h b/src/window_gui.h index 0fd76cfcc..494e5bfcb 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -345,6 +345,9 @@ public: const QueryString *GetQueryString(uint widnum) const; QueryString *GetQueryString(uint widnum); + virtual const char *GetFocusedText() const; + virtual const char *GetCaret() const; + virtual const char *GetMarkedText(size_t *length) const; virtual Point GetCaretPosition() const; void InitNested(WindowNumber number = 0); |