changeset 20245:e33b5bbff76b draft osx

WIP
author Michael Lutz <michi@icosahedron.de>
date Wed, 15 May 2013 22:34:29 +0200 (2013-05-15)
parents d96d97cf4232
children
files src/console_gui.cpp src/landscape.cpp src/misc_gui.cpp src/textbuf.cpp src/textbuf_type.h src/video/win32_v.cpp src/window.cpp src/window_gui.h
diffstat 8 files changed, 226 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/console_gui.cpp
+++ b/src/console_gui.cpp
@@ -216,6 +216,9 @@
 			delta = 0;
 		}
 
+		/* If we have a marked area, draw a background highlight. */
+		if (_iconsole_cmdline.marklength != 0) GfxFillRect(this->line_offset + delta + _iconsole_cmdline.markxoffs, this->height - this->line_height, this->line_offset + delta + _iconsole_cmdline.markxoffs + _iconsole_cmdline.marklength, this->height - 1, PC_DARK_RED);
+
 		DrawString(this->line_offset + delta, right, this->height - this->line_height, _iconsole_cmdline.buf, (TextColour)CC_COMMAND, SA_LEFT | SA_FORCE);
 
 		if (_focused_window == this && _iconsole_cmdline.caret) {
@@ -308,9 +311,9 @@
 		return ES_HANDLED;
 	}
 
-	virtual void InsertTextString(int wid, const char *str)
+	virtual void InsertTextString(int wid, const char *str, bool marked)
 	{
-		if (_iconsole_cmdline.InsertString(str)) {
+		if (_iconsole_cmdline.InsertString(str, marked)) {
 			IConsoleWindow::scroll = 0;
 			IConsoleResetHistoryPos();
 			this->SetDirty();
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -1044,15 +1044,39 @@
 	}
 }
 
+/** Callback to widen a river tile. */
+static bool RiverMakeWider(TileIndex tile, void *data)
+{
+	if (IsValidTile(tile) && !IsWaterTile(tile) && GetTileSlope(tile) == GetTileSlope((TileIndex)data)) {
+		MakeRiver(tile, Random());
+		/* Remove desert directly around the river tile. */
+		CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL);
+	}
+	return false;
+}
+
 /* AyStar callback when an route has been found. */
 static void River_FoundEndNode(AyStar *aystar, OpenListNode *current)
 {
+	/* Count river length. */
+	uint length = 0;
 	for (PathNode *path = &current->path; path != NULL; path = path->parent) {
+		length++;
+	}
+
+	uint cur_pos = 0;
+	for (PathNode *path = &current->path; path != NULL; path = path->parent, cur_pos++) {
 		TileIndex tile = path->node.tile;
 		if (!IsWaterTile(tile)) {
 			MakeRiver(tile, Random());
-			/* Remove desert directly around the river tile. */
-			CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL);
+			/* Widen river depending on how far we are away from the source. */
+			uint radius = min((length - cur_pos) / 15u, 3u);
+			if (radius > 1) {
+				CircularTileSearch(&tile, radius + RandomRange(1), RiverMakeWider, (void *)tile);
+			} else {
+				/* Remove desert directly around the river tile. */
+				CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL);
+			}
 		}
 	}
 }
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -774,7 +774,11 @@
 
 	if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
 
+	/* If we have a marked area, draw a background highlight. */
+	if (tb->marklength != 0) GfxFillRect(delta + tb->markxoffs, 0, delta + tb->markxoffs + tb->marklength - 1, bottom - top, PC_GREY);
+
 	DrawString(delta, tb->pixels, 0, tb->buf, TC_YELLOW);
+
 	bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
 	if (focussed && tb->caret) {
 		int caret_width = GetStringBoundingBox("_").width;
--- a/src/textbuf.cpp
+++ b/src/textbuf.cpp
@@ -148,6 +148,7 @@
 	memset(this->buf, 0, this->max_bytes);
 	this->bytes = this->chars = 1;
 	this->pixels = this->caretpos = this->caretxoffs = 0;
+	this->markpos = this->markend = this->markxoffs = this->marklength = 0;
 }
 
 /**
@@ -182,8 +183,14 @@
  * @param str String to insert.
  * @return True on successful change of Textbuf, or false otherwise.
  */
