From b97ce2e9738d5704064d1f1e44294a453cbf040c Mon Sep 17 00:00:00 2001
From: Adrien Destugues <pulkomandy@pulkomandy.tk>
Date: Mon, 30 Sep 2013 16:06:53 +0200
Subject: Reformat the existing haikuports patch to git format.


diff --git a/Makefile b/Makefile
index bf2b309..7902c56 100644
--- a/Makefile
+++ b/Makefile
@@ -196,6 +196,15 @@ DOSBIN_S =  dosbin_s
 # - Rename the executables to vimos2.exe, xxdos2.exe and teeos2.exe and copy
 #   them to here.
 # - "make os2bin".
+#
+# BeOS/Haiku OS
+# - Unpack the Unix "src", "extra" and "rt" archives.
+# - Aplly Haiku patch.
+# - Go to "src" directory and use "make autoconf" to regenerate configure script.
+# - Default "make [install]" will produce GUI version. 
+# - To prepare Haiku package use following command:
+#   	make haiku_package
+#	Both gui-less and full versions of vim will be packaged. 
 
 VIMVER	= vim-$(MAJOR).$(MINOR)
 VERSION = $(MAJOR)$(MINOR)
@@ -576,3 +585,37 @@ html: dist dist/$(COMMENT_HTML)
 farsi: dist dist/$(COMMENT_FARSI)
 	-rm -f dist/farsi$(VERSION).zip
 	zip -9 -rD -z dist/farsi$(VERSION).zip farsi < dist/$(COMMENT_FARSI)
+
+# Haiku package
+MACHINE=$(shell uname -m)
+ifeq ($(MACHINE), BePC)
+	MACHINE = x86-gcc$(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))
+endif
+DATE = `date +%F`
+PACKAGE_NAME := vim-$(VDOT)-$(MACHINE)-$(DATE)
+COMMENT = .OptionalPackageDescription
+DESCRIPTION = dist/boot/$(COMMENT)
+
+haiku_package: dist
+	-rm -rf dist/boot/
+	./configure --prefix=/boot/common \
+		--datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \
+		--mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \
+		--with-features=big --with-compiledby="$(COMPILEDBY)" --disable-nls
+	make clean; make install DESTDIR=`pwd`/dist
+	./configure --prefix=/boot/common  \
+		--datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \
+		--mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \
+		--with-features=big --disable-gui --with-compiledby="$(COMPILEDBY)" --disable-nls
+	make clean; make install DESTDIR=`pwd`/dist
+	-mkdir -p dist/boot/common/data/licenses
+	-cp runtime/doc/uganda.txt dist/boot/common/data/licenses/vim
+	ln -s -T vim dist/boot/common/bin/vi
+	echo "Package: Vim" > $(DESCRIPTION)
+	echo "Version: $(VDOT)-$(MACHINE)" >> $(DESCRIPTION)
+	echo "Copyright: Bram Moolenaar et al." >> $(DESCRIPTION)
+	echo "Description: Vi IMproved. Highly configurable text editor." >> $(DESCRIPTION)
+	echo "License: vim" >> $(DESCRIPTION)
+	echo "URL: http://www.vim.org/" >> $(DESCRIPTION)
+	cd dist/boot && zip -9 -r -z -y ../$(PACKAGE_NAME).zip * $(COMMENT) < $(COMMENT)
+
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 5403551..6f79962 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -6081,7 +6081,7 @@ arp			Compiled with ARP support (Amiga).
 autocmd			Compiled with autocommand support. |autocommand|
 balloon_eval		Compiled with |balloon-eval| support.
 balloon_multiline	GUI supports multiline balloons.
-beos			BeOS version of Vim.
+beos			BeOS/Haiku version of Vim.
 browse			Compiled with |:browse| support, and browse() will
 			work.
 builtin_terms		Compiled with some builtin terminals.
@@ -6133,6 +6133,7 @@ gui_mac			Compiled with Macintosh GUI.
 gui_motif		Compiled with Motif GUI.
 gui_photon		Compiled with Photon GUI.
 gui_win32		Compiled with MS Windows Win32 GUI.
+gui_beos		Compiled with BeOS/Haiku GUI.
 gui_win32s		idem, and Win32s system being used (Windows 3.1)
 gui_running		Vim is running in the GUI, or it will start soon.
 hangul_input		Compiled with Hangul input support. |hangul|
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index f9bbf78..7649e35 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -97,6 +97,7 @@ Recommended place for your personal GUI initializations:
 	OS/2		    $HOME/.gvimrc or $VIM/.gvimrc
 	MS-DOS and Win32    $HOME/_gvimrc or $VIM/_gvimrc
 	Amiga		    s:.gvimrc or $VIM/.gvimrc
+	Haiku		    $HOME/config/settings/vim/gvimrc
 
 There are a number of options which only have meaning in the GUI version of
 Vim.  These are 'guicursor', 'guifont', 'guipty' and 'guioptions'.  They are
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 4860eb2..be4c464 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -155,6 +155,7 @@ GUI ~
 |gui_w16.txt|	Windows 3.1 GUI
 |gui_w32.txt|	Win32 GUI
 |gui_x11.txt|	X11 GUI
+|gui_beos.txt|	BeOS/Haiku GUI
 
 Interfaces ~
 |if_cscop.txt|	using Cscope with Vim
@@ -181,7 +182,7 @@ Versions ~
 Remarks about specific systems ~
 |os_390.txt|	OS/390 Unix
 |os_amiga.txt|	Amiga
-|os_beos.txt|	BeOS and BeBox
+|os_beos.txt|	BeOS/Haiku and BeBox
 |os_dos.txt|	MS-DOS and MS-Windows NT/95 common items
 |os_mac.txt|	Macintosh
 |os_mint.txt|	Atari MiNT
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 1282a90..1fdbdd0 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3528,7 +3528,8 @@ A jump table for the options with a short description can be found at |Q_op|.
 		'guitablabel' can be used to change the text in the labels.
 		When 'e' is missing a non-GUI tab pages line may be used.
 		The GUI tabs are only supported on some systems, currently
-		GTK, Motif, Mac OS/X and MS-Windows.
+		GTK, Motif, Mac OS/X, Haiku and MS-Windows.
+
 								*'go-f'*
 	  'f'	Foreground: Don't use fork() to detach the GUI from the shell
 		where it was started.  Use this for programs that wait for the
@@ -5567,7 +5568,12 @@ A jump table for the options with a short description can be found at |Q_op|.
 						$VIM/vimfiles,
 						$VIMRUNTIME,
 						$VIM/vimfiles/after,
-						sys$login:vimfiles/after")
+						sys$login:vimfiles/after"
+					Haiku: "$BE_USER_SETTINGS/vim,
+						$VIM/vimfiles,
+						$VIMRUNTIME,
+						$VIM/vimfiles/after,
+						$BE_USER_SETTINGS/vim/after")
 			global
 			{not in Vi}
 	This is a list of directories which will be searched for runtime
@@ -6920,6 +6926,7 @@ A jump table for the options with a short description can be found at |Q_op|.
 				      in the GUI: "builtin_gui"
 					on Amiga: "amiga"
 					 on BeOS: "beos-ansi"
+					on Haiku: "xterm"
 					  on Mac: "mac-ansi"
 					 on MiNT: "vt52"
 				       on MS-DOS: "pcterm"
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 0632e8c..87c2181 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -756,6 +756,7 @@ accordingly.  Vim proceeds in this order:
 		OS/2		    $HOME/.vimrc or $VIM/.vimrc (or _vimrc)
 		MS-DOS and Win32    $HOME/_vimrc or $VIM/_vimrc
 		Amiga		    s:.vimrc or $VIM/.vimrc
+		Haiku		    $HOME/config/settings/vim/vimrc
 
 	If Vim was started with "-u filename", the file "filename" is used.
 	All following initializations until 4. are skipped.
@@ -791,6 +792,7 @@ accordingly.  Vim proceeds in this order:
 		    "$VIM/.vimrc"	(for OS/2 and Amiga) (*)
 		    "$HOME/_vimrc"	(for MS-DOS and Win32) (*)
 		    "$VIM/_vimrc"	(for MS-DOS and Win32) (*)
+		    "$HOME/.vimrc"	(for BeOS/Haiku) (*)
 		Note: For Unix, OS/2 and Amiga, when ".vimrc" does not exist,
 		"_vimrc" is also tried, in case an MS-DOS compatible file
 		system is used.  For MS-DOS and Win32 ".vimrc" is checked
@@ -880,6 +882,7 @@ sessions.  Put it in a place so that it will be found by 3b:
 	~/.vimrc	(Unix and OS/2)
 	s:.vimrc	(Amiga)
 	$VIM\_vimrc	(MS-DOS and Win32)
+	~/.vimrc	(BeOS/Haiku)
 Note that creating a vimrc file will cause the 'compatible' option to be off
 by default.  See |compatible-default|.
 
diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt
index 5d6706b..074acb6 100644
--- a/runtime/doc/vi_diff.txt
+++ b/runtime/doc/vi_diff.txt
@@ -139,6 +139,7 @@ Support for different systems.
 	- Atari MiNT
 	- VMS
 	- BeOS
+	- Haiku
 	- Macintosh
 	- Risc OS
 	- IBM OS/390
@@ -163,7 +164,7 @@ Graphical User Interface (GUI).				|gui|
 	define your own menus.  Better support for CTRL/SHIFT/ALT keys in
 	combination with special keys and mouse.  Supported for various
 	platforms, such as X11 (with Motif and Athena interfaces), GTK, Win32
-	(Windows 95 and later), BeOS, Amiga and Macintosh.
+	(Windows 95 and later), Haiku, Amiga and Macintosh.
 
 Multiple windows and buffers.				|windows.txt|
 	Vim can split the screen into several windows, each editing a
diff --git a/runtime/gvimrc_example.vim b/runtime/gvimrc_example.vim
index 5a5197e..e7e2538 100644
--- a/runtime/gvimrc_example.vim
+++ b/runtime/gvimrc_example.vim
@@ -9,6 +9,7 @@
 "	      for Amiga:  s:.gvimrc
 "  for MS-DOS and Win32:  $VIM\_gvimrc
 "	    for OpenVMS:  sys$login:.gvimrc
+"	   for Haiku OS:  ~/config/settings/vim/gvimrc
 
 " Make external commands work through a pipe instead of a pseudo-tty
 "set noguipty
diff --git a/runtime/vimrc_example.vim b/runtime/vimrc_example.vim
index b35100c..f5518d1 100644
--- a/runtime/vimrc_example.vim
+++ b/runtime/vimrc_example.vim
@@ -8,6 +8,7 @@
 "	      for Amiga:  s:.vimrc
 "  for MS-DOS and Win32:  $VIM\_vimrc
 "	    for OpenVMS:  sys$login:.vimrc
+"	   for Haiku OS:  ~/config/settings/vim/vimrc
 
 " When started as "evim", evim.vim will already have done these settings.
 if v:progname =~? "evim"
diff --git a/src/Makefile b/src/Makefile
index e582eed..985dfd2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1242,6 +1242,23 @@ NEXTAW_BUNDLE	=
 # too:
 #EXTRA_LIBS = /usr/openwin/lib/libXmu.sa -lm
 
+### BeOS GUI
+BEOSGUI_SRC	= gui.c gui_beos.cc pty.c
+BEOSGUI_OBJ	= objects/gui.o objects/gui_beos.o  objects/pty.o
+BEOSGUI_DEFS	= -DFEAT_GUI_BEOS
+BEOSGUI_IPATH	=
+BEOSGUI_LIBS_DIR =
+BEOSGUI_LIBS1	= -lbe -lroot -ltracker -ltranslation
+ifeq ($(strip $(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))), 4)
+BEOSGUI_LIBS1	+= -lsupc++
+endif
+BEOSGUI_LIBS2	=
+BEOSGUI_INSTALL = install_normal install_beos_extra
+BEOSGUI_TARGETS	= installglinks_beos
+BEOSGUI_MAN_TARGETS =  
+BEOSGUI_TESTTARGET = gui
+BEOSGUI_BUNDLE =
+
 # PHOTON GUI
 PHOTONGUI_SRC	= gui.c gui_photon.c pty.c
 PHOTONGUI_OBJ	= objects/gui.o objects/gui_photon.o objects/pty.o
@@ -2458,6 +2475,9 @@ objects/gui_at_sb.o: gui_at_sb.c
 objects/gui_athena.o: gui_athena.c
 	$(CCC) -o $@ gui_athena.c
 
+objects/gui_beos.o: gui_beos.cc
+	$(CCC) -o $@ gui_beos.cc
+
 objects/gui_beval.o: gui_beval.c
 	$(CCC) -o $@ gui_beval.c
 
@@ -2585,6 +2605,9 @@ objects/option.o: option.c
 objects/os_beos.o: os_beos.c
 	$(CCC) -o $@ os_beos.c
 
+objects/os_beos.rsrc: os_beos.rdef
+	cat $< | $(CCC) -E - | grep -v '^#' | rc -o "$@" -
+
 objects/os_qnx.o: os_qnx.c
 	$(CCC) -o $@ os_qnx.c
 
@@ -2738,6 +2761,56 @@ $(APPDIR)/Contents:
 
 
 ###############################################################################
+###
+### BeOS/Haiku OS installation
+###
+### This rule:
+###		- add resources to already installed vim binary to avoid stripping
+###			them during install;
+###		- copy rgb.txt to runtime directory;
+###		- update system MIME database with info about vim application.
+###
+install_beos_extra: $(DEST_BIN)/$(VIMTARGET) objects/os_beos.rsrc
+	xres -o $(DEST_BIN)/$(VIMTARGET) objects/os_beos.rsrc	
+	$(INSTALL_DATA) $(SCRIPTSOURCE)/rgb.txt $(DEST_RT)
+	mimeset	$(DEST_BIN)/$(VIMTARGET)
+
+###	
+###	List of g*-links that should be replaced with shell script equivalents.
+###	This solves the problem of them from Tracker.
+###
+BEOS_GLINKS = 	$(DEST_BIN)/$(GVIMTARGET) \
+				$(DEST_BIN)/$(GVIEWTARGET) \
+				$(DEST_BIN)/$(GVIMDIFFTARGET) \
+				$(DEST_BIN)/$(RGVIMTARGET) \
+				$(DEST_BIN)/$(RGVIEWTARGET)
+###	
+###	This rule:
+###		- Replace gvim link with copy of vim binary. 
+###		- Replace g*-links with shell script equivalents to solve the problem 
+###			of calling them from Tracker,
+###		- Add icon resources to mentioned g*-link shell scripts.
+###
+installglinks_beos: $(BEOS_GLINKS) install_beos_extra
+	@catattr -r "BEOS:ICON" $(DEST_BIN)/$(GVIMTARGET) > ~icon.attr
+	for i in $(BEOS_GLINKS); do \
+		rm $$i ; \
+		echo "#!/bin/sh" > $$i ; \
+		case $$i in \
+			$(DEST_BIN)/$(GVIMTARGET))     cp $(DEST_BIN)/$(VIMTARGET) $$i;; \
+			$(DEST_BIN)/$(GVIEWTARGET))    printf "%s -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+			$(DEST_BIN)/$(GVIMDIFFTARGET)) printf "%s -d %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+			$(DEST_BIN)/$(RGVIMTARGET))    printf "%s -Z %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+			$(DEST_BIN)/$(RGVIEWTARGET))   printf "%s -Z -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+			*) printf "%s %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+			esac ; \
+		chmod $(BINMOD) $$i ; \
+		addattr -f ~icon.attr  -t \'VICN\' BEOS:ICON $$i ; \
+	done
+	addattr -f ~icon.attr  -t \'VICN\' BEOS:ICON $(DEST_BIN)/$(VIMNAME)tutor
+	@rm ~icon.attr
+
+###############################################################################
 ### (automatically generated by 'make depend')
 ### Dependencies:
 objects/blowfish.o: blowfish.c vim.h auto/config.h feature.h os_unix.h \
diff --git a/src/configure.in b/src/configure.in
index 152313b..9161849 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -69,11 +69,13 @@ fi
 
 OS_EXTRA_SRC=""; OS_EXTRA_OBJ=""
 
-dnl Check for BeOS, which needs an extra source file
-AC_MSG_CHECKING(for BeOS)
+dnl Check for BeOS/Haiku, which needs an extra source file
+AC_MSG_CHECKING(for BeOS/Haiku)
 case `uname` in
     BeOS)	OS_EXTRA_SRC=os_beos.c; OS_EXTRA_OBJ=objects/os_beos.o
 		BEOS=yes; AC_MSG_RESULT(yes);;
+    Haiku)	OS_EXTRA_SRC=os_beos.c; OS_EXTRA_OBJ=objects/os_beos.o
+		BEOS=yes; AC_MSG_RESULT(yes);;
     *)		BEOS=no; AC_MSG_RESULT(no);;
 esac
 
@@ -1406,7 +1408,7 @@ AC_ARG_ENABLE(netbeans,
 if test "$enable_netbeans" = "yes"; then
   AC_MSG_RESULT(no)
   dnl On Solaris we need the socket and nsl library.
-  AC_CHECK_LIB(socket, socket)
+  AC_CHECK_LIB(network, socket)
   AC_CHECK_LIB(nsl, gethostbyname)
   AC_MSG_CHECKING(whether compiling netbeans integration is possible)
   AC_TRY_LINK([
@@ -1614,11 +1616,11 @@ else
   fi
 fi
 
-test "x$with_x" = xno -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
+test "x$with_x" = xno -a "x$BEOS" != "xyes" -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
 
 AC_MSG_CHECKING(--enable-gui argument)
 AC_ARG_ENABLE(gui,
- [  --enable-gui[=OPTS]     X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto")
+ [  --enable-gui[=OPTS]     X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/motif/athena/neXtaw/beos/photon/carbon]], , enable_gui="auto")
 
 dnl Canonicalize the --enable-gui= argument so that it can be easily compared.
 dnl Do not use character classes for portability with old tools.
@@ -1632,10 +1634,24 @@ SKIP_MOTIF=YES
 SKIP_ATHENA=YES
 SKIP_NEXTAW=YES
 SKIP_PHOTON=YES
+SKIP_BEOS=YES
 SKIP_CARBON=YES
 GUITYPE=NONE
 
-if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
+
+if test "x$BEOS" = "xyes"; then
+  SKIP_BEOS=
+  case "$enable_gui_canon" in
+    no)		AC_MSG_RESULT(no GUI support)
+		SKIP_BEOS=YES ;;
+    yes|"")	AC_MSG_RESULT(yes - automatic GUI support) ;;
+    auto)	AC_MSG_RESULT(auto - automatic GUI support) ;;
+    beos)	AC_MSG_RESULT(BeOS GUI support) ;;
+    *)		AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
+		SKIP_BEOS=YES ;;
+  esac
+
+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
   SKIP_PHOTON=
   case "$enable_gui_canon" in
     no)		AC_MSG_RESULT(no GUI support)
@@ -1786,6 +1802,7 @@ if test "x$MACOSX" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then
   SKIP_ATHENA=YES;
   SKIP_NEXTAW=YES;
   SKIP_PHOTON=YES;
+  SKIP_BEOS=YES
   SKIP_CARBON=YES
 fi
 
@@ -2277,6 +2294,11 @@ if test "x$GUITYPE:$enable_fontset" = "xGTK:yes"; then
   enable_fontset="no"
 fi
 
+dnl There is no test for the BeOS GUI, if it's selected it's used
+if test -z "$SKIP_BEOS"; then
+  GUITYPE=BEOSGUI
+fi
+
 if test -z "$SKIP_PHOTON"; then
   GUITYPE=PHOTONGUI
 fi
diff --git a/src/eval.c b/src/eval.c
index fc01006..44c02e9 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -11722,6 +11722,9 @@ f_has(argvars, rettv)
 #ifdef __BEOS__
 	"beos",
 #endif
+#ifdef __HAIKU__
+	"haiku",
+#endif
 #ifdef MSDOS
 # ifdef DJGPP
 	"dos32",
@@ -11894,6 +11897,9 @@ f_has(argvars, rettv)
 #ifdef FEAT_GUI_GNOME
 	"gui_gnome",
 #endif
+#ifdef FEAT_GUI_BEOS
+	"gui_beos",
+#endif
 #ifdef FEAT_GUI_MAC
 	"gui_mac",
 #endif
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index b338ed5..07f631b 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -6841,6 +6841,7 @@ ex_shell(eap)
 	|| (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \
 	|| defined(FEAT_GUI_MSWIN) \
 	|| defined(FEAT_GUI_MAC) \
+	|| defined(FEAT_GUI_BEOS) \
 	|| defined(PROTO)
 
 /*
diff --git a/src/feature.h b/src/feature.h
index ea79758..577e7c0 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -659,6 +659,14 @@
 /* #define FEAT_MBYTE_IME */
 # endif
 
+/*
+ * +multi_byte_ime	BeOS/Haiku input method support.  
+ *						Requires +multi_byte.
+ */
+#if defined(FEAT_BIG) && defined(FEAT_GUI_BEOS) && !defined(FEAT_MBYTE_IME)
+ #define FEAT_MBYTE_IME 
+# endif
+
 #if defined(FEAT_MBYTE_IME) && !defined(FEAT_MBYTE)
 # define FEAT_MBYTE
 #endif
@@ -768,7 +776,8 @@
 		|| defined(FEAT_GUI_MSWIN) \
 		|| ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \
 			&& defined(HAVE_XPM)) \
-		|| defined(FEAT_GUI_PHOTON))
+		|| defined(FEAT_GUI_PHOTON)\
+		|| defined(FEAT_GUI_BEOS)) 
 # define FEAT_TOOLBAR
 #endif
 
@@ -784,6 +793,7 @@
     && (defined(FEAT_GUI_GTK) \
 	|| (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \
 	|| defined(FEAT_GUI_MAC) \
+	|| defined(FEAT_GUI_BEOS) \
 	|| (defined(FEAT_GUI_MSWIN) && !defined(WIN16) \
 	    && (!defined(_MSC_VER) || _MSC_VER > 1020)))
 # define FEAT_GUI_TABLINE
@@ -795,7 +805,7 @@
  */
 #if defined(FEAT_NORMAL)
 # define FEAT_BROWSE_CMD
-# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_BEOS) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
 #  define FEAT_BROWSE
 # endif
 #endif
@@ -810,6 +820,7 @@
 		&& defined(HAVE_X11_XPM_H)) \
 	|| defined(FEAT_GUI_GTK) \
 	|| defined(FEAT_GUI_PHOTON) \
+	|| defined(FEAT_GUI_BEOS) \
 	|| defined(FEAT_GUI_MSWIN) \
 	|| defined(FEAT_GUI_MAC)
 #  define FEAT_CON_DIALOG
@@ -827,7 +838,8 @@
 #if defined(FEAT_GUI_DIALOG) && \
 	(defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
 	 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \
-	 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
+	 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))\
+	 || defined(FEAT_GUI_BEOS)
 # define FEAT_GUI_TEXTDIALOG
 #endif
 
diff --git a/src/gui.c b/src/gui.c
index 87930c6..537bd7b 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -59,7 +59,7 @@ static int can_update_cursor = TRUE; /* can display the cursor */
 gui_start()
 {
     char_u	*old_term;
-#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOS_X)
+#if defined(UNIX) && !defined(__HAIKU__) && !defined(__BEOS__) && !defined(MACOS_X)
 # define MAY_FORK
     int		dofork = TRUE;
 #endif
@@ -275,7 +275,7 @@ gui_init_check()
     gui.menu_width = 0;
 # endif
 #endif
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_BEOS))
     gui.toolbar_height = 0;
 #endif
 #if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF)
@@ -1167,10 +1167,10 @@ gui_position_components(total_width)
 	text_area_y += gui.tabline_height;
 #endif
 
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_BEOS))
     if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
     {
-# ifdef FEAT_GUI_ATHENA
+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_BEOS) 
 	gui_mch_set_toolbar_pos(0, text_area_y,
 				gui.menu_width, gui.toolbar_height);
 # endif
@@ -1178,6 +1178,13 @@ gui_position_components(total_width)
     }
 #endif
 
+# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_BEOS))
+	gui_mch_set_tabline_pos(0, text_area_y,
+				gui.menu_width, gui.tabline_height);
+    if (gui_has_tabline())
+	text_area_y += gui.tabline_height;
+#endif
+
     text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2;
     text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2;
 
@@ -1249,7 +1256,7 @@ gui_get_base_height()
 #  endif
 # endif
 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
-	|| defined(FEAT_GUI_MOTIF))
+	|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_BEOS))
     if (gui_has_tabline())
 	base_height += gui.tabline_height;
 # endif
@@ -1292,7 +1299,11 @@ gui_resize_shell(pixel_width, pixel_height)
 again:
     busy = TRUE;
 
-    /* Flush pending output before redrawing */
+#ifdef FEAT_GUI_BEOS
+    vim_lock_screen();
+#endif
+
+	/* Flush pending output before redrawing */
     out_flush();
 
     gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width;
@@ -1314,7 +1325,11 @@ again:
 	    || gui.num_rows != Rows || gui.num_cols != Columns)
 	shell_resized();
 
-    gui_update_scrollbars(TRUE);
+#ifdef FEAT_GUI_BEOS
+    vim_unlock_screen();
+#endif
+
+	gui_update_scrollbars(TRUE);
     gui_update_cursor(FALSE, TRUE);
 #if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK)
     xim_set_status_area();
@@ -4055,9 +4070,9 @@ gui_update_scrollbars(force)
 		y += gui.menu_height;
 #endif
 
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_BEOS))
 	    if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
-# ifdef FEAT_GUI_ATHENA
+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_BEOS)
 		y += gui.toolbar_height;
 # else
 #  ifdef FEAT_GUI_MSWIN
@@ -4066,7 +4081,8 @@ gui_update_scrollbars(force)
 # endif
 #endif
 
-#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN)
+		//XXX
+#if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_BEOS))
 	    if (gui_has_tabline())
 		y += gui.tabline_height;
 #endif
