From 0b30ec8c722d6e13d7981f57ce4c2ca96f37bb24 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 29 Aug 2018 21:51:04 +1000
Subject: Fix build


diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c
index 4c327f7..ccd72ce 100644
--- a/channels/rdpsnd/client/rdpsnd_main.c
+++ b/channels/rdpsnd/client/rdpsnd_main.c
@@ -1513,7 +1513,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
 	}
 
 	rdpsnd->attached = TRUE;
-#if !defined(_WIN32) && !defined(ANDROID)
+#if !defined(_WIN32) && !defined(ANDROID) && !defined(__HAIKU__)
 	{
 		sigset_t mask;
 		sigemptyset(&mask);
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 166847e..02481d0 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -55,6 +55,11 @@ if(FREERDP_VENDOR AND WITH_CLIENT)
 		message(STATUS "Adding Android client")
 		add_subdirectory(Android)
 	endif()
+
+	if(HAIKU)
+		message(STATUS "Adding Haiku client")
+		add_subdirectory(Haiku)
+	endif()
 endif()
 
 # Pick up other clients
diff --git a/winpr/include/winpr/winsock.h b/winpr/include/winpr/winsock.h
index 5e04418..f4e1717 100644
--- a/winpr/include/winpr/winsock.h
+++ b/winpr/include/winpr/winsock.h
@@ -84,6 +84,10 @@ WINPR_API INT winpr_inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf);
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <net/if.h>
+#ifdef __HAIKU__
+#include <sys/select.h>
+#include <sys/ioccom.h>
+#endif
 
 #include <winpr/io.h>
 #include <winpr/error.h>
diff --git a/winpr/libwinpr/synch/CMakeLists.txt b/winpr/libwinpr/synch/CMakeLists.txt
index 7c86c34..a7fda31 100644
--- a/winpr/libwinpr/synch/CMakeLists.txt
+++ b/winpr/libwinpr/synch/CMakeLists.txt
@@ -30,7 +30,7 @@ winpr_module_add(
 	timer.c
 	wait.c)
 
-if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID) AND (NOT OPENBSD))
+if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU) AND (NOT ANDROID) AND (NOT OPENBSD))
 	winpr_library_add(rt)
 endif()
 
diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c
index dbd628f..f8a125a 100644
--- a/winpr/libwinpr/synch/timer.c
+++ b/winpr/libwinpr/synch/timer.c
@@ -768,7 +768,9 @@ static int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue)
 	pthread_attr_init(&(timerQueue->attr));
 	timerQueue->param.sched_priority = sched_get_priority_max(SCHED_FIFO);
 	pthread_attr_setschedparam(&(timerQueue->attr), &(timerQueue->param));
+#ifndef __HAIKU__
 	pthread_attr_setschedpolicy(&(timerQueue->attr), SCHED_FIFO);
+#endif
 	pthread_create(&(timerQueue->thread), &(timerQueue->attr), TimerQueueThread, timerQueue);
 	return 0;
 }
diff --git a/winpr/libwinpr/sysinfo/CMakeLists.txt b/winpr/libwinpr/sysinfo/CMakeLists.txt
index f9b7f69..126eb48 100644
--- a/winpr/libwinpr/sysinfo/CMakeLists.txt
+++ b/winpr/libwinpr/sysinfo/CMakeLists.txt
@@ -21,10 +21,14 @@ endif()
 
 winpr_module_add(sysinfo.c)
 
-if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID) AND (NOT OPENBSD))
+if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU) AND (NOT ANDROID) AND (NOT OPENBSD))
 	winpr_library_add(rt)
 endif()
 
+if(HAIKU)
+	winpr_library_add(network)
+endif()
+
 if(BUILD_TESTING)
 	add_subdirectory(test)
 endif()
diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt
index abf4dc1..bf6d495 100644
--- a/winpr/libwinpr/utils/CMakeLists.txt
+++ b/winpr/libwinpr/utils/CMakeLists.txt
@@ -141,7 +141,7 @@ if(UNIX)
 	winpr_library_add(m)
 endif()
 
-if((FREEBSD) AND (NOT KFREEBSD))
+if(((FREEBSD) AND (NOT KFREEBSD)) OR (HAIKU))
 	winpr_library_add(execinfo)
 endif()
 
diff --git a/winpr/libwinpr/winsock/winsock.c b/winpr/libwinpr/winsock/winsock.c
index 50bf1eb..1ed7577 100644
--- a/winpr/libwinpr/winsock/winsock.c
+++ b/winpr/libwinpr/winsock/winsock.c
@@ -371,9 +371,11 @@ void WSASetLastError(int iError)
 		case WSAEPROTONOSUPPORT:
 			errno = EPROTONOSUPPORT;
 			break;
+#ifndef __HAIKU__
 		case WSAESOCKTNOSUPPORT:
 			errno = ESOCKTNOSUPPORT;
 			break;
+#endif
 		case WSAEOPNOTSUPP:
 			errno = EOPNOTSUPP;
 			break;
@@ -416,9 +418,11 @@ void WSASetLastError(int iError)
 		case WSAESHUTDOWN:
 			errno = ESHUTDOWN;
 			break;