-bool Textbuf::InsertString(const char *str)
+bool Textbuf::InsertString(const char *str, bool marked)
 {
+	uint16 insertpos   = (marked && this->marklength != 0) ? this->markpos   : this->caretpos;
+	uint16 insertxoffs = (marked && this->marklength != 0) ? this->markxoffs : this->caretxoffs;
+
+	if (marked) this->ClearMarkedText();
+
+	if (str == NULL) return false;
 
 	uint16 pixels = 0, bytes = 0, chars = 0;
 	WChar c;
@@ -203,18 +210,28 @@
 
 	if (bytes == 0) return false;
 
-	memmove(this->buf + this->caretpos + bytes, this->buf + this->caretpos, this->bytes - this->caretpos);
-	memcpy(this->buf + this->caretpos, str, bytes);
+	if (marked) {
+		this->markpos    = insertpos;
+		this->markend    = insertpos + bytes;
+		this->markxoffs  = insertxoffs;
+		this->marklength = pixels;
+	}
+
+	memmove(this->buf + insertpos + bytes, this->buf + insertpos, this->bytes - insertpos);
+	memcpy(this->buf + insertpos, str, bytes);
 	this->pixels += pixels;
-	this->caretxoffs += pixels;
 
 	this->bytes += bytes;
 	this->chars += chars;
-	this->caretpos += bytes;
 	assert(this->bytes <= this->max_bytes);
 	assert(this->chars <= this->max_chars);
 	this->buf[this->bytes - 1] = '\0'; // terminating zero
 
+	if (!marked) {
+		this->caretxoffs += pixels;
+		this->caretpos   += bytes;
+	}
+
 	return true;
 }
 
@@ -230,7 +247,42 @@
 
 	if (!GetClipboardContents(utf8_buf, lengthof(utf8_buf))) return false;
 
-	return this->InsertString(utf8_buf);
+	return this->InsertString(utf8_buf, false);
+}
+
+/**
+ *
+ */
+void Textbuf::ClearMarkedText()
+{
+	if (this->marklength == 0) return;
+
+	/* Count marked characters. */
+	uint c = 0;
+	const char *s = this->buf + this->markpos;
+	while (s < this->buf + this->markend) {
+		Utf8Consume(&s);
+		c++;
+	}
+
+	/* Strip marked characters from buffer. */
+	memmove(this->buf + this->markpos, this->buf + this->markend, this->bytes - this->markend);
+	this->bytes -= this->markend - this->markpos;
+	this->chars -= c;
+
+	/* Fixup caret if needed. */
+	if (this->caretpos > this->markpos) {
+		if (this->caretpos <= this->markend) {
+			this->caretpos   = this->markend;
+			this->caretxoffs = this->markxoffs;
+		} else {
+			this->caretpos   -= this->markend - this->markpos;
+			this->caretxoffs -= this->marklength;
+		}
+	}
+
+	this->markpos = this->markend = 0;
+	this->markxoffs = this->marklength = 0;
 }
 
 /**
--- a/src/textbuf_type.h
+++ b/src/textbuf_type.h
@@ -39,6 +39,10 @@
 	bool caret;               ///< is the caret ("_") visible or not
 	uint16 caretpos;          ///< the current position of the caret in the buffer, in bytes
 	uint16 caretxoffs;        ///< the current position of the caret in pixels
+	uint16 markpos;           ///< the start position of the marked area in the buffer, in bytes
+	uint16 markend;           ///< the end position of the marked area in the buffer, in bytes
+	uint16 markxoffs;         ///< the start position of the marked area in pixels
+	uint16 marklength;        ///< the length of the marked area in pixels
 
 	explicit Textbuf(uint16 max_bytes, uint16 max_chars = UINT16_MAX);
 	~Textbuf();
@@ -51,7 +55,7 @@
 	bool InsertClipboard();
 
 	bool InsertChar(uint32 key);
-	bool InsertString(const char *str);
+	bool InsertString(const char *str, bool marked);
 
 	bool DeleteChar(uint16 keycode);
 	bool MovePos(uint16 keycode);
@@ -61,6 +65,8 @@
 	bool HandleCaret();
 	void UpdateSize();
 
+	void ClearMarkedText();
+
 private:
 	bool CanDelChar(bool backspace);
 	WChar GetNextDelChar(bool backspace);
@@ -69,7 +75,6 @@
 	WChar MoveCaretLeft();
 	bool CanMoveCaretRight();
 	WChar MoveCaretRight();
-
 };
 
 #endif /* TEXTBUF_TYPE_H */
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -23,6 +23,7 @@
 #include "../progress.h"
 #include "../window_gui.h"
 #include "../window_func.h"
+//#include "../querystring_gui.h"
 #include "win32_v.h"
 #include <windows.h>
 
@@ -46,6 +47,9 @@
 uint _display_hz;
 uint _fullscreen_bpp;
 static Dimension _bck_resolution;
+#if !defined(WINCE) || _WIN32_WCE >= 0x400
+DWORD _imm_props;
+#endif
 
 /** Whether the drawing is/may be done in a separate thread. */
 static bool _draw_threaded;
