diff src/gui_haiku.cc @ 32670:695b50472e85

Fix line endings issue
author Christian Brabandt <cb@256bit.org>
date Mon, 26 Jun 2023 13:13:12 +0200
parents 448aef880252
children 1629cc65d78d
line wrap: on
line diff
--- a/src/gui_haiku.cc
+++ b/src/gui_haiku.cc
@@ -1,5092 +1,5092 @@
-/* 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.
- *
- * Based on "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@gmx.li> Apr-Mai 2009
- *
- */
-
-/*
- * Structure of the Haiku 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 <assert.h>
-#include <float.h>
-#include <syslog.h>
-
-#include "vim.h"
-#include "version.h"
-
-}   // extern "C"
-
-// ---------------- start of header part ----------------
-
-//#include <Alert.h>
-#include <Application.h>
-#include <Beep.h>
-#include <Bitmap.h>
-#include <Box.h>
-#include <Button.h>
-#include <Clipboard.h>
-#include <Debug.h>
-//#include <Directory.h>
-//#include <Entry.h>
-#include <File.h>
-#include <FilePanel.h>
-#include <FindDirectory.h>
-//#include <Font.h>
-#include <IconUtils.h>
-#include <Input.h>
-#include <ListView.h>
-#include <MenuBar.h>
-#include <MenuItem.h>
-//#include <MessageQueue.h>
-//#include <OS.h>
-#include <Path.h>
-#include <PictureButton.h>
-#include <PopUpMenu.h>
-//#include <Region.h>
-#include <Resources.h>
-//#include <Roster.h>
-#include <Screen.h>
-#include <ScrollBar.h>
-#include <ScrollView.h>
-#include <String.h>
-#include <StringView.h>
-//#include <SupportDefs.h>
-#include <TabView.h>
-#include <TextControl.h>
-#include <TextView.h>
-#include <TranslationUtils.h>
-#include <TranslatorFormats.h>
-#include <View.h>
-#include <Window.h>
-
-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:
-
-    class View : public BView {
-	typedef BView Inherited;
-
-	public:
-	View(BRect frame);
-	~View();
-
-	virtual void Draw(BRect updateRect);
-	void InitIcon(int32 type);
-
-	private:
-	BBitmap*    fIconBitmap;
-    };
-
-    VimDialog(int type, const char *title, const char *message,
-	    const char *buttons, int dfltbutton, const char *textfield,
-	    int ex_cmd);
-    ~VimDialog();
-
-    int Go();
-
-    virtual void MessageReceived(BMessage *msg);
-
-    private:
-    sem_id	    fDialogSem;
-    int		    fDialogValue;
-    BList	    fButtonsList;
-    BTextView*	    fMessageView;
-    BTextControl*   fInputControl;
-    const char*	    fInputValue;
-};
-
-class VimSelectFontDialog : public BWindow
-{
-    typedef BWindow Inherited;
-
-    void _CleanList(BListView* list);
-    void _UpdateFontStyles();
-    void _UpdateSizeInputPreview();
-    void _UpdateFontPreview();
-    bool _UpdateFromListItem(BListView* list, char* text, int textSize);
-    public:
-
-    VimSelectFontDialog(font_family* family, font_style* style, float* size);
-    ~VimSelectFontDialog();
-
-    bool Go();
-
-    virtual void MessageReceived(BMessage *msg);
-
-    private:
-    status_t	    fStatus;
-    sem_id	    fDialogSem;
-    bool	    fDialogValue;
-    font_family*    fFamily;
-    font_style*	    fStyle;
-    float*	    fSize;
-    font_family	    fFontFamily;
-    font_style	    fFontStyle;
-    float	    fFontSize;
-    BStringView*    fPreview;
-    BListView*	    fFamiliesList;
-    BListView*	    fStylesList;
-    BListView*	    fSizesList;
-    BTextControl*   fSizesInput;
-};
-
-#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
-    bool    csi_escape;
-};
-
-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)	{ (char_u)((g) >> 16), (char_u)((g) >> 8), (char_u)((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    ARRAY_LENGTH(special_keys)
-
-// ---------------- 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 .");
-}
-
-	static void
-drop_callback(void *cookie)
-{
-    // TODO here we could handle going to a specific position in the dropped
-    // file (see src/gui_mac.c, deleted in 8.2.1422)
-    // Update the screen display
-    update_screen(UPD_NOT_VALID);
-}
-
-    // 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, drop_callback, NULL);
-
-	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.
-     */
-    mch_signal(SIGINT, SIG_IGN);
-    mch_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);
-    km.csi_escape = false;
-    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.
-     */
-    mch_signal(SIGINT, SIG_IGN);
-    mch_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);
-#define W_WIDTH(curwin)   0
-}
-
-    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);
-	km.csi_escape = true;
-    } 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;
-	km.csi_escape = false;
-    }
-
-    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, 1);
-    if (newFont != NOFONT) {
-	gui.norm_font = (GuiFont)newFont;
-	gui_mch_set_font((GuiFont)newFont);
-	if (name && STRCMP(name, "*") != 0)
-	    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;
-	cells = 0;
-	for (int i=0; i<len; i++) {
-	    int cn = utf_ptr2cells((char_u *)(s+i));
-	    if (cn<4) cells += cn;
-	}
-
-	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) {
-	    clen = utf_ptr2len((u_char*)p);
-	    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);
-	    }
-	    cells = utf_ptr2cells((char_u *)p);
-	    if (cells<4) lastpos += cells;
-	    else	lastpos++;
-	    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;
-	cells = 0;
-	for (int i=0; i<len; i++) {
-	    int cn = utf_ptr2cells((char_u *)(s+i));
-	    if (cn<4) cells += cn;
-	}
-
-	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, int ex_cmd)
-: 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
-    VimDialog::View* view = new VimDialog::View(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.SetByteAt(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;
-}
-
-VimDialog::View::View(BRect frame)
-    :	BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
-    fIconBitmap(NULL)
-{
-    SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
-}
-
-VimDialog::View::~View()
-{
-    delete fIconBitmap;
-}
-
-void VimDialog::View::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 VimDialog::View::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;
-    //	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;
-
-    //	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;
-    }
-
-    if (fIconBitmap->ColorSpace() != B_CMAP8)
-	BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
-}
-
-const unsigned int  kVimDialogOKButtonMsg = 'FDOK';
-const unsigned int  kVimDialogCancelButtonMsg = 'FDCN';
-const unsigned int  kVimDialogSizeInputMsg = 'SICH';
-const unsigned int  kVimDialogFamilySelectMsg = 'MSFM';
-const unsigned int  kVimDialogStyleSelectMsg = 'MSST';
-const unsigned int  kVimDialogSizeSelectMsg = 'MSSZ';
-
-VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size)
-: BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
-	B_NOT_CLOSABLE | B_NOT_RESIZABLE |
-	B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
-    , fStatus(B_NO_INIT)
-    , fDialogSem(-1)
-    , fDialogValue(false)
-    , fFamily(family)
-    , fStyle(style)
-    , fSize(size)
-    , fFontSize(*size)
-    , fPreview(0)
-    , fFamiliesList(0)
-    , fStylesList(0)
-    , fSizesList(0)
-    , fSizesInput(0)
-{
-    strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH);
-    strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH);
-
-    //	"client" area view
-    BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
-		    B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED,
-		    B_PLAIN_BORDER);
-    AddChild(clientBox);
-
-    //	client view
-    BRect RC = clientBox->Bounds();
-    RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY);
-    BRect rc(RC.LeftTop(), RC.LeftTop());
-
-    //	at first create all controls
-    fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono");
-    clientBox->AddChild(fPreview);
-
-    BBox* boxDivider = new BBox(rc, B_EMPTY_STRING,
-	    B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER);
-    clientBox->AddChild(boxDivider);
-
-    BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:");
-    clientBox->AddChild(labelFamily);
-    labelFamily->ResizeToPreferred();
-
-    BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:");
-    clientBox->AddChild(labelStyle);
-    labelStyle->ResizeToPreferred();
-
-    BStringView *labelSize = new BStringView(rc, "labelSize", "Size:");
-    clientBox->AddChild(labelSize);
-    labelSize->ResizeToPreferred();
-
-    fFamiliesList = new BListView(rc, "listFamily",
-	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
-    BScrollView *scrollFamilies = new BScrollView("scrollFamily",
-	    fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
-    clientBox->AddChild(scrollFamilies);
-
-    fStylesList= new BListView(rc, "listStyles",
-	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
-    BScrollView *scrollStyles = new BScrollView("scrollStyle",
-	    fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
-    clientBox->AddChild(scrollStyles);
-
-    fSizesInput = new BTextControl(rc, "inputSize", NULL, "???",
-	    new BMessage(kVimDialogSizeInputMsg));
-    clientBox->AddChild(fSizesInput);
-    fSizesInput->ResizeToPreferred();
-
-    fSizesList = new BListView(rc, "listSizes",
-	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
-    BScrollView *scrollSizes = new BScrollView("scrollSize",
-	    fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
-    clientBox->AddChild(scrollSizes);
-
-    BButton *buttonOK = new BButton(rc, "buttonOK", "OK",
-			new BMessage(kVimDialogOKButtonMsg));
-    clientBox->AddChild(buttonOK);
-    buttonOK->ResizeToPreferred();
-
-    BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel",
-			new BMessage(kVimDialogCancelButtonMsg));
-    clientBox->AddChild(buttonCancel);
-    buttonCancel->ResizeToPreferred();
-
-    //	layout controls
-    float lineHeight = labelFamily->Bounds().Height();
-    float previewHeight = lineHeight * 3;
-    float offsetYLabels = previewHeight + kVimDialogSpacingY;
-    float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2;
-    float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2;
-    float listsHeight = lineHeight * 9;
-    float offsetYButtons = offsetYLists + listsHeight +  kVimDialogSpacingY;
-    float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height();
-    float familiesWidth = labelFamily->Bounds().Width() * 5;
-    float offsetXStyles = familiesWidth + kVimDialogSpacingX;
-    float stylesWidth = labelStyle->Bounds().Width() * 4;
-    float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX;
-    float sizesWidth = labelSize->Bounds().Width() * 2;
-    float maxControlsWidth = offsetXSizes + sizesWidth;
-
-    ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2,
-	maxControlsHeight + kVimDialogSpacingY * 2);
-
-    BRect rcVim = gui.vimWindow->Frame();
-    MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2,
-	    rcVim.top + (rcVim.Height() - Frame().Height()) / 2);
-
-    fPreview->ResizeTo(maxControlsWidth, previewHeight);
-    fPreview->SetAlignment(B_ALIGN_CENTER);
-
-    boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2);
-    boxDivider->ResizeTo(maxControlsWidth, 1.f);
-
-    labelFamily->MoveBy(0.f, offsetYLabels);
-    labelStyle->MoveBy(offsetXStyles, offsetYLabels);
-    labelSize->MoveBy(offsetXSizes, offsetYLabels);
-
-    //	text control alignment issues
-    float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
-    float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
-
-    scrollFamilies->MoveBy(0.f, offsetYLists);
-    scrollStyles->MoveBy(offsetXStyles, offsetYLists);
-    fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2);
-    scrollSizes->MoveBy(offsetXSizes, offsetYSizes);
-
-    fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER);
-
-    scrollFamilies->ResizeTo(familiesWidth, listsHeight);
-    scrollStyles->ResizeTo(stylesWidth, listsHeight);
-    fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height());
-    scrollSizes->ResizeTo(sizesWidth,
-	    listsHeight - (offsetYSizes - offsetYLists));
-
-    buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons);
-    buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width()
-	    - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons);
-
-    //	fill lists
-    int selIndex = -1;
-    int count = count_font_families();
-    for (int i = 0; i < count; i++) {
-	font_family family;
-	if (get_font_family(i, &family ) == B_OK) {
-	    fFamiliesList->AddItem(new BStringItem((const char*)family));
-	    if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0)
-		selIndex = i;
-	}
-    }
-
-    if (selIndex >= 0) {
-	fFamiliesList->Select(selIndex);
-	fFamiliesList->ScrollToSelection();
-    }
-
-    _UpdateFontStyles();
-
-    selIndex = -1;
-    for (int size = 8, index = 0; size <= 18; size++, index++) {
-	BString str;
-	str << size;
-	fSizesList->AddItem(new BStringItem(str));
-	if (size == fFontSize)
-	    selIndex = index;
-
-    }
-
-    if (selIndex >= 0) {
-	fSizesList->Select(selIndex);
-	fSizesList->ScrollToSelection();
-    }
-
-    fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg));
-    fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg));
-    fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg));
-    fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg));
-
-    _UpdateSizeInputPreview();
-    _UpdateFontPreview();
-
-    fStatus = B_OK;
-}
-
-VimSelectFontDialog::~VimSelectFontDialog()
-{
-    _CleanList(fFamiliesList);
-    _CleanList(fStylesList);
-    _CleanList(fSizesList);
-
-    if (fDialogSem > B_OK)
-	delete_sem(fDialogSem);
-}
-
-    void
-VimSelectFontDialog::_CleanList(BListView* list)
-{
-    while (0 < list->CountItems())
-	delete (dynamic_cast<BStringItem*>(list->RemoveItem((int32)0)));
-}
-
-    bool
-VimSelectFontDialog::Go()
-{
-    if (fStatus != B_OK) {
-	Quit();
-	return NOFONT;
-    }
-
-    fDialogSem = create_sem(0, "VimFontSelectDialogSem");
-    if (fDialogSem < B_OK) {
-	Quit();
-	return fDialogValue;
-    }
-
-    Show();
-
-    while (acquire_sem(fDialogSem) == B_INTERRUPTED);
-
-    bool retValue = fDialogValue;
-
-    if (Lock())
-	Quit();
-
-    return retValue;
-}
-
-
-void VimSelectFontDialog::_UpdateFontStyles()
-{
-    _CleanList(fStylesList);
-
-    int32 selIndex = -1;
-    int32 count = count_font_styles(fFontFamily);
-    for (int32 i = 0; i < count; i++) {
-	font_style style;
-	uint32 flags = 0;
-	if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) {
-	    fStylesList->AddItem(new BStringItem((const char*)style));
-	    if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0)
-		selIndex = i;
-	}
-    }
-
-    if (selIndex >= 0) {
-	fStylesList->Select(selIndex);
-	fStylesList->ScrollToSelection();
-    } else
-	fStylesList->Select(0);
-}
-
-
-void VimSelectFontDialog::_UpdateSizeInputPreview()
-{
-    char buf[10] = {0};
-    vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize);
-    fSizesInput->SetText(buf);
-}
-
-
-void VimSelectFontDialog::_UpdateFontPreview()
-{
-    BFont font;
-    fPreview->GetFont(&font);
-    font.SetSize(fFontSize);
-    font.SetFamilyAndStyle(fFontFamily, fFontStyle);
-    fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
-
-    BString str;
-    str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt.";
-    fPreview->SetText(str);
-}
-
-
-    bool
-VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize)
-{
-    int32 index = list->CurrentSelection();
-    if (index < 0)
-	return false;
-    BStringItem* item = (BStringItem*)list->ItemAt(index);
-    if (item == NULL)
-	return false;
-    strncpy(text, item->Text(), textSize);
-    return true;
-}
-
-
-void VimSelectFontDialog::MessageReceived(BMessage *msg)
-{
-    switch (msg->what) {
-	case kVimDialogOKButtonMsg:
-	    strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH);
-	    strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH);
-	    *fSize = fFontSize;
-	    fDialogValue = true;
-	case kVimDialogCancelButtonMsg:
-	    delete_sem(fDialogSem);
-	    fDialogSem = -1;
-	    return;
-	case B_KEY_UP:
-	    {
-		int32 key = 0;
-		if (msg->FindInt32("raw_char", &key) == B_OK
-			&& key == B_ESCAPE) {
-		    delete_sem(fDialogSem);
-		    fDialogSem = -1;
-		}
-	    }
-	    break;
-
-	case kVimDialogFamilySelectMsg:
-	    if (_UpdateFromListItem(fFamiliesList,
-		    fFontFamily, B_FONT_FAMILY_LENGTH)) {
-		_UpdateFontStyles();
-		_UpdateFontPreview();
-	    }
-	    break;
-	case kVimDialogStyleSelectMsg:
-	    if (_UpdateFromListItem(fStylesList,
-		    fFontStyle, B_FONT_STYLE_LENGTH))
-		_UpdateFontPreview();
-	    break;
-	case kVimDialogSizeSelectMsg:
-	    {
-		char buf[10] = {0};
-		if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) {
-		    float size = atof(buf);
-		    if (size > 0.f) {
-			fFontSize = size;
-			_UpdateSizeInputPreview();
-			_UpdateFontPreview();
-		    }
-		}
-	    }
-	    break;
-	case kVimDialogSizeInputMsg:
-	    {
-		float size = atof(fSizesInput->Text());
-		if (size > 0.f) {
-		    fFontSize = size;
-		    _UpdateFontPreview();
-		}
-	    }
-	    break;
-	default:
-	    break;
-    }
-    return BWindow::MessageReceived(msg);
-}
-
-#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;
-	}
-    }
-    return true;
-}
-
-    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);
-    }
-    return 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-8";
-key_map *keyMap;
-char *keyMapChars;
-int main_exitcode = 127;
-
-    status_t
-gui_haiku_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;
-		    }
-
-		    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
-			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;
-    }
-}
-
-/*
- * 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()
-{
-    display_errors();
-    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();
-	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 truly 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();
-    }
-}
-
-    int
-gui_mch_get_scrollbar_xpadding(void)
-{
-    // TODO: Calculate the padding for adjust scrollbar position when the
-    // Window is maximized.
-    return 0;
-}
-
-    int
-gui_mch_get_scrollbar_ypadding(void)
-{
-    // TODO: Calculate the padding for adjust scrollbar position when the
-    // Window is maximized.
-    return 0;
-}
-
-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(FEAT_GUI_HAIKU) || 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 does not flash
- */
-    int
-gui_mch_is_blink_off(void)
-{
-    return FALSE;
-}
-
-/*
- * 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(int may_call_gui_update_cursor)
-{
-    // 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;
-}
-
-
-    int
-gui_mch_font_dialog(font_family* family, font_style* style, float* size)
-{
-#if defined(FEAT_GUI_DIALOG)
-	// gui.vimWindow->Unlock();
-    VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size);
-    return dialog->Go();
-#else
-    return NOFONT;
-#endif // FEAT_GUI_DIALOG
-}
-
-
-GuiFont
-gui_mch_get_font(
-	char_u	    *name,
-	int	    giveErrorIfMissing)
-{
-    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};
-    float size = 0.f;
-
-    if (name == 0 && be_fixed_font == 0) {
-	if (giveErrorIfMissing)
-	    semsg(_(e_unknown_font_str), name);
-	return NOFONT;
-    }
-
-    bool useSelectGUI = false;
-    if (name != NULL)
-	if (STRCMP(name, "*") == 0) {
-	    useSelectGUI = true;
-	    STRNCPY(font_name, hl_get_font_name(), buff_size);
-	} else
-	    STRNCPY(font_name, name, buff_size);
-
-    if (font_name[0] == 0) {
-	be_fixed_font->GetFamilyAndStyle(&family, &style);
-	size = be_fixed_font->Size();
-	vim_snprintf(font_name, buff_size,
-	    (char*)"%s/%s/%.0f", family, style, size);
-    }
-
-    //	replace underscores with spaces
-    char* end = 0;
-    while (end = strchr((char *)font_name, '_'))
-	*end = ' ';
-
-    //	store the name before strtok corrupt the buffer ;-)
-    static char buff[buff_size] = {0};
-    STRNCPY(buff, font_name, buff_size);
-    STRNCPY(family, strtok(buff, "/\0"), B_FONT_FAMILY_LENGTH);
-    char* style_s = strtok(0, "/\0");
-    if (style_s != 0)
-	STRNCPY(style, style_s, B_FONT_STYLE_LENGTH);
-    size = atof((style_s != 0) ? strtok(0, "/\0") : "0");
-
-    if (useSelectGUI) {
-	if (gui_mch_font_dialog(&family, &style, &size) == NOFONT)
-	    return FAIL;
-	//  compose for further processing
-	vim_snprintf(font_name, buff_size,
-		(char*)"%s/%s/%.0f", family, style, size);
-	hl_set_font_name((char_u*)font_name);
-
-	//  Set guifont to the name of the selected font.
-	char_u* new_p_guifont = (char_u*)alloc(STRLEN(font_name) + 1);
-	if (new_p_guifont != NULL) {
-	    STRCPY(new_p_guifont, font_name);
-	    vim_free(p_guifont);
-	    p_guifont = new_p_guifont;
-	    //	Replace spaces in the font name with underscores.
-	    for ( ; *new_p_guifont; ++new_p_guifont)
-		if (*new_p_guifont == ' ')
-		    *new_p_guifont = '_';
-	}
-    }
-
-    VimFont *flp;
-    for (flp = fontList; flp; flp = flp->next) {
-	if (STRCMP(font_name, flp->name) == 0) {
-	    flp->refcount++;
-	    return (GuiFont)flp;
-	}
-    }
-
-    VimFont *font = new VimFont();
-    font->name = vim_strsave((char_u*)font_name);
-
-    if (count_font_styles(family) <= 0) {
-	if (giveErrorIfMissing)
-	    semsg(_(e_unknown_font_str), 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)
-{
-    return gui_get_color_cmn(name);
-}
-
-/*
- * 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();
-    }
-}
-
-	guicolor_T
-gui_mch_get_rgb_color(int r, int g, int b)
-{
-    return gui_get_rgb_color_cmn(r, g, b);
-}
-
-
-// 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(void)
-{
-    // 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);
-    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;
-    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_haiku_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(TRUE);
-	    focus = gui.in_focus;
-	}
-
-	gui_mch_flush();
-
-#ifdef MESSAGE_QUEUE
-# ifdef FEAT_TIMERS
-	did_add_timer = FALSE;
-# endif
-	parse_queued_messages();
-# ifdef FEAT_TIMERS
-	if (did_add_timer)
-	    // Need to recompute the waiting time.
-	    break;
-# endif
-# ifdef FEAT_JOB_CHANNEL
-	if (has_any_channel())
-	{
-	    if (wtime < 0 || timeout > 20000)
-		timeout = 20000;
-	}
-	else if (wtime < 0)
-	    timeout = B_INFINITE_TIMEOUT;
-# endif
-#endif
-
-	/*
-	 * Don't use gui_mch_update() because then we will spin-lock until a
-	 * char arrives, instead we use gui_haiku_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_haiku_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 it's 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(Clipboard_T *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(Clipboard_T *cbd)
-{
-    // Nothing needs to be done here
-}
-
-/*
- * Make vim the owner of the current selection.  Return OK upon success.
- */
-    int
-clip_mch_own_selection(Clipboard_T *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(Clipboard_T *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,
-	int ex_cmd)
-{
-    VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message,
-	    (char*)buttons, dfltbutton, (char*)textfield, ex_cmd);
-    return dialog->Go();
-}
-
-#endif // FEAT_GUI_DIALOG
-
-
-/*
- * Return the RGB value of a pixel as long.
- */
-    guicolor_T
-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;
-}
-#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
+/* 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.
+ *
+ * Based on "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@gmx.li> Apr-Mai 2009
+ *
+ */
+
+/*
+ * Structure of the Haiku 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 <assert.h>
+#include <float.h>
+#include <syslog.h>
+
+#include "vim.h"
+#include "version.h"
+
+}   // extern "C"
+
+// ---------------- start of header part ----------------
+
+//#include <Alert.h>
+#include <Application.h>
+#include <Beep.h>
+#include <Bitmap.h>
+#include <Box.h>
+#include <Button.h>
+#include <Clipboard.h>
+#include <Debug.h>
+//#include <Directory.h>
+//#include <Entry.h>
+#include <File.h>
+#include <FilePanel.h>
+#include <FindDirectory.h>
+//#include <Font.h>
+#include <IconUtils.h>
+#include <Input.h>
+#include <ListView.h>
+#include <MenuBar.h>
+#include <MenuItem.h>
+//#include <MessageQueue.h>
+//#include <OS.h>
+#include <Path.h>
+#include <PictureButton.h>
+#include <PopUpMenu.h>
+//#include <Region.h>
+#include <Resources.h>
+//#include <Roster.h>
+#include <Screen.h>
+#include <ScrollBar.h>
+#include <ScrollView.h>
+#include <String.h>
+#include <StringView.h>
+//#include <SupportDefs.h>
+#include <TabView.h>
+#include <TextControl.h>
+#include <TextView.h>
+#include <TranslationUtils.h>
+#include <TranslatorFormats.h>
+#include <View.h>
+#include <Window.h>
+
+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:
+
+    class View : public BView {
+	typedef BView Inherited;
+
+	public:
+	View(BRect frame);
+	~View();
+
+	virtual void Draw(BRect updateRect);
+	void InitIcon(int32 type);
+
+	private:
+	BBitmap*    fIconBitmap;
+    };
+
+    VimDialog(int type, const char *title, const char *message,
+	    const char *buttons, int dfltbutton, const char *textfield,
+	    int ex_cmd);
+    ~VimDialog();
+
+    int Go();
+
+    virtual void MessageReceived(BMessage *msg);
+
+    private:
+    sem_id	    fDialogSem;
+    int		    fDialogValue;
+    BList	    fButtonsList;
+    BTextView*	    fMessageView;
+    BTextControl*   fInputControl;
+    const char*	    fInputValue;
+};
+
+class VimSelectFontDialog : public BWindow
+{
+    typedef BWindow Inherited;
+
+    void _CleanList(BListView* list);
+    void _UpdateFontStyles();
+    void _UpdateSizeInputPreview();
+    void _UpdateFontPreview();
+    bool _UpdateFromListItem(BListView* list, char* text, int textSize);
+    public:
+
+    VimSelectFontDialog(font_family* family, font_style* style, float* size);
+    ~VimSelectFontDialog();
+
+    bool Go();
+
+    virtual void MessageReceived(BMessage *msg);
+
+    private:
+    status_t	    fStatus;
+    sem_id	    fDialogSem;
+    bool	    fDialogValue;
+    font_family*    fFamily;
+    font_style*	    fStyle;
+    float*	    fSize;
+    font_family	    fFontFamily;
+    font_style	    fFontStyle;
+    float	    fFontSize;
+    BStringView*    fPreview;
+    BListView*	    fFamiliesList;
+    BListView*	    fStylesList;
+    BListView*	    fSizesList;
+    BTextControl*   fSizesInput;
+};
+
+#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
+    bool    csi_escape;
+};
+
+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)	{ (char_u)((g) >> 16), (char_u)((g) >> 8), (char_u)((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    ARRAY_LENGTH(special_keys)
+
+// ---------------- 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 .");
+}
+
+	static void
+drop_callback(void *cookie)
+{
+    // TODO here we could handle going to a specific position in the dropped
+    // file (see src/gui_mac.c, deleted in 8.2.1422)
+    // Update the screen display
+    update_screen(UPD_NOT_VALID);
+}
+
+    // 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, drop_callback, NULL);
+
+	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.
+     */
+    mch_signal(SIGINT, SIG_IGN);
+    mch_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);
+    km.csi_escape = false;
+    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.
+     */
+    mch_signal(SIGINT, SIG_IGN);
+    mch_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);
+#define W_WIDTH(curwin)   0
+}
+
+    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);
+	km.csi_escape = true;
+    } 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;
+	km.csi_escape = false;
+    }
+
+    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, 1);
+    if (newFont != NOFONT) {
+	gui.norm_font = (GuiFont)newFont;
+	gui_mch_set_font((GuiFont)newFont);
+	if (name && STRCMP(name, "*") != 0)
+	    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;
+	cells = 0;
+	for (int i=0; i<len; i++) {
+	    int cn = utf_ptr2cells((char_u *)(s+i));
+	    if (cn<4) cells += cn;
+	}
+
+	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) {
+	    clen = utf_ptr2len((u_char*)p);
+	    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);
+	    }
+	    cells = utf_ptr2cells((char_u *)p);
+	    if (cells<4) lastpos += cells;
+	    else	lastpos++;
+	    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;
+	cells = 0;
+	for (int i=0; i<len; i++) {
+	    int cn = utf_ptr2cells((char_u *)(s+i));
+	    if (cn<4) cells += cn;
+	}
+
+	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, int ex_cmd)
+: 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
+    VimDialog::View* view = new VimDialog::View(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.SetByteAt(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;
+}
+
+VimDialog::View::View(BRect frame)
+    :	BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
+    fIconBitmap(NULL)
+{
+    SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+}
+
+VimDialog::View::~View()
+{
+    delete fIconBitmap;
+}
+
+void VimDialog::View::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 VimDialog::View::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;
+    //	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;
+
+    //	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;
+    }
+
+    if (fIconBitmap->ColorSpace() != B_CMAP8)
+	BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
+}
+
+const unsigned int  kVimDialogOKButtonMsg = 'FDOK';
+const unsigned int  kVimDialogCancelButtonMsg = 'FDCN';
+const unsigned int  kVimDialogSizeInputMsg = 'SICH';
+const unsigned int  kVimDialogFamilySelectMsg = 'MSFM';
+const unsigned int  kVimDialogStyleSelectMsg = 'MSST';
+const unsigned int  kVimDialogSizeSelectMsg = 'MSSZ';
+
+VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size)
+: BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
+	B_NOT_CLOSABLE | B_NOT_RESIZABLE |
+	B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
+    , fStatus(B_NO_INIT)
+    , fDialogSem(-1)
+    , fDialogValue(false)
+    , fFamily(family)
+    , fStyle(style)
+    , fSize(size)
+    , fFontSize(*size)
+    , fPreview(0)
+    , fFamiliesList(0)
+    , fStylesList(0)
+    , fSizesList(0)
+    , fSizesInput(0)
+{
+    strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH);
+    strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH);
+
+    //	"client" area view
+    BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
+		    B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED,
+		    B_PLAIN_BORDER);
+    AddChild(clientBox);
+
+    //	client view
+    BRect RC = clientBox->Bounds();
+    RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY);
+    BRect rc(RC.LeftTop(), RC.LeftTop());
+
+    //	at first create all controls
+    fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono");
+    clientBox->AddChild(fPreview);
+
+    BBox* boxDivider = new BBox(rc, B_EMPTY_STRING,
+	    B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER);
+    clientBox->AddChild(boxDivider);
+
+    BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:");
+    clientBox->AddChild(labelFamily);
+    labelFamily->ResizeToPreferred();
+
+    BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:");
+    clientBox->AddChild(labelStyle);
+    labelStyle->ResizeToPreferred();
+
+    BStringView *labelSize = new BStringView(rc, "labelSize", "Size:");
+    clientBox->AddChild(labelSize);
+    labelSize->ResizeToPreferred();
+
+    fFamiliesList = new BListView(rc, "listFamily",
+	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
+    BScrollView *scrollFamilies = new BScrollView("scrollFamily",
+	    fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
+    clientBox->AddChild(scrollFamilies);
+
+    fStylesList= new BListView(rc, "listStyles",
+	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
+    BScrollView *scrollStyles = new BScrollView("scrollStyle",
+	    fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
+    clientBox->AddChild(scrollStyles);
+
+    fSizesInput = new BTextControl(rc, "inputSize", NULL, "???",
+	    new BMessage(kVimDialogSizeInputMsg));
+    clientBox->AddChild(fSizesInput);
+    fSizesInput->ResizeToPreferred();
+
+    fSizesList = new BListView(rc, "listSizes",
+	    B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
+    BScrollView *scrollSizes = new BScrollView("scrollSize",
+	    fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
+    clientBox->AddChild(scrollSizes);
+
+    BButton *buttonOK = new BButton(rc, "buttonOK", "OK",
+			new BMessage(kVimDialogOKButtonMsg));
+    clientBox->AddChild(buttonOK);
+    buttonOK->ResizeToPreferred();
+
+    BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel",
+			new BMessage(kVimDialogCancelButtonMsg));
+    clientBox->AddChild(buttonCancel);
+    buttonCancel->ResizeToPreferred();
+
+    //	layout controls
+    float lineHeight = labelFamily->Bounds().Height();
+    float previewHeight = lineHeight * 3;
+    float offsetYLabels = previewHeight + kVimDialogSpacingY;
+    float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2;
+    float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2;
+    float listsHeight = lineHeight * 9;
+    float offsetYButtons = offsetYLists + listsHeight +  kVimDialogSpacingY;
+    float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height();
+    float familiesWidth = labelFamily->Bounds().Width() * 5;
+    float offsetXStyles = familiesWidth + kVimDialogSpacingX;
+    float stylesWidth = labelStyle->Bounds().Width() * 4;
+    float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX;
+    float sizesWidth = labelSize->Bounds().Width() * 2;
+    float maxControlsWidth = offsetXSizes + sizesWidth;
+
+    ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2,
+	maxControlsHeight + kVimDialogSpacingY * 2);
+
+    BRect rcVim = gui.vimWindow->Frame();
+    MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2,
+	    rcVim.top + (rcVim.Height() - Frame().Height()) / 2);
+
+    fPreview->ResizeTo(maxControlsWidth, previewHeight);
+    fPreview->SetAlignment(B_ALIGN_CENTER);
+
+    boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2);
+    boxDivider->ResizeTo(maxControlsWidth, 1.f);
+
+    labelFamily->MoveBy(0.f, offsetYLabels);
+    labelStyle->MoveBy(offsetXStyles, offsetYLabels);
+    labelSize->MoveBy(offsetXSizes, offsetYLabels);
+
+    //	text control alignment issues
+    float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
+    float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
+
+    scrollFamilies->MoveBy(0.f, offsetYLists);
+    scrollStyles->MoveBy(offsetXStyles, offsetYLists);
+    fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2);
+    scrollSizes->MoveBy(offsetXSizes, offsetYSizes);
+
+    fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER);
+
+    scrollFamilies->ResizeTo(familiesWidth, listsHeight);
+    scrollStyles->ResizeTo(stylesWidth, listsHeight);
+    fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height());
+    scrollSizes->ResizeTo(sizesWidth,
+	    listsHeight - (offsetYSizes - offsetYLists));
+
+    buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons);
+    buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width()
+	    - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons);
+
+    //	fill lists
+    int selIndex = -1;
+    int count = count_font_families();
+    for (int i = 0; i < count; i++) {
+	font_family family;
+	if (get_font_family(i, &family ) == B_OK) {
+	    fFamiliesList->AddItem(new BStringItem((const char*)family));
+	    if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0)
+		selIndex = i;
+	}
+    }
+
+    if (selIndex >= 0) {
+	fFamiliesList->Select(selIndex);
+	fFamiliesList->ScrollToSelection();
+    }
+
+    _UpdateFontStyles();
+
+    selIndex = -1;
+    for (int size = 8, index = 0; size <= 18; size++, index++) {
+	BString str;
+	str << size;
+	fSizesList->AddItem(new BStringItem(str));
+	if (size == fFontSize)
+	    selIndex = index;
+
+    }
+
+    if (selIndex >= 0) {
+	fSizesList->Select(selIndex);
+	fSizesList->ScrollToSelection();
+    }
+
+    fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg));
+    fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg));
+    fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg));
+    fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg));
+
+    _UpdateSizeInputPreview();
+    _UpdateFontPreview();
+
+    fStatus = B_OK;
+}
+
+VimSelectFontDialog::~VimSelectFontDialog()
+{
+    _CleanList(fFamiliesList);
+    _CleanList(fStylesList);
+    _CleanList(fSizesList);
+
+    if (fDialogSem > B_OK)
+	delete_sem(fDialogSem);
+}
+
+    void
+VimSelectFontDialog::_CleanList(BListView* list)
+{
+    while (0 < list->CountItems())
+	delete (dynamic_cast<BStringItem*>(list->RemoveItem((int32)0)));
+}
+
+    bool
+VimSelectFontDialog::Go()
+{
+    if (fStatus != B_OK) {
+	Quit();
+	return NOFONT;
+    }
+
+    fDialogSem = create_sem(0, "VimFontSelectDialogSem");
+    if (fDialogSem < B_OK) {
+	Quit();
+	return fDialogValue;
+    }
+
+    Show();
+
+    while (acquire_sem(fDialogSem) == B_INTERRUPTED);
+
+    bool retValue = fDialogValue;
+
+    if (Lock())
+	Quit();
+
+    return retValue;
+}
+
+
+void VimSelectFontDialog::_UpdateFontStyles()
+{
+    _CleanList(fStylesList);
+
+    int32 selIndex = -1;
+    int32 count = count_font_styles(fFontFamily);
+    for (int32 i = 0; i < count; i++) {
+	font_style style;
+	uint32 flags = 0;
+	if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) {
+	    fStylesList->AddItem(new BStringItem((const char*)style));
+	    if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0)
+		selIndex = i;
+	}
+    }
+
+    if (selIndex >= 0) {
+	fStylesList->Select(selIndex);
+	fStylesList->ScrollToSelection();
+    } else
+	fStylesList->Select(0);
+}
+
+
+void VimSelectFontDialog::_UpdateSizeInputPreview()
+{
+    char buf[10] = {0};
+    vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize);
+    fSizesInput->SetText(buf);
+}
+
+
+void VimSelectFontDialog::_UpdateFontPreview()
+{
+    BFont font;
+    fPreview->GetFont(&font);
+    font.SetSize(fFontSize);
+    font.SetFamilyAndStyle(fFontFamily, fFontStyle);
+    fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
+
+    BString str;
+    str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt.";
+    fPreview->SetText(str);
+}
+
+
+    bool
+VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize)
+{
+    int32 index = list->CurrentSelection();
+    if (index < 0)
+	return false;
+    BStringItem* item = (BStringItem*)list->ItemAt(index);
+    if (item == NULL)
+	return false;
+    strncpy(text, item->Text(), textSize);
+    return true;
+}
+
+
+void VimSelectFontDialog::MessageReceived(BMessage *msg)
+{
+    switch (msg->what) {
+	case kVimDialogOKButtonMsg:
+	    strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH);
+	    strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH);
+	    *fSize = fFontSize;
+	    fDialogValue = true;
+	case kVimDialogCancelButtonMsg:
+	    delete_sem(fDialogSem);
+	    fDialogSem = -1;
+	    return;
+	case B_KEY_UP:
+	    {
+		int32 key = 0;
+		if (msg->FindInt32("raw_char", &key) == B_OK
+			&& key == B_ESCAPE) {
+		    delete_sem(fDialogSem);
+		    fDialogSem = -1;
+		}
+	    }
+	    break;
+
+	case kVimDialogFamilySelectMsg:
+	    if (_UpdateFromListItem(fFamiliesList,
+		    fFontFamily, B_FONT_FAMILY_LENGTH)) {
+		_UpdateFontStyles();
+		_UpdateFontPreview();
+	    }
+	    break;
+	case kVimDialogStyleSelectMsg:
+	    if (_UpdateFromListItem(fStylesList,
+		    fFontStyle, B_FONT_STYLE_LENGTH))
+		_UpdateFontPreview();
+	    break;
+	case kVimDialogSizeSelectMsg:
+	    {
+		char buf[10] = {0};
+		if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) {
+		    float size = atof(buf);
+		    if (size > 0.f) {
+			fFontSize = size;
+			_UpdateSizeInputPreview();
+			_UpdateFontPreview();
+		    }
+		}
+	    }
+	    break;
+	case kVimDialogSizeInputMsg:
+	    {
+		float size = atof(fSizesInput->Text());
+		if (size > 0.f) {
+		    fFontSize = size;
+		    _UpdateFontPreview();
+		}
+	    }
+	    break;
+	default:
+	    break;
+    }
+    return BWindow::MessageReceived(msg);
+}
+
+#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;
+	}
+    }
+    return true;
+}
+
+    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);
+    }
+    return 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-8";
+key_map *keyMap;
+char *keyMapChars;
+int main_exitcode = 127;
+
+    status_t
+gui_haiku_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;
+		    }
+
+		    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
+			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;
+    }
+}
+
+/*
+ * 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()
+{
+    display_errors();
+    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();
+	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 truly 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();
+    }
+}
+
+    int
+gui_mch_get_scrollbar_xpadding(void)
+{
+    // TODO: Calculate the padding for adjust scrollbar position when the
+    // Window is maximized.
+    return 0;
+}
+
+    int
+gui_mch_get_scrollbar_ypadding(void)
+{
+    // TODO: Calculate the padding for adjust scrollbar position when the
+    // Window is maximized.
+    return 0;
+}
+
+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(FEAT_GUI_HAIKU) || 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 does not flash
+ */
+    int
+gui_mch_is_blink_off(void)
+{
+    return FALSE;
+}
+
+/*
+ * 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(int may_call_gui_update_cursor)
+{
+    // 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;
+}
+
+
+    int
+gui_mch_font_dialog(font_family* family, font_style* style, float* size)
+{
+#if defined(FEAT_GUI_DIALOG)
+	// gui.vimWindow->Unlock();
+    VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size);
+    return dialog->Go();
+#else
+    return NOFONT;
+#endif // FEAT_GUI_DIALOG
+}
+
+
+GuiFont
+gui_mch_get_font(
+	char_u	    *name,
+	int	    giveErrorIfMissing)
+{
+    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};
+    float size = 0.f;
+
+    if (name == 0 && be_fixed_font == 0) {
+	if (giveErrorIfMissing)
+	    semsg(_(e_unknown_font_str), name);
+	return NOFONT;
+    }
+
+    bool useSelectGUI = false;
+    if (name != NULL)
+	if (STRCMP(name, "*") == 0) {
+	    useSelectGUI = true;
+	    STRNCPY(font_name, hl_get_font_name(), buff_size);
+	} else
+	    STRNCPY(font_name, name, buff_size);
+
+    if (font_name[0] == 0) {
+	be_fixed_font->GetFamilyAndStyle(&family, &style);
+	size = be_fixed_font->Size();
+	vim_snprintf(font_name, buff_size,
+	    (char*)"%s/%s/%.0f", family, style, size);
+    }
+
+    //	replace underscores with spaces
+    char* end = 0;
+    while (end = strchr((char *)font_name, '_'))
+	*end = ' ';
+
+    //	store the name before strtok corrupt the buffer ;-)
+    static char buff[buff_size] = {0};
+    STRNCPY(buff, font_name, buff_size);
+    STRNCPY(family, strtok(buff, "/\0"), B_FONT_FAMILY_LENGTH);
+    char* style_s = strtok(0, "/\0");
+    if (style_s != 0)
+	STRNCPY(style, style_s, B_FONT_STYLE_LENGTH);
+    size = atof((style_s != 0) ? strtok(0, "/\0") : "0");
+
+    if (useSelectGUI) {
+	if (gui_mch_font_dialog(&family, &style, &size) == NOFONT)
+	    return FAIL;
+	//  compose for further processing
+	vim_snprintf(font_name, buff_size,
+		(char*)"%s/%s/%.0f", family, style, size);
+	hl_set_font_name((char_u*)font_name);
+
+	//  Set guifont to the name of the selected font.
+	char_u* new_p_guifont = (char_u*)alloc(STRLEN(font_name) + 1);
+	if (new_p_guifont != NULL) {
+	    STRCPY(new_p_guifont, font_name);
+	    vim_free(p_guifont);
+	    p_guifont = new_p_guifont;
+	    //	Replace spaces in the font name with underscores.
+	    for ( ; *new_p_guifont; ++new_p_guifont)
+		if (*new_p_guifont == ' ')
+		    *new_p_guifont = '_';
+	}
+    }
+
+    VimFont *flp;
+    for (flp = fontList; flp; flp = flp->next) {
+	if (STRCMP(font_name, flp->name) == 0) {
+	    flp->refcount++;
+	    return (GuiFont)flp;
+	}
+    }
+
+    VimFont *font = new VimFont();
+    font->name = vim_strsave((char_u*)font_name);
+
+    if (count_font_styles(family) <= 0) {
+	if (giveErrorIfMissing)
+	    semsg(_(e_unknown_font_str), 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)
+{
+    return gui_get_color_cmn(name);
+}
+
+/*
+ * 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();
+    }
+}
+
+	guicolor_T
+gui_mch_get_rgb_color(int r, int g, int b)
+{
+    return gui_get_rgb_color_cmn(r, g, b);
+}
+
+
+// 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(void)
+{
+    // 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);
+    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;
+    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_haiku_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(TRUE);
+	    focus = gui.in_focus;
+	}
+
+	gui_mch_flush();
+
+#ifdef MESSAGE_QUEUE
+# ifdef FEAT_TIMERS
+	did_add_timer = FALSE;
+# endif
+	parse_queued_messages();
+# ifdef FEAT_TIMERS
+	if (did_add_timer)
+	    // Need to recompute the waiting time.
+	    break;
+# endif
+# ifdef FEAT_JOB_CHANNEL
+	if (has_any_channel())
+	{
+	    if (wtime < 0 || timeout > 20000)
+		timeout = 20000;
+	}
+	else if (wtime < 0)
+	    timeout = B_INFINITE_TIMEOUT;
+# endif
+#endif
+
+	/*
+	 * Don't use gui_mch_update() because then we will spin-lock until a
+	 * char arrives, instead we use gui_haiku_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_haiku_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 it's 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(Clipboard_T *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(Clipboard_T *cbd)
+{
+    // Nothing needs to be done here
+}
+
+/*
+ * Make vim the owner of the current selection.  Return OK upon success.
+ */
+    int
+clip_mch_own_selection(Clipboard_T *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(Clipboard_T *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,
+	int ex_cmd)
+{
+    VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message,
+	    (char*)buttons, dfltbutton, (char*)textfield, ex_cmd);
+    return dialog->Go();
+}
+
+#endif // FEAT_GUI_DIALOG
+
+
+/*
+ * Return the RGB value of a pixel as long.
+ */
+    guicolor_T
+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;
+}
+#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