@@ -4811,7 +4827,8 @@ ex_gui(eap)
 }
 
 #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) \
-	|| defined(FEAT_GUI_PHOTON)) && defined(FEAT_TOOLBAR)) || defined(PROTO)
+	|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_BEOS)) \
+		&& defined(FEAT_TOOLBAR)) || defined(PROTO)
 /*
  * This is shared between Athena, Motif and GTK.
  */
diff --git a/src/gui.h b/src/gui.h
index 149603c..9feee3a 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -33,6 +33,10 @@
 # include <gtk/gtk.h>
 #endif
 
+#ifdef FEAT_GUI_BEOS
+# include "gui_beos.h"
+#endif
+
 #ifdef FEAT_GUI_MAC
 # include <Types.h>
 /*# include <Memory.h>*/
@@ -83,7 +87,7 @@
  * GUIs that support dropping files on a running Vim.
  */
 #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) \
-	|| defined(FEAT_GUI_GTK)
+	|| defined(FEAT_GUI_BEOS) || defined(FEAT_GUI_GTK)
 # define HAVE_DROP_FILE
 #endif
 
@@ -216,6 +220,9 @@ typedef struct GuiScrollbar
 				   scroll_shift is set to the number of shifts
 				   to reduce the count.  */
 #endif
+#if FEAT_GUI_BEOS
+    VimScrollBar *id;		/* Pointer to real scroll bar */
+#endif
 #ifdef FEAT_GUI_MAC
     ControlHandle id;		/* A handle to the scrollbar */
 #endif
@@ -412,7 +419,7 @@ typedef struct Gui
 
 #if defined(FEAT_GUI_TABLINE) \
 	&& (defined(FEAT_GUI_W32) || defined(FEAT_GUI_MOTIF) \
-		|| defined(FEAT_GUI_MAC))
+		|| defined(FEAT_GUI_MAC) || defined(FEAT_GUI_BEOS))
     int		tabline_height;
 #endif
 
@@ -421,7 +428,7 @@ typedef struct Gui
 #endif
 
 #if defined(FEAT_TOOLBAR) \
-	&& (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
+	&& (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_BEOS))
     int		toolbar_height;	    /* height of the toolbar */
 #endif
 
@@ -442,6 +449,14 @@ typedef struct Gui
     guicolor_T	currSpColor;	    /* Current special text color */
 #endif
 
+#ifdef FEAT_GUI_BEOS
+    VimApp     *vimApp;
+    VimWindow  *vimWindow;
+    VimFormView *vimForm;
+    VimTextAreaView *vimTextArea;
+    int		vdcmp;		    /* Vim Direct Communication Message Port */
+#endif
+
 #ifdef FEAT_GUI_MAC
     WindowPtr	VimWindow;
     MenuHandle	MacOSHelpMenu;	    /* Help menu provided by the MacOS */
