mirror of
https://github.com/yann64/haikuports.git
synced 2026-04-10 13:50:08 +02:00
6961 lines
183 KiB
Plaintext
6961 lines
183 KiB
Plaintext
From cffc035f69371fff65bc4c956b5191baa92e95bc Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Zolt=C3=A1n=20Mizsei?= <zmizsei@extrowerk.com>
|
|
Date: Fri, 21 Jul 2017 17:03:57 +0200
|
|
Subject: Applied patchset
|
|
|
|
|
|
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
|
|
index edc12ef..56404e5 100644
|
|
--- a/runtime/doc/eval.txt
|
|
+++ b/runtime/doc/eval.txt
|
|
@@ -8850,12 +8850,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 df02c5c..99d90ed 100644
|
|
--- a/runtime/doc/gui.txt
|
|
+++ b/runtime/doc/gui.txt
|
|
@@ -101,6 +101,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 2be3ced..a687a9f 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 56697d5..5cc2dc2 100644
|
|
--- a/runtime/doc/options.txt
|
|
+++ b/runtime/doc/options.txt
|
|
@@ -3875,7 +3875,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
|
|
@@ -6257,7 +6257,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
|
|
@@ -7715,6 +7720,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..ebcb247
|
|
--- /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/config/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 0ea6ea2..da21a1f 100644
|
|
--- a/runtime/doc/starting.txt
|
|
+++ b/runtime/doc/starting.txt
|
|
@@ -798,6 +798,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.
|
|
@@ -844,6 +845,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
|
|
@@ -955,6 +957,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 1099b81..6a08ccc 100644
|
|
--- a/runtime/doc/tags
|
|
+++ b/runtime/doc/tags
|
|
@@ -4619,6 +4619,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*
|
|
@@ -6699,6 +6700,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()*
|
|
@@ -7810,6 +7825,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 a68ebe5..10a6b4a 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 06204bd..8a5f726 100644
|
|
--- a/src/Makefile
|
|
+++ b/src/Makefile
|
|
@@ -1373,6 +1373,23 @@ CARBONGUI_BUNDLE = gui_bundle
|
|
APPDIR = $(VIMNAME).app
|
|
CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET)
|
|
|
|
+### Haiku GUI
|
|
+HAIKUGUI_SRC = gui.c gui_haiku.cc
|
|
+HAIKUGUI_OBJ = objects/gui.o objects/gui_haiku.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))))), 5)
|
|
+HAIKUGUI_LIBS1 += -lsupc++ -lstdc++
|
|
+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
|
|
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
|
|
@@ -3090,6 +3107,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
|
|
|
|
@@ -3213,6 +3233,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
|
|
|
|
@@ -3415,6 +3438,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.ac b/src/configure.ac
|
|
index 76714b1..d7bcd38 100644
|
|
--- a/src/configure.ac
|
|
+++ b/src/configure.ac
|
|
@@ -118,6 +118,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)
|
|
@@ -1987,7 +1993,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([
|
|
@@ -2224,11 +2234,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.
|
|
@@ -2243,10 +2253,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)
|
|
@@ -2410,6 +2433,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
|
|
|
|
@@ -3025,6 +3049,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 55d2295..d031a72 100644
|
|
--- a/src/evalfunc.c
|
|
+++ b/src/evalfunc.c
|
|
@@ -5539,6 +5539,9 @@ f_has(typval_T *argvars, typval_T *rettv)
|
|
#ifdef __BEOS__
|
|
"beos",
|
|
#endif
|
|
+#ifdef __HAIKU__
|
|
+ "haiku",
|
|
+#endif
|
|
#ifdef MACOS
|
|
"mac",
|
|
#endif
|
|
@@ -5716,6 +5719,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 b4351b2..2e6ce28 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
|
|
@@ -1837,6 +1840,8 @@ write_viminfo(char_u *file, int forceit)
|
|
int hidden = FALSE;
|
|
#endif
|
|
|
|
+char* filenameSeparatorPos;
|
|
+
|
|
if (no_viminfo())
|
|
return;
|
|
|
|
@@ -1844,6 +1849,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 e2dfd92..917975d 100644
|
|
--- a/src/ex_docmd.c
|
|
+++ b/src/ex_docmd.c
|
|
@@ -7880,6 +7880,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 37e4d31..adf7c39 100644
|
|
--- a/src/feature.h
|
|
+++ b/src/feature.h
|
|
@@ -635,6 +635,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
|
|
@@ -740,7 +748,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
|
|
|
|
@@ -756,6 +765,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
|
|
@@ -767,7 +777,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
|
|
@@ -791,6 +802,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
|
|
@@ -808,7 +820,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 fe91062..3e96a7d 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)
|
|
@@ -1355,10 +1355,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
|
|
@@ -1366,6 +1366,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;
|
|
|
|
@@ -1437,7 +1444,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
|
|
@@ -1480,6 +1487,10 @@ again:
|
|
new_pixel_height = 0;
|
|
busy = TRUE;
|
|
|
|
+ #ifdef FEAT_GUI_HAIKU
|
|
+ vim_lock_screen();
|
|
+ #endif
|
|
+
|
|
/* Flush pending output before redrawing */
|
|
out_flush();
|
|
|
|
@@ -1502,6 +1513,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)
|
|
@@ -4236,9 +4251,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
|
|
@@ -4247,7 +4262,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
|
|
@@ -4958,9 +4973,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 91b4c22..0c352ef 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
|
|
|
|
@@ -197,6 +201,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
|
|
@@ -410,7 +417,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
|
|
|
|
@@ -419,7 +426,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
|
|
|
|
@@ -440,6 +447,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..ef0ec7d
|
|
--- /dev/null
|
|
+++ b/src/gui_haiku.cc
|
|
@@ -0,0 +1,5292 @@
|
|
+/* 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, curwin->w_width, 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 > curwin->w_width)
|
|
+ {
|
|
+ pos.y++;
|
|
+ pos.x = 0;
|
|
+ }
|
|
+ if (sel_start<=i && i<sel_end)
|
|
+ {
|
|
+ SetLowColor(r_highlight);
|
|
+ IMData.location = ConvertToScreen(
|
|
+ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ SetLowColor(b_highlight);
|
|
+ }
|
|
+ r.Set(FILL_X(pos.x), FILL_Y(IMData.row + pos.y),
|
|
+ FILL_X(pos.x + cn) - PEN_WIDTH,
|
|
+ FILL_Y(IMData.row + pos.y + 1) - PEN_WIDTH);
|
|
+ FillRect(r, B_SOLID_LOW);
|
|
+ where.Set(TEXT_X(pos.x), TEXT_Y(IMData.row + pos.y));
|
|
+ DrawString((s+i), clen, where);
|
|
+ pos.x += cn;
|
|
+ }
|
|
+ IMData.count = (int)pos.y;
|
|
+
|
|
+ SetHighColor(hcolor);
|
|
+ SetLowColor(lcolor);
|
|
+}
|
|
+#endif
|
|
+/* ---------------- VimScrollBar ---------------- */
|
|
+
|
|
+/* BUG: XXX
|
|
+ * It seems that BScrollBar determine their direction not from
|
|
+ * "posture" but from if they are "tall" or "wide" in shape...
|
|
+ *
|
|
+ * Also, place them out of sight, because Vim enables them before
|
|
+ * they are positioned.
|
|
+ */
|
|
+VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
|
|
+ BScrollBar(posture == B_HORIZONTAL ? BRect(-100,-100,-10,-90) :
|
|
+ BRect(-100,-100,-90,-10),
|
|
+ "vim scrollbar", (BView *)NULL,
|
|
+ 0.0, 10.0, posture),
|
|
+ ignoreValue(-1),
|
|
+ scrollEventCount(0)
|
|
+{
|
|
+ gsb = g;
|
|
+ SetResizingMode(B_FOLLOW_NONE);
|
|
+}
|
|
+
|
|
+VimScrollBar::~VimScrollBar()
|
|
+{
|
|
+}
|
|
+
|
|
+ void
|
|
+VimScrollBar::ValueChanged(float newValue)
|
|
+{
|
|
+ if (ignoreValue >= 0.0 && newValue == ignoreValue) {
|
|
+ ignoreValue = -1;
|
|
+ return;
|
|
+ }
|
|
+ ignoreValue = -1;
|
|
+ /*
|
|
+ * We want to throttle the amount of scroll messages generated.
|
|
+ * Normally I presume you won't get a new message before we've
|
|
+ * handled the previous one, but because we're passing them on this
|
|
+ * happens very quickly. So instead we keep a counter of how many
|
|
+ * scroll events there are (or will be) in the VDCMP, and the
|
|
+ * throttling happens at the receiving end.
|
|
+ */
|
|
+ atomic_add(&scrollEventCount, 1);
|
|
+
|
|
+ struct VimScrollBarMsg sm;
|
|
+
|
|
+ sm.sb = this;
|
|
+ sm.value = (long) newValue;
|
|
+ sm.stillDragging = TRUE;
|
|
+
|
|
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
|
|
+
|
|
+ // calls gui_drag_scrollbar(sb, newValue, TRUE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * When the mouse goes up, report that scrolling has stopped.
|
|
+ * MouseUp() is NOT called when the mouse-up occurs outside
|
|
+ * the window, even though the thumb does move while the mouse
|
|
+ * is outside... This has some funny effects... XXX
|
|
+ * So we do special processing when the window de/activates.
|
|
+ */
|
|
+ void
|
|
+VimScrollBar::MouseUp(BPoint where)
|
|
+{
|
|
+ //BMessage *m = Window()->CurrentMessage();
|
|
+ //m->PrintToStream();
|
|
+
|
|
+ atomic_add(&scrollEventCount, 1);
|
|
+
|
|
+ struct VimScrollBarMsg sm;
|
|
+
|
|
+ sm.sb = this;
|
|
+ sm.value = (long) Value();
|
|
+ sm.stillDragging = FALSE;
|
|
+
|
|
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
|
|
+
|
|
+ // calls gui_drag_scrollbar(sb, newValue, FALSE);
|
|
+
|
|
+ Inherited::MouseUp(where);
|
|
+}
|
|
+
|
|
+ void
|
|
+VimScrollBar::SetValue(float newValue)
|
|
+{
|
|
+ if (newValue == Value())
|
|
+ return;
|
|
+
|
|
+ ignoreValue = newValue;
|
|
+ Inherited::SetValue(newValue);
|
|
+}
|
|
+
|
|
+/* ---------------- VimFont ---------------- */
|
|
+
|
|
+VimFont::VimFont(): BFont()
|
|
+{
|
|
+ init();
|
|
+}
|
|
+
|
|
+VimFont::VimFont(const VimFont *rhs): BFont(rhs)
|
|
+{
|
|
+ init();
|
|
+}
|
|
+
|
|
+VimFont::VimFont(const BFont *rhs): BFont(rhs)
|
|
+{
|
|
+ init();
|
|
+}
|
|
+
|
|
+VimFont::VimFont(const VimFont &rhs): BFont(rhs)
|
|
+{
|
|
+ init();
|
|
+}
|
|
+
|
|
+VimFont::~VimFont()
|
|
+{
|
|
+}
|
|
+
|
|
+ void
|
|
+VimFont::init()
|
|
+{
|
|
+ next = NULL;
|
|
+ refcount = 1;
|
|
+ name = NULL;
|
|
+}
|
|
+
|
|
+/* ---------------- VimDialog ---------------- */
|
|
+
|
|
+#if defined(FEAT_GUI_DIALOG)
|
|
+
|
|
+const unsigned int kVimDialogButtonMsg = 'VMDB';
|
|
+const unsigned int kVimDialogIconStripeWidth = 30;
|
|
+const unsigned int kVimDialogButtonsSpacingX = 9;
|
|
+const unsigned int kVimDialogButtonsSpacingY = 4;
|
|
+const unsigned int kVimDialogSpacingX = 6;
|
|
+const unsigned int kVimDialogSpacingY = 10;
|
|
+const unsigned int kVimDialogMinimalWidth = 310;
|
|
+const unsigned int kVimDialogMinimalHeight = 75;
|
|
+const BRect kDefaultRect =
|
|
+BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight);
|
|
+
|
|
+VimDialog::VimDialog(int type, const char *title, const char *message,
|
|
+ const char *buttons, int dfltbutton, const char *textfield, int ex_cmd)
|
|
+: BWindow(kDefaultRect, title, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
|
+ B_NOT_CLOSABLE | B_NOT_RESIZABLE |
|
|
+ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
|
+ , fDialogSem(-1)
|
|
+ , fDialogValue(dfltbutton)
|
|
+ , fMessageView(NULL)
|
|
+ , fInputControl(NULL)
|
|
+ , fInputValue(textfield)
|
|
+{
|
|
+ // master view
|
|
+ VimDialog::View* view = new VimDialog::View(Bounds());
|
|
+ if(view == NULL)
|
|
+ return;
|
|
+
|
|
+ if(title == NULL)
|
|
+ SetTitle("Vim " VIM_VERSION_MEDIUM);
|
|
+
|
|
+ AddChild(view);
|
|
+
|
|
+ // icon
|
|
+ view->InitIcon(type);
|
|
+
|
|
+ // buttons
|
|
+ int32 which = 1;
|
|
+ float maxButtonWidth = 0;
|
|
+ float maxButtonHeight = 0;
|
|
+ float buttonsWidth = 0;
|
|
+ float buttonsHeight = 0;
|
|
+ BString strButtons(buttons);
|
|
+ strButtons.RemoveAll("&");
|
|
+ do {
|
|
+ int32 end = strButtons.FindFirst('\n');
|
|
+ if(end != B_ERROR)
|
|
+ strButtons.SetByteAt(end, '\0');
|
|
+
|
|
+ BButton *button = _CreateButton(which++, strButtons.String());
|
|
+ view->AddChild(button);
|
|
+ fButtonsList.AddItem(button);
|
|
+
|
|
+ maxButtonWidth = max_c(maxButtonWidth, button->Bounds().Width());
|
|
+ maxButtonHeight = max_c(maxButtonHeight, button->Bounds().Height());
|
|
+ buttonsWidth += button->Bounds().Width();
|
|
+ buttonsHeight += button->Bounds().Height();
|
|
+
|
|
+ if(end == B_ERROR)
|
|
+ break;
|
|
+
|
|
+ strButtons.Remove(0, end + 1);
|
|
+ } while(true);
|
|
+
|
|
+ int32 buttonsCount = fButtonsList.CountItems();
|
|
+ buttonsWidth += kVimDialogButtonsSpacingX * (buttonsCount - 1);
|
|
+ buttonsHeight += kVimDialogButtonsSpacingY * (buttonsCount - 1);
|
|
+ float dialogWidth = buttonsWidth + kVimDialogIconStripeWidth +
|
|
+ kVimDialogSpacingX * 2;
|
|
+ float dialogHeight = maxButtonHeight + kVimDialogSpacingY * 3;
|
|
+
|
|
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
|
|
+ bool vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL) ||
|
|
+ dialogWidth >= gui.vimWindow->Bounds().Width();
|
|
+ if(vertical) {
|
|
+ dialogWidth -= buttonsWidth;
|
|
+ dialogWidth += maxButtonWidth;
|
|
+ dialogHeight -= maxButtonHeight;
|
|
+ dialogHeight += buttonsHeight;
|
|
+ }
|
|
+
|
|
+ dialogWidth = max_c(dialogWidth, kVimDialogMinimalWidth);
|
|
+
|
|
+ // message view
|
|
+ BRect rect(0, 0, dialogWidth, 0);
|
|
+ rect.left += kVimDialogIconStripeWidth + 16 + kVimDialogSpacingX;
|
|
+ rect.top += kVimDialogSpacingY;
|
|
+ rect.right -= kVimDialogSpacingX;
|
|
+ rect.bottom = rect.top;
|
|
+ fMessageView = new BTextView(rect, "_tv_", rect.OffsetByCopy(B_ORIGIN),
|
|
+ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
|
|
+
|
|
+ fMessageView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
+ rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
|
+ fMessageView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
|
|
+ fMessageView->SetText(message);
|
|
+ fMessageView->MakeEditable(false);
|
|
+ fMessageView->MakeSelectable(false);
|
|
+ fMessageView->SetWordWrap(true);
|
|
+ AddChild(fMessageView);
|
|
+
|
|
+ float messageHeight = fMessageView->TextHeight(0, fMessageView->CountLines());
|
|
+ fMessageView->ResizeBy(0, messageHeight);
|
|
+ fMessageView->SetTextRect(BRect(0, 0, rect.Width(), messageHeight));
|
|
+
|
|
+ dialogHeight += messageHeight;
|
|
+
|
|
+ // input view
|
|
+ if(fInputValue != NULL) {
|
|
+ rect.top =
|
|
+ rect.bottom += messageHeight + kVimDialogSpacingY;
|
|
+ fInputControl = new BTextControl(rect, "_iv_", NULL, fInputValue, NULL,
|
|
+ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED);
|
|
+ fInputControl->TextView()->SetText(fInputValue);
|
|
+ fInputControl->TextView()->SetWordWrap(false);
|
|
+ AddChild(fInputControl);
|
|
+
|
|
+ float width = 0.f, height = 0.f;
|
|
+ fInputControl->GetPreferredSize(&width, &height);
|
|
+ fInputControl->MakeFocus(true);
|
|
+
|
|
+ dialogHeight += height + kVimDialogSpacingY * 1.5;
|
|
+ }
|
|
+
|
|
+ dialogHeight = max_c(dialogHeight, kVimDialogMinimalHeight);
|
|
+
|
|
+ ResizeTo(dialogWidth, dialogHeight);
|
|
+ MoveTo((gui.vimWindow->Bounds().Width() - dialogWidth) / 2,
|
|
+ (gui.vimWindow->Bounds().Height() - dialogHeight) / 2);
|
|
+
|
|
+ // adjust layout of buttons
|
|
+ float buttonWidth = max_c(maxButtonWidth, rect.Width() * 0.66);
|
|
+ BPoint origin(dialogWidth, dialogHeight);
|
|
+ origin.x -= kVimDialogSpacingX + (vertical ? buttonWidth : buttonsWidth);
|
|
+ origin.y -= kVimDialogSpacingY + (vertical ? buttonsHeight : maxButtonHeight);
|
|
+
|
|
+ for(int32 i = 0 ; i < buttonsCount; i++) {
|
|
+ BButton *button = (BButton*)fButtonsList.ItemAt(i);
|
|
+ button->MoveTo(origin);
|
|
+ if(vertical) {
|
|
+ origin.y += button->Frame().Height() + kVimDialogButtonsSpacingY;
|
|
+ button->ResizeTo(buttonWidth, button->Frame().Height());
|
|
+ } else
|
|
+ origin.x += button->Frame().Width() + kVimDialogButtonsSpacingX;
|
|
+
|
|
+ if(dfltbutton == i + 1) {
|
|
+ button->MakeDefault(true);
|
|
+ button->MakeFocus(fInputControl == NULL);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+VimDialog::~VimDialog()
|
|
+{
|
|
+ if(fDialogSem > B_OK)
|
|
+ delete_sem(fDialogSem);
|
|
+}
|
|
+
|
|
+ int
|
|
+VimDialog::Go()
|
|
+{
|
|
+ fDialogSem = create_sem(0, "VimDialogSem");
|
|
+ if(fDialogSem < B_OK) {
|
|
+ Quit();
|
|
+ return fDialogValue;
|
|
+ }
|
|
+
|
|
+ Show();
|
|
+
|
|
+ while(acquire_sem(fDialogSem) == B_INTERRUPTED);
|
|
+
|
|
+ int retValue = fDialogValue;
|
|
+ if(fInputValue != NULL)
|
|
+ vim_strncpy((char_u*)fInputValue, (char_u*)fInputControl->Text(), IOSIZE - 1);
|
|
+
|
|
+ if(Lock())
|
|
+ Quit();
|
|
+
|
|
+ return retValue;
|
|
+}
|
|
+
|
|
+void VimDialog::MessageReceived(BMessage *msg)
|
|
+{
|
|
+ int32 which = 0;
|
|
+ if(msg->what != kVimDialogButtonMsg ||
|
|
+ msg->FindInt32("which", &which) != B_OK)
|
|
+ return BWindow::MessageReceived(msg);
|
|
+
|
|
+ fDialogValue = which;
|
|
+ delete_sem(fDialogSem);
|
|
+ fDialogSem = -1;
|
|
+}
|
|
+
|
|
+BButton* VimDialog::_CreateButton(int32 which, const char* label)
|
|
+{
|
|
+ BMessage *message = new BMessage(kVimDialogButtonMsg);
|
|
+ message->AddInt32("which", which);
|
|
+
|
|
+ BRect rect(0, 0, 0, 0);
|
|
+ BString name;
|
|
+ name << "_b" << which << "_";
|
|
+
|
|
+ BButton* button = new BButton(rect, name.String(), label, message,
|
|
+ B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
|
+
|
|
+ float width = 0.f, height = 0.f;
|
|
+ button->GetPreferredSize(&width, &height);
|
|
+ button->ResizeTo(width, height);
|
|
+
|
|
+ return button;
|
|
+}
|
|
+
|
|
+VimDialog::View::View(BRect frame)
|
|
+ : BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
|
|
+ fIconBitmap(NULL)
|
|
+{
|
|
+ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
+}
|
|
+
|
|
+VimDialog::View::~View()
|
|
+{
|
|
+ delete fIconBitmap;
|
|
+}
|
|
+
|
|
+void VimDialog::View::Draw(BRect updateRect)
|
|
+{
|
|
+ BRect stripeRect = Bounds();
|
|
+ stripeRect.right = kVimDialogIconStripeWidth;
|
|
+ SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
|
+ FillRect(stripeRect);
|
|
+
|
|
+ if(fIconBitmap == NULL)
|
|
+ return;
|
|
+
|
|
+ SetDrawingMode(B_OP_ALPHA);
|
|
+ SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
|
+ DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
|
|
+}
|
|
+
|
|
+void VimDialog::View::InitIcon(int32 type)
|
|
+{
|
|
+ if(type == VIM_GENERIC)
|
|
+ return;
|
|
+
|
|
+ BPath path;
|
|
+ status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
|
|
+ if(status != B_OK) {
|
|
+ fprintf(stderr, "Cannot retrieve app info:%s\n", strerror(status));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ path.Append("app_server");
|
|
+
|
|
+ BFile file(path.Path(), O_RDONLY);
|
|
+ if(file.InitCheck() != B_OK) {
|
|
+ fprintf(stderr, "App file assignment failed:%s\n",
|
|
+ strerror(file.InitCheck()));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ BResources resources(&file);
|
|
+ if(resources.InitCheck() != B_OK) {
|
|
+ fprintf(stderr, "App server resources assignment failed:%s\n",
|
|
+ strerror(resources.InitCheck()));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ const char *name = "";
|
|
+ switch(type) {
|
|
+ case VIM_ERROR: name = "stop"; break;
|
|
+ case VIM_WARNING: name = "warn"; break;
|
|
+ case VIM_INFO: name = "info"; break;
|
|
+ case VIM_QUESTION: name = "idea"; break;
|
|
+ default: return;
|
|
+ }
|
|
+
|
|
+ int32 iconSize = 32;
|
|
+ fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
|
|
+ if(fIconBitmap == NULL || fIconBitmap->InitCheck() != B_OK) {
|
|
+ fprintf(stderr, "Icon bitmap allocation failed:%s\n",
|
|
+ (fIconBitmap == NULL) ? "null" : strerror(fIconBitmap->InitCheck()));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ size_t size = 0;
|
|
+ const uint8* iconData = NULL;
|
|
+ // try vector icon first?
|
|
+ iconData = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, name, &size);
|
|
+ if(iconData != NULL && BIconUtils::GetVectorIcon(iconData, size, fIconBitmap) == B_OK)
|
|
+ return;
|
|
+
|
|
+ // try bitmap icon now
|
|
+ iconData = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE, name, &size);
|
|
+ if(iconData == NULL) {
|
|
+ fprintf(stderr, "Bitmap icon resource not found\n");
|
|
+ delete fIconBitmap;
|
|
+ fIconBitmap = NULL;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if(fIconBitmap->ColorSpace() != B_CMAP8)
|
|
+ BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
|
|
+}
|
|
+
|
|
+const unsigned int kVimDialogOKButtonMsg = 'FDOK';
|
|
+const unsigned int kVimDialogCancelButtonMsg = 'FDCN';
|
|
+const unsigned int kVimDialogSizeInputMsg = 'SICH';
|
|
+const unsigned int kVimDialogFamilySelectMsg = 'MSFM';
|
|
+const unsigned int kVimDialogStyleSelectMsg = 'MSST';
|
|
+const unsigned int kVimDialogSizeSelectMsg = 'MSSZ';
|
|
+
|
|
+VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size)
|
|
+: BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
|
+ B_NOT_CLOSABLE | B_NOT_RESIZABLE |
|
|
+ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
|
+ , fStatus(B_NO_INIT)
|
|
+ , fDialogSem(-1)
|
|
+ , fDialogValue(false)
|
|
+ , fFamily(family)
|
|
+ , fStyle(style)
|
|
+ , fSize(size)
|
|
+ , fFontSize(*size)
|
|
+ , fPreview(0)
|
|
+ , fFamiliesList(0)
|
|
+ , fStylesList(0)
|
|
+ , fSizesList(0)
|
|
+ , fSizesInput(0)
|
|
+{
|
|
+ strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH);
|
|
+ strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH);
|
|
+
|
|
+ // "client" area view
|
|
+ BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
|
|
+ B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED,
|
|
+ B_PLAIN_BORDER);
|
|
+ AddChild(clientBox);
|
|
+
|
|
+ // client view
|
|
+ BRect RC = clientBox->Bounds();
|
|
+ RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY);
|
|
+ BRect rc(RC.LeftTop(), RC.LeftTop());
|
|
+
|
|
+ // at first create all controls
|
|
+ fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono");
|
|
+ clientBox->AddChild(fPreview);
|
|
+
|
|
+ BBox* boxDivider = new BBox(rc, B_EMPTY_STRING,
|
|
+ B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER);
|
|
+ clientBox->AddChild(boxDivider);
|
|
+
|
|
+ BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:");
|
|
+ clientBox->AddChild(labelFamily);
|
|
+ labelFamily->ResizeToPreferred();
|
|
+
|
|
+ BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:");
|
|
+ clientBox->AddChild(labelStyle);
|
|
+ labelStyle->ResizeToPreferred();
|
|
+
|
|
+ BStringView *labelSize = new BStringView(rc, "labelSize", "Size:");
|
|
+ clientBox->AddChild(labelSize);
|
|
+ labelSize->ResizeToPreferred();
|
|
+
|
|
+ fFamiliesList = new BListView(rc, "listFamily",
|
|
+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
+ BScrollView *scrollFamilies = new BScrollView("scrollFamily",
|
|
+ fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
+ clientBox->AddChild(scrollFamilies);
|
|
+
|
|
+ fStylesList= new BListView(rc, "listStyles",
|
|
+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
+ BScrollView *scrollStyles = new BScrollView("scrollStyle",
|
|
+ fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
+ clientBox->AddChild(scrollStyles);
|
|
+
|
|
+ fSizesInput = new BTextControl(rc, "inputSize", NULL, "???",
|
|
+ new BMessage(kVimDialogSizeInputMsg));
|
|
+ clientBox->AddChild(fSizesInput);
|
|
+ fSizesInput->ResizeToPreferred();
|
|
+
|
|
+ fSizesList = new BListView(rc, "listSizes",
|
|
+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
+ BScrollView *scrollSizes = new BScrollView("scrollSize",
|
|
+ fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
+ clientBox->AddChild(scrollSizes);
|
|
+
|
|
+ BButton *buttonOK = new BButton(rc, "buttonOK", "OK",
|
|
+ new BMessage(kVimDialogOKButtonMsg));
|
|
+ clientBox->AddChild(buttonOK);
|
|
+ buttonOK->ResizeToPreferred();
|
|
+
|
|
+ BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel",
|
|
+ new BMessage(kVimDialogCancelButtonMsg));
|
|
+ clientBox->AddChild(buttonCancel);
|
|
+ buttonCancel->ResizeToPreferred();
|
|
+
|
|
+ // layout controls
|
|
+ float lineHeight = labelFamily->Bounds().Height();
|
|
+ float previewHeight = lineHeight * 3;
|
|
+ float offsetYLabels = previewHeight + kVimDialogSpacingY;
|
|
+ float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2;
|
|
+ float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2;
|
|
+ float listsHeight = lineHeight * 9;
|
|
+ float offsetYButtons = offsetYLists + listsHeight + kVimDialogSpacingY;
|
|
+ float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height();
|
|
+ float familiesWidth = labelFamily->Bounds().Width() * 5;
|
|
+ float offsetXStyles = familiesWidth + kVimDialogSpacingX;
|
|
+ float stylesWidth = labelStyle->Bounds().Width() * 4;
|
|
+ float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX;
|
|
+ float sizesWidth = labelSize->Bounds().Width() * 2;
|
|
+ float maxControlsWidth = offsetXSizes + sizesWidth;
|
|
+
|
|
+ ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2,
|
|
+ maxControlsHeight + kVimDialogSpacingY * 2);
|
|
+
|
|
+ BRect rcVim = gui.vimWindow->Frame();
|
|
+ MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2,
|
|
+ rcVim.top + (rcVim.Height() - Frame().Height()) / 2);
|
|
+
|
|
+ fPreview->ResizeTo(maxControlsWidth, previewHeight);
|
|
+ fPreview->SetAlignment(B_ALIGN_CENTER);
|
|
+
|
|
+ boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2);
|
|
+ boxDivider->ResizeTo(maxControlsWidth, 1.f);
|
|
+
|
|
+ labelFamily->MoveBy(0.f, offsetYLabels);
|
|
+ labelStyle->MoveBy(offsetXStyles, offsetYLabels);
|
|
+ labelSize->MoveBy(offsetXSizes, offsetYLabels);
|
|
+
|
|
+ // text control alignment issues
|
|
+ float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
|
|
+ float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
|
|
+
|
|
+ scrollFamilies->MoveBy(0.f, offsetYLists);
|
|
+ scrollStyles->MoveBy(offsetXStyles, offsetYLists);
|
|
+ fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2);
|
|
+ scrollSizes->MoveBy(offsetXSizes, offsetYSizes);
|
|
+
|
|
+ fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER);
|
|
+
|
|
+ scrollFamilies->ResizeTo(familiesWidth, listsHeight);
|
|
+ scrollStyles->ResizeTo(stylesWidth, listsHeight);
|
|
+ fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height());
|
|
+ scrollSizes->ResizeTo(sizesWidth,
|
|
+ listsHeight - (offsetYSizes - offsetYLists));
|
|
+
|
|
+ buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons);
|
|
+ buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width()
|
|
+ - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons);
|
|
+
|
|
+ // fill lists
|
|
+ int selIndex = -1;
|
|
+ int count = count_font_families();
|
|
+ for (int i = 0; i < count; i++) {
|
|
+ font_family family;
|
|
+ if (get_font_family(i, &family ) == B_OK) {
|
|
+ fFamiliesList->AddItem(new BStringItem((const char*)family));
|
|
+ if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0)
|
|
+ selIndex = i;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (selIndex >= 0) {
|
|
+ fFamiliesList->Select(selIndex);
|
|
+ fFamiliesList->ScrollToSelection();
|
|
+ }
|
|
+
|
|
+ _UpdateFontStyles();
|
|
+
|
|
+ selIndex = -1;
|
|
+ for (int size = 8, index = 0; size <= 18; size++, index++) {
|
|
+ BString str;
|
|
+ str << size;
|
|
+ fSizesList->AddItem(new BStringItem(str));
|
|
+ if (size == fFontSize)
|
|
+ selIndex = index;
|
|
+
|
|
+ }
|
|
+
|
|
+ if (selIndex >= 0) {
|
|
+ fSizesList->Select(selIndex);
|
|
+ fSizesList->ScrollToSelection();
|
|
+ }
|
|
+
|
|
+ fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg));
|
|
+ fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg));
|
|
+ fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg));
|
|
+ fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg));
|
|
+
|
|
+ _UpdateSizeInputPreview();
|
|
+ _UpdateFontPreview();
|
|
+
|
|
+ fStatus = B_OK;
|
|
+}
|
|
+
|
|
+VimSelectFontDialog::~VimSelectFontDialog()
|
|
+{
|
|
+ _CleanList(fFamiliesList);
|
|
+ _CleanList(fStylesList);
|
|
+ _CleanList(fSizesList);
|
|
+
|
|
+ if (fDialogSem > B_OK)
|
|
+ delete_sem(fDialogSem);
|
|
+}
|
|
+
|
|
+ void
|
|
+VimSelectFontDialog::_CleanList(BListView* list)
|
|
+{
|
|
+ while(0 < list->CountItems())
|
|
+ delete (dynamic_cast<BStringItem*>(list->RemoveItem((int32)0)));
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimSelectFontDialog::Go()
|
|
+{
|
|
+ if (fStatus != B_OK) {
|
|
+ Quit();
|
|
+ return NOFONT;
|
|
+ }
|
|
+
|
|
+ fDialogSem = create_sem(0, "VimFontSelectDialogSem");
|
|
+ if(fDialogSem < B_OK) {
|
|
+ Quit();
|
|
+ return fDialogValue;
|
|
+ }
|
|
+
|
|
+ Show();
|
|
+
|
|
+ while(acquire_sem(fDialogSem) == B_INTERRUPTED);
|
|
+
|
|
+ bool retValue = fDialogValue;
|
|
+
|
|
+ if(Lock())
|
|
+ Quit();
|
|
+
|
|
+ return retValue;
|
|
+}
|
|
+
|
|
+
|
|
+void VimSelectFontDialog::_UpdateFontStyles()
|
|
+{
|
|
+ _CleanList(fStylesList);
|
|
+
|
|
+ int32 selIndex = -1;
|
|
+ int32 count = count_font_styles(fFontFamily);
|
|
+ for (int32 i = 0; i < count; i++) {
|
|
+ font_style style;
|
|
+ uint32 flags = 0;
|
|
+ if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) {
|
|
+ fStylesList->AddItem(new BStringItem((const char*)style));
|
|
+ if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0)
|
|
+ selIndex = i;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (selIndex >= 0) {
|
|
+ fStylesList->Select(selIndex);
|
|
+ fStylesList->ScrollToSelection();
|
|
+ } else
|
|
+ fStylesList->Select(0);
|
|
+}
|
|
+
|
|
+
|
|
+void VimSelectFontDialog::_UpdateSizeInputPreview()
|
|
+{
|
|
+ char buf[10] = {0};
|
|
+ vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize);
|
|
+ fSizesInput->SetText(buf);
|
|
+}
|
|
+
|
|
+
|
|
+void VimSelectFontDialog::_UpdateFontPreview()
|
|
+{
|
|
+ BFont font;
|
|
+ fPreview->GetFont(&font);
|
|
+ font.SetSize(fFontSize);
|
|
+ font.SetFamilyAndStyle(fFontFamily, fFontStyle);
|
|
+ fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
|
|
+
|
|
+ BString str;
|
|
+ str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt.";
|
|
+ fPreview->SetText(str);
|
|
+}
|
|
+
|
|
+
|
|
+ bool
|
|
+VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize)
|
|
+{
|
|
+ int32 index = list->CurrentSelection();
|
|
+ if (index < 0)
|
|
+ return false;
|
|
+ BStringItem* item = (BStringItem*)list->ItemAt(index);
|
|
+ if (item == NULL)
|
|
+ return false;
|
|
+ strncpy(text, item->Text(), textSize);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
+void VimSelectFontDialog::MessageReceived(BMessage *msg)
|
|
+{
|
|
+ switch (msg->what) {
|
|
+ case kVimDialogOKButtonMsg:
|
|
+ strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH);
|
|
+ strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH);
|
|
+ *fSize = fFontSize;
|
|
+ fDialogValue = true;
|
|
+ case kVimDialogCancelButtonMsg:
|
|
+ delete_sem(fDialogSem);
|
|
+ fDialogSem = -1;
|
|
+ return;
|
|
+ case B_KEY_UP:
|
|
+ {
|
|
+ int32 key = 0;
|
|
+ if (msg->FindInt32("raw_char", &key) == B_OK
|
|
+ && key == B_ESCAPE) {
|
|
+ delete_sem(fDialogSem);
|
|
+ fDialogSem = -1;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case kVimDialogFamilySelectMsg:
|
|
+ if (_UpdateFromListItem(fFamiliesList,
|
|
+ fFontFamily, B_FONT_FAMILY_LENGTH)) {
|
|
+ _UpdateFontStyles();
|
|
+ _UpdateFontPreview();
|
|
+ }
|
|
+ break;
|
|
+ case kVimDialogStyleSelectMsg:
|
|
+ if (_UpdateFromListItem(fStylesList,
|
|
+ fFontStyle, B_FONT_STYLE_LENGTH))
|
|
+ _UpdateFontPreview();
|
|
+ break;
|
|
+ case kVimDialogSizeSelectMsg:
|
|
+ {
|
|
+ char buf[10] = {0};
|
|
+ if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) {
|
|
+ float size = atof(buf);
|
|
+ if (size > 0.f) {
|
|
+ fFontSize = size;
|
|
+ _UpdateSizeInputPreview();
|
|
+ _UpdateFontPreview();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case kVimDialogSizeInputMsg:
|
|
+ {
|
|
+ float size = atof(fSizesInput->Text());
|
|
+ if (size > 0.f) {
|
|
+ fFontSize = size;
|
|
+ _UpdateFontPreview();
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return BWindow::MessageReceived(msg);
|
|
+}
|
|
+
|
|
+#endif /* FEAT_GUI_DIALOG */
|
|
+
|
|
+#ifdef FEAT_TOOLBAR
|
|
+
|
|
+// some forward declaration required by toolbar functions...
|
|
+static BMessage * MenuMessage(vimmenu_T *menu);
|
|
+
|
|
+VimToolbar::VimToolbar(BRect frame, const char *name) :
|
|
+ BBox(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER)
|
|
+{
|
|
+}
|
|
+
|
|
+VimToolbar::~VimToolbar()
|
|
+{
|
|
+ int32 count = fButtonsList.CountItems();
|
|
+ for(int32 i = 0; i < count; i++)
|
|
+ delete (BPictureButton*)fButtonsList.ItemAt(i);
|
|
+ fButtonsList.MakeEmpty();
|
|
+
|
|
+ delete normalButtonsBitmap;
|
|
+ delete grayedButtonsBitmap;
|
|
+ normalButtonsBitmap = NULL;
|
|
+ grayedButtonsBitmap = NULL;
|
|
+}
|
|
+
|
|
+ void
|
|
+VimToolbar::AttachedToWindow()
|
|
+{
|
|
+ BBox::AttachedToWindow();
|
|
+
|
|
+ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
+}
|
|
+
|
|
+ float
|
|
+VimToolbar::ToolbarHeight() const
|
|
+{
|
|
+ float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
|
|
+ return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimToolbar::ModifyBitmapToGrayed(BBitmap *bitmap)
|
|
+{
|
|
+ float height = bitmap->Bounds().Height();
|
|
+ float width = bitmap->Bounds().Width();
|
|
+
|
|
+ rgb_color *bits = (rgb_color*)bitmap->Bits();
|
|
+ int32 pixels = bitmap->BitsLength() / 4;
|
|
+ for(int32 i = 0; i < pixels; i++) {
|
|
+ bits[i].red = bits[i].green =
|
|
+ bits[i].blue = ((uint32)bits[i].red + bits[i].green + bits[i].blue) / 3;
|
|
+ bits[i].alpha /= 4;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimToolbar::PrepareButtonBitmaps()
|
|
+{
|
|
+ // first try to load potentially customized $VIRUNTIME/bitmaps/builtin-tools.png
|
|
+ normalButtonsBitmap = LoadVimBitmap("builtin-tools.png");
|
|
+ if(normalButtonsBitmap == NULL)
|
|
+ // customized not found? dig application resources for "builtin-tools" one
|
|
+ normalButtonsBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "builtin-tools");
|
|
+
|
|
+ if(normalButtonsBitmap == NULL)
|
|
+ return false;
|
|
+
|
|
+ BMessage archive;
|
|
+ normalButtonsBitmap->Archive(&archive);
|
|
+
|
|
+ grayedButtonsBitmap = new BBitmap(&archive);
|
|
+ if(grayedButtonsBitmap == NULL)
|
|
+ return false;
|
|
+
|
|
+ // modify grayed bitmap
|
|
+ ModifyBitmapToGrayed(grayedButtonsBitmap);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+BBitmap *VimToolbar::LoadVimBitmap(const char* fileName)
|
|
+{
|
|
+ BBitmap *bitmap = NULL;
|
|
+
|
|
+ int mustfree = 0;
|
|
+ char_u* runtimePath = vim_getenv((char_u*)"VIMRUNTIME", &mustfree);
|
|
+ if(runtimePath != NULL && fileName != NULL) {
|
|
+ BString strPath((char*)runtimePath);
|
|
+ strPath << "/bitmaps/" << fileName;
|
|
+ bitmap = BTranslationUtils::GetBitmap(strPath.String());
|
|
+ }
|
|
+
|
|
+ if(mustfree)
|
|
+ vim_free(runtimePath);
|
|
+
|
|
+ return bitmap;
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimToolbar::GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed)
|
|
+{
|
|
+ float size = bitmapFrom->Bounds().Height() + 1.;
|
|
+
|
|
+ BView view(BRect(0, 0, size, size), "", 0, 0);
|
|
+
|
|
+ AddChild(&view);
|
|
+ view.BeginPicture(pictureTo);
|
|
+
|
|
+ view.SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
+ view.FillRect(view.Bounds());
|
|
+ view.SetDrawingMode(B_OP_OVER);
|
|
+
|
|
+ BRect source(0, 0, size - 1, size - 1);
|
|
+ BRect destination(source);
|
|
+
|
|
+ source.OffsetBy(size * index, 0);
|
|
+ destination.OffsetBy(ButtonMargin, ButtonMargin);
|
|
+
|
|
+ view.DrawBitmap(bitmapFrom, source, destination);
|
|
+
|
|
+ if(pressed) {
|
|
+ rgb_color shineColor = ui_color(B_SHINE_COLOR);
|
|
+ rgb_color shadowColor = ui_color(B_SHADOW_COLOR);
|
|
+ size += ButtonMargin * 2 - 1;
|
|
+ view.BeginLineArray(4);
|
|
+ view.AddLine(BPoint(0, 0), BPoint(size, 0), shadowColor);
|
|
+ view.AddLine(BPoint(size, 0), BPoint(size, size), shineColor);
|
|
+ view.AddLine(BPoint(size, size), BPoint(0, size), shineColor);
|
|
+ view.AddLine(BPoint(0, size), BPoint(0, 0), shadowColor);
|
|
+ view.EndLineArray();
|
|
+ }
|
|
+
|
|
+ view.EndPicture();
|
|
+ RemoveChild(&view);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimToolbar::AddButton(int32 index, vimmenu_T *menu)
|
|
+{
|
|
+ BPictureButton *button = NULL;
|
|
+ if(!menu_is_separator(menu->name)) {
|
|
+ float size = normalButtonsBitmap ?
|
|
+ normalButtonsBitmap->Bounds().Height() + 1. + ButtonMargin * 2 : 18.;
|
|
+ BRect frame(0, 0, size, size);
|
|
+ BPicture pictureOn;
|
|
+ BPicture pictureOff;
|
|
+ BPicture pictureGray;
|
|
+
|
|
+ if(menu->iconfile == NULL && menu->iconidx >= 0 && normalButtonsBitmap) {
|
|
+ GetPictureFromBitmap(&pictureOn, menu->iconidx, normalButtonsBitmap, true);
|
|
+ GetPictureFromBitmap(&pictureOff, menu->iconidx, normalButtonsBitmap, false);
|
|
+ GetPictureFromBitmap(&pictureGray, menu->iconidx, grayedButtonsBitmap, false);
|
|
+ } else {
|
|
+
|
|
+ char_u buffer[MAXPATHL] = {0};
|
|
+ BBitmap *bitmap = NULL;
|
|
+
|
|
+ if(menu->iconfile) {
|
|
+ gui_find_iconfile(menu->iconfile, buffer, (char*)"png");
|
|
+ bitmap = BTranslationUtils::GetBitmap((char*)buffer);
|
|
+ }
|
|
+
|
|
+ if(bitmap == NULL && gui_find_bitmap(menu->name, buffer, (char*)"png") == OK)
|
|
+ bitmap = BTranslationUtils::GetBitmap((char*)buffer);
|
|
+
|
|
+ if(bitmap == NULL)
|
|
+ bitmap = new BBitmap(BRect(0, 0, size, size), B_RGB32);
|
|
+
|
|
+ GetPictureFromBitmap(&pictureOn, 0, bitmap, true);
|
|
+ GetPictureFromBitmap(&pictureOff, 0, bitmap, false);
|
|
+ ModifyBitmapToGrayed(bitmap);
|
|
+ GetPictureFromBitmap(&pictureGray, 0, bitmap, false);
|
|
+
|
|
+ delete bitmap;
|
|
+ }
|
|
+
|
|
+ button = new BPictureButton(frame, (char*)menu->name,
|
|
+ &pictureOff, &pictureOn, MenuMessage(menu));
|
|
+
|
|
+ button->SetDisabledOn(&pictureGray);
|
|
+ button->SetDisabledOff(&pictureGray);
|
|
+
|
|
+ button->SetTarget(gui.vimTextArea);
|
|
+
|
|
+ AddChild(button);
|
|
+
|
|
+ menu->button = button;
|
|
+ }
|
|
+
|
|
+ bool result = fButtonsList.AddItem(button, index);
|
|
+ InvalidateLayout();
|
|
+ return result;
|
|
+}
|
|
+
|
|
+ bool
|
|
+VimToolbar::RemoveButton(vimmenu_T *menu)
|
|
+{
|
|
+ if(menu->button) {
|
|
+ if(fButtonsList.RemoveItem(menu->button)) {
|
|
+ delete menu->button;
|
|
+ menu->button = NULL;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+ 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-8";
|
|
+key_map *keyMap;
|
|
+char *keyMapChars;
|
|
+int main_exitcode = 127;
|
|
+
|
|
+ status_t
|
|
+gui_haiku_process_event(bigtime_t timeout)
|
|
+{
|
|
+ struct VimMsg vm;
|
|
+ int32 what;
|
|
+ ssize_t size;
|
|
+
|
|
+ size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm),
|
|
+ B_TIMEOUT, timeout);
|
|
+
|
|
+ if (size >= 0) {
|
|
+ switch (what) {
|
|
+ case VimMsg::Key:
|
|
+ {
|
|
+ char_u *string = vm.u.Key.chars;
|
|
+ int len = vm.u.Key.length;
|
|
+ if (len == 1 && string[0] == Ctrl_chr('C')) {
|
|
+ trash_input_buf();
|
|
+ got_int = TRUE;
|
|
+ }
|
|
+
|
|
+#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();
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+gui_mch_destroy_scrollbar(
|
|
+ scrollbar_T *sb)
|
|
+{
|
|
+ if (gui.vimWindow->Lock()) {
|
|
+ sb->id->RemoveSelf();
|
|
+ delete sb->id;
|
|
+ gui.vimWindow->Unlock();
|
|
+ }
|
|
+}
|
|
+
|
|
+ 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 f7789ff..1ef3f2e 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)
|
|
@@ -4228,7 +4232,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 d78a53b..2e428d9 100644
|
|
--- a/src/normal.c
|
|
+++ b/src/normal.c
|
|
@@ -2656,13 +2656,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 ecd70dc..87a50c3 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
|
|
@@ -1181,5 +1183,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..bf55aa9
|
|
--- /dev/null
|
|
+++ b/src/os_haiku.rdef
|
|
@@ -0,0 +1,143 @@
|
|
+/*
|
|
+ * os_haiku.rdef
|
|
+ */
|
|
+
|
|
+resource app_signature "application/x-vnd.Haiku-Vim-8";
|
|
+
|
|
+resource app_version {
|
|
+ major = @MAJOR@,
|
|
+ middle = @MIDDLE@,
|
|
+ minor = @MINOR@,
|
|
+
|
|
+ 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 59e5745..9c695b1 100644
|
|
--- a/src/os_unix.c
|
|
+++ b/src/os_unix.c
|
|
@@ -2184,7 +2184,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
|
|
@@ -2212,7 +2212,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);
|
|
@@ -4469,7 +4469,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 695affa..b9bc2e3 100644
|
|
--- a/src/os_unix.h
|
|
+++ b/src/os_unix.h
|
|
@@ -364,6 +364,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
|
|
@@ -374,6 +376,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/osdef1.h.in b/src/osdef1.h.in
|
|
index 5519104..9820c7b 100644
|
|
--- a/src/osdef1.h.in
|
|
+++ b/src/osdef1.h.in
|
|
@@ -66,7 +66,9 @@ extern void memmove(char *, char *, int);
|
|
# endif
|
|
#endif
|
|
/* used inside of FD_ZERO macro: */
|
|
+#ifndef __HAIKU__
|
|
extern void bzero(void *, size_t);
|
|
+#endif
|
|
#ifdef HAVE_SETSID
|
|
extern pid_t setsid(void);
|
|
#endif
|
|
diff --git a/src/proto.h b/src/proto.h
|
|
index 92e3f60..0c91cdb 100644
|
|
--- a/src/proto.h
|
|
+++ b/src/proto.h
|
|
@@ -243,6 +243,9 @@ extern char_u *vimpty_getenv(const char_u *string); /* in misc2.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 151a278..8072499 100644
|
|
--- a/src/pty.c
|
|
+++ b/src/pty.c
|
|
@@ -351,7 +351,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 3e08b60..d7a9df8 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. */
|
|
|
|
@@ -8746,6 +8755,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 */
|
|
|
|
/*
|
|
@@ -8977,6 +8990,10 @@ give_up:
|
|
}
|
|
#endif
|
|
|
|
+#ifdef FEAT_GUI_HAIKU
|
|
+ vim_unlock_screen();
|
|
+#endif
|
|
+
|
|
entered = FALSE;
|
|
--RedrawingDisabled;
|
|
|
|
@@ -9811,6 +9828,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. */
|
|
@@ -9862,6 +9883,10 @@ screen_ins_lines(
|
|
}
|
|
}
|
|
|
|
+#ifdef FEAT_GUI_HAIKU
|
|
+ vim_unlock_screen();
|
|
+#endif
|
|
+
|
|
screen_stop_highlight();
|
|
windgoto(cursor_row, 0);
|
|
if (clear_attr != 0)
|
|
@@ -10027,6 +10052,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. */
|
|
@@ -10086,6 +10115,10 @@ screen_del_lines(
|
|
}
|
|
}
|
|
|
|
+#ifdef FEAT_GUI_HAIKU
|
|
+ vim_unlock_screen();
|
|
+#endif
|
|
+
|
|
if (screen_attr != clear_attr)
|
|
screen_stop_highlight();
|
|
if (clear_attr != 0)
|
|
diff --git a/src/structs.h b/src/structs.h
|
|
index 7b0f70c..ae9865b 100644
|
|
--- a/src/structs.h
|
|
+++ b/src/structs.h
|
|
@@ -3137,6 +3137,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 9925b0a..5254b71 100644
|
|
--- a/src/term.c
|
|
+++ b/src/term.c
|
|
@@ -1354,6 +1354,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 f175e1a..caab0b5 100644
|
|
--- a/src/ui.c
|
|
+++ b/src/ui.c
|
|
@@ -3151,7 +3151,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 8d7a5e5..1619a41 100644
|
|
--- a/src/version.c
|
|
+++ b/src/version.c
|
|
@@ -3400,6 +3400,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
|
|
@@ -3417,6 +3420,7 @@ list_version(void)
|
|
# endif
|
|
# endif
|
|
# endif
|
|
+# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
diff --git a/src/vim.h b/src/vim.h
|
|
index 4567c36..a194194 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 */
|
|
@@ -2077,6 +2083,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. */
|
|
@@ -2117,7 +2126,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.14.2
|
|
|