@@ -428,6 +432,94 @@
 	_draw_thread->Exit();
 }
 
+
+static LRESULT CALLBACK HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	switch (msg) {
+		case WM_IME_SETCONTEXT:
+			DEBUG(driver, 0, "WM_IME_SETCONTEXT");
+//			lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+			break;
+
+		case WM_IME_NOTIFY:
+			switch (wParam) {
+				case IMN_CLOSESTATUSWINDOW:    DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_CLOSESTATUSWINDOW"); break;
+				case IMN_OPENSTATUSWINDOW:     DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_OPENSTATUSWINDOW"); break;
+				case IMN_CHANGECANDIDATE:      DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_CHANGECANDIDATE"); break;
+				case IMN_CLOSECANDIDATE:       DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_CLOSECANDIDATE"); break;
+				case IMN_OPENCANDIDATE:        DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_OPENCANDIDATE"); break;
+				case IMN_SETCONVERSIONMODE:    DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETCONVERSIONMODE"); break;
+				case IMN_SETSENTENCEMODE:      DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETSENTENCEMODE"); break;
+				case IMN_SETOPENSTATUS:        DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETOPENSTATUS"); break;
+				case IMN_SETCANDIDATEPOS:      DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETCANDIDATEPOS"); break;
+				case IMN_SETCOMPOSITIONFONT:   DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETCOMPOSITIONFONT"); break;
+				case IMN_SETCOMPOSITIONWINDOW: DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETCOMPOSITIONWINDOW"); break;
+				case IMN_SETSTATUSWINDOWPOS:   DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_SETSTATUSWINDOWPOS"); break;
+				case IMN_GUIDELINE:            DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_GUIDELINE"); break;
+				case IMN_PRIVATE:              DEBUG(driver, 0, "WM_IME_NOTIFY: IMN_PRIVATE"); break;
+			}
+			break;
+
+#if 0
+		case WM_IME_REQUEST:
+			switch (wParam) {
+				case IMR_COMPOSITIONWINDOW:      DEBUG(driver, 0, "WM_IME_REQUEST: IMR_COMPOSITIONWINDOW"); break;
+				case IMR_CANDIDATEWINDOW:        DEBUG(driver, 0, "WM_IME_REQUEST: IMR_CANDIDATEWINDOW"); break;
+				case IMR_COMPOSITIONFONT:        DEBUG(driver, 0, "WM_IME_REQUEST: IMR_COMPOSITIONFONT"); break;
+				case IMR_RECONVERTSTRING:        DEBUG(driver, 0, "WM_IME_REQUEST: IMR_RECONVERTSTRING"); break;
+				case IMR_CONFIRMRECONVERTSTRING: DEBUG(driver, 0, "WM_IME_REQUEST: IMR_CONFIRMRECONVERTSTRING"); break;
+				case IMR_QUERYCHARPOSITION:
+					DEBUG(driver, 0, "WM_IME_REQUEST: IMR_QUERYCHARPOSITION %u", ((IMECHARPOSITION *)lParam)->dwCharPos);
+/*					if (DrawIMECompositionString() && EditBoxInGlobalFocus() && _focused_window->window_class != WC_CONSOLE) {
+						IMECHARPOSITION *cpos = (IMECHARPOSITION *)lParam;
+
+						int x = _focused_window->nested_focus->pos_x + _focused_window->left;
+						int y = _focused_window->nested_focus->pos_y + _focused_window->top;
+
+						cpos->cLineHeight = FONT_HEIGHT_NORMAL;
+						cpos->pt.x = x + _focused_window->GetQueryString(_focused_window->nested_focus->index)->text.caretxoffs;
+						cpos->pt.y = y + FONT_HEIGHT_NORMAL;
+						SetRect(&cpos->rcDocument, x, y, x + _focused_window->nested_focus->current_x, y + _focused_window->nested_focus->current_y);
+
+						ClientToScreen(hwnd, &cpos->pt);
+						MapWindowPoints(hwnd, NULL, (LPPOINT)&cpos->rcDocument, 2);
+
+						return 1;
+					}*/
+					break;
+				case IMR_DOCUMENTFEED:           DEBUG(driver, 0, "WM_IME_REQUEST: IMR_DOCUMENTFEED"); break;
+			}
+			break;
+#endif
+
+		case WM_IME_CONTROL:
+			DEBUG(driver, 0, "WM_IME_CONTROL");
+			break;
+
+		case WM_IME_COMPOSITIONFULL:
+			DEBUG(driver, 0, "WM_IME_COMPOSITIONFULL");
+			break;
+
+		case WM_IME_SELECT:
+			DEBUG(driver, 0, "WM_IME_SELECT");
+			break;
+
+		case WM_IME_KEYDOWN:
+			DEBUG(driver, 0, "WM_IME_KEYDOWN");
+			break;
+
+		case WM_IME_KEYUP:
+			DEBUG(driver, 0, "WM_IME_KEYUP");
+			break;
+
+		case WM_IME_ENDCOMPOSITION:
+			DEBUG(driver, 0, "WM_IME_ENDCOMPOSITION");
+			break;
+	}
+
+	return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
 /** Forward key presses to the window system. */
 static LRESULT HandleCharMsg(uint keycode, WChar charcode)
 {
@@ -492,6 +584,12 @@
 }
 
 #if !defined(WINCE) || _WIN32_WCE >= 0x400