+#ifndef __HAIKU__
 		case WSAETOOMANYREFS:
 			errno = ETOOMANYREFS;
 			break;
+#endif
 		case WSAETIMEDOUT:
 			errno = ETIMEDOUT;
 			break;
@@ -445,18 +449,22 @@ void WSASetLastError(int iError)
 			errno = EPROCLIM;
 			break;
 #endif
+#ifndef __HAIKU__
 		case WSAEUSERS:
 			errno = EUSERS;
 			break;
+#endif
 		case WSAEDQUOT:
 			errno = EDQUOT;
 			break;
 		case WSAESTALE:
 			errno = ESTALE;
 			break;
+#ifndef __HAIKU__
 		case WSAEREMOTE:
 			errno = EREMOTE;
 			break;
+#endif
 	}
 }
 
@@ -516,9 +524,11 @@ int WSAGetLastError(void)
 		case EPROTONOSUPPORT:
 			iError = WSAEPROTONOSUPPORT;
 			break;
+#ifndef __HAIKU__
 		case ESOCKTNOSUPPORT:
 			iError = WSAESOCKTNOSUPPORT;
 			break;
+#endif
 		case EOPNOTSUPP:
 			iError = WSAEOPNOTSUPP;
 			break;
@@ -561,9 +571,11 @@ int WSAGetLastError(void)
 		case ESHUTDOWN:
 			iError = WSAESHUTDOWN;
 			break;
+#ifndef __HAIKU__
 		case ETOOMANYREFS:
 			iError = WSAETOOMANYREFS;
 			break;
+#endif
 		case ETIMEDOUT:
 			iError = WSAETIMEDOUT;
 			break;
@@ -590,19 +602,22 @@ int WSAGetLastError(void)
 			iError = WSAEPROCLIM;
 			break;
 #endif
+#ifndef __HAIKU__
 		case EUSERS:
 			iError = WSAEUSERS;
 			break;
+#endif
 		case EDQUOT:
 			iError = WSAEDQUOT;
 			break;
 		case ESTALE:
 			iError = WSAESTALE;
 			break;
+#ifndef __HAIKU__
 		case EREMOTE:
 			iError = WSAEREMOTE;
 			break;
-
+#endif
 		/* Special cases */
 
 #if (EAGAIN != EWOULDBLOCK)
diff --git a/winpr/winpr.pc.in b/winpr/winpr.pc.in
index 6b0c950..73aea67 100644
--- a/winpr/winpr.pc.in
+++ b/winpr/winpr.pc.in
@@ -11,5 +11,5 @@ Version: @WINPR_VERSION@
 Requires:
 Requires.private: libssl
 Libs: -L${libdir} ${libs}
-Libs.private: -ldl -lrt -lm -lpthread
+Libs.private: -ldl -lnetwork -lbe
 Cflags: -I${includedir}
-- 
2.16.4


From bb4cf466631ce75df92b53c7478c7fe41f281b77 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 29 Aug 2018 21:53:34 +1000
Subject: Add Haiku support