diff --git a/src/gui_beos.cc b/src/gui_beos.cc
new file mode 100644
index 0000000..ceafd40
--- /dev/null
+++ b/src/gui_beos.cc
@@ -0,0 +1,4868 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved			by Bram Moolenaar
+ *			    BeBox GUI support Copyright 1998 by Olaf Seibert.
+ *			    All Rights Reserved.
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * BeOS GUI.
+ *
+ * GUI support for the Buzzword Enhanced Operating System.
+ *
+ * Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99
+ *
+ * Haiku support by Siarzhuk Zharski <imker<at>gmx.li> Apr-Mai 2009
+ *
+ */
+
+/*
+ * Structure of the BeOS GUI code:
+ *
+ * There are 3 threads.
+ * 1. The initial thread. In gui_mch_prepare() this gets to run the
+ *    BApplication message loop. But before it starts doing that,
+ *    it creates thread 2
+ * 2. The main() thread. This thread is created in gui_mch_prepare()
+ *    and its purpose in life is to call main(argc, argv) again.
+ *    This thread is doing the bulk of the work.
+ * 3. Sooner or later, a window is opened by the main() thread. This
+ *    causes a second message loop to be created: the window thread.
+ *
+ * == alternatively ===
+ *
+ * #if RUN_BAPPLICATION_IN_NEW_THREAD...
+ *
+ * 1. The initial thread. In gui_mch_prepare() this gets to spawn
+ *    thread 2. After doing that, it returns to main() to do the
+ *    bulk of the work, being the main() thread.
+ * 2. Runs the BApplication.
+ * 3. The window thread, just like in the first case.
+ *
+ * This second alternative is cleaner from Vim's viewpoint. However,
+ * the BeBook seems to assume everywhere that the BApplication *must*
+ * run in the initial thread. So perhaps doing otherwise is very wrong.
+ *
+ * However, from a B_SINGLE_LAUNCH viewpoint, the first is better.
+ * If Vim is marked "Single Launch" in its application resources,
+ * and a file is dropped on the Vim icon, and another Vim is already
+ * running, the file is passed on to the earlier Vim. This happens
+ * in BApplication::Run(). So we want Vim to terminate if
+ * BApplication::Run() terminates. (See the BeBook, on BApplication.
+ * However, it seems that the second copy of Vim isn't even started
+ * in this case... which is for the better since I wouldn't know how
+ * to detect this case.)
+ *
+ * Communication between these threads occurs mostly by translating
+ * BMessages that come in and posting an appropriate translation on
+ * the VDCMP (Vim Direct Communication Message Port). Therefore the
+ * actions required for keypresses and window resizes, etc, are mostly
+ * performed in the main() thread.
+ *
+ * A notable exception to this is the Draw() event. The redrawing of
+ * the window contents is performed asynchronously from the window
+ * thread. To make this work correctly, a locking protocol is used when
+ * any thread is accessing the essential variables that are used by
+ * the window thread.
+ *
+ * This locking protocol consists of locking Vim's window. This is both
+ * convenient and necessary.
+ */
+
+extern "C" {
+
+#include <float.h>
+#include <assert.h>
+#include "vim.h"
+#include "globals.h"
+#include "proto.h"
+#include "version.h"
+
+}	/* extern "C" */
+
+/* ---------------- start of header part ---------------- */
+
+#include <be/app/MessageQueue.h>
+#include <be/app/Clipboard.h>
+#include <be/app/Roster.h>
+#include <be/kernel/OS.h>
+#include <be/support/Beep.h>
+#include <be/interface/View.h>
+#include <be/interface/Window.h>
+#include <be/interface/Box.h>
+#include <be/interface/TabView.h>
+#include <be/interface/MenuBar.h>
+#include <be/interface/MenuItem.h>
+#include <be/interface/PopUpMenu.h>
+#include <be/interface/ScrollBar.h>
+#include <be/interface/Region.h>
+#include <be/interface/Screen.h>
+#include <be/interface/Bitmap.h>
+#include <be/interface/TextView.h>
+#include <be/interface/TextControl.h>
+#include <be/interface/Font.h>
+#include <be/interface/Button.h>
+#include <be/interface/PictureButton.h>
+#include <be/interface/Alert.h>
+#include <be/interface/Input.h>
+#include <be/storage/Path.h>
+#include <be/storage/Directory.h>
+#include <be/storage/Entry.h>
+#include <be/storage/FilePanel.h>
+#include <be/storage/FindDirectory.h>
+#include <be/storage/File.h>
+#include <be/storage/Resources.h>
+#include <be/app/Application.h>
+#include <be/support/Debug.h>
+#include <be/support/String.h>
+#include <be/support/SupportDefs.h>
+#include <be/translation/TranslationUtils.h>
+#include <be/translation/TranslatorFormats.h>
+#include <posix/syslog.h>
+
+#ifdef __HAIKU__
+#include <IconUtils.h>
+#endif
+
+class VimApp;
+class VimFormView;
+class VimTextAreaView;
+class VimWindow;
+class VimToolbar;
+class VimTabLine;
+
+extern key_map *keyMap;
+extern char *keyMapChars;
+
+extern int main(int argc, char **argv);
+
+#ifndef B_MAX_PORT_COUNT
+#define B_MAX_PORT_COUNT    255
+#endif
+
+/*
+ * VimApp seems comparable to the X "vimShell"
+ */
+class VimApp: public BApplication
+{
+	typedef BApplication Inherited;
+	public:
+	VimApp(const char *appsig);
+	~VimApp();
+
+	// callbacks:
+#if 0
+	virtual void DispatchMessage(BMessage *m, BHandler *h)
+	{
+		m->PrintToStream();
+		Inherited::DispatchMessage(m, h);
+	}
+#endif
+	virtual void ReadyToRun();
+	virtual void ArgvReceived(int32 argc, char **argv);
+	virtual void RefsReceived(BMessage *m);
+	virtual bool QuitRequested();
+	virtual void MessageReceived(BMessage *m);
+
+	static void SendRefs(BMessage *m, bool changedir);
+
+	sem_id		fFilePanelSem;
+	BFilePanel*	fFilePanel;
+	BPath		fBrowsedPath;
+	private:
+};
+
+class VimWindow: public BWindow
+{
+	typedef BWindow Inherited;
+	public:
+	VimWindow();
+	~VimWindow();
+
+	//    virtual void DispatchMessage(BMessage *m, BHandler *h);
+	virtual void WindowActivated(bool active);
+	virtual bool QuitRequested();
+
+	VimFormView		*formView;
+
+	private:
+	void init();
+
+};
+
+class VimFormView: public BView
+{
+	typedef BView Inherited;
+	public:
+	VimFormView(BRect frame);
+	~VimFormView();
+
+	// callbacks:
+	virtual void AllAttached();
+	virtual void FrameResized(float new_width, float new_height);
+
+#define MENUBAR_MARGIN	1
+	float MenuHeight() const
+	{ return menuBar ? menuBar->Frame().Height() + MENUBAR_MARGIN: 0; }
+	BMenuBar *MenuBar() const
+	{ return menuBar; }
+
+	private:
+	void init(BRect);
+
+	BMenuBar		*menuBar;
+	VimTextAreaView	*textArea;
+
+#ifdef FEAT_TOOLBAR
+	public:
+	float ToolbarHeight() const;
+	VimToolbar *ToolBar() const
+	{ return toolBar; }
+	private:
+	VimToolbar		*toolBar;
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+	public:
+	VimTabLine *TabLine() const	{ return tabLine; }
+	bool IsShowingTabLine() const { return showingTabLine; }
+	void SetShowingTabLine(bool showing) { showingTabLine = showing;	}
+	float TablineHeight() const;
+	private:
+	VimTabLine	*tabLine;
+	int	showingTabLine;
+#endif
+};
+
+class VimTextAreaView: public BView
+{
+	typedef BView Inherited;
+	public:
+	VimTextAreaView(BRect frame);
+	~VimTextAreaView();
+
+	// callbacks:
+	virtual void Draw(BRect updateRect);
+	virtual void KeyDown(const char *bytes, int32 numBytes);
+	virtual void MouseDown(BPoint point);
+	virtual void MouseUp(BPoint point);
+	virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message);
+	virtual void MessageReceived(BMessage *m);
+
+	// own functions:
+	int mchInitFont(char_u *name);
+	void mchDrawString(int row, int col, char_u *s, int len, int flags);
+	void mchClearBlock(int row1, int col1, int row2, int col2);
+	void mchClearAll();
+	void mchDeleteLines(int row, int num_lines);
+	void mchInsertLines(int row, int num_lines);
+
+	static void guiSendMouseEvent(int button, int x, int y, int repeated_click, int_u modifiers);
+	static void guiMouseMoved(int x, int y);
+	static void guiBlankMouse(bool should_hide);
+	static int_u mouseModifiersToVim(int32 beModifiers);
+
+	int32 mouseDragEventCount;
+
+#ifdef FEAT_MBYTE_IME
+	void DrawIMString(void);
+#endif
+
+	private:
+	void init(BRect);
+
+	int_u	    vimMouseButton;
+	int_u	    vimMouseModifiers;
+
+#ifdef FEAT_MBYTE_IME
+	struct {
+		BMessenger* messenger;
+		BMessage* message;
+		BPoint location;
+		int row;
+		int col;
+		int count;
+	} IMData;
+#endif
+};
+
+class VimScrollBar: public BScrollBar
+{
+	typedef BScrollBar Inherited;
+	public:
+	VimScrollBar(scrollbar_T *gsb, orientation posture);
+	~VimScrollBar();
+
+	virtual void ValueChanged(float newValue);
+	virtual void MouseUp(BPoint where);
+	void SetValue(float newval);
+	scrollbar_T *getGsb()
+	{ return gsb; }
+
+	int32	    scrollEventCount;
+
+	private:
+	scrollbar_T *gsb;
+	float	ignoreValue;
+};
+
+
+#ifdef FEAT_TOOLBAR
+
+class VimToolbar : public BBox
+{
+	static BBitmap *normalButtonsBitmap;
+	static BBitmap *grayedButtonsBitmap;
+
+	BBitmap *LoadVimBitmap(const char* fileName);
+	bool GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed);
+	bool ModifyBitmapToGrayed(BBitmap *bitmap);
+
+	BList fButtonsList;
+	void InvalidateLayout();
+
+	public:
+	VimToolbar(BRect frame, const char * name);
+	~VimToolbar();
+
+	bool PrepareButtonBitmaps();
+
+	bool AddButton(int32 index, vimmenu_T *menu);
+	bool RemoveButton(vimmenu_T *menu);
+	bool GrayButton(vimmenu_T *menu, int grey);
+
+	float ToolbarHeight() const;
+	virtual void AttachedToWindow();
+};
+
+BBitmap *VimToolbar::normalButtonsBitmap    = NULL;
+BBitmap *VimToolbar::grayedButtonsBitmap  = NULL;
+
+const float ToolbarMargin = 3.;
+const float ButtonMargin  = 3.;
+
+#endif /*FEAT_TOOLBAR*/
+
+#ifdef FEAT_GUI_TABLINE
+
+class VimTabLine : public BTabView
+{
+	public:
+		class VimTab : public BTab {
+			public:
+				VimTab() : BTab(new BView(BRect(), "-Empty-", 0, 0)) {}
+
+			virtual void Select(BView* owner);
+		};
+
+		VimTabLine(BRect r) : BTabView(r, "vimTabLine", B_WIDTH_FROM_LABEL,
+			   B_FOLLOW_LEFT | B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS) {}
+	
+	float TablineHeight() const;
+	virtual void MouseDown(BPoint point);
+};
+
+#endif //FEAT_GUI_TABLINE
+
+
+/*
+ * For caching the fonts that are used;
+ * Vim seems rather sloppy in this regard.
+ */
+class VimFont: public BFont
+{
+	typedef BFont Inherited;
+	public:
+	VimFont();
+	VimFont(const VimFont *rhs);
+	VimFont(const BFont *rhs);
+	VimFont(const VimFont &rhs);
+	~VimFont();
+
+	VimFont *next;
+	int refcount;
+	char_u *name;
+
+	private:
+	void init();
+};
+
+#if defined(FEAT_GUI_DIALOG)
+
+class VimDialog : public BWindow
+{
+	typedef BWindow Inherited;
+
+	BButton* _CreateButton(int32 which, const char* label);
+
+	public:
+	VimDialog(int type, const char *title, const char *message,
+			const char *buttons, int dfltbutton, const char *textfield);
+	~VimDialog();
+
+	int Go();
+
+	virtual void MessageReceived(BMessage *msg);
+
+	private:
+	sem_id			fDialogSem;
+	int				fDialogValue;
+	BList			fButtonsList;
+	BTextView*		fMessageView;
+	BTextControl*	fInputControl;
+	const char*		fInputValue;
+};
+
+class VimDialogView : public BView 
+{
+	typedef BView Inherited;
+	public:
+	VimDialogView(BRect frame);
+	~VimDialogView();
+
+	virtual void Draw(BRect updateRect);
+
+	void InitIcon(int32 type);
+
+	BBitmap*	fIconBitmap;
+};
+
+#endif /* FEAT_GUI_DIALOG */
+
+/* ---------------- end of GUI classes ---------------- */
+
+struct MainArgs {
+	int		 argc;
+	char	**argv;
+};
+
+/*
+ * These messages are copied through the VDCMP.
+ * Therefore they ought not to have anything fancy.
+ * They must be of POD type (Plain Old Data)
+ * as the C++ standard calls them.
+ */
+
+#define	KEY_MSG_BUFSIZ	7
+#if KEY_MSG_BUFSIZ < MAX_KEY_CODE_LEN
+#error Increase KEY_MSG_BUFSIZ!
+#endif
+
+struct VimKeyMsg {
+	char_u	length;
+	char_u	chars[KEY_MSG_BUFSIZ];	/* contains Vim encoding */
+#ifdef FEAT_MBYTE
+	bool    csi_escape;
+#endif
+};
+
+struct VimResizeMsg {
+	int		width;
+	int		height;
+};
+
+struct VimScrollBarMsg {
+	VimScrollBar *sb;
+	long	value;
+	int		stillDragging;
+};
+
+struct VimMenuMsg {
+	vimmenu_T	*guiMenu;
+};
+
+struct VimMouseMsg {
+	int		button;
+	int		x;
+	int		y;
+	int		repeated_click;
+	int_u	modifiers;
+};
+
+struct VimMouseMovedMsg {
+	int		x;
+	int		y;
+};
+
+struct VimFocusMsg {
+	bool	active;
+};
+
+struct VimRefsMsg {
+	BMessage   *message;
+	bool	changedir;
+};
+
+struct VimTablineMsg {
+	int		index;
+};
+
+struct VimTablineMenuMsg {
+	int		index;
+	int		event;
+};
+
+struct VimMsg {
+	enum VimMsgType {
+		Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu
+	};
+
+	union {
+		struct VimKeyMsg	Key;
+		struct VimResizeMsg	NewSize;
+		struct VimScrollBarMsg	Scroll;
+		struct VimMenuMsg	Menu;
+		struct VimMouseMsg	Mouse;
+		struct VimMouseMovedMsg	MouseMoved;
+		struct VimFocusMsg	Focus;
+		struct VimRefsMsg	Refs;
+		struct VimTablineMsg	Tabline;
+		struct VimTablineMenuMsg	TablineMenu;
+	} u;
+};
+
+#define RGB(r, g, b)	((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0)
+#define GUI_TO_RGB(g)	{ (g) >> 16, (g) >> 8, (g) >> 0, 255 }
+
+/* ---------------- end of header part ---------------- */
+
+static struct specialkey
+{
+	uint16  BeKeys;
+#define KEY(a,b)	((a)<<8|(b))
+#define K(a)		KEY(0,a)		    // for ASCII codes
+#define F(b)		KEY(1,b)		    // for scancodes
+	char_u  vim_code0;
+	char_u  vim_code1;
+} special_keys[] =
+{
+	{K(B_UP_ARROW),	    'k', 'u'},
+	{K(B_DOWN_ARROW),	    'k', 'd'},
+	{K(B_LEFT_ARROW),	    'k', 'l'},
+	{K(B_RIGHT_ARROW),	    'k', 'r'},
+	{K(B_BACKSPACE),	    'k', 'b'},
+	{K(B_INSERT),	    'k', 'I'},
+	{K(B_DELETE),	    'k', 'D'},
+	{K(B_HOME),		    'k', 'h'},
+	{K(B_END),		    '@', '7'},
+	{K(B_PAGE_UP),	    'k', 'P'},	    /* XK_Prior */
+	{K(B_PAGE_DOWN),	    'k', 'N'},	    /* XK_Next, */
+
+#define FIRST_FUNCTION_KEY  11
+	{F(B_F1_KEY),	    'k', '1'},
+	{F(B_F2_KEY),	    'k', '2'},
+	{F(B_F3_KEY),	    'k', '3'},
+	{F(B_F4_KEY),	    'k', '4'},
+	{F(B_F5_KEY),	    'k', '5'},
+	{F(B_F6_KEY),	    'k', '6'},
+	{F(B_F7_KEY),	    'k', '7'},
+	{F(B_F8_KEY),	    'k', '8'},
+	{F(B_F9_KEY),	    'k', '9'},
+	{F(B_F10_KEY),	    'k', ';'},
+
+	{F(B_F11_KEY),	    'F', '1'},
+	{F(B_F12_KEY),	    'F', '2'},
+	//  {XK_F13,		    'F', '3'},		/* would be print screen/ */
+	/* sysreq */
+	{F(0x0F),		    'F', '4'},		/* scroll lock */
+	{F(0x10),		    'F', '5'},		/* pause/break */
+	//  {XK_F16,	    'F', '6'},
+	//  {XK_F17,	    'F', '7'},
+	//  {XK_F18,	    'F', '8'},
+	//  {XK_F19,	    'F', '9'},
+	//  {XK_F20,	    'F', 'A'},
+	//
+	//  {XK_F21,	    'F', 'B'},
+	//  {XK_F22,	    'F', 'C'},
+	//  {XK_F23,	    'F', 'D'},
+	//  {XK_F24,	    'F', 'E'},
+	//  {XK_F25,	    'F', 'F'},
+	//  {XK_F26,	    'F', 'G'},
+	//  {XK_F27,	    'F', 'H'},
+	//  {XK_F28,	    'F', 'I'},
+	//  {XK_F29,	    'F', 'J'},
+	//  {XK_F30,	    'F', 'K'},
+	//
+	//  {XK_F31,	    'F', 'L'},
+	//  {XK_F32,	    'F', 'M'},
+	//  {XK_F33,	    'F', 'N'},
+	//  {XK_F34,	    'F', 'O'},
+	//  {XK_F35,	    'F', 'P'},	    /* keysymdef.h defines up to F35 */
+
+	//  {XK_Help,	    '%', '1'},	    /* XK_Help */
+	{F(B_PRINT_KEY),	    '%', '9'},
+
+#if 0
+	/* Keypad keys: */
+	{F(0x48),	    'k', 'l'},	    /* XK_KP_Left */
+	{F(0x4A),	    'k', 'r'},	    /* XK_KP_Right */
+	{F(0x38),	    'k', 'u'},	    /* XK_KP_Up */
+	{F(0x59),	    'k', 'd'},	    /* XK_KP_Down */
+	{F(0x64),	    'k', 'I'},	    /* XK_KP_Insert */
+	{F(0x65),	    'k', 'D'},	    /* XK_KP_Delete */
+	{F(0x37),	    'k', 'h'},	    /* XK_KP_Home */
+	{F(0x58),	    '@', '7'},	    /* XK_KP_End */
+	{F(0x39),	    'k', 'P'},	    /* XK_KP_Prior */
+	{F(0x60),	    'k', 'N'},	    /* XK_KP_Next */
+	{F(0x49),	    '&', '8'},	    /* XK_Undo, keypad 5 */
+#endif
+
+	/* End of list marker: */
+	{0,			    0, 0}
+};
+
+#define NUM_SPECIAL_KEYS    (sizeof(special_keys)/sizeof(special_keys[0]))
+
+/* ---------------- VimApp ---------------- */
+
+	static void
+docd(BPath &path)
+{
+	mch_chdir((char *)path.Path());
+	/* Do this to get the side effects of a :cd command */
+	do_cmdline_cmd((char_u *)"cd .");
+}
+
+/*
+ * Really handle dropped files and folders.
+ */
+	static void
+RefsReceived(BMessage *m, bool changedir)
+{
+	uint32 type;
+	int32 count;
+
+	//m->PrintToStream();
+	switch (m->what) {
+		case B_REFS_RECEIVED:
+		case B_SIMPLE_DATA:
+			m->GetInfo("refs", &type, &count);
+			if (type != B_REF_TYPE)
+				goto bad;
+			break;
+		case B_ARGV_RECEIVED:
+			m->GetInfo("argv", &type, &count);
+			if (type != B_STRING_TYPE)
+				goto bad;
+			if (changedir) {
+				char *dirname;
+				if (m->FindString("cwd", (const char **) &dirname) == B_OK) {
+					chdir(dirname);
+					do_cmdline_cmd((char_u *)"cd .");
+				}
+			}
+			break;
+		default:
+bad:
+			//fprintf(stderr, "bad!\n");
+			delete m;
+			return;
+	}
+
+#ifdef FEAT_VISUAL
+	reset_VIsual();
+#endif
+
+	char_u  **fnames;
+	fnames = (char_u **) alloc(count * sizeof(char_u *));
+	int fname_index = 0;
+
+	switch (m->what) {
+		case B_REFS_RECEIVED:
+		case B_SIMPLE_DATA:
+			//fprintf(stderr, "case B_REFS_RECEIVED\n");
+			for (int i = 0; i < count; ++i)
+			{
+				entry_ref ref;
+				if (m->FindRef("refs", i, &ref) == B_OK) {
+					BEntry entry(&ref, false);
+					BPath path;
+					entry.GetPath(&path);
+
+					/* Change to parent directory? */
+					if (changedir) {
+						BPath parentpath;
+						path.GetParent(&parentpath);
+						docd(parentpath);
+					}
+
+					/* Is it a directory? If so, cd into it. */
+					BDirectory bdir(&ref);
+					if (bdir.InitCheck() == B_OK) {
+						/* don't cd if we already did it */
+						if (!changedir)
+							docd(path);
+					} else {
+						mch_dirname(IObuff, IOSIZE);
+						char_u *fname = shorten_fname((char_u *)path.Path(), IObuff);
+						if (fname == NULL)
+							fname = (char_u *)path.Path();
+						fnames[fname_index++] = vim_strsave(fname);
+						//fprintf(stderr, "%s\n", fname);
+					}
+
+					/* Only do it for the first file/dir */
+					changedir = false;
+				}
+			}
+			break;
+		case B_ARGV_RECEIVED:
+			//fprintf(stderr, "case B_ARGV_RECEIVED\n");
+			for (int i = 1; i < count; ++i)
+			{
+				char *fname;
+
+				if (m->FindString("argv", i, (const char **) &fname) == B_OK) {
+					fnames[fname_index++] = vim_strsave((char_u *)fname);
+				}
+			}
+			break;
+		default:
+			//fprintf(stderr, "case default\n");
+			break;
+	}
+
+	delete m;
+
+	/* Handle the drop, :edit to get to the file */
+	if (fname_index > 0) {
+		handle_drop(fname_index, fnames, FALSE);
+
+		/* Update the screen display */
+		update_screen(NOT_VALID);
+		setcursor();
+		out_flush();
+	} else {
+		vim_free(fnames);
+	}
+}
+
+VimApp::VimApp(const char *appsig):
+	BApplication(appsig),
+	fFilePanelSem(-1),
+	fFilePanel(NULL)
+{
+}
+
+VimApp::~VimApp()
+{
+}
+
+	void
+VimApp::ReadyToRun()
+{
+	/*
+	 * Apparently signals are inherited by the created thread -
+	 * disable the most annoying ones.
+	 */
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+}
+
+	void
+VimApp::ArgvReceived(int32 arg_argc, char **arg_argv)
+{
+	if (!IsLaunching()) {
+		/*
+		 * This can happen if we are set to Single or Exclusive
+		 * Launch. Be nice and open the file(s).
+		 */
+		if (gui.vimWindow)
+			gui.vimWindow->Minimize(false);
+		BMessage *m = CurrentMessage();
+		DetachCurrentMessage();
+		SendRefs(m, true);
+	}
+}
+
+	void
+VimApp::RefsReceived(BMessage *m)
+{
+	/* Horrible hack!!! XXX XXX XXX
+	 * The real problem is that b_start_ffc is set too late for
+	 * the initial empty buffer. As a result the window will be
+	 * split instead of abandoned.
+	 */
+	int limit = 15;
+	while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0))
+		snooze(100000);    // 0.1 s
+	if (gui.vimWindow)
+		gui.vimWindow->Minimize(false);
+	DetachCurrentMessage();
+	SendRefs(m, true);
+}
+
+/*
+ * Pass a BMessage on to the main() thread.
+ * Caller must have detached the message.
+ */
+	void
+VimApp::SendRefs(BMessage *m, bool changedir)
+{
+	VimRefsMsg rm;
+	rm.message = m;
+	rm.changedir = changedir;
+
+	write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm));
+	// calls ::RefsReceived
+}
+
+	void
+VimApp::MessageReceived(BMessage *m)
+{
+	switch (m->what) {
+		case 'save':
+			{
+				entry_ref refDirectory;
+				m->FindRef("directory", &refDirectory);
+				fBrowsedPath.SetTo(&refDirectory);
+				BString strName;
+				m->FindString("name", &strName);
+				fBrowsedPath.Append(strName.String());
+			}
+			break;
+		case 'open':
+			{
+				entry_ref ref;
+				m->FindRef("refs", &ref);
+				fBrowsedPath.SetTo(&ref);
+			}
+			break;
+		case B_CANCEL:
+			{
+				BFilePanel *panel;
+				m->FindPointer("source", (void**)&panel);
+				if(fFilePanelSem != -1 && panel == fFilePanel) 
+				{
+					delete_sem(fFilePanelSem);
+					fFilePanelSem = -1;
+				}
+
+			}
+			break;
+		default:
+			Inherited::MessageReceived(m);
+			break;
+	}
+}
+
+	bool
+VimApp::QuitRequested()
+{
+	(void)Inherited::QuitRequested();
+	return false;
+}
+
+/* ---------------- VimWindow ---------------- */
+
+VimWindow::VimWindow():
+	BWindow(BRect(40, 40, 150, 150),
+			"Vim",
+			B_TITLED_WINDOW,
+			0,
+			B_CURRENT_WORKSPACE)
+
+{
+	init();
+}
+
+VimWindow::~VimWindow()
+{
+	if (formView) {
+		RemoveChild(formView);
+		delete formView;
+	}
+	gui.vimWindow = NULL;
+}
+
+	void
+VimWindow::init()
+{
+	/* Attach the VimFormView */
+	formView = new VimFormView(Bounds());
+	if (formView != NULL) {
+		AddChild(formView);
+	}
+}
+
+#if 0  // disabled in zeta patch
+	void
+VimWindow::DispatchMessage(BMessage *m, BHandler *h)
+{
+	/*
+	 * Route B_MOUSE_UP messages to MouseUp(), in
+	 * a manner that should be compatible with the
+	 * intended future system behaviour.
+	 */
+	switch (m->what) {
+		case B_MOUSE_UP:
+			// if (!h) h = PreferredHandler();
+			// gcc isn't happy without this extra set of braces, complains about
+			// jump to case label crosses init of 'class BView * v'
+			// richard@whitequeen.com jul 99
+			{
+				BView *v = dynamic_cast<BView *>(h);
+				if (v) {
+					//m->PrintToStream();
+					BPoint where;
+					m->FindPoint("where", &where);
+					v->MouseUp(where);
+				} else {
+					Inherited::DispatchMessage(m, h);
+				}
+			}
+			break;
+		default:
+			Inherited::DispatchMessage(m, h);
+	}
+}
+#endif
+
+	void
+VimWindow::WindowActivated(bool active)
+{
+	Inherited::WindowActivated(active);
+	/* the textArea gets the keyboard action */
+	if (active && gui.vimTextArea)
+		gui.vimTextArea->MakeFocus(true);
+
+	struct VimFocusMsg fm;
+	fm.active = active;
+
+	write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm));
+}
+
+	bool
+VimWindow::QuitRequested()
+{
+	struct VimKeyMsg km;
+	km.length = 5;
+	memcpy((char *)km.chars, "\033:qa\r", km.length);
+
+#ifdef FEAT_MBYTE
+	km.csi_escape = false;
+#endif
+
+	write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+	return false;
+}
+
+/* ---------------- VimFormView ---------------- */
+
+VimFormView::VimFormView(BRect frame):
+	BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES,
+			B_WILL_DRAW | B_FRAME_EVENTS),
+	menuBar(NULL),
+#ifdef FEAT_TOOLBAR
+	toolBar(NULL),
+#endif	
+#ifdef FEAT_GUI_TABLINE
+//	showingTabLine(false),
+	tabLine(NULL),
+#endif
+	textArea(NULL)
+{
+	init(frame);
+}
+
+VimFormView::~VimFormView()
+{
+	if (menuBar) {
+		RemoveChild(menuBar);
+#ifdef never
+		// deleting the menuBar leads to SEGV on exit
+		// richard@whitequeen.com Jul 99
+		delete menuBar;
+#endif
+	}
+
+#ifdef FEAT_TOOLBAR
+	delete toolBar;
+#endif	
+
+#ifdef FEAT_GUI_TABLINE
+	delete tabLine;
+#endif
+
+	if (textArea) {
+		RemoveChild(textArea);
+		delete textArea;
+	}
+	gui.vimForm = NULL;
+}
+
+	void
+VimFormView::init(BRect frame)
+{
+	menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN),
+			"VimMenuBar");
+
+	AddChild(menuBar);
+	
+#ifdef FEAT_TOOLBAR
+	toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar");
+	toolBar->PrepareButtonBitmaps();
+	AddChild(toolBar);
+#endif	
+
+#ifdef FEAT_GUI_TABLINE
+	tabLine = new VimTabLine(BRect(0,0,0,0));
+//	tabLine->PrepareButtonBitmaps();
+	AddChild(tabLine);
+#endif	
+
+	BRect remaining = frame;
+	textArea = new VimTextAreaView(remaining);
+	AddChild(textArea);
+	/* The textArea will be resized later when menus are added */
+
+	gui.vimForm = this;
+}
+
+#ifdef FEAT_TOOLBAR
+	float 
+VimFormView::ToolbarHeight() const
+{ 
+	return toolBar ? toolBar->ToolbarHeight() : 0.; 
+}
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+	float 
+VimFormView::TablineHeight() const
+{
+	return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.; 
+}
+#endif
+
+	void
+VimFormView::AllAttached()
+{
+	/*
+	 * Apparently signals are inherited by the created thread -
+	 * disable the most annoying ones.
+	 */
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+
+	if (menuBar && textArea) {
+		/*
+		 * Resize the textArea to fill the space left over by the menu.
+		 * This is somewhat futile since it will be done again once
+		 * menus are added to the menu bar.
+		 */
+		BRect remaining = Bounds();
+
+#ifdef FEAT_MENU
+		remaining.top += MenuHeight();
+		menuBar->ResizeTo(remaining.right, remaining.top);
+		gui.menu_height = (int) MenuHeight();
+#endif
+
+#ifdef FEAT_TOOLBAR
+		toolBar->MoveTo(remaining.left, remaining.top);
+		toolBar->ResizeTo(remaining.right, ToolbarHeight());
+		remaining.top += ToolbarHeight();
+		gui.toolbar_height = ToolbarHeight();
+#endif	
+
+#ifdef FEAT_GUI_TABLINE
+		tabLine->MoveTo(remaining.left, remaining.top);
+		tabLine->ResizeTo(remaining.right + 1, TablineHeight());
+		remaining.top += TablineHeight();
+		gui.tabline_height = TablineHeight();
+#endif	
+
+		textArea->ResizeTo(remaining.Width(), remaining.Height());
+		textArea->MoveTo(remaining.left, remaining.top);
+	}
+
+
+	Inherited::AllAttached();
+}
+
+	void
+VimFormView::FrameResized(float new_width, float new_height)
+{
+	struct VimResizeMsg sm;
+	int adjust_h, adjust_w;
+
+	new_width += 1;	    // adjust from width to number of pixels occupied
+	new_height += 1;
+
+	sm.width = (int) new_width;
+	sm.height = (int) new_height;
+	adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width;
+	adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height;
+
+	if (adjust_w > 0 || adjust_h > 0) {
+		sm.width  -= adjust_w;
+		sm.height -= adjust_h;
+	}
+
+	write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm));
+	// calls gui_resize_shell(new_width, new_height);
+
+	return;
+
+	/*
+	 * The area below the vertical scrollbar is erased to the colour
+	 * set with SetViewColor() automatically, because we had set
+	 * B_WILL_DRAW. Resizing the window tight around the vertical
+	 * scroll bar also helps to avoid debris.
+	 */
+}
+
+/* ---------------- VimTextAreaView ---------------- */
+
+VimTextAreaView::VimTextAreaView(BRect frame):
+	BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES,
+#ifdef FEAT_MBYTE_IME
+		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INPUT_METHOD_AWARE),
+#else
+		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+#endif
+	mouseDragEventCount(0)
+{
+#ifdef FEAT_MBYTE_IME
+	IMData.messenger = NULL;
+	IMData.message = NULL;
+#endif
+	init(frame);
+}
+
+VimTextAreaView::~VimTextAreaView()
+{
+	gui.vimTextArea = NULL;
+}
+
+	void
+VimTextAreaView::init(BRect frame)
+{
+	/* set up global var for fast access */
+	gui.vimTextArea = this;
+
+	/*
+	 * Tell the app server not to erase the view: we will
+	 * fill it in completely by ourselves.
+	 * (Does this really work? Even if not, it won't harm either.)
+	 */
+	SetViewColor(B_TRANSPARENT_32_BIT);
+#define PEN_WIDTH   1
+	SetPenSize(PEN_WIDTH);
+}
+
+	void
+VimTextAreaView::Draw(BRect updateRect)
+{
+	/*
+	 * XXX Other ports call here:
+	 * out_flush();	     * make sure all output has been processed *
+	 * but we can't do that, since it involves too much information
+	 * that is owned by other threads...
+	 */
+
+	/*
+	 *  No need to use gui.vimWindow->Lock(): we are locked already.
+	 *  However, it would not hurt.
+	 */
+	rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
+	SetLowColor(rgb);
+	FillRect(updateRect, B_SOLID_LOW);
+	gui_redraw((int) updateRect.left, (int) updateRect.top,
+			(int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH));
+
+	/* Clear the border areas if needed */
+	SetLowColor(rgb);
+
+	if (updateRect.left < FILL_X(0))	// left border
+		FillRect(BRect(updateRect.left, updateRect.top,
+					FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW);
+	if (updateRect.top < FILL_Y(0))	// top border
+		FillRect(BRect(updateRect.left, updateRect.top,
+					updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW);
+	if (updateRect.right >= FILL_X(Columns)) // right border
+		FillRect(BRect(FILL_X((int)Columns), updateRect.top,
+					updateRect.right, updateRect.bottom), B_SOLID_LOW);
+	if (updateRect.bottom >= FILL_Y(Rows))   // bottom border
+		FillRect(BRect(updateRect.left, FILL_Y((int)Rows),
+					updateRect.right, updateRect.bottom), B_SOLID_LOW);
+
+#ifdef FEAT_MBYTE_IME
+	DrawIMString();
+#endif
+}
+
+	void
+VimTextAreaView::KeyDown(const char *bytes, int32 numBytes)
+{
+	struct VimKeyMsg km;
+	char_u *dest = km.chars;
+
+	bool canHaveVimModifiers = false;
+
+	BMessage *msg = Window()->CurrentMessage();
+	assert(msg);
+	//msg->PrintToStream();
+
+	/*
+	 * Convert special keys to Vim codes.
+	 * I think it is better to do it in the window thread
+	 * so we use at least a little bit of the potential
+	 * of our 2 CPUs. Besides, due to the fantastic mapping
+	 * of special keys to UTF-8, we have quite some work to
+	 * do...
+	 * TODO: I'm not quite happy with detection of special
+	 * keys. Perhaps I should use scan codes after all...
+	 */
+	if (numBytes > 1) {
+		/* This cannot be a special key */
+		if (numBytes > KEY_MSG_BUFSIZ)
+			numBytes = KEY_MSG_BUFSIZ;	    // should never happen... ???
+		km.length = numBytes;
+		memcpy((char *)dest, bytes, numBytes);
+#ifdef FEAT_MBYTE
+		km.csi_escape = true;
+#endif
+	} else {
+		int32 scancode = 0;
+		msg->FindInt32("key", &scancode);
+
+		int32 beModifiers = 0;
+		msg->FindInt32("modifiers", &beModifiers);
+
+		char_u string[3];
+		int len = 0;
+		km.length = 0;
+
+		/*
+		 * For normal, printable ASCII characters, don't look them up
+		 * to check if they might be a special key. They aren't.
+		 */
+		assert(B_BACKSPACE <= 0x20);
+		assert(B_DELETE == 0x7F);
+		if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) &&
+				numBytes == 1) {
+			/*
+			 * Due to the great nature of Be's mapping of special keys,
+			 * viz. into the range of the control characters,
+			 * we can only be sure it is *really* a special key if
+			 * if it is special without using ctrl. So, only if ctrl is
+			 * used, we need to check it unmodified.
+			 */
+			if (beModifiers & B_CONTROL_KEY) {
+				int index = keyMap->normal_map[scancode];
+				int newNumBytes = keyMapChars[index];
+				char_u *newBytes = (char_u *)&keyMapChars[index + 1];
+
+				/*
+				 * Check if still special without the control key.
+				 * This is needed for BACKSPACE: that key does produce
+				 * different values with modifiers (DEL).
+				 * Otherwise we could simply have checked for equality.
+				 */
+				if (newNumBytes != 1 || (*newBytes > 0x20 &&
+							*newBytes != 0x7F )) {
+					goto notspecial;
+				}
+				bytes = (char *)newBytes;
+			}
+			canHaveVimModifiers = true;
+
+			uint16 beoskey;
+			int first, last;
+
+			/*
+			 * If numBytes == 0 that probably always indicates a special key.
+			 * (does not happen yet)
+			 */
+			if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) {
+				beoskey = F(scancode);
+				first = FIRST_FUNCTION_KEY;
+				last = NUM_SPECIAL_KEYS;
+			} else if (*bytes == '\n' && scancode == 0x47) {
+				/* remap the (non-keypad) ENTER key from \n to \r. */
+				string[0] = '\r';
+				len = 1;
+				first = last = 0;
+			} else {
+				beoskey = K(bytes[0]);
+				first = 0;
+				last = FIRST_FUNCTION_KEY;
+			}
+
+			for (int i = first; i < last; i++) {
+				if (special_keys[i].BeKeys == beoskey) {
+					string[0] = CSI;
+					string[1] = special_keys[i].vim_code0;
+					string[2] = special_keys[i].vim_code1;
+					len = 3;
+				}
+			}
+		}
+notspecial:
+		if (len == 0) {
+			string[0] = bytes[0];
+			len = 1;
+		}
+
+		/* Special keys (and a few others) may have modifiers */
+#if 0
+		if (len == 3 ||
+				bytes[0] == B_SPACE || bytes[0] == B_TAB ||
+				bytes[0] == B_RETURN || bytes[0] == '\r' ||
+				bytes[0] == B_ESCAPE)
+#else
+			if (canHaveVimModifiers)
+#endif
+			{
+				int modifiers;
+				modifiers = 0;
+				if (beModifiers & B_SHIFT_KEY)
+					modifiers |= MOD_MASK_SHIFT;
+				if (beModifiers & B_CONTROL_KEY)
+					modifiers |= MOD_MASK_CTRL;
+				if (beModifiers & B_OPTION_KEY)
+					modifiers |= MOD_MASK_ALT;
+
+				/*
+				 * For some keys a shift modifier is translated into another key
+				 * code.  Do we need to handle the case where len != 1 and
+				 * string[0] != CSI? (Not for BeOS, since len == 3 implies
+				 * string[0] == CSI...)
+				 */
+				int key;
+				if (string[0] == CSI && len == 3)
+					key = TO_SPECIAL(string[1], string[2]);
+				else
+					key = string[0];
+				key = simplify_key(key, &modifiers);
+				if (IS_SPECIAL(key))
+				{
+					string[0] = CSI;
+					string[1] = K_SECOND(key);
+					string[2] = K_THIRD(key);
+					len = 3;
+				}
+				else
+				{
+					string[0] = key;
+					len = 1;
+				}
+
+				if (modifiers)
+				{
+					*dest++ = CSI;
+					*dest++ = KS_MODIFIER;
+					*dest++ = modifiers;
+					km.length = 3;
+				}
+			}
+		memcpy((char *)dest, string, len);
+		km.length += len;
+#ifdef FEAT_MBYTE
+		km.csi_escape = false;
+#endif
+	}
+
+	write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+	/*
+	 * blank out the pointer if necessary
+	 */
+	if (p_mh && !gui.pointer_hidden)
+	{
+		guiBlankMouse(true);
+		gui.pointer_hidden = TRUE;
+	}
+}
+void
+VimTextAreaView::guiSendMouseEvent(
+		int	    button,
+		int	    x,
+		int	    y,
+		int	    repeated_click,
+		int_u   modifiers)
+{
+	VimMouseMsg mm;
+
+	mm.button = button;
+	mm.x = x;
+	mm.y = y;
+	mm.repeated_click = repeated_click;
+	mm.modifiers = modifiers;
+
+	write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm));
+	// calls gui_send_mouse_event()
+
+	/*
+	 * if our pointer is currently hidden, then we should show it.
+	 */
+	if (gui.pointer_hidden)
+	{
+		guiBlankMouse(false);
+		gui.pointer_hidden = FALSE;
+	}
+}
+
+void
+VimTextAreaView::guiMouseMoved(
+		int	    x,
+		int	    y)
+{
+	VimMouseMovedMsg mm;
+
+	mm.x = x;
+	mm.y = y;
+
+	write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm));
+
+	if (gui.pointer_hidden)
+	{
+		guiBlankMouse(false);
+		gui.pointer_hidden = FALSE;
+	}
+}
+
+	void
+VimTextAreaView::guiBlankMouse(bool should_hide)
+{
+	if (should_hide) {
+		//gui.vimApp->HideCursor();
+		gui.vimApp->ObscureCursor();
+		/*
+		 * ObscureCursor() would even be easier, but then
+		 * Vim's idea of mouse visibility does not necessarily
+		 * correspond to reality.
+		 */
+	} else {
+		//gui.vimApp->ShowCursor();
+	}
+}
+
+	int_u
+VimTextAreaView::mouseModifiersToVim(int32 beModifiers)
+{
+	int_u vim_modifiers = 0x0;
+
+	if (beModifiers & B_SHIFT_KEY)
+		vim_modifiers |= MOUSE_SHIFT;
+	if (beModifiers & B_CONTROL_KEY)
+		vim_modifiers |= MOUSE_CTRL;
+	if (beModifiers & B_OPTION_KEY)	    /* Alt or Meta key */
+		vim_modifiers |= MOUSE_ALT;
+
+	return vim_modifiers;
+}
+
+	void
+VimTextAreaView::MouseDown(BPoint point)
+{
+	BMessage *m = Window()->CurrentMessage();
+	assert(m);
+
+	int32 buttons = 0;
+	m->FindInt32("buttons", &buttons);
+
+	int vimButton;
+
+	if (buttons & B_PRIMARY_MOUSE_BUTTON)
+		vimButton = MOUSE_LEFT;
+	else if (buttons & B_SECONDARY_MOUSE_BUTTON)
+		vimButton = MOUSE_RIGHT;
+	else if (buttons & B_TERTIARY_MOUSE_BUTTON)
+		vimButton = MOUSE_MIDDLE;
+	else
+		return;			/* Unknown button */
+
+	vimMouseButton = 1;		/* don't care which one */
+
+	/* Handle multiple clicks */
+	int32 clicks = 0;
+	m->FindInt32("clicks", &clicks);
+
+	int32 modifiers = 0;
+	m->FindInt32("modifiers", &modifiers);
+
+	vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+	guiSendMouseEvent(vimButton, point.x, point.y,
+			clicks > 1 /* = repeated_click*/, vimMouseModifiers);
+}
+
+	void
+VimTextAreaView::MouseUp(BPoint point)
+{
+	vimMouseButton = 0;
+
+	BMessage *m = Window()->CurrentMessage();
+	assert(m);
+	//m->PrintToStream();
+
+	int32 modifiers = 0;
+	m->FindInt32("modifiers", &modifiers);
+
+	vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+	guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y,
+			0 /* = repeated_click*/, vimMouseModifiers);
+
+	Inherited::MouseUp(point);
+}
+
+	void
+VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
+{
+	/*
+	 * if our pointer is currently hidden, then we should show it.
+	 */
+	if (gui.pointer_hidden)
+	{
+		guiBlankMouse(false);
+		gui.pointer_hidden = FALSE;
+	}
+
+	if (!vimMouseButton) {    /* could also check m->"buttons" */
+		guiMouseMoved(point.x, point.y);
+		return;
+	}
+
+	atomic_add(&mouseDragEventCount, 1);
+
+	/* Don't care much about "transit" */
+	guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers);
+}
+
+	void
+VimTextAreaView::MessageReceived(BMessage *m)
+{
+	switch (m->what) {
+		case 'menu':
+			{
+				VimMenuMsg mm;
+				mm.guiMenu = NULL;	/* in case no pointer in msg */
+				m->FindPointer("VimMenu", (void **)&mm.guiMenu);
+				write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm));
+			}
+			break;
+		case B_MOUSE_WHEEL_CHANGED:
+			{
+				VimScrollBar* scb = curwin->w_scrollbars[1].id;
+				float small=0, big=0, dy=0;
+				m->FindFloat("be:wheel_delta_y", &dy);
+				scb->GetSteps(&small, &big);
+				scb->SetValue(scb->Value()+small*dy*3);
+				scb->ValueChanged(scb->Value());
+#if 0
+				scb = curwin->w_scrollbars[0].id;
+				scb->GetSteps(&small, &big);
+				scb->SetValue(scb->Value()+small*dy);
+				scb->ValueChanged(scb->Value());
+#endif
+			}
+			break;
+#ifdef FEAT_MBYTE_IME
+		case B_INPUT_METHOD_EVENT:
+			{
+				int32 opcode;
+				m->FindInt32("be:opcode", &opcode);
+				switch(opcode)
+				{
+					case B_INPUT_METHOD_STARTED:
+						if(!IMData.messenger) delete IMData.messenger;
+						IMData.messenger = new BMessenger();
+						m->FindMessenger("be:reply_to", IMData.messenger);
+						break;
+					case B_INPUT_METHOD_CHANGED:
+						{
+							BString str;
+							bool confirmed;
+							if(IMData.message) *(IMData.message) = *m;
+							else               IMData.message = new BMessage(*m);
+							DrawIMString();
+							m->FindBool("be:confirmed", &confirmed);
+							if (confirmed)
+							{
+								m->FindString("be:string", &str);
+								char_u *chars = (char_u*)str.String();
+								struct VimKeyMsg km;
+								km.csi_escape = true;
+								int clen;
+								int i = 0;
+								while (i < str.Length())
+								{
+									clen = utf_ptr2len(chars+i);
+									memcpy(km.chars, chars+i, clen);
+									km.length = clen;
+									write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+									i += clen;
+								}
+							}
+						}
+						break;
+					case B_INPUT_METHOD_LOCATION_REQUEST:
+						{
+							BMessage msg(B_INPUT_METHOD_EVENT);
+							msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
+							msg.AddPoint("be:location_reply", IMData.location);
+							msg.AddFloat("be:height_reply", FILL_Y(1));
+							IMData.messenger->SendMessage(&msg);
+						}
+						break;   
+					case B_INPUT_METHOD_STOPPED:
+						delete IMData.messenger;
+						delete IMData.message;
+						IMData.messenger = NULL;
+						IMData.message = NULL;
+						break;
+				}
+			}
+			//TODO: sz: break here???
+#endif
+		default:
+			if (m->WasDropped()) {
+				BWindow *w = Window();
+				w->DetachCurrentMessage();
+				w->Minimize(false);
+				VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0);
+			} else {
+				Inherited::MessageReceived(m);
+			}
+			break;
+	}
+}
+
+	int
+VimTextAreaView::mchInitFont(char_u *name)
+{
+	VimFont *newFont = (VimFont *)gui_mch_get_font(name, 0);
+	if(newFont != NOFONT) {
+		gui.norm_font = (GuiFont)newFont;
+		gui_mch_set_font((GuiFont)newFont);
+		if (name)
+			hl_set_font_name(name);
+
+		SetDrawingMode(B_OP_COPY);
+
+		/*
+		 * Try to load other fonts for bold, italic, and bold-italic.
+		 * We should also try to work out what font to use for these when they are
+		 * not specified by X resources, but we don't yet.
+		 */
+		return OK;
+	}
+	return FAIL;
+}
+
+	void
+VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags)
+{
+	/*
+	 * First we must erase the area, because DrawString won't do
+	 * that for us. XXX Most of the time this is a waste of effort
+	 * since the bachground has been erased already... DRAW_TRANSP
+	 * should be set when appropriate!!!
+	 * (Rectangles include the bottom and right edge)
+	 */
+	if (!(flags & DRAW_TRANSP)) {
+		int cells;
+#ifdef FEAT_MBYTE
+		cells = 0;
+		for(int i=0; i<len; i++) {
+			int cn = utf_ptr2cells((char_u *)(s+i));
+			if(cn<4) cells += cn;
+		}
+#else
+		cells = len;
+#endif
+
+		BRect r(FILL_X(col), FILL_Y(row),
+				FILL_X(col + cells) - PEN_WIDTH, FILL_Y(row + 1) - PEN_WIDTH);
+		FillRect(r, B_SOLID_LOW);
+	}
+
+	BFont font;
+	this->GetFont(&font);
+	if(!font.IsFixed())
+	{
+		char* p = (char*)s;
+		int32 clen, lastpos = 0;
+		BPoint where;
+		int cells;
+		while((p - (char*)s) < len) {
+#ifdef FEAT_MBYTE
+			clen = utf_ptr2len((u_char*)p);
+#else
+			clen = 1;
+#endif
+			where.Set(TEXT_X(col+lastpos), TEXT_Y(row));
+			DrawString(p, clen, where);
+			if (flags & DRAW_BOLD) {
+				where.x += 1.0;
+				SetDrawingMode(B_OP_BLEND);
+				DrawString(p, clen, where);
+				SetDrawingMode(B_OP_COPY);
+			}
+#ifdef FEAT_MBYTE
+			cells = utf_ptr2cells((char_u *)p);
+			if(cells<4) lastpos += cells;
+			else        lastpos++;
+#else
+			lastpos++;
+#endif
+			p += clen;
+		}
+	}
+	else
+	{
+		BPoint where(TEXT_X(col), TEXT_Y(row));
+		DrawString((char*)s, len, where);
+		if (flags & DRAW_BOLD) {
+			where.x += 1.0;
+			SetDrawingMode(B_OP_BLEND);
+			DrawString((char*)s, len, where);
+			SetDrawingMode(B_OP_COPY);
+		}
+	}
+
+	if (flags & DRAW_UNDERL) {
+		int cells;
+#ifdef FEAT_MBYTE
+		cells = 0;
+		for(int i=0; i<len; i++) {
+			int cn = utf_ptr2cells((char_u *)(s+i));
+			if(cn<4) cells += cn;
+		}
+#else
+		cells = len;
+#endif
+
+		BPoint start(FILL_X(col), FILL_Y(row + 1) - PEN_WIDTH);
+		BPoint end(FILL_X(col + cells) - PEN_WIDTH, start.y);
+
+		StrokeLine(start, end);
+	}
+}
+
+void
+VimTextAreaView::mchClearBlock(
+		int		row1,
+		int		col1,
+		int		row2,
+		int		col2)
+{
+	BRect r(FILL_X(col1), FILL_Y(row1),
+			FILL_X(col2 + 1) - PEN_WIDTH, FILL_Y(row2 + 1) - PEN_WIDTH);
+	gui_mch_set_bg_color(gui.back_pixel);
+	FillRect(r, B_SOLID_LOW);
+}
+
+	void
+VimTextAreaView::mchClearAll()
+{
+	gui_mch_set_bg_color(gui.back_pixel);
+	FillRect(Bounds(), B_SOLID_LOW);
+}
+
+/*
+ * mchDeleteLines() Lock()s the window by itself.
+ */
+	void
+VimTextAreaView::mchDeleteLines(int row, int num_lines)
+{
+	BRect source, dest;
+	source.left = FILL_X(gui.scroll_region_left);
+	source.top = FILL_Y(row + num_lines);
+	source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+	source.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
+
+	dest.left = FILL_X(gui.scroll_region_left);
+	dest.top = FILL_Y(row);
+	dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+	dest.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
+
+	if (gui.vimWindow->Lock()) {
+		/* Clear one column more for when bold has spilled over */
+		CopyBits(source, dest);
+		gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+				gui.scroll_region_left,
+				gui.scroll_region_bot, gui.scroll_region_right);
+
+
+		gui.vimWindow->Unlock();
+		/*
+		 * The Draw() callback will be called now if some of the source
+		 * bits were not in the visible region.
+		 */
+	}
+	//gui_x11_check_copy_area();
+	// }
+}
+
+/*
+ * mchInsertLines() Lock()s the window by itself.
+ */
+	void
+VimTextAreaView::mchInsertLines(int row, int num_lines)
+{
+	BRect source, dest;
+
+	/* XXX Attempt at a hack: */
+	gui.vimWindow->UpdateIfNeeded();
+	source.left = FILL_X(gui.scroll_region_left);
+	source.top = FILL_Y(row);
+	source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+	source.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
+
+	dest.left = FILL_X(gui.scroll_region_left);
+	dest.top = FILL_Y(row + num_lines);
+	dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+	dest.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
+
+	if (gui.vimWindow->Lock()) {
+		/* Clear one column more for when bold has spilled over */
+		CopyBits(source, dest);
+		gui_clear_block(row, gui.scroll_region_left,
+				row + num_lines - 1, gui.scroll_region_right);
+
+		gui.vimWindow->Unlock();
+		/*
+		 * The Draw() callback will be called now if some of the source
+		 * bits were not in the visible region.
+		 * However, if we scroll too fast it can't keep up and the
+		 * update region gets messed up. This seems to be because copying
+		 * un-Draw()n bits does not generate Draw() calls for the copy...
+		 * I moved the hack to before the CopyBits() to reduce the
+		 * amount of additional waiting needed.
+		 */
+
+		//gui_x11_check_copy_area();
+
+	}
+}
+
+#ifdef FEAT_MBYTE_IME
+/*
+ * DrawIMString draws string with IMData.message.
+ */
+void VimTextAreaView::DrawIMString(void)
+{
+	static const rgb_color r_highlight = {255, 152, 152, 255},
+				 b_highlight = {152, 203, 255, 255};
+	BString str;
+	const char* s;
+	int len;
+	BMessage* msg = IMData.message;
+	if (!msg)
+		return;
+	gui_redraw_block(IMData.row, 0,
+			IMData.row + IMData.count, W_WIDTH(curwin), GUI_MON_NOCLEAR);
+	bool confirmed = false;
+	msg->FindBool("be:confirmed", &confirmed);
+	if (confirmed) 
+		return;
+	rgb_color hcolor = HighColor(), lcolor = LowColor();
+	msg->FindString("be:string", &str);
+	s = str.String();
+	len = str.Length();
+	SetHighColor(0, 0, 0);
+	IMData.row = gui.row;
+	IMData.col = gui.col;
+	int32 sel_start = 0, sel_end = 0;
+	msg->FindInt32("be:selection", 0, &sel_start);
+	msg->FindInt32("be:selection", 1, &sel_end);
+	int clen, cn;
+	BPoint pos(IMData.col, 0);
+	BRect r;
+	BPoint where;
+	IMData.location = ConvertToScreen(
+			BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
+	for (int i=0; i<len; i+=clen)
+	{
+		cn = utf_ptr2cells((char_u *)(s+i));
+		clen = utf_ptr2len((char_u *)(s+i));
+		if (pos.x + cn > W_WIDTH(curwin))
+		{
+			pos.y++;
+			pos.x = 0;
+		}
+		if (sel_start<=i && i<sel_end)
+		{
+			SetLowColor(r_highlight);
+			IMData.location = ConvertToScreen(
+					BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
+		}
+		else
+		{
+			SetLowColor(b_highlight);
+		}
+		r.Set(FILL_X(pos.x), FILL_Y(IMData.row + pos.y),
+				FILL_X(pos.x + cn) - PEN_WIDTH,
+				FILL_Y(IMData.row + pos.y + 1) - PEN_WIDTH);
+		FillRect(r, B_SOLID_LOW);
+		where.Set(TEXT_X(pos.x), TEXT_Y(IMData.row + pos.y));
+		DrawString((s+i), clen, where);
+		pos.x += cn;
+	}
+	IMData.count = (int)pos.y;
+
+	SetHighColor(hcolor);
+	SetLowColor(lcolor);
+}
+#endif
+/* ---------------- VimScrollBar ---------------- */
+
+/* BUG: XXX
+ * It seems that BScrollBar determine their direction not from
+ * "posture" but from if they are "tall" or "wide" in shape...
+ *
+ * Also, place them out of sight, because Vim enables them before
+ * they are positioned.
+ */
+VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
+	BScrollBar(posture == B_HORIZONTAL ?  BRect(-100,-100,-10,-90) :
+			BRect(-100,-100,-90,-10),
+			"vim scrollbar", (BView *)NULL,
+			0.0, 10.0, posture),
+	ignoreValue(-1),
+	scrollEventCount(0)
+{
+	gsb = g;
+	SetResizingMode(B_FOLLOW_NONE);
+}
+
+VimScrollBar::~VimScrollBar()
+{
+}
+
+	void
+VimScrollBar::ValueChanged(float newValue)
+{
+	if (ignoreValue >= 0.0 && newValue == ignoreValue) {
+		ignoreValue = -1;
+		return;
+	}
+	ignoreValue = -1;
+	/*
+	 * We want to throttle the amount of scroll messages generated.
+	 * Normally I presume you won't get a new message before we've
+	 * handled the previous one, but because we're passing them on this
+	 * happens very quickly. So instead we keep a counter of how many
+	 * scroll events there are (or will be) in the VDCMP, and the
+	 * throttling happens at the receiving end.
+	 */
+	atomic_add(&scrollEventCount, 1);
+
+	struct VimScrollBarMsg sm;
+
+	sm.sb = this;
+	sm.value = (long) newValue;
+	sm.stillDragging = TRUE;
+
+	write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+	// calls gui_drag_scrollbar(sb, newValue, TRUE);
+}
+
+/*
+ * When the mouse goes up, report that scrolling has stopped.
+ * MouseUp() is NOT called when the mouse-up occurs outside
+ * the window, even though the thumb does move while the mouse
+ * is outside... This has some funny effects... XXX
+ * So we do special processing when the window de/activates.
+ */
+	void
+VimScrollBar::MouseUp(BPoint where)
+{
+	//BMessage *m = Window()->CurrentMessage();
+	//m->PrintToStream();
+
+	atomic_add(&scrollEventCount, 1);
+
+	struct VimScrollBarMsg sm;
+
+	sm.sb = this;
+	sm.value = (long) Value();
+	sm.stillDragging = FALSE;
+
+	write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+	// calls gui_drag_scrollbar(sb, newValue, FALSE);
+
+	Inherited::MouseUp(where);
+}
+
+	void
+VimScrollBar::SetValue(float newValue)
+{
+	if (newValue == Value())
+		return;
+
+	ignoreValue = newValue;
+	Inherited::SetValue(newValue);
+}
+
+/* ---------------- VimFont ---------------- */
+
+VimFont::VimFont(): BFont()
+{
+	init();
+}
+
+VimFont::VimFont(const VimFont *rhs): BFont(rhs)
+{
+	init();
+}
+
+VimFont::VimFont(const BFont *rhs): BFont(rhs)
+{
+	init();
+}
+
+VimFont::VimFont(const VimFont &rhs): BFont(rhs)
+{
+	init();
+}
+
+VimFont::~VimFont()
+{
+}
+
+	void
+VimFont::init()
+{
+	next = NULL;
+	refcount = 1;
+	name = NULL;
+}
+
+/* ---------------- VimDialog ---------------- */
+
+#if defined(FEAT_GUI_DIALOG)
+
+const unsigned int	kVimDialogButtonMsg = 'VMDB';
+const unsigned int	kVimDialogIconStripeWidth = 30;
+const unsigned int	kVimDialogButtonsSpacingX = 9;
+const unsigned int	kVimDialogButtonsSpacingY = 4;
+const unsigned int	kVimDialogSpacingX = 6;
+const unsigned int	kVimDialogSpacingY = 10;
+const unsigned int	kVimDialogMinimalWidth  = 310;
+const unsigned int	kVimDialogMinimalHeight = 75;
+const BRect			kDefaultRect = 
+BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight); 
+
+VimDialog::VimDialog(int type, const char *title, const char *message,
+		const char *buttons, int dfltbutton, const char *textfield)
+: BWindow(kDefaultRect, title, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, 
+		B_NOT_CLOSABLE | B_NOT_RESIZABLE | 
+		B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
+	, fDialogSem(-1)
+	, fDialogValue(dfltbutton)
+	, fMessageView(NULL)
+	, fInputControl(NULL)
+	 , fInputValue(textfield)
+{
+	// master view
+	VimDialogView* view = new VimDialogView(Bounds());
+	if(view == NULL) {
+		return;
+	}
+
+	if(title == NULL) {
+		SetTitle("Vim " VIM_VERSION_MEDIUM);
+	}
+
+	AddChild(view);
+
+	// icon
+	view->InitIcon(type);
+
+	// buttons
+	int32 which = 1;
+	float maxButtonWidth  = 0;
+	float maxButtonHeight = 0;
+	float buttonsWidth    = 0;
+	float buttonsHeight   = 0;
+	BString strButtons(buttons);
+	strButtons.RemoveAll("&");
+	do {
+		int32 end = strButtons.FindFirst('\n');
+		if(end != B_ERROR) {
+			strButtons[end] = '\0';
+		}
+
+		BButton *button = _CreateButton(which++, strButtons.String());
+		view->AddChild(button);
+		fButtonsList.AddItem(button);
+
+		maxButtonWidth  = max_c(maxButtonWidth,  button->Bounds().Width());
+		maxButtonHeight = max_c(maxButtonHeight, button->Bounds().Height());
+		buttonsWidth   += button->Bounds().Width();
+		buttonsHeight  += button->Bounds().Height();
+
+		if(end == B_ERROR) {
+			break;
+		}
+
+		strButtons.Remove(0, end + 1);
+	} while(true);
+
+	int32 buttonsCount = fButtonsList.CountItems();	
+	buttonsWidth      += kVimDialogButtonsSpacingX * (buttonsCount - 1);
+	buttonsHeight     += kVimDialogButtonsSpacingY * (buttonsCount - 1);
+	float dialogWidth  = buttonsWidth + kVimDialogIconStripeWidth + 
+		kVimDialogSpacingX * 2;
+	float dialogHeight = maxButtonHeight + kVimDialogSpacingY * 3; 
+
+	/* Check 'v' flag in 'guioptions': vertical button placement. */
+	bool vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL) ||
+		dialogWidth >= gui.vimWindow->Bounds().Width();
+	if(vertical) {
+		dialogWidth  -= buttonsWidth; 
+		dialogWidth  += maxButtonWidth;
+		dialogHeight -= maxButtonHeight; 
+		dialogHeight += buttonsHeight; 
+	}
+
+	dialogWidth  = max_c(dialogWidth,  kVimDialogMinimalWidth);
+
+	// message view
+	BRect rect(0, 0, dialogWidth, 0);
+	rect.left  += kVimDialogIconStripeWidth + 16 + kVimDialogSpacingX;
+	rect.top   += kVimDialogSpacingY;
+	rect.right -= kVimDialogSpacingX;
+	rect.bottom = rect.top;
+	fMessageView = new BTextView(rect, "_tv_", rect.OffsetByCopy(B_ORIGIN),
+			B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
+
+	fMessageView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
+	fMessageView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
+	fMessageView->SetText(message);
+	fMessageView->MakeEditable(false);
+	fMessageView->MakeSelectable(false);
+	fMessageView->SetWordWrap(true);
+	AddChild(fMessageView);
+
+	float messageHeight = fMessageView->TextHeight(0, fMessageView->CountLines());
+	fMessageView->ResizeBy(0, messageHeight);
+	fMessageView->SetTextRect(BRect(0, 0, rect.Width(), messageHeight));
+
+	dialogHeight += messageHeight;
+
+	// input view
+	if(fInputValue != NULL) {
+		rect.top     =
+			rect.bottom += messageHeight + kVimDialogSpacingY;
+		fInputControl = new BTextControl(rect, "_iv_", NULL, fInputValue, NULL,
+				B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE |  B_PULSE_NEEDED);
+		fInputControl->TextView()->SetText(fInputValue); 
+		fInputControl->TextView()->SetWordWrap(false);
+		AddChild(fInputControl); 
+
+		float width = 0.f, height = 0.f;
+		fInputControl->GetPreferredSize(&width, &height);
+		fInputControl->MakeFocus(true);
+
+		dialogHeight += height + kVimDialogSpacingY * 1.5;
+	}
+
+	dialogHeight = max_c(dialogHeight, kVimDialogMinimalHeight);
+
+	ResizeTo(dialogWidth, dialogHeight);
+	MoveTo((gui.vimWindow->Bounds().Width() - dialogWidth) / 2,
+			(gui.vimWindow->Bounds().Height() - dialogHeight) / 2);
+
+	// adjust layout of buttons 
+	float buttonWidth = max_c(maxButtonWidth, rect.Width() * 0.66);
+	BPoint origin(dialogWidth, dialogHeight);
+	origin.x -= kVimDialogSpacingX + (vertical ? buttonWidth : buttonsWidth);
+	origin.y -= kVimDialogSpacingY + (vertical ? buttonsHeight  : maxButtonHeight);
+
+	for(int32 i = 0 ; i < buttonsCount; i++) {
+		BButton *button = (BButton*)fButtonsList.ItemAt(i);
+		button->MoveTo(origin);
+		if(vertical) {
+			origin.y += button->Frame().Height() + kVimDialogButtonsSpacingY;
+			button->ResizeTo(buttonWidth, button->Frame().Height());
+		} else {
+			origin.x += button->Frame().Width() + kVimDialogButtonsSpacingX;
+		}
+		if(dfltbutton == i + 1) {
+			button->MakeDefault(true);
+			button->MakeFocus(fInputControl == NULL);
+		}
+	}
+}
+
+VimDialog::~VimDialog()
+{
+	if(fDialogSem > B_OK) {
+		delete_sem(fDialogSem);
+	}
+
+} 
+
+	int
+VimDialog::Go()
+{
+	fDialogSem = create_sem(0, "VimDialogSem");
+	if(fDialogSem < B_OK) {
+		Quit();
+		return fDialogValue;
+	}
+
+	Show();
+
+	while(acquire_sem(fDialogSem) == B_INTERRUPTED);
+
+	int retValue = fDialogValue;
+	if(fInputValue != NULL) {
+		vim_strncpy((char_u*)fInputValue, (char_u*)fInputControl->Text(), IOSIZE - 1);
+	}
+	if(Lock()) {
+		Quit();
+	}
+
+	return retValue;
+} 
+
+void VimDialog::MessageReceived(BMessage *msg)
+{
+	int32 which = 0;
+	if(msg->what != kVimDialogButtonMsg ||
+			msg->FindInt32("which", &which) != B_OK) 
+	{
+		return BWindow::MessageReceived(msg);
+	}
+
+	fDialogValue = which;
+	delete_sem(fDialogSem);
+	fDialogSem = -1;
+}
+
+BButton* VimDialog::_CreateButton(int32 which, const char* label)
+{
+	BMessage *message = new BMessage(kVimDialogButtonMsg);
+	message->AddInt32("which", which);
+
+	BRect rect(0, 0, 0, 0);
+	BString name;
+	name << "_b" << which << "_";
+
+	BButton* button = new BButton(rect, name.String(), label, message,
+			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
+
+	float width = 0.f, height = 0.f; 
+	button->GetPreferredSize(&width, &height);
+	button->ResizeTo(width, height);
+
+	return button;
+}
+
+VimDialogView::VimDialogView(BRect frame)
+	:	BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
+	fIconBitmap(NULL)
+{
+	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+}
+
+VimDialogView::~VimDialogView()
+{
+	delete fIconBitmap;
+}
+
+void VimDialogView::Draw(BRect updateRect)
+{
+	BRect stripeRect = Bounds();
+	stripeRect.right = kVimDialogIconStripeWidth;
+	SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
+	FillRect(stripeRect);
+
+	if(fIconBitmap == NULL) {
+		return;
+	}
+
+	SetDrawingMode(B_OP_ALPHA);
+	SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
+	DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
+}
+
+void VimDialogView::InitIcon(int32 type)
+{
+	if(type == VIM_GENERIC) {
+		return;
+	}
+
+	BPath path;
+	status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
+	if(status != B_OK) {
+		fprintf(stderr, "Cannot retrieve app info:%s\n", strerror(status));
+		return;
+	}
+
+	path.Append("app_server");
+
+	BFile file(path.Path(), O_RDONLY);
+	if(file.InitCheck() != B_OK) {
+		fprintf(stderr, "App file assignment failed:%s\n", 
+				strerror(file.InitCheck()));
+		return;
+	}
+
+	BResources resources(&file);
+	if(resources.InitCheck() != B_OK) {
+		fprintf(stderr, "App server resources assignment failed:%s\n", 
+				strerror(resources.InitCheck()));
+		return;
+	}
+
+	const char *name = "";
+	switch(type) {
+		case VIM_ERROR:		name = "stop"; break;
+		case VIM_WARNING:	name = "warn"; break;
+		case VIM_INFO:		name = "info"; break;
+		case VIM_QUESTION:	name = "idea"; break;
+		default: return;
+	}
+
+	int32 iconSize = 32;
+	fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
+	if(fIconBitmap == NULL || fIconBitmap->InitCheck() != B_OK) {
+		fprintf(stderr, "Icon bitmap allocation failed:%s\n", 
+				(fIconBitmap == NULL) ? "null" : strerror(fIconBitmap->InitCheck()));
+		return;
+	}
+
+	size_t size = 0;
+	const uint8* iconData = NULL;  
+#ifdef __HAIKU__
+	// try vector icon first?
+	iconData = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, name, &size);
+	if(iconData != NULL && BIconUtils::GetVectorIcon(iconData, size, fIconBitmap) == B_OK) {
+		return;
+	}
+#endif
+
+	// try bitmap icon now
+	iconData = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE, name, &size);
+	if(iconData == NULL) {
+		fprintf(stderr, "Bitmap icon resource not found\n"); 
+		delete fIconBitmap;
+		fIconBitmap = NULL;
+		return;
+	}
+
+#ifdef __HAIKU__
+	if(fIconBitmap->ColorSpace() != B_CMAP8) {
+		BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
+	}
+#else
+	fIconBitmap->SetBits(iconData, size, 0, B_CMAP8);
+#endif	
+}
+
+#endif /* FEAT_GUI_DIALOG */
+
+#ifdef FEAT_TOOLBAR
+
+// some forward declaration required by toolbar functions...
+static BMessage * MenuMessage(vimmenu_T *menu);
+
+VimToolbar::VimToolbar(BRect frame, const char *name) : 
+	BBox(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER)
+{
+}
+
+VimToolbar::~VimToolbar()
+{
+	int32 count = fButtonsList.CountItems();
+	for(int32 i = 0; i < count; i++) {
+		delete (BPictureButton*)fButtonsList.ItemAt(i); 
+	}
+	fButtonsList.MakeEmpty();
+
+	delete normalButtonsBitmap;
+	delete grayedButtonsBitmap;
+	normalButtonsBitmap    = NULL;
+	grayedButtonsBitmap  = NULL;
+}
+
+	void
+VimToolbar::AttachedToWindow()
+{
+	BBox::AttachedToWindow();
+	
+	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+}
+	
+	float 
+VimToolbar::ToolbarHeight() const
+{
+	float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
+	return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
+}
+
+	bool
+VimToolbar::ModifyBitmapToGrayed(BBitmap *bitmap)
+{
+	float height = bitmap->Bounds().Height();
+	float width  = bitmap->Bounds().Width();
+
+	rgb_color *bits = (rgb_color*)bitmap->Bits();
+	int32 pixels = bitmap->BitsLength() / 4;
+	for(int32 i = 0; i < pixels; i++) {
+		bits[i].red = bits[i].green =
+		bits[i].blue = ((uint32)bits[i].red + bits[i].green + bits[i].blue) / 3;
+		bits[i].alpha /= 4;
+	}
+
+	return true;
+}
+
+	bool 
+VimToolbar::PrepareButtonBitmaps()
+{
+	// first try to load potentially customized $VIRUNTIME/bitmaps/builtin-tools.png
+	normalButtonsBitmap = LoadVimBitmap("builtin-tools.png");
+	if(normalButtonsBitmap == NULL) {
+		// customized not found? dig application resources for "builtin-tools" one
+		normalButtonsBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "builtin-tools");
+	}
+
+	if(normalButtonsBitmap == NULL) {
+		return false;
+	}
+
+	BMessage archive;
+	normalButtonsBitmap->Archive(&archive);
+
+	grayedButtonsBitmap = new BBitmap(&archive);
+	if(grayedButtonsBitmap == NULL) {
+		return false;
+	}
+		
+	// modify grayed bitmap
+	ModifyBitmapToGrayed(grayedButtonsBitmap);
+
+	return true;
+}
+
+BBitmap *VimToolbar::LoadVimBitmap(const char* fileName)
+{
+	BBitmap *bitmap = NULL;
+	
+	int mustfree = 0;
+	char_u* runtimePath = vim_getenv((char_u*)"VIMRUNTIME", &mustfree);
+	if(runtimePath != NULL && fileName != NULL) {
+		BString strPath((char*)runtimePath);
+		strPath << "/bitmaps/" << fileName;
+		bitmap = BTranslationUtils::GetBitmap(strPath.String());
+	}
+
+	if(mustfree) {
+		vim_free(runtimePath);
+	}
+
+	return bitmap;
+}
+
+	bool
+VimToolbar::GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed)
+{
+	float size = bitmapFrom->Bounds().Height() + 1.;
+	
+	BView view(BRect(0, 0, size, size), "", 0, 0);
+
+	AddChild(&view);
+	view.BeginPicture(pictureTo);
+
+	view.SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+	view.FillRect(view.Bounds());
+	view.SetDrawingMode(B_OP_OVER);
+
+	BRect source(0, 0, size - 1, size - 1);
+	BRect destination(source);
+
+	source.OffsetBy(size * index, 0);
+	destination.OffsetBy(ButtonMargin, ButtonMargin);
+
+	view.DrawBitmap(bitmapFrom, source, destination);
+
+	if(pressed)	{
+		rgb_color shineColor  = ui_color(B_SHINE_COLOR);
+		rgb_color shadowColor = ui_color(B_SHADOW_COLOR);
+		size += ButtonMargin * 2 - 1;
+		view.BeginLineArray(4);
+		view.AddLine(BPoint(0, 0),		 BPoint(size, 0),	 shadowColor);
+		view.AddLine(BPoint(size, 0),	 BPoint(size, size), shineColor);
+		view.AddLine(BPoint(size, size), BPoint(0, size),	 shineColor);
+		view.AddLine(BPoint(0, size),	 BPoint(0, 0),		 shadowColor);
+		view.EndLineArray();
+	}
+
+	view.EndPicture();
+	RemoveChild(&view);
+
+	return true;
+}
+
+	bool 
+VimToolbar::AddButton(int32 index, vimmenu_T *menu)
+{
+	BPictureButton *button = NULL;
+	if(!menu_is_separator(menu->name)) {
+		float size = normalButtonsBitmap ? 
+			normalButtonsBitmap->Bounds().Height() + 1. + ButtonMargin * 2 : 18.;
+		BRect frame(0, 0, size, size);
+		BPicture pictureOn;
+		BPicture pictureOff;
+		BPicture pictureGray;
+
+		if(menu->iconfile == NULL && menu->iconidx >= 0 && normalButtonsBitmap) {
+			GetPictureFromBitmap(&pictureOn,  menu->iconidx, normalButtonsBitmap, true);
+			GetPictureFromBitmap(&pictureOff, menu->iconidx, normalButtonsBitmap, false);
+			GetPictureFromBitmap(&pictureGray, menu->iconidx, grayedButtonsBitmap, false);
+		} else {
+
+			char_u buffer[MAXPATHL] = {0};
+			BBitmap *bitmap = NULL;
+
+			if(menu->iconfile) {
+				gui_find_iconfile(menu->iconfile, buffer, (char*)"png");
+				bitmap = BTranslationUtils::GetBitmap((char*)buffer);
+			}
+
+			if(bitmap == NULL && gui_find_bitmap(menu->name, buffer, (char*)"png") == OK) {
+				bitmap = BTranslationUtils::GetBitmap((char*)buffer);
+			}
+
+			if(bitmap == NULL) {
+				bitmap = new BBitmap(BRect(0, 0, size, size), B_RGB32);
+			}
+
+			GetPictureFromBitmap(&pictureOn,   0, bitmap, true);
+			GetPictureFromBitmap(&pictureOff,  0, bitmap, false);
+			ModifyBitmapToGrayed(bitmap);
+			GetPictureFromBitmap(&pictureGray, 0, bitmap, false);
+
+			delete bitmap;
+		}
+
+		button = new BPictureButton(frame, (char*)menu->name, 
+					&pictureOff, &pictureOn, MenuMessage(menu));
+		
+		button->SetDisabledOn(&pictureGray);
+		button->SetDisabledOff(&pictureGray);
+
+		button->SetTarget(gui.vimTextArea);
+
+		AddChild(button);
+		
+		menu->button = button;
+	}
+
+	bool result = fButtonsList.AddItem(button, index);
+	InvalidateLayout();
+	return result;
+}
+
+	bool 
+VimToolbar::RemoveButton(vimmenu_T *menu)
+{
+	if(menu->button) {
+		if(fButtonsList.RemoveItem(menu->button)) {
+			delete menu->button;
+			menu->button = NULL;
+		}
+	}
+}
+
+	bool 
+VimToolbar::GrayButton(vimmenu_T *menu, int grey)
+{
+	if(menu->button) {
+		int32 index = fButtonsList.IndexOf(menu->button);
+		if(index >= 0) {
+			menu->button->SetEnabled(grey ? false : true);
+		}
+	}
+}
+
+	void 
+VimToolbar::InvalidateLayout()
+{
+	int32 offset = ToolbarMargin;
+	int32 count = fButtonsList.CountItems();
+	for(int32 i = 0; i < count; i++) {
+		BPictureButton *button = (BPictureButton *)fButtonsList.ItemAt(i);
+		if(button) {
+			button->MoveTo(offset, ToolbarMargin);
+			offset += button->Bounds().Width() + ToolbarMargin;
+		} else
+			offset += ToolbarMargin * 3;
+	}
+}
+
+#endif /*FEAT_TOOLBAR*/
+
+#if defined(FEAT_GUI_TABLINE)
+
+	float 
+VimTabLine::TablineHeight() const
+{
+//	float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
+//	return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
+	return TabHeight();// + ToolbarMargin;
+}
+
+void
+VimTabLine::MouseDown(BPoint point)
+{
+	if(!gui_mch_showing_tabline())
+		return;
+
+	BMessage *m = Window()->CurrentMessage();
+	assert(m);
+
+	int32 buttons = 0;
+	m->FindInt32("buttons", &buttons);
+
+	int32 clicks = 0;
+	m->FindInt32("clicks", &clicks);
+
+	int index = 0; // 0 means here - no tab found
+	for (int i = 0; i < CountTabs(); i++) {
+		if(TabFrame(i).Contains(point)) {
+			index = i + 1; // indexes are 1-based
+			break;
+		}
+	}
+
+	int event = -1;
+
+	if ((buttons & B_PRIMARY_MOUSE_BUTTON) && clicks > 1) {
+		// left button double click on - create new tab
+		event = TABLINE_MENU_NEW;
+
+	} else if (buttons & B_TERTIARY_MOUSE_BUTTON) {
+		// middle button click - close the pointed tab 
+		// or create new one in case empty space
+		event = index > 0 ? TABLINE_MENU_CLOSE : TABLINE_MENU_NEW;
+
+	} else if (buttons & B_SECONDARY_MOUSE_BUTTON) {
+		// right button click - show context menu		
+		BPopUpMenu* popUpMenu = new BPopUpMenu("tabLineContextMenu", false, false);
+		popUpMenu->AddItem(new BMenuItem(_("Close tabi R"), new BMessage(TABLINE_MENU_CLOSE)));
+		popUpMenu->AddItem(new BMenuItem(_("New tab    T"), new BMessage(TABLINE_MENU_NEW)));
+		popUpMenu->AddItem(new BMenuItem(_("Open tab..."), new BMessage(TABLINE_MENU_OPEN)));
+
+		ConvertToScreen(&point);
+		BMenuItem* item = popUpMenu->Go(point);
+		if (item != NULL) {
+			event = item->Command();
+		}
+
+		delete popUpMenu;
+
+	} else {
+		// default processing
+		BTabView::MouseDown(point);
+		return;
+	}
+
+	if (event < 0)
+		return;
+
+	VimTablineMenuMsg tmm;
+	tmm.index = index;
+	tmm.event = event;
+	write_port(gui.vdcmp, VimMsg::TablineMenu, &tmm, sizeof(tmm));
+}
+
+void
+VimTabLine::VimTab::Select(BView* owner)
+{
+	BTab::Select(owner);
+
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+	if(tabLine != NULL) {
+
+		int32 i = 0;
+		for (; i < tabLine->CountTabs(); i++) {
+			if(this == tabLine->TabAt(i))
+				break;
+		}
+		
+		printf("%d:%d:%s\n", i, tabLine->CountTabs(), tabLine->TabAt(i)->Label());
+		if(i < tabLine->CountTabs()) {
+			VimTablineMsg tm;
+			tm.index = i + 1;
+			write_port(gui.vdcmp, VimMsg::Tabline, &tm, sizeof(tm));
+		}
+	}
+}
+
+#endif // defined(FEAT_GUI_TABLINE)
+
+/* ---------------- ---------------- */
+
+// some global variables
+static char appsig[] = "application/x-vnd.Haiku-Vim-7";
+key_map *keyMap;
+char *keyMapChars;
+int main_exitcode = 127;
+
+	status_t
+gui_beos_process_event(bigtime_t timeout)
+{
+	struct VimMsg vm;
+	int32 what;
+	ssize_t size;
+
+	size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm),
+			B_TIMEOUT, timeout);
+
+	if (size >= 0) {
+		switch (what) {
+			case VimMsg::Key:
+				{
+					char_u *string = vm.u.Key.chars;
+					int len = vm.u.Key.length;
+					if (len == 1 && string[0] == Ctrl_chr('C')) {
+						trash_input_buf();
+						got_int = TRUE;
+					}
+
+#ifdef FEAT_MBYTE
+					if (vm.u.Key.csi_escape)
+#ifndef FEAT_MBYTE_IME
+					{
+						int		i;
+						char_u	buf[2];
+
+						for (i = 0; i < len; ++i)
+						{
+							add_to_input_buf(string + i, 1);
+							if (string[i] == CSI)
+							{
+								/* Turn CSI into K_CSI. */
+								buf[0] = KS_EXTRA;
+								buf[1] = (int)KE_CSI;
+								add_to_input_buf(buf, 2);
+							}
+						}
+					}
+#else
+					add_to_input_buf_csi(string, len);
+#endif
+					else
+#endif
+						add_to_input_buf(string, len);
+				}
+				break;
+			case VimMsg::Resize:
+				gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height);
+				break;
+			case VimMsg::ScrollBar:
+				{
+					/*
+					 * If loads of scroll messages queue up, use only the last
+					 * one. Always report when the scrollbar stops dragging.
+					 * This is not perfect yet anyway: these events are queued
+					 * yet again, this time in the keyboard input buffer.
+					 */
+					int32 oldCount =
+						atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1);
+					if (oldCount <= 1 || !vm.u.Scroll.stillDragging)
+						gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(),
+								vm.u.Scroll.value, vm.u.Scroll.stillDragging);
+				}
+				break;
+#if defined(FEAT_MENU)
+			case VimMsg::Menu:
+				gui_menu_cb(vm.u.Menu.guiMenu);
+				break;
+#endif
+			case VimMsg::Mouse:
+				{
+					int32 oldCount;
+					if (vm.u.Mouse.button == MOUSE_DRAG)
+						oldCount =
+							atomic_add(&gui.vimTextArea->mouseDragEventCount, -1);
+					else
+						oldCount = 0;
+					if (oldCount <= 1)
+						gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x,
+								vm.u.Mouse.y, vm.u.Mouse.repeated_click,
+								vm.u.Mouse.modifiers);
+				}
+				break;
+			case VimMsg::MouseMoved:
+				{
+					gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y);
+				}
+				break;
+			case VimMsg::Focus:
+				gui.in_focus = vm.u.Focus.active;
+				/* XXX Signal that scrollbar dragging has stopped?
+				 * This is needed because we don't get a MouseUp if
+				 * that happens while outside the window... :-(
+				 */
+				if (gui.dragged_sb) {
+					gui.dragged_sb = SBAR_NONE;
+				}
+				// gui_update_cursor(TRUE, FALSE);
+				break;
+			case VimMsg::Refs:
+				::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir);
+				break;
+			case VimMsg::Tabline:
+				send_tabline_event(vm.u.Tabline.index);
+				break;
+			case VimMsg::TablineMenu:
+				send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event);
+				break;
+			default:
+				// unrecognised message, ignore it
+				break;
+		}
+	}
+
+	/*
+	 * If size < B_OK, it is an error code.
+	 */
+	return size;
+}
+
+/*
+ * Here are some functions to protect access to ScreenLines[] and
+ * LineOffset[]. These are used from the window thread to respond
+ * to a Draw() callback. When that occurs, the window is already
+ * locked by the system.
+ *
+ * Other code that needs to lock is any code that changes these
+ * variables. Other read-only access, or access merely to the
+ * contents of the screen buffer, need not be locked.
+ *
+ * If there is no window, don't call Lock() but do succeed.
+ */
+
+	int
+vim_lock_screen()
+{
+	return !gui.vimWindow || gui.vimWindow->Lock();
+}
+
+	void
+vim_unlock_screen()
+{
+	if (gui.vimWindow)
+		gui.vimWindow->Unlock();
+}
+
+#define RUN_BAPPLICATION_IN_NEW_THREAD	0
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+
+	int32
+run_vimapp(void *args)
+{
+	VimApp app(appsig);
+
+	gui.vimApp = &app;
+	app.Run();			    /* Run until Quit() called */
+
+	return 0;
+}
+
+#else
+
+	int32
+call_main(void *args)
+{
+	struct MainArgs *ma = (MainArgs *)args;
+
+	return main(ma->argc, ma->argv);
+}
+#endif
+
+/*
+ * Parse the GUI related command-line arguments.  Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly.  This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+	void
+gui_mch_prepare(
+		int		*argc,
+		char	**argv)
+{
+	/*
+	 * We don't have any command line arguments for the BeOS GUI yet,
+	 * but this is an excellent place to create our Application object.
+	 */
+	if (!gui.vimApp) {
+		thread_info tinfo;
+		get_thread_info(find_thread(NULL), &tinfo);
+
+		/* May need the port very early on to process RefsReceived() */
+		gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP");
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+		thread_id tid = spawn_thread(run_vimapp, "vim VimApp",
+				tinfo.priority, NULL);
+		if (tid >= B_OK) {
+			resume_thread(tid);
+		} else {
+			getout(1);
+		}
+#else
+		MainArgs ma = { *argc, argv };
+		thread_id tid = spawn_thread(call_main, "vim main()",
+				tinfo.priority, &ma);
+		if (tid >= B_OK) {
+			VimApp app(appsig);
+
+			gui.vimApp = &app;
+			resume_thread(tid);
+			/*
+			 * This is rather horrible.
+			 * call_main will call main() again...
+			 * There will be no infinite recursion since
+			 * gui.vimApp is set now.
+			 */
+			app.Run();			    /* Run until Quit() called */
+			//fprintf(stderr, "app.Run() returned...\n");
+			status_t dummy_exitcode;
+			(void)wait_for_thread(tid, &dummy_exitcode);
+
+			/*
+			 * This path should be the normal one taken to exit Vim.
+			 * The main() thread calls mch_exit() which calls
+			 * gui_mch_exit() which terminates its thread.
+			 */
+			exit(main_exitcode);
+		}
+#endif
+	}
+	/* Don't fork() when starting the GUI. Spawned threads are not
+	 * duplicated with a fork(). The result is a mess.
+	 */
+	gui.dofork = FALSE;
+	/*
+	 * XXX Try to determine whether we were started from
+	 * the Tracker or the terminal.
+	 * It would be nice to have this work, because the Tracker
+	 * follows symlinks, so even if you double-click on gvim,
+	 * when it is a link to vim it will still pass a command name
+	 * of vim...
+	 * We try here to see if stdin comes from /dev/null. If so,
+	 * (or if there is an error, which should never happen) start the GUI.
+	 * This does the wrong thing for vim - </dev/null, and we're
+	 * too early to see the command line parsing. Tough.
+	 * On the other hand, it starts the gui for vim file & which is nice.
+	 */
+	if (!isatty(0)) {
+		struct stat stat_stdin, stat_dev_null;
+
+		if (fstat(0, &stat_stdin) == -1 ||
+				stat("/dev/null", &stat_dev_null) == -1 ||
+				(stat_stdin.st_dev == stat_dev_null.st_dev &&
+				 stat_stdin.st_ino == stat_dev_null.st_ino))
+			gui.starting = TRUE;
+	}
+
+	// TODO: test
+#if 0	
+	team_info ti;
+	get_team_info(getpid(), &ti);
+	BString str;
+	str << ti.argc << ":" << ti.args << "\n"; 
+	BAlert *alert=new BAlert(str.String(), str.String(), "OK");
+	alert->Go();
+
+	/*
+	   for(size_t i = 0; i < 50; i++) {
+	   snooze(1000000);
+	   syslog(LOG_INFO, "vim snooze:%d\n", i);
+	   }
+	   */
+#endif
+
+}
+
+/*
+ * Check if the GUI can be started.  Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+	int
+gui_mch_init_check(void)
+{
+	return OK;		/* TODO: GUI can always be started? */
+}
+
+/*
+ * Initialise the GUI.  Create all the windows, set up all the call-backs
+ * etc.
+ */
+	int
+gui_mch_init()
+{
+	gui.def_norm_pixel = RGB(0x00, 0x00, 0x00);	// black
+	gui.def_back_pixel = RGB(0xFF, 0xFF, 0xFF);	// white
+	gui.norm_pixel = gui.def_norm_pixel;
+	gui.back_pixel = gui.def_back_pixel;
+
+	gui.scrollbar_width = (int) B_V_SCROLL_BAR_WIDTH;
+	gui.scrollbar_height = (int) B_H_SCROLL_BAR_HEIGHT;
+#ifdef FEAT_MENU
+	gui.menu_height = 19;	// initial guess -
+	// correct for my default settings
+#endif
+	gui.border_offset = 3;	// coordinates are inside window borders
+
+	if (gui.vdcmp < B_OK)
+		return FAIL;
+	get_key_map(&keyMap, &keyMapChars);
+
+	gui.vimWindow = new VimWindow();	/* hidden and locked */
+	if (!gui.vimWindow)
+		return FAIL;
+
+	gui.vimWindow->Run();		/* Run() unlocks but does not show */
+
+	/* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+	 * file) */
+	set_normal_colors();
+
+	/*
+	 * Check that none of the colors are the same as the background color
+	 */
+	gui_check_colors();
+
+	/* Get the colors for the highlight groups (gui_check_colors() might have
+	 * changed them) */
+	highlight_gui_started();		/* re-init colors and fonts */
+
+	gui_mch_new_colors();		/* window must exist for this */
+
+	return OK;
+}
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+	void
+gui_mch_new_colors()
+{
+	rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
+
+	if (gui.vimWindow->Lock()) {
+		gui.vimForm->SetViewColor(rgb);
+		// Does this not have too much effect for those small rectangles?
+		gui.vimForm->Invalidate();
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+	int
+gui_mch_open()
+{
+	if (gui_win_x != -1 && gui_win_y != -1)
+		gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+	/* Actually open the window */
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->Show();
+		gui.vimWindow->Unlock();
+
+#if USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+		/* Kill the thread that may have been created for the Terminal */
+		beos_cleanup_read_thread();
+#endif
+
+		return OK;
+	}
+
+	return FAIL;
+}
+
+	void
+gui_mch_exit(int vim_exitcode)
+{
+	if (gui.vimWindow) {
+		thread_id tid = gui.vimWindow->Thread();
+		gui.vimWindow->Lock();
+		gui.vimWindow->Quit();
+		/* Wait until it is truely gone */
+		int32 exitcode;
+		wait_for_thread(tid, &exitcode);
+	}
+	delete_port(gui.vdcmp);
+#if !RUN_BAPPLICATION_IN_NEW_THREAD
+	/*
+	 * We are in the main() thread - quit the App thread and
+	 * quit ourselves (passing on the exitcode). Use a global since the
+	 * value from exit_thread() is only used if wait_for_thread() is
+	 * called in time (race condition).
+	 */
+#endif
+	if (gui.vimApp) {
+		VimTextAreaView::guiBlankMouse(false);
+
+		main_exitcode = vim_exitcode;
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+		thread_id tid = gui.vimApp->Thread();
+		int32 exitcode;
+		gui.vimApp->Lock();
+		gui.vimApp->Quit();
+		gui.vimApp->Unlock();
+		wait_for_thread(tid, &exitcode);
+#else
+		gui.vimApp->Lock();
+		gui.vimApp->Quit();
+		gui.vimApp->Unlock();
+		/* suicide */
+		exit_thread(vim_exitcode);
+#endif
+	}
+	/* If we are somehow still here, let mch_exit() handle things. */
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+	int
+gui_mch_get_winpos(int *x, int *y)
+{
+	if (gui.vimWindow->Lock()) {
+		BRect r;
+		r = gui.vimWindow->Frame();
+		gui.vimWindow->Unlock();
+		*x = (int)r.left;
+		*y = (int)r.top;
+		return OK;
+	}
+	else
+		return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+	void
+gui_mch_set_winpos(int x, int y)
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->MoveTo(x, y);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Set the size of the window to the given width and height in pixels.
+ */
+void
+gui_mch_set_shellsize(
+		int		width,
+		int		height,
+		int		min_width,
+		int		min_height,
+		int		base_width,
+		int		base_height,
+		int		direction) //TODO: utilize?
+{
+	/*
+	 * We are basically given the size of the VimForm, if I understand
+	 * correctly. Since it fills the window completely, this will also
+	 * be the size of the window.
+	 */
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH);
+
+		/* set size limits */
+		float minWidth, maxWidth, minHeight, maxHeight;
+
+		gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth,
+				&minHeight, &maxHeight);
+		gui.vimWindow->SetSizeLimits(min_width, maxWidth,
+				min_height, maxHeight);
+
+		/*
+		 * Set the resizing alignment depending on font size.
+		 */
+		gui.vimWindow->SetWindowAlignment(
+				B_PIXEL_ALIGNMENT,		// window_alignment mode,
+				1,				// int32 h,
+				0,				// int32 hOffset = 0,
+				gui.char_width,		// int32 width = 0,
+				base_width,			// int32 widthOffset = 0,
+				1,				// int32 v = 0,
+				0,				// int32 vOffset = 0,
+				gui.char_height,		// int32 height = 0,
+				base_height			// int32 heightOffset = 0
+				);
+
+		gui.vimWindow->Unlock();
+	}
+}
+
+void
+gui_mch_get_screen_dimensions(
+		int		*screen_w,
+		int		*screen_h)
+{
+	BRect frame;
+
+	{
+		BScreen screen(gui.vimWindow);
+
+		if (screen.IsValid()) {
+			frame = screen.Frame();
+		} else {
+			frame.right = 640;
+			frame.bottom = 480;
+		}
+	}
+
+	/* XXX approximations... */
+	*screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20;
+	*screen_h = (int) frame.bottom - gui.scrollbar_height
+#ifdef FEAT_MENU
+		- gui.menu_height
+#endif
+		- 30;
+}
+
+void
+gui_mch_set_text_area_pos(
+		int		x,
+		int		y,
+		int		w,
+		int		h)
+{
+	if (!gui.vimTextArea)
+		return;
+
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->MoveTo(x, y);
+		gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+
+/*#ifdef FEAT_GUI_TABLINE
+		if(gui.vimForm->TabLine() != NULL) {
+			gui.vimForm->TabLine()->ResizeTo(w, gui.vimForm->TablineHeight());
+		}
+#endif //FEAT_GUI_TABLINE*/
+
+		gui.vimWindow->Unlock();
+	}
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+void
+gui_mch_enable_scrollbar(
+		scrollbar_T	*sb,
+		int		flag)
+{
+	VimScrollBar *vsb = sb->id;
+	if (gui.vimWindow->Lock()) {
+		/*
+		 * This function is supposed to be idempotent, but Show()/Hide()
+		 * is not. Therefore we test if they are needed.
+		 */
+		if (flag) {
+			if (vsb->IsHidden()) {
+				vsb->Show();
+			}
+		} else {
+			if (!vsb->IsHidden()) {
+				vsb->Hide();
+			}
+		}
+		gui.vimWindow->Unlock();
+	}
+}
+
+void
+gui_mch_set_scrollbar_thumb(
+		scrollbar_T *sb,
+		int		val,
+		int		size,
+		int		max)
+{
+	if (gui.vimWindow->Lock()) {
+		VimScrollBar *s = sb->id;
+		if (max == 0) {
+			s->SetValue(0);
+			s->SetRange(0.0, 0.0);
+		} else {
+			s->SetProportion((float)size / (max + 1.0));
+			s->SetSteps(1.0, size > 5 ? size - 2 : size);
+#ifndef SCROLL_PAST_END		// really only defined in gui.c...
+			max = max + 1 - size;
+#endif
+			if (max < s->Value()) {
+				/*
+				 * If the new maximum is lower than the current value,
+				 * setting it would cause the value to be clipped and
+				 * therefore a ValueChanged() call.
+				 * We avoid this by setting the value first, because
+				 * it presumably is <= max.
+				 */
+				s->SetValue(val);
+				s->SetRange(0.0, max);
+			} else {
+				/*
+				 * In the other case, set the range first, since the
+				 * new value might be higher than the current max.
+				 */
+				s->SetRange(0.0, max);
+				s->SetValue(val);
+			}
+		}
+		gui.vimWindow->Unlock();
+	}
+}
+
+void
+gui_mch_set_scrollbar_pos(
+		scrollbar_T *sb,
+		int		x,
+		int		y,
+		int		w,
+		int		h)
+{
+	if (gui.vimWindow->Lock()) {
+		BRect winb = gui.vimWindow->Bounds();
+		float vsbx = x, vsby = y;
+		VimScrollBar *vsb = sb->id;
+		vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+		if(winb.right-(x+w)<w) vsbx = winb.right - (w - PEN_WIDTH);
+		vsb->MoveTo(vsbx, vsby);
+		gui.vimWindow->Unlock();
+	}
+}
+
+void
+gui_mch_create_scrollbar(
+		scrollbar_T *sb,
+		int		orient)		/* SBAR_VERT or SBAR_HORIZ */
+{
+	orientation posture =
+		(orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL;
+
+	VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture);
+	if (gui.vimWindow->Lock()) {
+		vsb->SetTarget(gui.vimTextArea);
+		vsb->Hide();
+		gui.vimForm->AddChild(vsb);
+		gui.vimWindow->Unlock();
+	}
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+void
+gui_mch_destroy_scrollbar(
+		scrollbar_T	*sb)
+{
+	if (gui.vimWindow->Lock()) {
+		sb->id->RemoveSelf();
+		delete sb->id;
+		gui.vimWindow->Unlock();
+	}
+}
+#endif
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE	not blinking at all
+ * BLINK_OFF	blinking, cursor is not shown
+ * BLINK_ON	blinking, cursor is shown
+ */
+
+#define BLINK_NONE  0
+#define BLINK_OFF   1
+#define BLINK_ON    2
+
+static int		blink_state = BLINK_NONE;
+static long_u		blink_waittime = 700;
+static long_u		blink_ontime = 400;
+static long_u		blink_offtime = 250;
+static int	blink_timer = 0;
+
+void
+gui_mch_set_blinking(
+		long    waittime,
+		long    on,
+		long    off)
+{
+	/* TODO */
+	blink_waittime = waittime;
+	blink_ontime = on;
+	blink_offtime = off;
+}
+
+/*
+ * Stop the cursor blinking.  Show the cursor if it wasn't shown.
+ */
+	void
+gui_mch_stop_blink()
+{
+	/* TODO */
+	if (blink_timer != 0)
+	{
+		//XtRemoveTimeOut(blink_timer);
+		blink_timer = 0;
+	}
+	if (blink_state == BLINK_OFF)
+		gui_update_cursor(TRUE, FALSE);
+	blink_state = BLINK_NONE;
+}
+
+/*
+ * Start the cursor blinking.  If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+	void
+gui_mch_start_blink()
+{
+	/* TODO */
+	if (blink_timer != 0)
+		;//XtRemoveTimeOut(blink_timer);
+	/* Only switch blinking on if none of the times is zero */
+	if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+	{
+		blink_timer = 1; //XtAppAddTimeOut(app_context, blink_waittime,
+		blink_state = BLINK_ON;
+		gui_update_cursor(TRUE, FALSE);
+	}
+}
+
+/*
+ * Initialise vim to use the font with the given name.	Return FAIL if the font
+ * could not be loaded, OK otherwise.
+ */
+int
+gui_mch_init_font(
+		char_u		*font_name,
+		int			fontset)
+{
+	if (gui.vimWindow->Lock())
+	{
+		int rc = gui.vimTextArea->mchInitFont(font_name);
+		gui.vimWindow->Unlock();
+
+		return rc;
+	}
+
+	return FAIL;
+}
+
+	int
+gui_mch_adjust_charsize()
+{
+	return FAIL;
+}
+
+
+
+GuiFont
+gui_mch_get_font(
+		char_u		*name,
+		int			giveErrorIfMissing)
+{
+	VimFont		*font = NOFONT;
+	static VimFont *fontList = NULL;
+
+	if (!gui.in_use)		    /* can't do this when GUI not running */
+		return NOFONT;
+
+	// storage for locally modified name;
+	const int buff_size = B_FONT_FAMILY_LENGTH + B_FONT_STYLE_LENGTH + 20;
+	static char font_name[buff_size] = {0};
+	font_family family = {0};
+	font_style  style  = {0};
+
+	if (name == 0 && be_fixed_font == 0) {
+		if(giveErrorIfMissing)
+			EMSG2("(fe0) default font is not defined", name);
+		return NOFONT;
+	}
+
+	if (name != 0) {
+		STRNCPY(font_name, name, buff_size);
+		// replace underscores with spaces
+		char* end = 0;
+		while (end = strchr((char *)font_name, '_'))
+			*end = ' ';
+	} else {
+		be_fixed_font->GetFamilyAndStyle(&family, &style);
+		vim_snprintf(font_name, buff_size, (char*)"%s/%s/%.0f", 
+				family, style, be_fixed_font->Size());	
+	}
+
+	VimFont *flp;
+	for (flp = fontList; flp; flp = flp->next) {
+		if (STRCMP(font_name, flp->name) == 0) {
+			flp->refcount++;
+			return (GuiFont)flp;
+		}
+	}
+
+	// create font and store the name before strtok corrupt the buffer ;-)
+	font = new VimFont();
+	font->name = vim_strsave((char_u*)font_name);
+
+	strncpy(family, strtok(font_name, "/\0"), B_FONT_FAMILY_LENGTH);
+
+	char* style_s = strtok(0, "/\0");
+	if(style_s != 0)
+		strncpy(style,  style_s, B_FONT_STYLE_LENGTH);
+
+	float size = atof((style_s != 0) ? strtok(0, "/\0") : "0");
+
+	if(count_font_styles(family) <= 0) {
+		if (giveErrorIfMissing)
+			EMSG2("(fe0) Specified font %s is not found", font->name);
+		delete font;
+		return NOFONT;
+	}
+
+	/* Remember font in the static list for later use */
+	font->next = fontList;
+	fontList = font;
+
+	font->SetFamilyAndStyle(family, style);
+	if(size > 0.f) 
+		font->SetSize(size);
+
+	font->SetSpacing(B_FIXED_SPACING);
+	font->SetEncoding(B_UNICODE_UTF8);
+
+	return (GuiFont)font;
+}
+
+/*
+ * Set the current text font.
+ */
+void
+gui_mch_set_font(
+		GuiFont	font)
+{
+	if (gui.vimWindow->Lock()) {
+		VimFont *vf = (VimFont *)font;
+
+		gui.vimTextArea->SetFont(vf);
+
+		gui.char_width = (int) vf->StringWidth("n");
+		font_height fh;
+		vf->GetHeight(&fh);
+		gui.char_height = (int)(fh.ascent + 0.9999)
+			+ (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999);
+		gui.char_ascent = (int)(fh.ascent + 0.9999);
+
+		gui.vimWindow->Unlock();
+	}
+}
+
+/* XXX TODO This is apparently never called... */
+void
+gui_mch_free_font(
+		GuiFont	font)
+{
+	if(font == NOFONT)
+		return;
+	VimFont *f = (VimFont *)font;
+	if (--f->refcount <= 0) {
+		if (f->refcount < 0)
+			fprintf(stderr, "VimFont: refcount < 0\n");
+		delete f;
+	}
+}
+
+	char_u *
+gui_mch_get_fontname(GuiFont font, char_u *name)
+{
+	if (name == NULL)
+		return NULL;
+	return vim_strsave(name);
+}
+
+/*
+ * Adjust gui.char_height (after 'linespace' was changed).
+ */
+	int
+gui_mch_adjust_charheight()
+{
+
+	//TODO: linespace support?
+
+//#ifdef FEAT_XFONTSET
+//	if (gui.fontset != NOFONTSET)
+//	{
+//	gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace;
+//	gui.char_ascent = fontset_ascent((XFontSet)gui.fontset)
+//	+ p_linespace / 2;
+//	}
+//	else
+//#endif
+	{
+		VimFont *font = (VimFont *)gui.norm_font;
+		font_height fh = {0};
+		font->GetHeight(&fh);
+		gui.char_height = (int)(fh.ascent + fh.descent + 0.5) + p_linespace;
+		gui.char_ascent = (int)(fh.ascent + 0.5) + p_linespace / 2;
+	}
+	return OK;
+}
+
+	void
+gui_mch_getmouse(int *x, int *y)
+{
+	fprintf(stderr, "gui_mch_getmouse");
+
+	/*int		rootx, rooty, winx, winy;
+	  Window	root, child;
+	  unsigned int mask;
+
+	  if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
+	  &rootx, &rooty, &winx, &winy, &mask)) {
+	 *x = winx;
+	 *y = winy;
+	 } else*/ {
+		 *x = -1;
+		 *y = -1;
+	 }
+}
+
+	void
+gui_mch_mousehide(int hide)
+{
+	fprintf(stderr, "gui_mch_getmouse");
+	// TODO
+}
+
+	static int
+hex_digit(int c)
+{
+	if (isdigit(c))
+		return c - '0';
+	c = TOLOWER_ASC(c);
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return -1000;
+}
+
+/*
+ * This function has been lifted from gui_w32.c and extended a bit.
+ *
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+guicolor_T
+gui_mch_get_color(
+		char_u	*name)
+{
+	typedef struct GuiColourTable
+	{
+		const char    *name;
+		guicolor_T     colour;
+	} GuiColourTable;
+
+#define NSTATIC_COLOURS		50 //32
+#define NDYNAMIC_COLOURS	33
+#define NCOLOURS		(NSTATIC_COLOURS + NDYNAMIC_COLOURS)
+
+	static GuiColourTable table[NCOLOURS] =
+	{
+		{"Black",	    RGB(0x00, 0x00, 0x00)},
+		{"DarkGray",	    RGB(0x80, 0x80, 0x80)},
+		{"DarkGrey",	    RGB(0x80, 0x80, 0x80)},
+		{"Gray",	    RGB(0xC0, 0xC0, 0xC0)},
+		{"Grey",	    RGB(0xC0, 0xC0, 0xC0)},
+		{"LightGray",	    RGB(0xD3, 0xD3, 0xD3)},
+		{"LightGrey",	    RGB(0xD3, 0xD3, 0xD3)},
+		{"Gray10",	    RGB(0x1A, 0x1A, 0x1A)},
+		{"Grey10",	    RGB(0x1A, 0x1A, 0x1A)},
+		{"Gray20",	    RGB(0x33, 0x33, 0x33)},
+		{"Grey20",	    RGB(0x33, 0x33, 0x33)},
+		{"Gray30",	    RGB(0x4D, 0x4D, 0x4D)},
+		{"Grey30",	    RGB(0x4D, 0x4D, 0x4D)},
+		{"Gray40",	    RGB(0x66, 0x66, 0x66)},
+		{"Grey40",	    RGB(0x66, 0x66, 0x66)},
+		{"Gray50",	    RGB(0x7F, 0x7F, 0x7F)},
+		{"Grey50",	    RGB(0x7F, 0x7F, 0x7F)},
+		{"Gray60",	    RGB(0x99, 0x99, 0x99)},
+		{"Grey60",	    RGB(0x99, 0x99, 0x99)},
+		{"Gray70",	    RGB(0xB3, 0xB3, 0xB3)},
+		{"Grey70",	    RGB(0xB3, 0xB3, 0xB3)},
+		{"Gray80",	    RGB(0xCC, 0xCC, 0xCC)},
+		{"Grey80",	    RGB(0xCC, 0xCC, 0xCC)},
+		{"Gray90",	    RGB(0xE5, 0xE5, 0xE5)},
+		{"Grey90",	    RGB(0xE5, 0xE5, 0xE5)},
+		{"White",	    RGB(0xFF, 0xFF, 0xFF)},
+		{"DarkRed",	    RGB(0x80, 0x00, 0x00)},
+		{"Red",		    RGB(0xFF, 0x00, 0x00)},
+		{"LightRed",	    RGB(0xFF, 0xA0, 0xA0)},
+		{"DarkBlue",	    RGB(0x00, 0x00, 0x80)},
+		{"Blue",	    RGB(0x00, 0x00, 0xFF)},
+		{"LightBlue",	    RGB(0xA0, 0xA0, 0xFF)},
+		{"DarkGreen",	    RGB(0x00, 0x80, 0x00)},
+		{"Green",	    RGB(0x00, 0xFF, 0x00)},
+		{"LightGreen",	    RGB(0xA0, 0xFF, 0xA0)},
+		{"DarkCyan",	    RGB(0x00, 0x80, 0x80)},
+		{"Cyan",	    RGB(0x00, 0xFF, 0xFF)},
+		{"LightCyan",	    RGB(0xA0, 0xFF, 0xFF)},
+		{"DarkMagenta",	    RGB(0x80, 0x00, 0x80)},
+		{"Magenta",	    RGB(0xFF, 0x00, 0xFF)},
+		{"LightMagenta",    RGB(0xFF, 0xA0, 0xFF)},
+		{"Brown",	    RGB(0x80, 0x40, 0x40)},
+		{"Yellow",	    RGB(0xFF, 0xFF, 0x00)},
+		{"LightYellow",	    RGB(0xFF, 0xFF, 0xA0)},
+		{"DarkYellow",	    RGB(0xBB, 0xBB, 0x00)},
+		{"SeaGreen",	    RGB(0x2E, 0x8B, 0x57)},
+		{"Orange",	    RGB(0xFF, 0xA5, 0x00)},
+		{"Purple",	    RGB(0xA0, 0x20, 0xF0)},
+		{"SlateBlue",	    RGB(0x6A, 0x5A, 0xCD)},
+		{"Violet",	    RGB(0xEE, 0x82, 0xEE)},
+		// NOTE: some entries are zero-allocated for NDDYNAMIC_COLORS 
+		//		 in this table!
+	};
+
+	static int endColour = NSTATIC_COLOURS;
+	static int newColour = NSTATIC_COLOURS;
+
+	int		    r, g, b;
+	int		    i;
+
+	if (name[0] == '#' && STRLEN(name) == 7)
+	{
+		/* Name is in "#rrggbb" format */
+		r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+		g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+		b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+		if (r < 0 || g < 0 || b < 0)
+			return INVALCOLOR;
+		return RGB(r, g, b);
+	}
+	else
+	{
+		/* Check if the name is one of the colours we know */
+		for (i = 0; i < endColour; i++)
+			if (STRICMP(name, table[i].name) == 0)
+				return table[i].colour;
+	}
+
+	/*
+	 * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
+	 */
+	{
+#define LINE_LEN 100
+		FILE	*fd;
+		char	line[LINE_LEN];
+		char_u	*fname;
+
+		fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+		if (fname == NULL)
+			return INVALCOLOR;
+
+		fd = fopen((char *)fname, "rt");
+		vim_free(fname);
+		if (fd == NULL)
+			return INVALCOLOR;
+
+		while (!feof(fd))
+		{
+			int	    len;
+			int	    pos;
+			char    *colour;
+
+			fgets(line, LINE_LEN, fd);
+			len = strlen(line);
+
+			if (len <= 1 || line[len-1] != '\n')
+				continue;
+
+			line[len-1] = '\0';
+
+			i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+			if (i != 3)
+				continue;
+
+			colour = line + pos;
+
+			if (STRICMP(colour, name) == 0)
+			{
+				fclose(fd);
+				/*
+				 * Now remember this colour in the table.
+				 * A LRU scheme might be better but this is simpler.
+				 * Or could use a growing array.
+				 */
+				guicolor_T gcolour = RGB(r,g,b);
+
+				//NOTE: see note above in table allocation! We are working here with 
+				//		dynamically allocated names, not constant ones!
+				vim_free((char*)table[newColour].name);
+				table[newColour].name = (char *)vim_strsave((char_u *)colour);
+				table[newColour].colour = gcolour;
+
+				newColour++;
+				if (newColour >= NCOLOURS)
+					newColour = NSTATIC_COLOURS;
+				if (endColour < NCOLOURS)
+					endColour = newColour;
+
+				return gcolour;
+			}
+		}
+
+		fclose(fd);
+	}
+
+	return INVALCOLOR;
+}
+
+/*
+ * Set the current text foreground color.
+ */
+void
+gui_mch_set_fg_color(
+		guicolor_T	color)
+{
+	rgb_color rgb = GUI_TO_RGB(color);
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->SetHighColor(rgb);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Set the current text background color.
+ */
+void
+gui_mch_set_bg_color(
+		guicolor_T	color)
+{
+	rgb_color rgb = GUI_TO_RGB(color);
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->SetLowColor(rgb);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Set the current text special color.
+ */
+	void
+gui_mch_set_sp_color(guicolor_T	color)
+{
+	//prev_sp_color = color;
+}
+
+void
+gui_mch_draw_string(
+		int		row,
+		int		col,
+		char_u	*s,
+		int		len,
+		int		flags)
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->mchDrawString(row, col, s, len, flags);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+int
+gui_mch_haskey(
+		char_u	*name)
+{
+	int i;
+
+	for (i = 0; special_keys[i].BeKeys != 0; i++)
+		if (name[0] == special_keys[i].vim_code0 &&
+				name[1] == special_keys[i].vim_code1)
+			return OK;
+	return FAIL;
+}
+
+	void
+gui_mch_beep()
+{
+	::beep();
+}
+
+	void
+gui_mch_flash(int msec)
+{
+	/* Do a visual beep by reversing the foreground and background colors */
+
+	if (gui.vimWindow->Lock()) {
+		BRect rect = gui.vimTextArea->Bounds();
+
+		gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+		gui.vimTextArea->FillRect(rect);
+		gui.vimTextArea->Sync();
+		snooze(msec * 1000);	 /* wait for a few msec */
+		gui.vimTextArea->FillRect(rect);
+		gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+		gui.vimTextArea->Flush();
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+void
+gui_mch_invert_rectangle(
+		int		r,
+		int		c,
+		int		nr,
+		int		nc)
+{
+	BRect rect;
+	rect.left = FILL_X(c);
+	rect.top = FILL_Y(r);
+	rect.right = rect.left + nc * gui.char_width - PEN_WIDTH;
+	rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH;
+
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+		gui.vimTextArea->FillRect(rect);
+		gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Iconify the GUI window.
+ */
+	void
+gui_mch_iconify()
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->Minimize(true);
+		gui.vimWindow->Unlock();
+	}
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+	void
+gui_mch_set_foreground()
+{
+	/* TODO */
+}
+#endif
+
+/*
+ * Set the window title
+ */
+void
+gui_mch_settitle(
+		char_u	*title,
+		char_u	*icon)
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->SetTitle((char *)title);
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+	void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+	gui_mch_set_fg_color(color);
+
+	BRect r;
+	r.left = FILL_X(gui.col);
+	r.top = FILL_Y(gui.row);
+#ifdef FEAT_MBYTE
+	int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); //TODO-TODO
+	if(cells>=4) cells = 1;
+	r.right = r.left + cells*gui.char_width - PEN_WIDTH;
+#else
+	r.right = r.left + gui.char_width - PEN_WIDTH;
+#endif
+	r.bottom = r.top + gui.char_height - PEN_WIDTH;
+
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->StrokeRect(r);
+		gui.vimWindow->Unlock();
+		//gui_mch_flush();
+	}
+}
+
+/*
+ * Draw part of a cursor, only w pixels wide, and h pixels high.
+ */
+void
+gui_mch_draw_part_cursor(
+		int		w,
+		int		h,
+		guicolor_T	color)
+{
+	gui_mch_set_fg_color(color);
+
+	BRect r;
+	r.left =
+#ifdef FEAT_RIGHTLEFT
+		/* vertical line should be on the right of current point */
+		CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+		FILL_X(gui.col);
+	r.right = r.left + w - PEN_WIDTH;
+	r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH;
+	r.top = r.bottom - h + PEN_WIDTH;
+
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->FillRect(r);
+		gui.vimWindow->Unlock();
+		//gui_mch_flush();
+	}
+}
+
+/*
+ * Catch up with any queued events.  This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc.  If there is
+ * nothing in the event queue (& no timers pending), then we return
+ * immediately.
+ */
+	void
+gui_mch_update()
+{
+	gui_mch_flush();
+	while (port_count(gui.vdcmp) > 0 &&
+			!vim_is_input_buf_full() &&
+			gui_beos_process_event(0) >= B_OK)
+		/* nothing */ ;
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars().  Waits for a character
+ * from the keyboard.
+ *	wtime == -1		Wait forever.
+ *	wtime == 0		This should never happen.
+ *	wtime > 0		Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+int
+gui_mch_wait_for_chars(
+		int		wtime)
+{
+	int		    focus;
+	bigtime_t	    until, timeout;
+	status_t	    st;
+
+	if (wtime >= 0) {
+		timeout = wtime * 1000;
+		until = system_time() + timeout;
+	} else {
+		timeout = B_INFINITE_TIMEOUT;
+	}
+
+	focus = gui.in_focus;
+	for (;;)
+	{
+		/* Stop or start blinking when focus changes */
+		if (gui.in_focus != focus)
+		{
+			if (gui.in_focus)
+				gui_mch_start_blink();
+			else
+				gui_mch_stop_blink();
+			focus = gui.in_focus;
+		}
+
+		gui_mch_flush();
+		/*
+		 * Don't use gui_mch_update() because then we will spin-lock until a
+		 * char arrives, instead we use gui_beos_process_event() to hang until
+		 * an event arrives.  No need to check for input_buf_full because we
+		 * are returning as soon as it contains a single char.
+		 */
+		st = gui_beos_process_event(timeout);
+
+		if (input_available())
+			return OK;
+		if (st < B_OK)		    /* includes B_TIMED_OUT */
+			return FAIL;
+
+		/*
+		 * Calculate how much longer we're willing to wait for the
+		 * next event.
+		 */
+		if (wtime >= 0) {
+			timeout = until - system_time();
+			if (timeout < 0)
+				break;
+		}
+	}
+	return FAIL;
+
+}
+
+/*
+ * Output routines.
+ */
+
+/*
+ * Flush any output to the screen. This is typically called before
+ * the app goes to sleep.
+ */
+	void
+gui_mch_flush()
+{
+	// does this need to lock the window? Apparently not but be safe.
+	if (gui.vimWindow->Lock()) {
+		gui.vimWindow->Flush();
+		gui.vimWindow->Unlock();
+	}
+	return;
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+void
+gui_mch_clear_block(
+		int		row1,
+		int		col1,
+		int		row2,
+		int		col2)
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->mchClearBlock(row1, col1, row2, col2);
+		gui.vimWindow->Unlock();
+	}
+}
+
+	void
+gui_mch_clear_all()
+{
+	if (gui.vimWindow->Lock()) {
+		gui.vimTextArea->mchClearAll();
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+void
+gui_mch_delete_lines(
+		int		row,
+		int		num_lines)
+{
+	gui.vimTextArea->mchDeleteLines(row, num_lines);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+void
+gui_mch_insert_lines(
+		int		row,
+		int		num_lines)
+{
+	gui.vimTextArea->mchInsertLines(row, num_lines);
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Menu stuff.
+ */
+
+void
+gui_mch_enable_menu(
+		int		flag)
+{
+	if (gui.vimWindow->Lock())
+	{
+		BMenuBar *menubar = gui.vimForm->MenuBar();
+		menubar->SetEnabled(flag);
+		gui.vimWindow->Unlock();
+	}
+}
+
+void
+gui_mch_set_menu_pos(
+		int		x,
+		int		y,
+		int		w,
+		int		h)
+{
+	/* It will be in the right place anyway */
+}
+
+/*
+ * Add a sub menu to the menu bar.
+ */
+void
+gui_mch_add_menu(
+		vimmenu_T	*menu,
+		int		idx)
+{
+	vimmenu_T	*parent = menu->parent;
+
+	// popup menu - just create it unattached
+	if (menu_is_popup(menu->name) && parent == NULL) {
+		BPopUpMenu* popUpMenu = new BPopUpMenu((const char*)menu->name, false, false);
+		menu->submenu_id = popUpMenu;
+		menu->id = NULL;
+		return;
+	}
+
+	if (!menu_is_menubar(menu->name)
+			|| (parent != NULL && parent->submenu_id == NULL))
+		return;
+
+	if (gui.vimWindow->Lock())
+	{
+		/* Major re-write of the menu code, it was failing with memory corruption when
+		 * we started loading multiple files (the Buffer menu)
+		 *
+		 * Note we don't use the preference values yet, all are inserted into the
+		 * menubar on a first come-first served basis...
+		 *
+		 * richard@whitequeen.com jul 99
+		 */
+
+		BMenu *tmp;
+
+		if ( parent )
+			tmp = parent->submenu_id;
+		else
+			tmp = gui.vimForm->MenuBar();
+		// make sure we don't try and add the same menu twice. The Buffers menu tries to
+		// do this and Be starts to crash...
+
+		if ( ! tmp->FindItem((const char *) menu->dname)) {
+
+			BMenu *bmenu = new BMenu((char *)menu->dname);
+
+			menu->submenu_id = bmenu;
+
+			// when we add a BMenu to another Menu, it creates the interconnecting BMenuItem
+			tmp->AddItem(bmenu);
+
+			// Now its safe to query the menu for the associated MenuItem....
+			menu->id = tmp->FindItem((const char *) menu->dname);
+
+		}
+		gui.vimWindow->Unlock();
+	}
+}
+
+	void
+gui_mch_toggle_tearoffs(int enable)
+{
+	/* no tearoff menus */
+}
+
+	static BMessage *
+MenuMessage(vimmenu_T *menu)
+{
+	BMessage *m = new BMessage('menu');
+	m->AddPointer("VimMenu", (void *)menu);
+
+	return m;
+}
+
+/*
+ * Add a menu item to a menu
+ */
+void
+gui_mch_add_menu_item(
+		vimmenu_T	*menu,
+		int		idx)
+{
+	int		mnemonic = 0;
+	vimmenu_T	*parent = menu->parent;
+
+	/* TODO: use menu->actext */
+	/* This is difficult, since on Be, an accelerator must be a single char
+	 * and a lot of Vim ones are the standard VI commands.
+	 *
+	 * Punt for Now...
+	 * richard@whiequeen.com jul 99
+	 */
+	if (gui.vimWindow->Lock())
+	{
+#ifdef FEAT_TOOLBAR
+		if(menu_is_toolbar(parent->name)) { 
+			VimToolbar *toolbar = gui.vimForm->ToolBar();
+			if(toolbar != NULL) {
+				toolbar->AddButton(idx, menu);
+			}
+		} else
+#endif	
+
+		if (parent->submenu_id != NULL || menu_is_popup(parent->name)) { 
+			if (menu_is_separator(menu->name)) {
+				BSeparatorItem *item = new BSeparatorItem();
+				parent->submenu_id->AddItem(item);
+				menu->id = item;
+				menu->submenu_id = NULL;
+			}
+			else {
+				BMenuItem *item = new BMenuItem((char *)menu->dname,
+						MenuMessage(menu));
+				item->SetTarget(gui.vimTextArea);
+				item->SetTrigger((char) menu->mnemonic);
+				parent->submenu_id->AddItem(item);
+				menu->id = item;
+				menu->submenu_id = NULL;
+			}
+		}
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+void
+gui_mch_destroy_menu(
+		vimmenu_T	*menu)
+{
+	if (gui.vimWindow->Lock())
+	{
+#ifdef FEAT_TOOLBAR
+		if(menu->parent && menu_is_toolbar(menu->parent->name)) {
+			VimToolbar *toolbar = gui.vimForm->ToolBar();
+			if(toolbar != NULL) {
+				toolbar->RemoveButton(menu);
+			}
+		} else
+#endif
+		{
+			assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0);
+			/*
+			 * Detach this menu from its parent, so that it is not deleted
+			 * twice once we get to delete that parent.
+			 * Deleting a BMenuItem also deletes the associated BMenu, if any
+			 * (which does not have any items anymore since they were
+			 * removed and deleted before).
+			 */
+			BMenu *bmenu = menu->id->Menu();
+			if (bmenu)
+			{
+				bmenu->RemoveItem(menu->id);
+				/*
+				 * If we removed the last item from the menu bar,
+				 * resize it out of sight.
+				 */
+				if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0)
+				{
+					bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN);
+				}
+			}
+			delete menu->id;
+			menu->id = NULL;
+			menu->submenu_id = NULL;
+
+			gui.menu_height = (int) gui.vimForm->MenuHeight();
+		}
+		gui.vimWindow->Unlock();
+	}
+}
+
+/*
+ * Make a menu either grey or not grey.
+ */
+void
+gui_mch_menu_grey(
+		vimmenu_T	*menu,
+		int		grey)
+{
+#ifdef FEAT_TOOLBAR
+	if(menu->parent && menu_is_toolbar(menu->parent->name)) {
+		if (gui.vimWindow->Lock()) {
+			VimToolbar *toolbar = gui.vimForm->ToolBar();
+			if(toolbar != NULL) {
+				toolbar->GrayButton(menu, grey);
+			}
+			gui.vimWindow->Unlock();
+		}
+	} else
+#endif
+	if (menu->id != NULL)
+		menu->id->SetEnabled(!grey);
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+void
+gui_mch_menu_hidden(
+		vimmenu_T	*menu,
+		int		hidden)
+{
+	if (menu->id != NULL)
+		menu->id->SetEnabled(!hidden);
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+	void
+gui_mch_draw_menubar()
+{
+	/* Nothing to do in BeOS */
+}
+
+	void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+	if (!menu_is_popup(menu->name) || menu->submenu_id == NULL)
+		return;
+
+	BPopUpMenu* popupMenu = dynamic_cast<BPopUpMenu*>(menu->submenu_id);
+	if (popupMenu == NULL)
+		return;
+
+	BPoint point;
+	if(gui.vimWindow->Lock()) {
+		uint32 buttons = 0;
+		gui.vimTextArea->GetMouse(&point, &buttons);
+		gui.vimTextArea->ConvertToScreen(&point);
+		gui.vimWindow->Unlock();
+	}
+	popupMenu->Go(point, true);
+}
+
+#endif /* FEAT_MENU */
+
+/* Mouse stuff */
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Clipboard stuff, for cutting and pasting text to other windows.
+ */
+char textplain[] = "text/plain";
+char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype";
+
+/*
+ * Get the current selection and put it in the clipboard register.
+ */
+	void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+	if (be_clipboard->Lock())
+	{
+		BMessage *m = be_clipboard->Data();
+		//m->PrintToStream();
+
+		char_u *string = NULL;
+		ssize_t stringlen = -1;
+
+		if (m->FindData(textplain, B_MIME_TYPE,
+					(const void **)&string, &stringlen) == B_OK
+				|| m->FindString("text", (const char **)&string) == B_OK)
+		{
+			if (stringlen == -1)
+				stringlen = STRLEN(string);
+
+			int type;
+			char *seltype;
+			ssize_t seltypelen;
+
+			/*
+			 * Try to get the special vim selection type first
+			 */
+			if (m->FindData(vimselectiontype, B_MIME_TYPE,
+						(const void **)&seltype, &seltypelen) == B_OK)
+			{
+				switch (*seltype)
+				{
+					default:
+					case 'L':	type = MLINE;	break;
+					case 'C':	type = MCHAR;	break;
+#ifdef FEAT_VISUAL
+					case 'B':	type = MBLOCK;	break;
+#endif
+				}
+			}
+			else
+			{
+				/* Otherwise use heuristic as documented */
+				type = memchr(string, stringlen, '\n') ? MLINE : MCHAR;
+			}
+			clip_yank_selection(type, string, (long)stringlen, cbd);
+		}
+		be_clipboard->Unlock();
+	}
+}
+/*
+ * Make vim the owner of the current selection.
+ */
+	void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+	/* Nothing needs to be done here */
+}
+
+/*
+ * Make vim the owner of the current selection.  Return OK upon success.
+ */
+	int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+	/*
+	 * Never actually own the clipboard.  If another application sets the
+	 * clipboard, we don't want to think that we still own it.
+	 */
+	return FAIL;
+}
+
+/*
+ * Send the current selection to the clipboard.
+ */
+	void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+	if (be_clipboard->Lock())
+	{
+		be_clipboard->Clear();
+		BMessage *m = be_clipboard->Data();
+		assert(m);
+
+		/* If the '*' register isn't already filled in, fill it in now */
+		cbd->owned = TRUE;
+		clip_get_selection(cbd);
+		cbd->owned = FALSE;
+
+		char_u  *str = NULL;
+		long_u  count;
+		int	type;
+
+		type = clip_convert_selection(&str, &count, cbd);
+
+		if (type < 0)
+			return;
+
+		m->AddData(textplain, B_MIME_TYPE, (void *)str, count);
+
+		/* Add type of selection */
+		char    vtype;
+		switch (type)
+		{
+			default:
+			case MLINE:    vtype = 'L';    break;
+			case MCHAR:    vtype = 'C';    break;
+#ifdef FEAT_VISUAL
+			case MBLOCK:   vtype = 'B';    break;
+#endif
+		}
+		m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1);
+
+		vim_free(str);
+
+		be_clipboard->Commit();
+		be_clipboard->Unlock();
+	}
+}
+
+#endif	/* FEAT_CLIPBOARD */
+
+#ifdef FEAT_BROWSE
+/*
+ * Pop open a file browser and return the file selected, in allocated memory,
+ * or NULL if Cancel is hit.
+ *  saving  - TRUE if the file will be saved to, FALSE if it will be opened.
+ *  title   - Title message for the file browser dialog.
+ *  dflt    - Default name of file.
+ *  ext     - Default extension to be added to files without extensions.
+ *  initdir - directory in which to open the browser (NULL = current dir)
+ *  filter  - Filter for matched files to choose from.
+ *  Has a format like this:
+ *  "C Files (*.c)\0*.c\0"
+ *  "All Files\0*.*\0\0"
+ *  If these two strings were concatenated, then a choice of two file
+ *  filters will be selectable to the user.  Then only matching files will
+ *  be shown in the browser.  If NULL, the default allows all files.
+ *
+ *  *NOTE* - the filter string must be terminated with TWO nulls.
+ */
+char_u *
+gui_mch_browse(
+		int saving,
+		char_u *title,
+		char_u *dflt,
+		char_u *ext,
+		char_u *initdir,
+		char_u *filter)
+{
+	gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL, 
+			NULL, NULL, 0, false, 
+			new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true);
+	
+	gui.vimApp->fBrowsedPath.Unset();
+
+	gui.vimApp->fFilePanel->Window()->SetTitle((char*)title);
+	gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir);
+
+	gui.vimApp->fFilePanel->Show();
+
+	gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem");
+
+	while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED);
+
+	char_u *fileName = NULL;
+	status_t result = gui.vimApp->fBrowsedPath.InitCheck();
+	if(result == B_OK) {
+		fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path());
+	} else
+		if(result != B_NO_INIT) {
+			fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n", 
+					result, strerror(result));
+		}
+
+	delete gui.vimApp->fFilePanel;
+	gui.vimApp->fFilePanel = NULL;
+
+	return fileName;
+}
+#endif /* FEAT_BROWSE */
+
+
+#if defined(FEAT_GUI_DIALOG)
+
+/*
+ * Create a dialog dynamically from the parameter strings.
+ * type		= type of dialog (question, alert, etc.)
+ * title	= dialog title. may be NULL for default title.
+ * message	= text to display. Dialog sizes to accommodate it.
+ * buttons	= '\n' separated list of button captions, default first.
+ * dfltbutton	= number of default button.
+ *
+ * This routine returns 1 if the first button is pressed,
+ *			2 for the second, etc.
+ *
+ *			0 indicates Esc was pressed.
+ *			-1 for unexpected error
+ *
+ * If stubbing out this fn, return 1.
+ */
+
+int
+gui_mch_dialog(
+		int		 type,
+		char_u	*title,
+		char_u	*message,
+		char_u	*buttons,
+		int		 dfltbutton,
+		char_u	*textfield)
+{
+	VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message, 
+			(char*)buttons, dfltbutton, (char*)textfield);
+	return dialog->Go();
+}
+
+#endif /* FEAT_GUI_DIALOG */
+
+
+/*
+ * Return the RGB value of a pixel as long.
+ */
+	long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+	rgb_color rgb = GUI_TO_RGB(pixel);
+
+	return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8)
+		+ (rgb.blue & 0xff);
+}
+
+	void
+gui_mch_setmouse(int x, int y)
+{
+	TRACE();
+	/* TODO */
+}
+
+#ifdef FEAT_MBYTE_IME
+	void
+im_set_position(int row, int col)
+{
+	if(gui.vimWindow->Lock())
+	{
+		gui.vimTextArea->DrawIMString();
+		gui.vimWindow->Unlock();
+	}
+	return;
+}
+
+	void
+im_set_active(int activate)
+{
+	//TODO:
+#if 0
+	if(activate)
+		printf("IME ON\n");
+	else
+		printf("IME OFF\n");
+#endif
+	return;
+}
+
+	int 
+im_get_status()
+{
+	//TODO:
+	return(1);
+}
+#endif
+
+	void
+gui_mch_show_toolbar(int showit)
+{
+	VimToolbar *toolbar = gui.vimForm->ToolBar();
+	gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.;
+}
+
+	void 
+gui_mch_set_toolbar_pos(int x, int y, int w, int h)
+{
+	VimToolbar *toolbar = gui.vimForm->ToolBar();
+	if(toolbar != NULL) {
+		if (gui.vimWindow->Lock()) {
+			toolbar->MoveTo(x, y);
+			toolbar->ResizeTo(w - 1, h - 1);
+			gui.vimWindow->Unlock();
+		}
+	}
+}
+
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+
+/*
+ * Show or hide the tabline.
+ */
+    void
+gui_mch_show_tabline(int showit)
+{
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+
+    if (tabLine == NULL)
+		return;
+
+    if (!showit != !gui.vimForm->IsShowingTabLine()) {
+		gui.vimForm->SetShowingTabLine(showit != 0);
+		gui.tabline_height = gui.vimForm->TablineHeight();
+    }
+}
+
+	void 
+gui_mch_set_tabline_pos(int x, int y, int w, int h)
+{
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+	if(tabLine != NULL) {
+		if (gui.vimWindow->Lock()) {
+			tabLine->MoveTo(x, y);
+			tabLine->ResizeTo(w - 1, h - 1);
+			gui.vimWindow->Unlock();
+		}
+	}
+}
+
+/*
+ * Return TRUE when tabline is displayed.
+ */
+    int
+gui_mch_showing_tabline()
+{
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+    return tabLine != NULL && gui.vimForm->IsShowingTabLine();
+}
+
+/*
+ * Update the labels of the tabline.
+ */
+    void
+gui_mch_update_tabline()
+{
+    tabpage_T	*tp;
+    int		nr = 0;
+    int		curtabidx = 0;
+
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+
+    if (tabLine == NULL)
+		return;
+
+	gui.vimWindow->Lock();
+
+    /* Add a label for each tab page.  They all contain the same text area. */
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) {
+		if (tp == curtab)
+		    curtabidx = nr;
+
+		BTab* tab = tabLine->TabAt(nr);
+
+		if (tab == NULL) {
+			tab = new VimTabLine::VimTab();
+			tabLine->AddTab(NULL, tab);
+		}
+		
+		get_tabline_label(tp, FALSE);
+		tab->SetLabel((const char*)NameBuff);
+		tabLine->Invalidate();
+    }
+
+    /* Remove any old labels. */
+	while (nr < tabLine->CountTabs())
+		tabLine->RemoveTab(nr);
+	
+	if(tabLine->Selection() != curtabidx)
+		tabLine->Select(curtabidx);
+
+	gui.vimWindow->Unlock();
+}
+
+/*
+ * Set the current tab to "nr".  First tab is 1.
+ */
+    void
+gui_mch_set_curtab(int nr)
+{
+	VimTabLine *tabLine = gui.vimForm->TabLine();
+	if(tabLine == NULL)
+		return;
+
+	gui.vimWindow->Lock();
+	
+	if(tabLine->Selection() != nr -1)
+		tabLine->Select(nr -1);
+	
+	gui.vimWindow->Unlock();
+}
+
+#endif //FEAT_GUI_TABLINE
diff --git a/src/gui_beos.h b/src/gui_beos.h
new file mode 100644
index 0000000..7f323cd
--- /dev/null
+++ b/src/gui_beos.h
@@ -0,0 +1,51 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved		by Bram Moolenaar
+ *				GUI support by Olaf "Rhialto" Seibert
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * BeOS GUI.
+ *
+ * GUI support for the Buzzword Enhanced Operating System for PPC.
+ *
+ */
+
+/*
+ * This file must be acceptable both as C and C++.
+ * The BeOS API is defined in terms of C++, but some classes
+ * should be somewhat known in the common C code.
+ */
+
+/* System classes */
+
+struct BMenu;
+struct BMenuItem;
+struct BPictureButton;
+
+/* Our own Vim-related classes */
+
+struct VimApp;
+struct VimFormView;
+struct VimTextAreaView;
+struct VimWindow;
+struct VimScrollBar;
+
+/* Locking functions */
+
+extern int vim_lock_screen();
+extern void vim_unlock_screen();
+
+#ifndef __cplusplus
+
+typedef struct BMenu BMenu;
+typedef struct BMenuItem BMenuItem;
+typedef struct BPictureButton BPictureButton;
+typedef struct VimWindow VimWindow;
+typedef struct VimFormView VimFormView;
+typedef struct VimTextAreaView VimTextAreaView;
+typedef struct VimApp VimApp;
+typedef struct VimScrollBar VimScrollBar;
+
+#endif
diff --git a/src/misc1.c b/src/misc1.c
index fd178c9..b8c838a 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -14,6 +14,10 @@
 #include "vim.h"
 #include "version.h"
 
