From 73fe94df329b2f217304612b31a6a21a1c6c440d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jon=C3=A1s=20Perusqu=C3=ADa=20Morales?=
 <jonaspm_99@outlook.com>
Date: Thu, 5 Nov 2015 22:43:42 -0700
Subject: [PATCH 1/9] Create es.ini

Made Spanish Translation for DlangIDE
---
 views/res/i18n/es.ini | 77 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 views/res/i18n/es.ini

diff --git a/views/res/i18n/es.ini b/views/res/i18n/es.ini
new file mode 100644
index 0000000..36024f7
--- /dev/null
+++ b/views/res/i18n/es.ini
@@ -0,0 +1,77 @@
+EXIT=Salir
+MENU_FILE=&ARCHIVO
+MENU_FILE_NEW=&Nuevo
+MENU_FILE_NEW_SOURCE_FILE=Nuevo Archivo Fuente
+MENU_FILE_NEW_PROJECT=Nuevo Proyecto
+MENU_FILE_NEW_WORKSPACE=Nuevo Espacio de Trabajo
+MENU_FILE_OPEN=&Abrir archivo...
+MENU_FILE_OPEN_WORKSPACE=Abrir Proyecto o Espacio de Trabajo...
+MENU_FILE_OPEN_RECENT=Abrir reciente
+MENU_FILE_SAVE=&Guardar archivo
+MENU_FILE_SAVE_AS=&Guardar archivo como...
+MENU_FILE_SAVE_ALL=&Guardar todo
+MENU_FILE_EXIT=S&alir
+MENU_EDIT=&EDITAR
+MENU_EDIT_COPY=&Copiar
+MENU_EDIT_PASTE=&Pegar
+MENU_EDIT_CUT=Corta&r
+MENU_EDIT_UNDO=&Deshacer
+MENU_EDIT_REDO=&Rehacer
+MENU_EDIT_INDENT=Sangrar bloque
+MENU_EDIT_UNINDENT=De-sangrar bloque
+MENU_EDIT_TOGGLE_LINE_COMMENT=Alternar comentario de línea
+MENU_EDIT_TOGGLE_BLOCK_COMMENT=Alternar comentario de bloque
+MENU_EDIT_ADVANCED=Avanzado...
+MENU_EDIT_PREFERENCES=&Preferencias
+MENU_BUILD_CONFIGURATIONS=Configuraciones de construcción
+MENU_BUILD=&Contruir
+MENU_BUILD_WORKSPACE_BUILD=Construir espacio de trabajo
+MENU_BUILD_WORKSPACE_REBUILD=Reconstruir espacio de trabajo
+MENU_BUILD_WORKSPACE_CLEAN=Limpiar espacio de trabajo
+MENU_BUILD_PROJECT_BUILD=Construir Proyecto
+MENU_BUILD_PROJECT_REBUILD=Reconstruir Proyecto
+MENU_BUILD_PROJECT_CLEAN=Limpiar Proyecto
+MENU_PROJECT=&PROYECTO
+MENU_PROJECT_CONFIGURATIONS=Configuraciones de Proyecto
+MENU_PROJECT_SET_AS_STARTUP=Establecer como Proyecto de Inicio
+MENU_PROJECT_SETTINGS=Ajustes de Proyecto
+MENU_PROJECT_REFRESH=Refrescar elementos del espacio de trabajo
+MENU_PROJECT_UPDATE_DEPENDENCIES=Actualizar Dependencias
+MENU_DEBUG=&DEPURAR
+MENU_DEBUG_START_DEBUGGING=Iniciar Depuración
+MENU_DEBUG_START_NO_DEBUGGING=Iniciar sin Depuración
+MENU_DEBUG_CONTINUE=Continuar Depurando
+MENU_DEBUG_STOP=Detener
+MENU_DEBUG_PAUSE=Pausar
+MENU_VIEW=&VISTA
+MENU_VIEW_LANGUAGE=Lenguaje de &Interfaz
+MENU_VIEW_LANGUAGE_ES=Spanish
+MENU_VIEW_LANGUAGE_EN=English
+MENU_VIEW_LANGUAGE_RU=Русский
+MENU_VIEW_THEME=&Tema
+MENU_VIEW_THEME_DEFAULT=&Por Defecto
+MENU_VIEW_THEME_CUSTOM1=&Personalizado 1
+MENU_WINDOW=&VENTANA
+MENU_WINDOW_PREFERENCES=&Preferencias
+MENU_WINDOW_CLOSE_ALL_DOCUMENTS=Cerrar todos los Documentos
+MENU_HELP=&AYUDA
+MENU_HELP_VIEW_HELP=&Ver ayuda
+MENU_HELP_ABOUT=&Acerca de
+MENU_NAVIGATE=Navegar
+
+GO_TO_DEFINITION=Ir a Definición
+SHOW_COMPLETIONS=Obtener Autocompletados
+FIND_TEXT=Encontrar texto
+
+
+TAB_LONG_LIST=Larga lista
+TAB_BUTTONS=Botones
+TAB_ANIMATION=Animación
+TAB_TABLE_LAYOUT=Diseño de tabla
+TAB_EDITORS=Editores
+
+
+MENU_PROJECT_FOLDER_ADD_ITEM=Añadir...
+MENU_PROJECT_FOLDER_OPEN_ITEM=Abrir
+MENU_PROJECT_FOLDER_REMOVE_ITEM=Remover
+MENU_PROJECT_FOLDER_RENAME_ITEM=Renombrar...

From 87f12a94358436ecb14597687e25c95b6fcab030 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Mon, 16 Nov 2015 08:48:41 +0300
Subject: [PATCH 2/9] add Spanish translation

---
 src/dlangide/ui/settings.d | 7 +++++--
 views/resources.list       | 1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/dlangide/ui/settings.d b/src/dlangide/ui/settings.d
index 61da088..ef7e733 100644
--- a/src/dlangide/ui/settings.d
+++ b/src/dlangide/ui/settings.d
@@ -8,7 +8,7 @@ import dlangui.dialogs.settingsdialog;
 
 
 const AVAILABLE_THEMES = ["ide_theme_default", "ide_theme_dark"];
