Files
haikuports/app-editors/vim/patches/vim-8.0.0046.patchset
miqlas c527264139 Vim: Add recipe for versionn 8 (#840)
* patchset needs cleaning.
* recipe could use $portVersion, SOURCE_DIR could be dropped.
2016-11-09 11:16:58 +01:00

7018 lines
185 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
From 65c1b63afda81ed6198c5c1bd175e4e28be75bda Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zolt=C3=A1n=20Mizsei?= <zmizsei@extrowerk.com>
Date: Tue, 25 Oct 2016 19:58:41 +0200
Subject: [PATCH] Squashed patch
2
patches
3
Fixes
Original configure
---
runtime/doc/eval.txt | 2 +
runtime/doc/gui.txt | 1 +
runtime/doc/help.txt | 1 +
runtime/doc/options.txt | 10 +-
runtime/doc/os_haiku.txt | 223 ++
runtime/doc/starting.txt | 3 +
runtime/doc/tags | 16 +
runtime/doc/vi_diff.txt | 3 +-
runtime/gvimrc_example.vim | 1 +
runtime/lang/menu_pl.utf-8.vim | 3 +
runtime/vimrc_example.vim | 1 +
src/Makefile | 80 +
src/configure.in | 37 +-
src/evalfunc.c | 6 +
src/ex_cmds.c | 18 +
src/ex_docmd.c | 1 +
src/feature.h | 19 +-
src/gui.c | 34 +-
src/gui.h | 21 +-
src/gui_haiku.cc | 5294 ++++++++++++++++++++++++++++++++++++++++
src/gui_haiku.h | 51 +
src/misc1.c | 15 +-
src/normal.c | 5 +-
src/option.h | 4 +
src/os_haiku.h | 29 +
src/os_haiku.rdef | 143 ++
src/os_unix.c | 6 +-
src/os_unix.h | 4 +
src/po/zh_CN.cp936.po | 2 +-
src/proto.h | 3 +
src/proto/gui_haiku.pro | 92 +
src/pty.c | 2 +-
src/screen.c | 33 +
src/structs.h | 7 +
src/term.c | 5 +
src/ui.c | 2 +-
src/version.c | 4 +
src/vim.h | 11 +-
38 files changed, 6160 insertions(+), 32 deletions(-)
create mode 100644 runtime/doc/os_haiku.txt
create mode 100644 runtime/lang/menu_pl.utf-8.vim
create mode 100644 src/gui_haiku.cc
create mode 100644 src/gui_haiku.h
create mode 100644 src/os_haiku.h
create mode 100644 src/os_haiku.rdef
create mode 100644 src/proto/gui_haiku.pro
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 88599dd..a799c95 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -8326,12 +8326,14 @@ gui_gnome Compiled with Gnome support (gui_gtk is also defined).
gui_gtk Compiled with GTK+ GUI (any version).
gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined).
gui_gtk3 Compiled with GTK+ 3 GUI (gui_gtk is also defined).
+gui_haiku Compiled with Haiku GUI.
gui_mac Compiled with Macintosh GUI.
gui_motif Compiled with Motif GUI.
gui_photon Compiled with Photon GUI.
gui_running Vim is running in the GUI, or it will start soon.
gui_win32 Compiled with MS Windows Win32 GUI.
gui_win32s idem, and Win32s system being used (Windows 3.1)
+haiku Haiku version of Vim.
hangul_input Compiled with Hangul input support. |hangul|
iconv Can use iconv() for conversion.
insert_expand Compiled with support for CTRL-X expansion commands in
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index efe6319..33b8cd7 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -100,6 +100,7 @@ Recommended place for your personal GUI initializations:
or $VIM/_gvimrc
Amiga s:.gvimrc, home:.gvimrc, home:vimfiles:gvimrc
or $VIM/.gvimrc
+ Haiku $HOME/config/settings/vim/gvimrc
The personal initialization files are searched in the order specified above
and only the first one that is found is read.
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 58049f6..318e434 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -192,6 +192,7 @@ Remarks about specific systems ~
|os_os2.txt| OS/2
|os_qnx.txt| QNX
|os_risc.txt| RISC-OS
+|os_haiku.txt| Haiku
|os_unix.txt| Unix
|os_vms.txt| VMS
|os_win32.txt| MS-Windows 95/98/NT
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 390fab0..40a6fbe 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3785,7 +3785,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'guitablabel' can be used to change the text in the labels.
When 'e' is missing a non-GUI tab pages line may be used.
The GUI tabs are only supported on some systems, currently
- GTK, Motif, Mac OS/X and MS-Windows.
+ GTK, Motif, Mac OS/X, Haiku and MS-Windows.
*'go-f'*
'f' Foreground: Don't use fork() to detach the GUI from the shell
where it was started. Use this for programs that wait for the
@@ -6085,7 +6085,12 @@ A jump table for the options with a short description can be found at |Q_op|.
$VIM/vimfiles,
$VIMRUNTIME,
$VIM/vimfiles/after,
- sys$login:vimfiles/after")
+ sys$login:vimfiles/after"
+ Haiku: "$BE_USER_SETTINGS/vim,
+ $VIM/vimfiles,
+ $VIMRUNTIME,
+ $VIM/vimfiles/after,
+ $BE_USER_SETTINGS/vim/after")
global
{not in Vi}
This is a list of directories which will be searched for runtime
@@ -7543,6 +7548,7 @@ A jump table for the options with a short description can be found at |Q_op|.
on MiNT: "vt52"
on MS-DOS: "pcterm"
on OS/2: "os2ansi"
+ on Haiku: "xterm"
on Unix: "ansi"
on VMS: "ansi"
on Win 32: "win32")
diff --git a/runtime/doc/os_haiku.txt b/runtime/doc/os_haiku.txt
new file mode 100644
index 0000000..b95e13d
--- /dev/null
+++ b/runtime/doc/os_haiku.txt
@@ -0,0 +1,223 @@
+*os_haiku.txt* For Vim version 7.4. Last change: 2013 Sep 12
+
+
+ VIM REFERENCE MANUAL by Bram Moolenaar
+
+ *Haiku*
+
+This file contains the particularities for the Haiku version of Vim. For
+matters not discussed in this file, Vim behaves very much like the Unix
+|os_unix.txt| version.
+
+ 1. General |haiku-general|
+ 2. Compiling Vim |haiku-compiling|
+ 3. The Haiku GUI |haiku-gui|
+ 4. The $VIM directory |haiku-vimdir|
+ 5. The $BE_USER_SETTINGS
+ directory |haiku-user-settings-dir|
+ 6. Drag & Drop |haiku-dragndrop|
+ 7. Single Launch vs. Multiple
+ Launch |haiku-launch|
+ 8. Fonts |haiku-fonts|
+ 9. The meta key modifier |haiku-meta|
+10. Mouse key mappings |haiku-mouse|
+11. Color names |haiku-colors|
+12. Credits |haiku-support-credits|
+13. Bugs & things To Do |haiku-bugs|
+
+
+1. General *haiku-general*
+
+The default syntax highlighting mostly works with different foreground colors
+to highlight items. This works best if you set your Terminal window to a
+darkish background and light letters. Some middle-grey background (for
+instance (r,g,b)=(168,168,168)) with black letters also works nicely.
+
+
+2. Compiling Vim *haiku-compiling*
+
+Vim can be compiled using the standard configure/make approach. Running
+./configure without any arguments or passing --enable-gui=haiku, will compile
+vim with the Haiku GUI support. Run ./configure --help , to find out other
+features you can enable/disable.
+
+Now you should use "make" to compile Vim, then "make install" to install it.
+For seamless integration into the Haiku the GUI-less vim binary should be
+additionally installed over the GUI version. Typical build commands are: >
+
+ ./configure --prefix=`finddir B_COMMON_DIRECTORY` \
+ --datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \
+ --mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \
+ make clean
+ make install
+
+ ./configure --prefix=`finddir B_COMMON_DIRECTORY` \
+ --datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \
+ --mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \
+ --disable-gui
+ make clean
+ make install
+
+
+3. The Haiku GUI *haiku-gui*
+
+Normally Vim starts with the GUI if you start it as gvim or vim -g. The vim
+version with GUI tries to determine if it was started from the Tracker instead
+of the Terminal, and if so, use the GUI anyway. However, the current detection
+scheme is fooled if you use the command "vim - </dev/null".
+
+Stuff that does not work yet:
+
+- Mouse up events are not generated when outside the window. This may be a bug in
+ Haiku. You can notice this when selecting text and moving the cursor outside
+ the window, then letting go of the mouse button. Another way is when you
+ drag the scrollbar and do the same thing. Because Vim still thinks you are
+ still playing with the scrollbar it won't change it itself. I provided a
+ workaround which kicks in when the window is activated or deactivated (so it
+ works best with focus- follows-mouse turned on).
+- The cursor does not flash (very low priority; I'm not sure I even like it
+ when it flashes)
+
+
+4. The $VIM directory *haiku-vimdir*
+
+$VIM is the symbolic name for the place where Vims support files are stored.
+The default value for $VIM is set at compile time and can be determined with >
+
+ :version
+
+The normal value is /boot/common/data/vim. If you don't like it you can
+set the VIM environment variable to override this, or set 'helpfile' in your
+.vimrc: >
+
+ :if version >= 500
+ : set helpfile=~/vim/vim74/doc/help.txt
+ : syntax on
+ :endif
+
+
+5. The $USER_SETTINGS_DIR directory *haiku-user-settings-dir*
+
+$USER_SETTINGS_DIR is the symbolic name for the place where Haiku
+configuration and settings files are stored.
+
+The normal value is /boot/home/condig/settings.
+
+
+6. Drag & Drop *haiku-dragndrop*
+
+You can drop files and directories on either the Vim icon (starts a new Vim
+session, unless you use the File Types application to set Vim to be "Single
+Launch") or on the Vim window (starts editing the files). Dropping a folder
+sets Vim's current working directory. |:cd| |:pwd| If you drop files or
+folders with either SHIFT key pressed, Vim changes directory to the folder
+that contains the first item dropped. When starting Vim, there is no need to
+press shift: Vim behaves as if you do.
+
+Files dropped set the current argument list. |argument-list|
+
+
+7. Single Launch vs. Multiple Launch *haiku-launch*
+
+As distributed Vim's Application Flags (as seen in the FileTypes preference)
+are set to Multiple Launch. If you prefer, you can set them to Single Launch
+instead. Attempts to start a second copy of Vim will cause the first Vim to
+open the files instead. This works from the Tracker but also from the command
+line. In the latter case, non-file (option) arguments are not supported.
+Another drawback of the Single Launch is silent ignore of "Open With ..."
+requests by vim instance that running as non-GUI application even GUI support
+was compiled in. Vim instance running with GUI has no such problems.
+
+NB: Only the GUI version has a BApplication (and hence Application Flags).
+This section does not apply to the GUI-less version, should you compile one.
+
+
+8. Fonts *haiku-fonts*
+
+Set fonts with >
+
+ :set guifont=DejaVu_Sans_Mono/Book/12
+
+where the first part is the font family, the second part the style, and the
+third part the size. You can use underscores instead of spaces in family and
+style.
+
+Best results are obtained with monospaced fonts. Vim attempts to use all
+fonts in B_FIXED_SPACING mode but apparently this does not work for
+proportional fonts (despite what the BeBook says).
+
+To verify which encodings are supported by the current font give the >
+
+ :digraphs
+
+command, which lists a bunch of characters with their ISO Latin 1 encoding.
+If, for instance, there are "box" characters among them, or the last character
+isn't a dotted-y, then for this font the encoding does not work.
+
+If the font you specify is unavailable, you get the system fixed font.
+
+GUI Font Selection Dialog is available at giving the >
+
+ :set guifont=*
+
+command.
+
+
+9. The meta key modifier *haiku-meta*
+
+The META key modifier is obtained by the left or right OPTION keys. This is
+because the ALT (aka COMMAND) keys are not passed to applications.
+
+
+10. Mouse key mappings *haiku-mouse*
+
+Vim calls the various mouse buttons LeftMouse, MiddleMouse and RightMouse. If
+you use the default Mouse preference settings these names indeed correspond to
+reality. Vim uses this mapping:
+
+ Button 1 -> LeftMouse,
+ Button 2 -> RightMouse,
+ Button 3 -> MiddleMouse.
+
+If your mouse has fewer than 3 buttons you can provide your own mapping from
+mouse clicks with modifier(s) to other mouse buttons. See the file
+$VIM/macros/swapmous.vim for an example. |gui-mouse-mapping|
+
+
+11. Color names *haiku-colors*
+
+Vim has a number of color names built-in. Additional names are read from the
+file $VIMRUNTIME/rgb.txt, if present. This file is basically the color
+database from X. Names used from this file are cached for efficiency.
+
+
+12. GUI Toolbar Images *haiku-toolbar-images*
+
+Alternative set of toolbar images should be the PNG image of any height you
+like. Image width is calculated to contain at least 32 buttons in one-row
+cells.
+The image should be stored under the name $VIRUNTIME/bitmaps/builtin-tools.png
+More info about the buttons assignment are at |builtin-tools|.
+
+
+13. Credits *haiku-support-credits*
+
+Haiku port is based on work done for BeOS version by many people
+ - BeBox GUI support Copyright 1998 by Olaf Seibert;
+ - Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99;
+ - Those who contributed, not listed above but not forgotten;
+ - Haiku support by Siarzhuk Zharski <imker@gmx.li> Apr-Mai 2009.
+
+Thank you, all!
+
+
+13. Bugs & things To Do *haiku-bugs*
+
+The port is under development now and far away from the perfect state. Bug
+reports, patches and wishes are welcome.
+
+
+ -Siarzhuk Zharski <imker@gmx.li>
+
+
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 8ce3c63..3ff0b9f 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -776,6 +776,7 @@ accordingly. Vim proceeds in this order:
or $VIM/_vimrc
Amiga s:.vimrc, home:.vimrc, home:vimfiles:vimrc
or $VIM/.vimrc
+ Haiku $HOME/config/settings/vim/vimrc
The files are searched in the order specified above and only the first
one that is found is read.
@@ -822,6 +823,7 @@ accordingly. Vim proceeds in this order:
"$HOME/_vimrc" (for MS-DOS and Win32) (*)
"$HOME/vimfiles/vimrc" (for MS-DOS and Win32) (*)
"$VIM/_vimrc" (for MS-DOS and Win32) (*)
+ "$HOME/config/settings/vim/vimrc" (for Haiku) (*)
Note: For Unix, OS/2 and Amiga, when ".vimrc" does not exist,
"_vimrc" is also tried, in case an MS-DOS compatible file
system is used. For MS-DOS and Win32 ".vimrc" is checked
@@ -932,6 +934,7 @@ sessions. Put it in a place so that it will be found by 3b:
~/.vimrc (Unix and OS/2)
s:.vimrc (Amiga)
$VIM\_vimrc (MS-DOS and Win32)
+ ~/config/settings/vim/vimrc (Haiku)
Note that creating a vimrc file will cause the 'compatible' option to be off
by default. See |compatible-default|.
diff --git a/runtime/doc/tags b/runtime/doc/tags
index fa1465e..e8ef3c1 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -4542,6 +4542,7 @@ GetLatestVimScripts-copyright pi_getscript.txt /*GetLatestVimScripts-copyright*
GetLatestVimScripts_dat pi_getscript.txt /*GetLatestVimScripts_dat*
Gnome gui_x11.txt /*Gnome*
H motion.txt /*H*
+Haiku os_haiku.txt /*Haiku*
I insert.txt /*I*
ICCF uganda.txt /*ICCF*
IM-server mbyte.txt /*IM-server*
@@ -6592,6 +6593,20 @@ g~ change.txt /*g~*
g~g~ change.txt /*g~g~*
g~~ change.txt /*g~~*
h motion.txt /*h*
+haiku-bugs os_haiku.txt /*haiku-bugs*
+haiku-colors os_haiku.txt /*haiku-colors*
+haiku-compiling os_haiku.txt /*haiku-compiling*
+haiku-dragndrop os_haiku.txt /*haiku-dragndrop*
+haiku-fonts os_haiku.txt /*haiku-fonts*
+haiku-general os_haiku.txt /*haiku-general*
+haiku-gui os_haiku.txt /*haiku-gui*
+haiku-launch os_haiku.txt /*haiku-launch*
+haiku-meta os_haiku.txt /*haiku-meta*
+haiku-mouse os_haiku.txt /*haiku-mouse*
+haiku-support-credits os_haiku.txt /*haiku-support-credits*
+haiku-toolbar-images os_haiku.txt /*haiku-toolbar-images*
+haiku-user-settings-dir os_haiku.txt /*haiku-user-settings-dir*
+haiku-vimdir os_haiku.txt /*haiku-vimdir*
hangul hangulin.txt /*hangul*
hangulin.txt hangulin.txt /*hangulin.txt*
has() eval.txt /*has()*
@@ -7694,6 +7709,7 @@ os_390.txt os_390.txt /*os_390.txt*
os_amiga.txt os_amiga.txt /*os_amiga.txt*
os_beos.txt os_beos.txt /*os_beos.txt*
os_dos.txt os_dos.txt /*os_dos.txt*
+os_haiku.txt os_haiku.txt /*os_haiku.txt*
os_mac.txt os_mac.txt /*os_mac.txt*
os_mint.txt os_mint.txt /*os_mint.txt*
os_msdos.txt os_msdos.txt /*os_msdos.txt*
diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt
index 9a4981f..7f3e415 100644
--- a/runtime/doc/vi_diff.txt
+++ b/runtime/doc/vi_diff.txt
@@ -140,6 +140,7 @@ Support for different systems.
- Atari MiNT
- VMS
- BeOS
+ - Haiku
- Macintosh
- Risc OS
- IBM OS/390
@@ -167,7 +168,7 @@ Graphical User Interface (GUI). |gui|
define your own menus. Better support for CTRL/SHIFT/ALT keys in
combination with special keys and mouse. Supported for various
platforms, such as X11 (with Motif and Athena interfaces), GTK, Win32
- (Windows 95 and later), BeOS, Amiga and Macintosh.
+ (Windows 95 and later), Haiku, Amiga and Macintosh.
Multiple windows and buffers. |windows.txt|
Vim can split the screen into several windows, each editing a
diff --git a/runtime/gvimrc_example.vim b/runtime/gvimrc_example.vim
index fa0f685..a7975f9 100644
--- a/runtime/gvimrc_example.vim
+++ b/runtime/gvimrc_example.vim
@@ -10,6 +10,7 @@
" for Amiga: s:.gvimrc
" for MS-DOS and Win32: $VIM\_gvimrc
" for OpenVMS: sys$login:.gvimrc
+" for Haiku OS: ~/config/settings/vim/gvimrc
" Make external commands work through a pipe instead of a pseudo-tty
"set noguipty
diff --git a/runtime/lang/menu_pl.utf-8.vim b/runtime/lang/menu_pl.utf-8.vim
new file mode 100644
index 0000000..a746df2
--- /dev/null
+++ b/runtime/lang/menu_pl.utf-8.vim
@@ -0,0 +1,3 @@
+" Menu Translations: Polish
+
+source <sfile>:p:h/menu_pl_pl.utf-8.vim
diff --git a/runtime/vimrc_example.vim b/runtime/vimrc_example.vim
index 7f5bae0..77d3a0a 100644
--- a/runtime/vimrc_example.vim
+++ b/runtime/vimrc_example.vim
@@ -8,6 +8,7 @@
" for Amiga: s:.vimrc
" for MS-DOS and Win32: $VIM\_vimrc
" for OpenVMS: sys$login:.vimrc
+" for Haiku OS: ~/config/settings/vim/vimrc
" When started as "evim", evim.vim will already have done these settings.
if v:progname =~? "evim"
diff --git a/src/Makefile b/src/Makefile
index fd07946..84c64fa 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1360,6 +1360,23 @@ CARBONGUI_BUNDLE = gui_bundle
APPDIR = $(VIMNAME).app
CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET)
+### Haiku GUI
+HAIKUGUI_SRC = gui.c gui_haiku.cc pty.c
+HAIKUGUI_OBJ = objects/gui.o objects/gui_haiku.o objects/pty.o
+HAIKUGUI_DEFS = -DFEAT_GUI_HAIKU
+HAIKUGUI_IPATH =
+HAIKUGUI_LIBS_DIR =
+HAIKUGUI_LIBS1 = -lbe -lroot -ltracker -ltranslation
+ifeq ($(strip $(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))), 4)
+HAIKUGUI_LIBS1 += -lsupc++
+endif
+HAIKUGUI_LIBS2 =
+HAIKUGUI_INSTALL = install_normal install_haiku_extra
+HAIKUGUI_TARGETS = installglinks_haiku
+HAIKUGUI_MAN_TARGETS =
+HAIKUGUI_TESTTARGET = gui
+HAIKUGUI_BUNDLE =
+
# All GUI files
ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c
ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w32.pro gui_photon.pro
@@ -2945,6 +2962,9 @@ objects/gui_gtk_gresources.o: auto/gui_gtk_gresources.c
objects/gui_gtk_x11.o: gui_gtk_x11.c
$(CCC) -o $@ gui_gtk_x11.c
+objects/gui_haiku.o: gui_haiku.cc
+ $(CCC) -o $@ gui_haiku.cc
+
objects/gui_motif.o: gui_motif.c
$(CCC) -o $@ gui_motif.c
@@ -3064,6 +3084,9 @@ objects/option.o: option.c
objects/os_beos.o: os_beos.c
$(CCC) -o $@ os_beos.c
+objects/os_haiku.rsrc: os_haiku.rdef
+ cat $< | $(CCC) -E - | grep -v '^#' | rc -o "$@" -
+
objects/os_qnx.o: os_qnx.c
$(CCC) -o $@ os_qnx.c
@@ -3232,6 +3255,63 @@ $(APPDIR)/Contents:
###############################################################################
+###
+### Haiku installation
+###
+### This rule:
+### - add resources to already installed vim binary to avoid stripping
+### them during install;
+### - copy rgb.txt to runtime directory;
+### - update system MIME database with info about vim application.
+###
+install_haiku_extra: $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc
+ xres -o $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc
+ $(INSTALL_DATA) $(SCRIPTSOURCE)/rgb.txt $(DEST_RT)
+ mimeset $(DEST_BIN)/$(VIMTARGET)
+
+###
+### List of g*-links that should be replaced with shell script equivalents.
+### This solves the problem of them from Tracker.
+###
+HAIKU_GLINKS = $(DEST_BIN)/$(GVIMTARGET) \
+ $(DEST_BIN)/$(GVIEWTARGET) \
+ $(DEST_BIN)/$(GVIMDIFFTARGET) \
+ $(DEST_BIN)/$(RGVIMTARGET) \
+ $(DEST_BIN)/$(RGVIEWTARGET)
+###
+### This rule:
+### - Replace gvim link with copy of vim binary.
+### - Replace g*-links with shell script equivalents to solve the problem
+### of calling them from Tracker,
+### - Add icon resources to mentioned g*-link shell scripts
+### - in case gui-less vim.con executable available use it.
+###
+installglinks_haiku: $(HAIKU_GLINKS) install_haiku_extra
+ @catattr -r "BEOS:ICON" $(DEST_BIN)/$(GVIMTARGET) > ~icon.attr
+ for i in $(HAIKU_GLINKS); do \
+ rm $$i ; \
+ echo "#!/bin/sh" > $$i ; \
+ case $$i in \
+ $(DEST_BIN)/$(GVIMTARGET)) \
+ cp $(DEST_BIN)/$(VIMTARGET) $$i ; \
+ if [ -f $(VIMTARGET).con ] ; then \
+ $(STRIP) $(VIMTARGET).con ; \
+ mv $(VIMTARGET).con $(DEST_BIN)/$(VIMTARGET) ; \
+ fi ;; \
+ $(DEST_BIN)/$(GVIEWTARGET)) printf "%s -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+ $(DEST_BIN)/$(GVIMDIFFTARGET)) printf "%s -d %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+ $(DEST_BIN)/$(RGVIMTARGET)) printf "%s -Z %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+ $(DEST_BIN)/$(RGVIEWTARGET)) printf "%s -Z -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+ *) printf "%s %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
+ esac ; \
+ chmod $(BINMOD) $$i ; \
+ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $$i ; \
+ done
+ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $(DEST_BIN)/$(VIMNAME)tutor
+ @rm ~icon.attr
+
+###############################################################################
+
### (automatically generated by 'make depend')
### Dependencies:
objects/arabic.o: arabic.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
diff --git a/src/configure.in b/src/configure.in
index 43bf9ad..491073d 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -114,6 +114,12 @@ case `uname` in
*) BEOS=no; AC_MSG_RESULT(no);;
esac
+AC_MSG_CHECKING(for Haiku)
+case `uname` in
+ Haiku) HAIKU=yes; AC_MSG_RESULT(yes);;
+ *) HAIKU=no; AC_MSG_RESULT(no);;
+esac
+
dnl If QNX is found, assume we don't want to use Xphoton
dnl unless it was specifically asked for (--with-x)
AC_MSG_CHECKING(for QNX)
@@ -1979,7 +1985,11 @@ fi
if test "$enable_channel" = "yes"; then
dnl On Solaris we need the socket and nsl library.
- AC_CHECK_LIB(socket, socket)
+ if test "x$HAIKU" = "xyes"; then
+ AC_CHECK_LIB(network, socket)
+ else
+ AC_CHECK_LIB(socket, socket)
+ fi
AC_CHECK_LIB(nsl, gethostbyname)
AC_MSG_CHECKING(whether compiling with process communication is possible)
AC_TRY_LINK([
@@ -2184,11 +2194,11 @@ else
fi
fi
-test "x$with_x" = xno -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
+test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
AC_MSG_CHECKING(--enable-gui argument)
AC_ARG_ENABLE(gui,
- [ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto")
+ [ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/haiku/photon/carbon]], , enable_gui="auto")
dnl Canonicalize the --enable-gui= argument so that it can be easily compared.
dnl Do not use character classes for portability with old tools.
@@ -2203,10 +2213,23 @@ SKIP_MOTIF=YES
SKIP_ATHENA=YES
SKIP_NEXTAW=YES
SKIP_PHOTON=YES
+SKIP_HAIKU=YES
SKIP_CARBON=YES
GUITYPE=NONE
-if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
+if test "x$HAIKU" = "xyes"; then
+ SKIP_HAIKU=
+ case "$enable_gui_canon" in
+ no) AC_MSG_RESULT(no GUI support)
+ SKIP_HAIKU=YES ;;
+ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;;
+ auto) AC_MSG_RESULT(auto - automatic GUI support) ;;
+ haiku) AC_MSG_RESULT(Haiku GUI support) ;;
+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
+ SKIP_HAIKU=YES ;;
+ esac
+
+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
SKIP_PHOTON=
case "$enable_gui_canon" in
no) AC_MSG_RESULT(no GUI support)
@@ -2370,6 +2393,7 @@ if test "x$MACOSX" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then
SKIP_ATHENA=YES;
SKIP_NEXTAW=YES;
SKIP_PHOTON=YES;
+ SKIP_HAIKU=YES;
SKIP_CARBON=YES
fi
@@ -2990,6 +3014,11 @@ if test "x$GUITYPE:$enable_fontset" = "xGTK:yes"; then
enable_fontset="no"
fi
+dnl There is no test for the Haiku GUI, if it's selected it's used
+if test -z "$SKIP_HAIKU"; then
+ GUITYPE=HAIKUGUI
+fi
+
if test -z "$SKIP_PHOTON"; then
GUITYPE=PHOTONGUI
fi
diff --git a/src/evalfunc.c b/src/evalfunc.c
index f643329..cdb2fe9 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5446,6 +5446,9 @@ f_has(typval_T *argvars, typval_T *rettv)
#ifdef __BEOS__
"beos",
#endif
+#ifdef __HAIKU__
+ "haiku",
+#endif
#ifdef MACOS
"mac",
#endif
@@ -5623,6 +5626,9 @@ f_has(typval_T *argvars, typval_T *rettv)
#ifdef FEAT_GUI_GNOME
"gui_gnome",
#endif
+#ifdef FEAT_GUI_HAIKU
+ "gui_haiku",
+#endif
#ifdef FEAT_GUI_MAC
"gui_mac",
#endif
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index cb58f24..2edbc63 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -14,6 +14,9 @@
#include "vim.h"
#include "version.h"
+#include <sys/stat.h>
+#include <string.h>
+
#ifdef FEAT_FLOAT
# include <float.h>
#endif
@@ -1839,6 +1842,8 @@ write_viminfo(char_u *file, int forceit)
int hidden = FALSE;
#endif
+char* filenameSeparatorPos;
+
if (no_viminfo())
return;
@@ -1846,6 +1851,19 @@ write_viminfo(char_u *file, int forceit)
if (fname == NULL)
return;
+ /* Ensure that configuration folder(for viminfo) exist */
+ filenameSeparatorPos = strrchr(fname, '/');
+ if(filenameSeparatorPos != NULL &&
+ filenameSeparatorPos - (char*)fname > 1) {
+ // > 1 because root directory always exists anyway
+ *filenameSeparatorPos = '\0';
+ //<fname, filenameSparatorPos) is directory path
+ mkdir(fname, S_IRWXU);
+
+ *filenameSeparatorPos = '/';
+ //restore original filename
+ }
+
fp_in = mch_fopen((char *)fname, READBIN);
if (fp_in == NULL)
{
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 6802b8b..abd310c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7747,6 +7747,7 @@ ex_shell(exarg_T *eap UNUSED)
|| (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \
|| defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MAC) \
+ || defined(FEAT_GUI_HAIKU) \
|| defined(PROTO)
/*
diff --git a/src/feature.h b/src/feature.h
index 138279e..b211727 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -637,6 +637,14 @@
/* #define FEAT_MBYTE_IME */
# endif
+/*
+ * +multi_byte_ime Haiku input method support.
+ * Requires +multi_byte.
+ */
+#if defined(FEAT_BIG) && defined(FEAT_GUI_HAIKU) && !defined(FEAT_MBYTE_IME)
+ #define FEAT_MBYTE_IME
+# endif
+
#if defined(FEAT_MBYTE_IME) && !defined(FEAT_MBYTE)
# define FEAT_MBYTE
#endif
@@ -742,7 +750,8 @@
|| defined(FEAT_GUI_MSWIN) \
|| ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \
&& defined(HAVE_XPM)) \
- || defined(FEAT_GUI_PHOTON))
+ || defined(FEAT_GUI_PHOTON)\
+ || defined(FEAT_GUI_HAIKU))
# define FEAT_TOOLBAR
#endif
@@ -758,6 +767,7 @@
&& (defined(FEAT_GUI_GTK) \
|| (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \
|| defined(FEAT_GUI_MAC) \
+ || defined(FEAT_GUI_HAIKU) \
|| (defined(FEAT_GUI_MSWIN) \
&& (!defined(_MSC_VER) || _MSC_VER > 1020)))
# define FEAT_GUI_TABLINE
@@ -769,7 +779,8 @@
*/
#if defined(FEAT_NORMAL)
# define FEAT_BROWSE_CMD
-# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
+ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
# define FEAT_BROWSE
# endif
#endif
@@ -793,6 +804,7 @@
&& defined(HAVE_X11_XPM_H)) \
|| defined(FEAT_GUI_GTK) \
|| defined(FEAT_GUI_PHOTON) \
+ || defined(FEAT_GUI_HAIKU) \
|| defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MAC)
# define FEAT_CON_DIALOG
@@ -810,7 +822,8 @@
#if defined(FEAT_GUI_DIALOG) && \
(defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \
- || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))\
+ || defined(FEAT_GUI_HAIKU)
# define FEAT_GUI_TEXTDIALOG
# ifndef ALWAYS_USE_GUI
# define FEAT_CON_DIALOG
diff --git a/src/gui.c b/src/gui.c
index 87b0839..bfeaa25 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -424,7 +424,7 @@ gui_init_check(void)
gui.menu_width = 0;
# endif
#endif
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU))
gui.toolbar_height = 0;
#endif
#if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF)
@@ -1338,10 +1338,10 @@ gui_position_components(int total_width UNUSED)
text_area_y += gui.tabline_height;
#endif
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU))
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
{
-# ifdef FEAT_GUI_ATHENA
+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
gui_mch_set_toolbar_pos(0, text_area_y,
gui.menu_width, gui.toolbar_height);
# endif
@@ -1349,6 +1349,13 @@ gui_position_components(int total_width UNUSED)
}
#endif
+# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_HAIKU))
+ gui_mch_set_tabline_pos(0, text_area_y,
+ gui.menu_width, gui.tabline_height);
+ if (gui_has_tabline())
+ text_area_y += gui.tabline_height;
+#endif
+
text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2;
text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2;
@@ -1420,7 +1427,7 @@ gui_get_base_height(void)
# endif
# endif
# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
- || defined(FEAT_GUI_MOTIF))
+ || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
if (gui_has_tabline())
base_height += gui.tabline_height;
# endif
@@ -1461,6 +1468,10 @@ gui_resize_shell(int pixel_width, int pixel_height)
again:
busy = TRUE;
+#ifdef FEAT_GUI_HAIKU
+ vim_lock_screen();
+#endif
+
/* Flush pending output before redrawing */
out_flush();
@@ -1483,6 +1494,10 @@ again:
|| gui.num_rows != Rows || gui.num_cols != Columns)
shell_resized();
+#ifdef FEAT_GUI_HAIKU
+ vim_unlock_screen();
+#endif
+
gui_update_scrollbars(TRUE);
gui_update_cursor(FALSE, TRUE);
#if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK)
@@ -4248,9 +4263,9 @@ gui_update_scrollbars(
y += gui.menu_height;
#endif
-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA))
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU))
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
-# ifdef FEAT_GUI_ATHENA
+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
y += gui.toolbar_height;
# else
# ifdef FEAT_GUI_MSWIN
@@ -4259,7 +4274,7 @@ gui_update_scrollbars(
# endif
#endif
-#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN)
+#if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU))
if (gui_has_tabline())
y += gui.tabline_height;
#endif
@@ -4988,9 +5003,10 @@ ex_gui(exarg_T *eap)
}
#if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) \
- || defined(FEAT_GUI_PHOTON)) && defined(FEAT_TOOLBAR)) || defined(PROTO)
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_HAIKU)) \
+ && defined(FEAT_TOOLBAR)) || defined(PROTO)
/*
- * This is shared between Athena, Motif and GTK.
+ * This is shared between Athena, Haiku, Motif and GTK.
*/
static void gfp_setname(char_u *fname, void *cookie);
diff --git a/src/gui.h b/src/gui.h
index 4769716..8a321e4 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -33,6 +33,10 @@
# include <gtk/gtk.h>
#endif
+#ifdef FEAT_GUI_HAIKU
+# include "gui_haiku.h"
+#endif
+
#ifdef FEAT_GUI_MAC
# include <Types.h>
/*# include <Memory.h>*/
@@ -70,7 +74,7 @@
* GUIs that support dropping files on a running Vim.
*/
#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) \
- || defined(FEAT_GUI_GTK)
+ || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_GTK)
# define HAVE_DROP_FILE
#endif
@@ -198,6 +202,9 @@ typedef struct GuiScrollbar
scroll_shift is set to the number of shifts
to reduce the count. */
#endif
+#if FEAT_GUI_HAIKU
+ VimScrollBar *id; /* Pointer to real scroll bar */
+#endif
#ifdef FEAT_GUI_MAC
ControlHandle id; /* A handle to the scrollbar */
#endif
@@ -411,7 +418,7 @@ typedef struct Gui
#if defined(FEAT_GUI_TABLINE) \
&& (defined(FEAT_GUI_W32) || defined(FEAT_GUI_MOTIF) \
- || defined(FEAT_GUI_MAC))
+ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_HAIKU))
int tabline_height;
#endif
@@ -420,7 +427,7 @@ typedef struct Gui
#endif
#if defined(FEAT_TOOLBAR) \
- && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
+ && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
int toolbar_height; /* height of the toolbar */
#endif
@@ -441,6 +448,14 @@ typedef struct Gui
guicolor_T currSpColor; /* Current special text color */
#endif
+#ifdef FEAT_GUI_HAIKU
+ VimApp *vimApp;
+ VimWindow *vimWindow;
+ VimFormView *vimForm;
+ VimTextAreaView *vimTextArea;
+ int vdcmp; /* Vim Direct Communication Message Port */
+#endif
+
#ifdef FEAT_GUI_MAC
WindowPtr VimWindow;
MenuHandle MacOSHelpMenu; /* Help menu provided by the MacOS */
diff --git a/src/gui_haiku.cc b/src/gui_haiku.cc
new file mode 100644
index 0000000..3a4fae5
--- /dev/null
+++ b/src/gui_haiku.cc
@@ -0,0 +1,5294 @@
+/* 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 "globals.h"
+#include "proto.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 */
+#ifdef FEAT_MBYTE
+ bool csi_escape;
+#endif
+};
+
+struct VimResizeMsg {
+ int width;
+ int height;
+};
+
+struct VimScrollBarMsg {
+ VimScrollBar *sb;
+ long value;
+ int stillDragging;
+};
+
+struct VimMenuMsg {
+ vimmenu_T *guiMenu;
+};
+
+struct VimMouseMsg {
+ int button;
+ int x;
+ int y;
+ int repeated_click;
+ int_u modifiers;
+};
+
+struct VimMouseMovedMsg {
+ int x;
+ int y;
+};
+
+struct VimFocusMsg {
+ bool active;
+};
+
+struct VimRefsMsg {
+ BMessage *message;
+ bool changedir;
+};
+
+struct VimTablineMsg {
+ int index;
+};
+
+struct VimTablineMenuMsg {
+ int index;
+ int event;
+};
+
+struct VimMsg {
+ enum VimMsgType {
+ Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu
+ };
+
+ union {
+ struct VimKeyMsg Key;
+ struct VimResizeMsg NewSize;
+ struct VimScrollBarMsg Scroll;
+ struct VimMenuMsg Menu;
+ struct VimMouseMsg Mouse;
+ struct VimMouseMovedMsg MouseMoved;
+ struct VimFocusMsg Focus;
+ struct VimRefsMsg Refs;
+ struct VimTablineMsg Tabline;
+ struct VimTablineMenuMsg TablineMenu;
+ } u;
+};
+
+#define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0)
+#define GUI_TO_RGB(g) { (g) >> 16, (g) >> 8, (g) >> 0, 255 }
+
+/* ---------------- end of header part ---------------- */
+
+static struct specialkey
+{
+ uint16 BeKeys;
+#define KEY(a,b) ((a)<<8|(b))
+#define K(a) KEY(0,a) // for ASCII codes
+#define F(b) KEY(1,b) // for scancodes
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {K(B_UP_ARROW), 'k', 'u'},
+ {K(B_DOWN_ARROW), 'k', 'd'},
+ {K(B_LEFT_ARROW), 'k', 'l'},
+ {K(B_RIGHT_ARROW), 'k', 'r'},
+ {K(B_BACKSPACE), 'k', 'b'},
+ {K(B_INSERT), 'k', 'I'},
+ {K(B_DELETE), 'k', 'D'},
+ {K(B_HOME), 'k', 'h'},
+ {K(B_END), '@', '7'},
+ {K(B_PAGE_UP), 'k', 'P'}, /* XK_Prior */
+ {K(B_PAGE_DOWN), 'k', 'N'}, /* XK_Next, */
+
+#define FIRST_FUNCTION_KEY 11
+ {F(B_F1_KEY), 'k', '1'},
+ {F(B_F2_KEY), 'k', '2'},
+ {F(B_F3_KEY), 'k', '3'},
+ {F(B_F4_KEY), 'k', '4'},
+ {F(B_F5_KEY), 'k', '5'},
+ {F(B_F6_KEY), 'k', '6'},
+ {F(B_F7_KEY), 'k', '7'},
+ {F(B_F8_KEY), 'k', '8'},
+ {F(B_F9_KEY), 'k', '9'},
+ {F(B_F10_KEY), 'k', ';'},
+
+ {F(B_F11_KEY), 'F', '1'},
+ {F(B_F12_KEY), 'F', '2'},
+ // {XK_F13, 'F', '3'}, /* would be print screen/ */
+ /* sysreq */
+ {F(0x0F), 'F', '4'}, /* scroll lock */
+ {F(0x10), 'F', '5'}, /* pause/break */
+ // {XK_F16, 'F', '6'},
+ // {XK_F17, 'F', '7'},
+ // {XK_F18, 'F', '8'},
+ // {XK_F19, 'F', '9'},
+ // {XK_F20, 'F', 'A'},
+ //
+ // {XK_F21, 'F', 'B'},
+ // {XK_F22, 'F', 'C'},
+ // {XK_F23, 'F', 'D'},
+ // {XK_F24, 'F', 'E'},
+ // {XK_F25, 'F', 'F'},
+ // {XK_F26, 'F', 'G'},
+ // {XK_F27, 'F', 'H'},
+ // {XK_F28, 'F', 'I'},
+ // {XK_F29, 'F', 'J'},
+ // {XK_F30, 'F', 'K'},
+ //
+ // {XK_F31, 'F', 'L'},
+ // {XK_F32, 'F', 'M'},
+ // {XK_F33, 'F', 'N'},
+ // {XK_F34, 'F', 'O'},
+ // {XK_F35, 'F', 'P'}, /* keysymdef.h defines up to F35 */
+
+ // {XK_Help, '%', '1'}, /* XK_Help */
+ {F(B_PRINT_KEY), '%', '9'},
+
+#if 0
+ /* Keypad keys: */
+ {F(0x48), 'k', 'l'}, /* XK_KP_Left */
+ {F(0x4A), 'k', 'r'}, /* XK_KP_Right */
+ {F(0x38), 'k', 'u'}, /* XK_KP_Up */
+ {F(0x59), 'k', 'd'}, /* XK_KP_Down */
+ {F(0x64), 'k', 'I'}, /* XK_KP_Insert */
+ {F(0x65), 'k', 'D'}, /* XK_KP_Delete */
+ {F(0x37), 'k', 'h'}, /* XK_KP_Home */
+ {F(0x58), '@', '7'}, /* XK_KP_End */
+ {F(0x39), 'k', 'P'}, /* XK_KP_Prior */
+ {F(0x60), 'k', 'N'}, /* XK_KP_Next */
+ {F(0x49), '&', '8'}, /* XK_Undo, keypad 5 */
+#endif
+
+ /* End of list marker: */
+ {0, 0, 0}
+};
+
+#define NUM_SPECIAL_KEYS (sizeof(special_keys)/sizeof(special_keys[0]))
+
+/* ---------------- VimApp ---------------- */
+
+ static void
+docd(BPath &path)
+{
+ mch_chdir((char *)path.Path());
+ /* Do this to get the side effects of a :cd command */
+ do_cmdline_cmd((char_u *)"cd .");
+}
+
+/*
+ * Really handle dropped files and folders.
+ */
+ static void
+RefsReceived(BMessage *m, bool changedir)
+{
+ uint32 type;
+ int32 count;
+
+ m->PrintToStream();
+ switch (m->what) {
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ m->GetInfo("refs", &type, &count);
+ if (type != B_REF_TYPE)
+ goto bad;
+ break;
+ case B_ARGV_RECEIVED:
+ m->GetInfo("argv", &type, &count);
+ if (type != B_STRING_TYPE)
+ goto bad;
+ if (changedir) {
+ char *dirname;
+ if (m->FindString("cwd", (const char **) &dirname) == B_OK) {
+ chdir(dirname);
+ do_cmdline_cmd((char_u *)"cd .");
+ }
+ }
+ break;
+ default:
+bad:
+ //fprintf(stderr, "bad!\n");
+ delete m;
+ return;
+ }
+
+#ifdef FEAT_VISUAL
+ reset_VIsual();
+#endif
+
+ char_u **fnames;
+ fnames = (char_u **) alloc(count * sizeof(char_u *));
+ int fname_index = 0;
+
+ switch (m->what) {
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ //fprintf(stderr, "case B_REFS_RECEIVED\n");
+ for (int i = 0; i < count; ++i)
+ {
+ entry_ref ref;
+ if (m->FindRef("refs", i, &ref) == B_OK) {
+ BEntry entry(&ref, false);
+ BPath path;
+ entry.GetPath(&path);
+
+ /* Change to parent directory? */
+ if (changedir) {
+ BPath parentpath;
+ path.GetParent(&parentpath);
+ docd(parentpath);
+ }
+
+ /* Is it a directory? If so, cd into it. */
+ BDirectory bdir(&ref);
+ if (bdir.InitCheck() == B_OK) {
+ /* don't cd if we already did it */
+ if (!changedir)
+ docd(path);
+ } else {
+ mch_dirname(IObuff, IOSIZE);
+ char_u *fname = shorten_fname((char_u *)path.Path(), IObuff);
+ if (fname == NULL)
+ fname = (char_u *)path.Path();
+ fnames[fname_index++] = vim_strsave(fname);
+ //fprintf(stderr, "%s\n", fname);
+ }
+
+ /* Only do it for the first file/dir */
+ changedir = false;
+ }
+ }
+ break;
+ case B_ARGV_RECEIVED:
+ //fprintf(stderr, "case B_ARGV_RECEIVED\n");
+ for (int i = 1; i < count; ++i)
+ {
+ char *fname;
+
+ if (m->FindString("argv", i, (const char **) &fname) == B_OK) {
+ fnames[fname_index++] = vim_strsave((char_u *)fname);
+ }
+ }
+ break;
+ default:
+ //fprintf(stderr, "case default\n");
+ break;
+ }
+
+ delete m;
+
+ /* Handle the drop, :edit to get to the file */
+ if (fname_index > 0) {
+ handle_drop(fname_index, fnames, FALSE);
+
+ /* Update the screen display */
+ update_screen(NOT_VALID);
+ setcursor();
+ out_flush();
+ } else {
+ vim_free(fnames);
+ }
+}
+
+VimApp::VimApp(const char *appsig):
+ BApplication(appsig),
+ fFilePanelSem(-1),
+ fFilePanel(NULL)
+{
+}
+
+VimApp::~VimApp()
+{
+}
+
+ void
+VimApp::ReadyToRun()
+{
+ /*
+ * Apparently signals are inherited by the created thread -
+ * disable the most annoying ones.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+}
+
+ void
+VimApp::ArgvReceived(int32 arg_argc, char **arg_argv)
+{
+ if (!IsLaunching()) {
+ /*
+ * This can happen if we are set to Single or Exclusive
+ * Launch. Be nice and open the file(s).
+ */
+ if (gui.vimWindow)
+ gui.vimWindow->Minimize(false);
+ BMessage *m = CurrentMessage();
+ DetachCurrentMessage();
+ SendRefs(m, true);
+ }
+}
+
+ void
+VimApp::RefsReceived(BMessage *m)
+{
+ /* Horrible hack!!! XXX XXX XXX
+ * The real problem is that b_start_ffc is set too late for
+ * the initial empty buffer. As a result the window will be
+ * split instead of abandoned.
+ */
+ int limit = 15;
+ while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0))
+ snooze(100000); // 0.1 s
+ if (gui.vimWindow)
+ gui.vimWindow->Minimize(false);
+ DetachCurrentMessage();
+ SendRefs(m, true);
+}
+
+/*
+ * Pass a BMessage on to the main() thread.
+ * Caller must have detached the message.
+ */
+ void
+VimApp::SendRefs(BMessage *m, bool changedir)
+{
+ VimRefsMsg rm;
+ rm.message = m;
+ rm.changedir = changedir;
+
+ write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm));
+ // calls ::RefsReceived
+}
+
+ void
+VimApp::MessageReceived(BMessage *m)
+{
+ switch (m->what) {
+ case 'save':
+ {
+ entry_ref refDirectory;
+ m->FindRef("directory", &refDirectory);
+ fBrowsedPath.SetTo(&refDirectory);
+ BString strName;
+ m->FindString("name", &strName);
+ fBrowsedPath.Append(strName.String());
+ }
+ break;
+ case 'open':
+ {
+ entry_ref ref;
+ m->FindRef("refs", &ref);
+ fBrowsedPath.SetTo(&ref);
+ }
+ break;
+ case B_CANCEL:
+ {
+ BFilePanel *panel;
+ m->FindPointer("source", (void**)&panel);
+ if(fFilePanelSem != -1 && panel == fFilePanel)
+ {
+ delete_sem(fFilePanelSem);
+ fFilePanelSem = -1;
+ }
+
+ }
+ break;
+ default:
+ Inherited::MessageReceived(m);
+ break;
+ }
+}
+
+ bool
+VimApp::QuitRequested()
+{
+ (void)Inherited::QuitRequested();
+ return false;
+}
+
+/* ---------------- VimWindow ---------------- */
+
+VimWindow::VimWindow():
+ BWindow(BRect(40, 40, 150, 150),
+ "Vim",
+ B_TITLED_WINDOW,
+ 0,
+ B_CURRENT_WORKSPACE)
+
+{
+ init();
+}
+
+VimWindow::~VimWindow()
+{
+ if (formView) {
+ RemoveChild(formView);
+ delete formView;
+ }
+ gui.vimWindow = NULL;
+}
+
+ void
+VimWindow::init()
+{
+ /* Attach the VimFormView */
+ formView = new VimFormView(Bounds());
+ if (formView != NULL) {
+ AddChild(formView);
+ }
+}
+
+#if 0 // disabled in zeta patch
+ void
+VimWindow::DispatchMessage(BMessage *m, BHandler *h)
+{
+ /*
+ * Route B_MOUSE_UP messages to MouseUp(), in
+ * a manner that should be compatible with the
+ * intended future system behaviour.
+ */
+ switch (m->what) {
+ case B_MOUSE_UP:
+ // if (!h) h = PreferredHandler();
+ // gcc isn't happy without this extra set of braces, complains about
+ // jump to case label crosses init of 'class BView * v'
+ // richard@whitequeen.com jul 99
+ {
+ BView *v = dynamic_cast<BView *>(h);
+ if (v) {
+ //m->PrintToStream();
+ BPoint where;
+ m->FindPoint("where", &where);
+ v->MouseUp(where);
+ } else {
+ Inherited::DispatchMessage(m, h);
+ }
+ }
+ break;
+ default:
+ Inherited::DispatchMessage(m, h);
+ }
+}
+#endif
+
+ void
+VimWindow::WindowActivated(bool active)
+{
+ Inherited::WindowActivated(active);
+ /* the textArea gets the keyboard action */
+ if (active && gui.vimTextArea)
+ gui.vimTextArea->MakeFocus(true);
+
+ struct VimFocusMsg fm;
+ fm.active = active;
+
+ write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm));
+}
+
+ bool
+VimWindow::QuitRequested()
+{
+ struct VimKeyMsg km;
+ km.length = 5;
+ memcpy((char *)km.chars, "\033:qa\r", km.length);
+
+#ifdef FEAT_MBYTE
+ km.csi_escape = false;
+#endif
+
+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+ return false;
+}
+
+/* ---------------- VimFormView ---------------- */
+
+VimFormView::VimFormView(BRect frame):
+ BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES,
+ B_WILL_DRAW | B_FRAME_EVENTS),
+ menuBar(NULL),
+#ifdef FEAT_TOOLBAR
+ toolBar(NULL),
+#endif
+#ifdef FEAT_GUI_TABLINE
+// showingTabLine(false),
+ tabLine(NULL),
+#endif
+ textArea(NULL)
+{
+ init(frame);
+}
+
+VimFormView::~VimFormView()
+{
+ if (menuBar) {
+ RemoveChild(menuBar);
+#ifdef never
+ // deleting the menuBar leads to SEGV on exit
+ // richard@whitequeen.com Jul 99
+ delete menuBar;
+#endif
+ }
+
+#ifdef FEAT_TOOLBAR
+ delete toolBar;
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+ delete tabLine;
+#endif
+
+ if (textArea) {
+ RemoveChild(textArea);
+ delete textArea;
+ }
+ gui.vimForm = NULL;
+}
+
+ void
+VimFormView::init(BRect frame)
+{
+ menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN),
+ "VimMenuBar");
+
+ AddChild(menuBar);
+
+#ifdef FEAT_TOOLBAR
+ toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar");
+ toolBar->PrepareButtonBitmaps();
+ AddChild(toolBar);
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+ tabLine = new VimTabLine(BRect(0,0,0,0));
+// tabLine->PrepareButtonBitmaps();
+ AddChild(tabLine);
+#endif
+
+ BRect remaining = frame;
+ textArea = new VimTextAreaView(remaining);
+ AddChild(textArea);
+ /* The textArea will be resized later when menus are added */
+
+ gui.vimForm = this;
+}
+
+#ifdef FEAT_TOOLBAR
+ float
+VimFormView::ToolbarHeight() const
+{
+ return toolBar ? toolBar->ToolbarHeight() : 0.;
+}
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+ float
+VimFormView::TablineHeight() const
+{
+ return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.;
+}
+#endif
+
+ void
+VimFormView::AllAttached()
+{
+ /*
+ * Apparently signals are inherited by the created thread -
+ * disable the most annoying ones.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ if (menuBar && textArea) {
+ /*
+ * Resize the textArea to fill the space left over by the menu.
+ * This is somewhat futile since it will be done again once
+ * menus are added to the menu bar.
+ */
+ BRect remaining = Bounds();
+
+#ifdef FEAT_MENU
+ remaining.top += MenuHeight();
+ menuBar->ResizeTo(remaining.right, remaining.top);
+ gui.menu_height = (int) MenuHeight();
+#endif
+
+#ifdef FEAT_TOOLBAR
+ toolBar->MoveTo(remaining.left, remaining.top);
+ toolBar->ResizeTo(remaining.right, ToolbarHeight());
+ remaining.top += ToolbarHeight();
+ gui.toolbar_height = ToolbarHeight();
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+ tabLine->MoveTo(remaining.left, remaining.top);
+ tabLine->ResizeTo(remaining.right + 1, TablineHeight());
+ remaining.top += TablineHeight();
+ gui.tabline_height = TablineHeight();
+#endif
+
+ textArea->ResizeTo(remaining.Width(), remaining.Height());
+ textArea->MoveTo(remaining.left, remaining.top);
+ }
+
+
+ Inherited::AllAttached();
+}
+
+ void
+VimFormView::FrameResized(float new_width, float new_height)
+{
+ struct VimResizeMsg sm;
+ int adjust_h, adjust_w;
+
+ new_width += 1; // adjust from width to number of pixels occupied
+ new_height += 1;
+
+ sm.width = (int) new_width;
+ sm.height = (int) new_height;
+ adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width;
+ adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height;
+
+ if (adjust_w > 0 || adjust_h > 0) {
+ sm.width -= adjust_w;
+ sm.height -= adjust_h;
+ }
+
+ write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm));
+ // calls gui_resize_shell(new_width, new_height);
+
+ return;
+
+ /*
+ * The area below the vertical scrollbar is erased to the colour
+ * set with SetViewColor() automatically, because we had set
+ * B_WILL_DRAW. Resizing the window tight around the vertical
+ * scroll bar also helps to avoid debris.
+ */
+}
+
+/* ---------------- VimTextAreaView ---------------- */
+
+VimTextAreaView::VimTextAreaView(BRect frame):
+ BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES,
+#ifdef FEAT_MBYTE_IME
+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INPUT_METHOD_AWARE),
+#else
+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+#endif
+ mouseDragEventCount(0)
+{
+#ifdef FEAT_MBYTE_IME
+ IMData.messenger = NULL;
+ IMData.message = NULL;
+#endif
+ init(frame);
+}
+
+VimTextAreaView::~VimTextAreaView()
+{
+ gui.vimTextArea = NULL;
+}
+
+ void
+VimTextAreaView::init(BRect frame)
+{
+ /* set up global var for fast access */
+ gui.vimTextArea = this;
+
+ /*
+ * Tell the app server not to erase the view: we will
+ * fill it in completely by ourselves.
+ * (Does this really work? Even if not, it won't harm either.)
+ */
+ SetViewColor(B_TRANSPARENT_32_BIT);
+#define PEN_WIDTH 1
+ SetPenSize(PEN_WIDTH);
+}
+
+ void
+VimTextAreaView::Draw(BRect updateRect)
+{
+ /*
+ * XXX Other ports call here:
+ * out_flush(); * make sure all output has been processed *
+ * but we can't do that, since it involves too much information
+ * that is owned by other threads...
+ */
+
+ /*
+ * No need to use gui.vimWindow->Lock(): we are locked already.
+ * However, it would not hurt.
+ */
+ rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
+ SetLowColor(rgb);
+ FillRect(updateRect, B_SOLID_LOW);
+ gui_redraw((int) updateRect.left, (int) updateRect.top,
+ (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH));
+
+ /* Clear the border areas if needed */
+ SetLowColor(rgb);
+
+ if (updateRect.left < FILL_X(0)) // left border
+ FillRect(BRect(updateRect.left, updateRect.top,
+ FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW);
+ if (updateRect.top < FILL_Y(0)) // top border
+ FillRect(BRect(updateRect.left, updateRect.top,
+ updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW);
+ if (updateRect.right >= FILL_X(Columns)) // right border
+ FillRect(BRect(FILL_X((int)Columns), updateRect.top,
+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
+ if (updateRect.bottom >= FILL_Y(Rows)) // bottom border
+ FillRect(BRect(updateRect.left, FILL_Y((int)Rows),
+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
+
+#ifdef FEAT_MBYTE_IME
+ DrawIMString();
+#endif
+}
+
+ void
+VimTextAreaView::KeyDown(const char *bytes, int32 numBytes)
+{
+ struct VimKeyMsg km;
+ char_u *dest = km.chars;
+
+ bool canHaveVimModifiers = false;
+
+ BMessage *msg = Window()->CurrentMessage();
+ assert(msg);
+ //msg->PrintToStream();
+
+ /*
+ * Convert special keys to Vim codes.
+ * I think it is better to do it in the window thread
+ * so we use at least a little bit of the potential
+ * of our 2 CPUs. Besides, due to the fantastic mapping
+ * of special keys to UTF-8, we have quite some work to
+ * do...
+ * TODO: I'm not quite happy with detection of special
+ * keys. Perhaps I should use scan codes after all...
+ */
+ if (numBytes > 1) {
+ /* This cannot be a special key */
+ if (numBytes > KEY_MSG_BUFSIZ)
+ numBytes = KEY_MSG_BUFSIZ; // should never happen... ???
+ km.length = numBytes;
+ memcpy((char *)dest, bytes, numBytes);
+#ifdef FEAT_MBYTE
+ km.csi_escape = true;
+#endif
+ } else {
+ int32 scancode = 0;
+ msg->FindInt32("key", &scancode);
+
+ int32 beModifiers = 0;
+ msg->FindInt32("modifiers", &beModifiers);
+
+ char_u string[3];
+ int len = 0;
+ km.length = 0;
+
+ /*
+ * For normal, printable ASCII characters, don't look them up
+ * to check if they might be a special key. They aren't.
+ */
+ assert(B_BACKSPACE <= 0x20);
+ assert(B_DELETE == 0x7F);
+ if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) &&
+ numBytes == 1) {
+ /*
+ * Due to the great nature of Be's mapping of special keys,
+ * viz. into the range of the control characters,
+ * we can only be sure it is *really* a special key if
+ * if it is special without using ctrl. So, only if ctrl is
+ * used, we need to check it unmodified.
+ */
+ if (beModifiers & B_CONTROL_KEY) {
+ int index = keyMap->normal_map[scancode];
+ int newNumBytes = keyMapChars[index];
+ char_u *newBytes = (char_u *)&keyMapChars[index + 1];
+
+ /*
+ * Check if still special without the control key.
+ * This is needed for BACKSPACE: that key does produce
+ * different values with modifiers (DEL).
+ * Otherwise we could simply have checked for equality.
+ */
+ if (newNumBytes != 1 || (*newBytes > 0x20 &&
+ *newBytes != 0x7F )) {
+ goto notspecial;
+ }
+ bytes = (char *)newBytes;
+ }
+ canHaveVimModifiers = true;
+
+ uint16 beoskey;
+ int first, last;
+
+ /*
+ * If numBytes == 0 that probably always indicates a special key.
+ * (does not happen yet)
+ */
+ if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) {
+ beoskey = F(scancode);
+ first = FIRST_FUNCTION_KEY;
+ last = NUM_SPECIAL_KEYS;
+ } else if (*bytes == '\n' && scancode == 0x47) {
+ /* remap the (non-keypad) ENTER key from \n to \r. */
+ string[0] = '\r';
+ len = 1;
+ first = last = 0;
+ } else {
+ beoskey = K(bytes[0]);
+ first = 0;
+ last = FIRST_FUNCTION_KEY;
+ }
+
+ for (int i = first; i < last; i++) {
+ if (special_keys[i].BeKeys == beoskey) {
+ string[0] = CSI;
+ string[1] = special_keys[i].vim_code0;
+ string[2] = special_keys[i].vim_code1;
+ len = 3;
+ }
+ }
+ }
+notspecial:
+ if (len == 0) {
+ string[0] = bytes[0];
+ len = 1;
+ }
+
+ /* Special keys (and a few others) may have modifiers */
+#if 0
+ if (len == 3 ||
+ bytes[0] == B_SPACE || bytes[0] == B_TAB ||
+ bytes[0] == B_RETURN || bytes[0] == '\r' ||
+ bytes[0] == B_ESCAPE)
+#else
+ if (canHaveVimModifiers)
+#endif
+ {
+ int modifiers;
+ modifiers = 0;
+ if (beModifiers & B_SHIFT_KEY)
+ modifiers |= MOD_MASK_SHIFT;
+ if (beModifiers & B_CONTROL_KEY)
+ modifiers |= MOD_MASK_CTRL;
+ if (beModifiers & B_OPTION_KEY)
+ modifiers |= MOD_MASK_ALT;
+
+ /*
+ * For some keys a shift modifier is translated into another key
+ * code. Do we need to handle the case where len != 1 and
+ * string[0] != CSI? (Not for BeOS, since len == 3 implies
+ * string[0] == CSI...)
+ */
+ int key;
+ if (string[0] == CSI && len == 3)
+ key = TO_SPECIAL(string[1], string[2]);
+ else
+ key = string[0];
+ key = simplify_key(key, &modifiers);
+ if (IS_SPECIAL(key))
+ {
+ string[0] = CSI;
+ string[1] = K_SECOND(key);
+ string[2] = K_THIRD(key);
+ len = 3;
+ }
+ else
+ {
+ string[0] = key;
+ len = 1;
+ }
+
+ if (modifiers)
+ {
+ *dest++ = CSI;
+ *dest++ = KS_MODIFIER;
+ *dest++ = modifiers;
+ km.length = 3;
+ }
+ }
+ memcpy((char *)dest, string, len);
+ km.length += len;
+#ifdef FEAT_MBYTE
+ km.csi_escape = false;
+#endif
+ }
+
+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+ /*
+ * blank out the pointer if necessary
+ */
+ if (p_mh && !gui.pointer_hidden)
+ {
+ guiBlankMouse(true);
+ gui.pointer_hidden = TRUE;
+ }
+}
+void
+VimTextAreaView::guiSendMouseEvent(
+ int button,
+ int x,
+ int y,
+ int repeated_click,
+ int_u modifiers)
+{
+ VimMouseMsg mm;
+
+ mm.button = button;
+ mm.x = x;
+ mm.y = y;
+ mm.repeated_click = repeated_click;
+ mm.modifiers = modifiers;
+
+ write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm));
+ // calls gui_send_mouse_event()
+
+ /*
+ * if our pointer is currently hidden, then we should show it.
+ */
+ if (gui.pointer_hidden)
+ {
+ guiBlankMouse(false);
+ gui.pointer_hidden = FALSE;
+ }
+}
+
+void
+VimTextAreaView::guiMouseMoved(
+ int x,
+ int y)
+{
+ VimMouseMovedMsg mm;
+
+ mm.x = x;
+ mm.y = y;
+
+ write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm));
+
+ if (gui.pointer_hidden)
+ {
+ guiBlankMouse(false);
+ gui.pointer_hidden = FALSE;
+ }
+}
+
+ void
+VimTextAreaView::guiBlankMouse(bool should_hide)
+{
+ if (should_hide) {
+ //gui.vimApp->HideCursor();
+ gui.vimApp->ObscureCursor();
+ /*
+ * ObscureCursor() would even be easier, but then
+ * Vim's idea of mouse visibility does not necessarily
+ * correspond to reality.
+ */
+ } else {
+ //gui.vimApp->ShowCursor();
+ }
+}
+
+ int_u
+VimTextAreaView::mouseModifiersToVim(int32 beModifiers)
+{
+ int_u vim_modifiers = 0x0;
+
+ if (beModifiers & B_SHIFT_KEY)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (beModifiers & B_CONTROL_KEY)
+ vim_modifiers |= MOUSE_CTRL;
+ if (beModifiers & B_OPTION_KEY) /* Alt or Meta key */
+ vim_modifiers |= MOUSE_ALT;
+
+ return vim_modifiers;
+}
+
+ void
+VimTextAreaView::MouseDown(BPoint point)
+{
+ BMessage *m = Window()->CurrentMessage();
+ assert(m);
+
+ int32 buttons = 0;
+ m->FindInt32("buttons", &buttons);
+
+ int vimButton;
+
+ if (buttons & B_PRIMARY_MOUSE_BUTTON)
+ vimButton = MOUSE_LEFT;
+ else if (buttons & B_SECONDARY_MOUSE_BUTTON)
+ vimButton = MOUSE_RIGHT;
+ else if (buttons & B_TERTIARY_MOUSE_BUTTON)
+ vimButton = MOUSE_MIDDLE;
+ else
+ return; /* Unknown button */
+
+ vimMouseButton = 1; /* don't care which one */
+
+ /* Handle multiple clicks */
+ int32 clicks = 0;
+ m->FindInt32("clicks", &clicks);
+
+ int32 modifiers = 0;
+ m->FindInt32("modifiers", &modifiers);
+
+ vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+ guiSendMouseEvent(vimButton, point.x, point.y,
+ clicks > 1 /* = repeated_click*/, vimMouseModifiers);
+}
+
+ void
+VimTextAreaView::MouseUp(BPoint point)
+{
+ vimMouseButton = 0;
+
+ BMessage *m = Window()->CurrentMessage();
+ assert(m);
+ //m->PrintToStream();
+
+ int32 modifiers = 0;
+ m->FindInt32("modifiers", &modifiers);
+
+ vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+ guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y,
+ 0 /* = repeated_click*/, vimMouseModifiers);
+
+ Inherited::MouseUp(point);
+}
+
+ void
+VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
+{
+ /*
+ * if our pointer is currently hidden, then we should show it.
+ */
+ if (gui.pointer_hidden)
+ {
+ guiBlankMouse(false);
+ gui.pointer_hidden = FALSE;
+ }
+
+ if (!vimMouseButton) { /* could also check m->"buttons" */
+ guiMouseMoved(point.x, point.y);
+ return;
+ }
+
+ atomic_add(&mouseDragEventCount, 1);
+
+ /* Don't care much about "transit" */
+ guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers);
+}
+
+ void
+VimTextAreaView::MessageReceived(BMessage *m)
+{
+ switch (m->what) {
+ case 'menu':
+ {
+ VimMenuMsg mm;
+ mm.guiMenu = NULL; /* in case no pointer in msg */
+ m->FindPointer("VimMenu", (void **)&mm.guiMenu);
+ write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm));
+ }
+ break;
+ case B_MOUSE_WHEEL_CHANGED:
+ {
+ VimScrollBar* scb = curwin->w_scrollbars[1].id;
+ float small=0, big=0, dy=0;
+ m->FindFloat("be:wheel_delta_y", &dy);
+ scb->GetSteps(&small, &big);
+ scb->SetValue(scb->Value()+small*dy*3);
+ scb->ValueChanged(scb->Value());
+#if 0
+ scb = curwin->w_scrollbars[0].id;
+ scb->GetSteps(&small, &big);
+ scb->SetValue(scb->Value()+small*dy);
+ scb->ValueChanged(scb->Value());
+#endif
+ }
+ break;
+#ifdef FEAT_MBYTE_IME
+ case B_INPUT_METHOD_EVENT:
+ {
+ int32 opcode;
+ m->FindInt32("be:opcode", &opcode);
+ switch(opcode)
+ {
+ case B_INPUT_METHOD_STARTED:
+ if(!IMData.messenger) delete IMData.messenger;
+ IMData.messenger = new BMessenger();
+ m->FindMessenger("be:reply_to", IMData.messenger);
+ break;
+ case B_INPUT_METHOD_CHANGED:
+ {
+ BString str;
+ bool confirmed;
+ if(IMData.message) *(IMData.message) = *m;
+ else IMData.message = new BMessage(*m);
+ DrawIMString();
+ m->FindBool("be:confirmed", &confirmed);
+ if (confirmed)
+ {
+ m->FindString("be:string", &str);
+ char_u *chars = (char_u*)str.String();
+ struct VimKeyMsg km;
+ km.csi_escape = true;
+ int clen;
+ int i = 0;
+ while (i < str.Length())
+ {
+ clen = utf_ptr2len(chars+i);
+ memcpy(km.chars, chars+i, clen);
+ km.length = clen;
+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+ i += clen;
+ }
+ }
+ }
+ break;
+ case B_INPUT_METHOD_LOCATION_REQUEST:
+ {
+ BMessage msg(B_INPUT_METHOD_EVENT);
+ msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
+ msg.AddPoint("be:location_reply", IMData.location);
+ msg.AddFloat("be:height_reply", FILL_Y(1));
+ IMData.messenger->SendMessage(&msg);
+ }
+ break;
+ case B_INPUT_METHOD_STOPPED:
+ delete IMData.messenger;
+ delete IMData.message;
+ IMData.messenger = NULL;
+ IMData.message = NULL;
+ break;
+ }
+ }
+ //TODO: sz: break here???
+#endif
+ default:
+ if (m->WasDropped()) {
+ BWindow *w = Window();
+ w->DetachCurrentMessage();
+ w->Minimize(false);
+ VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0);
+ } else {
+ Inherited::MessageReceived(m);
+ }
+ break;
+ }
+}
+
+ int
+VimTextAreaView::mchInitFont(char_u *name)
+{
+ VimFont *newFont = (VimFont *)gui_mch_get_font(name, 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;
+#ifdef FEAT_MBYTE
+ cells = 0;
+ for(int i=0; i<len; i++) {
+ int cn = utf_ptr2cells((char_u *)(s+i));
+ if(cn<4) cells += cn;
+ }
+#else
+ cells = len;
+#endif
+
+ BRect r(FILL_X(col), FILL_Y(row),
+ FILL_X(col + cells) - PEN_WIDTH, FILL_Y(row + 1) - PEN_WIDTH);
+ FillRect(r, B_SOLID_LOW);
+ }
+
+ BFont font;
+ this->GetFont(&font);
+ if(!font.IsFixed())
+ {
+ char* p = (char*)s;
+ int32 clen, lastpos = 0;
+ BPoint where;
+ int cells;
+ while((p - (char*)s) < len) {
+#ifdef FEAT_MBYTE
+ clen = utf_ptr2len((u_char*)p);
+#else
+ clen = 1;
+#endif
+ where.Set(TEXT_X(col+lastpos), TEXT_Y(row));
+ DrawString(p, clen, where);
+ if (flags & DRAW_BOLD) {
+ where.x += 1.0;
+ SetDrawingMode(B_OP_BLEND);
+ DrawString(p, clen, where);
+ SetDrawingMode(B_OP_COPY);
+ }
+#ifdef FEAT_MBYTE
+ cells = utf_ptr2cells((char_u *)p);
+ if(cells<4) lastpos += cells;
+ else lastpos++;
+#else
+ lastpos++;
+#endif
+ p += clen;
+ }
+ }
+ else
+ {
+ BPoint where(TEXT_X(col), TEXT_Y(row));
+ DrawString((char*)s, len, where);
+ if (flags & DRAW_BOLD) {
+ where.x += 1.0;
+ SetDrawingMode(B_OP_BLEND);
+ DrawString((char*)s, len, where);
+ SetDrawingMode(B_OP_COPY);
+ }
+ }
+
+ if (flags & DRAW_UNDERL) {
+ int cells;
+#ifdef FEAT_MBYTE
+ cells = 0;
+ for(int i=0; i<len; i++) {
+ int cn = utf_ptr2cells((char_u *)(s+i));
+ if(cn<4) cells += cn;
+ }
+#else
+ cells = len;
+#endif
+
+ BPoint start(FILL_X(col), FILL_Y(row + 1) - PEN_WIDTH);
+ BPoint end(FILL_X(col + cells) - PEN_WIDTH, start.y);
+
+ StrokeLine(start, end);
+ }
+}
+
+void
+VimTextAreaView::mchClearBlock(
+ int row1,
+ int col1,
+ int row2,
+ int col2)
+{
+ BRect r(FILL_X(col1), FILL_Y(row1),
+ FILL_X(col2 + 1) - PEN_WIDTH, FILL_Y(row2 + 1) - PEN_WIDTH);
+ gui_mch_set_bg_color(gui.back_pixel);
+ FillRect(r, B_SOLID_LOW);
+}
+
+ void
+VimTextAreaView::mchClearAll()
+{
+ gui_mch_set_bg_color(gui.back_pixel);
+ FillRect(Bounds(), B_SOLID_LOW);
+}
+
+/*
+ * mchDeleteLines() Lock()s the window by itself.
+ */
+ void
+VimTextAreaView::mchDeleteLines(int row, int num_lines)
+{
+ BRect source, dest;
+ source.left = FILL_X(gui.scroll_region_left);
+ source.top = FILL_Y(row + num_lines);
+ source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+ source.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
+
+ dest.left = FILL_X(gui.scroll_region_left);
+ dest.top = FILL_Y(row);
+ dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+ dest.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ /* Clear one column more for when bold has spilled over */
+ CopyBits(source, dest);
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+
+
+ gui.vimWindow->Unlock();
+ /*
+ * The Draw() callback will be called now if some of the source
+ * bits were not in the visible region.
+ */
+ }
+ //gui_x11_check_copy_area();
+ // }
+}
+
+/*
+ * mchInsertLines() Lock()s the window by itself.
+ */
+ void
+VimTextAreaView::mchInsertLines(int row, int num_lines)
+{
+ BRect source, dest;
+
+ /* XXX Attempt at a hack: */
+ gui.vimWindow->UpdateIfNeeded();
+ source.left = FILL_X(gui.scroll_region_left);
+ source.top = FILL_Y(row);
+ source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+ source.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
+
+ dest.left = FILL_X(gui.scroll_region_left);
+ dest.top = FILL_Y(row + num_lines);
+ dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
+ dest.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ /* Clear one column more for when bold has spilled over */
+ CopyBits(source, dest);
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+
+ gui.vimWindow->Unlock();
+ /*
+ * The Draw() callback will be called now if some of the source
+ * bits were not in the visible region.
+ * However, if we scroll too fast it can't keep up and the
+ * update region gets messed up. This seems to be because copying
+ * un-Draw()n bits does not generate Draw() calls for the copy...
+ * I moved the hack to before the CopyBits() to reduce the
+ * amount of additional waiting needed.
+ */
+
+ //gui_x11_check_copy_area();
+
+ }
+}
+
+#ifdef FEAT_MBYTE_IME
+/*
+ * DrawIMString draws string with IMData.message.
+ */
+void VimTextAreaView::DrawIMString(void)
+{
+ static const rgb_color r_highlight = {255, 152, 152, 255},
+ b_highlight = {152, 203, 255, 255};
+ BString str;
+ const char* s;
+ int len;
+ BMessage* msg = IMData.message;
+ if (!msg)
+ return;
+ gui_redraw_block(IMData.row, 0,
+ IMData.row + IMData.count, W_WIDTH(curwin), GUI_MON_NOCLEAR);
+ bool confirmed = false;
+ msg->FindBool("be:confirmed", &confirmed);
+ if (confirmed)
+ return;
+ rgb_color hcolor = HighColor(), lcolor = LowColor();
+ msg->FindString("be:string", &str);
+ s = str.String();
+ len = str.Length();
+ SetHighColor(0, 0, 0);
+ IMData.row = gui.row;
+ IMData.col = gui.col;
+ int32 sel_start = 0, sel_end = 0;
+ msg->FindInt32("be:selection", 0, &sel_start);
+ msg->FindInt32("be:selection", 1, &sel_end);
+ int clen, cn;
+ BPoint pos(IMData.col, 0);
+ BRect r;
+ BPoint where;
+ IMData.location = ConvertToScreen(
+ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
+ for (int i=0; i<len; i+=clen)
+ {
+ cn = utf_ptr2cells((char_u *)(s+i));
+ clen = utf_ptr2len((char_u *)(s+i));
+ if (pos.x + cn > W_WIDTH(curwin))
+ {
+ pos.y++;
+ pos.x = 0;
+ }
+ if (sel_start<=i && i<sel_end)
+ {
+ SetLowColor(r_highlight);
+ IMData.location = ConvertToScreen(
+ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
+ }
+ else
+ {
+ SetLowColor(b_highlight);
+ }
+ r.Set(FILL_X(pos.x), FILL_Y(IMData.row + pos.y),
+ FILL_X(pos.x + cn) - PEN_WIDTH,
+ FILL_Y(IMData.row + pos.y + 1) - PEN_WIDTH);
+ FillRect(r, B_SOLID_LOW);
+ where.Set(TEXT_X(pos.x), TEXT_Y(IMData.row + pos.y));
+ DrawString((s+i), clen, where);
+ pos.x += cn;
+ }
+ IMData.count = (int)pos.y;
+
+ SetHighColor(hcolor);
+ SetLowColor(lcolor);
+}
+#endif
+/* ---------------- VimScrollBar ---------------- */
+
+/* BUG: XXX
+ * It seems that BScrollBar determine their direction not from
+ * "posture" but from if they are "tall" or "wide" in shape...
+ *
+ * Also, place them out of sight, because Vim enables them before
+ * they are positioned.
+ */
+VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
+ BScrollBar(posture == B_HORIZONTAL ? BRect(-100,-100,-10,-90) :
+ BRect(-100,-100,-90,-10),
+ "vim scrollbar", (BView *)NULL,
+ 0.0, 10.0, posture),
+ ignoreValue(-1),
+ scrollEventCount(0)
+{
+ gsb = g;
+ SetResizingMode(B_FOLLOW_NONE);
+}
+
+VimScrollBar::~VimScrollBar()
+{
+}
+
+ void
+VimScrollBar::ValueChanged(float newValue)
+{
+ if (ignoreValue >= 0.0 && newValue == ignoreValue) {
+ ignoreValue = -1;
+ return;
+ }
+ ignoreValue = -1;
+ /*
+ * We want to throttle the amount of scroll messages generated.
+ * Normally I presume you won't get a new message before we've
+ * handled the previous one, but because we're passing them on this
+ * happens very quickly. So instead we keep a counter of how many
+ * scroll events there are (or will be) in the VDCMP, and the
+ * throttling happens at the receiving end.
+ */
+ atomic_add(&scrollEventCount, 1);
+
+ struct VimScrollBarMsg sm;
+
+ sm.sb = this;
+ sm.value = (long) newValue;
+ sm.stillDragging = TRUE;
+
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+ // calls gui_drag_scrollbar(sb, newValue, TRUE);
+}
+
+/*
+ * When the mouse goes up, report that scrolling has stopped.
+ * MouseUp() is NOT called when the mouse-up occurs outside
+ * the window, even though the thumb does move while the mouse
+ * is outside... This has some funny effects... XXX
+ * So we do special processing when the window de/activates.
+ */
+ void
+VimScrollBar::MouseUp(BPoint where)
+{
+ //BMessage *m = Window()->CurrentMessage();
+ //m->PrintToStream();
+
+ atomic_add(&scrollEventCount, 1);
+
+ struct VimScrollBarMsg sm;
+
+ sm.sb = this;
+ sm.value = (long) Value();
+ sm.stillDragging = FALSE;
+
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+ // calls gui_drag_scrollbar(sb, newValue, FALSE);
+
+ Inherited::MouseUp(where);
+}
+
+ void
+VimScrollBar::SetValue(float newValue)
+{
+ if (newValue == Value())
+ return;
+
+ ignoreValue = newValue;
+ Inherited::SetValue(newValue);
+}
+
+/* ---------------- VimFont ---------------- */
+
+VimFont::VimFont(): BFont()
+{
+ init();
+}
+
+VimFont::VimFont(const VimFont *rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::VimFont(const BFont *rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::VimFont(const VimFont &rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::~VimFont()
+{
+}
+
+ void
+VimFont::init()
+{
+ next = NULL;
+ refcount = 1;
+ name = NULL;
+}
+
+/* ---------------- VimDialog ---------------- */
+
+#if defined(FEAT_GUI_DIALOG)
+
+const unsigned int kVimDialogButtonMsg = 'VMDB';
+const unsigned int kVimDialogIconStripeWidth = 30;
+const unsigned int kVimDialogButtonsSpacingX = 9;
+const unsigned int kVimDialogButtonsSpacingY = 4;
+const unsigned int kVimDialogSpacingX = 6;
+const unsigned int kVimDialogSpacingY = 10;
+const unsigned int kVimDialogMinimalWidth = 310;
+const unsigned int kVimDialogMinimalHeight = 75;
+const BRect kDefaultRect =
+BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight);
+
+VimDialog::VimDialog(int type, const char *title, const char *message,
+ const char *buttons, int dfltbutton, const char *textfield, 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[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;
+ }
+ }
+}
+
+ bool
+VimToolbar::GrayButton(vimmenu_T *menu, int grey)
+{
+ if(menu->button) {
+ int32 index = fButtonsList.IndexOf(menu->button);
+ if(index >= 0)
+ menu->button->SetEnabled(grey ? false : true);
+ }
+}
+
+ void
+VimToolbar::InvalidateLayout()
+{
+ int32 offset = ToolbarMargin;
+ int32 count = fButtonsList.CountItems();
+ for(int32 i = 0; i < count; i++) {
+ BPictureButton *button = (BPictureButton *)fButtonsList.ItemAt(i);
+ if(button) {
+ button->MoveTo(offset, ToolbarMargin);
+ offset += button->Bounds().Width() + ToolbarMargin;
+ } else
+ offset += ToolbarMargin * 3;
+ }
+}
+
+#endif /*FEAT_TOOLBAR*/
+
+#if defined(FEAT_GUI_TABLINE)
+
+ float
+VimTabLine::TablineHeight() const
+{
+// float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
+// return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
+ return TabHeight();// + ToolbarMargin;
+}
+
+void
+VimTabLine::MouseDown(BPoint point)
+{
+ if(!gui_mch_showing_tabline())
+ return;
+
+ BMessage *m = Window()->CurrentMessage();
+ assert(m);
+
+ int32 buttons = 0;
+ m->FindInt32("buttons", &buttons);
+
+ int32 clicks = 0;
+ m->FindInt32("clicks", &clicks);
+
+ int index = 0; // 0 means here - no tab found
+ for (int i = 0; i < CountTabs(); i++) {
+ if(TabFrame(i).Contains(point)) {
+ index = i + 1; // indexes are 1-based
+ break;
+ }
+ }
+
+ int event = -1;
+
+ if ((buttons & B_PRIMARY_MOUSE_BUTTON) && clicks > 1)
+ // left button double click on - create new tab
+ event = TABLINE_MENU_NEW;
+
+ else if (buttons & B_TERTIARY_MOUSE_BUTTON)
+ // middle button click - close the pointed tab
+ // or create new one in case empty space
+ event = index > 0 ? TABLINE_MENU_CLOSE : TABLINE_MENU_NEW;
+
+ else if (buttons & B_SECONDARY_MOUSE_BUTTON) {
+ // right button click - show context menu
+ BPopUpMenu* popUpMenu = new BPopUpMenu("tabLineContextMenu", false, false);
+ popUpMenu->AddItem(new BMenuItem(_("Close tabi R"), new BMessage(TABLINE_MENU_CLOSE)));
+ popUpMenu->AddItem(new BMenuItem(_("New tab T"), new BMessage(TABLINE_MENU_NEW)));
+ popUpMenu->AddItem(new BMenuItem(_("Open tab..."), new BMessage(TABLINE_MENU_OPEN)));
+
+ ConvertToScreen(&point);
+ BMenuItem* item = popUpMenu->Go(point);
+ if (item != NULL) {
+ event = item->Command();
+ }
+
+ delete popUpMenu;
+
+ } else {
+ // default processing
+ BTabView::MouseDown(point);
+ return;
+ }
+
+ if (event < 0)
+ return;
+
+ VimTablineMenuMsg tmm;
+ tmm.index = index;
+ tmm.event = event;
+ write_port(gui.vdcmp, VimMsg::TablineMenu, &tmm, sizeof(tmm));
+}
+
+void
+VimTabLine::VimTab::Select(BView* owner)
+{
+ BTab::Select(owner);
+
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+ if(tabLine != NULL) {
+
+ int32 i = 0;
+ for (; i < tabLine->CountTabs(); i++)
+ if(this == tabLine->TabAt(i))
+ break;
+
+// printf("%d:%d:%s\n", i, tabLine->CountTabs(), tabLine->TabAt(i)->Label());
+ if(i < tabLine->CountTabs()) {
+ VimTablineMsg tm;
+ tm.index = i + 1;
+ write_port(gui.vdcmp, VimMsg::Tabline, &tm, sizeof(tm));
+ }
+ }
+}
+
+#endif // defined(FEAT_GUI_TABLINE)
+
+/* ---------------- ---------------- */
+
+// some global variables
+static char appsig[] = "application/x-vnd.Haiku-Vim-7";
+key_map *keyMap;
+char *keyMapChars;
+int main_exitcode = 127;
+
+ status_t
+gui_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;
+ }
+
+#ifdef FEAT_MBYTE
+ if (vm.u.Key.csi_escape)
+#ifndef FEAT_MBYTE_IME
+ {
+ int i;
+ char_u buf[2];
+
+ for (i = 0; i < len; ++i)
+ {
+ add_to_input_buf(string + i, 1);
+ if (string[i] == CSI)
+ {
+ /* Turn CSI into K_CSI. */
+ buf[0] = KS_EXTRA;
+ buf[1] = (int)KE_CSI;
+ add_to_input_buf(buf, 2);
+ }
+ }
+ }
+#else
+ add_to_input_buf_csi(string, len);
+#endif
+ else
+#endif
+ add_to_input_buf(string, len);
+ }
+ break;
+ case VimMsg::Resize:
+ gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height);
+ break;
+ case VimMsg::ScrollBar:
+ {
+ /*
+ * If loads of scroll messages queue up, use only the last
+ * one. Always report when the scrollbar stops dragging.
+ * This is not perfect yet anyway: these events are queued
+ * yet again, this time in the keyboard input buffer.
+ */
+ int32 oldCount =
+ atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1);
+ if (oldCount <= 1 || !vm.u.Scroll.stillDragging)
+ gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(),
+ vm.u.Scroll.value, vm.u.Scroll.stillDragging);
+ }
+ break;
+#if defined(FEAT_MENU)
+ case VimMsg::Menu:
+ gui_menu_cb(vm.u.Menu.guiMenu);
+ break;
+#endif
+ case VimMsg::Mouse:
+ {
+ int32 oldCount;
+ if (vm.u.Mouse.button == MOUSE_DRAG)
+ oldCount =
+ atomic_add(&gui.vimTextArea->mouseDragEventCount, -1);
+ else
+ oldCount = 0;
+ if (oldCount <= 1)
+ gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x,
+ vm.u.Mouse.y, vm.u.Mouse.repeated_click,
+ vm.u.Mouse.modifiers);
+ }
+ break;
+ case VimMsg::MouseMoved:
+ {
+ gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y);
+ }
+ break;
+ case VimMsg::Focus:
+ gui.in_focus = vm.u.Focus.active;
+ /* XXX Signal that scrollbar dragging has stopped?
+ * This is needed because we don't get a MouseUp if
+ * that happens while outside the window... :-(
+ */
+ if (gui.dragged_sb) {
+ gui.dragged_sb = SBAR_NONE;
+ }
+ // gui_update_cursor(TRUE, FALSE);
+ break;
+ case VimMsg::Refs:
+ ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir);
+ break;
+ case VimMsg::Tabline:
+ send_tabline_event(vm.u.Tabline.index);
+ break;
+ case VimMsg::TablineMenu:
+ send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event);
+ break;
+ default:
+ // unrecognised message, ignore it
+ break;
+ }
+ }
+
+ /*
+ * If size < B_OK, it is an error code.
+ */
+ return size;
+}
+
+/*
+ * Here are some functions to protect access to ScreenLines[] and
+ * LineOffset[]. These are used from the window thread to respond
+ * to a Draw() callback. When that occurs, the window is already
+ * locked by the system.
+ *
+ * Other code that needs to lock is any code that changes these
+ * variables. Other read-only access, or access merely to the
+ * contents of the screen buffer, need not be locked.
+ *
+ * If there is no window, don't call Lock() but do succeed.
+ */
+
+ int
+vim_lock_screen()
+{
+ return !gui.vimWindow || gui.vimWindow->Lock();
+}
+
+ void
+vim_unlock_screen()
+{
+ if (gui.vimWindow)
+ gui.vimWindow->Unlock();
+}
+
+#define RUN_BAPPLICATION_IN_NEW_THREAD 0
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+
+ int32
+run_vimapp(void *args)
+{
+ VimApp app(appsig);
+
+ gui.vimApp = &app;
+ app.Run(); /* Run until Quit() called */
+
+ return 0;
+}
+
+#else
+
+ int32
+call_main(void *args)
+{
+ struct MainArgs *ma = (MainArgs *)args;
+
+ return main(ma->argc, ma->argv);
+}
+#endif
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(
+ int *argc,
+ char **argv)
+{
+ /*
+ * We don't have any command line arguments for the BeOS GUI yet,
+ * but this is an excellent place to create our Application object.
+ */
+ if (!gui.vimApp) {
+ thread_info tinfo;
+ get_thread_info(find_thread(NULL), &tinfo);
+
+ /* May need the port very early on to process RefsReceived() */
+ gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP");
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+ thread_id tid = spawn_thread(run_vimapp, "vim VimApp",
+ tinfo.priority, NULL);
+ if (tid >= B_OK) {
+ resume_thread(tid);
+ } else {
+ getout(1);
+ }
+#else
+ MainArgs ma = { *argc, argv };
+ thread_id tid = spawn_thread(call_main, "vim main()",
+ tinfo.priority, &ma);
+ if (tid >= B_OK) {
+ VimApp app(appsig);
+
+ gui.vimApp = &app;
+ resume_thread(tid);
+ /*
+ * This is rather horrible.
+ * call_main will call main() again...
+ * There will be no infinite recursion since
+ * gui.vimApp is set now.
+ */
+ app.Run(); /* Run until Quit() called */
+ //fprintf(stderr, "app.Run() returned...\n");
+ status_t dummy_exitcode;
+ (void)wait_for_thread(tid, &dummy_exitcode);
+
+ /*
+ * This path should be the normal one taken to exit Vim.
+ * The main() thread calls mch_exit() which calls
+ * gui_mch_exit() which terminates its thread.
+ */
+ exit(main_exitcode);
+ }
+#endif
+ }
+ /* Don't fork() when starting the GUI. Spawned threads are not
+ * duplicated with a fork(). The result is a mess.
+ */
+ gui.dofork = FALSE;
+ /*
+ * XXX Try to determine whether we were started from
+ * the Tracker or the terminal.
+ * It would be nice to have this work, because the Tracker
+ * follows symlinks, so even if you double-click on gvim,
+ * when it is a link to vim it will still pass a command name
+ * of vim...
+ * We try here to see if stdin comes from /dev/null. If so,
+ * (or if there is an error, which should never happen) start the GUI.
+ * This does the wrong thing for vim - </dev/null, and we're
+ * too early to see the command line parsing. Tough.
+ * On the other hand, it starts the gui for vim file & which is nice.
+ */
+ if (!isatty(0)) {
+ struct stat stat_stdin, stat_dev_null;
+
+ if (fstat(0, &stat_stdin) == -1 ||
+ stat("/dev/null", &stat_dev_null) == -1 ||
+ (stat_stdin.st_dev == stat_dev_null.st_dev &&
+ stat_stdin.st_ino == stat_dev_null.st_ino))
+ gui.starting = TRUE;
+ }
+}
+
+/*
+ * 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 truely gone */
+ int32 exitcode;
+ wait_for_thread(tid, &exitcode);
+ }
+ delete_port(gui.vdcmp);
+#if !RUN_BAPPLICATION_IN_NEW_THREAD
+ /*
+ * We are in the main() thread - quit the App thread and
+ * quit ourselves (passing on the exitcode). Use a global since the
+ * value from exit_thread() is only used if wait_for_thread() is
+ * called in time (race condition).
+ */
+#endif
+ if (gui.vimApp) {
+ VimTextAreaView::guiBlankMouse(false);
+
+ main_exitcode = vim_exitcode;
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+ thread_id tid = gui.vimApp->Thread();
+ int32 exitcode;
+ gui.vimApp->Lock();
+ gui.vimApp->Quit();
+ gui.vimApp->Unlock();
+ wait_for_thread(tid, &exitcode);
+#else
+ gui.vimApp->Lock();
+ gui.vimApp->Quit();
+ gui.vimApp->Unlock();
+ /* suicide */
+ exit_thread(vim_exitcode);
+#endif
+ }
+ /* If we are somehow still here, let mch_exit() handle things. */
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ if (gui.vimWindow->Lock()) {
+ BRect r;
+ r = gui.vimWindow->Frame();
+ gui.vimWindow->Unlock();
+ *x = (int)r.left;
+ *y = (int)r.top;
+ return OK;
+ }
+ else
+ return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->MoveTo(x, y);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Set the size of the window to the given width and height in pixels.
+ */
+void
+gui_mch_set_shellsize(
+ int width,
+ int height,
+ int min_width,
+ int min_height,
+ int base_width,
+ int base_height,
+ int direction) //TODO: utilize?
+{
+ /*
+ * We are basically given the size of the VimForm, if I understand
+ * correctly. Since it fills the window completely, this will also
+ * be the size of the window.
+ */
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH);
+
+ /* set size limits */
+ float minWidth, maxWidth, minHeight, maxHeight;
+
+ gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth,
+ &minHeight, &maxHeight);
+ gui.vimWindow->SetSizeLimits(min_width, maxWidth,
+ min_height, maxHeight);
+
+ /*
+ * Set the resizing alignment depending on font size.
+ */
+ gui.vimWindow->SetWindowAlignment(
+ B_PIXEL_ALIGNMENT, // window_alignment mode,
+ 1, // int32 h,
+ 0, // int32 hOffset = 0,
+ gui.char_width, // int32 width = 0,
+ base_width, // int32 widthOffset = 0,
+ 1, // int32 v = 0,
+ 0, // int32 vOffset = 0,
+ gui.char_height, // int32 height = 0,
+ base_height // int32 heightOffset = 0
+ );
+
+ gui.vimWindow->Unlock();
+ }
+}
+
+void
+gui_mch_get_screen_dimensions(
+ int *screen_w,
+ int *screen_h)
+{
+ BRect frame;
+
+ {
+ BScreen screen(gui.vimWindow);
+
+ if (screen.IsValid()) {
+ frame = screen.Frame();
+ } else {
+ frame.right = 640;
+ frame.bottom = 480;
+ }
+ }
+
+ /* XXX approximations... */
+ *screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20;
+ *screen_h = (int) frame.bottom - gui.scrollbar_height
+#ifdef FEAT_MENU
+ - gui.menu_height
+#endif
+ - 30;
+}
+
+void
+gui_mch_set_text_area_pos(
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ if (!gui.vimTextArea)
+ return;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->MoveTo(x, y);
+ gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+
+/*#ifdef FEAT_GUI_TABLINE
+ if(gui.vimForm->TabLine() != NULL) {
+ gui.vimForm->TabLine()->ResizeTo(w, gui.vimForm->TablineHeight());
+ }
+#endif //FEAT_GUI_TABLINE*/
+
+ gui.vimWindow->Unlock();
+ }
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+void
+gui_mch_enable_scrollbar(
+ scrollbar_T *sb,
+ int flag)
+{
+ VimScrollBar *vsb = sb->id;
+ if (gui.vimWindow->Lock()) {
+ /*
+ * This function is supposed to be idempotent, but Show()/Hide()
+ * is not. Therefore we test if they are needed.
+ */
+ if (flag) {
+ if (vsb->IsHidden()) {
+ vsb->Show();
+ }
+ } else {
+ if (!vsb->IsHidden()) {
+ vsb->Hide();
+ }
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+void
+gui_mch_set_scrollbar_thumb(
+ scrollbar_T *sb,
+ int val,
+ int size,
+ int max)
+{
+ if (gui.vimWindow->Lock()) {
+ VimScrollBar *s = sb->id;
+ if (max == 0) {
+ s->SetValue(0);
+ s->SetRange(0.0, 0.0);
+ } else {
+ s->SetProportion((float)size / (max + 1.0));
+ s->SetSteps(1.0, size > 5 ? size - 2 : size);
+#ifndef SCROLL_PAST_END // really only defined in gui.c...
+ max = max + 1 - size;
+#endif
+ if (max < s->Value()) {
+ /*
+ * If the new maximum is lower than the current value,
+ * setting it would cause the value to be clipped and
+ * therefore a ValueChanged() call.
+ * We avoid this by setting the value first, because
+ * it presumably is <= max.
+ */
+ s->SetValue(val);
+ s->SetRange(0.0, max);
+ } else {
+ /*
+ * In the other case, set the range first, since the
+ * new value might be higher than the current max.
+ */
+ s->SetRange(0.0, max);
+ s->SetValue(val);
+ }
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+void
+gui_mch_set_scrollbar_pos(
+ scrollbar_T *sb,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ if (gui.vimWindow->Lock()) {
+ BRect winb = gui.vimWindow->Bounds();
+ float vsbx = x, vsby = y;
+ VimScrollBar *vsb = sb->id;
+ vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+ if(winb.right-(x+w)<w) vsbx = winb.right - (w - PEN_WIDTH);
+ vsb->MoveTo(vsbx, vsby);
+ gui.vimWindow->Unlock();
+ }
+}
+
+void
+gui_mch_create_scrollbar(
+ scrollbar_T *sb,
+ int orient) /* SBAR_VERT or SBAR_HORIZ */
+{
+ orientation posture =
+ (orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL;
+
+ VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture);
+ if (gui.vimWindow->Lock()) {
+ vsb->SetTarget(gui.vimTextArea);
+ vsb->Hide();
+ gui.vimForm->AddChild(vsb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+void
+gui_mch_destroy_scrollbar(
+ scrollbar_T *sb)
+{
+ if (gui.vimWindow->Lock()) {
+ sb->id->RemoveSelf();
+ delete sb->id;
+ gui.vimWindow->Unlock();
+ }
+}
+#endif
+
+ 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()
+{
+ /* 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)
+ EMSG2("(fe0) default font is not defined", 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 = 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)
+ EMSG2("(fe0) Specified font %s is not found", font->name);
+ delete font;
+ return NOFONT;
+ }
+
+ // Remember font in the static list for later use
+ font->next = fontList;
+ fontList = font;
+
+ font->SetFamilyAndStyle(family, style);
+ if(size > 0.f)
+ font->SetSize(size);
+
+ font->SetSpacing(B_FIXED_SPACING);
+ font->SetEncoding(B_UNICODE_UTF8);
+
+ return (GuiFont)font;
+}
+
+/*
+ * Set the current text font.
+ */
+void
+gui_mch_set_font(
+ GuiFont font)
+{
+ if (gui.vimWindow->Lock()) {
+ VimFont *vf = (VimFont *)font;
+
+ gui.vimTextArea->SetFont(vf);
+
+ gui.char_width = (int) vf->StringWidth("n");
+ font_height fh;
+ vf->GetHeight(&fh);
+ gui.char_height = (int)(fh.ascent + 0.9999)
+ + (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999);
+ gui.char_ascent = (int)(fh.ascent + 0.9999);
+
+ gui.vimWindow->Unlock();
+ }
+}
+
+/* XXX TODO This is apparently never called... */
+void
+gui_mch_free_font(
+ GuiFont font)
+{
+ if(font == NOFONT)
+ return;
+ VimFont *f = (VimFont *)font;
+ if (--f->refcount <= 0) {
+ if (f->refcount < 0)
+ fprintf(stderr, "VimFont: refcount < 0\n");
+ delete f;
+ }
+}
+
+ char_u *
+gui_mch_get_fontname(GuiFont font, char_u *name)
+{
+ if (name == NULL)
+ return NULL;
+ return vim_strsave(name);
+}
+
+/*
+ * Adjust gui.char_height (after 'linespace' was changed).
+ */
+ int
+gui_mch_adjust_charheight()
+{
+
+ //TODO: linespace support?
+
+//#ifdef FEAT_XFONTSET
+// if (gui.fontset != NOFONTSET)
+// {
+// gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace;
+// gui.char_ascent = fontset_ascent((XFontSet)gui.fontset)
+// + p_linespace / 2;
+// }
+// else
+//#endif
+ {
+ VimFont *font = (VimFont *)gui.norm_font;
+ font_height fh = {0};
+ font->GetHeight(&fh);
+ gui.char_height = (int)(fh.ascent + fh.descent + 0.5) + p_linespace;
+ gui.char_ascent = (int)(fh.ascent + 0.5) + p_linespace / 2;
+ }
+ return OK;
+}
+
+/*
+ * Display the saved error message(s).
+ */
+#ifdef USE_MCH_ERRMSG
+ void
+display_errors(void)
+{
+ char *p;
+ char_u pError[256];
+
+ if (error_ga.ga_data == NULL)
+ return;
+
+ /* avoid putting up a message box with blanks only */
+ for (p = (char *)error_ga.ga_data; *p; ++p)
+ if (!isspace(*p))
+ {
+ if (STRLEN(p) > 255)
+ pError[0] = 255;
+ else
+ pError[0] = STRLEN(p);
+
+ STRNCPY(&pError[1], p, pError[0]);
+// ParamText(pError, nil, nil, nil);
+// Alert(128, nil);
+ break;
+ /* TODO: handled message longer than 256 chars
+ * use auto-sizeable alert
+ * or dialog with scrollbars (TextEdit zone)
+ */
+ }
+ ga_clear(&error_ga);
+}
+#endif
+
+ void
+gui_mch_getmouse(int *x, int *y)
+{
+ fprintf(stderr, "gui_mch_getmouse");
+
+ /*int rootx, rooty, winx, winy;
+ Window root, child;
+ unsigned int mask;
+
+ if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
+ &rootx, &rooty, &winx, &winy, &mask)) {
+ *x = winx;
+ *y = winy;
+ } else*/ {
+ *x = -1;
+ *y = -1;
+ }
+}
+
+ void
+gui_mch_mousehide(int hide)
+{
+ fprintf(stderr, "gui_mch_getmouse");
+ // TODO
+}
+
+ static int
+hex_digit(int c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+
+/*
+ * This function has been lifted from gui_w32.c and extended a bit.
+ *
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+guicolor_T
+gui_mch_get_color(
+ char_u *name)
+{
+ typedef struct GuiColourTable
+ {
+ const char *name;
+ guicolor_T colour;
+ } GuiColourTable;
+
+#define NSTATIC_COLOURS 50 //32
+#define NDYNAMIC_COLOURS 33
+#define NCOLOURS (NSTATIC_COLOURS + NDYNAMIC_COLOURS)
+
+ static GuiColourTable table[NCOLOURS] =
+ {
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"DarkGray", RGB(0x80, 0x80, 0x80)},
+ {"DarkGrey", RGB(0x80, 0x80, 0x80)},
+ {"Gray", RGB(0xC0, 0xC0, 0xC0)},
+ {"Grey", RGB(0xC0, 0xC0, 0xC0)},
+ {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
+ {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
+ {"Gray10", RGB(0x1A, 0x1A, 0x1A)},
+ {"Grey10", RGB(0x1A, 0x1A, 0x1A)},
+ {"Gray20", RGB(0x33, 0x33, 0x33)},
+ {"Grey20", RGB(0x33, 0x33, 0x33)},
+ {"Gray30", RGB(0x4D, 0x4D, 0x4D)},
+ {"Grey30", RGB(0x4D, 0x4D, 0x4D)},
+ {"Gray40", RGB(0x66, 0x66, 0x66)},
+ {"Grey40", RGB(0x66, 0x66, 0x66)},
+ {"Gray50", RGB(0x7F, 0x7F, 0x7F)},
+ {"Grey50", RGB(0x7F, 0x7F, 0x7F)},
+ {"Gray60", RGB(0x99, 0x99, 0x99)},
+ {"Grey60", RGB(0x99, 0x99, 0x99)},
+ {"Gray70", RGB(0xB3, 0xB3, 0xB3)},
+ {"Grey70", RGB(0xB3, 0xB3, 0xB3)},
+ {"Gray80", RGB(0xCC, 0xCC, 0xCC)},
+ {"Grey80", RGB(0xCC, 0xCC, 0xCC)},
+ {"Gray90", RGB(0xE5, 0xE5, 0xE5)},
+ {"Grey90", RGB(0xE5, 0xE5, 0xE5)},
+ {"White", RGB(0xFF, 0xFF, 0xFF)},
+ {"DarkRed", RGB(0x80, 0x00, 0x00)},
+ {"Red", RGB(0xFF, 0x00, 0x00)},
+ {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
+ {"DarkBlue", RGB(0x00, 0x00, 0x80)},
+ {"Blue", RGB(0x00, 0x00, 0xFF)},
+ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
+ {"DarkGreen", RGB(0x00, 0x80, 0x00)},
+ {"Green", RGB(0x00, 0xFF, 0x00)},
+ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
+ {"DarkCyan", RGB(0x00, 0x80, 0x80)},
+ {"Cyan", RGB(0x00, 0xFF, 0xFF)},
+ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
+ {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
+ {"Magenta", RGB(0xFF, 0x00, 0xFF)},
+ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
+ {"Brown", RGB(0x80, 0x40, 0x40)},
+ {"Yellow", RGB(0xFF, 0xFF, 0x00)},
+ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
+ {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
+ {"Orange", RGB(0xFF, 0xA5, 0x00)},
+ {"Purple", RGB(0xA0, 0x20, 0xF0)},
+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
+ {"Violet", RGB(0xEE, 0x82, 0xEE)},
+ // NOTE: some entries are zero-allocated for NDDYNAMIC_COLORS
+ // in this table!
+ };
+
+ static int endColour = NSTATIC_COLOURS;
+ static int newColour = NSTATIC_COLOURS;
+
+ int r, g, b;
+ int i;
+
+ if (name[0] == '#' && STRLEN(name) == 7)
+ {
+ /* Name is in "#rrggbb" format */
+ r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+ g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+ b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+ if (r < 0 || g < 0 || b < 0)
+ return INVALCOLOR;
+ return RGB(r, g, b);
+ }
+ else
+ {
+ /* Check if the name is one of the colours we know */
+ for (i = 0; i < endColour; i++)
+ if (STRICMP(name, table[i].name) == 0)
+ return table[i].colour;
+ }
+
+ /*
+ * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
+ */
+ {
+#define LINE_LEN 100
+ FILE *fd;
+ char line[LINE_LEN];
+ char_u *fname;
+
+ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+ if (fname == NULL)
+ return INVALCOLOR;
+
+ fd = fopen((char *)fname, "rt");
+ vim_free(fname);
+ if (fd == NULL)
+ return INVALCOLOR;
+
+ while (!feof(fd))
+ {
+ int len;
+ int pos;
+ char *colour;
+
+ fgets(line, LINE_LEN, fd);
+ len = strlen(line);
+
+ if (len <= 1 || line[len-1] != '\n')
+ continue;
+
+ line[len-1] = '\0';
+
+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+ if (i != 3)
+ continue;
+
+ colour = line + pos;
+
+ if (STRICMP(colour, name) == 0)
+ {
+ fclose(fd);
+ /*
+ * Now remember this colour in the table.
+ * A LRU scheme might be better but this is simpler.
+ * Or could use a growing array.
+ */
+ guicolor_T gcolour = RGB(r,g,b);
+
+ //NOTE: see note above in table allocation! We are working here with
+ // dynamically allocated names, not constant ones!
+ vim_free((char*)table[newColour].name);
+ table[newColour].name = (char *)vim_strsave((char_u *)colour);
+ table[newColour].colour = gcolour;
+
+ newColour++;
+ if (newColour >= NCOLOURS)
+ newColour = NSTATIC_COLOURS;
+ if (endColour < NCOLOURS)
+ endColour = newColour;
+
+ return gcolour;
+ }
+ }
+
+ fclose(fd);
+ }
+
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text foreground color.
+ */
+void
+gui_mch_set_fg_color(
+ guicolor_T color)
+{
+ rgb_color rgb = GUI_TO_RGB(color);
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetHighColor(rgb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Set the current text background color.
+ */
+void
+gui_mch_set_bg_color(
+ guicolor_T color)
+{
+ rgb_color rgb = GUI_TO_RGB(color);
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetLowColor(rgb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Set the current text special color.
+ */
+ void
+gui_mch_set_sp_color(guicolor_T color)
+{
+ //prev_sp_color = color;
+}
+
+void
+gui_mch_draw_string(
+ int row,
+ int col,
+ char_u *s,
+ int len,
+ int flags)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->mchDrawString(row, col, s, len, flags);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+int
+gui_mch_haskey(
+ char_u *name)
+{
+ int i;
+
+ for (i = 0; special_keys[i].BeKeys != 0; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+ void
+gui_mch_beep()
+{
+ ::beep();
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ /* Do a visual beep by reversing the foreground and background colors */
+
+ if (gui.vimWindow->Lock()) {
+ BRect rect = gui.vimTextArea->Bounds();
+
+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->Sync();
+ snooze(msec * 1000); /* wait for a few msec */
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+ gui.vimTextArea->Flush();
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+void
+gui_mch_invert_rectangle(
+ int r,
+ int c,
+ int nr,
+ int nc)
+{
+ BRect rect;
+ rect.left = FILL_X(c);
+ rect.top = FILL_Y(r);
+ rect.right = rect.left + nc * gui.char_width - PEN_WIDTH;
+ rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify()
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->Minimize(true);
+ gui.vimWindow->Unlock();
+ }
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ /* TODO */
+}
+#endif
+
+/*
+ * Set the window title
+ */
+void
+gui_mch_settitle(
+ char_u *title,
+ char_u *icon)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->SetTitle((char *)title);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ gui_mch_set_fg_color(color);
+
+ BRect r;
+ r.left = FILL_X(gui.col);
+ r.top = FILL_Y(gui.row);
+#ifdef FEAT_MBYTE
+ int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); //TODO-TODO
+ if(cells>=4) cells = 1;
+ r.right = r.left + cells*gui.char_width - PEN_WIDTH;
+#else
+ r.right = r.left + gui.char_width - PEN_WIDTH;
+#endif
+ r.bottom = r.top + gui.char_height - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->StrokeRect(r);
+ gui.vimWindow->Unlock();
+ //gui_mch_flush();
+ }
+}
+
+/*
+ * Draw part of a cursor, only w pixels wide, and h pixels high.
+ */
+void
+gui_mch_draw_part_cursor(
+ int w,
+ int h,
+ guicolor_T color)
+{
+ gui_mch_set_fg_color(color);
+
+ BRect r;
+ r.left =
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col);
+ r.right = r.left + w - PEN_WIDTH;
+ r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH;
+ r.top = r.bottom - h + PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->FillRect(r);
+ gui.vimWindow->Unlock();
+ //gui_mch_flush();
+ }
+}
+
+/*
+ * Catch up with any queued events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update()
+{
+ gui_mch_flush();
+ while (port_count(gui.vdcmp) > 0 &&
+ !vim_is_input_buf_full() &&
+ gui_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();
+ focus = gui.in_focus;
+ }
+
+ gui_mch_flush();
+ /*
+ * Don't use gui_mch_update() because then we will spin-lock until a
+ * char arrives, instead we use gui_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 its safe to query the menu for the associated MenuItem....
+ menu->id = tmp->FindItem((const char *) menu->dname);
+
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(int enable)
+{
+ /* no tearoff menus */
+}
+
+ static BMessage *
+MenuMessage(vimmenu_T *menu)
+{
+ BMessage *m = new BMessage('menu');
+ m->AddPointer("VimMenu", (void *)menu);
+
+ return m;
+}
+
+/*
+ * Add a menu item to a menu
+ */
+void
+gui_mch_add_menu_item(
+ vimmenu_T *menu,
+ int idx)
+{
+ int mnemonic = 0;
+ vimmenu_T *parent = menu->parent;
+
+ /* TODO: use menu->actext */
+ /* This is difficult, since on Be, an accelerator must be a single char
+ * and a lot of Vim ones are the standard VI commands.
+ *
+ * Punt for Now...
+ * richard@whiequeen.com jul 99
+ */
+ if (gui.vimWindow->Lock())
+ {
+#ifdef FEAT_TOOLBAR
+ if(menu_is_toolbar(parent->name)) {
+ VimToolbar *toolbar = gui.vimForm->ToolBar();
+ if(toolbar != NULL) {
+ toolbar->AddButton(idx, menu);
+ }
+ } else
+#endif
+
+ if (parent->submenu_id != NULL || menu_is_popup(parent->name)) {
+ if (menu_is_separator(menu->name)) {
+ BSeparatorItem *item = new BSeparatorItem();
+ parent->submenu_id->AddItem(item);
+ menu->id = item;
+ menu->submenu_id = NULL;
+ }
+ else {
+ BMenuItem *item = new BMenuItem((char *)menu->dname,
+ MenuMessage(menu));
+ item->SetTarget(gui.vimTextArea);
+ item->SetTrigger((char) menu->mnemonic);
+ parent->submenu_id->AddItem(item);
+ menu->id = item;
+ menu->submenu_id = NULL;
+ }
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+void
+gui_mch_destroy_menu(
+ vimmenu_T *menu)
+{
+ if (gui.vimWindow->Lock())
+ {
+#ifdef FEAT_TOOLBAR
+ if(menu->parent && menu_is_toolbar(menu->parent->name)) {
+ VimToolbar *toolbar = gui.vimForm->ToolBar();
+ if(toolbar != NULL) {
+ toolbar->RemoveButton(menu);
+ }
+ } else
+#endif
+ {
+ assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0);
+ /*
+ * Detach this menu from its parent, so that it is not deleted
+ * twice once we get to delete that parent.
+ * Deleting a BMenuItem also deletes the associated BMenu, if any
+ * (which does not have any items anymore since they were
+ * removed and deleted before).
+ */
+ BMenu *bmenu = menu->id->Menu();
+ if (bmenu)
+ {
+ bmenu->RemoveItem(menu->id);
+ /*
+ * If we removed the last item from the menu bar,
+ * resize it out of sight.
+ */
+ if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0)
+ {
+ bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN);
+ }
+ }
+ delete menu->id;
+ menu->id = NULL;
+ menu->submenu_id = NULL;
+
+ gui.menu_height = (int) gui.vimForm->MenuHeight();
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Make a menu either grey or not grey.
+ */
+void
+gui_mch_menu_grey(
+ vimmenu_T *menu,
+ int grey)
+{
+#ifdef FEAT_TOOLBAR
+ if(menu->parent && menu_is_toolbar(menu->parent->name)) {
+ if (gui.vimWindow->Lock()) {
+ VimToolbar *toolbar = gui.vimForm->ToolBar();
+ if(toolbar != NULL) {
+ toolbar->GrayButton(menu, grey);
+ }
+ gui.vimWindow->Unlock();
+ }
+ } else
+#endif
+ if (menu->id != NULL)
+ menu->id->SetEnabled(!grey);
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+void
+gui_mch_menu_hidden(
+ vimmenu_T *menu,
+ int hidden)
+{
+ if (menu->id != NULL)
+ menu->id->SetEnabled(!hidden);
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar()
+{
+ /* Nothing to do in BeOS */
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ if (!menu_is_popup(menu->name) || menu->submenu_id == NULL)
+ return;
+
+ BPopUpMenu* popupMenu = dynamic_cast<BPopUpMenu*>(menu->submenu_id);
+ if (popupMenu == NULL)
+ return;
+
+ BPoint point;
+ if(gui.vimWindow->Lock()) {
+ uint32 buttons = 0;
+ gui.vimTextArea->GetMouse(&point, &buttons);
+ gui.vimTextArea->ConvertToScreen(&point);
+ gui.vimWindow->Unlock();
+ }
+ popupMenu->Go(point, true);
+}
+
+#endif /* FEAT_MENU */
+
+/* Mouse stuff */
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Clipboard stuff, for cutting and pasting text to other windows.
+ */
+char textplain[] = "text/plain";
+char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype";
+
+/*
+ * Get the current selection and put it in the clipboard register.
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ if (be_clipboard->Lock())
+ {
+ BMessage *m = be_clipboard->Data();
+ //m->PrintToStream();
+
+ char_u *string = NULL;
+ ssize_t stringlen = -1;
+
+ if (m->FindData(textplain, B_MIME_TYPE,
+ (const void **)&string, &stringlen) == B_OK
+ || m->FindString("text", (const char **)&string) == B_OK)
+ {
+ if (stringlen == -1)
+ stringlen = STRLEN(string);
+
+ int type;
+ char *seltype;
+ ssize_t seltypelen;
+
+ /*
+ * Try to get the special vim selection type first
+ */
+ if (m->FindData(vimselectiontype, B_MIME_TYPE,
+ (const void **)&seltype, &seltypelen) == B_OK)
+ {
+ switch (*seltype)
+ {
+ default:
+ case 'L': type = MLINE; break;
+ case 'C': type = MCHAR; break;
+#ifdef FEAT_VISUAL
+ case 'B': type = MBLOCK; break;
+#endif
+ }
+ }
+ else
+ {
+ /* Otherwise use heuristic as documented */
+ type = memchr(string, stringlen, '\n') ? MLINE : MCHAR;
+ }
+ clip_yank_selection(type, string, (long)stringlen, cbd);
+ }
+ be_clipboard->Unlock();
+ }
+}
+/*
+ * Make vim the owner of the current selection.
+ */
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ /* Nothing needs to be done here */
+}
+
+/*
+ * Make vim the owner of the current selection. Return OK upon success.
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ /*
+ * Never actually own the clipboard. If another application sets the
+ * clipboard, we don't want to think that we still own it.
+ */
+ return FAIL;
+}
+
+/*
+ * Send the current selection to the clipboard.
+ */
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+ if (be_clipboard->Lock())
+ {
+ be_clipboard->Clear();
+ BMessage *m = be_clipboard->Data();
+ assert(m);
+
+ /* If the '*' register isn't already filled in, fill it in now */
+ cbd->owned = TRUE;
+ clip_get_selection(cbd);
+ cbd->owned = FALSE;
+
+ char_u *str = NULL;
+ long_u count;
+ int type;
+
+ type = clip_convert_selection(&str, &count, cbd);
+
+ if (type < 0)
+ return;
+
+ m->AddData(textplain, B_MIME_TYPE, (void *)str, count);
+
+ /* Add type of selection */
+ char vtype;
+ switch (type)
+ {
+ default:
+ case MLINE: vtype = 'L'; break;
+ case MCHAR: vtype = 'C'; break;
+#ifdef FEAT_VISUAL
+ case MBLOCK: vtype = 'B'; break;
+#endif
+ }
+ m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1);
+
+ vim_free(str);
+
+ be_clipboard->Commit();
+ be_clipboard->Unlock();
+ }
+}
+
+#endif /* FEAT_CLIPBOARD */
+
+#ifdef FEAT_BROWSE
+/*
+ * Pop open a file browser and return the file selected, in allocated memory,
+ * or NULL if Cancel is hit.
+ * saving - TRUE if the file will be saved to, FALSE if it will be opened.
+ * title - Title message for the file browser dialog.
+ * dflt - Default name of file.
+ * ext - Default extension to be added to files without extensions.
+ * initdir - directory in which to open the browser (NULL = current dir)
+ * filter - Filter for matched files to choose from.
+ * Has a format like this:
+ * "C Files (*.c)\0*.c\0"
+ * "All Files\0*.*\0\0"
+ * If these two strings were concatenated, then a choice of two file
+ * filters will be selectable to the user. Then only matching files will
+ * be shown in the browser. If NULL, the default allows all files.
+ *
+ * *NOTE* - the filter string must be terminated with TWO nulls.
+ */
+char_u *
+gui_mch_browse(
+ int saving,
+ char_u *title,
+ char_u *dflt,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+ gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL,
+ NULL, NULL, 0, false,
+ new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true);
+
+ gui.vimApp->fBrowsedPath.Unset();
+
+ gui.vimApp->fFilePanel->Window()->SetTitle((char*)title);
+ gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir);
+
+ gui.vimApp->fFilePanel->Show();
+
+ gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem");
+
+ while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED);
+
+ char_u *fileName = NULL;
+ status_t result = gui.vimApp->fBrowsedPath.InitCheck();
+ if(result == B_OK) {
+ fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path());
+ } else
+ if(result != B_NO_INIT) {
+ fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n",
+ result, strerror(result));
+ }
+
+ delete gui.vimApp->fFilePanel;
+ gui.vimApp->fFilePanel = NULL;
+
+ return fileName;
+}
+#endif /* FEAT_BROWSE */
+
+
+#if defined(FEAT_GUI_DIALOG)
+
+/*
+ * Create a dialog dynamically from the parameter strings.
+ * type = type of dialog (question, alert, etc.)
+ * title = dialog title. may be NULL for default title.
+ * message = text to display. Dialog sizes to accommodate it.
+ * buttons = '\n' separated list of button captions, default first.
+ * dfltbutton = number of default button.
+ *
+ * This routine returns 1 if the first button is pressed,
+ * 2 for the second, etc.
+ *
+ * 0 indicates Esc was pressed.
+ * -1 for unexpected error
+ *
+ * If stubbing out this fn, return 1.
+ */
+
+int
+gui_mch_dialog(
+ int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int dfltbutton,
+ char_u *textfield,
+ 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;
+}
+
+ void
+im_set_active(int activate)
+{
+ //TODO:
+#if 0
+ if(activate)
+ printf("IME ON\n");
+ else
+ printf("IME OFF\n");
+#endif
+ return;
+}
+
+ int
+im_get_status()
+{
+ //TODO:
+ return(1);
+}
+#endif
+
+ void
+gui_mch_show_toolbar(int showit)
+{
+ VimToolbar *toolbar = gui.vimForm->ToolBar();
+ gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.;
+}
+
+ void
+gui_mch_set_toolbar_pos(int x, int y, int w, int h)
+{
+ VimToolbar *toolbar = gui.vimForm->ToolBar();
+ if(toolbar != NULL) {
+ if (gui.vimWindow->Lock()) {
+ toolbar->MoveTo(x, y);
+ toolbar->ResizeTo(w - 1, h - 1);
+ gui.vimWindow->Unlock();
+ }
+ }
+}
+
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+
+/*
+ * Show or hide the tabline.
+ */
+ void
+gui_mch_show_tabline(int showit)
+{
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+
+ if (tabLine == NULL)
+ return;
+
+ if (!showit != !gui.vimForm->IsShowingTabLine()) {
+ gui.vimForm->SetShowingTabLine(showit != 0);
+ gui.tabline_height = gui.vimForm->TablineHeight();
+ }
+}
+
+ void
+gui_mch_set_tabline_pos(int x, int y, int w, int h)
+{
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+ if(tabLine != NULL) {
+ if (gui.vimWindow->Lock()) {
+ tabLine->MoveTo(x, y);
+ tabLine->ResizeTo(w - 1, h - 1);
+ gui.vimWindow->Unlock();
+ }
+ }
+}
+
+/*
+ * Return TRUE when tabline is displayed.
+ */
+ int
+gui_mch_showing_tabline()
+{
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+ return tabLine != NULL && gui.vimForm->IsShowingTabLine();
+}
+
+/*
+ * Update the labels of the tabline.
+ */
+ void
+gui_mch_update_tabline()
+{
+ tabpage_T *tp;
+ int nr = 0;
+ int curtabidx = 0;
+
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+
+ if (tabLine == NULL)
+ return;
+
+ gui.vimWindow->Lock();
+
+ /* Add a label for each tab page. They all contain the same text area. */
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) {
+ if (tp == curtab)
+ curtabidx = nr;
+
+ BTab* tab = tabLine->TabAt(nr);
+
+ if (tab == NULL) {
+ tab = new VimTabLine::VimTab();
+ tabLine->AddTab(NULL, tab);
+ }
+
+ get_tabline_label(tp, FALSE);
+ tab->SetLabel((const char*)NameBuff);
+ tabLine->Invalidate();
+ }
+
+ /* Remove any old labels. */
+ while (nr < tabLine->CountTabs())
+ tabLine->RemoveTab(nr);
+
+ if(tabLine->Selection() != curtabidx)
+ tabLine->Select(curtabidx);
+
+ gui.vimWindow->Unlock();
+}
+
+/*
+ * Set the current tab to "nr". First tab is 1.
+ */
+ void
+gui_mch_set_curtab(int nr)
+{
+ VimTabLine *tabLine = gui.vimForm->TabLine();
+ if(tabLine == NULL)
+ return;
+
+ gui.vimWindow->Lock();
+
+ if(tabLine->Selection() != nr -1)
+ tabLine->Select(nr -1);
+
+ gui.vimWindow->Unlock();
+}
+
+#endif //FEAT_GUI_TABLINE
diff --git a/src/gui_haiku.h b/src/gui_haiku.h
new file mode 100644
index 0000000..414d127
--- /dev/null
+++ b/src/gui_haiku.h
@@ -0,0 +1,51 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Olaf "Rhialto" Seibert
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * Haiku GUI.
+ *
+ * Based on "GUI support for the Buzzword Enhanced Operating System for PPC."
+ *
+ */
+
+/*
+ * This file must be acceptable both as C and C++.
+ * The BeOS API is defined in terms of C++, but some classes
+ * should be somewhat known in the common C code.
+ */
+
+/* System classes */
+
+struct BMenu;
+struct BMenuItem;
+struct BPictureButton;
+
+/* Our own Vim-related classes */
+
+struct VimApp;
+struct VimFormView;
+struct VimTextAreaView;
+struct VimWindow;
+struct VimScrollBar;
+
+/* Locking functions */
+
+extern int vim_lock_screen();
+extern void vim_unlock_screen();
+
+#ifndef __cplusplus
+
+typedef struct BMenu BMenu;
+typedef struct BMenuItem BMenuItem;
+typedef struct BPictureButton BPictureButton;
+typedef struct VimWindow VimWindow;
+typedef struct VimFormView VimFormView;
+typedef struct VimTextAreaView VimTextAreaView;
+typedef struct VimApp VimApp;
+typedef struct VimScrollBar VimScrollBar;
+
+#endif
diff --git a/src/misc1.c b/src/misc1.c
index 6bf7d75..420553f 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -14,6 +14,10 @@
#include "vim.h"
#include "version.h"
+#if defined(__HAIKU__)
+#include <storage/FindDirectory.h>
+#endif
+
static char_u *vim_version_dir(char_u *vimdir);
static char_u *remove_tail(char_u *p, char_u *pend, char_u *name);
#if defined(FEAT_CMDL_COMPL)
@@ -4214,7 +4218,16 @@ vim_getenv(char_u *name, int *mustfree)
vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
if (!vimruntime && STRCMP(name, "VIM") != 0)
- return NULL;
+#if defined(__HAIKU__)
+ // special handling for user settings directory...
+ if(STRCMP(name, "BE_USER_SETTINGS") == 0) {
+ static char userSettingsPath[MAXPATHL] = {0};
+ if(B_OK == find_directory(B_USER_SETTINGS_DIRECTORY, 0,
+ false, userSettingsPath, MAXPATHL))
+ return userSettingsPath;
+ } else
+#endif
+ return NULL;
/*
* When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM.
diff --git a/src/normal.c b/src/normal.c
index 99ced41..7717ca6 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2642,13 +2642,14 @@ do_mouse(
if (!is_click)
return FALSE;
#endif
-#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
if (is_click || is_drag)
return FALSE;
#endif
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
- || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
+ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \
+ || defined(FEAT_GUI_HAIKU)
if (gui.in_use)
{
jump_flags = 0;
diff --git a/src/option.h b/src/option.h
index 13acabf..5d9bc4a 100644
--- a/src/option.h
+++ b/src/option.h
@@ -10,6 +10,8 @@
* option.h: definition of global variables for settable options
*/
+#ifndef _OPTION_H_
+#define _OPTION_H_
/*
* Default values for 'errorformat'.
* The "%f|%l| %m" one is used for when the contents of the quickfix window is
@@ -1185,5 +1187,7 @@ enum
, WV_COUNT /* must be the last one */
};
+#endif //_OPTION_H_
+
/* Value for b_p_ul indicating the global value must be used. */
#define NO_LOCAL_UNDOLEVEL -123456
diff --git a/src/os_haiku.h b/src/os_haiku.h
new file mode 100644
index 0000000..c9bfe75
--- /dev/null
+++ b/src/os_haiku.h
@@ -0,0 +1,29 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Haiku port by Siarzhuk Zharski
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * os_haiku.h
+ */
+
+#define USE_TERM_CONSOLE
+
+#define USR_VIM_DIR "$BE_USER_SETTINGS/vim"
+
+#define USR_EXRC_FILE USR_VIM_DIR "/exrc"
+#define USR_VIMRC_FILE USR_VIM_DIR "/vimrc"
+#define USR_GVIMRC_FILE USR_VIM_DIR "/gvimrc"
+#define VIMINFO_FILE USR_VIM_DIR "/viminfo"
+
+#ifdef RUNTIME_GLOBAL
+# define DFLT_RUNTIMEPATH USR_VIM_DIR "/vimfiles," RUNTIME_GLOBAL \
+ ",$VIMRUNTIME," RUNTIME_GLOBAL "/after," USR_VIM_DIR "/vimfiles/after"
+#else
+# define DFLT_RUNTIMEPATH USR_VIM_DIR "/vimfiles," "$VIM/vimfiles" \
+ ",$VIMRUNTIME," "$VIM/vimfiles/after," USR_VIM_DIR "/vimfiles/after"
+#endif
diff --git a/src/os_haiku.rdef b/src/os_haiku.rdef
new file mode 100644
index 0000000..215269e
--- /dev/null
+++ b/src/os_haiku.rdef
@@ -0,0 +1,143 @@
+/*
+ * os_haiku.rdef
+ */
+
+resource app_signature "application/x-vnd.Haiku-Vim-7";
+
+resource app_version {
+ major = 7,
+ middle = 4,
+ minor = 0,
+
+ variety = B_APPV_FINAL,
+ internal = 0,
+
+ short_info = "VIM Editor",
+ long_info = "VI Improved Editor by Bram Moolenaar et al."
+};
+
+resource app_flags B_MULTIPLE_LAUNCH;
+
+resource file_types message {
+ "types" = "text",
+ "types" = "text/plain",
+ "types" = "text/x-source-code",
+ "types" = "text/x-patch",
+ "types" = "text/html",
+ "types" = "text/xml",
+ "types" = "text/x-makefile",
+ "types" = "text/x-jamfile"
+};
+
+resource vector_icon {
+ $"6E636966050501020006023B8CFD3CB8E4BF59B63E2F604BACDB47A13E00FFFF"
+ $"FFFF909DA702000603BAF8BA3CE3F6BF8EB9BDA8484BC75C4AEA1200C1C7CC79"
+ $"D9E0E5FFC1C7CC020006020000003DC000C000000000004C000049FFFF00B3FF"
+ $"B3FF026C52020006023BD04F3BD04FBED4133ED4134B6000462FB00053AB53FF"
+ $"007F00060618FFFCFFFF63FF282528252725262726262627262B262B262C282D"
+ $"272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA2659315ABA26595E"
+ $"2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A254A254925482748"
+ $"264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D3E2B3E2C3E2B3E"
+ $"273E273E263C253D253C250618FFFCFFFF63FF28252825272526272626262726"
+ $"2B262B262C282D272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA26"
+ $"59315ABA26595E2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A25"
+ $"4A254925482748264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D"
+ $"3E2B3E2C3E2B3E273E273E263C253D253C250A08BEA359BE3D593C5A415AC03B"
+ $"59BFD559434C404C06218A88888888C83E3F02484CC1D359C16D445A49C36B59"
+ $"C305C3CA50C5C8C50359C49D4C5A51C69B59C635C6FA50C8F8C83359C7CD545A"
+ $"59C9CB59C965CA6B4DCA6B4DCA804C5A4C584C584C574CC86D4DC8D34DC86D4D"
+ $"C73B524C534C524C504C504C4F4CC53D4DC5A34DC53D4DC40B4B4C0608EBECC0"
+ $"B64AC0B64AC11C4AC13349C14848C0F847C15E47C0F847C092C01648C02C47C0"
+ $"1648C00149C0504ABFEA4AC0504A0A04405E5E40402222400A0A000105180015"
+ $"01178600040A0001051815FF01178400040A030105000A0401051001157C0004"
+ $"0A000100381D1F001501178600040A000100381D1F15FF01178300040A010101"
+ $"201D1F0A020101301D1F01157E00040A0003020304381D1F15FF01178400040A"
+ $"0203020304281D1F15FF"
+};
+
+resource(1, "builtin-tools") #'PNG ' array {
+ $"89504E470D0A1A0A0000000D494844520000022E0000001208030000004BB3A5"
+ $"1200000300504C5445000000800000008000808000000080800080008080C0C0"
+ $"C0C0DCC0A6CAF0402000602000802000A02000C02000E0200000400020400040"
+ $"4000604000804000A04000C04000E04000006000206000406000606000806000"
+ $"A06000C06000E06000008000208000408000608000808000A08000C08000E080"
+ $"0000A00020A00040A00060A00080A000A0A000C0A000E0A00000C00020C00040"
+ $"C00060C00080C000A0C000C0C000E0C00000E00020E00040E00060E00080E000"
+ $"A0E000C0E000E0E000000040200040400040600040800040A00040C00040E000"
+ $"40002040202040402040602040802040A02040C02040E0204000404020404040"
+ $"4040604040804040A04040C04040E04040006040206040406040606040806040"
+ $"A06040C06040E06040008040208040408040608040808040A08040C08040E080"
+ $"4000A04020A04040A04060A04080A040A0A040C0A040E0A04000C04020C04040"
+ $"C04060C04080C040A0C040C0C040E0C04000E04020E04040E04060E04080E040"
+ $"A0E040C0E040E0E040000080200080400080600080800080A00080C00080E000"
+ $"80002080202080402080602080802080A02080C02080E0208000408020408040"
+ $"4080604080804080A04080C04080E04080006080206080406080606080806080"
+ $"A06080C06080E06080008080208080408080608080808080A08080C08080E080"
+ $"8000A08020A08040A08060A08080A080A0A080C0A080E0A08000C08020C08040"
+ $"C08060C08080C080A0C080C0C080E0C08000E08020E08040E08060E08080E080"
+ $"A0E080C0E080E0E0800000C02000C04000C06000C08000C0A000C0C000C0E000"
+ $"C00020C02020C04020C06020C08020C0A020C0C020C0E020C00040C02040C040"
+ $"40C06040C08040C0A040C0C040C0E040C00060C02060C04060C06060C08060C0"
+ $"A060C0C060C0E060C00080C02080C04080C06080C08080C0A080C0C080C0E080"
+ $"C000A0C020A0C040A0C060A0C080A0C0A0A0C0C0A0C0E0A0C000C0C020C0C040"
+ $"C0C060C0C080C0C0A0C0C0FFFBF0A0A0A4808080FF000000FF00FFFF000000FF"
+ $"FF00FF00FFFFFFFFFF58D234440000000874524E53FFFFFFFFFFFFFF00DE83BD"
+ $"59000000097048597300000B1200000B1201D2DD7EFC0000070D494441546881"
+ $"DD994B6E23390C86695880F6BDCD19BCCD3AD7CA7DB4CD197C965EE7044619D0"
+ $"F0299192AA5C9907D018762776D12A3DA8AF7E520E64B382FFB792FF004BCD4E"
+ $"DF02C1DC0717347779C3FFDB8D5F43A3705900FE8838FCDB868119C3F3E32EDA"
+ $"BB5A1897CA916A1B566CA49DED7865B2E3E930FC6397A9AAEDE232F10409EA37"
+ $"5B851A70793C020BB70C1B8CB4C436057EFFF6BCACE0BD0CAF75159D21567B6D"
+ $"B2BB9EC73AF7E89C21013E3EF03F1A4CD339BDA77E390523594BE549EA7E55DD"
+ $"E8793B68FEF332D4D3BD72BFE1B2D68D19171A87861F37ADB4163A3FEB87E6A7"
+ $"06411B06146E37D8B60D6E9E176C121A212D81976930BAE5C231A657895D5B80"
+ $"8735AE6BD5068729057FCC318FB5183DC682BB8924AC4D5AB456557F9771D647"
+ $"066E0B378A6491FD65381017DDB2793BD2674A9F64E14950CF67DFD8941D3D5D"
+ $"37DA62B1BB1B9ADFE4452BA3B3C41649D58BE6B77E58065C36B3EEC26C856D7A"
+ $"3E2A332ECFA73E3BBD53EE955F5BB8F939B3F85B749D2DDA003A0A5E546B392D"
+ $"6CE11962C1FD4412D6664C01702B990E4FA5C6591F18F4CDF1913475B1597975"
+ $"498A4BB3B632E7EA7B5F5C2E620A83C4C0ED2AFB7BBD4268157191693455129A"
+ $"BF6BD329C265918F461496EAF23219E5E7B3549977BF036FE1DFEDE9ACB2E7FB"
+ $"819736D9B76152F8C7B6B95E5AE06DA99327C682FBF9289E04B46B306D2519AB"
+ $"6480361D9A8ABDC0F291ABFE8271F916D9A849D505432FEA42D3E4965E5D1C2E"
+ $"B486CE463247C025E54159436982B898395C26759970A9BE9386CB948FC64473"
+ $"A676912AC06DFA53E5A51753C0A4D08F17730E6A734C81F7C94853BC3C8AF44B"
+ $"79A9974B5C18EE6573795C86041E49405ACAE68CC72168AEF9FAF686BF4D5DDC"
+ $"74CB98902AB8D7EA70112E0ACE076B1776DEFB7EA4BBE1B2509784893799BCA4"
+ $"76ED71416971BBCEEA623DF1B21197DB50D2840662853E2A2E19E95C2C6883BA"
+ $"A4B6DB63EDB23A19C536BCBF5E5ECAF329F2D22704C221DEE670113016C540DD"
+ $"C18576B7B0BA202CC2CB85B410F9B085F1D5E3228F00F45880CC221891A04EA1"
+ $"E55B7F181705081B15F12C71A9DC41FBC454489B414F4685D0D80A4E3F3E1789"
+ $"9FFA1D7521509ABCC89BF439E2E28B9BA82E0D97F844AD6A17E969D09F1E3448"
+ $"699EA2B0100FC9793C44E7E1B02DA50BA6A3E621655179E9B858FD32D1E11C75"
+ $"74B567B0CB0AC55B4EA37425106AFDEC1D35F2A1692DF24224E8BBB221840117"
+ $"038871F9DEC385122A83AF2E914B6B06E06B17C605E70F776760B8B45A32292E"
+ $"76D01E710907F0E1F4B4A72ECEE3594D417103762C223D688A4B5497391F9CF0"
+ $"80E1622393B290C0607CF2A1BA4CB84CAE6E8A4B257929242EF4CEE078F48599"
+ $"E712F900417117976DC3021AA9907F084703E885BA48426D5955E432F78B880B"
+ $"DD8AFEFB7BB32B182EDD64844299A74CB8D0C1903ED13594A1D47DA12E34B8B7"
+ $"D223E28F0249C5A5056DA52EAEA7AF2FEEE88C87BEA42364DCC83D40D97059D5"
+ $"2E7BC9A8F62D51EBC9A8B2C0DB01C9E8E80BEB7213F880F032E18240081C1D17"
+ $"03E8585D72FE91BA6805E6707987515D4CE9932F598637EECCC7B8F8134D5DA9"
+ $"8BC7E5F1F86A56DCF13AE022EAD282C6B844010CDC15DAFD331EE5C51FA5537D"
+ $"3C727E704A7A3ED9B53A198DA56E0FEB949F7AA92B0072F552A463CA8C7D6156"
+ $"BB0C7CF00E1EE0029BA41E4D47C8E9E6D5E5089755ED62CDD6B80CF21270F9F5"
+ $"ABE3C2E7202970F3E8695B2CEAD28AD81D7571C9E8FEF5B5C4C59BA94B0B9AE0"
+ $"1204D075F478281CAF3DB9A5A3968D522DC8CB0379C1B4C4BCACBF77C9FE201D"
+ $"4F46D666719016846C9D720CF234C8C968E443867BDBC1C578E927A306D0212E"
+ $"35984D09DCC54B5CDEF770E95FB3B883B439CCD3BE7751DD61D3A3D89EBAECE0"
+ $"32ABCB58EA46010C1D8D70EC7A7AADDB78C1D9154E095E5D2EFAAA87AAF990CC"
+ $"59B9D95E1BE0546747EA6CDFBB381AD2E4E158D02ADFDE022F0E17C9A81E5703"
+ $"E8B07681F12EF9C85D2C71C130BAEF78F670B1435083A37DABDB1D599391952F"
+ $"14BA78F0E1DD7500ADE73CE1A20F00DE2B995652909F22DC7B2784C2394FE6BF"
+ $"01683A0237985717AC5D742297A02E1185D196B8F0BBFE374DB730A561F6F458"
+ $"445E3C2E8155C65501A24612D60997D55DAE3399EF1A9769C7965B2867A0E2E2"
+ $"A31E7759F41835B4E9C7A71120F0EA02E51017BA45FF3253665C5C19AB70BCF6"
+ $"642D5B2423411F8C6B97868B8D9E5BED326AB84637E032B5E94A648AED17C634"
+ $"CC1E178B7D5C661302A891ECBE4E07E6591FD81A9781B3A5A339E749F94BFF32"
+ $"75AED701A01D71099DF832450BF94900492EBA3109273CD9FE02C03909FA6024"
+ $"912D194D339C0EC9D6CCAD7AD166F2C485312E93671150B617B88C8D86DC731A"
+ $"1767E7EEF90FEC3599BB77B416E3EAE7689CF114DBE3E262B898CB34FECE845E"
+ $"4CFAEF79764372DC201F65AC97B792C14FE6F387DBB4F83918273C6E9B866FD9"
+ $"FF17F6CF36F92F1B9E631E8B8F3FBC0000000049454E44AE426082"
+};
diff --git a/src/os_unix.c b/src/os_unix.c
index 0569184..d79b846 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -2186,7 +2186,7 @@ mch_settitle(char_u *title, char_u *icon)
if (get_x11_windis() == OK)
type = 1;
#else
-# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
+# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
if (gui.in_use)
type = 1;
# endif
@@ -2214,7 +2214,7 @@ mch_settitle(char_u *title, char_u *icon)
# endif
set_x11_title(title); /* x11 */
#endif
-#if defined(FEAT_GUI_GTK) \
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)\
|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
else
gui_mch_settitle(title, icon);
@@ -4321,7 +4321,7 @@ mch_call_shell(
{
SIGSET_DECL(curset)
-# ifdef __BEOS__
+# if defined(__BEOS__) && USE_THREAD_FOR_INPUT_WITH_TIMEOUT
beos_cleanup_read_thread();
# endif
diff --git a/src/os_unix.h b/src/os_unix.h
index 1070746..f8dd8bb 100644
--- a/src/os_unix.h
+++ b/src/os_unix.h
@@ -368,6 +368,8 @@ typedef struct dsc$descriptor DESC;
#define DFLT_ERRORFILE "errors.err"
+#ifndef DFLT_RUNTIMEPATH
+
#ifdef VMS
# define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after"
#else
@@ -378,6 +380,8 @@ typedef struct dsc$descriptor DESC;
# endif
#endif
+#endif
+
#ifdef VMS
# ifndef VAX
# define VMS_TEMPNAM /* to fix default .LIS extension */
diff --git a/src/po/zh_CN.cp936.po b/src/po/zh_CN.cp936.po
index 36c7b97..185aae5 100644
--- a/src/po/zh_CN.cp936.po
+++ b/src/po/zh_CN.cp936.po
@@ -2896,7 +2896,7 @@ msgid "--remote <files>\tEdit <files> in a Vim server if possible"
msgstr "--remote <files>\t<><74><EFBFBD>п<EFBFBD><D0BF>ܣ<EFBFBD><DCA3><EFBFBD> Vim <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<CFB1>ļ<EFBFBD> <files>"
msgid "--remote-silent <files> Same, don't complain if there is no server"
-msgstr "--remote-silent <files> ͬ<>ϣ<EFBFBD><CFA3>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Թ"
+msgstr "--remote-silent <files> ͬ<>ϣ<EFBFBD><CFA3>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Թ"
msgid ""
"--remote-wait <files> As --remote but wait for files to have been edited"
diff --git a/src/proto.h b/src/proto.h
index 8cfdb12..69fe8d3 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -236,6 +236,9 @@ extern char_u *vimpty_getenv(const char_u *string); /* from pty.c */
extern char *vim_SelFile(Widget toplevel, char *prompt, char *init_path, int (*show_entry)(), int x, int y, guicolor_T fg, guicolor_T bg, guicolor_T scroll_fg, guicolor_T scroll_bg);
# endif
# endif
+# ifdef FEAT_GUI_HAIKU
+# include "gui_haiku.pro"
+# endif
# ifdef FEAT_GUI_MAC
# include "gui_mac.pro"
# endif
diff --git a/src/proto/gui_haiku.pro b/src/proto/gui_haiku.pro
new file mode 100644
index 0000000..deb412b
--- /dev/null
+++ b/src/proto/gui_haiku.pro
@@ -0,0 +1,92 @@
+/* gui_haiku.cc - hand crafted */
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int vim_exitcode));
+int gui_mch_init_check __ARGS((void));
+void gui_mch_flush __ARGS((void));
+
+void gui_mch_new_colors __ARGS((void));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_sp_color __ARGS((guicolor_T color));
+/*long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));*/
+guicolor_T gui_mch_get_rgb(guicolor_T pixel);
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_set_font __ARGS((GuiFont font));
+int gui_mch_init_font __ARGS((char_u* font_name, int fontset));
+void gui_mch_free_font __ARGS((GuiFont font));
+char_u* gui_mch_get_fontname __ARGS((GuiFont font, char_u *name));
+
+void gui_mch_set_winpos __ARGS((int x, int y));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_shellsize __ARGS((int w, int h, int m_w, int m_h, int b_w, int b_h, int d));
+void gui_mch_get_screen_dimensions __ARGS((int* screen_w, int* screen_h));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T* sb, int flag));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb,int val, int size, int max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T* sb));
+
+void gui_mch_set_blinking __ARGS((long waittime, long on, long off));
+void gui_mch_stop_blink __ARGS(());
+void gui_mch_start_blink __ARGS(());
+
+int gui_mch_adjust_charheight __ARGS(());
+void gui_mch_draw_string __ARGS((int row, int col, char_u* s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u* name));
+void gui_mch_beep __ARGS(());
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS(());
+void gui_mch_set_foreground __ARGS(());
+void gui_mch_settitle __ARGS((char_u* title, char_u* icon));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS(());
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS(());
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+
+void gui_mch_getmouse __ARGS((int *x, int *y));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_mousehide __ARGS((int hide));
+
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_add_menu __ARGS((vimmenu_T* menu, int idx));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS(());
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+
+char_u* gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u* message, char_u *buttons, int dfltbutton, char_u* textfield, int ex_cmd));
+
+void im_set_position __ARGS((int row, int col));
+void im_set_active __ARGS((int activate));
+int im_get_status __ARGS(());
+
+void gui_mch_show_toolbar __ARGS((int showit));
+void gui_mch_set_toolbar_pos __ARGS((int x, int y, int w, int h));
+
+void gui_mch_show_tabline __ARGS((int showit));
+void gui_mch_set_tabline_pos __ARGS((int x, int y, int w, int h));
+int gui_mch_showing_tabline __ARGS((void));
+void gui_mch_update_tabline __ARGS((void));
+void gui_mch_set_curtab __ARGS((int nr));
+// char_u *gui_mch_font_dialog __ARGS((char_u *oldval));
diff --git a/src/pty.c b/src/pty.c
index c07256f..fdd4572 100644
--- a/src/pty.c
+++ b/src/pty.c
@@ -348,7 +348,7 @@ OpenPTY(char **ttyn)
static char PtyProto[] = "/dev/ptym/ptyXY";
static char TtyProto[] = "/dev/pty/ttyXY";
# else
-# ifdef __BEOS__
+# if defined(__BEOS__) || defined(__HAIKU__)
static char PtyProto[] = "/dev/pt/XY";
static char TtyProto[] = "/dev/tt/XY";
# else
diff --git a/src/screen.c b/src/screen.c
index 78f89eb..0b64a17 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -89,6 +89,15 @@
#include "vim.h"
+#ifdef __HAIKU__
+// FIXME!!!
+ int
+gui_mch_is_blink_off(void)
+{
+ return FALSE;
+}
+#endif
+
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
@@ -8571,6 +8580,10 @@ retry:
win_new_shellsize(); /* fit the windows in the new sized shell */
+#ifdef FEAT_GUI_HAIKU
+ vim_lock_screen(); /* be safe, put it here */
+#endif
+
comp_col(); /* recompute columns for shown command and ruler */
/*
@@ -8814,6 +8827,10 @@ give_up:
}
#endif
+#ifdef FEAT_GUI_HAIKU
+ vim_unlock_screen();
+#endif
+
entered = FALSE;
--RedrawingDisabled;
@@ -9672,6 +9689,10 @@ screen_ins_lines(
clip_scroll_selection(-line_count);
#endif
+#ifdef FEAT_GUI_HAIKU
+ vim_lock_screen();
+#endif
+
#ifdef FEAT_GUI
/* Don't update the GUI cursor here, ScreenLines[] is invalid until the
* scrolling is actually carried out. */
@@ -9724,6 +9745,10 @@ screen_ins_lines(
}
}
+#ifdef FEAT_GUI_HAIKU
+ vim_unlock_screen();
+#endif
+
screen_stop_highlight();
windgoto(cursor_row, 0);
@@ -9893,6 +9918,10 @@ screen_del_lines(
clip_scroll_selection(line_count);
#endif
+#ifdef FEAT_GUI_HAIKU
+ vim_lock_screen();
+#endif
+
#ifdef FEAT_GUI
/* Don't update the GUI cursor here, ScreenLines[] is invalid until the
* scrolling is actually carried out. */
@@ -9953,6 +9982,10 @@ screen_del_lines(
}
}
+#ifdef FEAT_GUI_HAIKU
+ vim_unlock_screen();
+#endif
+
screen_stop_highlight();
#ifdef FEAT_WINDOWS
diff --git a/src/structs.h b/src/structs.h
index 7a4d7fb..3f7b68f 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3029,6 +3029,13 @@ struct VimMenu
HMENU submenu_id; /* If this is submenu, add children here */
HWND tearoff_handle; /* hWnd of tearoff if created */
#endif
+#if FEAT_GUI_HAIKU
+ BMenuItem *id; /* Id of menu item */
+ BMenu *submenu_id; /* If this is submenu, add children here */
+# ifdef FEAT_TOOLBAR
+ BPictureButton *button;
+# endif
+#endif
#ifdef FEAT_GUI_MAC
/* MenuHandle id; */
/* short index; */ /* the item index within the father menu */
diff --git a/src/term.c b/src/term.c
index a9c2c57..e9c2311 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1314,6 +1314,11 @@ termgui_mch_get_rgb(guicolor_T color)
# define DEFAULT_TERM (char_u *)"beos-ansi"
#endif
+#ifdef __HAIKU__
+# undef DEFAULT_TERM
+# define DEFAULT_TERM (char_u *)"xterm"
+#endif
+
#ifndef DEFAULT_TERM
# define DEFAULT_TERM (char_u *)"dumb"
#endif
diff --git a/src/ui.c b/src/ui.c
index ad29190..9de4d2e 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -3122,7 +3122,7 @@ mouse_find_win(int *rowp, int *colp UNUSED)
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
- || defined(FEAT_GUI_PHOTON) || defined(PROTO)
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_HAIKU) || defined(PROTO)
/*
* Translate window coordinates to buffer position without any side effects
*/
diff --git a/src/version.c b/src/version.c
index d25b91f..6570d33 100644
--- a/src/version.c
+++ b/src/version.c
@@ -1143,6 +1143,9 @@ list_version(void)
MSG_PUTS(_("with X11-Athena GUI."));
# endif
# else
+# ifdef FEAT_GUI_HAIKU
+ MSG_PUTS(_("with Haiku GUI."));
+# else
# ifdef FEAT_GUI_PHOTON
MSG_PUTS(_("with Photon GUI."));
# else
@@ -1160,6 +1163,7 @@ list_version(void)
# endif
# endif
# endif
+# endif
# endif
# endif
# endif
diff --git a/src/vim.h b/src/vim.h
index 5946d63..fe13146 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -115,6 +115,7 @@
|| defined(FEAT_GUI_ATHENA) \
|| defined(FEAT_GUI_MAC) \
|| defined(FEAT_GUI_W32) \
+ || defined(FEAT_GUI_HAIKU) \
|| defined(FEAT_GUI_PHOTON)
# define FEAT_GUI_ENABLED /* also defined with NO_X11_INCLUDES */
# if !defined(FEAT_GUI) && !defined(NO_X11_INCLUDES)
@@ -255,6 +256,11 @@
# include "os_beos.h"
#endif
+#ifdef __HAIKU__
+# include "os_haiku.h"
+# define __ARGS(x) x
+#endif
+
#if (defined(UNIX) || defined(VMS)) \
&& (!defined(MACOS_X) || defined(HAVE_CONFIG_H))
# include "os_unix.h" /* bring lots of system header files */
@@ -2080,6 +2086,9 @@ typedef struct VimClipboard
int_u format; /* Vim's own special clipboard format */
int_u format_raw; /* Vim's raw text clipboard format */
# endif
+# ifdef FEAT_GUI_HAIKU
+ /* no clipboard at the moment. TODO???? */
+# endif
} VimClipboard;
#else
typedef int VimClipboard; /* This is required for the prototypes. */
@@ -2119,7 +2128,7 @@ typedef enum
* been seen at that stage. But it must be before globals.h, where error_ga
* is declared. */
#if !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_X11) \
- && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO)
+ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) && !defined(FEAT_GUI_HAIKU)
# define mch_errmsg(str) fprintf(stderr, "%s", (str))
# define display_errors() fflush(stderr)
# define mch_msg(str) printf("%s", (str))
--
2.10.0