+#if defined(__HAIKU__)
+#include <storage/FindDirectory.h>
+#endif
+
 static char_u *vim_version_dir __ARGS((char_u *vimdir));
 static char_u *remove_tail __ARGS((char_u *p, char_u *pend, char_u *name));
 static int copy_indent __ARGS((int size, char_u	*src));
@@ -3902,7 +3906,18 @@ vim_getenv(name, mustfree)
 
     vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
     if (!vimruntime && STRCMP(name, "VIM") != 0)
-	return NULL;
+#if defined(__HAIKU__)
+		// special handling for user settings directory...
+		if(STRCMP(name, "BE_USER_SETTINGS") == 0) {
+			static char userSettingsPath[MAXPATHL] = {0};
+			if(B_OK == find_directory(B_USER_SETTINGS_DIRECTORY, 0, 
+										false, userSettingsPath, MAXPATHL)) 
+			{
+				return userSettingsPath;
+			}
+		} else 
+#endif
+		return NULL;
 
     /*
      * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM.
diff --git a/src/normal.c b/src/normal.c
index b76e40d..d8ef2f1 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2599,6 +2599,7 @@ do_mouse(oap, c, dir, count, fixindent)
      * shift-left button -> right button
      * alt-left button   -> alt-right button
      */
+	
     if (mouse_model_popup())
     {
 	if (which_button == MOUSE_RIGHT
@@ -2613,13 +2614,14 @@ do_mouse(oap, c, dir, count, fixindent)
 	    if (!is_click)
 		return FALSE;
 #endif
-#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_BEOS)
 	    if (is_click || is_drag)
 		return FALSE;
 #endif
 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
 	    || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
-	    || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
+	    || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \
+		|| defined(FEAT_GUI_BEOS)
 	    if (gui.in_use)
 	    {
 		jump_flags = 0;
@@ -5385,7 +5387,8 @@ nv_clear(cap)
 {
     if (!checkclearop(cap->oap))
     {
-#if defined(__BEOS__) && !USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+#if defined(__BEOS__) || defined(__HAIKU__)
+#if !USE_THREAD_FOR_INPUT_WITH_TIMEOUT
 	/*
 	 * Right now, the BeBox doesn't seem to have an easy way to detect
 	 * window resizing, so we cheat and make the user detect it
@@ -5393,6 +5396,7 @@ nv_clear(cap)
 	 */
 	ui_get_shellsize();
 #endif
+#endif
 #ifdef FEAT_SYN_HL
 	/* Clear all syntax states to force resyncing. */
 	syn_stack_free_all(curwin->w_s);
diff --git a/src/option.h b/src/option.h
index 0f697c2..a4121b9 100644
--- a/src/option.h
+++ b/src/option.h
@@ -9,7 +9,8 @@
 /*
  * option.h: definition of global variables for settable options
  */
-
+#ifndef _OPTION_H_
+#define _OPTION_H_
 /*
  * Default values for 'errorformat'.
  * The "%f|%l| %m" one is used for when the contents of the quickfix window is
@@ -1095,3 +1096,4 @@ enum
     , WV_WRAP
     , WV_COUNT	    /* must be the last one */
 };
+#endif //_OPTION_H_
diff --git a/src/os_beos.c b/src/os_beos.c
index 10135aa..e46c1ca 100644
--- a/src/os_beos.c
+++ b/src/os_beos.c
@@ -23,8 +23,8 @@
 #define thread_id int
 #endif
 
-char_u charbuf;
-signed char charcount;
+volatile char_u charbuf;
+volatile signed char charcount;
 sem_id character_present;
 sem_id character_wanted;
 thread_id read_thread_id;
@@ -50,7 +50,7 @@ read_thread(void *dummy)
     for (;;) {
 	if (acquire_sem(character_wanted) != B_NO_ERROR)
 	    break;
-	charcount = read(read_cmd_fd, &charbuf, 1);
+	charcount = read(read_cmd_fd, (char_u*)&charbuf, 1);
 	release_sem(character_present);
     }
 
@@ -70,13 +70,18 @@ beos_cleanup_read_thread(void)
 
 #endif
 
+#ifdef __BEOS__ 
+
 /*
  * select() emulation. Hopefully, in DR9 there will be something
  * useful supplied by the system. ... Alas, not. Not in AAPR, nor
  * in PR or even PR2... R3 then maybe? I don't think so!
  */
 
-    int
+/* sz: Haiku has finally select() support 
+ *		and not require this emulation, I hope! */
+
+	int
 beos_select(int nbits,
        struct fd_set *rbits,
        struct fd_set *wbits,
@@ -84,7 +89,11 @@ beos_select(int nbits,
        struct timeval *timeout)
 {
     bigtime_t tmo;
-
+// TODO !!!!
+#ifdef FEAT_GUI_BEOS 
+ 	if(gui.in_use)
+	return select(nbits, rbits, wbits, ebits, timeout);
+#endif
     if (nbits == 0) {
 	/* select is purely being used for delay */
 	snooze(timeout->tv_sec * 1e6 + timeout->tv_usec);
@@ -153,13 +162,15 @@ beos_select(int nbits,
 	    acquired = acquire_sem(character_present);
 	if (acquired == B_NO_ERROR) {
 	    if (charcount > 0) {
-		add_to_input_buf(&charbuf, 1);
+		add_to_input_buf((char_u*)&charbuf, charcount);
 #if !TRY_ABORT
 		release_sem(character_wanted);
 #endif
 
 		return 1;
 	    } else {
+		charbuf = 0;
+		add_to_input_buf((char_u*)&charbuf, 1);
 #if !TRY_ABORT
 		release_sem(character_wanted);
 #endif
@@ -183,7 +194,7 @@ beos_select(int nbits,
 	    if (acquired == B_TIMED_OUT)
 		acquire_sem(character_present);
 	    if (charcount > 0) {
-		add_to_input_buf(&charbuf, 1);
+		add_to_input_buf(&charbuf, charcount);
 		return 1;
 	    }
 	    return 0;
@@ -192,6 +203,19 @@ beos_select(int nbits,
     }
 #endif
 
+
+#if 0 // FEAT_GUI_BEOS
+    /*
+     * If not reading from terminal, pretend there is input.
+     * This makes the pty reading (for the GUI) "work" for
+     * :!ls but not for :r !ls ... weird.
+     */
+    if (gui.in_use && State == EXTERNCMD)
+	return 1;
+#endif
+	
     return 0;
 }
 
+#endif /* __BEOS__ */
+
diff --git a/src/os_beos.h b/src/os_beos.h
index 260834e..c6da995 100644
--- a/src/os_beos.h
+++ b/src/os_beos.h
@@ -20,6 +20,18 @@
 #undef	BEOS_DR8
 #define	BEOS_PR_OR_BETTER
 
-/* select emulation */
+#define USR_VIM_DIR "$BE_USER_SETTINGS/vim"
+
+#define USR_EXRC_FILE	USR_VIM_DIR "/exrc"
+#define USR_VIMRC_FILE	USR_VIM_DIR "/vimrc"
+#define USR_GVIMRC_FILE	USR_VIM_DIR "/gvimrc"
+#define VIMINFO_FILE	USR_VIM_DIR "/viminfo"
+
+#ifdef RUNTIME_GLOBAL
+# define DFLT_RUNTIMEPATH	USR_VIM_DIR "/vimfiles,"  RUNTIME_GLOBAL \
+			",$VIMRUNTIME," RUNTIME_GLOBAL "/after," USR_VIM_DIR "/vimfiles/after"
+#else
+# define DFLT_RUNTIMEPATH	USR_VIM_DIR "/vimfiles," "$VIM/vimfiles" \
+			",$VIMRUNTIME," "$VIM/vimfiles/after,"   USR_VIM_DIR "/vimfiles/after"
+#endif
 
-#include <net/socket.h>		/* for typedefs and #defines only */
diff --git a/src/os_beos.rdef b/src/os_beos.rdef
new file mode 100644
index 0000000..004ed05
--- /dev/null
+++ b/src/os_beos.rdef
@@ -0,0 +1,205 @@
+/*
+ * Vim.rdef
+ */
+
+resource app_signature "application/x-vnd.Haiku-Vim-7";
+
+resource app_version {
+	major  = 7,
+	middle = 3,
+	minor  = 0,
+
+	variety = B_APPV_FINAL,
+	internal = 0,
+
+	short_info = "VIM Editor",
+	long_info = "VI Improved Editor by Bram Moolenaar et al."
+};
+
+//resource app_flags B_SINGLE_LAUNCH;
+resource app_flags B_MULTIPLE_LAUNCH;
+
+resource file_types message {
+	"types" = "text",
+	"types" = "text/plain",
+	"types" = "text/x-source-code",
+	"types" = "text/x-patch",
+	"types" = "text/html",
+	"types" = "text/xml",
+	"types" = "text/x-makefile",
+	"types" = "text/x-jamfile"
+};
+
+#ifdef __HAIKU__
+
+resource vector_icon {
+	$"6E636966050501020006023B8CFD3CB8E4BF59B63E2F604BACDB47A13E00FFFF"
+	$"FFFF909DA702000603BAF8BA3CE3F6BF8EB9BDA8484BC75C4AEA1200C1C7CC79"
+	$"D9E0E5FFC1C7CC020006020000003DC000C000000000004C000049FFFF00B3FF"
+	$"B3FF026C52020006023BD04F3BD04FBED4133ED4134B6000462FB00053AB53FF"
+	$"007F00060618FFFCFFFF63FF282528252725262726262627262B262B262C282D"
+	$"272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA2659315ABA26595E"
+	$"2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A254A254925482748"
+	$"264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D3E2B3E2C3E2B3E"
+	$"273E273E263C253D253C250618FFFCFFFF63FF28252825272526272626262726"
+	$"2B262B262C282D272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA26"
+	$"59315ABA26595E2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A25"
+	$"4A254925482748264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D"
+	$"3E2B3E2C3E2B3E273E273E263C253D253C250A08BEA359BE3D593C5A415AC03B"
+	$"59BFD559434C404C06218A88888888C83E3F02484CC1D359C16D445A49C36B59"
+	$"C305C3CA50C5C8C50359C49D4C5A51C69B59C635C6FA50C8F8C83359C7CD545A"
+	$"59C9CB59C965CA6B4DCA6B4DCA804C5A4C584C584C574CC86D4DC8D34DC86D4D"
+	$"C73B524C534C524C504C504C4F4CC53D4DC5A34DC53D4DC40B4B4C0608EBECC0"
+	$"B64AC0B64AC11C4AC13349C14848C0F847C15E47C0F847C092C01648C02C47C0"
+	$"1648C00149C0504ABFEA4AC0504A0A04405E5E40402222400A0A000105180015"
+	$"01178600040A0001051815FF01178400040A030105000A0401051001157C0004"
+	$"0A000100381D1F001501178600040A000100381D1F15FF01178300040A010101"
+	$"201D1F0A020101301D1F01157E00040A0003020304381D1F15FF01178400040A"
+	$"0203020304281D1F15FF"
+};
+
+#else // HAIKU_TARGET_PLATFORM_HAIKU
+
+resource large_icon array {
+	$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+	$"FFFFFFFFFFFFFFFFFFFFFFFFFFFF01343500FFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+	$"FFFFFF00000000000001000000003439393400FF000000000000000000FFFFFF"
+	$"FFFF001F1F1F1F1F1F1F1F1F1F1F0039393934001F1F1F1F1F1F1F1F1F00FFFF"
+	$"FFFF001F181818181818181818181800393939001F18181818181818171800FF"
+	$"FFFFFF00181818181818181818181000393939390018181818181818181000FF"
+	$"FFFFFFFF0010181818181818100F0039393939393900101818181818101000FF"
+	$"FFFFFFFF001F1818181818181000393939393939001F1818181818101000FFFF"
+	$"FFFFFFFF001F18181818181810003939393939001F1F18181818101000FFFFFF"
+	$"FFFFFFFF001F181818181818100039393939001F1F18181818101000FFFFFFFF"
+	$"FFFFFFFF001F1818191818181000393939001F1F18181818101001FFFFFFFFFF"
+	$"FFFFFFFF001F18181818181810003939001F1F181818181010003400FFFFFFFF"
+	$"FFFFFF01001F181818181818100039001F1F1818181810100039393500FFFFFF"
+	$"FFFF0135001F1818171818181000001F1F18181818101000393939393401FFFF"
+	$"FF013439001F1818181818180F001F1F19171818100F003939393939393501FF"
+	$"00353939001F181818181818101F1F1818181810100039393939393939393501"
+	$"01253939001F181818181818101F181818171010003939393939393939392500"
+	$"FF002539001F18181818181810181817181010003939393939393939392500FF"
+	$"FFFF0025001F181818181818181818180000003939393939393939392501FFFF"
+	$"FFFFFF00001F1818181818181818180017180139393939393939392500FFFFFF"
+	$"FFFFFFFF001F18181818181818181800181800393939393939392500FFFFFFFF"
+	$"FFFFFFFF001F1818181818181818100000003900000139000000000000FFFFFF"
+	$"FFFFFFFF001F181818181818181000181818001818180018181800171801FFFF"
+	$"FFFFFFFF001F18181818181810100000181800001818181818181818181801FF"
+	$"FFFFFFFF001F181818181810100000181800000018182525181800001801FFFF"
+	$"FFFFFFFF001F181818181010003900181800001817250018180000181800FFFF"
+	$"FFFFFFFF001F181818101000393900181800001818000018180000181800FFFF"
+	$"FFFFFFFF001F1818101000002500181800001818000018180000181800FFFFFF"
+	$"FFFFFFFFFF0018101100FFFF000018181800181800001818000018181801FFFF"
+	$"FFFFFFFFFFFF000000FFFFFFFF01000000250000FFFF0100FFFF010000FFFFFF"
+	$"FFFFFFFFFFFFFFFFFFFFFFFFFFFF01252501FFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+	$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+};
+
+resource mini_icon array {
+	$"FFFF00000000003434FF00000000FFFF"
+	$"FF001F1F1F1F1F0439001F1F1F1F03FF"
+	$"FF001818181818100000181818181000"
+	$"FFFF00181818100039001F18181000FF"
+	$"FFFF001818181000001F18181000FFFF"
+	$"FFFF0018181810001F1818100025FFFF"
+	$"FF3400181818101F18181000393925FF"
+	$"34390018181818180000393939393925"
+	$"00390018181818001800000039003925"
+	$"FF0000181818180000001818001800FF"
+	$"FFFF0018181800181800181818181800"
+	$"FFFF0018181800001800180018001800"
+	$"FFFF0018181039001800182518001800"
+	$"FFFF0018100000181800180018001800"
+	$"FFFFFF0000FF2500002500FF00FF00FF"
+	$"FFFFFFFFFFFFFF2525FFFFFFFFFFFFFF"
+};
+
+#endif // HAIKU_TARGET_PLATFORM_HAIKU
+
+resource(1, "builtin-tools") #'PNG ' array {
+	$"89504E470D0A1A0A0000000D494844520000022E0000001208030000004BB3A5"
+	$"1200000300504C5445000000800000008000808000000080800080008080C0C0"
+	$"C0C0DCC0A6CAF0402000602000802000A02000C02000E0200000400020400040"
+	$"4000604000804000A04000C04000E04000006000206000406000606000806000"
+	$"A06000C06000E06000008000208000408000608000808000A08000C08000E080"
+	$"0000A00020A00040A00060A00080A000A0A000C0A000E0A00000C00020C00040"
+	$"C00060C00080C000A0C000C0C000E0C00000E00020E00040E00060E00080E000"
+	$"A0E000C0E000E0E000000040200040400040600040800040A00040C00040E000"
+	$"40002040202040402040602040802040A02040C02040E0204000404020404040"
+	$"4040604040804040A04040C04040E04040006040206040406040606040806040"
+	$"A06040C06040E06040008040208040408040608040808040A08040C08040E080"
+	$"4000A04020A04040A04060A04080A040A0A040C0A040E0A04000C04020C04040"
+	$"C04060C04080C040A0C040C0C040E0C04000E04020E04040E04060E04080E040"
+	$"A0E040C0E040E0E040000080200080400080600080800080A00080C00080E000"
+	$"80002080202080402080602080802080A02080C02080E0208000408020408040"
+	$"4080604080804080A04080C04080E04080006080206080406080606080806080"
+	$"A06080C06080E06080008080208080408080608080808080A08080C08080E080"
+	$"8000A08020A08040A08060A08080A080A0A080C0A080E0A08000C08020C08040"
+	$"C08060C08080C080A0C080C0C080E0C08000E08020E08040E08060E08080E080"
+	$"A0E080C0E080E0E0800000C02000C04000C06000C08000C0A000C0C000C0E000"
+	$"C00020C02020C04020C06020C08020C0A020C0C020C0E020C00040C02040C040"
+	$"40C06040C08040C0A040C0C040C0E040C00060C02060C04060C06060C08060C0"
+	$"A060C0C060C0E060C00080C02080C04080C06080C08080C0A080C0C080C0E080"
+	$"C000A0C020A0C040A0C060A0C080A0C0A0A0C0C0A0C0E0A0C000C0C020C0C040"
+	$"C0C060C0C080C0C0A0C0C0FFFBF0A0A0A4808080FF000000FF00FFFF000000FF"
+	$"FF00FF00FFFFFFFFFF58D234440000000874524E53FFFFFFFFFFFFFF00DE83BD"
+	$"59000000097048597300000B1200000B1201D2DD7EFC0000070D494441546881"
+	$"DD994B6E23390C86695880F6BDCD19BCCD3AD7CA7DB4CD197C965EE7044619D0"
+	$"F0299192AA5C9907D018762776D12A3DA8AF7E520E64B382FFB792FF004BCD4E"
+	$"DF02C1DC0717347779C3FFDB8D5F43A3705900FE8838FCDB868119C3F3E32EDA"
+	$"BB5A1897CA916A1B566CA49DED7865B2E3E930FC6397A9AAEDE232F10409EA37"
+	$"5B851A70793C020BB70C1B8CB4C436057EFFF6BCACE0BD0CAF75159D21567B6D"
+	$"B2BB9EC73AF7E89C21013E3EF03F1A4CD339BDA77E390523594BE549EA7E55DD"
+	$"E8793B68FEF332D4D3BD72BFE1B2D68D19171A87861F37ADB4163A3FEB87E6A7"
+	$"06411B06146E37D8B60D6E9E176C121A212D81976930BAE5C231A657895D5B80"
+	$"8735AE6BD5068729057FCC318FB5183DC682BB8924AC4D5AB456557F9771D647"
+	$"066E0B378A6491FD65381017DDB2793BD2674A9F64E14950CF67DFD8941D3D5D"
+	$"37DA62B1BB1B9ADFE4452BA3B3C41649D58BE6B77E58065C36B3EEC26C856D7A"
+	$"3E2A332ECFA73E3BBD53EE955F5BB8F939B3F85B749D2DDA003A0A5E546B392D"
+	$"6CE11962C1FD4412D6664C01702B990E4FA5C6591F18F4CDF1913475B1597975"
+	$"498A4BB3B632E7EA7B5F5C2E620A83C4C0ED2AFB7BBD4268157191693455129A"
+	$"BF6BD329C265918F461496EAF23219E5E7B3549977BF036FE1DFEDE9ACB2E7FB"
+	$"819736D9B76152F8C7B6B95E5AE06DA99327C682FBF9289E04B46B306D2519AB"
+	$"6480361D9A8ABDC0F291ABFE8271F916D9A849D505432FEA42D3E4965E5D1C2E"
+	$"B486CE463247C025E54159436982B898395C26759970A9BE9386CB948FC64473"
+	$"A676912AC06DFA53E5A51753C0A4D08F17730E6A734C81F7C94853BC3C8AF44B"
+	$"79A9974B5C18EE6573795C86041E49405ACAE68CC72168AEF9FAF686BF4D5DDC"
+	$"74CB98902AB8D7EA70112E0ACE076B1776DEFB7EA4BBE1B2509784893799BCA4"
+	$"76ED71416971BBCEEA623DF1B21197DB50D2840662853E2A2E19E95C2C6883BA"
+	$"A4B6DB63EDB23A19C536BCBF5E5ECAF329F2D22704C221DEE670113016C540DD"
+	$"C18576B7B0BA202CC2CB85B410F9B085F1D5E3228F00F45880CC221891A04EA1"
+	$"E55B7F181705081B15F12C71A9DC41FBC454489B414F4685D0D80A4E3F3E1789"
+	$"9FFA1D7521509ABCC89BF439E2E28B9BA82E0D97F844AD6A17E969D09F1E3448"
+	$"699EA2B0100FC9793C44E7E1B02DA50BA6A3E621655179E9B858FD32D1E11C75"
+	$"74B567B0CB0AC55B4EA37425106AFDEC1D35F2A1692DF24224E8BBB221840117"
+	$"038871F9DEC385122A83AF2E914B6B06E06B17C605E70F776760B8B45A32292E"
+	$"76D01E710907F0E1F4B4A72ECEE3594D417103762C223D688A4B5497391F9CF0"
+	$"80E1622393B290C0607CF2A1BA4CB84CAE6E8A4B257929242EF4CEE078F48599"
+	$"E712F900417117976DC3021AA9907F084703E885BA48426D5955E432F78B880B"
+	$"DD8AFEFB7BB32B182EDD64844299A74CB8D0C1903ED13594A1D47DA12E34B8B7"
+	$"D223E28F0249C5A5056DA52EAEA7AF2FEEE88C87BEA42364DCC83D40D97059D5"
+	$"2E7BC9A8F62D51EBC9A8B2C0DB01C9E8E80BEB7213F880F032E18240081C1D17"
+	$"03E8585D72FE91BA6805E6707987515D4CE9932F598637EECCC7B8F8134D5DA9"
+	$"8BC7E5F1F86A56DCF13AE022EAD282C6B844010CDC15DAFD331EE5C51FA5537D"
+	$"3C727E704A7A3ED9B53A198DA56E0FEB949F7AA92B0072F552A463CA8C7D6156"
+	$"BB0C7CF00E1EE0029BA41E4D47C8E9E6D5E5089755ED62CDD6B80CF21270F9F5"
+	$"ABE3C2E7202970F3E8695B2CEAD28AD81D7571C9E8FEF5B5C4C59BA94B0B9AE0"
+	$"1204D075F478281CAF3DB9A5A3968D522DC8CB0379C1B4C4BCACBF77C9FE201D"
+	$"4F46D666719016846C9D720CF234C8C968E443867BDBC1C578E927A306D0212E"
+	$"35984D09DCC54B5CDEF770E95FB3B883B439CCD3BE7751DD61D3A3D89EBAECE0"
+	$"32ABCB58EA46010C1D8D70EC7A7AADDB78C1D9154E095E5D2EFAAA87AAF990CC"
+	$"59B9D95E1BE0546747EA6CDFBB381AD2E4E158D02ADFDE022F0E17C9A81E5703"
+	$"E8B07681F12EF9C85D2C71C130BAEF78F670B1435083A37DABDB1D599391952F"
+	$"14BA78F0E1DD7500ADE73CE1A20F00DE2B995652909F22DC7B2784C2394FE6BF"
+	$"01683A0237985717AC5D742297A02E1185D196B8F0BBFE374DB730A561F6F458"
+	$"445E3C2E8155C65501A24612D60997D55DAE3399EF1A9769C7965B2867A0E2E2"
+	$"A31E7759F41835B4E9C7A71120F0EA02E51017BA45FF3253665C5C19AB70BCF6"
+	$"642D5B2423411F8C6B97868B8D9E5BED326AB84637E032B5E94A648AED17C634"
+	$"CC1E178B7D5C661302A891ECBE4E07E6591FD81A9781B3A5A339E749F94BFF32"
+	$"75AED701A01D71099DF832450BF94900492EBA3109273CD9FE02C03909FA6024"
+	$"912D194D339C0EC9D6CCAD7AD166F2C485312E93671150B617B88C8D86DC731A"
+	$"1767E7EEF90FEC3599BB77B416E3EAE7689CF114DBE3E262B898CB34FECE845E"
+	$"4CFAEF79764372DC201F65AC97B792C14FE6F387DBB4F83918273C6E9B866FD9"
+	$"FF17F6CF36F92F1B9E631E8B8F3FBC0000000049454E44AE426082"
+};
+
diff --git a/src/os_unix.c b/src/os_unix.c
index a82c65d..823fa74 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1131,7 +1131,7 @@ sigcont_handler SIGDEFARG(sigarg)
 mch_suspend()
 {
     /* BeOS does have SIGTSTP, but it doesn't work. */
-#if defined(SIGTSTP) && !defined(__BEOS__)
+#if defined(SIGTSTP) && !defined(__BEOS__) && !defined(__HAIKU__)
     out_flush();	    /* needed to make cursor visible on some systems */
     settmode(TMODE_COOK);
     out_flush();	    /* needed to disable mouse on some systems */
@@ -2017,6 +2017,11 @@ mch_settitle(title, icon)
     if (gui.in_use)
 	type = 1;
 # endif
+# ifdef FEAT_GUI_BEOS
+    /* TODO: If this means (gui.in_use) why not merge with above? (Dany) */
+    /* we always have a 'window' */
+    type = 1;
+# endif
 #endif
 
     /*
@@ -2041,7 +2046,7 @@ mch_settitle(title, icon)
 # endif
 	    set_x11_title(title);		/* x11 */
 #endif
-#if defined(FEAT_GUI_GTK) \
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_BEOS)\
 	|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
 	else
 	    gui_mch_settitle(title, icon);
@@ -3088,7 +3093,9 @@ mch_exit(r)
     ml_close_all(TRUE);		/* remove all memfiles */
     may_core_dump();
 #ifdef FEAT_GUI
+# ifndef FEAT_GUI_BEOS		/* BeOS always has GUI */
     if (gui.in_use)
+# endif
 	gui_exit(r);
 #endif
 
@@ -3918,7 +3925,7 @@ mch_call_shell(cmd, options)
 
     if (!pipe_error)			/* pty or pipe opened or not used */
     {
-# ifdef __BEOS__
+# if defined(__BEOS__) || defined(__HAIKU__) && USE_THREAD_FOR_INPUT_WITH_TIMEOUT
 	beos_cleanup_read_thread();
 # endif
 
diff --git a/src/os_unix.h b/src/os_unix.h
index 5fd28af..a371c4e 100644
--- a/src/os_unix.h
+++ b/src/os_unix.h
@@ -388,6 +388,8 @@ typedef struct dsc$descriptor   DESC;
 
 #define DFLT_ERRORFILE		"errors.err"
 
+#ifndef DFLT_RUNTIMEPATH
+
 #ifdef OS2
 # define DFLT_RUNTIMEPATH	"$HOME/vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/vimfiles/after"
 #else
@@ -402,6 +404,8 @@ typedef struct dsc$descriptor   DESC;
 # endif
 #endif
 
+#endif
+
 #ifdef OS2
 /*
  * Try several directories to put the temp files.
diff --git a/src/proto.h b/src/proto.h
index 40fb2a9..036bb72 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -59,7 +59,7 @@ extern int _stricoll __ARGS((char *a, char *b));
 # ifdef VMS
 #  include "os_vms.pro"
 # endif
-# ifdef __BEOS__
+# if defined(__BEOS__) || defined(__HAIKU__)
 #  include "os_beos.pro"
 # endif
 # ifdef RISCOS
@@ -239,6 +239,9 @@ extern char_u *vimpty_getenv __ARGS((const char_u *string));	/* from pty.c */
 extern char *vim_SelFile __ARGS((Widget toplevel, char *prompt, char *init_path, int (*show_entry)(), int x, int y, guicolor_T fg, guicolor_T bg, guicolor_T scroll_fg, guicolor_T scroll_bg));
 #   endif
 #  endif
+#  ifdef FEAT_GUI_BEOS
+#   include "gui_beos.pro"
+#  endif
 #  ifdef FEAT_GUI_MAC
 #   include "gui_mac.pro"
 #  endif
diff --git a/src/proto/gui_beos.pro b/src/proto/gui_beos.pro
new file mode 100644
index 0000000..b74cd20
--- /dev/null
+++ b/src/proto/gui_beos.pro
@@ -0,0 +1,90 @@
+/* gui_beos.cc - hand crafted */
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int vim_exitcode));
+int gui_mch_init_check __ARGS((void));
+void gui_mch_flush __ARGS((void));
+
+void gui_mch_new_colors __ARGS((void));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_set_fg_color __ARGS((guicolor_T	color));
+void gui_mch_set_sp_color __ARGS((guicolor_T	color));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_set_font __ARGS((GuiFont font));
+int gui_mch_init_font __ARGS((char_u* font_name, int fontset));
+void gui_mch_free_font __ARGS((GuiFont font));
+char_u* gui_mch_get_fontname __ARGS((GuiFont font, char_u *name));
+
+void gui_mch_set_winpos __ARGS((int x, int y));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_shellsize __ARGS((int w, int h, int m_w, int m_h, int b_w, int b_h, int d));
+void gui_mch_get_screen_dimensions __ARGS((int* screen_w, int* screen_h));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T* sb, int flag));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb,int val, int size, int max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T* sb));
+
+void gui_mch_set_blinking __ARGS((long waittime, long on, long off));
+void gui_mch_stop_blink __ARGS(());
+void gui_mch_start_blink __ARGS(());
+
+int gui_mch_adjust_charheight __ARGS(());
+void gui_mch_draw_string __ARGS((int row, int col, char_u* s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u* name));
+void gui_mch_beep __ARGS(());
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS(());
+void gui_mch_set_foreground __ARGS(());
+void gui_mch_settitle __ARGS((char_u* title, char_u* icon));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS(());
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS(());
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+
+void gui_mch_getmouse __ARGS((int *x, int *y));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_mousehide __ARGS((int hide));
+
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_add_menu __ARGS((vimmenu_T* menu, int idx));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T	*menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS(());
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+
+char_u* gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u	*title, char_u* message, char_u	*buttons, int dfltbutton, char_u* textfield));
+
+void im_set_position __ARGS((int row, int col));
+void im_set_active __ARGS((int activate));
+int im_get_status __ARGS(());
+
+void gui_mch_show_toolbar __ARGS((int showit));
+void gui_mch_set_toolbar_pos __ARGS((int x, int y, int w, int h));
+
+void gui_mch_show_tabline __ARGS((int showit));
+void gui_mch_set_tabline_pos __ARGS((int x, int y, int w, int h));
+int gui_mch_showing_tabline __ARGS((void));
+void gui_mch_update_tabline __ARGS((void));
+void gui_mch_set_curtab __ARGS((int nr));
diff --git a/src/proto/os_beos.pro b/src/proto/os_beos.pro
new file mode 100644
index 0000000..c537101
--- /dev/null
+++ b/src/proto/os_beos.pro
@@ -0,0 +1,4 @@
+/* os_beos.c */
+void beos_cleanup_read_thread __ARGS((void));
+int beos_select __ARGS((int nbits, struct fd_set *rbits, struct fd_set *wbits, struct fd_set *ebits, struct timeval *timeout));
+/* vim: set ft=c : */
diff --git a/src/pty.c b/src/pty.c
index 944eccf..a5c5d59 100644
--- a/src/pty.c
+++ b/src/pty.c
@@ -353,7 +353,7 @@ OpenPTY(ttyn)
 static char PtyProto[] = "/dev/ptym/ptyXY";
 static char TtyProto[] = "/dev/pty/ttyXY";
 # else
-#  ifdef __BEOS__
+#  if defined(__BEOS__) || defined(__HAIKU__)
 static char PtyProto[] = "/dev/pt/XY";
 static char TtyProto[] = "/dev/tt/XY";
 #  else
diff --git a/src/screen.c b/src/screen.c
index 380eb8b..b696b68 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -7917,6 +7917,10 @@ retry:
 
     win_new_shellsize();    /* fit the windows in the new sized shell */
 
+#ifdef FEAT_GUI_BEOS
+    vim_lock_screen();  /* be safe, put it here */
+#endif
+
     comp_col();		/* recompute columns for shown command and ruler */
 
     /*
@@ -8160,6 +8164,9 @@ give_up:
     }
 #endif
 
+#ifdef FEAT_GUI_BEOS
+    vim_unlock_screen();
+#endif
     entered = FALSE;
     --RedrawingDisabled;
 
@@ -9023,6 +9030,9 @@ screen_ins_lines(off, row, line_count, end, wp)
 	clip_scroll_selection(-line_count);
 #endif
 
+#ifdef FEAT_GUI_BEOS
+    vim_lock_screen();
+#endif
 #ifdef FEAT_GUI
     /* Don't update the GUI cursor here, ScreenLines[] is invalid until the
      * scrolling is actually carried out. */
@@ -9075,6 +9085,10 @@ screen_ins_lines(off, row, line_count, end, wp)
 	}
     }
 
+#ifdef FEAT_GUI_BEOS
+    vim_unlock_screen();
+#endif
+
     screen_stop_highlight();
     windgoto(cursor_row, 0);
 
@@ -9244,6 +9258,9 @@ screen_del_lines(off, row, line_count, end, force, wp)
 	clip_scroll_selection(line_count);
 #endif
 
+#ifdef FEAT_GUI_BEOS
+    vim_lock_screen();
+#endif
 #ifdef FEAT_GUI
     /* Don't update the GUI cursor here, ScreenLines[] is invalid until the
      * scrolling is actually carried out. */
@@ -9303,6 +9320,10 @@ screen_del_lines(off, row, line_count, end, force, wp)
 	}
     }
 