-const AVAILABLE_LANGUAGES = ["en", "ru"];
+const AVAILABLE_LANGUAGES = ["en", "ru", "es"];
 
 class IDESettings : SettingsFile {
 
@@ -146,7 +146,10 @@ SettingsPage createSettingsPages() {
     ui.addStringComboBox("interface/theme", UIString("Theme"d), [
             StringListValue("ide_theme_default", "Default"d), 
             StringListValue("ide_theme_dark", "Dark"d)]);
-    ui.addStringComboBox("interface/language", UIString("Language"d), [StringListValue("en", "English"d), StringListValue("ru", "Russian"d)]);
+	ui.addStringComboBox("interface/language", UIString("Language"d), [
+			StringListValue("en", "English"d), 
+			StringListValue("ru", "Russian"d), 
+			StringListValue("es", "Spanish"d)]);
     ui.addIntComboBox("interface/hintingMode", UIString("Font hinting mode"d), [StringListValue(0, "Normal"d), StringListValue(1, "Force Auto Hint"d), 
                 StringListValue(2, "Disabled"d), StringListValue(3, "Light"d)]);
     ui.addIntComboBox("interface/minAntialiasedFontSize", UIString("Minimum font size for antialiasing"d), 
diff --git a/views/resources.list b/views/resources.list
index a7f97d0..50de379 100644
--- a/views/resources.list
+++ b/views/resources.list
@@ -2,6 +2,7 @@ res/ide_theme_default.xml
 res/ide_theme_dark.xml
 res/i18n/en.ini
 res/i18n/ru.ini
+res/i18n/es.ini
 res/hdpi/hdpi_configure.png
 res/hdpi/hdpi_debug-run.png
 res/hdpi/hdpi_document-close.png

From 46256ca65068dd5a61564c9ebe8c28b859fde916 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Mon, 16 Nov 2015 09:31:15 +0300
Subject: [PATCH 3/9] blocking queue

---
 src/ddebug/common/queue.d | 82 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/src/ddebug/common/queue.d b/src/ddebug/common/queue.d
index bac99ec..1a5ebf0 100644
--- a/src/ddebug/common/queue.d
+++ b/src/ddebug/common/queue.d
@@ -7,20 +7,102 @@ class BlockingQueue(T) {
 
 	private Mutex _mutex;
 	private Condition _condition;
+	private T[] _buffer;
+	private int _readPos;
+	private int _writePos;
 
 	this() {
 		_mutex = new Mutex();
 		_condition = new Condition(_mutex);
+		_readPos = 0;
+		_writePos = 0;
+	}
+
+	void close() {
+		if (_condition) {
+			destroy(_condition);
+			_condition = null;
+		}
+		if (_mutex) {
+			destroy(_mutex);
+			_mutex = null;
+		}
 	}
 
 	~this() {
 		// TODO: destroy mutex?
+		close();
+	}
+
+	private void move() {
+		if (_readPos > 1024 && _readPos > _buffer.length * 3 / 4) {
+			// move buffer data
+			for (int i = 0; _readPos + i < _writePos; i++)
+				_buffer[i] = _buffer[_readPos + i];
+			_writePos -= _readPos;
+			_readPos = 0;
+		}
+	}
+
+	private void append(ref T item) {
+		if (_writePos >= _buffer.length) {
+			move();
+			_buffer.length = _buffer.length == 0 ? 64 : _buffer.length * 2;
+		}
+		_buffer[_writePos++] = item;
 	}
 
 	void put(T item) {
+		synchronized(_mutex) {
+			append(item);
+			_condition.notifyAll();
+		}
 	}
 
+	void put(T[] items) {
+		synchronized(_mutex) {
+			foreach(ref item; items) {
+				append(item);
+			}
+			append(item);
+			_condition.notifyAll();
+		}
+	}
+	
 	bool get(ref T value, int timeoutMillis) {
+		synchronized(_mutex) {
+			if (_readPos < _writePos) {
+				value = _buffer[_readPos++];
+				return true;
+			}
+			if (timeoutMillis <= 0)
+				_condition.wait(); // no timeout
+			else if (!_condition.wait(dur!msecs(timeoutMillis)))
+				return false; // timeout
+			if (_readPos < _writePos) {
+				value = _buffer[_readPos++];
+				return true;
+			}
+		}
+		return false;
+	}
+
+	bool getAll(ref T[] values, int timeoutMillis) {
+		synchronized(_mutex) {
+			values.length = 0;
+			while (_readPos < _writePos)
+				values ~= _buffer[_readPos++];
+			if (values.length > 0)
+				return true;
+			if (timeoutMillis <= 0)
+				_condition.wait(); // no timeout
+			else if (!_condition.wait(dur!msecs(timeoutMillis)))
+				return false; // timeout
+			while (_readPos < _writePos)
+				values ~= _buffer[_readPos++];
+			if (values.length > 0)
+				return true;
+		}
 		return false;
 	}
 }

From 0ebd6c239434e8c7f32f415952be3e4ef567fd6c Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Mon, 16 Nov 2015 10:27:14 +0300
Subject: [PATCH 4/9] blocking queue

---
 src/ddebug/common/queue.d | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/src/ddebug/common/queue.d b/src/ddebug/common/queue.d
index 1a5ebf0..2e2a643 100644
--- a/src/ddebug/common/queue.d
+++ b/src/ddebug/common/queue.d
@@ -10,6 +10,7 @@ class BlockingQueue(T) {
 	private T[] _buffer;
 	private int _readPos;
 	private int _writePos;
+	private shared bool _closed;
 
 	this() {
 		_mutex = new Mutex();
@@ -19,6 +20,15 @@ class BlockingQueue(T) {
 	}
 
 	void close() {
+		if (_mutex && !_closed) {
+			synchronized(_mutex) {
+				_closed = true;
+				if (_condition !is null)
+					_condition.notifyAll();
+			}
+		} else {
+			_closed = true;
+		}
 		if (_condition) {
 			destroy(_condition);
 			_condition = null;
@@ -53,14 +63,22 @@ class BlockingQueue(T) {
 	}
 
 	void put(T item) {
+		if (_closed)
+			return;
 		synchronized(_mutex) {
+			if (_closed)
+				return;
 			append(item);
 			_condition.notifyAll();
 		}
 	}
 
 	void put(T[] items) {
+		if (_closed)
+			return;
 		synchronized(_mutex) {
+			if (_closed)
+				return;
 			foreach(ref item; items) {
 				append(item);
 			}
@@ -70,7 +88,11 @@ class BlockingQueue(T) {
 	}
 	
 	bool get(ref T value, int timeoutMillis) {
+		if (_closed)
+			return false;
 		synchronized(_mutex) {
+			if (_closed)
+				return false;
 			if (_readPos < _writePos) {
 				value = _buffer[_readPos++];
 				return true;
@@ -88,7 +110,11 @@ class BlockingQueue(T) {
 	}
 
 	bool getAll(ref T[] values, int timeoutMillis) {
+		if (_closed)
+			return false;
 		synchronized(_mutex) {
+			if (_closed)
+				return false;
 			values.length = 0;
 			while (_readPos < _writePos)
 				values ~= _buffer[_readPos++];

From be7717e1086acc819c79b7c8ea8b1075cbe76e42 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Mon, 16 Nov 2015 16:34:07 +0300
Subject: [PATCH 5/9] GDB support, continue

---
 dlangide-monod-linux.dproj    |  5 ++
 src/ddebug/common/debugger.d  | 86 ++++++++++++++++++++++++++++++--
 src/ddebug/common/queue.d     |  5 +-
 src/ddebug/gdb/gdbinterface.d | 94 +++++++++++++++++++++++++++++++++++
 src/dlangide.d                | 41 ++++++++++++++-
 5 files changed, 223 insertions(+), 8 deletions(-)
 create mode 100644 src/ddebug/gdb/gdbinterface.d

diff --git a/dlangide-monod-linux.dproj b/dlangide-monod-linux.dproj
index 23a6d04..66e9e98 100644
--- a/dlangide-monod-linux.dproj
+++ b/dlangide-monod-linux.dproj
@@ -33,6 +33,7 @@
         <String>USE_OPENGL</String>
         <String>USE_SDL</String>
         <String>USE_FREETYPE</String>
+        <String>USE_GDB_DEBUG</String>
         <String>EmbedStandardResources</String>
       </VersionIds>
     </VersionIds>
@@ -192,5 +193,9 @@
     <Compile Include="src\dlangide\workspace\workspace.d" />
     <Compile Include="src\ddebug\common\debugger.d" />
     <Compile Include="src\ddebug\common\queue.d" />
+    <Compile Include="src\ddebug\gdb\gdbinterface.d" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="src\ddebug\gdb\" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/ddebug/common/debugger.d b/src/ddebug/common/debugger.d
index 9c99a16..3176917 100644
--- a/src/ddebug/common/debugger.d
+++ b/src/ddebug/common/debugger.d
@@ -2,26 +2,106 @@ module ddebug.common.debugger;
 
 import core.thread;
 import dlangui.core.logger;
+import ddebug.common.queue;
+
+enum ResponseCode : int {
+	/// Operation finished successfully
+	Ok = 0,
+
+	// more success codes here
+
+	/// General purpose failure code
+	Fail = 1000,
+	/// method is not implemented
+	NotImplemented,
+	/// error running debugger
+	CannotRunDebugger,
+
+	// more error codes here
+}
+
+alias Runnable = void delegate();
+alias DebuggerResponse = void delegate(ResponseCode code, string msg);
 
 interface Debugger {
 	/// start debugging
-	void startDebugging(string executable, string[] args, string workingDir);
+	void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response);
 }
 
-interface DebuggerCallback {
+
+
+/// proxy for debugger interface implementing async calls
+class DebuggerProxy : Debugger {
+	private DebuggerBase _debugger;
+	private void delegate(Runnable runnable) _callbackDelegate;
+
+	this(DebuggerBase debugger, void delegate(Runnable runnable) callbackDelegate) {
+		_debugger = debugger;
+		_callbackDelegate = callbackDelegate;
+	}
+
+	void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response) {
+		_debugger.postRequest(delegate() {
+				_debugger.startDebugging(debuggerExecutable, executable, args, workingDir,
+					delegate(ResponseCode code, string msg) {
+						_callbackDelegate( delegate() { response(code, msg); } );
+					}
+				);
+		});
+	}
+
 }
 
-class DebuggerBase : Thread {
+class DebuggerBase : Thread, Debugger {
 	private bool _stopRequested;
 	private bool _finished;
+	protected string _debuggerExecutable;
+	protected BlockingQueue!Runnable _queue;
+
+	void postRequest(Runnable request) {
+		_queue.put(request);
+	}
 
 	this() {
 		super(&run);
+		_queue = new BlockingQueue!Runnable();
 	}
 
+	~this() {
+		stop();
+		destroy(_queue);
+		_queue = null;
+	}
+
+	void stop() {
+		Log.i("Debugger.stop()");
+		_stopRequested = true;
+		_queue.close();
+	}
+
+	protected void onDebuggerThreadStarted() {
+	}
+
+	protected void onDebuggerThreadFinished() {
+	}
+	
+	/// thread func: execute all tasks from queue
 	private void run() {
+		onDebuggerThreadStarted();
 		Log.i("Debugger thread started");
+		while (!_stopRequested) {
+			Runnable task;
+			if (_queue.get(task, 0)) {
+				task();
+			}
+		}
 		Log.i("Debugger thread finished");
 		_finished = true;
+		onDebuggerThreadFinished();
 	}
+
+	void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response) {
+		response(ResponseCode.NotImplemented, "Not Implemented");
+	}
+
 }
diff --git a/src/ddebug/common/queue.d b/src/ddebug/common/queue.d
index 2e2a643..d4669b9 100644
--- a/src/ddebug/common/queue.d
+++ b/src/ddebug/common/queue.d
@@ -82,7 +82,6 @@ class BlockingQueue(T) {
 			foreach(ref item; items) {
 				append(item);
 			}
-			append(item);
 			_condition.notifyAll();
 		}
 	}
@@ -99,7 +98,7 @@ class BlockingQueue(T) {
 			}
 			if (timeoutMillis <= 0)
 				_condition.wait(); // no timeout
-			else if (!_condition.wait(dur!msecs(timeoutMillis)))
+			else if (!_condition.wait(dur!"msecs"(timeoutMillis)))
 				return false; // timeout
 			if (_readPos < _writePos) {
 				value = _buffer[_readPos++];
@@ -122,7 +121,7 @@ class BlockingQueue(T) {
 				return true;
 			if (timeoutMillis <= 0)
 				_condition.wait(); // no timeout
-			else if (!_condition.wait(dur!msecs(timeoutMillis)))
+			else if (!_condition.wait(dur!"msecs"(timeoutMillis)))
 				return false; // timeout
 			while (_readPos < _writePos)
 				values ~= _buffer[_readPos++];
diff --git a/src/ddebug/gdb/gdbinterface.d b/src/ddebug/gdb/gdbinterface.d
new file mode 100644
index 0000000..76ea636
--- /dev/null
+++ b/src/ddebug/gdb/gdbinterface.d
@@ -0,0 +1,94 @@
+module ddebug.gdb.gdbinterface;
+
+public import ddebug.common.debugger;
+import dlangui.core.logger;
+import ddebug.common.queue;
+import dlangide.builders.extprocess;
+import std.utf;
+
+class ConsoleDebuggerInterface : DebuggerBase, TextWriter {
+	protected ExternalProcess _debuggerProcess;
+
+	protected ExternalProcessState runDebuggerProcess(string executable, string[]args, string dir) {
+		_debuggerProcess = new ExternalProcess();
+		ExternalProcessState state = _debuggerProcess.run(executable, args, dir, this);
+		return state;
+	}
+
+	private string[] _stdoutLines;
+	private char[] _stdoutBuf;
+	/// return true to clear lines list
+	protected bool onDebuggerStdoutLines(string[] lines) {
+		return true;
+	}
+	private void onStdoutText(string text) {
+		_stdoutBuf ~= text;
+		// pass full lines
+		int startPos = 0;
+		bool fullLinesFound = false;
+		for (int i = 0; i < _stdoutBuf.length; i++) {
+			if (_stdoutBuf[i] == '\n' || _stdoutBuf[i] == '\r') {
+				if (i <= startPos)
+					_stdoutLines ~= "";
+				else
+					_stdoutLines ~= _stdoutBuf[startPos .. i].dup;
+				fullLinesFound = true;
+				if (i + 1 < _stdoutBuf.length) {
+					if ((_stdoutBuf[i] == '\n' && _stdoutBuf[i + 1] == '\r')
+							|| (_stdoutBuf[i] == '\r' && _stdoutBuf[i + 1] == '\n'))
+						i++;
+				}
+				startPos = i + 1;
+			}
+		}
+		if (fullLinesFound) {
+			for (int i = 0; i + startPos < _stdoutBuf.length; i++)
+				_stdoutBuf[i] = _stdoutBuf[i + startPos];
+			_stdoutBuf.length = _stdoutBuf.length - startPos;
+			if (onDebuggerStdoutLines(_stdoutLines)) {
+				_stdoutLines.length = 0;
+			}
+		}
+	}
+
+	/// log lines
+	override void writeText(dstring text) {
+		string text8 = toUTF8(text);
+		postRequest(delegate() {
+				onStdoutText(text8);
+		});
+	}
+
+}
+
+class GDBInterface : ConsoleDebuggerInterface {
+
+	override void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response) {
+		string[] debuggerArgs;
+		debuggerArgs ~= "--interpreter=mi";
+		debuggerArgs ~= "--silent";
+		debuggerArgs ~= "--args";
+		debuggerArgs ~= executable;
+		foreach(arg; args)
+			debuggerArgs ~= arg;
+		ExternalProcessState state = runDebuggerProcess(debuggerExecutable, debuggerArgs, workingDir);
+		Log.i("Debugger process state:");
+		if (state == ExternalProcessState.Running) {
+			response(ResponseCode.Ok, "Started");
+		} else {
+			response(ResponseCode.CannotRunDebugger, "Error while trying to run debugger process");
+		}
+	}
+
+	override void stop() {
+		if (_debuggerProcess !is null)
+			_debuggerProcess.kill();
+		super.stop();
+	}
+
+	/// return true to clear lines list
+	override protected bool onDebuggerStdoutLines(string[] lines) {
+		Log.d("onDebuggerStdout ", lines);
+		return true;
+	}
+}
diff --git a/src/dlangide.d b/src/dlangide.d
index 799ba3b..643bfb5 100644
--- a/src/dlangide.d
+++ b/src/dlangide.d
@@ -59,14 +59,17 @@ extern (C) int UIAppMain(string[] args) {
     version(USE_WIN_DEBUG) {
         debuggerTest();
     }
+	version(USE_GDB_DEBUG) {
+		debuggerTest();
+	}
 
     // create window
     Window window = Platform.instance.createWindow("Dlang IDE", null, WindowFlag.Resizable, 800, 600);
     // set window icon
     window.windowIcon = drawableCache.getImage("dlangui-logo1");
 	
-    Widget w = new Widget();
-    pragma(msg, w.click.return_t, "", w.click.params_t);
+    //Widget w = new Widget();
+    //pragma(msg, w.click.return_t, "", w.click.params_t);
 
     IDEFrame frame = new IDEFrame(window);
 
@@ -93,6 +96,40 @@ version(USE_WIN_DEBUG) {
     }
 }
 
+version(USE_GDB_DEBUG) {
+	void debuggerTest() {
+		import ddebug.gdb.gdbinterface;
+		import core.thread;
+		Log.d("Testing GDB debugger");
+		DebuggerBase debugger = new DebuggerBase();
+		debugger.startDebugging("gdb", "test", [], "", delegate(ResponseCode code, string msg) {
+				Log.d("startDebugging result: ", code, " : ", msg);
+				//assert(code == ResponseCode.NotImplemented);
+			});
+		debugger.stop();
+		destroy(debugger);
+
+		// async
+
+		debugger = new GDBInterface();
+		DebuggerProxy proxy = new DebuggerProxy(debugger, delegate(Runnable runnable) {
+				runnable();
+			});
+		Log.d("calling debugger.start()");
+		debugger.start();
+		Log.d("calling proxy.startDebugging()");
+		proxy.startDebugging("gdb", "/home/lve/src/d/dlangide/test/gdbtest", ["param1", "param2"], "/home/lve/src/d/dlangide/test", delegate(ResponseCode code, string msg) {
+				Log.d("startDebugging result: ", code, " : ", msg);
+				//assert(code == ResponseCode.NotImplemented);
+			});
+		Thread.sleep(dur!"msecs"(2000));
+		debugger.stop();
+		Thread.sleep(dur!"msecs"(2000));
+		destroy(debugger);
+		Log.d("Testing of GDB debugger is finished");
+	}
+}
+
 unittest {
     void jsonTest() {
         import dlangui.core.settings;

From 26e805fe1d2da7ae70b4ff3435b405593116293e Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Mon, 16 Nov 2015 16:54:32 +0300
Subject: [PATCH 6/9] gdb support

---
 src/ddebug/gdb/gdbinterface.d      | 16 ++++++++++++++++
 src/dlangide/builders/extprocess.d |  8 +++++---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/src/ddebug/gdb/gdbinterface.d b/src/ddebug/gdb/gdbinterface.d
index 76ea636..91fb190 100644
--- a/src/ddebug/gdb/gdbinterface.d
+++ b/src/ddebug/gdb/gdbinterface.d
@@ -5,6 +5,7 @@ import dlangui.core.logger;
 import ddebug.common.queue;
 import dlangide.builders.extprocess;
 import std.utf;
+import std.conv : to;
 
 class ConsoleDebuggerInterface : DebuggerBase, TextWriter {
 	protected ExternalProcess _debuggerProcess;
@@ -51,6 +52,10 @@ class ConsoleDebuggerInterface : DebuggerBase, TextWriter {
 		}
 	}
 
+	bool sendLine(string text) {
+		return _debuggerProcess.write(text ~ "\n");
+	}
+
 	/// log lines
 	override void writeText(dstring text) {
 		string text8 = toUTF8(text);
@@ -63,6 +68,15 @@ class ConsoleDebuggerInterface : DebuggerBase, TextWriter {
 
 class GDBInterface : ConsoleDebuggerInterface {
 
+	protected int commandId;
+
+
+	int sendCommand(string text) {
+		commandId++;
+		sendLine(to!string(commandId) ~ text);
+		return commandId;
+	}
+
 	override void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response) {
 		string[] debuggerArgs;
 		debuggerArgs ~= "--interpreter=mi";
@@ -75,6 +89,8 @@ class GDBInterface : ConsoleDebuggerInterface {
 		Log.i("Debugger process state:");
 		if (state == ExternalProcessState.Running) {
 			response(ResponseCode.Ok, "Started");
+			sendCommand("-break-insert main");
+			sendCommand("-exec-run");
 		} else {
 			response(ResponseCode.CannotRunDebugger, "Error while trying to run debugger process");
 		}
diff --git a/src/dlangide/builders/extprocess.d b/src/dlangide/builders/extprocess.d
index 9d782e9..3d4fd46 100644
--- a/src/dlangide/builders/extprocess.d
+++ b/src/dlangide/builders/extprocess.d
@@ -400,14 +400,16 @@ class ExternalProcess {
         return _state;
     }
 
-    void write(string data) {
+    bool write(string data) {
         if(_state == ExternalProcessState.Error || _state == ExternalProcessState.None || _state == ExternalProcessState.Stopped) {
-            return;
+            return false;
         }
         else {
             Log.d("writing ", data.length, " characters to stdin");
             _pipes.stdin.write("", data);
-            _pipes.stdin.close();
+			_pipes.stdin.flush();
+            //_pipes.stdin.close();
+			return true;
         }
     }
 }

From 2e5f328d31893a341721bee166f50ea2120ebbd4 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Fri, 4 Dec 2015 10:02:18 +0300
Subject: [PATCH 7/9] add disowntty project; settings fixes; newproject

---
 dlangide-monod-linux.dproj      | 24 ++++++++++++
 dlangide-monod-linux.sln        | 29 +++++++++++++++
 src/dlangide/ui/newproject.d    | 52 ++++++++++++++++++++++++++
 src/dlangide/ui/settings.d      |  5 ++-
 tools/disowntty/disowntty.d     | 65 +++++++++++++++++++++++++++++++++
 tools/disowntty/disowntty.dproj | 48 ++++++++++++++++++++++++
 6 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 tools/disowntty/disowntty.d
 create mode 100644 tools/disowntty/disowntty.dproj

diff --git a/dlangide-monod-linux.dproj b/dlangide-monod-linux.dproj
index 66e9e98..602b037 100644
--- a/dlangide-monod-linux.dproj
+++ b/dlangide-monod-linux.dproj
@@ -165,6 +165,30 @@
     <Externalconsole>true</Externalconsole>
     <DebugLevel>0</DebugLevel>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|x64' ">
+    <OutputPath>bin\DebugX11</OutputPath>
+    <VersionIds>
+      <VersionIds>
+        <String>USE_X11</String>
+        <String>USE_FREETYPE</String>
+        <String>USE_GDB_DEBUG</String>
+        <String>EmbedStandardResources</String>
+      </VersionIds>
+    </VersionIds>
+    <ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
+    <LinkinThirdPartyLibraries>true</LinkinThirdPartyLibraries>
+    <ExtraLinkerArguments>-L-lX11</ExtraLinkerArguments>
+    <ExtraCompilerArguments>-Jviews
+-Jviews/res
+-Jviews/res/i18n
+-Jviews/res/mdpi
+-Jviews/res/hdpi</ExtraCompilerArguments>
+    <UnittestMode>false</UnittestMode>
+    <OutputName>dlangide-monod-linux</OutputName>
+    <Target>Executable</Target>
+    <Externalconsole>true</Externalconsole>
+    <DebugLevel>0</DebugLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Compile Include="src\dlangide.d" />
     <Compile Include="src\ddc\lexer\exceptions.d" />
diff --git a/dlangide-monod-linux.sln b/dlangide-monod-linux.sln
index b7e62bd..ba2f7dc 100644
--- a/dlangide-monod-linux.sln
+++ b/dlangide-monod-linux.sln
@@ -13,6 +13,8 @@ Project("{3947E667-4C90-4C3A-BEB9-7148D6FE0D7C}") = "tetris-monod-linux", "..\dl
 EndProject
 Project("{3947E667-4C90-4C3A-BEB9-7148D6FE0D7C}") = "dmledit-monod-linux", "..\dlangui\examples\dmledit\dmledit-monod-linux.dproj", "{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}"
 EndProject
+Project("{3947E667-4C90-4C3A-BEB9-7148D6FE0D7C}") = "disowntty", "tools\disowntty\disowntty.dproj", "{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -21,12 +23,15 @@ Global
 		DebugMinimal|Any CPU = DebugMinimal|Any CPU
 		ReleaseMinimal|Any CPU = ReleaseMinimal|Any CPU
 		UnittestMinimal|Any CPU = UnittestMinimal|Any CPU
+		DebugX11|Any CPU = DebugX11|Any CPU
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.Debug|Any CPU.ActiveCfg = Debug|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.Debug|Any CPU.Build.0 = Debug|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.Release|Any CPU.ActiveCfg = Release|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.Release|Any CPU.Build.0 = Release|x64
 		{075C374A-563A-4CAC-9E9F-0B6E1DFEAEC3}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -39,6 +44,8 @@ Global
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.Debug|Any CPU.Build.0 = Debug|x64
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.Release|Any CPU.ActiveCfg = Release|x64
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.Release|Any CPU.Build.0 = Release|x64
 		{0A3A0D08-E4DC-418E-B92B-561CC91C2306}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -51,6 +58,8 @@ Global
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.Debug|Any CPU.Build.0 = Debug|x64
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.Release|Any CPU.ActiveCfg = Release|x64
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.Release|Any CPU.Build.0 = Release|x64
 		{54BDE028-6064-4CA9-B6CA-4C0BEEE70F24}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -63,6 +72,8 @@ Global
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.Debug|Any CPU.Build.0 = Debug|x64
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{85ECF79F-B75F-4459-8A90-3857961F2029}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{85ECF79F-B75F-4459-8A90-3857961F2029}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.Release|Any CPU.ActiveCfg = Release|x64
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.Release|Any CPU.Build.0 = Release|x64
 		{85ECF79F-B75F-4459-8A90-3857961F2029}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -75,6 +86,8 @@ Global
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.Debug|Any CPU.Build.0 = Debug|x64
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.Release|Any CPU.ActiveCfg = Release|x64
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.Release|Any CPU.Build.0 = Release|x64
 		{8E722D80-CF8D-4D98-BEAE-7BC9E6752AC4}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -87,6 +100,8 @@ Global
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.Debug|Any CPU.Build.0 = Debug|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.DebugMinimal|Any CPU.ActiveCfg = DebugMinimal|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.DebugMinimal|Any CPU.Build.0 = DebugMinimal|x64
+		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.DebugX11|Any CPU.ActiveCfg = DebugX11|x64
+		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.DebugX11|Any CPU.Build.0 = DebugX11|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.Release|Any CPU.ActiveCfg = Release|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.Release|Any CPU.Build.0 = Release|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.ReleaseMinimal|Any CPU.ActiveCfg = ReleaseMinimal|x64
@@ -95,5 +110,19 @@ Global
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.Unittest|Any CPU.Build.0 = Unittest|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.UnittestMinimal|Any CPU.ActiveCfg = UnittestMinimal|x64
 		{A38BEF21-AAFE-4115-A978-63B7C8C2FBD1}.UnittestMinimal|Any CPU.Build.0 = UnittestMinimal|x64
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.DebugMinimal|Any CPU.ActiveCfg = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.DebugMinimal|Any CPU.Build.0 = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.DebugX11|Any CPU.ActiveCfg = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.DebugX11|Any CPU.Build.0 = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Release|Any CPU.Build.0 = Release|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.ReleaseMinimal|Any CPU.ActiveCfg = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.ReleaseMinimal|Any CPU.Build.0 = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Unittest|Any CPU.ActiveCfg = Unittest|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.Unittest|Any CPU.Build.0 = Unittest|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.UnittestMinimal|Any CPU.ActiveCfg = Debug|Any CPU
+		{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}.UnittestMinimal|Any CPU.Build.0 = Debug|Any CPU
 	EndGlobalSection
 EndGlobal
diff --git a/src/dlangide/ui/newproject.d b/src/dlangide/ui/newproject.d
index 0f02d49..deeabb6 100644
--- a/src/dlangide/ui/newproject.d
+++ b/src/dlangide/ui/newproject.d
@@ -4,6 +4,10 @@ import dlangui.core.types;
 import dlangui.core.i18n;
 import dlangui.platforms.common.platform;
 import dlangui.dialogs.dialog;
+import dlangui.widgets.widget;
+import dlangui.widgets.layouts;
+import dlangui.widgets.editors;
+import dlangui.dml.parser;
 
 class NewProjectDlg : Dialog {
 
@@ -18,6 +22,54 @@ class NewProjectDlg : Dialog {
 	/// override to implement creation of dialog controls
 	override void init() {
         super.init();
+		Widget content = parseML(q{
+				VerticalLayout {
+				id: vlayout
+					HorizontalLayout {
+						VerticalLayout {
+						layoutWidth: FILL_PARENT; layoutHeight: FILL_PARENT; layoutWidth: 1
+							TextWidget {
+							text: "Project type"
+							}
+						}
+						VerticalLayout {
+						layoutWidth: FILL_PARENT; layoutWeight: FILL_PARENT; layoutWidth: 1
+							TextWidget {
+							text: "Template"
+							}
+						}
+						VerticalLayout {
+						layoutWidth: FILL_PARENT; layoutWeight: FILL_PARENT; layoutWidth: 1
+							TextWidget {
+							text: "Description"
+							}
+						}
+					}
+				margins: Rect { left: 5; right: 3; top: 2; bottom: 4 }
+				padding: Rect { 5, 4, 3, 2 } // same as Rect { left: 5; top: 4; right: 3; bottom: 2 }
+					TextWidget {
+						/* this widget can be accessed via id myLabel1 
+            e.g. w.childById!TextWidget("myLabel1") 
+        */
+					id: myLabel1
+							text: "Some text"; padding: 5
+							enabled: false
+					}
+					TextWidget {
+					id: myLabel2
+							text: "More text"; margins: 5
+							enabled: true
+					}
+					CheckBox{ id: cb1; text: "Some checkbox" }
+					HorizontalLayout {
+						RadioButton { id: rb1; text: "Radio Button 1" }
+						RadioButton { id: rb1; text: "Radio Button 2" }
+					}
+				}
+			});
+		// you can access loaded items by id - e.g. to assign signal listeners
+		auto edit1 = window.mainWidget.childById!EditLine("edit1");
+
 	}
 
 }
diff --git a/src/dlangide/ui/settings.d b/src/dlangide/ui/settings.d
index ef7e733..aea0be8 100644
--- a/src/dlangide/ui/settings.d
+++ b/src/dlangide/ui/settings.d
@@ -142,7 +142,10 @@ SettingsPage createSettingsPages() {
     texted.addCheckbox("editors/textEditor/useSpacesForTabs", UIString("Use spaces for tabs"d));
     texted.addCheckbox("editors/textEditor/smartIndents", UIString("Smart indents"d));
     texted.addCheckbox("editors/textEditor/smartIndentsAfterPaste", UIString("Smart indent after paste"d));
-    SettingsPage ui = res.addChild("interface", UIString("Interface"d));
+	SettingsPage dlang = res.addChild("dlang", UIString("D"d));
+	SettingsPage ddebug = dlang.addChild("dlang/debugger", UIString("Debugger"d));
+	ddebug.addStringEdit("dlang/debugger/executable", UIString("Debugger executable"d), "gdb");
+	SettingsPage ui = res.addChild("interface", UIString("Interface"d));
     ui.addStringComboBox("interface/theme", UIString("Theme"d), [
             StringListValue("ide_theme_default", "Default"d), 
             StringListValue("ide_theme_dark", "Dark"d)]);
diff --git a/tools/disowntty/disowntty.d b/tools/disowntty/disowntty.d
new file mode 100644
index 0000000..dace944
--- /dev/null
+++ b/tools/disowntty/disowntty.d
@@ -0,0 +1,65 @@
+/* tty;exec disowntty  */
+//#include <sys/ioctl.h>
+//#include <unistd.h>
+//#include <stdio.h>
+//#include <limits.h>
+//#include <stdlib.h>
+//#include <signal.h>
+
+//import std.stdio;
+import std.string;
+import std.c.stdlib;
+import core.thread;
+import core.sys.posix.signal;
+import core.sys.posix.sys.ioctl;
+import core.sys.posix.unistd;
+import core.sys.posix.stdio;
+
+//extern(C) void signal(int sig, void function(int) );
+//extern(C) void setbuf(FILE * stream, char * buf);
+//extern(C) void ioctl(int fd, uint request, int param);
+
+void end(string msg)
+{
+    perror(msg.toStringz);
+    for (;;)
+		Thread.sleep(dur!"seconds"(1));
+}
+
+alias extern(C) void function(int) sigfn_t;
+
+void main(string args[])
+{
+  	FILE *tty_name_file;
+	if (args.length < 2)
+		exit(1);
+
+    string tty_filename = args[1];
+
+	sigfn_t orig;
+  	setbuf (stdout, null);
+  	orig = signal (SIGHUP, SIG_IGN);
+  	if (orig !is SIG_DFL)
+    	end ("signal (SIGHUP)");
+
+	printf("%s %s\n", tty_filename.toStringz, ttyname(STDIN_FILENO));
+	tty_name_file = fopen(tty_filename.toStringz, "w");
+	fprintf(tty_name_file, "%s\n", ttyname(STDIN_FILENO));
+	fclose(tty_name_file);
+	
+	/* Verify we are the sole owner of the tty.  */
+	if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) != 0)
+    	end ("TIOCSCTTY");
+
+  	printf("%s %s\n", tty_filename.toStringz, ttyname(STDIN_FILENO));
+  	tty_name_file = fopen(tty_filename.toStringz, "w");
+  	fprintf(tty_name_file, "%s\n", ttyname(STDIN_FILENO));
+  	fclose(tty_name_file);
+
+  	/* Disown the tty.  */
+  	if (ioctl (STDIN_FILENO, TIOCNOTTY) != 0)
+    	end ("TIOCNOTTY");
+  	end ("OK, disowned");
+
+	exit(1);
+}
diff --git a/tools/disowntty/disowntty.dproj b/tools/disowntty/disowntty.dproj
new file mode 100644
index 0000000..1b1c4b9
--- /dev/null
+++ b/tools/disowntty/disowntty.dproj
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{FB7A3FF6-0E67-47D1-BA70-F258F9A0E332}</ProjectGuid>
+    <BaseDirectory>.</BaseDirectory>
+    <Compiler>DMD2</Compiler>
+    <PreferOneStepBuild>true</PreferOneStepBuild>
+    <UseDefaultCompiler>true</UseDefaultCompiler>
+    <IncrementalLinking>true</IncrementalLinking>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Debug</OutputPath>
+    <ObjectsDirectory>obj/Debug</ObjectsDirectory>
+    <LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
+    <UnittestMode>false</UnittestMode>
+    <OutputName>disowntty</OutputName>
+    <Target>Executable</Target>
+    <Externalconsole>true</Externalconsole>
+    <DebugLevel>0</DebugLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>bin\Release</OutputPath>
+    <ObjectsDirectory>obj/Release</ObjectsDirectory>
+    <LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
+    <UnittestMode>false</UnittestMode>
+    <OutputName>disowntty</OutputName>
+    <Target>Executable</Target>
+    <Externalconsole>true</Externalconsole>
+    <DebugLevel>0</DebugLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Unittest|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Unittest</OutputPath>
+    <ObjectsDirectory>obj/Unittest</ObjectsDirectory>
+    <LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
+    <UnittestMode>true</UnittestMode>
+    <OutputName>disowntty</OutputName>
+    <Target>Executable</Target>
+    <Externalconsole>true</Externalconsole>
+    <DebugLevel>0</DebugLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="disowntty.d" />
+  </ItemGroup>
+</Project>
\ No newline at end of file

From ce0ed698c2832610f37d14c0f1f8f484ec190d32 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Fri, 4 Dec 2015 10:04:03 +0300
Subject: [PATCH 8/9] fix build error

---
 src/dlangide.d                | 4 ++--
 src/dlangide/ui/searchPanel.d | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/dlangide.d b/src/dlangide.d
index 643bfb5..88f11c9 100644
--- a/src/dlangide.d
+++ b/src/dlangide.d
@@ -60,7 +60,7 @@ extern (C) int UIAppMain(string[] args) {
         debuggerTest();
     }
 	version(USE_GDB_DEBUG) {
-		debuggerTest();
+		debuggerTestGDB();
 	}
 
     // create window
@@ -97,7 +97,7 @@ version(USE_WIN_DEBUG) {
 }
 
 version(USE_GDB_DEBUG) {
-	void debuggerTest() {
+	void debuggerTestGDB() {
 		import ddebug.gdb.gdbinterface;
 		import core.thread;
 		Log.d("Testing GDB debugger");
diff --git a/src/dlangide/ui/searchPanel.d b/src/dlangide/ui/searchPanel.d
index b778b9e..c3bf391 100644
--- a/src/dlangide/ui/searchPanel.d
+++ b/src/dlangide/ui/searchPanel.d
@@ -197,7 +197,7 @@ class SearchWidget : TabWidget {
 		_layout.addChild(_findText);
 		
 		auto goButton = new ImageButton("findTextButton", "edit-find");
-		goButton.onClickListener = &onFindButtonPressed;
+		goButton.click = &onFindButtonPressed;
 		_layout.addChild(goButton);
         
         _searchScope = new ComboBox("searchScope", ["File"d, "Project"d, "Dependencies"d, "Everywhere"d]);

From 894089d1bde88205fe9b8bd81b1abaf9d9a868f8 Mon Sep 17 00:00:00 2001
From: Vadim Lopatin <buggins@fromru.com>
Date: Fri, 4 Dec 2015 11:17:54 +0300
Subject: [PATCH 9/9] GDB - external terminal

---
 src/ddebug/gdb/gdbinterface.d | 97 ++++++++++++++++++++++++++++++++++-
 src/dlangide.d                |  4 +-
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/src/ddebug/gdb/gdbinterface.d b/src/ddebug/gdb/gdbinterface.d
index 91fb190..b307861 100644
--- a/src/ddebug/gdb/gdbinterface.d
+++ b/src/ddebug/gdb/gdbinterface.d
@@ -66,6 +66,7 @@ class ConsoleDebuggerInterface : DebuggerBase, TextWriter {
 
 }
 
+import std.process;
 class GDBInterface : ConsoleDebuggerInterface {
 
 	protected int commandId;
@@ -77,8 +78,100 @@ class GDBInterface : ConsoleDebuggerInterface {
 		return commandId;
 	}
 
+	Pid terminalPid;
+	string terminalTty;
+
+	string startTerminal(string termExecutable) {
+		Log.d("Starting terminal");
+		import std.random;
+		import std.file;
+		import std.path;
+		import std.string;
+		import core.thread;
+		uint n = uniform(0, 0x10000000, rndGen());
+		terminalTty = null;
+		string termfile = buildPath(tempDir, format("dlangide-term-name-%07x.tmp", n));
+		Log.d("temp file for tty name: ", termfile);
+		try {
+			terminalPid = spawnProcess([
+				termExecutable,
+				"-title",
+				"DLangIDE External Console",
+				"-e",
+				"echo 'DlangIDE External Console' && tty > " ~ termfile ~ " && sleep 1000000"
+			]);
+			for (int i = 0; i < 20; i++) {
+				Thread.sleep(dur!"msecs"(100));
+				if (!isTerminalActive) {
+					Log.e("Failed to get terminal TTY");
+					return null;
+				}
+				if (!exists(termfile)) {
+					Thread.sleep(dur!"msecs"(20));
+					break;
+				}
+			}
+			// read TTY from file
+			if (exists(termfile)) {
+				terminalTty = readText(termfile);
+				if (terminalTty.endsWith("\n"))
+					terminalTty = terminalTty[0 .. $-1];
+				// delete file
+				remove(termfile);
+			}
+		} catch (Exception e) {
+			Log.e("Failed to start terminal ", e);
+			killTerminal();
+		}
+		if (terminalTty.length == 0) {
+			Log.i("Cannot start terminal");
+			killTerminal();
+		} else {
+			Log.i("Terminal: ", terminalTty);
+		}
+		return terminalTty;
+	}
+
+	bool isTerminalActive() {
+		if (terminalPid is null)
+			return false;
+		auto res = tryWait(terminalPid);
+		if (res.terminated) {
+			Log.d("isTerminalActive: Terminal is stopped");
+			wait(terminalPid);
+			terminalPid = Pid.init;
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	void killTerminal() {
+		if (terminalPid is null)
+			return;
+		try {
+			Log.d("Trying to kill terminal");
+			kill(terminalPid, 9);
+			Log.d("Waiting for terminal process termination");
+			wait(terminalPid);
+			terminalPid = Pid.init;
+			Log.d("Killed");
+		} catch (Exception e) {
+			Log.d("Exception while killing terminal", e);
+			terminalPid = Pid.init;
+		}
+	}
+
+	string terminalExecutableFileName = "xterm";
 	override void startDebugging(string debuggerExecutable, string executable, string[] args, string workingDir, DebuggerResponse response) {
 		string[] debuggerArgs;
+		terminalTty = startTerminal(terminalExecutableFileName);
+		if (terminalTty.length == 0) {
+			response(ResponseCode.CannotRunDebugger, "Cannot start terminal");
+			return;
+		}
+		debuggerArgs ~= "-tty";
+		debuggerArgs ~= terminalTty;
 		debuggerArgs ~= "--interpreter=mi";
 		debuggerArgs ~= "--silent";
 		debuggerArgs ~= "--args";
@@ -89,16 +182,18 @@ class GDBInterface : ConsoleDebuggerInterface {
 		Log.i("Debugger process state:");
 		if (state == ExternalProcessState.Running) {
 			response(ResponseCode.Ok, "Started");
-			sendCommand("-break-insert main");
+			//sendCommand("-break-insert main");
 			sendCommand("-exec-run");
 		} else {
 			response(ResponseCode.CannotRunDebugger, "Error while trying to run debugger process");
+			return;
 		}
 	}
 
 	override void stop() {
 		if (_debuggerProcess !is null)
 			_debuggerProcess.kill();
+		killTerminal();
 		super.stop();
 	}
 
diff --git a/src/dlangide.d b/src/dlangide.d
index 88f11c9..6d8421b 100644
--- a/src/dlangide.d
+++ b/src/dlangide.d
@@ -122,9 +122,9 @@ version(USE_GDB_DEBUG) {
 				Log.d("startDebugging result: ", code, " : ", msg);
 				//assert(code == ResponseCode.NotImplemented);
 			});
-		Thread.sleep(dur!"msecs"(2000));
+		Thread.sleep(dur!"msecs"(200000));
 		debugger.stop();
-		Thread.sleep(dur!"msecs"(2000));
+		Thread.sleep(dur!"msecs"(200000));
 		destroy(debugger);
 		Log.d("Testing of GDB debugger is finished");
 	}