changeset 20714:fdf6e212a787 draft

-Add: [OSX] Display the IME composition string ourself.
author Michael Lutz <michi@icosahedron.de>
date Fri, 26 Jul 2013 01:41:39 +0200
parents 6baaec6722b9
children db681959a377
files src/console_gui.cpp src/querystring_gui.h src/video/cocoa/cocoa_v.mm src/window.cpp src/window_gui.h
diffstat 5 files changed, 159 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/console_gui.cpp
+++ b/src/console_gui.cpp
@@ -320,6 +320,24 @@
 		}
 	}
 
+	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);
--- a/src/querystring_gui.h
+++ b/src/querystring_gui.h
@@ -55,6 +55,37 @@
 	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);
--- 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 @@
 
 
 
+/**
+ * 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 @@
 /** 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 @@
 /** 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. */
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -324,6 +324,46 @@
 }
 
 /**
+ * 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.
  */
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -345,6 +345,9 @@
 	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);