+#ifdef FEAT_GUI_BEOS
+    vim_unlock_screen();
+#endif
+
     screen_stop_highlight();
 
 #ifdef FEAT_VERTSPLIT
diff --git a/src/structs.h b/src/structs.h
index 884d6a9..690cf4d 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2330,6 +2330,13 @@ struct VimMenu
     HMENU	submenu_id;	    /* If this is submenu, add children here */
     HWND	tearoff_handle;	    /* hWnd of tearoff if created */
 #endif
+#if FEAT_GUI_BEOS
+    BMenuItem	*id;		    /* Id of menu item */
+    BMenu	*submenu_id;	    /* If this is submenu, add children here */
+# ifdef FEAT_TOOLBAR
+	BPictureButton *button;
+# endif
+#endif
 #ifdef FEAT_GUI_MAC
 /*  MenuHandle	id; */
 /*  short	index;	*/	    /* the item index within the father menu */
diff --git a/src/term.c b/src/term.c
index 8c42662..bd6c7b7 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1436,6 +1436,11 @@ static struct builtin_term builtin_termcaps[] =
 # define DEFAULT_TERM	(char_u *)"beos-ansi"
 #endif
 
+#ifdef __HAIKU__
+# undef DEFAULT_TERM
+# define DEFAULT_TERM	(char_u *)"xterm"
+#endif
+
 #ifndef DEFAULT_TERM
 # define DEFAULT_TERM	(char_u *)"dumb"
 #endif