+/** Should we draw the composition string ourself, i.e is this a normal IME? */
+static bool DrawIMECompositionString()
+{
+	return (_imm_props & IME_PROP_AT_CARET) && !(_imm_props & IME_PROP_SPECIAL_UI);
+}
+
 /** Set position of the composition window to the caret position. */
 static void SetCompositionPos(HWND hwnd)
 {
@@ -585,6 +683,7 @@
 
 #else
 
+static bool DrawIMECompositionString() { return false; }
 static void SetCompositionPos(HWND hwnd) {}
 static void SetCandidatePos(HWND hwnd) {}
 static void CancelIMEComposition(HWND hwnd) {}
@@ -601,6 +700,9 @@
 		case WM_CREATE:
 			SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
 			SetCompositionPos(hwnd);
+#if !defined(WINCE) || _WIN32_WCE >= 0x400
+			_imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
+#endif
 			break;
 
 		case WM_ENTERSIZEMOVE:
@@ -727,8 +829,18 @@
 		}
 
 #if !defined(WINCE) || _WIN32_WCE >= 0x400
+		case WM_INPUTLANGCHANGE:
+			_imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
+			break;
+
+		case WM_IME_SETCONTEXT:
+			/* Don't show the composition window if we draw the string ourself. */
+			if (DrawIMECompositionString()) lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+			break;
+
 		case WM_IME_STARTCOMPOSITION:
 			SetCompositionPos(hwnd);
+			if (DrawIMECompositionString()) return 0;
 			break;
 
 		case WM_IME_COMPOSITION:
@@ -754,6 +866,7 @@
 			return 0;
 
 		case WM_CHAR: {
+			DEBUG(driver, 0, "WM_CHAR: %x", wParam);
 			uint scancode = GB(lParam, 16, 8);
 			uint charcode = wParam;
 
@@ -952,6 +1065,15 @@
 			break;
 		}
 #endif
+
+		case WM_IME_CONTROL:
+		case WM_IME_COMPOSITIONFULL:
+		case WM_IME_SELECT:
+//		case WM_IME_REQUEST:
+		case WM_IME_KEYDOWN:
+		case WM_IME_KEYUP:
+		case WM_IME_ENDCOMPOSITION:
+			return HandleIMEMessage(hwnd, msg, wParam, lParam);
 	}
 
 	return DefWindowProc(hwnd, msg, wParam, lParam);
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -2406,12 +2406,12 @@
  * @param wid Edit box widget.
  * @param str Text string to insert.
  */
-/* virtual */ void Window::InsertTextString(int wid, const char *str)
+/* virtual */ void Window::InsertTextString(int wid, const char *str, bool marked)
 {
 	QueryString *query = this->GetQueryString(wid);
 	if (query == NULL) return;
 
-	if (query->text.InsertString(str)) {
+	if (query->text.InsertString(str, marked) || marked) {
 		this->SetWidgetDirty(wid);
 		this->OnEditboxChanged(wid);
 	}
@@ -2425,7 +2425,7 @@
 {
 	if (!EditBoxInGlobalFocus()) return;
 
-	_focused_window->InsertTextString(_focused_window->window_class == WC_CONSOLE ? 0 : _focused_window->nested_focus->index, str);
+	_focused_window->InsertTextString(_focused_window->window_class == WC_CONSOLE ? 0 : _focused_window->nested_focus->index, str, false);
 }
 
 /**
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -469,7 +469,7 @@
 	bool SetFocusedWidget(int widget_index);
 
 	EventState HandleEditBoxKey(int wid, WChar key, uint16 keycode);
-	virtual void InsertTextString(int wid, const char *str);
+	virtual void InsertTextString(int wid, const char *str, bool marked);
 
 	void HandleButtonClick(byte widget);
 	int GetRowFromWidget(int clickpos, int widget, int padding, int line_height = -1) const;