From 1fde16fb2dd10e363a7ab70c6c33cbee2ad1ad43 Mon Sep 17 00:00:00 2001
From: Adam Wardynski <award@.(win7-laptop)>
Date: Thu, 16 Dec 2010 20:59:32 +0100
Subject: [PATCH] Unicode support reading from Win Console in wcclparser tool.

---
 wcclparser/main.cpp | 106 ++++++++++++++++++++++++++++++++------------
 1 file changed, 78 insertions(+), 28 deletions(-)

diff --git a/wcclparser/main.cpp b/wcclparser/main.cpp
index cd00f57..6eea080 100644
--- a/wcclparser/main.cpp
+++ b/wcclparser/main.cpp
@@ -19,42 +19,26 @@
 #include <histedit.h>
 #endif
 
+#ifdef _WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
 /**
  * @desc A simple command line tester for testing operators
  */
 
-
 namespace {
 	const char* _prompt = "Enter any operator expression: ";
 }
 
-void std_read_loop(boost::function<bool (const std::string&)>& line_cb)
-{
-	while (std::cin.good()) {
-		std::cout << _prompt << std::flush;
-		std::string s;
-		getline(std::cin, s);
-		if (line_cb(s)) {
-			return;
-		}
-	}
-}
+#if defined(HAVE_LIBEDIT) && !defined(_WINDOWS) //non-Windows libedit read loop
 
-int clear_screen()
-{
-#ifdef _WINDOWS
-	return std::system("cls");
-#else
-	return std::system("clear");
-#endif
-}
-
-#ifdef HAVE_LIBEDIT
 const char* query_prompt(EditLine*) {
 	return _prompt;
 }
 
-void libedit_read_loop(boost::function<bool (const std::string&)>& line_cb)
+void read_loop(boost::function<bool (const std::string&)>& line_cb)
 {
 	EditLine *el = el_init("wccl-parser", stdin, stdout, stderr);
 	el_set(el, EL_PROMPT, &query_prompt);
@@ -89,7 +73,77 @@ void libedit_read_loop(boost::function<bool (const std::string&)>& line_cb)
 	history_end(myhistory);
 	el_end(el);
 }
+
+#elif defined(_WINDOWS) // windows console read loop, doing UNICODE
+
+struct ConsoleCPSetter
+{
+	UINT original_CP;
+	ConsoleCPSetter(UINT cp) {
+		original_CP = GetConsoleCP();
+		SetConsoleCP(cp);
+	}
+	~ConsoleCPSetter() {
+		SetConsoleCP(original_CP);
+	}
+};
+
+void read_loop(boost::function<bool (const std::string&)>& line_cb)
+{
+	HANDLE stdinhandle = GetStdHandle(STD_INPUT_HANDLE);
+	WCHAR buffer[1024];
+	const int max = sizeof(buffer)/sizeof(WCHAR) - 1;
+	ConsoleCPSetter cp(CP_UTF8);
+	bool more = true;
+	while(more) {
+		std::cout << _prompt << std::flush;
+		std::wstring s;
+		while(more) {
+			DWORD read;
+			if (ReadConsoleW(stdinhandle, buffer, max, &read, NULL)) { 
+				buffer[read] = NULL;
+				while(buffer[read - 1] == L'\n' || buffer[read - 1] == L'\r') {
+					buffer[--read] = 0;
+				}
+				more = (read == max);
+				s += buffer;
+			} else {
+				if (GetLastError() == ERROR_INVALID_HANDLE) {
+					// assume stdin redirect, fallback to standard getline
+					getline(std::wcin, s);
+				}
+				more = false;
+			}
+		}
+		UnicodeString us(s.c_str());
+		more = !line_cb(PwrNlp::to_utf8(us));
+	}
+}
+
+#else // standard io read loop
+
+void read_loop(boost::function<bool (const std::string&)>& line_cb)
+{
+	while (std::cin.good()) {
+		std::cout << _prompt << std::flush;
+		std::string s;
+		getline(std::cin, s);
+		if (line_cb(s)) {
+			return;
+		}
+	}
+}
+
+#endif
+
+int clear_screen()
+{
+#ifdef _WINDOWS
+	return std::system("cls");
+#else
+	return std::system("clear");
 #endif
+}
 
 bool process_line(const std::string& line, Wccl::Parser& parser,
 	Wccl::SentenceContext& sc, bool all_positions, bool dump_variables)
@@ -247,11 +301,7 @@ int main(int argc, char** argv)
 		boost::function<bool (const std::string&)> f;
 		f = boost::bind(&process_line, _1, boost::ref(parser), boost::ref(sc),
 			position == "all", dump_variables);
-#ifdef HAVE_LIBEDIT
-		libedit_read_loop(f);
-#else
-		std_read_loop(f);
-#endif
+		read_loop(f);
 	} catch (PwrNlp::PwrNlpError& e) {
 		std::cerr << e.info() << std::endl;
 		return 2;
-- 
GitLab