diff --git a/src/ui.c b/src/ui.c
index 9a04476..0886244 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -269,7 +269,7 @@ ui_suspend()
     mch_suspend();
 }
 
-#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__)
+#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__) || defined(__HAIKU__)
 /*
  * When the OS can't really suspend, call this function to start a shell.
  * This is never called in the GUI.
@@ -3000,7 +3000,7 @@ mouse_find_win(rowp, colp)
 
 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \
 	|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
-	|| defined(FEAT_GUI_PHOTON) || defined(PROTO)
+	|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_BEOS) || defined(PROTO)
 /*
  * Translate window coordinates to buffer position without any side effects
  */
diff --git a/src/version.c b/src/version.c
index 79522a4..298b0e6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -949,6 +949,9 @@ list_version()
     MSG_PUTS(_("with X11-Athena GUI."));
 #    endif
 #   else
+#    ifdef FEAT_GUI_BEOS
+    MSG_PUTS(_("with BeOS/Haiku GUI."));
+#    else
 #     ifdef FEAT_GUI_PHOTON
     MSG_PUTS(_("with Photon GUI."));
 #     else
@@ -966,6 +969,7 @@ list_version()
 #	  endif
 #	 endif
 #	endif
+#       endif
 #      endif
 #    endif
 #   endif
diff --git a/src/vim.h b/src/vim.h
index b9ce325..aaa407a 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -115,6 +115,7 @@
     || defined(FEAT_GUI_MAC) \
     || defined(FEAT_GUI_W32) \
     || defined(FEAT_GUI_W16) \
+    || defined(FEAT_GUI_BEOS) \
     || defined(FEAT_GUI_PHOTON)
 # if !defined(FEAT_GUI) && !defined(NO_X11_INCLUDES)
 #  define FEAT_GUI
@@ -255,7 +256,7 @@
 # define __ARGS(x) x
 #endif
 
-#ifdef __BEOS__
+#if defined(__BEOS__) || defined(__HAIKU__)
 # include "os_beos.h"
 # define __ARGS(x)  x
 #endif
@@ -1903,6 +1904,9 @@ typedef struct VimClipboard
     int_u	format;		/* Vim's own special clipboard format */
     int_u	format_raw;	/* Vim's raw text clipboard format */
 # endif
+# ifdef FEAT_GUI_BEOS
+				/* no clipboard at the moment */
+# endif
 } VimClipboard;
 #else
 typedef int VimClipboard;	/* This is required for the prototypes. */
-- 
1.8.3.4