diff --git a/client/Haiku/App.cpp b/client/Haiku/App.cpp
new file mode 100644
index 0000000..92874d0
--- /dev/null
+++ b/client/Haiku/App.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 Your Name <your@email.address>
+ * All rights reserved. Distributed under the terms of the MIT license.
+ */
+ 
+#include "App.h"
+
+const char *APPSIGNATURE = "application/x-vnd.freerdp";
+
+TestApplication::TestApplication()
+		  :BApplication(APPSIGNATURE)
+{
+
+}
+
+
+TestApplication::~TestApplication()
+{
+}
+
diff --git a/client/Haiku/App.h b/client/Haiku/App.h
new file mode 100644
index 0000000..828c3bc
--- /dev/null
+++ b/client/Haiku/App.h
@@ -0,0 +1,16 @@
+#ifndef _TEST_APPLICATION_H
+#define _TEST_APPLICATION_H
+
+#include <Application.h>
+#include <FilePanel.h>
+#include <Path.h>
+#include <stdio.h>
+
+class TestApplication : public BApplication {
+	public:
+						TestApplication();
+		virtual			~TestApplication();
+};
+
+#endif
+
diff --git a/client/Haiku/CMakeLists.txt b/client/Haiku/CMakeLists.txt
new file mode 100644
index 0000000..1441dc8
--- /dev/null
+++ b/client/Haiku/CMakeLists.txt
@@ -0,0 +1,36 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP Haiku UI cmake build script
+#
+# Copyright 2018 Gerasim Troeglazov <3dEyes@gmail.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set(MODULE_NAME "FreeRDP")
+set(MODULE_PREFIX "FREERDP_CLIENT_HAIKU")
+set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
+
+set(${MODULE_PREFIX}_SRCS
+	FreeRDP.cpp App.cpp MainWindow.cpp MainView.cpp)
+
+add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+
+set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS})
+set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp)
+set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} be network media translation)
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND rc -o Resources.rsrc ${CMAKE_CURRENT_SOURCE_DIR}/Resources.rdef COMMENT "Compiling resources")
+ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND xres -o ${MODULE_NAME} Resources.rsrc COMMENT "Adding resources to executable")
+ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND mimeset --all ${MODULE_NAME} COMMENT "Adjusting MIME types")
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Haiku")
diff --git a/client/Haiku/FreeRDP.cpp b/client/Haiku/FreeRDP.cpp
new file mode 100644
index 0000000..a3fbb7b
--- /dev/null
+++ b/client/Haiku/FreeRDP.cpp
@@ -0,0 +1,322 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * FreeRDP Test UI
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2016 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <Application.h>
+#include <Window.h>
+#include <SupportDefs.h>
+#include <Bitmap.h>
+#include <Screen.h>
+#include <View.h>
+#include <Rect.h>
+
+#include "App.h"
+#include "MainWindow.h"
+#include "MainView.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+
+#include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/client/file.h>
+#include <freerdp/client/cmdline.h>
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/client/channels.h>
+#include <freerdp/channels/channels.h>
+#include <freerdp/locale/keyboard.h>
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <freerdp/log.h>
+
+}
+
+#define TAG CLIENT_TAG("haiku")
+
+MainWindow *wnd = NULL;
+
+struct tf_context
+{
+	rdpContext _p;
+};
+typedef struct tf_context tfContext;
+
+static BOOL tf_context_new(freerdp* instance, rdpContext* context)
+{
+	return TRUE;
+}
+
+static void tf_context_free(freerdp* instance, rdpContext* context)
+{
+}
+
+static BOOL tf_begin_paint(rdpContext* context)
+{
+	rdpGdi* gdi = context->gdi;
+	gdi->primary->hdc->hwnd->invalid->null = TRUE;
+	return TRUE;
+}
+
+static BOOL tf_end_paint(rdpContext* context)
+{
+	rdpGdi* gdi = context->gdi;
+	
+	if(wnd==NULL)
+		return TRUE;
+			
+	if (gdi->primary->hdc->hwnd->invalid->null)
+		return TRUE;
+
+	char* data = (char*)wnd->fb->GetBuffer();
+
+	int x = gdi->primary->hdc->hwnd->invalid->x;
+	int y = gdi->primary->hdc->hwnd->invalid->y;
+	int w = gdi->primary->hdc->hwnd->invalid->w;
+	int h = gdi->primary->hdc->hwnd->invalid->h;
+	
+	for (int i = 0; i < h; i++)
+	{
+		memcpy(data + ((i + y) * (gdi->width * GetBytesPerPixel(
+		                              gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat),
+		       gdi->primary_buffer + ((i + y) * (gdi->width * GetBytesPerPixel(
+		                                  gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat),
+		       w * GetBytesPerPixel(gdi->dstFormat));
+	}
+	
+	wnd->fb->Paint();
+	
+	return TRUE;
+}
+
+static BOOL tf_pre_connect(freerdp* instance)
+{
+	rdpSettings* settings;
+	settings = instance->settings;
+	settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
+	settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
+	settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
+	settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
+	settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
+	settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
+	settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
+	settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE;
+	settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE;
+	settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
+	settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE;
+	settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE;
+	settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE;
+	settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
+	settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
+	settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
+	settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
+	
+	if (settings->Fullscreen) {
+		BScreen screen;
+		settings->DesktopWidth = (UINT32) screen.Frame().right + 1;
+		settings->DesktopHeight = (UINT32) screen.Frame().bottom + 1;
+	}
+	
+	return TRUE;
+}
+
+static BOOL tf_post_connect(freerdp* instance)
+{
+	rdpGdi* gdi;
+	rdpContext* context;
+	rdpSettings* settings;
+
+	context = ((rdpContext*) instance->context);
+
+	if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
+		return FALSE;
+
+	gdi = instance->context->gdi;
+	settings = instance->settings;
+
+	instance->update->BeginPaint = tf_begin_paint;
+	instance->update->EndPaint = tf_end_paint;
+
+	if(wnd==NULL) {
+		char wndTitle[256]={"FreeRDP"};
+		
+		BRect rect = BRect(50, 50, 50 + gdi->width, 50 + gdi->height);
+		if (settings->Fullscreen) {
+			rect = BRect(0, 0, gdi->width, gdi->height);
+		}
+		if (settings->WindowTitle != NULL)
+			snprintf(wndTitle, 255, "%s", settings->WindowTitle);
+		else if (settings->ServerPort == 3389)
+			snprintf(wndTitle, 255, "FreeRDP: %s", settings->ServerHostname);
+		else
+			snprintf(wndTitle, 255, "FreeRDP: %S:%u", settings->ServerHostname, settings->ServerPort);
+
+		wnd = new MainWindow(rect, wndTitle, instance);
+		wnd->Show();
+	}	
+
+	return TRUE;
+}
+
+static void tf_post_disconnect(freerdp* instance)
+{
+	rdpContext* context;
+
+	if (!instance)
+		return;
+
+	if (!instance->context)
+		return;
+
+	context = (rdpContext*) instance->context;
+	gdi_free(instance);
+
+	if (wnd!=NULL) {
+		wnd->Lock();
+		wnd->Quit();
+	}
+}
+
+static DWORD WINAPI tf_haiku_app_thread_proc(LPVOID arg)
+{
+	TestApplication app;
+	app.Run();
+	
+	ExitThread(0);
+	return 0;
+}
+
+
+static DWORD WINAPI tf_client_thread_proc(LPVOID arg)
+{
+	freerdp* instance = (freerdp*)arg;
+	DWORD nCount;
+	DWORD status;
+	HANDLE handles[64];
+
+	if (!freerdp_connect(instance))
+	{
+		WLog_ERR(TAG, "connection failure");
+		return 0;
+	}
+
+	while (!freerdp_shall_disconnect(instance))
+	{
+		nCount = freerdp_get_event_handles(instance->context, &handles[0], 64);
+
+		if (nCount == 0)
+		{
+			WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__);
+			break;
+		}
+
+		status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
+
+		if (status == WAIT_FAILED)
+		{
+			WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %"PRIu32"", __FUNCTION__,
+			         status);
+			break;
+		}
+
+		if (!freerdp_check_event_handles(instance->context))
+		{
+			if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
+				WLog_ERR(TAG, "Failed to check FreeRDP event handles");
+
+			break;
+		}
+	}
+
+	freerdp_disconnect(instance);
+	ExitThread(0);
+	return 0;
+}
+
+int main(int argc, char* argv[])
+{
+	int status;
+	HANDLE thread;
+	freerdp* instance;
+	instance = freerdp_new();
+
+	if (!instance)
+	{
+		WLog_ERR(TAG, "Couldn't create instance");
+		winpr_exit(1);
+	}
+
+	instance->PreConnect = tf_pre_connect;
+	instance->PostConnect = tf_post_connect;
+	instance->PostDisconnect = tf_post_disconnect;
+	instance->ContextSize = sizeof(tfContext);
+	instance->ContextNew = tf_context_new;
+	instance->ContextFree = tf_context_free;
+	freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
+
+	if (!freerdp_context_new(instance))
+	{
+		WLog_ERR(TAG, "Couldn't create context");
+		return winpr_exit(1);
+	}
+
+	status = freerdp_client_settings_parse_command_line(instance->settings, argc,
+	         argv, FALSE);
+
+	if (status < 0)
+	{
+		return winpr_exit(0);
+	}
+
+	if (!freerdp_client_load_addins(instance->context->channels,
+	                                instance->settings))
+		return winpr_exit(-1);
+
+	//if (!(thread = CreateThread(NULL, 0, tf_haiku_app_thread_proc, instance, 0, NULL)))
+	//{
+//		WLog_ERR(TAG, "Failed to create app thread");
+//	}
+
+	if (!(thread = CreateThread(NULL, 0, tf_client_thread_proc, instance, 0, NULL)))
+	{
+		WLog_ERR(TAG, "Failed to create client thread");
+	}
+	else
+	{
+		WaitForSingleObject(thread, INFINITE);
+	}
+
+	freerdp_context_free(instance);
+	freerdp_free(instance);
+	return winpr_exit(0);
+}
diff --git a/client/Haiku/MainView.cpp b/client/Haiku/MainView.cpp
new file mode 100644
index 0000000..00e70a0
--- /dev/null
+++ b/client/Haiku/MainView.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2010 Your Name <your@email.address>
+ * All rights reserved. Distributed under the terms of the MIT license.
+ */
+
+#include "MainWindow.h"
+#include "MainView.h"
+
+
+FBView::FBView(BRect rect) : 
+	BView(rect, "FBView", B_FOLLOW_ALL, B_WILL_DRAW|B_PULSE_NEEDED|B_FRAME_EVENTS),
+	showBar(false)
+{
+	FBView(rect, rect.IntegerWidth(), rect.IntegerHeight());
+}
+
+FBView::FBView(BRect rect, int width, int height) : 
+	BView(rect, "FBView", B_FOLLOW_ALL, B_WILL_DRAW|B_PULSE_NEEDED|B_FRAME_EVENTS),
+	showBar(false)
+{
+	buffer_width = width;
+	buffer_height = height;
+	lastButtons = 0;
+	
+	BRect	fbRect = BRect(0,0,buffer_width-1,buffer_height-1);	
+	bufferView = new BView(fbRect, "bufferView", B_FOLLOW_ALL_SIDES, 0);
+	bufferBitmap = new BBitmap(fbRect, B_RGB32, true);	
+	bufferBitmap->AddChild(bufferView);
+
+	font = be_bold_font;
+	font.SetSize(14);
+	SetFont(&font, B_FONT_ALL);
+	
+	title = BString("FreeRDP");
+	
+	//printf("BTranslationUtils::GetBitmap\n");
+	//closeBitmap = BTranslationUtils::GetBitmapFile("/NoIndex64/Public/FreeRDP/client/Haiku/images/close.png");
+	//printf("W:%f H:%f\n", closeBitmap->Bounds().Width(), closeBitmap->Bounds().Height());
+	//zoomBitmap = new BBitmap(BRect(0,0,16,16),B_RGB32);//BTranslationUtils::GetBitmap(B_PNG_FORMAT, "zoom.png");
+}
+
+FBView::~FBView()
+{
+	//delete closeBitmap;
+	//delete zoomBitmap;
+}
+
+void
+FBView::AttachedToWindow(void)
+{
+	tickCount = 0;
+}
+
+void
+FBView::Pulse(void)
+{
+	uint32 dx = Bounds().Width() / 3;
+	uint32 h = showBar?20:2;
+	if (lastPos.y >= 0 && lastPos.y < h && lastPos.x > dx && lastPos.x < dx * 2 ) {
+		tickCount++;
+		if(tickCount > 5) {
+			showBar = true;
+			Invalidate();
+		}
+		return;
+	}
+	if(showBar) {
+		showBar = false;
+		Invalidate();
+	}
+	tickCount = 0;
+}
+
+void
+FBView::SetInstance(freerdp *inst)
+{
+	instance = inst;
+	title.SetTo(Window()->Title());
+}
+
+BPoint	
+FBView::GetLastMousePos()
+{
+	return lastPos;
+}
+
+void FBView::MouseMoved(BPoint p, uint32 transit,const BMessage *message)
+{
+	rdpInput* input = instance->input;
+	switch(transit)
+	 {
+	 	case B_INSIDE_VIEW:
+	 	case B_ENTERED_VIEW:
+	 		{
+	 			input->MouseEvent(input, PTR_FLAGS_MOVE, p.x, p.y);
+	 			tickCount = 0;
+	 			break;
+	 		}
+	 	case B_EXITED_VIEW:
+	 		break;
+	 	case B_OUTSIDE_VIEW:
+	 		break; 
+	 }
+	lastPos = p;
+}
+
+void FBView::MouseDown(BPoint p)
+{
+	rdpInput* input = instance->input;
+
+	uint32 dx = Bounds().Width() / 3;
+	uint32 h = showBar?20:2;
+
+	uint32 buttons = Window()->CurrentMessage()->FindInt32("buttons");
+	int32 clicks = Window()->CurrentMessage()->FindInt32("clicks");
+	int flags = PTR_FLAGS_DOWN;
+	
+	if (buttons & B_PRIMARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON1;
+	if (buttons & B_SECONDARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON2;
+	if (buttons & B_TERTIARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON2;
+
+	if (showBar && buttons & B_PRIMARY_MOUSE_BUTTON) {
+		BRect closeButtonRect(dx + 3, 3, dx + h - 3, h - 3);
+		if (closeButtonRect.Contains(p)) {
+			freerdp_abort_connect(instance);
+		} else if(clicks == 2) {
+			Window()->Minimize(true);
+			flags = 0;
+		}
+	}
+
+	if (flags != 0)
+		input->MouseEvent(input, flags, p.x, p.y);
+	
+	lastPos = p;
+	lastButtons = buttons;
+}
+
+void FBView::MouseUp(BPoint p)
+{
+	rdpInput* input = instance->input;
+
+	uint32 buttons = Window()->CurrentMessage()->FindInt32("buttons");
+	int flags = 0;
+
+	if ((buttons ^ lastButtons) & B_PRIMARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON1;
+	if ((buttons ^ lastButtons) & B_SECONDARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON2;
+	if ((buttons ^lastButtons) & B_TERTIARY_MOUSE_BUTTON)
+			flags |= PTR_FLAGS_BUTTON2;
+			
+	if (flags != 0)
+		input->MouseEvent(input, flags, p.x, p.y);
+	
+	lastPos = p;
+	lastButtons = buttons;
+}
+
+void
+FBView::Draw(BRect r)
+{
+	uint32 dx = Bounds().Width() / 3;
+	uint32 h = showBar?20:2;
+
+	DrawBitmap(bufferBitmap, r, r);
+	if (showBar) {		
+		BRect r(dx, -1, dx * 2, h);
+		SetDrawingMode(B_OP_COPY);
+		
+		SetHighColor(255, 203, 0);
+		SetLowColor(255, 203, 0);
+		FillRect(r);
+		SetHighColor(179, 143, 0);
+		SetLowColor(179, 143, 0);
+		StrokeRect(r);
+		
+		SetDrawingMode(B_OP_ALPHA);
+		BRect closeButtonRect(dx + 3, 3, dx + h - 3, h - 3);
+		StrokeRect(closeButtonRect);
+		//DrawBitmap(closeBitmap, BPoint(dx + 3, 3));
+		
+		SetHighColor(0, 0, 0);
+		SetLowColor(0, 0, 0);
+		float width = font.StringWidth(title);
+		DrawString(title, BPoint(Bounds().Width()/2 - width/2, 16));
+	}
+}
+
+void 
+FBView::Paint()
+{
+  if(LockLooper())	{
+ 	 bufferView->LockLooper();
+ 	 SetDrawingMode(B_OP_COPY);
+	 DrawBitmap(bufferBitmap);//, bufferView->Bounds(), Bounds());
+	 bufferView->UnlockLooper();
+	 UnlockLooper();
+	}
+}
+
+uint32 *
+FBView::GetBuffer()
+{
+	if(bufferBitmap) {
+		return (uint32*)bufferBitmap->Bits();
+	}
+	return NULL;
+}
+
+uint32	
+FBView::GetBufferSize()
+{
+	if(bufferBitmap) {
+		return bufferBitmap->BitsLength()/4;
+	}
+	return 0;
+}
+
+int
+FBView::Width() 
+{
+	return buffer_width;
+}
+
+int
+FBView::Height()
+{
+	return buffer_height;
+}
+
+
diff --git a/client/Haiku/MainView.h b/client/Haiku/MainView.h
new file mode 100644
index 0000000..8597c85
--- /dev/null
+++ b/client/Haiku/MainView.h
@@ -0,0 +1,74 @@
+#ifndef _H_FBVIEW_
+#define _H_FBVIEW_
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+
+#include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/client/file.h>
+#include <freerdp/client/cmdline.h>
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/client/channels.h>
+#include <freerdp/channels/channels.h>
+#include <freerdp/locale/keyboard.h>
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <freerdp/log.h>
+
+}
+
+#include <SupportDefs.h>
+#include <Bitmap.h>
+#include <String.h>
+#include <Font.h>
+#include <View.h>
+#include <Rect.h>
+#include <TranslationUtils.h>
+#include <TranslatorFormats.h>
+
+class FBView : public BView 
+{
+ public:
+		FBView(BRect rect);
+		FBView(BRect rect, int width, int height);
+		~FBView();
+		
+		void 	Paint();
+		void 	SetInstance(freerdp *instance);
+		uint32	*GetBuffer();
+		uint32	GetBufferSize();
+		BPoint	GetLastMousePos();
+		
+		int		Width();
+		int		Height();
+protected:
+		virtual void	Draw(BRect r);
+		virtual void 	MouseDown(BPoint p);
+ 		virtual void 	MouseUp(BPoint p);
+ 		virtual void 	MouseMoved(BPoint point, uint32 transit, const BMessage *message);
+ 		virtual void 	Pulse(void);
+ 		virtual void 	AttachedToWindow(void);
+
+private:
+ 		int		buffer_width;
+ 		int		buffer_height;
+		BView	*bufferView;
+		BBitmap *bufferBitmap;
+		BBitmap *closeBitmap;
+		BBitmap *zoomBitmap;
+		uint32  lastButtons;
+		BPoint	lastPos;
+		freerdp *instance;
+		uint32	tickCount;
+		bool	showBar;
+		BFont 	font;
+		BString title;
+};
+
+#endif
diff --git a/client/Haiku/MainWindow.cpp b/client/Haiku/MainWindow.cpp
new file mode 100644
index 0000000..8228e34
--- /dev/null
+++ b/client/Haiku/MainWindow.cpp
@@ -0,0 +1,131 @@
+#include <Application.h>
+#include <Window.h>
+#include "MainWindow.h"
+
+BApplication app("application/x-vnd.freerdp");
+
+static const uint32 be_to_scan_codes[] = {
+VK_ESCAPE, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
+VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, VK_PRINT, VK_SCROLL, 0,
+//////////
+VK_OEM_3,VK_KEY_1,VK_KEY_2,VK_KEY_3,VK_KEY_4,VK_KEY_5,VK_KEY_6,VK_KEY_7,VK_KEY_8,
+VK_KEY_9,VK_KEY_0,VK_OEM_MINUS,VK_OEM_PLUS,VK_BACK,VK_INSERT|KBDEXT,
+VK_HOME|KBDEXT,VK_PRIOR|KBDEXT,VK_NUMLOCK,VK_DIVIDE|KBDEXT,VK_MULTIPLY,VK_SUBTRACT,
+//////////
+VK_TAB,VK_KEY_Q,VK_KEY_W,VK_KEY_E,VK_KEY_R,VK_KEY_T,VK_KEY_Y,VK_KEY_U,VK_KEY_I,
+VK_KEY_O,VK_KEY_P,VK_OEM_4,VK_OEM_6,VK_OEM_5,VK_DELETE|KBDEXT,VK_END|KBDEXT,VK_NEXT|KBDEXT,
+VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9,VK_ADD,
+//////////
+VK_CAPITAL,VK_KEY_A,VK_KEY_S,VK_KEY_D,VK_KEY_F,VK_KEY_G,VK_KEY_H,VK_KEY_J,VK_KEY_K,VK_KEY_L,VK_OEM_1,VK_OEM_7,VK_RETURN,
+VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6,
+//////////
+VK_LSHIFT,VK_KEY_Z,VK_KEY_X,VK_KEY_C,VK_KEY_V,VK_KEY_B,VK_KEY_N,VK_KEY_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
+VK_RSHIFT,VK_UP|KBDEXT,VK_NUMPAD1,VK_NUMPAD2,VK_NUMPAD3,VK_RETURN|KBDEXT,
+//////////
+VK_LCONTROL,VK_LMENU,VK_SPACE,VK_RMENU,VK_RCONTROL,VK_LEFT|KBDEXT,VK_DOWN|KBDEXT,VK_RIGHT|KBDEXT,VK_NUMPAD0,VK_DECIMAL,
+VK_LWIN|KBDEXT,VK_RWIN|KBDEXT,127,0
+};
+
+
+MainWindow::MainWindow(BRect frame, const char* title, freerdp *inst)
+	: BWindow(frame, title, B_TITLED_WINDOW_LOOK,B_NORMAL_WINDOW_FEEL,B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
+{	
+	fb = new FBView(Bounds(), frame.Width(),frame.Height());
+	AddChild(fb);
+	SetInstance(inst);
+	SetPulseRate(100000);
+}
+
+
+MainWindow::~MainWindow()
+{	 
+}
+
+void 
+MainWindow::MessageReceived(BMessage *message)
+{
+	switch(message->what) {
+		case B_UNMAPPED_KEY_DOWN:
+		case B_KEY_DOWN:
+		{
+			rdpInput* input = instance->input;
+
+			const char *bytes;
+			int32 key;
+			uint32 keycode;
+			message->FindInt32("key",&key);
+			keycode = be_to_scan_codes[(uint8)key-1];
+			DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, input->context->settings->KeyboardType);
+
+			if (scancode)
+				freerdp_input_send_keyboard_event_ex(input, TRUE, scancode);
+					
+			break;
+		}
+		case B_UNMAPPED_KEY_UP:
+		case B_KEY_UP:
+		{
+			rdpInput* input = instance->input;
+
+			const char *bytes;
+			int32 key;
+			uint32 keycode;
+			message->FindInt32("key",&key);
+			keycode = be_to_scan_codes[(uint8)key-1];
+			DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, input->context->settings->KeyboardType);
+		
+			if (scancode)
+				freerdp_input_send_keyboard_event_ex(input, FALSE, scancode);
+					
+			break;
+		} 
+		case B_MOUSE_WHEEL_CHANGED:
+			{
+				rdpInput* input = instance->input;
+		 		BPoint pos = fb->GetLastMousePos();
+
+			 	float shift=0;
+				UINT16 flags;
+				
+			 	flags = PTR_FLAGS_WHEEL;
+
+			 	if(message->FindFloat("be:wheel_delta_y",&shift)==B_OK) {
+		        	if(shift<0) {
+						flags |= 0x0078;
+		        	}
+					if(shift>0) {
+						flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
+			        }
+				}
+				input->MouseEvent(input, flags, pos.x, pos.y);
+				break;
+			}
+//		case B_CLIPBOARD_CHANGED:
+//			{
+//			 break;
+//			}
+		case B_WINDOW_ACTIVATED:
+		case B_WORKSPACE_ACTIVATED:
+			{
+			 break;
+			}
+		default:
+			BWindow::MessageReceived(message);
+			break;		
+	}
+}
+
+
+void
+MainWindow::SetInstance(freerdp *inst)
+{
+	instance = inst;
+	fb->SetInstance(inst);
+}
+
+bool
+MainWindow::QuitRequested()
+{	
+	freerdp_abort_connect(instance);
+	return false;
+}
diff --git a/client/Haiku/MainWindow.h b/client/Haiku/MainWindow.h
new file mode 100644
index 0000000..709a2c0
--- /dev/null
+++ b/client/Haiku/MainWindow.h
@@ -0,0 +1,50 @@
+#ifndef _TEST_WINDOW_H
+#define _TEST_WINDOW_H
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+
+#include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/client/file.h>
+#include <freerdp/client/cmdline.h>
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/client/channels.h>
+#include <freerdp/channels/channels.h>
+#include <freerdp/locale/keyboard.h>
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <freerdp/log.h>
+
+}
+
+#include <Application.h>
+#include <Window.h>
+#include <View.h>
+#include <OS.h>
+
+#include "MainView.h"
+
+class MainWindow : public BWindow {
+	public:
+						MainWindow(BRect rect, const char* name, freerdp *instance);
+		virtual			~MainWindow();
+
+		virtual void 	MessageReceived(BMessage *message);
+		bool			QuitRequested();
+		
+		void 			SetInstance(freerdp *instance);
+		
+		FBView			*fb;
+	private:
+		freerdp 		*instance;
+};
+
+#endif
+
+
diff --git a/client/Haiku/ModuleOptions.cmake b/client/Haiku/ModuleOptions.cmake
new file mode 100644
index 0000000..130bfa1
--- /dev/null
+++ b/client/Haiku/ModuleOptions.cmake
@@ -0,0 +1,4 @@
+
+set(FREERDP_CLIENT_NAME "hfreerdp")
+set(FREERDP_CLIENT_PLATFORM "Haiku")
+set(FREERDP_CLIENT_VENDOR "FreeRDP")
diff --git a/client/Haiku/Resources.rdef b/client/Haiku/Resources.rdef
new file mode 100644
index 0000000..86dd149
--- /dev/null
+++ b/client/Haiku/Resources.rdef
@@ -0,0 +1,55 @@
+/*
+ * Resources.rdef
+ */
+
+resource app_signature "application/x-vnd.freerdp";
+
+resource app_flags B_MULTIPLE_LAUNCH;
+
+resource app_version {
+	major  = 2,
+	middle = 0,
+	minor  = 0,
+	variety = 0,
+	internal = 0,
+	short_info = "FreeRDP",
+	long_info = "FreeRDP"
+};
+
+resource(1, "close.png") #'PNG ' import "images/close.png";
+resource(2, "zoom.png") #'PNG ' import "images/zoom.png";
+
+resource vector_icon {
+	$"6E6369662803010000020016023CC7ED389BBFBA16553E39AF4977C842ADC700"
+	$"FFFFD3020016023C529D3753A2B8966F3D9D074B6044496AAF0047FFA0020016"
+	$"02BC4E75BC411A3C90D9BCA00C47587D4ABA850090FFD40200160238313C3B5C"
+	$"F0BFCD953C7AAB4C13943FCAF901ECFFC3054B04016B020006033E2F99387F17"
+	$"BA42DC3FF5B84A0E32482C90001D1E2C3D454658FF010101020006023879063B"
+	$"8224BE2CC73B10D94A1F6F49B89400242222FF9A9A9A020006033C69A6000000"
+	$"0000003E186148800049800000D4CECE58F3F3F3FFD9D9D90389FF0005000500"
+	$"0500030100000500033A3A4303F46E0C03010000020016023CC7ED389BBFBA16"
+	$"553E39AF4977C842ADC700FFFFD3020006023C529D3753A2B8966F3D9D074B60"
+	$"44496AAF00474747FFA5A0A002001602BC4E75BC411A3C90D9BCA00C47587D4A"
+	$"BA850090FFD40200160238313C3B5CF0BFCD953C7AAB4C13943FCAF901ECFFC3"
+	$"054B04017E020006033E2F99387F17BA42DC3FF5B84A0E32482C90001D1E2C3D"
+	$"454658FF010101020006023879063B8224BE2CC73B10D94A1F6F49B894002422"
+	$"22FF9A9A9A020006033C69A60000000000003E186148800049800000D4CECE58"
+	$"F3F3F3FFD9D9D9038AFF01050005000500030100000500033A3A43033A3A4303"
+	$"0100000300AAFF0300FF0003FFAA002200000A062228224A485E525252302C22"
+	$"0A042228483852302C220A044838485E525252300A042228224A485E48380A04"
+	$"453A45572446242C0A04B560442446242CB569B8200A0445544557244626440A"
+	$"0438263D234E28492C080438263D234E284E2E0A03492C4E284E2E0802425843"
+	$"C9830A06486054606052CA1BC5B95C4D524800000A0430303050505050300000"
+	$"000000000A04B570B86DB57DC12FC17CC729C17CBD8F0A062228224A485E5252"
+	$"52302C220A062228224A485E525252302C220A042228483852302C220A044838"
+	$"485E525252300A042228224A485E48380A042228224A485E48380A04453A4557"
+	$"2446242C0A04B560442446242CB569B8200A04B560442446242CB569B8200A04"
+	$"45544557244626440A0438263D234E28492C080438263D234E284E2E0A03492C"
+	$"4E284E2E0802425843C9830A04B570B86DB57DC12FC17CC729C17CBD8F0F0A06"
+	$"010C000A0001091001178400040A040108000A05010A000A0001011001178400"
+	$"040A010102000A03020405000A080106000A090107000A0A010B1815FF011782"
+	$"20040A020103000A110112023E00150000000000003E260D42CEDE44B6B40A26"
+	$"0112023E21EE0000000000003E260D483363471B5A0A250112023E0015000000"
+	$"0000003E260D42CEDE482DAD0A270112023E21EE0000000000003E41BA483363"
+	$"4901E6"
+};
diff --git a/client/Haiku/images/close.png b/client/Haiku/images/close.png
new file mode 100644
index 0000000000000000000000000000000000000000..584d790923a6dc766842e4baa2227f64aadf8d69
GIT binary patch
literal 163
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|S)MMAAsQ2>UNYosP~dTU*#5C1
z?&xHT3L*8qvmS)Rs^%_~Q2YFsS$|1!`it3(se32J%wO~`Wl79&Ge*bW6bJsAT;5qx
zyj8p8Sia;7Tn;+p{rlF+C$9^_wg>sMZ`w6A=~t~(WG?TLi_iZua`!Yw+VW_I0BvRP
MboFyt=akR{0P0ga`Tzg`

literal 0
HcmV?d00001

diff --git a/client/Haiku/images/zoom.png b/client/Haiku/images/zoom.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b796324247432ac5b5a9c595daf97cf4c2e33ab
GIT binary patch
literal 248
zcmV<U00;kxP)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM0002LNkl<ZD3O(s
zy$!-J5Jq267GWP(v{cm0zzoo(VFHSzz!DWpumClLCZPxtwnGu;NB)V#$%Spbr~7o5
zocF{^tdIU@3W)6kRq}nJ%Hbl5jP?^2d>T~(m?k3lv=wGL_)S2bcK<~Zn+v+O$JD4w
z=7(6M7ckPgvJNZ)kve)5dRo^uk}R^|9$dN;gjfxLl)0OGO6v+p-R=0fr%y=TVb9RL
y(0D?Gwt^cePMdcmQk({o_O=|SbiIe?JE<RZxEtBM=8k#*0000<MNUMnLSTYJn`goR

literal 0
HcmV?d00001

-- 
2.16.4

