• R/O
  • SSH

vim: 提交

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

修訂22f0dda71638c77ed958b0c8d5e0766dd6b67b02 (tree)
時間2020-02-27 00:30:04
作者Bram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Log Message

patch 8.2.0320: no Haiku support

Commit: https://github.com/vim/vim/commit/b3f740695a0199d22cd97aee314f06c7ae32d2ea
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Feb 26 16:16:53 2020 +0100

patch 8.2.0320: no Haiku support
Problem: No Haiku support.
Solution: Add support for Haiku. (Emir Sari, closes https://github.com/vim/vim/issues/5605)

Change Summary

差異

diff -r 619eb9bc3249 -r 22f0dda71638 Filelist
--- a/Filelist Wed Feb 26 13:45:07 2020 +0100
+++ b/Filelist Wed Feb 26 16:30:04 2020 +0100
@@ -599,6 +599,14 @@
599599 src/testdir/amiga.vim \
600600 src/xxd/Make_amiga.mak \
601601
602+# source files for Haiku (also in the extra archive)
603+SRC_HAIKU = \
604+ src/os_haiku.h \
605+ src/os_haiku.rdef \
606+ src/gui_haiku.cc \
607+ src/gui_haiku.h \
608+ src/proto/gui_haiku.pro \
609+
602610 # source files for the Mac (also in the extra archive)
603611 SRC_MAC = \
604612 src/INSTALLmac.txt \
@@ -634,13 +642,13 @@
634642 src/proto/gui_photon.pro \
635643 src/proto/os_qnx.pro \
636644
637-
638645 # source files for the extra archive (all sources that are not for Unix)
639646 SRC_EXTRA = \
640647 $(SRC_AMI) \
641648 $(SRC_AMI_DOS) \
642649 $(SRC_DOS) \
643650 $(SRC_DOS_BIN) \
651+ $(SRC_HAIKU) \
644652 $(SRC_MAC) \
645653 $(SRC_QNX) \
646654 $(SRC_VMS) \
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/Makefile
--- a/runtime/doc/Makefile Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/Makefile Wed Feb 26 16:30:04 2020 +0100
@@ -64,6 +64,7 @@
6464 os_amiga.txt \
6565 os_beos.txt \
6666 os_dos.txt \
67+ os_haiku.txt \
6768 os_mac.txt \
6869 os_mint.txt \
6970 os_msdos.txt \
@@ -204,6 +205,7 @@
204205 os_amiga.html \
205206 os_beos.html \
206207 os_dos.html \
208+ os_haiku.html \
207209 os_mac.html \
208210 os_mint.html \
209211 os_msdos.html \
@@ -422,6 +424,9 @@
422424 os_dos.txt:
423425 touch os_dos.txt
424426
427+os_haiku.txt:
428+ touch os_haiku.txt
429+
425430 os_mac.txt:
426431 touch os_mac.txt
427432
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/eval.txt Wed Feb 26 16:30:04 2020 +0100
@@ -10766,12 +10766,14 @@
1076610766 gui_gtk Compiled with GTK+ GUI (any version).
1076710767 gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined).
1076810768 gui_gtk3 Compiled with GTK+ 3 GUI (gui_gtk is also defined).
10769+gui_haiku Compiled with Haiku GUI.
1076910770 gui_mac Compiled with Macintosh GUI.
1077010771 gui_motif Compiled with Motif GUI.
1077110772 gui_photon Compiled with Photon GUI.
1077210773 gui_running Vim is running in the GUI, or it will start soon.
1077310774 gui_win32 Compiled with MS Windows Win32 GUI.
1077410775 gui_win32s idem, and Win32s system being used (Windows 3.1)
10776+haiku Haiku version of Vim.
1077510777 hangul_input Compiled with Hangul input support. |hangul|
1077610778 hpux HP-UX version of Vim.
1077710779 iconv Can use iconv() for conversion.
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/gui.txt
--- a/runtime/doc/gui.txt Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/gui.txt Wed Feb 26 16:30:04 2020 +0100
@@ -99,6 +99,7 @@
9999 or $VIM/_gvimrc
100100 Amiga s:.gvimrc, home:.gvimrc, home:vimfiles:gvimrc
101101 or $VIM/.gvimrc
102+ Haiku $HOME/config/settings/vim/gvimrc
102103
103104 The personal initialization files are searched in the order specified above
104105 and only the first one that is found is read.
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/help.txt
--- a/runtime/doc/help.txt Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/help.txt Wed Feb 26 16:30:04 2020 +0100
@@ -204,6 +204,7 @@
204204 |os_os2.txt| OS/2
205205 |os_qnx.txt| QNX
206206 |os_risc.txt| RISC-OS
207+|os_haiku.txt| Haiku
207208 |os_unix.txt| Unix
208209 |os_vms.txt| VMS
209210 |os_win32.txt| MS-Windows
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/options.txt
--- a/runtime/doc/options.txt Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/options.txt Wed Feb 26 16:30:04 2020 +0100
@@ -3769,7 +3769,7 @@
37693769 'guitablabel' can be used to change the text in the labels.
37703770 When 'e' is missing a non-GUI tab pages line may be used.
37713771 The GUI tabs are only supported on some systems, currently
3772- GTK, Motif, Mac OS/X and MS-Windows.
3772+ GTK, Motif, Mac OS/X, Haiku, and MS-Windows.
37733773 *'go-f'*
37743774 'f' Foreground: Don't use fork() to detach the GUI from the shell
37753775 where it was started. Use this for programs that wait for the
@@ -6207,6 +6207,11 @@
62076207 Macintosh: "$VIM:vimfiles,
62086208 $VIMRUNTIME,
62096209 $VIM:vimfiles:after"
6210+ Haiku: "$BE_USER_SETTINGS/vim,
6211+ $VIM/vimfiles,
6212+ $VIMRUNTIME,
6213+ $VIM/vimfiles/after,
6214+ $BE_USER_SETTINGS/vim/after")
62106215 VMS: "sys$login:vimfiles,
62116216 $VIM/vimfiles,
62126217 $VIMRUNTIME,
@@ -7665,6 +7670,7 @@
76657670 in the GUI: "builtin_gui"
76667671 on Amiga: "amiga"
76677672 on BeOS: "beos-ansi"
7673+ on Haiku: "xterm"
76687674 on Mac: "mac-ansi"
76697675 on MiNT: "vt52"
76707676 on Unix: "ansi"
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/os_haiku.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/doc/os_haiku.txt Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,228 @@
1+*os_haiku.txt* For Vim version 8.2. Last change: 2020 Feb 26
2+
3+
4+ VIM REFERENCE MANUAL by Bram Moolenaar
5+
6+
7+ *Haiku*
8+This file contains the particularities for the Haiku version of Vim. For
9+matters not discussed in this file, Vim behaves very much like the Unix
10+|os_unix.txt| version.
11+
12+Haiku is an open-source operating system inspired by BeOS, that specifically
13+targets personal computing.
14+
15+ 1. General |haiku-general|
16+ 2. Compiling Vim |haiku-compiling|
17+ 3. The Haiku GUI |haiku-gui|
18+ 4. The $VIM directory |haiku-vimdir|
19+ 5. The $BE_USER_SETTINGS
20+ directory |haiku-user-settings-dir|
21+ 6. Drag & Drop |haiku-dragndrop|
22+ 7. Single Launch vs. Multiple
23+ Launch |haiku-launch|
24+ 8. Fonts |haiku-fonts|
25+ 9. The meta key modifier |haiku-meta|
26+10. Mouse key mappings |haiku-mouse|
27+11. Color names |haiku-colors|
28+12. Credits |haiku-support-credits|
29+13. Bugs & things To Do |haiku-bugs|
30+
31+
32+1. General *haiku-general*
33+
34+The default syntax highlighting mostly works with different foreground colors
35+to highlight items. This works best if you set your Terminal window to a
36+darkish background and light letters. Some middle-grey background (for
37+instance (r,g,b)=(168,168,168)) with black letters also works nicely.
38+
39+
40+2. Compiling Vim *haiku-compiling*
41+
42+Vim can be compiled using the standard configure/make approach. Running
43+./configure without any arguments or passing --enable-gui=haiku, will compile
44+vim with the Haiku GUI support. Run ./configure --help , to find out other
45+features you can enable/disable.
46+
47+Now you should use "make" to compile Vim, then "make install" to install it.
48+For seamless integration into the Haiku the GUI-less vim binary should be
49+additionally installed over the GUI version. Typical build commands are: >
50+
51+ ./configure --prefix=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY` \
52+ --datarootdir=`finddir B_SYSTEM_NONPACKAGED_DATA_DIRECTORY` \
53+ --mandir=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY`/documentation/man \
54+ make clean
55+ make install
56+
57+ ./configure --prefix=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY` \
58+ --datarootdir=`finddir B_SYSTEM_NONPACKAGED_DATA_DIRECTORY` \
59+ --mandir=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY`/documentation/man \
60+ --disable-gui
61+ make clean
62+ make install
63+
64+
65+3. The Haiku GUI *haiku-gui*
66+
67+Normally Vim starts with the GUI if you start it as gvim or vim -g. The vim
68+version with GUI tries to determine if it was started from the Tracker instead
69+of the Terminal, and if so, uses the GUI anyway. However, the current detection
70+scheme is fooled if you use the command "vim - </dev/null".
71+
72+Stuff that does not work yet:
73+
74+- Mouse up events are not generated when outside the window. This may be a bug in
75+ Haiku. You can notice this when selecting text and moving the cursor outside
76+ the window, then letting go of the mouse button. Another way is when you
77+ drag the scrollbar and do the same thing. Because Vim still thinks you are
78+ still playing with the scrollbar it won't change it itself. I provided a
79+ workaround which kicks in when the window is activated or deactivated (so it
80+ works best with focus- follows-mouse turned on).
81+- The cursor does not flash (very low priority; I'm not sure I even like it
82+ when it flashes)
83+
84+
85+4. The $VIM directory *haiku-vimdir*
86+
87+$VIM is the symbolic name for the place where Vims support files are stored.
88+The default value for $VIM is set at compile time and can be determined with >
89+
90+ :version
91+
92+The normal value is /boot/common/data/vim. If you don't like it you can
93+set the VIM environment variable to override this, or set 'helpfile' in your
94+.vimrc: >
95+
96+ :if version >= 500
97+ : set helpfile=~/vim/runtime/doc/help.txt
98+ : syntax on
99+ :endif
100+
101+
102+5. The $USER_SETTINGS_DIR directory *haiku-user-settings-dir*
103+
104+$USER_SETTINGS_DIR is the symbolic name for the place where Haiku
105+configuration and settings files are stored.
106+
107+The normal value is /boot/home/config/settings.
108+
109+
110+6. Drag & Drop *haiku-dragndrop*
111+
112+You can drop files and directories on either the Vim icon (starts a new Vim
113+session, unless you use the File Types application to set Vim to be "Single
114+Launch") or on the Vim window (starts editing the files). Dropping a folder
115+sets Vim's current working directory. |:cd| |:pwd| If you drop files or
116+folders with either SHIFT key pressed, Vim changes directory to the folder
117+that contains the first item dropped. When starting Vim, there is no need to
118+press shift: Vim behaves as if you do.
119+
120+Files dropped set the current argument list. |argument-list|
121+
122+
123+7. Single Launch vs. Multiple Launch *haiku-launch*
124+
125+As distributed Vim's Application Flags (as seen in the FileTypes preference)
126+are set to Multiple Launch. If you prefer, you can set them to Single Launch
127+instead. Attempts to start a second copy of Vim will cause the first Vim to
128+open the files instead. This works from the Tracker but also from the command
129+line. In the latter case, non-file (option) arguments are not supported.
130+Another drawback of the Single Launch is silent ignore of "Open With ..."
131+requests by vim instance that running as non-GUI application even GUI support
132+was compiled in. Vim instance running with GUI has no such problems.
133+
134+NB: Only the GUI version has a BApplication (and hence Application Flags).
135+This section does not apply to the GUI-less version, should you compile one.
136+
137+
138+8. Fonts *haiku-fonts*
139+
140+Set fonts with >
141+
142+ :set guifont=DejaVu_Sans_Mono/Book/12
143+
144+where the first part is the font family, the second part the style, and the
145+third part the size. You can use underscores instead of spaces in family and
146+style.
147+
148+Best results are obtained with monospaced fonts. Vim attempts to use all
149+fonts in B_FIXED_SPACING mode but apparently this does not work for
150+proportional fonts (despite what the BeBook says).
151+
152+To verify which encodings are supported by the current font give the >
153+
154+ :digraphs
155+
156+command, which lists a bunch of characters with their ISO Latin 1 encoding.
157+If, for instance, there are "box" characters among them, or the last character
158+isn't a dotted-y, then for this font the encoding does not work.
159+
160+If the font you specify is unavailable, you get the system fixed font.
161+
162+GUI Font Selection Dialog is available at giving the >
163+
164+ :set guifont=*
165+
166+command.
167+
168+
169+9. The meta key modifier *haiku-meta*
170+
171+The META key modifier is obtained by the left or right OPTION keys. This is
172+because the ALT (aka COMMAND) keys are not passed to applications.
173+
174+
175+10. Mouse key mappings *haiku-mouse*
176+
177+Vim calls the various mouse buttons LeftMouse, MiddleMouse and RightMouse. If
178+you use the default Mouse preference settings these names indeed correspond to
179+reality. Vim uses this mapping:
180+
181+ Button 1 -> LeftMouse,
182+ Button 2 -> RightMouse,
183+ Button 3 -> MiddleMouse.
184+
185+If your mouse has fewer than 3 buttons you can provide your own mapping from
186+mouse clicks with modifier(s) to other mouse buttons. See the file
187+$VIM/macros/swapmous.vim for an example. |gui-mouse-mapping|
188+
189+
190+11. Color names *haiku-colors*
191+
192+Vim has a number of color names built-in. Additional names are read from the
193+file $VIMRUNTIME/rgb.txt, if present. This file is basically the color
194+database from X. Names used from this file are cached for efficiency.
195+
196+
197+12. GUI Toolbar Images *haiku-toolbar-images*
198+
199+Alternative set of toolbar images should be the PNG image of any height you
200+like. Image width is calculated to contain at least 32 buttons in one-row
201+cells.
202+The image should be stored under the name $VIRUNTIME/bitmaps/builtin-tools.png
203+More info about the buttons assignment are at |builtin-tools|.
204+
205+
206+13. Credits *haiku-support-credits*
207+
208+Haiku port is based on work done for BeOS version by many people
209+ - BeBox GUI support Copyright 1998 by Olaf Seibert;
210+ - Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99;
211+ - Those who contributed, not listed above but not forgotten;
212+ - Haiku support by Siarzhuk Zharski <imker@gmx.li> Apr-Mai 2009.
213+
214+All the changes and patches released under vim-license.
215+
216+Thank you, all!
217+
218+
219+13. Bugs & things To Do *haiku-bugs*
220+
221+The port is under development now and far away from the perfect state. Bug
222+reports, patches and wishes are welcome.
223+
224+
225+ -Siarzhuk Zharski <imker@gmx.li>
226+
227+
228+ vim:tw=78:ts=8:ft=help:norl:
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/starting.txt
--- a/runtime/doc/starting.txt Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/starting.txt Wed Feb 26 16:30:04 2020 +0100
@@ -790,6 +790,7 @@
790790 or $VIM/_vimrc
791791 Amiga s:.vimrc, home:.vimrc, home:vimfiles:vimrc
792792 or $VIM/.vimrc
793+ Haiku $HOME/config/settings/vim/vimrc
793794
794795 The files are searched in the order specified above and only the first
795796 one that is found is read.
@@ -835,6 +836,8 @@
835836 "$HOME/_vimrc" (for Win32) (*)
836837 "$HOME/vimfiles/vimrc" (for Win32) (*)
837838 "$VIM/_vimrc" (for Win32) (*)
839+ "$HOME/config/settings/vim/vimrc" (for Haiku) (*)
840+
838841 Note: For Unix and Amiga, when ".vimrc" does not exist,
839842 "_vimrc" is also tried, in case an MS-DOS compatible file
840843 system is used. For MS-Windows ".vimrc" is checked after
@@ -950,6 +953,8 @@
950953 ~/.vimrc (Unix)
951954 s:.vimrc (Amiga)
952955 $VIM\_vimrc (Win32)
956+ ~/config/settings/vim/vimrc (Haiku)
957+
953958 Note that creating a vimrc file will cause the 'compatible' option to be off
954959 by default. See |compatible-default|.
955960
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/doc/tags
--- a/runtime/doc/tags Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/doc/tags Wed Feb 26 16:30:04 2020 +0100
@@ -4871,6 +4871,7 @@
48714871 GetLatestVimScripts_dat pi_getscript.txt /*GetLatestVimScripts_dat*
48724872 Gnome gui_x11.txt /*Gnome*
48734873 H motion.txt /*H*
4874+Haiku os_haiku.txt /*Haiku*
48744875 I insert.txt /*I*
48754876 ICCF uganda.txt /*ICCF*
48764877 IM-server mbyte.txt /*IM-server*
@@ -7053,6 +7054,20 @@
70537054 g~g~ change.txt /*g~g~*
70547055 g~~ change.txt /*g~~*
70557056 h motion.txt /*h*
7057+haiku-bugs os_haiku.txt /*haiku-bugs*
7058+haiku-colors os_haiku.txt /*haiku-colors*
7059+haiku-compiling os_haiku.txt /*haiku-compiling*
7060+haiku-dragndrop os_haiku.txt /*haiku-dragndrop*
7061+haiku-fonts os_haiku.txt /*haiku-fonts*
7062+haiku-general os_haiku.txt /*haiku-general*
7063+haiku-gui os_haiku.txt /*haiku-gui*
7064+haiku-launch os_haiku.txt /*haiku-launch*
7065+haiku-meta os_haiku.txt /*haiku-meta*
7066+haiku-mouse os_haiku.txt /*haiku-mouse*
7067+haiku-support-credits os_haiku.txt /*haiku-support-credits*
7068+haiku-toolbar-images os_haiku.txt /*haiku-toolbar-images*
7069+haiku-user-settings-dir os_haiku.txt /*haiku-user-settings-dir*
7070+haiku-vimdir os_haiku.txt /*haiku-vimdir*
70567071 hangul hangulin.txt /*hangul*
70577072 hangulin.txt hangulin.txt /*hangulin.txt*
70587073 has() eval.txt /*has()*
@@ -8211,6 +8226,7 @@
82118226 os_amiga.txt os_amiga.txt /*os_amiga.txt*
82128227 os_beos.txt os_beos.txt /*os_beos.txt*
82138228 os_dos.txt os_dos.txt /*os_dos.txt*
8229+os_haiku.txt os_haiku.txt /*os_haiku.txt*
82148230 os_mac.txt os_mac.txt /*os_mac.txt*
82158231 os_mint.txt os_mint.txt /*os_mint.txt*
82168232 os_msdos.txt os_msdos.txt /*os_msdos.txt*
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/gvimrc_example.vim
--- a/runtime/gvimrc_example.vim Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/gvimrc_example.vim Wed Feb 26 16:30:04 2020 +0100
@@ -6,10 +6,11 @@
66 " Last change: 2016 Apr 05
77 "
88 " To use it, copy it to
9-" for Unix: ~/.gvimrc
10-" for Amiga: s:.gvimrc
11-" for MS-DOS and Win32: $VIM\_gvimrc
12-" for OpenVMS: sys$login:.gvimrc
9+" for Unix: ~/.gvimrc
10+" for Amiga: s:.gvimrc
11+" for MS-Windows: $VIM\_gvimrc
12+" for Haiku: ~/config/settings/vim/gvimrc
13+" for OpenVMS: sys$login:.gvimrc
1314
1415 " Make external commands work through a pipe instead of a pseudo-tty
1516 "set noguipty
diff -r 619eb9bc3249 -r 22f0dda71638 runtime/vimrc_example.vim
--- a/runtime/vimrc_example.vim Wed Feb 26 13:45:07 2020 +0100
+++ b/runtime/vimrc_example.vim Wed Feb 26 16:30:04 2020 +0100
@@ -7,6 +7,7 @@
77 " for Unix: ~/.vimrc
88 " for Amiga: s:.vimrc
99 " for MS-Windows: $VIM\_vimrc
10+" for Haiku: ~/config/settings/vim/vimrc
1011 " for OpenVMS: sys$login:.vimrc
1112
1213 " When started as "evim", evim.vim will already have done these settings, bail
diff -r 619eb9bc3249 -r 22f0dda71638 src/INSTALL
--- a/src/INSTALL Wed Feb 26 13:45:07 2020 +0100
+++ b/src/INSTALL Wed Feb 26 16:30:04 2020 +0100
@@ -16,7 +16,7 @@
1616 See INSTALLx.txt for cross-compiling on Unix
1717 See ../READMEdir/README_390.txt for z/OS and OS/390 Unix
1818 See ../runtime/doc/os_beos.txt for BeBox
19-
19+See ../runtime/doc/os_haiku.txt for Haiku
2020
2121 1. Generic
2222 ==========
diff -r 619eb9bc3249 -r 22f0dda71638 src/Makefile
--- a/src/Makefile Wed Feb 26 13:45:07 2020 +0100
+++ b/src/Makefile Wed Feb 26 16:30:04 2020 +0100
@@ -1385,6 +1385,20 @@
13851385 APPDIR = $(VIMNAME).app
13861386 CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET)
13871387
1388+### Haiku GUI
1389+HAIKUGUI_SRC = gui.c gui_haiku.cc
1390+HAIKUGUI_OBJ = objects/gui.o objects/gui_haiku.o
1391+HAIKUGUI_DEFS = -DFEAT_GUI_HAIKU
1392+HAIKUGUI_IPATH =
1393+HAIKUGUI_LIBS_DIR =
1394+HAIKUGUI_LIBS1 = -lbe -lroot -ltracker -ltranslation -lsupc++ -lstdc++
1395+HAIKUGUI_LIBS2 =
1396+HAIKUGUI_INSTALL = install_normal install_haiku_extra
1397+HAIKUGUI_TARGETS = installglinks_haiku
1398+HAIKUGUI_MAN_TARGETS =
1399+HAIKUGUI_TESTTARGET = gui
1400+HAIKUGUI_BUNDLE =
1401+
13881402 # All GUI files
13891403 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
13901404 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
@@ -3217,6 +3231,9 @@
32173231 objects/gui_gtk_x11.o: gui_gtk_x11.c
32183232 $(CCC) -o $@ gui_gtk_x11.c
32193233
3234+objects/gui_haiku.o: gui_haiku.cc
3235+ $(CCC) -o $@ gui_haiku.cc
3236+
32203237 objects/gui_motif.o: gui_motif.c
32213238 $(CCC) -o $@ gui_motif.c
32223239
@@ -3349,6 +3366,9 @@
33493366 objects/os_qnx.o: os_qnx.c
33503367 $(CCC) -o $@ os_qnx.c
33513368
3369+objects/os_haiku.rsrc: os_haiku.rdef
3370+ cat $< | $(CCC) -E - | grep -v '^#' | rc -o "$@" -
3371+
33523372 objects/os_macosx.o: os_macosx.m
33533373 $(CCC) -o $@ os_macosx.m
33543374
@@ -3617,6 +3637,61 @@
36173637 objects/gui_gtk_x11.o: version.h
36183638
36193639 ###############################################################################
3640+#
3641+# Haiku installation
3642+#
3643+# This rule:
3644+# - add resources to already installed vim binary to avoid
3645+# stripping them during install;
3646+# - copy rgb.txt to runtime directory;
3647+# - update system MIME database with info about vim application.
3648+#
3649+install_haiku_extra: $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc
3650+ xres -o $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc
3651+ $(INSTALL_DATA) $(SCRIPTSOURCE)/rgb.txt $(DEST_RT)
3652+ mimeset $(DEST_BIN)/$(VIMTARGET)
3653+
3654+# List of g*-links that should be replaced with shell script equivalents.
3655+# This solves the problem of them from Tracker.
3656+#
3657+HAIKU_GLINKS = $(DEST_BIN)/$(GVIMTARGET) \
3658+ $(DEST_BIN)/$(GVIEWTARGET) \
3659+ $(DEST_BIN)/$(GVIMDIFFTARGET) \
3660+ $(DEST_BIN)/$(RGVIMTARGET) \
3661+ $(DEST_BIN)/$(RGVIEWTARGET)
3662+
3663+# This rule:
3664+# - Replace gvim link with copy of vim binary.
3665+# - Replace g*-links with shell script equivalents to solve the
3666+# problem of calling them from Tracker,
3667+# - Add icon resources to mentioned g*-link shell scripts
3668+# - in case gui-less vim.con executable available use it.
3669+#
3670+installglinks_haiku: $(HAIKU_GLINKS) install_haiku_extra
3671+ @catattr -r "BEOS:ICON" $(DEST_BIN)/$(GVIMTARGET) > ~icon.attr
3672+ for i in $(HAIKU_GLINKS); do \
3673+ rm $$i ; \
3674+ echo "#!/bin/sh" > $$i ; \
3675+ case $$i in \
3676+ $(DEST_BIN)/$(GVIMTARGET)) \
3677+ cp $(DEST_BIN)/$(VIMTARGET) $$i ; \
3678+ if [ -f $(VIMTARGET).con ] ; then \
3679+ $(STRIP) $(VIMTARGET).con ; \
3680+ mv $(VIMTARGET).con $(DEST_BIN)/$(VIMTARGET) ; \
3681+ fi ;; \
3682+ $(DEST_BIN)/$(GVIEWTARGET)) printf "%s -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
3683+ $(DEST_BIN)/$(GVIMDIFFTARGET)) printf "%s -d %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
3684+ $(DEST_BIN)/$(RGVIMTARGET)) printf "%s -Z %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
3685+ $(DEST_BIN)/$(RGVIEWTARGET)) printf "%s -Z -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
3686+ *) printf "%s %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \
3687+ esac ; \
3688+ chmod $(BINMOD) $$i ; \
3689+ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $$i ; \
3690+ done
3691+ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $(DEST_BIN)/$(VIMNAME)tutor
3692+ @rm ~icon.attr
3693+
3694+###############################################################################
36203695 ### (automatically generated by 'make depend')
36213696 ### Dependencies:
36223697 objects/arabic.o: arabic.c vim.h protodef.h auto/config.h feature.h os_unix.h \
diff -r 619eb9bc3249 -r 22f0dda71638 src/auto/configure
--- a/src/auto/configure Wed Feb 26 13:45:07 2020 +0100
+++ b/src/auto/configure Wed Feb 26 16:30:04 2020 +0100
@@ -1501,7 +1501,7 @@
15011501 --disable-farsi Deprecated.
15021502 --enable-xim Include XIM input support.
15031503 --enable-fontset Include X fontset output support.
1504- --enable-gui=OPTS X11 GUI. default=auto OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon
1504+ --enable-gui=OPTS X11 GUI. default=auto OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/haiku/photon/carbon
15051505 --enable-gtk2-check If auto-select GUI, check for GTK+ 2 default=yes
15061506 --enable-gnome-check If GTK GUI, check for GNOME default=no
15071507 --enable-gtk3-check If auto-select GUI, check for GTK+ 3 default=yes
@@ -4543,6 +4543,15 @@
45434543 $as_echo "no" >&6; };;
45444544 esac
45454545
4546+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Haiku" >&5
4547+$as_echo_n "checking for Haiku... " >&6; }
4548+case `uname` in
4549+ Haiku) HAIKU=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
4550+$as_echo "yes" >&6; };;
4551+ *) HAIKU=no; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
4552+$as_echo "no" >&6; };;
4553+esac
4554+
45464555 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for QNX" >&5
45474556 $as_echo_n "checking for QNX... " >&6; }
45484557 case `uname` in
@@ -7714,7 +7723,55 @@
77147723 fi
77157724
77167725 if test "$enable_channel" = "yes"; then
7717- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
7726+
7727+ if test "x$HAIKU" = "xyes"; then
7728+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5
7729+$as_echo_n "checking for socket in -lnetwork... " >&6; }
7730+if ${ac_cv_lib_network_socket+:} false; then :
7731+ $as_echo_n "(cached) " >&6
7732+else
7733+ ac_check_lib_save_LIBS=$LIBS
7734+LIBS="-lnetwork $LIBS"
7735+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
7736+/* end confdefs.h. */
7737+
7738+/* Override any GCC internal prototype to avoid an error.
7739+ Use char because int might match the return type of a GCC
7740+ builtin and then its argument prototype would still apply. */
7741+#ifdef __cplusplus
7742+extern "C"
7743+#endif
7744+char socket ();
7745+int
7746+main ()
7747+{
7748+return socket ();
7749+ ;
7750+ return 0;
7751+}
7752+_ACEOF
7753+if ac_fn_c_try_link "$LINENO"; then :
7754+ ac_cv_lib_network_socket=yes
7755+else
7756+ ac_cv_lib_network_socket=no
7757+fi
7758+rm -f core conftest.err conftest.$ac_objext \
7759+ conftest$ac_exeext conftest.$ac_ext
7760+LIBS=$ac_check_lib_save_LIBS
7761+fi
7762+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5
7763+$as_echo "$ac_cv_lib_network_socket" >&6; }
7764+if test "x$ac_cv_lib_network_socket" = xyes; then :
7765+ cat >>confdefs.h <<_ACEOF
7766+#define HAVE_LIBNETWORK 1
7767+_ACEOF
7768+
7769+ LIBS="-lnetwork $LIBS"
7770+
7771+fi
7772+
7773+ else
7774+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
77187775 $as_echo_n "checking for socket in -lsocket... " >&6; }
77197776 if ${ac_cv_lib_socket_socket+:} false; then :
77207777 $as_echo_n "(cached) " >&6
@@ -7759,6 +7816,8 @@
77597816
77607817 fi
77617818
7819+ fi
7820+
77627821 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
77637822 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
77647823 if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
@@ -9034,7 +9093,7 @@
90349093 as_fn_error $? "could not configure X" "$LINENO" 5
90359094 fi
90369095
9037-test "x$with_x" = xno -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
9096+test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
90389097
90399098 { $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-gui argument" >&5
90409099 $as_echo_n "checking --enable-gui argument... " >&6; }
@@ -9056,10 +9115,27 @@
90569115 SKIP_ATHENA=YES
90579116 SKIP_NEXTAW=YES
90589117 SKIP_PHOTON=YES
9118+SKIP_HAIKU=YES
90599119 SKIP_CARBON=YES
90609120 GUITYPE=NONE
90619121
9062-if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
9122+if test "x$HAIKU" = "xyes"; then
9123+ SKIP_HAIKU=
9124+ case "$enable_gui_canon" in
9125+ no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5
9126+$as_echo "no GUI support" >&6; }
9127+ SKIP_HAIKU=YES ;;
9128+ yes|"") { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - automatic GUI support" >&5
9129+$as_echo "yes - automatic GUI support" >&6; } ;;
9130+ auto) { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto - automatic GUI support" >&5
9131+$as_echo "auto - automatic GUI support" >&6; } ;;
9132+ haiku) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Haiku GUI support" >&5
9133+$as_echo "Haiku GUI support" >&6; } ;;
9134+ *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Sorry, $enable_gui GUI is not supported" >&5
9135+$as_echo "Sorry, $enable_gui GUI is not supported" >&6; }
9136+ SKIP_HAIKU=YES ;;
9137+ esac
9138+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
90639139 SKIP_PHOTON=
90649140 case "$enable_gui_canon" in
90659141 no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5
@@ -9283,6 +9359,7 @@
92839359 SKIP_ATHENA=YES;
92849360 SKIP_NEXTAW=YES;
92859361 SKIP_PHOTON=YES;
9362+ SKIP_HAIKU=YES;
92869363 SKIP_CARBON=YES
92879364 fi
92889365
@@ -10589,6 +10666,10 @@
1058910666 enable_fontset="no"
1059010667 fi
1059110668
10669+if test -z "$SKIP_HAIKU"; then
10670+ GUITYPE=HAIKUGUI
10671+fi
10672+
1059210673 if test -z "$SKIP_PHOTON"; then
1059310674 GUITYPE=PHOTONGUI
1059410675 fi
diff -r 619eb9bc3249 -r 22f0dda71638 src/configure.ac
--- a/src/configure.ac Wed Feb 26 13:45:07 2020 +0100
+++ b/src/configure.ac Wed Feb 26 16:30:04 2020 +0100
@@ -154,6 +154,12 @@
154154 *) BEOS=no; AC_MSG_RESULT(no);;
155155 esac
156156
157+AC_MSG_CHECKING(for Haiku)
158+case `uname` in
159+ Haiku) HAIKU=yes; AC_MSG_RESULT(yes);;
160+ *) HAIKU=no; AC_MSG_RESULT(no);;
161+esac
162+
157163 dnl If QNX is found, assume we don't want to use Xphoton
158164 dnl unless it was specifically asked for (--with-x)
159165 AC_MSG_CHECKING(for QNX)
@@ -2033,7 +2039,13 @@
20332039
20342040 if test "$enable_channel" = "yes"; then
20352041 dnl On Solaris we need the socket and nsl library.
2036- AC_CHECK_LIB(socket, socket)
2042+
2043+ if test "x$HAIKU" = "xyes"; then
2044+ AC_CHECK_LIB(network, socket)
2045+ else
2046+ AC_CHECK_LIB(socket, socket)
2047+ fi
2048+
20372049 AC_CHECK_LIB(nsl, gethostbyname)
20382050 AC_MSG_CHECKING(whether compiling with process communication is possible)
20392051 AC_TRY_LINK([
@@ -2311,11 +2323,11 @@
23112323 AC_MSG_ERROR([could not configure X])
23122324 fi
23132325
2314-test "x$with_x" = xno -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
2326+test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
23152327
23162328 AC_MSG_CHECKING(--enable-gui argument)
23172329 AC_ARG_ENABLE(gui,
2318- [ --enable-gui[=OPTS] X11 GUI. [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto")
2330+ [ --enable-gui[=OPTS] X11 GUI. [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/haiku/photon/carbon]], , enable_gui="auto")
23192331
23202332 dnl Canonicalize the --enable-gui= argument so that it can be easily compared.
23212333 dnl Do not use character classes for portability with old tools.
@@ -2330,10 +2342,22 @@
23302342 SKIP_ATHENA=YES
23312343 SKIP_NEXTAW=YES
23322344 SKIP_PHOTON=YES
2345+SKIP_HAIKU=YES
23332346 SKIP_CARBON=YES
23342347 GUITYPE=NONE
23352348
2336-if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
2349+if test "x$HAIKU" = "xyes"; then
2350+ SKIP_HAIKU=
2351+ case "$enable_gui_canon" in
2352+ no) AC_MSG_RESULT(no GUI support)
2353+ SKIP_HAIKU=YES ;;
2354+ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;;
2355+ auto) AC_MSG_RESULT(auto - automatic GUI support) ;;
2356+ haiku) AC_MSG_RESULT(Haiku GUI support) ;;
2357+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
2358+ SKIP_HAIKU=YES ;;
2359+ esac
2360+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
23372361 SKIP_PHOTON=
23382362 case "$enable_gui_canon" in
23392363 no) AC_MSG_RESULT(no GUI support)
@@ -2499,6 +2523,7 @@
24992523 SKIP_ATHENA=YES;
25002524 SKIP_NEXTAW=YES;
25012525 SKIP_PHOTON=YES;
2526+ SKIP_HAIKU=YES;
25022527 SKIP_CARBON=YES
25032528 fi
25042529
@@ -3112,6 +3137,11 @@
31123137 enable_fontset="no"
31133138 fi
31143139
3140+dnl There is no test for the Haiku GUI, if it's selected it's used
3141+if test -z "$SKIP_HAIKU"; then
3142+ GUITYPE=HAIKUGUI
3143+fi
3144+
31153145 if test -z "$SKIP_PHOTON"; then
31163146 GUITYPE=PHOTONGUI
31173147 fi
diff -r 619eb9bc3249 -r 22f0dda71638 src/evalfunc.c
--- a/src/evalfunc.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/evalfunc.c Wed Feb 26 16:30:04 2020 +0100
@@ -3264,6 +3264,9 @@
32643264 #ifdef __BEOS__
32653265 "beos",
32663266 #endif
3267+#ifdef __HAIKU__
3268+ "haiku",
3269+#endif
32673270 #if defined(BSD) && !defined(MACOS_X)
32683271 "bsd",
32693272 #endif
@@ -3450,6 +3453,9 @@
34503453 #ifdef FEAT_GUI_GNOME
34513454 "gui_gnome",
34523455 #endif
3456+#ifdef FEAT_GUI_HAIKU
3457+ "gui_haiku",
3458+#endif
34533459 #ifdef FEAT_GUI_MAC
34543460 "gui_mac",
34553461 #endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/feature.h
--- a/src/feature.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/feature.h Wed Feb 26 16:30:04 2020 +0100
@@ -514,7 +514,11 @@
514514 */
515515 #if defined(FEAT_GUI_MSWIN) && !defined(FEAT_MBYTE_IME)
516516 // #define FEAT_MBYTE_IME
517-# endif
517+#endif
518+
519+#if defined(FEAT_BIG) && defined(FEAT_GUI_HAIKU) && !defined(FEAT_MBYTE_IME)
520+# define FEAT_MBYTE_IME
521+#endif
518522
519523 // Use iconv() when it's available.
520524 #if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV)
@@ -604,7 +608,9 @@
604608 || defined(FEAT_GUI_MSWIN) \
605609 || ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \
606610 && defined(HAVE_XPM)) \
607- || defined(FEAT_GUI_PHOTON))
611+ || defined(FEAT_GUI_PHOTON) \
612+ || defined(FEAT_GUI_HAIKU))
613+
608614 # define FEAT_TOOLBAR
609615 #endif
610616
@@ -627,6 +633,7 @@
627633 && (defined(FEAT_GUI_GTK) \
628634 || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \
629635 || defined(FEAT_GUI_MAC) \
636+ || defined(FEAT_GUI_HAIKU) \
630637 || (defined(FEAT_GUI_MSWIN) \
631638 && (!defined(_MSC_VER) || _MSC_VER > 1020)))
632639 # define FEAT_GUI_TABLINE
@@ -638,7 +645,9 @@
638645 */
639646 #if defined(FEAT_NORMAL)
640647 # define FEAT_BROWSE_CMD
641-# 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)
648+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
649+ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_PHOTON) \
650+ || defined(FEAT_GUI_MAC)
642651 # define FEAT_BROWSE
643652 # endif
644653 #endif
@@ -663,6 +672,7 @@
663672 && defined(HAVE_X11_XPM_H)) \
664673 || defined(FEAT_GUI_GTK) \
665674 || defined(FEAT_GUI_PHOTON) \
675+ || defined(FEAT_GUI_HAIKU) \
666676 || defined(FEAT_GUI_MSWIN) \
667677 || defined(FEAT_GUI_MAC)
668678 # define FEAT_CON_DIALOG
@@ -680,7 +690,8 @@
680690 #if defined(FEAT_GUI_DIALOG) && \
681691 (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
682692 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \
683- || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
693+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
694+ || defined(FEAT_GUI_HAIKU))
684695 # define FEAT_GUI_TEXTDIALOG
685696 # ifndef ALWAYS_USE_GUI
686697 # define FEAT_CON_DIALOG
diff -r 619eb9bc3249 -r 22f0dda71638 src/fileio.c
--- a/src/fileio.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/fileio.c Wed Feb 26 16:30:04 2020 +0100
@@ -3367,6 +3367,7 @@
33673367 #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
33683368 || defined(FEAT_GUI_MSWIN) \
33693369 || defined(FEAT_GUI_MAC) \
3370+ || defined(FEAT_GUI_HAIKU) \
33703371 || defined(PROTO)
33713372 /*
33723373 * Shorten all filenames in "fnames[count]" by current directory.
@@ -4422,130 +4423,133 @@
44224423 void *context,
44234424 int (*checkitem)(void *context, char_u *name))
44244425 {
4425- int failed = FALSE;
4426-# ifdef MSWIN
4427- char_u *buf, *p;
4428- int ok;
4429- HANDLE hFind = INVALID_HANDLE_VALUE;
4430- WIN32_FIND_DATAW wfb;
4431- WCHAR *wn = NULL; // UTF-16 name, NULL when not used.
4432-# endif
4426+ int failed = FALSE;
4427+ char_u *p;
44334428
44344429 ga_init2(gap, (int)sizeof(char *), 20);
44354430
44364431 # ifdef MSWIN
4437- buf = alloc(MAXPATHL);
4438- if (buf == NULL)
4439- return FAIL;
4440- STRNCPY(buf, path, MAXPATHL-5);
4441- p = buf + STRLEN(buf);
4442- MB_PTR_BACK(buf, p);
4443- if (*p == '\\' || *p == '/')
4444- *p = NUL;
4445- STRCAT(buf, "\\*");
4446-
4447- wn = enc_to_utf16(buf, NULL);
4448- if (wn != NULL)
4449- hFind = FindFirstFileW(wn, &wfb);
4450- ok = (hFind != INVALID_HANDLE_VALUE);
4451- if (!ok)
44524432 {
4453- failed = TRUE;
4454- smsg(_(e_notopen), path);
4455- }
4456- else
4457- {
4458- while (ok)
4433+ char_u *buf;
4434+ int ok;
4435+ HANDLE hFind = INVALID_HANDLE_VALUE;
4436+ WIN32_FIND_DATAW wfb;
4437+ WCHAR *wn = NULL; // UTF-16 name, NULL when not used.
4438+
4439+ buf = alloc(MAXPATHL);
4440+ if (buf == NULL)
4441+ return FAIL;
4442+ STRNCPY(buf, path, MAXPATHL-5);
4443+ p = buf + STRLEN(buf);
4444+ MB_PTR_BACK(buf, p);
4445+ if (*p == '\\' || *p == '/')
4446+ *p = NUL;
4447+ STRCAT(buf, "\\*");
4448+
4449+ wn = enc_to_utf16(buf, NULL);
4450+ if (wn != NULL)
4451+ hFind = FindFirstFileW(wn, &wfb);
4452+ ok = (hFind != INVALID_HANDLE_VALUE);
4453+ if (!ok)
44594454 {
4460- int ignore;
4461-
4462- p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here
4463- if (p == NULL)
4464- break; // out of memory
4465-
4466- ignore = p[0] == '.' && (p[1] == NUL
4467- || (p[1] == '.' && p[2] == NUL));
4468- if (!ignore && checkitem != NULL)
4455+ failed = TRUE;
4456+ smsg(_(e_notopen), path);
4457+ }
4458+ else
4459+ {
4460+ while (ok)
44694461 {
4470- int r = checkitem(context, p);
4471-
4472- if (r < 0)
4462+ int ignore;
4463+
4464+ p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here
4465+ if (p == NULL)
4466+ break; // out of memory
4467+
4468+ ignore = p[0] == '.' && (p[1] == NUL
4469+ || (p[1] == '.' && p[2] == NUL));
4470+ if (!ignore && checkitem != NULL)
44734471 {
4474- vim_free(p);
4475- break;
4472+ int r = checkitem(context, p);
4473+
4474+ if (r < 0)
4475+ {
4476+ vim_free(p);
4477+ break;
4478+ }
4479+ if (r == 0)
4480+ ignore = TRUE;
44764481 }
4477- if (r == 0)
4478- ignore = TRUE;
4482+
4483+ if (!ignore)
4484+ {
4485+ if (ga_grow(gap, 1) == OK)
4486+ ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p);
4487+ else
4488+ {
4489+ failed = TRUE;
4490+ vim_free(p);
4491+ break;
4492+ }
4493+ }
4494+
4495+ vim_free(p);
4496+ ok = FindNextFileW(hFind, &wfb);
44794497 }
4480-
4481- if (!ignore)
4498+ FindClose(hFind);
4499+ }
4500+
4501+ vim_free(buf);
4502+ vim_free(wn);
4503+ }
4504+# else
4505+ {
4506+ DIR *dirp;
4507+ struct dirent *dp;
4508+
4509+ dirp = opendir((char *)path);
4510+ if (dirp == NULL)
4511+ {
4512+ failed = TRUE;
4513+ smsg(_(e_notopen), path);
4514+ }
4515+ else
4516+ {
4517+ for (;;)
44824518 {
4483- if (ga_grow(gap, 1) == OK)
4484- ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p);
4485- else
4519+ int ignore;
4520+
4521+ dp = readdir(dirp);
4522+ if (dp == NULL)
4523+ break;
4524+ p = (char_u *)dp->d_name;
4525+
4526+ ignore = p[0] == '.' &&
4527+ (p[1] == NUL ||
4528+ (p[1] == '.' && p[2] == NUL));
4529+ if (!ignore && checkitem != NULL)
44864530 {
4487- failed = TRUE;
4488- vim_free(p);
4489- break;
4531+ int r = checkitem(context, p);
4532+
4533+ if (r < 0)
4534+ break;
4535+ if (r == 0)
4536+ ignore = TRUE;
4537+ }
4538+
4539+ if (!ignore)
4540+ {
4541+ if (ga_grow(gap, 1) == OK)
4542+ ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p);
4543+ else
4544+ {
4545+ failed = TRUE;
4546+ break;
4547+ }
44904548 }
44914549 }
44924550
4493- vim_free(p);
4494- ok = FindNextFileW(hFind, &wfb);
4551+ closedir(dirp);
44954552 }
4496- FindClose(hFind);
4497- }
4498-
4499- vim_free(buf);
4500- vim_free(wn);
4501-# else
4502- DIR *dirp;
4503- struct dirent *dp;
4504- char_u *p;
4505-
4506- dirp = opendir((char *)path);
4507- if (dirp == NULL)
4508- {
4509- failed = TRUE;
4510- smsg(_(e_notopen), path);
4511- }
4512- else
4513- {
4514- for (;;)
4515- {
4516- int ignore;
4517-
4518- dp = readdir(dirp);
4519- if (dp == NULL)
4520- break;
4521- p = (char_u *)dp->d_name;
4522-
4523- ignore = p[0] == '.' &&
4524- (p[1] == NUL ||
4525- (p[1] == '.' && p[2] == NUL));
4526- if (!ignore && checkitem != NULL)
4527- {
4528- int r = checkitem(context, p);
4529-
4530- if (r < 0)
4531- break;
4532- if (r == 0)
4533- ignore = TRUE;
4534- }
4535-
4536- if (!ignore)
4537- {
4538- if (ga_grow(gap, 1) == OK)
4539- ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p);
4540- else
4541- {
4542- failed = TRUE;
4543- break;
4544- }
4545- }
4546- }
4547-
4548- closedir(dirp);
45494553 }
45504554 # endif
45514555
diff -r 619eb9bc3249 -r 22f0dda71638 src/globals.h
--- a/src/globals.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/globals.h Wed Feb 26 16:30:04 2020 +0100
@@ -1524,7 +1524,7 @@
15241524 EXTERN char e_fontset[] INIT(= N_("E234: Unknown fontset: %s"));
15251525 #endif
15261526 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \
1527- || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN)
1527+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
15281528 EXTERN char e_font[] INIT(= N_("E235: Unknown font: %s"));
15291529 #endif
15301530 #if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)
diff -r 619eb9bc3249 -r 22f0dda71638 src/gui.c
--- a/src/gui.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/gui.c Wed Feb 26 16:30:04 2020 +0100
@@ -446,7 +446,8 @@
446446 gui.menu_width = 0;
447447 # endif
448448 #endif
449-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
449+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
450+ || defined(FEAT_GUI_HAIKU))
450451 gui.toolbar_height = 0;
451452 #endif
452453 #if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF)
@@ -1371,10 +1372,11 @@
13711372 text_area_y += gui.tabline_height;
13721373 #endif
13731374
1374-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
1375+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
1376+ || defined(FEAT_GUI_HAIKU))
13751377 if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
13761378 {
1377-# ifdef FEAT_GUI_ATHENA
1379+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
13781380 gui_mch_set_toolbar_pos(0, text_area_y,
13791381 gui.menu_width, gui.toolbar_height);
13801382 # endif
@@ -1382,6 +1384,13 @@
13821384 }
13831385 #endif
13841386
1387+# if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_HAIKU)
1388+ gui_mch_set_tabline_pos(0, text_area_y,
1389+ gui.menu_width, gui.tabline_height);
1390+ if (gui_has_tabline())
1391+ text_area_y += gui.tabline_height;
1392+#endif
1393+
13851394 text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2;
13861395 text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2;
13871396
@@ -1453,7 +1462,7 @@
14531462 # endif
14541463 # endif
14551464 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
1456- || defined(FEAT_GUI_MOTIF))
1465+ || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
14571466 if (gui_has_tabline())
14581467 base_height += gui.tabline_height;
14591468 # endif
@@ -1496,6 +1505,10 @@
14961505 new_pixel_height = 0;
14971506 busy = TRUE;
14981507
1508+#ifdef FEAT_GUI_HAIKU
1509+ vim_lock_screen();
1510+#endif
1511+
14991512 // Flush pending output before redrawing
15001513 out_flush();
15011514
@@ -1518,6 +1531,10 @@
15181531 || gui.num_rows != Rows || gui.num_cols != Columns)
15191532 shell_resized();
15201533
1534+#ifdef FEAT_GUI_HAIKU
1535+ vim_unlock_screen();
1536+#endif
1537+
15211538 gui_update_scrollbars(TRUE);
15221539 gui_update_cursor(FALSE, TRUE);
15231540 #if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK)
@@ -4254,9 +4271,10 @@
42544271 y += gui.menu_height;
42554272 #endif
42564273
4257-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA))
4274+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) \
4275+ || defined(FEAT_GUI_HAIKU))
42584276 if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
4259-# ifdef FEAT_GUI_ATHENA
4277+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
42604278 y += gui.toolbar_height;
42614279 # else
42624280 # ifdef FEAT_GUI_MSWIN
@@ -4265,7 +4283,7 @@
42654283 # endif
42664284 #endif
42674285
4268-#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN)
4286+#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
42694287 if (gui_has_tabline())
42704288 y += gui.tabline_height;
42714289 #endif
@@ -5035,10 +5053,11 @@
50355053 }
50365054
50375055 #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \
5038- || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)) \
5056+ || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON) \
5057+ || defined(FEAT_GUI_HAIKU)) \
50395058 && defined(FEAT_TOOLBAR)) || defined(PROTO)
50405059 /*
5041- * This is shared between Athena, Motif and GTK.
5060+ * This is shared between Athena, Haiku, Motif, and GTK.
50425061 */
50435062
50445063 /*
diff -r 619eb9bc3249 -r 22f0dda71638 src/gui.h
--- a/src/gui.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/gui.h Wed Feb 26 16:30:04 2020 +0100
@@ -29,6 +29,10 @@
2929 # include <gtk/gtk.h>
3030 #endif
3131
32+#ifdef FEAT_GUI_HAIKU
33+# include "gui_haiku.h"
34+#endif
35+
3236 // Needed when generating prototypes, since FEAT_GUI is always defined then.
3337 #if defined(FEAT_XCLIPBOARD) && !defined(FEAT_GUI_MOTIF) \
3438 && !defined(FEAT_GUI_ATHENA) && !defined(FEAT_GUI_GTK)
@@ -73,7 +77,8 @@
7377 */
7478 #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
7579 || defined(FEAT_GUI_MSWIN) \
76- || defined(FEAT_GUI_MAC)
80+ || defined(FEAT_GUI_MAC) \
81+ || defined(FEAT_GUI_HAIKU)
7782 # define HAVE_DROP_FILE
7883 #endif
7984
@@ -200,6 +205,10 @@
200205 // scroll_shift is set to the number of shifts
201206 // to reduce the count.
202207 #endif
208+
209+#if FEAT_GUI_HAIKU
210+ VimScrollBar *id; // Pointer to real scroll bar
211+#endif
203212 #ifdef FEAT_GUI_MAC
204213 ControlHandle id; // A handle to the scrollbar
205214 #endif
@@ -426,7 +435,7 @@
426435
427436 #if defined(FEAT_GUI_TABLINE) \
428437 && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
429- || defined(FEAT_GUI_MAC))
438+ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_HAIKU))
430439 int tabline_height;
431440 #endif
432441
@@ -435,7 +444,7 @@
435444 #endif
436445
437446 #if defined(FEAT_TOOLBAR) \
438- && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
447+ && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
439448 int toolbar_height; // height of the toolbar
440449 #endif
441450
@@ -456,6 +465,14 @@
456465 guicolor_T currSpColor; // Current special text color
457466 #endif
458467
468+#ifdef FEAT_GUI_HAIKU
469+ VimApp *vimApp;
470+ VimWindow *vimWindow;
471+ VimFormView *vimForm;
472+ VimTextAreaView *vimTextArea;
473+ int vdcmp; // Vim Direct Communication Message Port
474+#endif
475+
459476 #ifdef FEAT_GUI_MAC
460477 WindowPtr VimWindow;
461478 MenuHandle MacOSHelpMenu; // Help menu provided by the MacOS
diff -r 619eb9bc3249 -r 22f0dda71638 src/gui_haiku.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui_haiku.cc Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,5242 @@
1+/* vi:set ts=8 sts=4 sw=4:
2+ *
3+ * VIM - Vi IMproved by Bram Moolenaar
4+ * BeBox GUI support Copyright 1998 by Olaf Seibert.
5+ * All Rights Reserved.
6+ *
7+ * Do ":help uganda" in Vim to read copying and usage conditions.
8+ * Do ":help credits" in Vim to see a list of people who contributed.
9+ *
10+ * Based on "GUI support for the Buzzword Enhanced Operating System."
11+ *
12+ * Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99
13+ *
14+ * Haiku support by Siarzhuk Zharski <imker@gmx.li> Apr-Mai 2009
15+ *
16+ */
17+
18+/*
19+ * Structure of the Haiku GUI code:
20+ *
21+ * There are 3 threads.
22+ * 1. The initial thread. In gui_mch_prepare() this gets to run the
23+ * BApplication message loop. But before it starts doing that,
24+ * it creates thread 2
25+ * 2. The main() thread. This thread is created in gui_mch_prepare()
26+ * and its purpose in life is to call main(argc, argv) again.
27+ * This thread is doing the bulk of the work.
28+ * 3. Sooner or later, a window is opened by the main() thread. This
29+ * causes a second message loop to be created: the window thread.
30+ *
31+ * == alternatively ===
32+ *
33+ * #if RUN_BAPPLICATION_IN_NEW_THREAD...
34+ *
35+ * 1. The initial thread. In gui_mch_prepare() this gets to spawn
36+ * thread 2. After doing that, it returns to main() to do the
37+ * bulk of the work, being the main() thread.
38+ * 2. Runs the BApplication.
39+ * 3. The window thread, just like in the first case.
40+ *
41+ * This second alternative is cleaner from Vim's viewpoint. However,
42+ * the BeBook seems to assume everywhere that the BApplication *must*
43+ * run in the initial thread. So perhaps doing otherwise is very wrong.
44+ *
45+ * However, from a B_SINGLE_LAUNCH viewpoint, the first is better.
46+ * If Vim is marked "Single Launch" in its application resources,
47+ * and a file is dropped on the Vim icon, and another Vim is already
48+ * running, the file is passed on to the earlier Vim. This happens
49+ * in BApplication::Run(). So we want Vim to terminate if
50+ * BApplication::Run() terminates. (See the BeBook, on BApplication.
51+ * However, it seems that the second copy of Vim isn't even started
52+ * in this case... which is for the better since I wouldn't know how
53+ * to detect this case.)
54+ *
55+ * Communication between these threads occurs mostly by translating
56+ * BMessages that come in and posting an appropriate translation on
57+ * the VDCMP (Vim Direct Communication Message Port). Therefore the
58+ * actions required for keypresses and window resizes, etc, are mostly
59+ * performed in the main() thread.
60+ *
61+ * A notable exception to this is the Draw() event. The redrawing of
62+ * the window contents is performed asynchronously from the window
63+ * thread. To make this work correctly, a locking protocol is used when
64+ * any thread is accessing the essential variables that are used by
65+ * the window thread.
66+ *
67+ * This locking protocol consists of locking Vim's window. This is both
68+ * convenient and necessary.
69+ */
70+
71+extern "C" {
72+
73+#include <assert.h>
74+#include <float.h>
75+#include <syslog.h>
76+
77+#include "vim.h"
78+#include "globals.h"
79+#include "proto.h"
80+#include "version.h"
81+
82+} // extern "C"
83+
84+// ---------------- start of header part ----------------
85+
86+//#include <Alert.h>
87+#include <Application.h>
88+#include <Beep.h>
89+#include <Bitmap.h>
90+#include <Box.h>
91+#include <Button.h>
92+#include <Clipboard.h>
93+#include <Debug.h>
94+//#include <Directory.h>
95+//#include <Entry.h>
96+#include <File.h>
97+#include <FilePanel.h>
98+#include <FindDirectory.h>
99+//#include <Font.h>
100+#include <IconUtils.h>
101+#include <Input.h>
102+#include <ListView.h>
103+#include <MenuBar.h>
104+#include <MenuItem.h>
105+//#include <MessageQueue.h>
106+//#include <OS.h>
107+#include <Path.h>
108+#include <PictureButton.h>
109+#include <PopUpMenu.h>
110+//#include <Region.h>
111+#include <Resources.h>
112+//#include <Roster.h>
113+#include <Screen.h>
114+#include <ScrollBar.h>
115+#include <ScrollView.h>
116+#include <String.h>
117+#include <StringView.h>
118+//#include <SupportDefs.h>
119+#include <TabView.h>
120+#include <TextControl.h>
121+#include <TextView.h>
122+#include <TranslationUtils.h>
123+#include <TranslatorFormats.h>
124+#include <View.h>
125+#include <Window.h>
126+
127+class VimApp;
128+class VimFormView;
129+class VimTextAreaView;
130+class VimWindow;
131+class VimToolbar;
132+class VimTabLine;
133+
134+extern key_map *keyMap;
135+extern char *keyMapChars;
136+
137+extern int main(int argc, char **argv);
138+
139+#ifndef B_MAX_PORT_COUNT
140+#define B_MAX_PORT_COUNT 255
141+#endif
142+
143+// VimApp seems comparable to the X "vimShell"
144+class VimApp: public BApplication
145+{
146+ typedef BApplication Inherited;
147+ public:
148+ VimApp(const char *appsig);
149+ ~VimApp();
150+
151+ // callbacks:
152+#if 0
153+ virtual void DispatchMessage(BMessage *m, BHandler *h)
154+ {
155+ m->PrintToStream();
156+ Inherited::DispatchMessage(m, h);
157+ }
158+#endif
159+ virtual void ReadyToRun();
160+ virtual void ArgvReceived(int32 argc, char **argv);
161+ virtual void RefsReceived(BMessage *m);
162+ virtual bool QuitRequested();
163+ virtual void MessageReceived(BMessage *m);
164+
165+ static void SendRefs(BMessage *m, bool changedir);
166+
167+ sem_id fFilePanelSem;
168+ BFilePanel* fFilePanel;
169+ BPath fBrowsedPath;
170+ private:
171+};
172+
173+class VimWindow: public BWindow
174+{
175+ typedef BWindow Inherited;
176+ public:
177+ VimWindow();
178+ ~VimWindow();
179+
180+ // virtual void DispatchMessage(BMessage *m, BHandler *h);
181+ virtual void WindowActivated(bool active);
182+ virtual bool QuitRequested();
183+
184+ VimFormView *formView;
185+
186+ private:
187+ void init();
188+
189+};
190+
191+class VimFormView: public BView
192+{
193+ typedef BView Inherited;
194+ public:
195+ VimFormView(BRect frame);
196+ ~VimFormView();
197+
198+ // callbacks:
199+ virtual void AllAttached();
200+ virtual void FrameResized(float new_width, float new_height);
201+
202+#define MENUBAR_MARGIN 1
203+ float MenuHeight() const
204+ { return menuBar ? menuBar->Frame().Height() + MENUBAR_MARGIN: 0; }
205+ BMenuBar *MenuBar() const
206+ { return menuBar; }
207+
208+ private:
209+ void init(BRect);
210+
211+ BMenuBar *menuBar;
212+ VimTextAreaView *textArea;
213+
214+#ifdef FEAT_TOOLBAR
215+ public:
216+ float ToolbarHeight() const;
217+ VimToolbar *ToolBar() const
218+ { return toolBar; }
219+ private:
220+ VimToolbar *toolBar;
221+#endif
222+
223+#ifdef FEAT_GUI_TABLINE
224+ public:
225+ VimTabLine *TabLine() const { return tabLine; }
226+ bool IsShowingTabLine() const { return showingTabLine; }
227+ void SetShowingTabLine(bool showing) { showingTabLine = showing; }
228+ float TablineHeight() const;
229+ private:
230+ VimTabLine *tabLine;
231+ int showingTabLine;
232+#endif
233+};
234+
235+class VimTextAreaView: public BView
236+{
237+ typedef BView Inherited;
238+ public:
239+ VimTextAreaView(BRect frame);
240+ ~VimTextAreaView();
241+
242+ // callbacks:
243+ virtual void Draw(BRect updateRect);
244+ virtual void KeyDown(const char *bytes, int32 numBytes);
245+ virtual void MouseDown(BPoint point);
246+ virtual void MouseUp(BPoint point);
247+ virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message);
248+ virtual void MessageReceived(BMessage *m);
249+
250+ // own functions:
251+ int mchInitFont(char_u *name);
252+ void mchDrawString(int row, int col, char_u *s, int len, int flags);
253+ void mchClearBlock(int row1, int col1, int row2, int col2);
254+ void mchClearAll();
255+ void mchDeleteLines(int row, int num_lines);
256+ void mchInsertLines(int row, int num_lines);
257+
258+ static void guiSendMouseEvent(int button, int x, int y, int repeated_click, int_u modifiers);
259+ static void guiMouseMoved(int x, int y);
260+ static void guiBlankMouse(bool should_hide);
261+ static int_u mouseModifiersToVim(int32 beModifiers);
262+
263+ int32 mouseDragEventCount;
264+
265+#ifdef FEAT_MBYTE_IME
266+ void DrawIMString(void);
267+#endif
268+
269+ private:
270+ void init(BRect);
271+
272+ int_u vimMouseButton;
273+ int_u vimMouseModifiers;
274+
275+#ifdef FEAT_MBYTE_IME
276+ struct {
277+ BMessenger* messenger;
278+ BMessage* message;
279+ BPoint location;
280+ int row;
281+ int col;
282+ int count;
283+ } IMData;
284+#endif
285+};
286+
287+class VimScrollBar: public BScrollBar
288+{
289+ typedef BScrollBar Inherited;
290+ public:
291+ VimScrollBar(scrollbar_T *gsb, orientation posture);
292+ ~VimScrollBar();
293+
294+ virtual void ValueChanged(float newValue);
295+ virtual void MouseUp(BPoint where);
296+ void SetValue(float newval);
297+ scrollbar_T *getGsb()
298+ { return gsb; }
299+
300+ int32 scrollEventCount;
301+
302+ private:
303+ scrollbar_T *gsb;
304+ float ignoreValue;
305+};
306+
307+
308+#ifdef FEAT_TOOLBAR
309+
310+class VimToolbar : public BBox
311+{
312+ static BBitmap *normalButtonsBitmap;
313+ static BBitmap *grayedButtonsBitmap;
314+
315+ BBitmap *LoadVimBitmap(const char* fileName);
316+ bool GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed);
317+ bool ModifyBitmapToGrayed(BBitmap *bitmap);
318+
319+ BList fButtonsList;
320+ void InvalidateLayout();
321+
322+ public:
323+ VimToolbar(BRect frame, const char * name);
324+ ~VimToolbar();
325+
326+ bool PrepareButtonBitmaps();
327+
328+ bool AddButton(int32 index, vimmenu_T *menu);
329+ bool RemoveButton(vimmenu_T *menu);
330+ bool GrayButton(vimmenu_T *menu, int grey);
331+
332+ float ToolbarHeight() const;
333+ virtual void AttachedToWindow();
334+};
335+
336+BBitmap *VimToolbar::normalButtonsBitmap = NULL;
337+BBitmap *VimToolbar::grayedButtonsBitmap = NULL;
338+
339+const float ToolbarMargin = 3.;
340+const float ButtonMargin = 3.;
341+
342+#endif //FEAT_TOOLBAR
343+
344+#ifdef FEAT_GUI_TABLINE
345+
346+class VimTabLine : public BTabView
347+{
348+ public:
349+ class VimTab : public BTab {
350+ public:
351+ VimTab() : BTab(new BView(BRect(), "-Empty-", 0, 0)) {}
352+
353+ virtual void Select(BView* owner);
354+ };
355+
356+ VimTabLine(BRect r) : BTabView(r, "vimTabLine", B_WIDTH_FROM_LABEL,
357+ B_FOLLOW_LEFT | B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS) {}
358+
359+ float TablineHeight() const;
360+ virtual void MouseDown(BPoint point);
361+};
362+
363+#endif //FEAT_GUI_TABLINE
364+
365+
366+// For caching the fonts that are used;
367+// Vim seems rather sloppy in this regard.
368+class VimFont: public BFont
369+{
370+ typedef BFont Inherited;
371+ public:
372+ VimFont();
373+ VimFont(const VimFont *rhs);
374+ VimFont(const BFont *rhs);
375+ VimFont(const VimFont &rhs);
376+ ~VimFont();
377+
378+ VimFont *next;
379+ int refcount;
380+ char_u *name;
381+
382+ private:
383+ void init();
384+};
385+
386+#if defined(FEAT_GUI_DIALOG)
387+
388+class VimDialog : public BWindow
389+{
390+ typedef BWindow Inherited;
391+
392+ BButton* _CreateButton(int32 which, const char* label);
393+
394+ public:
395+
396+ class View : public BView {
397+ typedef BView Inherited;
398+
399+ public:
400+ View(BRect frame);
401+ ~View();
402+
403+ virtual void Draw(BRect updateRect);
404+ void InitIcon(int32 type);
405+
406+ private:
407+ BBitmap* fIconBitmap;
408+ };
409+
410+ VimDialog(int type, const char *title, const char *message,
411+ const char *buttons, int dfltbutton, const char *textfield,
412+ int ex_cmd);
413+ ~VimDialog();
414+
415+ int Go();
416+
417+ virtual void MessageReceived(BMessage *msg);
418+
419+ private:
420+ sem_id fDialogSem;
421+ int fDialogValue;
422+ BList fButtonsList;
423+ BTextView* fMessageView;
424+ BTextControl* fInputControl;
425+ const char* fInputValue;
426+};
427+
428+class VimSelectFontDialog : public BWindow
429+{
430+ typedef BWindow Inherited;
431+
432+ void _CleanList(BListView* list);
433+ void _UpdateFontStyles();
434+ void _UpdateSizeInputPreview();
435+ void _UpdateFontPreview();
436+ bool _UpdateFromListItem(BListView* list, char* text, int textSize);
437+ public:
438+
439+ VimSelectFontDialog(font_family* family, font_style* style, float* size);
440+ ~VimSelectFontDialog();
441+
442+ bool Go();
443+
444+ virtual void MessageReceived(BMessage *msg);
445+
446+ private:
447+ status_t fStatus;
448+ sem_id fDialogSem;
449+ bool fDialogValue;
450+ font_family* fFamily;
451+ font_style* fStyle;
452+ float* fSize;
453+ font_family fFontFamily;
454+ font_style fFontStyle;
455+ float fFontSize;
456+ BStringView* fPreview;
457+ BListView* fFamiliesList;
458+ BListView* fStylesList;
459+ BListView* fSizesList;
460+ BTextControl* fSizesInput;
461+};
462+
463+#endif // FEAT_GUI_DIALOG
464+
465+// ---------------- end of GUI classes ----------------
466+
467+struct MainArgs {
468+ int argc;
469+ char **argv;
470+};
471+
472+// These messages are copied through the VDCMP.
473+// Therefore they ought not to have anything fancy.
474+// They must be of POD type (Plain Old Data)
475+// as the C++ standard calls them.
476+
477+#define KEY_MSG_BUFSIZ 7
478+#if KEY_MSG_BUFSIZ < MAX_KEY_CODE_LEN
479+#error Increase KEY_MSG_BUFSIZ!
480+#endif
481+
482+struct VimKeyMsg {
483+ char_u length;
484+ char_u chars[KEY_MSG_BUFSIZ]; // contains Vim encoding
485+ bool csi_escape;
486+};
487+
488+struct VimResizeMsg {
489+ int width;
490+ int height;
491+};
492+
493+struct VimScrollBarMsg {
494+ VimScrollBar *sb;
495+ long value;
496+ int stillDragging;
497+};
498+
499+struct VimMenuMsg {
500+ vimmenu_T *guiMenu;
501+};
502+
503+struct VimMouseMsg {
504+ int button;
505+ int x;
506+ int y;
507+ int repeated_click;
508+ int_u modifiers;
509+};
510+
511+struct VimMouseMovedMsg {
512+ int x;
513+ int y;
514+};
515+
516+struct VimFocusMsg {
517+ bool active;
518+};
519+
520+struct VimRefsMsg {
521+ BMessage *message;
522+ bool changedir;
523+};
524+
525+struct VimTablineMsg {
526+ int index;
527+};
528+
529+struct VimTablineMenuMsg {
530+ int index;
531+ int event;
532+};
533+
534+struct VimMsg {
535+ enum VimMsgType {
536+ Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu
537+ };
538+
539+ union {
540+ struct VimKeyMsg Key;
541+ struct VimResizeMsg NewSize;
542+ struct VimScrollBarMsg Scroll;
543+ struct VimMenuMsg Menu;
544+ struct VimMouseMsg Mouse;
545+ struct VimMouseMovedMsg MouseMoved;
546+ struct VimFocusMsg Focus;
547+ struct VimRefsMsg Refs;
548+ struct VimTablineMsg Tabline;
549+ struct VimTablineMenuMsg TablineMenu;
550+ } u;
551+};
552+
553+#define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0)
554+#define GUI_TO_RGB(g) { (g) >> 16, (g) >> 8, (g) >> 0, 255 }
555+
556+// ---------------- end of header part ----------------
557+
558+static struct specialkey
559+{
560+ uint16 BeKeys;
561+#define KEY(a,b) ((a)<<8|(b))
562+#define K(a) KEY(0,a) // for ASCII codes
563+#define F(b) KEY(1,b) // for scancodes
564+ char_u vim_code0;
565+ char_u vim_code1;
566+} special_keys[] =
567+{
568+ {K(B_UP_ARROW), 'k', 'u'},
569+ {K(B_DOWN_ARROW), 'k', 'd'},
570+ {K(B_LEFT_ARROW), 'k', 'l'},
571+ {K(B_RIGHT_ARROW), 'k', 'r'},
572+ {K(B_BACKSPACE), 'k', 'b'},
573+ {K(B_INSERT), 'k', 'I'},
574+ {K(B_DELETE), 'k', 'D'},
575+ {K(B_HOME), 'k', 'h'},
576+ {K(B_END), '@', '7'},
577+ {K(B_PAGE_UP), 'k', 'P'}, // XK_Prior
578+ {K(B_PAGE_DOWN), 'k', 'N'}, // XK_Next,
579+
580+#define FIRST_FUNCTION_KEY 11
581+ {F(B_F1_KEY), 'k', '1'},
582+ {F(B_F2_KEY), 'k', '2'},
583+ {F(B_F3_KEY), 'k', '3'},
584+ {F(B_F4_KEY), 'k', '4'},
585+ {F(B_F5_KEY), 'k', '5'},
586+ {F(B_F6_KEY), 'k', '6'},
587+ {F(B_F7_KEY), 'k', '7'},
588+ {F(B_F8_KEY), 'k', '8'},
589+ {F(B_F9_KEY), 'k', '9'},
590+ {F(B_F10_KEY), 'k', ';'},
591+
592+ {F(B_F11_KEY), 'F', '1'},
593+ {F(B_F12_KEY), 'F', '2'},
594+ // {XK_F13, 'F', '3'}, // would be print screen
595+ // sysreq
596+ {F(0x0F), 'F', '4'}, // scroll lock
597+ {F(0x10), 'F', '5'}, // pause/break
598+ // {XK_F16, 'F', '6'},
599+ // {XK_F17, 'F', '7'},
600+ // {XK_F18, 'F', '8'},
601+ // {XK_F19, 'F', '9'},
602+ // {XK_F20, 'F', 'A'},
603+ // {XK_F21, 'F', 'B'},
604+ // {XK_F22, 'F', 'C'},
605+ // {XK_F23, 'F', 'D'},
606+ // {XK_F24, 'F', 'E'},
607+ // {XK_F25, 'F', 'F'},
608+ // {XK_F26, 'F', 'G'},
609+ // {XK_F27, 'F', 'H'},
610+ // {XK_F28, 'F', 'I'},
611+ // {XK_F29, 'F', 'J'},
612+ // {XK_F30, 'F', 'K'},
613+ // {XK_F31, 'F', 'L'},
614+ // {XK_F32, 'F', 'M'},
615+ // {XK_F33, 'F', 'N'},
616+ // {XK_F34, 'F', 'O'},
617+ // {XK_F35, 'F', 'P'}, // keysymdef.h defines up to F35
618+
619+ // {XK_Help, '%', '1'}, // XK_Help
620+ {F(B_PRINT_KEY), '%', '9'},
621+
622+#if 0
623+ // Keypad keys:
624+ {F(0x48), 'k', 'l'}, // XK_KP_Left
625+ {F(0x4A), 'k', 'r'}, // XK_KP_Right
626+ {F(0x38), 'k', 'u'}, // XK_KP_Up
627+ {F(0x59), 'k', 'd'}, // XK_KP_Down
628+ {F(0x64), 'k', 'I'}, // XK_KP_Insert
629+ {F(0x65), 'k', 'D'}, // XK_KP_Delete
630+ {F(0x37), 'k', 'h'}, // XK_KP_Home
631+ {F(0x58), '@', '7'}, // XK_KP_End
632+ {F(0x39), 'k', 'P'}, // XK_KP_Prior
633+ {F(0x60), 'k', 'N'}, // XK_KP_Next
634+ {F(0x49), '&', '8'}, // XK_Undo, keypad 5
635+#endif
636+
637+ // End of list marker:
638+ {0, 0, 0}
639+};
640+
641+#define NUM_SPECIAL_KEYS (sizeof(special_keys)/sizeof(special_keys[0]))
642+
643+// ---------------- VimApp ----------------
644+
645+ static void
646+docd(BPath &path)
647+{
648+ mch_chdir((char *)path.Path());
649+ // Do this to get the side effects of a :cd command
650+ do_cmdline_cmd((char_u *)"cd .");
651+}
652+
653+ static void
654+drop_callback(void *cookie)
655+{
656+ // TODO here we could handle going to a specific position in the dropped
657+ // file (see src/gui_mac.c)
658+ // Update the screen display
659+ update_screen(NOT_VALID);
660+}
661+
662+ // Really handle dropped files and folders.
663+ static void
664+RefsReceived(BMessage *m, bool changedir)
665+{
666+ uint32 type;
667+ int32 count;
668+
669+ m->PrintToStream();
670+ switch (m->what) {
671+ case B_REFS_RECEIVED:
672+ case B_SIMPLE_DATA:
673+ m->GetInfo("refs", &type, &count);
674+ if (type != B_REF_TYPE)
675+ goto bad;
676+ break;
677+ case B_ARGV_RECEIVED:
678+ m->GetInfo("argv", &type, &count);
679+ if (type != B_STRING_TYPE)
680+ goto bad;
681+ if (changedir) {
682+ char *dirname;
683+ if (m->FindString("cwd", (const char **) &dirname) == B_OK) {
684+ chdir(dirname);
685+ do_cmdline_cmd((char_u *)"cd .");
686+ }
687+ }
688+ break;
689+ default:
690+bad:
691+ /*fprintf(stderr, "bad!\n"); */
692+ delete m;
693+ return;
694+ }
695+
696+#ifdef FEAT_VISUAL
697+ reset_VIsual();
698+#endif
699+
700+ char_u **fnames;
701+ fnames = (char_u **) alloc(count * sizeof(char_u *));
702+ int fname_index = 0;
703+
704+ switch (m->what) {
705+ case B_REFS_RECEIVED:
706+ case B_SIMPLE_DATA:
707+ // fprintf(stderr, "case B_REFS_RECEIVED\n");
708+ for (int i = 0; i < count; ++i)
709+ {
710+ entry_ref ref;
711+ if (m->FindRef("refs", i, &ref) == B_OK) {
712+ BEntry entry(&ref, false);
713+ BPath path;
714+ entry.GetPath(&path);
715+
716+ // Change to parent directory?
717+ if (changedir) {
718+ BPath parentpath;
719+ path.GetParent(&parentpath);
720+ docd(parentpath);
721+ }
722+
723+ // Is it a directory? If so, cd into it.
724+ BDirectory bdir(&ref);
725+ if (bdir.InitCheck() == B_OK) {
726+ // don't cd if we already did it
727+ if (!changedir)
728+ docd(path);
729+ } else {
730+ mch_dirname(IObuff, IOSIZE);
731+ char_u *fname = shorten_fname((char_u *)path.Path(), IObuff);
732+ if (fname == NULL)
733+ fname = (char_u *)path.Path();
734+ fnames[fname_index++] = vim_strsave(fname);
735+ // fprintf(stderr, "%s\n", fname);
736+ }
737+
738+ // Only do it for the first file/dir
739+ changedir = false;
740+ }
741+ }
742+ break;
743+ case B_ARGV_RECEIVED:
744+ // fprintf(stderr, "case B_ARGV_RECEIVED\n");
745+ for (int i = 1; i < count; ++i)
746+ {
747+ char *fname;
748+
749+ if (m->FindString("argv", i, (const char **) &fname) == B_OK) {
750+ fnames[fname_index++] = vim_strsave((char_u *)fname);
751+ }
752+ }
753+ break;
754+ default:
755+ // fprintf(stderr, "case default\n");
756+ break;
757+ }
758+
759+ delete m;
760+
761+ // Handle the drop, :edit to get to the file
762+ if (fname_index > 0) {
763+ handle_drop(fname_index, fnames, FALSE, drop_callback, NULL);
764+
765+ setcursor();
766+ out_flush();
767+ } else {
768+ vim_free(fnames);
769+ }
770+}
771+
772+VimApp::VimApp(const char *appsig):
773+ BApplication(appsig),
774+ fFilePanelSem(-1),
775+ fFilePanel(NULL)
776+{
777+}
778+
779+VimApp::~VimApp()
780+{
781+}
782+
783+ void
784+VimApp::ReadyToRun()
785+{
786+ /*
787+ * Apparently signals are inherited by the created thread -
788+ * disable the most annoying ones.
789+ */
790+ signal(SIGINT, SIG_IGN);
791+ signal(SIGQUIT, SIG_IGN);
792+}
793+
794+ void
795+VimApp::ArgvReceived(int32 arg_argc, char **arg_argv)
796+{
797+ if (!IsLaunching()) {
798+ /*
799+ * This can happen if we are set to Single or Exclusive
800+ * Launch. Be nice and open the file(s).
801+ */
802+ if (gui.vimWindow)
803+ gui.vimWindow->Minimize(false);
804+ BMessage *m = CurrentMessage();
805+ DetachCurrentMessage();
806+ SendRefs(m, true);
807+ }
808+}
809+
810+ void
811+VimApp::RefsReceived(BMessage *m)
812+{
813+ // Horrible hack!!! XXX XXX XXX
814+ // The real problem is that b_start_ffc is set too late for
815+ // the initial empty buffer. As a result the window will be
816+ // split instead of abandoned.
817+ int limit = 15;
818+ while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0))
819+ snooze(100000); // 0.1 s
820+ if (gui.vimWindow)
821+ gui.vimWindow->Minimize(false);
822+ DetachCurrentMessage();
823+ SendRefs(m, true);
824+}
825+
826+/*
827+ * Pass a BMessage on to the main() thread.
828+ * Caller must have detached the message.
829+ */
830+ void
831+VimApp::SendRefs(BMessage *m, bool changedir)
832+{
833+ VimRefsMsg rm;
834+ rm.message = m;
835+ rm.changedir = changedir;
836+
837+ write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm));
838+ // calls ::RefsReceived
839+}
840+
841+ void
842+VimApp::MessageReceived(BMessage *m)
843+{
844+ switch (m->what) {
845+ case 'save':
846+ {
847+ entry_ref refDirectory;
848+ m->FindRef("directory", &refDirectory);
849+ fBrowsedPath.SetTo(&refDirectory);
850+ BString strName;
851+ m->FindString("name", &strName);
852+ fBrowsedPath.Append(strName.String());
853+ }
854+ break;
855+ case 'open':
856+ {
857+ entry_ref ref;
858+ m->FindRef("refs", &ref);
859+ fBrowsedPath.SetTo(&ref);
860+ }
861+ break;
862+ case B_CANCEL:
863+ {
864+ BFilePanel *panel;
865+ m->FindPointer("source", (void**)&panel);
866+ if(fFilePanelSem != -1 && panel == fFilePanel)
867+ {
868+ delete_sem(fFilePanelSem);
869+ fFilePanelSem = -1;
870+ }
871+
872+ }
873+ break;
874+ default:
875+ Inherited::MessageReceived(m);
876+ break;
877+ }
878+}
879+
880+ bool
881+VimApp::QuitRequested()
882+{
883+ (void)Inherited::QuitRequested();
884+ return false;
885+}
886+
887+// ---------------- VimWindow ----------------
888+
889+VimWindow::VimWindow():
890+ BWindow(BRect(40, 40, 150, 150),
891+ "Vim",
892+ B_TITLED_WINDOW,
893+ 0,
894+ B_CURRENT_WORKSPACE)
895+
896+{
897+ init();
898+}
899+
900+VimWindow::~VimWindow()
901+{
902+ if (formView) {
903+ RemoveChild(formView);
904+ delete formView;
905+ }
906+ gui.vimWindow = NULL;
907+}
908+
909+ void
910+VimWindow::init()
911+{
912+ // Attach the VimFormView
913+ formView = new VimFormView(Bounds());
914+ if (formView != NULL) {
915+ AddChild(formView);
916+ }
917+}
918+
919+#if 0 // disabled in zeta patch
920+ void
921+VimWindow::DispatchMessage(BMessage *m, BHandler *h)
922+{
923+ /*
924+ * Route B_MOUSE_UP messages to MouseUp(), in
925+ * a manner that should be compatible with the
926+ * intended future system behaviour.
927+ */
928+ switch (m->what) {
929+ case B_MOUSE_UP:
930+ // if (!h) h = PreferredHandler();
931+ // gcc isn't happy without this extra set of braces, complains about
932+ // jump to case label crosses init of 'class BView * v'
933+ // richard@whitequeen.com jul 99
934+ {
935+ BView *v = dynamic_cast<BView *>(h);
936+ if (v) {
937+ // m->PrintToStream();
938+ BPoint where;
939+ m->FindPoint("where", &where);
940+ v->MouseUp(where);
941+ } else {
942+ Inherited::DispatchMessage(m, h);
943+ }
944+ }
945+ break;
946+ default:
947+ Inherited::DispatchMessage(m, h);
948+ }
949+}
950+#endif
951+
952+ void
953+VimWindow::WindowActivated(bool active)
954+{
955+ Inherited::WindowActivated(active);
956+ // the textArea gets the keyboard action
957+ if (active && gui.vimTextArea)
958+ gui.vimTextArea->MakeFocus(true);
959+
960+ struct VimFocusMsg fm;
961+ fm.active = active;
962+
963+ write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm));
964+}
965+
966+ bool
967+VimWindow::QuitRequested()
968+{
969+ struct VimKeyMsg km;
970+ km.length = 5;
971+ memcpy((char *)km.chars, "\033:qa\r", km.length);
972+ km.csi_escape = false;
973+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
974+ return false;
975+}
976+
977+// ---------------- VimFormView ----------------
978+
979+VimFormView::VimFormView(BRect frame):
980+ BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES,
981+ B_WILL_DRAW | B_FRAME_EVENTS),
982+ menuBar(NULL),
983+#ifdef FEAT_TOOLBAR
984+ toolBar(NULL),
985+#endif
986+#ifdef FEAT_GUI_TABLINE
987+// showingTabLine(false),
988+ tabLine(NULL),
989+#endif
990+ textArea(NULL)
991+{
992+ init(frame);
993+}
994+
995+VimFormView::~VimFormView()
996+{
997+ if (menuBar) {
998+ RemoveChild(menuBar);
999+#ifdef never
1000+ // deleting the menuBar leads to SEGV on exit
1001+ // richard@whitequeen.com Jul 99
1002+ delete menuBar;
1003+#endif
1004+ }
1005+
1006+#ifdef FEAT_TOOLBAR
1007+ delete toolBar;
1008+#endif
1009+
1010+#ifdef FEAT_GUI_TABLINE
1011+ delete tabLine;
1012+#endif
1013+
1014+ if (textArea) {
1015+ RemoveChild(textArea);
1016+ delete textArea;
1017+ }
1018+ gui.vimForm = NULL;
1019+}
1020+
1021+ void
1022+VimFormView::init(BRect frame)
1023+{
1024+ menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN),
1025+ "VimMenuBar");
1026+
1027+ AddChild(menuBar);
1028+
1029+#ifdef FEAT_TOOLBAR
1030+ toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar");
1031+ toolBar->PrepareButtonBitmaps();
1032+ AddChild(toolBar);
1033+#endif
1034+
1035+#ifdef FEAT_GUI_TABLINE
1036+ tabLine = new VimTabLine(BRect(0,0,0,0));
1037+// tabLine->PrepareButtonBitmaps();
1038+ AddChild(tabLine);
1039+#endif
1040+
1041+ BRect remaining = frame;
1042+ textArea = new VimTextAreaView(remaining);
1043+ AddChild(textArea);
1044+ // The textArea will be resized later when menus are added
1045+
1046+ gui.vimForm = this;
1047+}
1048+
1049+#ifdef FEAT_TOOLBAR
1050+ float
1051+VimFormView::ToolbarHeight() const
1052+{
1053+ return toolBar ? toolBar->ToolbarHeight() : 0.;
1054+}
1055+#endif
1056+
1057+#ifdef FEAT_GUI_TABLINE
1058+ float
1059+VimFormView::TablineHeight() const
1060+{
1061+ return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.;
1062+}
1063+#endif
1064+
1065+ void
1066+VimFormView::AllAttached()
1067+{
1068+ /*
1069+ * Apparently signals are inherited by the created thread -
1070+ * disable the most annoying ones.
1071+ */
1072+ signal(SIGINT, SIG_IGN);
1073+ signal(SIGQUIT, SIG_IGN);
1074+
1075+ if (menuBar && textArea) {
1076+ /*
1077+ * Resize the textArea to fill the space left over by the menu.
1078+ * This is somewhat futile since it will be done again once
1079+ * menus are added to the menu bar.
1080+ */
1081+ BRect remaining = Bounds();
1082+
1083+#ifdef FEAT_MENU
1084+ remaining.top += MenuHeight();
1085+ menuBar->ResizeTo(remaining.right, remaining.top);
1086+ gui.menu_height = (int) MenuHeight();
1087+#endif
1088+
1089+#ifdef FEAT_TOOLBAR
1090+ toolBar->MoveTo(remaining.left, remaining.top);
1091+ toolBar->ResizeTo(remaining.right, ToolbarHeight());
1092+ remaining.top += ToolbarHeight();
1093+ gui.toolbar_height = ToolbarHeight();
1094+#endif
1095+
1096+#ifdef FEAT_GUI_TABLINE
1097+ tabLine->MoveTo(remaining.left, remaining.top);
1098+ tabLine->ResizeTo(remaining.right + 1, TablineHeight());
1099+ remaining.top += TablineHeight();
1100+ gui.tabline_height = TablineHeight();
1101+#endif
1102+
1103+ textArea->ResizeTo(remaining.Width(), remaining.Height());
1104+ textArea->MoveTo(remaining.left, remaining.top);
1105+ }
1106+
1107+
1108+ Inherited::AllAttached();
1109+}
1110+
1111+ void
1112+VimFormView::FrameResized(float new_width, float new_height)
1113+{
1114+ struct VimResizeMsg sm;
1115+ int adjust_h, adjust_w;
1116+
1117+ new_width += 1; // adjust from width to number of pixels occupied
1118+ new_height += 1;
1119+
1120+ sm.width = (int) new_width;
1121+ sm.height = (int) new_height;
1122+ adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width;
1123+ adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height;
1124+
1125+ if (adjust_w > 0 || adjust_h > 0) {
1126+ sm.width -= adjust_w;
1127+ sm.height -= adjust_h;
1128+ }
1129+
1130+ write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm));
1131+ // calls gui_resize_shell(new_width, new_height);
1132+
1133+ return;
1134+
1135+ /*
1136+ * The area below the vertical scrollbar is erased to the colour
1137+ * set with SetViewColor() automatically, because we had set
1138+ * B_WILL_DRAW. Resizing the window tight around the vertical
1139+ * scroll bar also helps to avoid debris.
1140+ */
1141+}
1142+
1143+// ---------------- VimTextAreaView ----------------
1144+
1145+VimTextAreaView::VimTextAreaView(BRect frame):
1146+ BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES,
1147+#ifdef FEAT_MBYTE_IME
1148+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INPUT_METHOD_AWARE),
1149+#else
1150+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
1151+#endif
1152+ mouseDragEventCount(0)
1153+{
1154+#ifdef FEAT_MBYTE_IME
1155+ IMData.messenger = NULL;
1156+ IMData.message = NULL;
1157+#endif
1158+ init(frame);
1159+}
1160+
1161+VimTextAreaView::~VimTextAreaView()
1162+{
1163+ gui.vimTextArea = NULL;
1164+}
1165+
1166+ void
1167+VimTextAreaView::init(BRect frame)
1168+{
1169+ // set up global var for fast access
1170+ gui.vimTextArea = this;
1171+
1172+ /*
1173+ * Tell the app server not to erase the view: we will
1174+ * fill it in completely by ourselves.
1175+ * (Does this really work? Even if not, it won't harm either.)
1176+ */
1177+ SetViewColor(B_TRANSPARENT_32_BIT);
1178+#define PEN_WIDTH 1
1179+ SetPenSize(PEN_WIDTH);
1180+#define W_WIDTH(curwin) 0
1181+}
1182+
1183+ void
1184+VimTextAreaView::Draw(BRect updateRect)
1185+{
1186+ /*
1187+ * XXX Other ports call here:
1188+ * out_flush(); * make sure all output has been processed *
1189+ * but we can't do that, since it involves too much information
1190+ * that is owned by other threads...
1191+ */
1192+
1193+ /*
1194+ * No need to use gui.vimWindow->Lock(): we are locked already.
1195+ * However, it would not hurt.
1196+ */
1197+ rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
1198+ SetLowColor(rgb);
1199+ FillRect(updateRect, B_SOLID_LOW);
1200+ gui_redraw((int) updateRect.left, (int) updateRect.top,
1201+ (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH));
1202+
1203+ // Clear the border areas if needed
1204+ SetLowColor(rgb);
1205+
1206+ if (updateRect.left < FILL_X(0)) // left border
1207+ FillRect(BRect(updateRect.left, updateRect.top,
1208+ FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW);
1209+ if (updateRect.top < FILL_Y(0)) // top border
1210+ FillRect(BRect(updateRect.left, updateRect.top,
1211+ updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW);
1212+ if (updateRect.right >= FILL_X(Columns)) // right border
1213+ FillRect(BRect(FILL_X((int)Columns), updateRect.top,
1214+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
1215+ if (updateRect.bottom >= FILL_Y(Rows)) // bottom border
1216+ FillRect(BRect(updateRect.left, FILL_Y((int)Rows),
1217+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
1218+
1219+#ifdef FEAT_MBYTE_IME
1220+ DrawIMString();
1221+#endif
1222+}
1223+
1224+ void
1225+VimTextAreaView::KeyDown(const char *bytes, int32 numBytes)
1226+{
1227+ struct VimKeyMsg km;
1228+ char_u *dest = km.chars;
1229+
1230+ bool canHaveVimModifiers = false;
1231+
1232+ BMessage *msg = Window()->CurrentMessage();
1233+ assert(msg);
1234+ // msg->PrintToStream();
1235+
1236+ /*
1237+ * Convert special keys to Vim codes.
1238+ * I think it is better to do it in the window thread
1239+ * so we use at least a little bit of the potential
1240+ * of our 2 CPUs. Besides, due to the fantastic mapping
1241+ * of special keys to UTF-8, we have quite some work to
1242+ * do...
1243+ * TODO: I'm not quite happy with detection of special
1244+ * keys. Perhaps I should use scan codes after all...
1245+ */
1246+ if (numBytes > 1) {
1247+ // This cannot be a special key
1248+ if (numBytes > KEY_MSG_BUFSIZ)
1249+ numBytes = KEY_MSG_BUFSIZ; // should never happen... ???
1250+ km.length = numBytes;
1251+ memcpy((char *)dest, bytes, numBytes);
1252+ km.csi_escape = true;
1253+ } else {
1254+ int32 scancode = 0;
1255+ msg->FindInt32("key", &scancode);
1256+
1257+ int32 beModifiers = 0;
1258+ msg->FindInt32("modifiers", &beModifiers);
1259+
1260+ char_u string[3];
1261+ int len = 0;
1262+ km.length = 0;
1263+
1264+ /*
1265+ * For normal, printable ASCII characters, don't look them up
1266+ * to check if they might be a special key. They aren't.
1267+ */
1268+ assert(B_BACKSPACE <= 0x20);
1269+ assert(B_DELETE == 0x7F);
1270+ if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) &&
1271+ numBytes == 1) {
1272+ /*
1273+ * Due to the great nature of Be's mapping of special keys,
1274+ * viz. into the range of the control characters,
1275+ * we can only be sure it is *really* a special key if
1276+ * if it is special without using ctrl. So, only if ctrl is
1277+ * used, we need to check it unmodified.
1278+ */
1279+ if (beModifiers & B_CONTROL_KEY) {
1280+ int index = keyMap->normal_map[scancode];
1281+ int newNumBytes = keyMapChars[index];
1282+ char_u *newBytes = (char_u *)&keyMapChars[index + 1];
1283+
1284+ /*
1285+ * Check if still special without the control key.
1286+ * This is needed for BACKSPACE: that key does produce
1287+ * different values with modifiers (DEL).
1288+ * Otherwise we could simply have checked for equality.
1289+ */
1290+ if (newNumBytes != 1 || (*newBytes > 0x20 &&
1291+ *newBytes != 0x7F )) {
1292+ goto notspecial;
1293+ }
1294+ bytes = (char *)newBytes;
1295+ }
1296+ canHaveVimModifiers = true;
1297+
1298+ uint16 beoskey;
1299+ int first, last;
1300+
1301+ /*
1302+ * If numBytes == 0 that probably always indicates a special key.
1303+ * (does not happen yet)
1304+ */
1305+ if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) {
1306+ beoskey = F(scancode);
1307+ first = FIRST_FUNCTION_KEY;
1308+ last = NUM_SPECIAL_KEYS;
1309+ } else if (*bytes == '\n' && scancode == 0x47) {
1310+ // remap the (non-keypad) ENTER key from \n to \r.
1311+ string[0] = '\r';
1312+ len = 1;
1313+ first = last = 0;
1314+ } else {
1315+ beoskey = K(bytes[0]);
1316+ first = 0;
1317+ last = FIRST_FUNCTION_KEY;
1318+ }
1319+
1320+ for (int i = first; i < last; i++) {
1321+ if (special_keys[i].BeKeys == beoskey) {
1322+ string[0] = CSI;
1323+ string[1] = special_keys[i].vim_code0;
1324+ string[2] = special_keys[i].vim_code1;
1325+ len = 3;
1326+ }
1327+ }
1328+ }
1329+notspecial:
1330+ if (len == 0) {
1331+ string[0] = bytes[0];
1332+ len = 1;
1333+ }
1334+
1335+ // Special keys (and a few others) may have modifiers
1336+#if 0
1337+ if (len == 3 ||
1338+ bytes[0] == B_SPACE || bytes[0] == B_TAB ||
1339+ bytes[0] == B_RETURN || bytes[0] == '\r' ||
1340+ bytes[0] == B_ESCAPE)
1341+#else
1342+ if (canHaveVimModifiers)
1343+#endif
1344+ {
1345+ int modifiers;
1346+ modifiers = 0;
1347+ if (beModifiers & B_SHIFT_KEY)
1348+ modifiers |= MOD_MASK_SHIFT;
1349+ if (beModifiers & B_CONTROL_KEY)
1350+ modifiers |= MOD_MASK_CTRL;
1351+ if (beModifiers & B_OPTION_KEY)
1352+ modifiers |= MOD_MASK_ALT;
1353+
1354+ /*
1355+ * For some keys a shift modifier is translated into another key
1356+ * code. Do we need to handle the case where len != 1 and
1357+ * string[0] != CSI? (Not for BeOS, since len == 3 implies
1358+ * string[0] == CSI...)
1359+ */
1360+ int key;
1361+ if (string[0] == CSI && len == 3)
1362+ key = TO_SPECIAL(string[1], string[2]);
1363+ else
1364+ key = string[0];
1365+ key = simplify_key(key, &modifiers);
1366+ if (IS_SPECIAL(key))
1367+ {
1368+ string[0] = CSI;
1369+ string[1] = K_SECOND(key);
1370+ string[2] = K_THIRD(key);
1371+ len = 3;
1372+ }
1373+ else
1374+ {
1375+ string[0] = key;
1376+ len = 1;
1377+ }
1378+
1379+ if (modifiers)
1380+ {
1381+ *dest++ = CSI;
1382+ *dest++ = KS_MODIFIER;
1383+ *dest++ = modifiers;
1384+ km.length = 3;
1385+ }
1386+ }
1387+ memcpy((char *)dest, string, len);
1388+ km.length += len;
1389+ km.csi_escape = false;
1390+ }
1391+
1392+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
1393+
1394+ /*
1395+ * blank out the pointer if necessary
1396+ */
1397+ if (p_mh && !gui.pointer_hidden)
1398+ {
1399+ guiBlankMouse(true);
1400+ gui.pointer_hidden = TRUE;
1401+ }
1402+}
1403+void
1404+VimTextAreaView::guiSendMouseEvent(
1405+ int button,
1406+ int x,
1407+ int y,
1408+ int repeated_click,
1409+ int_u modifiers)
1410+{
1411+ VimMouseMsg mm;
1412+
1413+ mm.button = button;
1414+ mm.x = x;
1415+ mm.y = y;
1416+ mm.repeated_click = repeated_click;
1417+ mm.modifiers = modifiers;
1418+
1419+ write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm));
1420+ // calls gui_send_mouse_event()
1421+
1422+ /*
1423+ * if our pointer is currently hidden, then we should show it.
1424+ */
1425+ if (gui.pointer_hidden)
1426+ {
1427+ guiBlankMouse(false);
1428+ gui.pointer_hidden = FALSE;
1429+ }
1430+}
1431+
1432+void
1433+VimTextAreaView::guiMouseMoved(
1434+ int x,
1435+ int y)
1436+{
1437+ VimMouseMovedMsg mm;
1438+
1439+ mm.x = x;
1440+ mm.y = y;
1441+
1442+ write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm));
1443+
1444+ if (gui.pointer_hidden)
1445+ {
1446+ guiBlankMouse(false);
1447+ gui.pointer_hidden = FALSE;
1448+ }
1449+}
1450+
1451+ void
1452+VimTextAreaView::guiBlankMouse(bool should_hide)
1453+{
1454+ if (should_hide) {
1455+ // gui.vimApp->HideCursor();
1456+ gui.vimApp->ObscureCursor();
1457+ /*
1458+ * ObscureCursor() would even be easier, but then
1459+ * Vim's idea of mouse visibility does not necessarily
1460+ * correspond to reality.
1461+ */
1462+ } else {
1463+ // gui.vimApp->ShowCursor();
1464+ }
1465+}
1466+
1467+ int_u
1468+VimTextAreaView::mouseModifiersToVim(int32 beModifiers)
1469+{
1470+ int_u vim_modifiers = 0x0;
1471+
1472+ if (beModifiers & B_SHIFT_KEY)
1473+ vim_modifiers |= MOUSE_SHIFT;
1474+ if (beModifiers & B_CONTROL_KEY)
1475+ vim_modifiers |= MOUSE_CTRL;
1476+ if (beModifiers & B_OPTION_KEY) // Alt or Meta key
1477+ vim_modifiers |= MOUSE_ALT;
1478+
1479+ return vim_modifiers;
1480+}
1481+
1482+ void
1483+VimTextAreaView::MouseDown(BPoint point)
1484+{
1485+ BMessage *m = Window()->CurrentMessage();
1486+ assert(m);
1487+
1488+ int32 buttons = 0;
1489+ m->FindInt32("buttons", &buttons);
1490+
1491+ int vimButton;
1492+
1493+ if (buttons & B_PRIMARY_MOUSE_BUTTON)
1494+ vimButton = MOUSE_LEFT;
1495+ else if (buttons & B_SECONDARY_MOUSE_BUTTON)
1496+ vimButton = MOUSE_RIGHT;
1497+ else if (buttons & B_TERTIARY_MOUSE_BUTTON)
1498+ vimButton = MOUSE_MIDDLE;
1499+ else
1500+ return; // Unknown button
1501+
1502+ vimMouseButton = 1; // don't care which one
1503+
1504+ // Handle multiple clicks
1505+ int32 clicks = 0;
1506+ m->FindInt32("clicks", &clicks);
1507+
1508+ int32 modifiers = 0;
1509+ m->FindInt32("modifiers", &modifiers);
1510+
1511+ vimMouseModifiers = mouseModifiersToVim(modifiers);
1512+
1513+ guiSendMouseEvent(vimButton, point.x, point.y,
1514+ clicks > 1 /* = repeated_click*/, vimMouseModifiers);
1515+}
1516+
1517+ void
1518+VimTextAreaView::MouseUp(BPoint point)
1519+{
1520+ vimMouseButton = 0;
1521+
1522+ BMessage *m = Window()->CurrentMessage();
1523+ assert(m);
1524+ // m->PrintToStream();
1525+
1526+ int32 modifiers = 0;
1527+ m->FindInt32("modifiers", &modifiers);
1528+
1529+ vimMouseModifiers = mouseModifiersToVim(modifiers);
1530+
1531+ guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y,
1532+ 0 /* = repeated_click*/, vimMouseModifiers);
1533+
1534+ Inherited::MouseUp(point);
1535+}
1536+
1537+ void
1538+VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
1539+{
1540+ /*
1541+ * if our pointer is currently hidden, then we should show it.
1542+ */
1543+ if (gui.pointer_hidden)
1544+ {
1545+ guiBlankMouse(false);
1546+ gui.pointer_hidden = FALSE;
1547+ }
1548+
1549+ if (!vimMouseButton) { // could also check m->"buttons"
1550+ guiMouseMoved(point.x, point.y);
1551+ return;
1552+ }
1553+
1554+ atomic_add(&mouseDragEventCount, 1);
1555+
1556+ // Don't care much about "transit"
1557+ guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers);
1558+}
1559+
1560+ void
1561+VimTextAreaView::MessageReceived(BMessage *m)
1562+{
1563+ switch (m->what) {
1564+ case 'menu':
1565+ {
1566+ VimMenuMsg mm;
1567+ mm.guiMenu = NULL; // in case no pointer in msg
1568+ m->FindPointer("VimMenu", (void **)&mm.guiMenu);
1569+ write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm));
1570+ }
1571+ break;
1572+ case B_MOUSE_WHEEL_CHANGED:
1573+ {
1574+ VimScrollBar* scb = curwin->w_scrollbars[1].id;
1575+ float small=0, big=0, dy=0;
1576+ m->FindFloat("be:wheel_delta_y", &dy);
1577+ scb->GetSteps(&small, &big);
1578+ scb->SetValue(scb->Value()+small*dy*3);
1579+ scb->ValueChanged(scb->Value());
1580+#if 0
1581+ scb = curwin->w_scrollbars[0].id;
1582+ scb->GetSteps(&small, &big);
1583+ scb->SetValue(scb->Value()+small*dy);
1584+ scb->ValueChanged(scb->Value());
1585+#endif
1586+ }
1587+ break;
1588+#ifdef FEAT_MBYTE_IME
1589+ case B_INPUT_METHOD_EVENT:
1590+ {
1591+ int32 opcode;
1592+ m->FindInt32("be:opcode", &opcode);
1593+ switch(opcode)
1594+ {
1595+ case B_INPUT_METHOD_STARTED:
1596+ if(!IMData.messenger) delete IMData.messenger;
1597+ IMData.messenger = new BMessenger();
1598+ m->FindMessenger("be:reply_to", IMData.messenger);
1599+ break;
1600+ case B_INPUT_METHOD_CHANGED:
1601+ {
1602+ BString str;
1603+ bool confirmed;
1604+ if(IMData.message) *(IMData.message) = *m;
1605+ else IMData.message = new BMessage(*m);
1606+ DrawIMString();
1607+ m->FindBool("be:confirmed", &confirmed);
1608+ if (confirmed)
1609+ {
1610+ m->FindString("be:string", &str);
1611+ char_u *chars = (char_u*)str.String();
1612+ struct VimKeyMsg km;
1613+ km.csi_escape = true;
1614+ int clen;
1615+ int i = 0;
1616+ while (i < str.Length())
1617+ {
1618+ clen = utf_ptr2len(chars+i);
1619+ memcpy(km.chars, chars+i, clen);
1620+ km.length = clen;
1621+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
1622+ i += clen;
1623+ }
1624+ }
1625+ }
1626+ break;
1627+ case B_INPUT_METHOD_LOCATION_REQUEST:
1628+ {
1629+ BMessage msg(B_INPUT_METHOD_EVENT);
1630+ msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
1631+ msg.AddPoint("be:location_reply", IMData.location);
1632+ msg.AddFloat("be:height_reply", FILL_Y(1));
1633+ IMData.messenger->SendMessage(&msg);
1634+ }
1635+ break;
1636+ case B_INPUT_METHOD_STOPPED:
1637+ delete IMData.messenger;
1638+ delete IMData.message;
1639+ IMData.messenger = NULL;
1640+ IMData.message = NULL;
1641+ break;
1642+ }
1643+ }
1644+ // TODO: sz: break here???
1645+#endif
1646+ default:
1647+ if (m->WasDropped()) {
1648+ BWindow *w = Window();
1649+ w->DetachCurrentMessage();
1650+ w->Minimize(false);
1651+ VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0);
1652+ } else {
1653+ Inherited::MessageReceived(m);
1654+ }
1655+ break;
1656+ }
1657+}
1658+
1659+ int
1660+VimTextAreaView::mchInitFont(char_u *name)
1661+{
1662+ VimFont *newFont = (VimFont *)gui_mch_get_font(name, 1);
1663+ if(newFont != NOFONT) {
1664+ gui.norm_font = (GuiFont)newFont;
1665+ gui_mch_set_font((GuiFont)newFont);
1666+ if (name && STRCMP(name, "*") != 0)
1667+ hl_set_font_name(name);
1668+
1669+ SetDrawingMode(B_OP_COPY);
1670+
1671+ /*
1672+ * Try to load other fonts for bold, italic, and bold-italic.
1673+ * We should also try to work out what font to use for these when they are
1674+ * not specified by X resources, but we don't yet.
1675+ */
1676+ return OK;
1677+ }
1678+ return FAIL;
1679+}
1680+
1681+ void
1682+VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags)
1683+{
1684+ /*
1685+ * First we must erase the area, because DrawString won't do
1686+ * that for us. XXX Most of the time this is a waste of effort
1687+ * since the bachground has been erased already... DRAW_TRANSP
1688+ * should be set when appropriate!!!
1689+ * (Rectangles include the bottom and right edge)
1690+ */
1691+ if (!(flags & DRAW_TRANSP)) {
1692+ int cells;
1693+ cells = 0;
1694+ for(int i=0; i<len; i++) {
1695+ int cn = utf_ptr2cells((char_u *)(s+i));
1696+ if(cn<4) cells += cn;
1697+ }
1698+
1699+ BRect r(FILL_X(col), FILL_Y(row),
1700+ FILL_X(col + cells) - PEN_WIDTH, FILL_Y(row + 1) - PEN_WIDTH);
1701+ FillRect(r, B_SOLID_LOW);
1702+ }
1703+
1704+ BFont font;
1705+ this->GetFont(&font);
1706+ if(!font.IsFixed())
1707+ {
1708+ char* p = (char*)s;
1709+ int32 clen, lastpos = 0;
1710+ BPoint where;
1711+ int cells;
1712+ while((p - (char*)s) < len) {
1713+ clen = utf_ptr2len((u_char*)p);
1714+ where.Set(TEXT_X(col+lastpos), TEXT_Y(row));
1715+ DrawString(p, clen, where);
1716+ if (flags & DRAW_BOLD) {
1717+ where.x += 1.0;
1718+ SetDrawingMode(B_OP_BLEND);
1719+ DrawString(p, clen, where);
1720+ SetDrawingMode(B_OP_COPY);
1721+ }
1722+ cells = utf_ptr2cells((char_u *)p);
1723+ if(cells<4) lastpos += cells;
1724+ else lastpos++;
1725+ p += clen;
1726+ }
1727+ }
1728+ else
1729+ {
1730+ BPoint where(TEXT_X(col), TEXT_Y(row));
1731+ DrawString((char*)s, len, where);
1732+ if (flags & DRAW_BOLD) {
1733+ where.x += 1.0;
1734+ SetDrawingMode(B_OP_BLEND);
1735+ DrawString((char*)s, len, where);
1736+ SetDrawingMode(B_OP_COPY);
1737+ }
1738+ }
1739+
1740+ if (flags & DRAW_UNDERL) {
1741+ int cells;
1742+ cells = 0;
1743+ for(int i=0; i<len; i++) {
1744+ int cn = utf_ptr2cells((char_u *)(s+i));
1745+ if(cn<4) cells += cn;
1746+ }
1747+
1748+ BPoint start(FILL_X(col), FILL_Y(row + 1) - PEN_WIDTH);
1749+ BPoint end(FILL_X(col + cells) - PEN_WIDTH, start.y);
1750+
1751+ StrokeLine(start, end);
1752+ }
1753+}
1754+
1755+void
1756+VimTextAreaView::mchClearBlock(
1757+ int row1,
1758+ int col1,
1759+ int row2,
1760+ int col2)
1761+{
1762+ BRect r(FILL_X(col1), FILL_Y(row1),
1763+ FILL_X(col2 + 1) - PEN_WIDTH, FILL_Y(row2 + 1) - PEN_WIDTH);
1764+ gui_mch_set_bg_color(gui.back_pixel);
1765+ FillRect(r, B_SOLID_LOW);
1766+}
1767+
1768+ void
1769+VimTextAreaView::mchClearAll()
1770+{
1771+ gui_mch_set_bg_color(gui.back_pixel);
1772+ FillRect(Bounds(), B_SOLID_LOW);
1773+}
1774+
1775+/*
1776+ * mchDeleteLines() Lock()s the window by itself.
1777+ */
1778+ void
1779+VimTextAreaView::mchDeleteLines(int row, int num_lines)
1780+{
1781+ BRect source, dest;
1782+ source.left = FILL_X(gui.scroll_region_left);
1783+ source.top = FILL_Y(row + num_lines);
1784+ source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
1785+ source.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
1786+
1787+ dest.left = FILL_X(gui.scroll_region_left);
1788+ dest.top = FILL_Y(row);
1789+ dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
1790+ dest.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
1791+
1792+ if (gui.vimWindow->Lock()) {
1793+ // Clear one column more for when bold has spilled over
1794+ CopyBits(source, dest);
1795+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
1796+ gui.scroll_region_left,
1797+ gui.scroll_region_bot, gui.scroll_region_right);
1798+
1799+
1800+ gui.vimWindow->Unlock();
1801+ /*
1802+ * The Draw() callback will be called now if some of the source
1803+ * bits were not in the visible region.
1804+ */
1805+ }
1806+ // gui_x11_check_copy_area();
1807+ // }
1808+}
1809+
1810+/*
1811+ * mchInsertLines() Lock()s the window by itself.
1812+ */
1813+ void
1814+VimTextAreaView::mchInsertLines(int row, int num_lines)
1815+{
1816+ BRect source, dest;
1817+
1818+ // XXX Attempt at a hack:
1819+ gui.vimWindow->UpdateIfNeeded();
1820+ source.left = FILL_X(gui.scroll_region_left);
1821+ source.top = FILL_Y(row);
1822+ source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
1823+ source.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
1824+
1825+ dest.left = FILL_X(gui.scroll_region_left);
1826+ dest.top = FILL_Y(row + num_lines);
1827+ dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
1828+ dest.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
1829+
1830+ if (gui.vimWindow->Lock()) {
1831+ // Clear one column more for when bold has spilled over
1832+ CopyBits(source, dest);
1833+ gui_clear_block(row, gui.scroll_region_left,
1834+ row + num_lines - 1, gui.scroll_region_right);
1835+
1836+ gui.vimWindow->Unlock();
1837+ /*
1838+ * The Draw() callback will be called now if some of the source
1839+ * bits were not in the visible region.
1840+ * However, if we scroll too fast it can't keep up and the
1841+ * update region gets messed up. This seems to be because copying
1842+ * un-Draw()n bits does not generate Draw() calls for the copy...
1843+ * I moved the hack to before the CopyBits() to reduce the
1844+ * amount of additional waiting needed.
1845+ */
1846+
1847+ // gui_x11_check_copy_area();
1848+
1849+ }
1850+}
1851+
1852+#ifdef FEAT_MBYTE_IME
1853+/*
1854+ * DrawIMString draws string with IMData.message.
1855+ */
1856+void VimTextAreaView::DrawIMString(void)
1857+{
1858+ static const rgb_color r_highlight = {255, 152, 152, 255},
1859+ b_highlight = {152, 203, 255, 255};
1860+ BString str;
1861+ const char* s;
1862+ int len;
1863+ BMessage* msg = IMData.message;
1864+ if (!msg)
1865+ return;
1866+ gui_redraw_block(IMData.row, 0,
1867+ IMData.row + IMData.count, W_WIDTH(curwin), GUI_MON_NOCLEAR);
1868+ bool confirmed = false;
1869+ msg->FindBool("be:confirmed", &confirmed);
1870+ if (confirmed)
1871+ return;
1872+ rgb_color hcolor = HighColor(), lcolor = LowColor();
1873+ msg->FindString("be:string", &str);
1874+ s = str.String();
1875+ len = str.Length();
1876+ SetHighColor(0, 0, 0);
1877+ IMData.row = gui.row;
1878+ IMData.col = gui.col;
1879+ int32 sel_start = 0, sel_end = 0;
1880+ msg->FindInt32("be:selection", 0, &sel_start);
1881+ msg->FindInt32("be:selection", 1, &sel_end);
1882+ int clen, cn;
1883+ BPoint pos(IMData.col, 0);
1884+ BRect r;
1885+ BPoint where;
1886+ IMData.location = ConvertToScreen(
1887+ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
1888+ for (int i=0; i<len; i+=clen)
1889+ {
1890+ cn = utf_ptr2cells((char_u *)(s+i));
1891+ clen = utf_ptr2len((char_u *)(s+i));
1892+ if (pos.x + cn > W_WIDTH(curwin))
1893+ {
1894+ pos.y++;
1895+ pos.x = 0;
1896+ }
1897+ if (sel_start<=i && i<sel_end)
1898+ {
1899+ SetLowColor(r_highlight);
1900+ IMData.location = ConvertToScreen(
1901+ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
1902+ }
1903+ else
1904+ {
1905+ SetLowColor(b_highlight);
1906+ }
1907+ r.Set(FILL_X(pos.x), FILL_Y(IMData.row + pos.y),
1908+ FILL_X(pos.x + cn) - PEN_WIDTH,
1909+ FILL_Y(IMData.row + pos.y + 1) - PEN_WIDTH);
1910+ FillRect(r, B_SOLID_LOW);
1911+ where.Set(TEXT_X(pos.x), TEXT_Y(IMData.row + pos.y));
1912+ DrawString((s+i), clen, where);
1913+ pos.x += cn;
1914+ }
1915+ IMData.count = (int)pos.y;
1916+
1917+ SetHighColor(hcolor);
1918+ SetLowColor(lcolor);
1919+}
1920+#endif
1921+// ---------------- VimScrollBar ----------------
1922+
1923+/*
1924+ * BUG: XXX
1925+ * It seems that BScrollBar determine their direction not from
1926+ * "posture" but from if they are "tall" or "wide" in shape...
1927+ *
1928+ * Also, place them out of sight, because Vim enables them before
1929+ * they are positioned.
1930+ */
1931+VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
1932+ BScrollBar(posture == B_HORIZONTAL ? BRect(-100,-100,-10,-90) :
1933+ BRect(-100,-100,-90,-10),
1934+ "vim scrollbar", (BView *)NULL,
1935+ 0.0, 10.0, posture),
1936+ ignoreValue(-1),
1937+ scrollEventCount(0)
1938+{
1939+ gsb = g;
1940+ SetResizingMode(B_FOLLOW_NONE);
1941+}
1942+
1943+VimScrollBar::~VimScrollBar()
1944+{
1945+}
1946+
1947+ void
1948+VimScrollBar::ValueChanged(float newValue)
1949+{
1950+ if (ignoreValue >= 0.0 && newValue == ignoreValue) {
1951+ ignoreValue = -1;
1952+ return;
1953+ }
1954+ ignoreValue = -1;
1955+ /*
1956+ * We want to throttle the amount of scroll messages generated.
1957+ * Normally I presume you won't get a new message before we've
1958+ * handled the previous one, but because we're passing them on this
1959+ * happens very quickly. So instead we keep a counter of how many
1960+ * scroll events there are (or will be) in the VDCMP, and the
1961+ * throttling happens at the receiving end.
1962+ */
1963+ atomic_add(&scrollEventCount, 1);
1964+
1965+ struct VimScrollBarMsg sm;
1966+
1967+ sm.sb = this;
1968+ sm.value = (long) newValue;
1969+ sm.stillDragging = TRUE;
1970+
1971+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
1972+
1973+ // calls gui_drag_scrollbar(sb, newValue, TRUE);
1974+}
1975+
1976+/*
1977+ * When the mouse goes up, report that scrolling has stopped.
1978+ * MouseUp() is NOT called when the mouse-up occurs outside
1979+ * the window, even though the thumb does move while the mouse
1980+ * is outside... This has some funny effects... XXX
1981+ * So we do special processing when the window de/activates.
1982+ */
1983+ void
1984+VimScrollBar::MouseUp(BPoint where)
1985+{
1986+ // BMessage *m = Window()->CurrentMessage();
1987+ // m->PrintToStream();
1988+
1989+ atomic_add(&scrollEventCount, 1);
1990+
1991+ struct VimScrollBarMsg sm;
1992+
1993+ sm.sb = this;
1994+ sm.value = (long) Value();
1995+ sm.stillDragging = FALSE;
1996+
1997+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
1998+
1999+ // calls gui_drag_scrollbar(sb, newValue, FALSE);
2000+
2001+ Inherited::MouseUp(where);
2002+}
2003+
2004+ void
2005+VimScrollBar::SetValue(float newValue)
2006+{
2007+ if (newValue == Value())
2008+ return;
2009+
2010+ ignoreValue = newValue;
2011+ Inherited::SetValue(newValue);
2012+}
2013+
2014+// ---------------- VimFont ----------------
2015+
2016+VimFont::VimFont(): BFont()
2017+{
2018+ init();
2019+}
2020+
2021+VimFont::VimFont(const VimFont *rhs): BFont(rhs)
2022+{
2023+ init();
2024+}
2025+
2026+VimFont::VimFont(const BFont *rhs): BFont(rhs)
2027+{
2028+ init();
2029+}
2030+
2031+VimFont::VimFont(const VimFont &rhs): BFont(rhs)
2032+{
2033+ init();
2034+}
2035+
2036+VimFont::~VimFont()
2037+{
2038+}
2039+
2040+ void
2041+VimFont::init()
2042+{
2043+ next = NULL;
2044+ refcount = 1;
2045+ name = NULL;
2046+}
2047+
2048+// ---------------- VimDialog ----------------
2049+
2050+#if defined(FEAT_GUI_DIALOG)
2051+
2052+const unsigned int kVimDialogButtonMsg = 'VMDB';
2053+const unsigned int kVimDialogIconStripeWidth = 30;
2054+const unsigned int kVimDialogButtonsSpacingX = 9;
2055+const unsigned int kVimDialogButtonsSpacingY = 4;
2056+const unsigned int kVimDialogSpacingX = 6;
2057+const unsigned int kVimDialogSpacingY = 10;
2058+const unsigned int kVimDialogMinimalWidth = 310;
2059+const unsigned int kVimDialogMinimalHeight = 75;
2060+const BRect kDefaultRect =
2061+BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight);
2062+
2063+VimDialog::VimDialog(int type, const char *title, const char *message,
2064+ const char *buttons, int dfltbutton, const char *textfield, int ex_cmd)
2065+: BWindow(kDefaultRect, title, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
2066+ B_NOT_CLOSABLE | B_NOT_RESIZABLE |
2067+ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
2068+ , fDialogSem(-1)
2069+ , fDialogValue(dfltbutton)
2070+ , fMessageView(NULL)
2071+ , fInputControl(NULL)
2072+ , fInputValue(textfield)
2073+{
2074+ // master view
2075+ VimDialog::View* view = new VimDialog::View(Bounds());
2076+ if(view == NULL)
2077+ return;
2078+
2079+ if(title == NULL)
2080+ SetTitle("Vim " VIM_VERSION_MEDIUM);
2081+
2082+ AddChild(view);
2083+
2084+ // icon
2085+ view->InitIcon(type);
2086+
2087+ // buttons
2088+ int32 which = 1;
2089+ float maxButtonWidth = 0;
2090+ float maxButtonHeight = 0;
2091+ float buttonsWidth = 0;
2092+ float buttonsHeight = 0;
2093+ BString strButtons(buttons);
2094+ strButtons.RemoveAll("&");
2095+ do {
2096+ int32 end = strButtons.FindFirst('\n');
2097+ if(end != B_ERROR)
2098+ strButtons.SetByteAt(end, '\0');
2099+
2100+ BButton *button = _CreateButton(which++, strButtons.String());
2101+ view->AddChild(button);
2102+ fButtonsList.AddItem(button);
2103+
2104+ maxButtonWidth = max_c(maxButtonWidth, button->Bounds().Width());
2105+ maxButtonHeight = max_c(maxButtonHeight, button->Bounds().Height());
2106+ buttonsWidth += button->Bounds().Width();
2107+ buttonsHeight += button->Bounds().Height();
2108+
2109+ if(end == B_ERROR)
2110+ break;
2111+
2112+ strButtons.Remove(0, end + 1);
2113+ } while(true);
2114+
2115+ int32 buttonsCount = fButtonsList.CountItems();
2116+ buttonsWidth += kVimDialogButtonsSpacingX * (buttonsCount - 1);
2117+ buttonsHeight += kVimDialogButtonsSpacingY * (buttonsCount - 1);
2118+ float dialogWidth = buttonsWidth + kVimDialogIconStripeWidth +
2119+ kVimDialogSpacingX * 2;
2120+ float dialogHeight = maxButtonHeight + kVimDialogSpacingY * 3;
2121+
2122+ // Check 'v' flag in 'guioptions': vertical button placement.
2123+ bool vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL) ||
2124+ dialogWidth >= gui.vimWindow->Bounds().Width();
2125+ if(vertical) {
2126+ dialogWidth -= buttonsWidth;
2127+ dialogWidth += maxButtonWidth;
2128+ dialogHeight -= maxButtonHeight;
2129+ dialogHeight += buttonsHeight;
2130+ }
2131+
2132+ dialogWidth = max_c(dialogWidth, kVimDialogMinimalWidth);
2133+
2134+ // message view
2135+ BRect rect(0, 0, dialogWidth, 0);
2136+ rect.left += kVimDialogIconStripeWidth + 16 + kVimDialogSpacingX;
2137+ rect.top += kVimDialogSpacingY;
2138+ rect.right -= kVimDialogSpacingX;
2139+ rect.bottom = rect.top;
2140+ fMessageView = new BTextView(rect, "_tv_", rect.OffsetByCopy(B_ORIGIN),
2141+ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
2142+
2143+ fMessageView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
2144+ rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
2145+ fMessageView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
2146+ fMessageView->SetText(message);
2147+ fMessageView->MakeEditable(false);
2148+ fMessageView->MakeSelectable(false);
2149+ fMessageView->SetWordWrap(true);
2150+ AddChild(fMessageView);
2151+
2152+ float messageHeight = fMessageView->TextHeight(0, fMessageView->CountLines());
2153+ fMessageView->ResizeBy(0, messageHeight);
2154+ fMessageView->SetTextRect(BRect(0, 0, rect.Width(), messageHeight));
2155+
2156+ dialogHeight += messageHeight;
2157+
2158+ // input view
2159+ if(fInputValue != NULL) {
2160+ rect.top =
2161+ rect.bottom += messageHeight + kVimDialogSpacingY;
2162+ fInputControl = new BTextControl(rect, "_iv_", NULL, fInputValue, NULL,
2163+ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED);
2164+ fInputControl->TextView()->SetText(fInputValue);
2165+ fInputControl->TextView()->SetWordWrap(false);
2166+ AddChild(fInputControl);
2167+
2168+ float width = 0.f, height = 0.f;
2169+ fInputControl->GetPreferredSize(&width, &height);
2170+ fInputControl->MakeFocus(true);
2171+
2172+ dialogHeight += height + kVimDialogSpacingY * 1.5;
2173+ }
2174+
2175+ dialogHeight = max_c(dialogHeight, kVimDialogMinimalHeight);
2176+
2177+ ResizeTo(dialogWidth, dialogHeight);
2178+ MoveTo((gui.vimWindow->Bounds().Width() - dialogWidth) / 2,
2179+ (gui.vimWindow->Bounds().Height() - dialogHeight) / 2);
2180+
2181+ // adjust layout of buttons
2182+ float buttonWidth = max_c(maxButtonWidth, rect.Width() * 0.66);
2183+ BPoint origin(dialogWidth, dialogHeight);
2184+ origin.x -= kVimDialogSpacingX + (vertical ? buttonWidth : buttonsWidth);
2185+ origin.y -= kVimDialogSpacingY + (vertical ? buttonsHeight : maxButtonHeight);
2186+
2187+ for(int32 i = 0 ; i < buttonsCount; i++) {
2188+ BButton *button = (BButton*)fButtonsList.ItemAt(i);
2189+ button->MoveTo(origin);
2190+ if(vertical) {
2191+ origin.y += button->Frame().Height() + kVimDialogButtonsSpacingY;
2192+ button->ResizeTo(buttonWidth, button->Frame().Height());
2193+ } else
2194+ origin.x += button->Frame().Width() + kVimDialogButtonsSpacingX;
2195+
2196+ if(dfltbutton == i + 1) {
2197+ button->MakeDefault(true);
2198+ button->MakeFocus(fInputControl == NULL);
2199+ }
2200+ }
2201+}
2202+
2203+VimDialog::~VimDialog()
2204+{
2205+ if(fDialogSem > B_OK)
2206+ delete_sem(fDialogSem);
2207+}
2208+
2209+ int
2210+VimDialog::Go()
2211+{
2212+ fDialogSem = create_sem(0, "VimDialogSem");
2213+ if(fDialogSem < B_OK) {
2214+ Quit();
2215+ return fDialogValue;
2216+ }
2217+
2218+ Show();
2219+
2220+ while(acquire_sem(fDialogSem) == B_INTERRUPTED);
2221+
2222+ int retValue = fDialogValue;
2223+ if(fInputValue != NULL)
2224+ vim_strncpy((char_u*)fInputValue, (char_u*)fInputControl->Text(), IOSIZE - 1);
2225+
2226+ if(Lock())
2227+ Quit();
2228+
2229+ return retValue;
2230+}
2231+
2232+void VimDialog::MessageReceived(BMessage *msg)
2233+{
2234+ int32 which = 0;
2235+ if(msg->what != kVimDialogButtonMsg ||
2236+ msg->FindInt32("which", &which) != B_OK)
2237+ return BWindow::MessageReceived(msg);
2238+
2239+ fDialogValue = which;
2240+ delete_sem(fDialogSem);
2241+ fDialogSem = -1;
2242+}
2243+
2244+BButton* VimDialog::_CreateButton(int32 which, const char* label)
2245+{
2246+ BMessage *message = new BMessage(kVimDialogButtonMsg);
2247+ message->AddInt32("which", which);
2248+
2249+ BRect rect(0, 0, 0, 0);
2250+ BString name;
2251+ name << "_b" << which << "_";
2252+
2253+ BButton* button = new BButton(rect, name.String(), label, message,
2254+ B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
2255+
2256+ float width = 0.f, height = 0.f;
2257+ button->GetPreferredSize(&width, &height);
2258+ button->ResizeTo(width, height);
2259+
2260+ return button;
2261+}
2262+
2263+VimDialog::View::View(BRect frame)
2264+ : BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
2265+ fIconBitmap(NULL)
2266+{
2267+ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
2268+}
2269+
2270+VimDialog::View::~View()
2271+{
2272+ delete fIconBitmap;
2273+}
2274+
2275+void VimDialog::View::Draw(BRect updateRect)
2276+{
2277+ BRect stripeRect = Bounds();
2278+ stripeRect.right = kVimDialogIconStripeWidth;
2279+ SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
2280+ FillRect(stripeRect);
2281+
2282+ if(fIconBitmap == NULL)
2283+ return;
2284+
2285+ SetDrawingMode(B_OP_ALPHA);
2286+ SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
2287+ DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
2288+}
2289+
2290+void VimDialog::View::InitIcon(int32 type)
2291+{
2292+ if(type == VIM_GENERIC)
2293+ return;
2294+
2295+ BPath path;
2296+ status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
2297+ if(status != B_OK) {
2298+ fprintf(stderr, "Cannot retrieve app info:%s\n", strerror(status));
2299+ return;
2300+ }
2301+
2302+ path.Append("app_server");
2303+
2304+ BFile file(path.Path(), O_RDONLY);
2305+ if(file.InitCheck() != B_OK) {
2306+ fprintf(stderr, "App file assignment failed:%s\n",
2307+ strerror(file.InitCheck()));
2308+ return;
2309+ }
2310+
2311+ BResources resources(&file);
2312+ if(resources.InitCheck() != B_OK) {
2313+ fprintf(stderr, "App server resources assignment failed:%s\n",
2314+ strerror(resources.InitCheck()));
2315+ return;
2316+ }
2317+
2318+ const char *name = "";
2319+ switch(type) {
2320+ case VIM_ERROR: name = "stop"; break;
2321+ case VIM_WARNING: name = "warn"; break;
2322+ case VIM_INFO: name = "info"; break;
2323+ case VIM_QUESTION: name = "idea"; break;
2324+ default: return;
2325+ }
2326+
2327+ int32 iconSize = 32;
2328+ fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
2329+ if(fIconBitmap == NULL || fIconBitmap->InitCheck() != B_OK) {
2330+ fprintf(stderr, "Icon bitmap allocation failed:%s\n",
2331+ (fIconBitmap == NULL) ? "null" : strerror(fIconBitmap->InitCheck()));
2332+ return;
2333+ }
2334+
2335+ size_t size = 0;
2336+ const uint8* iconData = NULL;
2337+ // try vector icon first?
2338+ iconData = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, name, &size);
2339+ if(iconData != NULL && BIconUtils::GetVectorIcon(iconData, size, fIconBitmap) == B_OK)
2340+ return;
2341+
2342+ // try bitmap icon now
2343+ iconData = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE, name, &size);
2344+ if(iconData == NULL) {
2345+ fprintf(stderr, "Bitmap icon resource not found\n");
2346+ delete fIconBitmap;
2347+ fIconBitmap = NULL;
2348+ return;
2349+ }
2350+
2351+ if(fIconBitmap->ColorSpace() != B_CMAP8)
2352+ BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
2353+}
2354+
2355+const unsigned int kVimDialogOKButtonMsg = 'FDOK';
2356+const unsigned int kVimDialogCancelButtonMsg = 'FDCN';
2357+const unsigned int kVimDialogSizeInputMsg = 'SICH';
2358+const unsigned int kVimDialogFamilySelectMsg = 'MSFM';
2359+const unsigned int kVimDialogStyleSelectMsg = 'MSST';
2360+const unsigned int kVimDialogSizeSelectMsg = 'MSSZ';
2361+
2362+VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size)
2363+: BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
2364+ B_NOT_CLOSABLE | B_NOT_RESIZABLE |
2365+ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
2366+ , fStatus(B_NO_INIT)
2367+ , fDialogSem(-1)
2368+ , fDialogValue(false)
2369+ , fFamily(family)
2370+ , fStyle(style)
2371+ , fSize(size)
2372+ , fFontSize(*size)
2373+ , fPreview(0)
2374+ , fFamiliesList(0)
2375+ , fStylesList(0)
2376+ , fSizesList(0)
2377+ , fSizesInput(0)
2378+{
2379+ strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH);
2380+ strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH);
2381+
2382+ // "client" area view
2383+ BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
2384+ B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED,
2385+ B_PLAIN_BORDER);
2386+ AddChild(clientBox);
2387+
2388+ // client view
2389+ BRect RC = clientBox->Bounds();
2390+ RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY);
2391+ BRect rc(RC.LeftTop(), RC.LeftTop());
2392+
2393+ // at first create all controls
2394+ fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono");
2395+ clientBox->AddChild(fPreview);
2396+
2397+ BBox* boxDivider = new BBox(rc, B_EMPTY_STRING,
2398+ B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER);
2399+ clientBox->AddChild(boxDivider);
2400+
2401+ BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:");
2402+ clientBox->AddChild(labelFamily);
2403+ labelFamily->ResizeToPreferred();
2404+
2405+ BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:");
2406+ clientBox->AddChild(labelStyle);
2407+ labelStyle->ResizeToPreferred();
2408+
2409+ BStringView *labelSize = new BStringView(rc, "labelSize", "Size:");
2410+ clientBox->AddChild(labelSize);
2411+ labelSize->ResizeToPreferred();
2412+
2413+ fFamiliesList = new BListView(rc, "listFamily",
2414+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
2415+ BScrollView *scrollFamilies = new BScrollView("scrollFamily",
2416+ fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
2417+ clientBox->AddChild(scrollFamilies);
2418+
2419+ fStylesList= new BListView(rc, "listStyles",
2420+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
2421+ BScrollView *scrollStyles = new BScrollView("scrollStyle",
2422+ fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
2423+ clientBox->AddChild(scrollStyles);
2424+
2425+ fSizesInput = new BTextControl(rc, "inputSize", NULL, "???",
2426+ new BMessage(kVimDialogSizeInputMsg));
2427+ clientBox->AddChild(fSizesInput);
2428+ fSizesInput->ResizeToPreferred();
2429+
2430+ fSizesList = new BListView(rc, "listSizes",
2431+ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
2432+ BScrollView *scrollSizes = new BScrollView("scrollSize",
2433+ fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
2434+ clientBox->AddChild(scrollSizes);
2435+
2436+ BButton *buttonOK = new BButton(rc, "buttonOK", "OK",
2437+ new BMessage(kVimDialogOKButtonMsg));
2438+ clientBox->AddChild(buttonOK);
2439+ buttonOK->ResizeToPreferred();
2440+
2441+ BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel",
2442+ new BMessage(kVimDialogCancelButtonMsg));
2443+ clientBox->AddChild(buttonCancel);
2444+ buttonCancel->ResizeToPreferred();
2445+
2446+ // layout controls
2447+ float lineHeight = labelFamily->Bounds().Height();
2448+ float previewHeight = lineHeight * 3;
2449+ float offsetYLabels = previewHeight + kVimDialogSpacingY;
2450+ float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2;
2451+ float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2;
2452+ float listsHeight = lineHeight * 9;
2453+ float offsetYButtons = offsetYLists + listsHeight + kVimDialogSpacingY;
2454+ float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height();
2455+ float familiesWidth = labelFamily->Bounds().Width() * 5;
2456+ float offsetXStyles = familiesWidth + kVimDialogSpacingX;
2457+ float stylesWidth = labelStyle->Bounds().Width() * 4;
2458+ float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX;
2459+ float sizesWidth = labelSize->Bounds().Width() * 2;
2460+ float maxControlsWidth = offsetXSizes + sizesWidth;
2461+
2462+ ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2,
2463+ maxControlsHeight + kVimDialogSpacingY * 2);
2464+
2465+ BRect rcVim = gui.vimWindow->Frame();
2466+ MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2,
2467+ rcVim.top + (rcVim.Height() - Frame().Height()) / 2);
2468+
2469+ fPreview->ResizeTo(maxControlsWidth, previewHeight);
2470+ fPreview->SetAlignment(B_ALIGN_CENTER);
2471+
2472+ boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2);
2473+ boxDivider->ResizeTo(maxControlsWidth, 1.f);
2474+
2475+ labelFamily->MoveBy(0.f, offsetYLabels);
2476+ labelStyle->MoveBy(offsetXStyles, offsetYLabels);
2477+ labelSize->MoveBy(offsetXSizes, offsetYLabels);
2478+
2479+ // text control alignment issues
2480+ float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
2481+ float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
2482+
2483+ scrollFamilies->MoveBy(0.f, offsetYLists);
2484+ scrollStyles->MoveBy(offsetXStyles, offsetYLists);
2485+ fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2);
2486+ scrollSizes->MoveBy(offsetXSizes, offsetYSizes);
2487+
2488+ fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER);
2489+
2490+ scrollFamilies->ResizeTo(familiesWidth, listsHeight);
2491+ scrollStyles->ResizeTo(stylesWidth, listsHeight);
2492+ fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height());
2493+ scrollSizes->ResizeTo(sizesWidth,
2494+ listsHeight - (offsetYSizes - offsetYLists));
2495+
2496+ buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons);
2497+ buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width()
2498+ - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons);
2499+
2500+ // fill lists
2501+ int selIndex = -1;
2502+ int count = count_font_families();
2503+ for (int i = 0; i < count; i++) {
2504+ font_family family;
2505+ if (get_font_family(i, &family ) == B_OK) {
2506+ fFamiliesList->AddItem(new BStringItem((const char*)family));
2507+ if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0)
2508+ selIndex = i;
2509+ }
2510+ }
2511+
2512+ if (selIndex >= 0) {
2513+ fFamiliesList->Select(selIndex);
2514+ fFamiliesList->ScrollToSelection();
2515+ }
2516+
2517+ _UpdateFontStyles();
2518+
2519+ selIndex = -1;
2520+ for (int size = 8, index = 0; size <= 18; size++, index++) {
2521+ BString str;
2522+ str << size;
2523+ fSizesList->AddItem(new BStringItem(str));
2524+ if (size == fFontSize)
2525+ selIndex = index;
2526+
2527+ }
2528+
2529+ if (selIndex >= 0) {
2530+ fSizesList->Select(selIndex);
2531+ fSizesList->ScrollToSelection();
2532+ }
2533+
2534+ fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg));
2535+ fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg));
2536+ fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg));
2537+ fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg));
2538+
2539+ _UpdateSizeInputPreview();
2540+ _UpdateFontPreview();
2541+
2542+ fStatus = B_OK;
2543+}
2544+
2545+VimSelectFontDialog::~VimSelectFontDialog()
2546+{
2547+ _CleanList(fFamiliesList);
2548+ _CleanList(fStylesList);
2549+ _CleanList(fSizesList);
2550+
2551+ if (fDialogSem > B_OK)
2552+ delete_sem(fDialogSem);
2553+}
2554+
2555+ void
2556+VimSelectFontDialog::_CleanList(BListView* list)
2557+{
2558+ while(0 < list->CountItems())
2559+ delete (dynamic_cast<BStringItem*>(list->RemoveItem((int32)0)));
2560+}
2561+
2562+ bool
2563+VimSelectFontDialog::Go()
2564+{
2565+ if (fStatus != B_OK) {
2566+ Quit();
2567+ return NOFONT;
2568+ }
2569+
2570+ fDialogSem = create_sem(0, "VimFontSelectDialogSem");
2571+ if(fDialogSem < B_OK) {
2572+ Quit();
2573+ return fDialogValue;
2574+ }
2575+
2576+ Show();
2577+
2578+ while(acquire_sem(fDialogSem) == B_INTERRUPTED);
2579+
2580+ bool retValue = fDialogValue;
2581+
2582+ if(Lock())
2583+ Quit();
2584+
2585+ return retValue;
2586+}
2587+
2588+
2589+void VimSelectFontDialog::_UpdateFontStyles()
2590+{
2591+ _CleanList(fStylesList);
2592+
2593+ int32 selIndex = -1;
2594+ int32 count = count_font_styles(fFontFamily);
2595+ for (int32 i = 0; i < count; i++) {
2596+ font_style style;
2597+ uint32 flags = 0;
2598+ if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) {
2599+ fStylesList->AddItem(new BStringItem((const char*)style));
2600+ if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0)
2601+ selIndex = i;
2602+ }
2603+ }
2604+
2605+ if (selIndex >= 0) {
2606+ fStylesList->Select(selIndex);
2607+ fStylesList->ScrollToSelection();
2608+ } else
2609+ fStylesList->Select(0);
2610+}
2611+
2612+
2613+void VimSelectFontDialog::_UpdateSizeInputPreview()
2614+{
2615+ char buf[10] = {0};
2616+ vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize);
2617+ fSizesInput->SetText(buf);
2618+}
2619+
2620+
2621+void VimSelectFontDialog::_UpdateFontPreview()
2622+{
2623+ BFont font;
2624+ fPreview->GetFont(&font);
2625+ font.SetSize(fFontSize);
2626+ font.SetFamilyAndStyle(fFontFamily, fFontStyle);
2627+ fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
2628+
2629+ BString str;
2630+ str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt.";
2631+ fPreview->SetText(str);
2632+}
2633+
2634+
2635+ bool
2636+VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize)
2637+{
2638+ int32 index = list->CurrentSelection();
2639+ if (index < 0)
2640+ return false;
2641+ BStringItem* item = (BStringItem*)list->ItemAt(index);
2642+ if (item == NULL)
2643+ return false;
2644+ strncpy(text, item->Text(), textSize);
2645+ return true;
2646+}
2647+
2648+
2649+void VimSelectFontDialog::MessageReceived(BMessage *msg)
2650+{
2651+ switch (msg->what) {
2652+ case kVimDialogOKButtonMsg:
2653+ strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH);
2654+ strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH);
2655+ *fSize = fFontSize;
2656+ fDialogValue = true;
2657+ case kVimDialogCancelButtonMsg:
2658+ delete_sem(fDialogSem);
2659+ fDialogSem = -1;
2660+ return;
2661+ case B_KEY_UP:
2662+ {
2663+ int32 key = 0;
2664+ if (msg->FindInt32("raw_char", &key) == B_OK
2665+ && key == B_ESCAPE) {
2666+ delete_sem(fDialogSem);
2667+ fDialogSem = -1;
2668+ }
2669+ }
2670+ break;
2671+
2672+ case kVimDialogFamilySelectMsg:
2673+ if (_UpdateFromListItem(fFamiliesList,
2674+ fFontFamily, B_FONT_FAMILY_LENGTH)) {
2675+ _UpdateFontStyles();
2676+ _UpdateFontPreview();
2677+ }
2678+ break;
2679+ case kVimDialogStyleSelectMsg:
2680+ if (_UpdateFromListItem(fStylesList,
2681+ fFontStyle, B_FONT_STYLE_LENGTH))
2682+ _UpdateFontPreview();
2683+ break;
2684+ case kVimDialogSizeSelectMsg:
2685+ {
2686+ char buf[10] = {0};
2687+ if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) {
2688+ float size = atof(buf);
2689+ if (size > 0.f) {
2690+ fFontSize = size;
2691+ _UpdateSizeInputPreview();
2692+ _UpdateFontPreview();
2693+ }
2694+ }
2695+ }
2696+ break;
2697+ case kVimDialogSizeInputMsg:
2698+ {
2699+ float size = atof(fSizesInput->Text());
2700+ if (size > 0.f) {
2701+ fFontSize = size;
2702+ _UpdateFontPreview();
2703+ }
2704+ }
2705+ break;
2706+ default:
2707+ break;
2708+ }
2709+ return BWindow::MessageReceived(msg);
2710+}
2711+
2712+#endif // FEAT_GUI_DIALOG
2713+
2714+#ifdef FEAT_TOOLBAR
2715+
2716+// some forward declaration required by toolbar functions...
2717+static BMessage * MenuMessage(vimmenu_T *menu);
2718+
2719+VimToolbar::VimToolbar(BRect frame, const char *name) :
2720+ BBox(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER)
2721+{
2722+}
2723+
2724+VimToolbar::~VimToolbar()
2725+{
2726+ int32 count = fButtonsList.CountItems();
2727+ for(int32 i = 0; i < count; i++)
2728+ delete (BPictureButton*)fButtonsList.ItemAt(i);
2729+ fButtonsList.MakeEmpty();
2730+
2731+ delete normalButtonsBitmap;
2732+ delete grayedButtonsBitmap;
2733+ normalButtonsBitmap = NULL;
2734+ grayedButtonsBitmap = NULL;
2735+}
2736+
2737+ void
2738+VimToolbar::AttachedToWindow()
2739+{
2740+ BBox::AttachedToWindow();
2741+
2742+ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
2743+}
2744+
2745+ float
2746+VimToolbar::ToolbarHeight() const
2747+{
2748+ float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
2749+ return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
2750+}
2751+
2752+ bool
2753+VimToolbar::ModifyBitmapToGrayed(BBitmap *bitmap)
2754+{
2755+ float height = bitmap->Bounds().Height();
2756+ float width = bitmap->Bounds().Width();
2757+
2758+ rgb_color *bits = (rgb_color*)bitmap->Bits();
2759+ int32 pixels = bitmap->BitsLength() / 4;
2760+ for(int32 i = 0; i < pixels; i++) {
2761+ bits[i].red = bits[i].green =
2762+ bits[i].blue = ((uint32)bits[i].red + bits[i].green + bits[i].blue) / 3;
2763+ bits[i].alpha /= 4;
2764+ }
2765+
2766+ return true;
2767+}
2768+
2769+ bool
2770+VimToolbar::PrepareButtonBitmaps()
2771+{
2772+ // first try to load potentially customized $VIRUNTIME/bitmaps/builtin-tools.png
2773+ normalButtonsBitmap = LoadVimBitmap("builtin-tools.png");
2774+ if(normalButtonsBitmap == NULL)
2775+ // customized not found? dig application resources for "builtin-tools" one
2776+ normalButtonsBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "builtin-tools");
2777+
2778+ if(normalButtonsBitmap == NULL)
2779+ return false;
2780+
2781+ BMessage archive;
2782+ normalButtonsBitmap->Archive(&archive);
2783+
2784+ grayedButtonsBitmap = new BBitmap(&archive);
2785+ if(grayedButtonsBitmap == NULL)
2786+ return false;
2787+
2788+ // modify grayed bitmap
2789+ ModifyBitmapToGrayed(grayedButtonsBitmap);
2790+
2791+ return true;
2792+}
2793+
2794+BBitmap *VimToolbar::LoadVimBitmap(const char* fileName)
2795+{
2796+ BBitmap *bitmap = NULL;
2797+
2798+ int mustfree = 0;
2799+ char_u* runtimePath = vim_getenv((char_u*)"VIMRUNTIME", &mustfree);
2800+ if(runtimePath != NULL && fileName != NULL) {
2801+ BString strPath((char*)runtimePath);
2802+ strPath << "/bitmaps/" << fileName;
2803+ bitmap = BTranslationUtils::GetBitmap(strPath.String());
2804+ }
2805+
2806+ if(mustfree)
2807+ vim_free(runtimePath);
2808+
2809+ return bitmap;
2810+}
2811+
2812+ bool
2813+VimToolbar::GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed)
2814+{
2815+ float size = bitmapFrom->Bounds().Height() + 1.;
2816+
2817+ BView view(BRect(0, 0, size, size), "", 0, 0);
2818+
2819+ AddChild(&view);
2820+ view.BeginPicture(pictureTo);
2821+
2822+ view.SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
2823+ view.FillRect(view.Bounds());
2824+ view.SetDrawingMode(B_OP_OVER);
2825+
2826+ BRect source(0, 0, size - 1, size - 1);
2827+ BRect destination(source);
2828+
2829+ source.OffsetBy(size * index, 0);
2830+ destination.OffsetBy(ButtonMargin, ButtonMargin);
2831+
2832+ view.DrawBitmap(bitmapFrom, source, destination);
2833+
2834+ if(pressed) {
2835+ rgb_color shineColor = ui_color(B_SHINE_COLOR);
2836+ rgb_color shadowColor = ui_color(B_SHADOW_COLOR);
2837+ size += ButtonMargin * 2 - 1;
2838+ view.BeginLineArray(4);
2839+ view.AddLine(BPoint(0, 0), BPoint(size, 0), shadowColor);
2840+ view.AddLine(BPoint(size, 0), BPoint(size, size), shineColor);
2841+ view.AddLine(BPoint(size, size), BPoint(0, size), shineColor);
2842+ view.AddLine(BPoint(0, size), BPoint(0, 0), shadowColor);
2843+ view.EndLineArray();
2844+ }
2845+
2846+ view.EndPicture();
2847+ RemoveChild(&view);
2848+
2849+ return true;
2850+}
2851+
2852+ bool
2853+VimToolbar::AddButton(int32 index, vimmenu_T *menu)
2854+{
2855+ BPictureButton *button = NULL;
2856+ if(!menu_is_separator(menu->name)) {
2857+ float size = normalButtonsBitmap ?
2858+ normalButtonsBitmap->Bounds().Height() + 1. + ButtonMargin * 2 : 18.;
2859+ BRect frame(0, 0, size, size);
2860+ BPicture pictureOn;
2861+ BPicture pictureOff;
2862+ BPicture pictureGray;
2863+
2864+ if(menu->iconfile == NULL && menu->iconidx >= 0 && normalButtonsBitmap) {
2865+ GetPictureFromBitmap(&pictureOn, menu->iconidx, normalButtonsBitmap, true);
2866+ GetPictureFromBitmap(&pictureOff, menu->iconidx, normalButtonsBitmap, false);
2867+ GetPictureFromBitmap(&pictureGray, menu->iconidx, grayedButtonsBitmap, false);
2868+ } else {
2869+
2870+ char_u buffer[MAXPATHL] = {0};
2871+ BBitmap *bitmap = NULL;
2872+
2873+ if(menu->iconfile) {
2874+ gui_find_iconfile(menu->iconfile, buffer, (char*)"png");
2875+ bitmap = BTranslationUtils::GetBitmap((char*)buffer);
2876+ }
2877+
2878+ if(bitmap == NULL && gui_find_bitmap(menu->name, buffer, (char*)"png") == OK)
2879+ bitmap = BTranslationUtils::GetBitmap((char*)buffer);
2880+
2881+ if(bitmap == NULL)
2882+ bitmap = new BBitmap(BRect(0, 0, size, size), B_RGB32);
2883+
2884+ GetPictureFromBitmap(&pictureOn, 0, bitmap, true);
2885+ GetPictureFromBitmap(&pictureOff, 0, bitmap, false);
2886+ ModifyBitmapToGrayed(bitmap);
2887+ GetPictureFromBitmap(&pictureGray, 0, bitmap, false);
2888+
2889+ delete bitmap;
2890+ }
2891+
2892+ button = new BPictureButton(frame, (char*)menu->name,
2893+ &pictureOff, &pictureOn, MenuMessage(menu));
2894+
2895+ button->SetDisabledOn(&pictureGray);
2896+ button->SetDisabledOff(&pictureGray);
2897+
2898+ button->SetTarget(gui.vimTextArea);
2899+
2900+ AddChild(button);
2901+
2902+ menu->button = button;
2903+ }
2904+
2905+ bool result = fButtonsList.AddItem(button, index);
2906+ InvalidateLayout();
2907+ return result;
2908+}
2909+
2910+ bool
2911+VimToolbar::RemoveButton(vimmenu_T *menu)
2912+{
2913+ if(menu->button) {
2914+ if(fButtonsList.RemoveItem(menu->button)) {
2915+ delete menu->button;
2916+ menu->button = NULL;
2917+ }
2918+ }
2919+}
2920+
2921+ bool
2922+VimToolbar::GrayButton(vimmenu_T *menu, int grey)
2923+{
2924+ if(menu->button) {
2925+ int32 index = fButtonsList.IndexOf(menu->button);
2926+ if(index >= 0)
2927+ menu->button->SetEnabled(grey ? false : true);
2928+ }
2929+}
2930+
2931+ void
2932+VimToolbar::InvalidateLayout()
2933+{
2934+ int32 offset = ToolbarMargin;
2935+ int32 count = fButtonsList.CountItems();
2936+ for(int32 i = 0; i < count; i++) {
2937+ BPictureButton *button = (BPictureButton *)fButtonsList.ItemAt(i);
2938+ if(button) {
2939+ button->MoveTo(offset, ToolbarMargin);
2940+ offset += button->Bounds().Width() + ToolbarMargin;
2941+ } else
2942+ offset += ToolbarMargin * 3;
2943+ }
2944+}
2945+
2946+#endif /*FEAT_TOOLBAR*/
2947+
2948+#if defined(FEAT_GUI_TABLINE)
2949+
2950+ float
2951+VimTabLine::TablineHeight() const
2952+{
2953+// float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
2954+// return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
2955+ return TabHeight(); // + ToolbarMargin;
2956+}
2957+
2958+void
2959+VimTabLine::MouseDown(BPoint point)
2960+{
2961+ if(!gui_mch_showing_tabline())
2962+ return;
2963+
2964+ BMessage *m = Window()->CurrentMessage();
2965+ assert(m);
2966+
2967+ int32 buttons = 0;
2968+ m->FindInt32("buttons", &buttons);
2969+
2970+ int32 clicks = 0;
2971+ m->FindInt32("clicks", &clicks);
2972+
2973+ int index = 0; // 0 means here - no tab found
2974+ for (int i = 0; i < CountTabs(); i++) {
2975+ if(TabFrame(i).Contains(point)) {
2976+ index = i + 1; // indexes are 1-based
2977+ break;
2978+ }
2979+ }
2980+
2981+ int event = -1;
2982+
2983+ if ((buttons & B_PRIMARY_MOUSE_BUTTON) && clicks > 1)
2984+ // left button double click on - create new tab
2985+ event = TABLINE_MENU_NEW;
2986+
2987+ else if (buttons & B_TERTIARY_MOUSE_BUTTON)
2988+ // middle button click - close the pointed tab
2989+ // or create new one in case empty space
2990+ event = index > 0 ? TABLINE_MENU_CLOSE : TABLINE_MENU_NEW;
2991+
2992+ else if (buttons & B_SECONDARY_MOUSE_BUTTON) {
2993+ // right button click - show context menu
2994+ BPopUpMenu* popUpMenu = new BPopUpMenu("tabLineContextMenu", false, false);
2995+ popUpMenu->AddItem(new BMenuItem(_("Close tabi R"), new BMessage(TABLINE_MENU_CLOSE)));
2996+ popUpMenu->AddItem(new BMenuItem(_("New tab T"), new BMessage(TABLINE_MENU_NEW)));
2997+ popUpMenu->AddItem(new BMenuItem(_("Open tab..."), new BMessage(TABLINE_MENU_OPEN)));
2998+
2999+ ConvertToScreen(&point);
3000+ BMenuItem* item = popUpMenu->Go(point);
3001+ if (item != NULL) {
3002+ event = item->Command();
3003+ }
3004+
3005+ delete popUpMenu;
3006+
3007+ } else {
3008+ // default processing
3009+ BTabView::MouseDown(point);
3010+ return;
3011+ }
3012+
3013+ if (event < 0)
3014+ return;
3015+
3016+ VimTablineMenuMsg tmm;
3017+ tmm.index = index;
3018+ tmm.event = event;
3019+ write_port(gui.vdcmp, VimMsg::TablineMenu, &tmm, sizeof(tmm));
3020+}
3021+
3022+void
3023+VimTabLine::VimTab::Select(BView* owner)
3024+{
3025+ BTab::Select(owner);
3026+
3027+ VimTabLine *tabLine = gui.vimForm->TabLine();
3028+ if(tabLine != NULL) {
3029+
3030+ int32 i = 0;
3031+ for (; i < tabLine->CountTabs(); i++)
3032+ if(this == tabLine->TabAt(i))
3033+ break;
3034+
3035+// printf("%d:%d:%s\n", i, tabLine->CountTabs(), tabLine->TabAt(i)->Label());
3036+ if(i < tabLine->CountTabs()) {
3037+ VimTablineMsg tm;
3038+ tm.index = i + 1;
3039+ write_port(gui.vdcmp, VimMsg::Tabline, &tm, sizeof(tm));
3040+ }
3041+ }
3042+}
3043+
3044+#endif // defined(FEAT_GUI_TABLINE)
3045+
3046+// ---------------- ----------------
3047+
3048+// some global variables
3049+static char appsig[] = "application/x-vnd.Haiku-Vim-8";
3050+key_map *keyMap;
3051+char *keyMapChars;
3052+int main_exitcode = 127;
3053+
3054+ status_t
3055+gui_haiku_process_event(bigtime_t timeout)
3056+{
3057+ struct VimMsg vm;
3058+ int32 what;
3059+ ssize_t size;
3060+
3061+ size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm),
3062+ B_TIMEOUT, timeout);
3063+
3064+ if (size >= 0) {
3065+ switch (what) {
3066+ case VimMsg::Key:
3067+ {
3068+ char_u *string = vm.u.Key.chars;
3069+ int len = vm.u.Key.length;
3070+ if (len == 1 && string[0] == Ctrl_chr('C')) {
3071+ trash_input_buf();
3072+ got_int = TRUE;
3073+ }
3074+
3075+ if (vm.u.Key.csi_escape)
3076+#ifndef FEAT_MBYTE_IME
3077+ {
3078+ int i;
3079+ char_u buf[2];
3080+
3081+ for (i = 0; i < len; ++i)
3082+ {
3083+ add_to_input_buf(string + i, 1);
3084+ if (string[i] == CSI)
3085+ {
3086+ // Turn CSI into K_CSI.
3087+ buf[0] = KS_EXTRA;
3088+ buf[1] = (int)KE_CSI;
3089+ add_to_input_buf(buf, 2);
3090+ }
3091+ }
3092+ }
3093+#else
3094+ add_to_input_buf_csi(string, len);
3095+#endif
3096+ else
3097+ add_to_input_buf(string, len);
3098+ }
3099+ break;
3100+ case VimMsg::Resize:
3101+ gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height);
3102+ break;
3103+ case VimMsg::ScrollBar:
3104+ {
3105+ /*
3106+ * If loads of scroll messages queue up, use only the last
3107+ * one. Always report when the scrollbar stops dragging.
3108+ * This is not perfect yet anyway: these events are queued
3109+ * yet again, this time in the keyboard input buffer.
3110+ */
3111+ int32 oldCount =
3112+ atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1);
3113+ if (oldCount <= 1 || !vm.u.Scroll.stillDragging)
3114+ gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(),
3115+ vm.u.Scroll.value, vm.u.Scroll.stillDragging);
3116+ }
3117+ break;
3118+#if defined(FEAT_MENU)
3119+ case VimMsg::Menu:
3120+ gui_menu_cb(vm.u.Menu.guiMenu);
3121+ break;
3122+#endif
3123+ case VimMsg::Mouse:
3124+ {
3125+ int32 oldCount;
3126+ if (vm.u.Mouse.button == MOUSE_DRAG)
3127+ oldCount =
3128+ atomic_add(&gui.vimTextArea->mouseDragEventCount, -1);
3129+ else
3130+ oldCount = 0;
3131+ if (oldCount <= 1)
3132+ gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x,
3133+ vm.u.Mouse.y, vm.u.Mouse.repeated_click,
3134+ vm.u.Mouse.modifiers);
3135+ }
3136+ break;
3137+ case VimMsg::MouseMoved:
3138+ {
3139+ gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y);
3140+ }
3141+ break;
3142+ case VimMsg::Focus:
3143+ gui.in_focus = vm.u.Focus.active;
3144+ // XXX Signal that scrollbar dragging has stopped?
3145+ // This is needed because we don't get a MouseUp if
3146+ // that happens while outside the window... :-(
3147+ if (gui.dragged_sb) {
3148+ gui.dragged_sb = SBAR_NONE;
3149+ }
3150+ // gui_update_cursor(TRUE, FALSE);
3151+ break;
3152+ case VimMsg::Refs:
3153+ ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir);
3154+ break;
3155+ case VimMsg::Tabline:
3156+ send_tabline_event(vm.u.Tabline.index);
3157+ break;
3158+ case VimMsg::TablineMenu:
3159+ send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event);
3160+ break;
3161+ default:
3162+ // unrecognised message, ignore it
3163+ break;
3164+ }
3165+ }
3166+
3167+ /*
3168+ * If size < B_OK, it is an error code.
3169+ */
3170+ return size;
3171+}
3172+
3173+/*
3174+ * Here are some functions to protect access to ScreenLines[] and
3175+ * LineOffset[]. These are used from the window thread to respond
3176+ * to a Draw() callback. When that occurs, the window is already
3177+ * locked by the system.
3178+ *
3179+ * Other code that needs to lock is any code that changes these
3180+ * variables. Other read-only access, or access merely to the
3181+ * contents of the screen buffer, need not be locked.
3182+ *
3183+ * If there is no window, don't call Lock() but do succeed.
3184+ */
3185+
3186+ int
3187+vim_lock_screen()
3188+{
3189+ return !gui.vimWindow || gui.vimWindow->Lock();
3190+}
3191+
3192+ void
3193+vim_unlock_screen()
3194+{
3195+ if (gui.vimWindow)
3196+ gui.vimWindow->Unlock();
3197+}
3198+
3199+#define RUN_BAPPLICATION_IN_NEW_THREAD 0
3200+
3201+#if RUN_BAPPLICATION_IN_NEW_THREAD
3202+
3203+ int32
3204+run_vimapp(void *args)
3205+{
3206+ VimApp app(appsig);
3207+
3208+ gui.vimApp = &app;
3209+ app.Run(); // Run until Quit() called
3210+
3211+ return 0;
3212+}
3213+
3214+#else
3215+
3216+ int32
3217+call_main(void *args)
3218+{
3219+ struct MainArgs *ma = (MainArgs *)args;
3220+
3221+ return main(ma->argc, ma->argv);
3222+}
3223+#endif
3224+
3225+/*
3226+ * Parse the GUI related command-line arguments. Any arguments used are
3227+ * deleted from argv, and *argc is decremented accordingly. This is called
3228+ * when vim is started, whether or not the GUI has been started.
3229+ */
3230+ void
3231+gui_mch_prepare(
3232+ int *argc,
3233+ char **argv)
3234+{
3235+ /*
3236+ * We don't have any command line arguments for the BeOS GUI yet,
3237+ * but this is an excellent place to create our Application object.
3238+ */
3239+ if (!gui.vimApp) {
3240+ thread_info tinfo;
3241+ get_thread_info(find_thread(NULL), &tinfo);
3242+
3243+ // May need the port very early on to process RefsReceived()
3244+ gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP");
3245+
3246+#if RUN_BAPPLICATION_IN_NEW_THREAD
3247+ thread_id tid = spawn_thread(run_vimapp, "vim VimApp",
3248+ tinfo.priority, NULL);
3249+ if (tid >= B_OK) {
3250+ resume_thread(tid);
3251+ } else {
3252+ getout(1);
3253+ }
3254+#else
3255+ MainArgs ma = { *argc, argv };
3256+ thread_id tid = spawn_thread(call_main, "vim main()",
3257+ tinfo.priority, &ma);
3258+ if (tid >= B_OK) {
3259+ VimApp app(appsig);
3260+
3261+ gui.vimApp = &app;
3262+ resume_thread(tid);
3263+ /*
3264+ * This is rather horrible.
3265+ * call_main will call main() again...
3266+ * There will be no infinite recursion since
3267+ * gui.vimApp is set now.
3268+ */
3269+ app.Run(); // Run until Quit() called
3270+ // fprintf(stderr, "app.Run() returned...\n");
3271+ status_t dummy_exitcode;
3272+ (void)wait_for_thread(tid, &dummy_exitcode);
3273+
3274+ /*
3275+ * This path should be the normal one taken to exit Vim.
3276+ * The main() thread calls mch_exit() which calls
3277+ * gui_mch_exit() which terminates its thread.
3278+ */
3279+ exit(main_exitcode);
3280+ }
3281+#endif
3282+ }
3283+ // Don't fork() when starting the GUI. Spawned threads are not
3284+ // duplicated with a fork(). The result is a mess.
3285+ gui.dofork = FALSE;
3286+ /*
3287+ * XXX Try to determine whether we were started from
3288+ * the Tracker or the terminal.
3289+ * It would be nice to have this work, because the Tracker
3290+ * follows symlinks, so even if you double-click on gvim,
3291+ * when it is a link to vim it will still pass a command name
3292+ * of vim...
3293+ * We try here to see if stdin comes from /dev/null. If so,
3294+ * (or if there is an error, which should never happen) start the GUI.
3295+ * This does the wrong thing for vim - </dev/null, and we're
3296+ * too early to see the command line parsing. Tough.
3297+ * On the other hand, it starts the gui for vim file & which is nice.
3298+ */
3299+ if (!isatty(0)) {
3300+ struct stat stat_stdin, stat_dev_null;
3301+
3302+ if (fstat(0, &stat_stdin) == -1 ||
3303+ stat("/dev/null", &stat_dev_null) == -1 ||
3304+ (stat_stdin.st_dev == stat_dev_null.st_dev &&
3305+ stat_stdin.st_ino == stat_dev_null.st_ino))
3306+ gui.starting = TRUE;
3307+ }
3308+}
3309+
3310+/*
3311+ * Check if the GUI can be started. Called before gvimrc is sourced.
3312+ * Return OK or FAIL.
3313+ */
3314+ int
3315+gui_mch_init_check(void)
3316+{
3317+ return OK; // TODO: GUI can always be started?
3318+}
3319+
3320+/*
3321+ * Initialise the GUI. Create all the windows, set up all the call-backs
3322+ * etc.
3323+ */
3324+ int
3325+gui_mch_init()
3326+{
3327+ display_errors();
3328+ gui.def_norm_pixel = RGB(0x00, 0x00, 0x00); // black
3329+ gui.def_back_pixel = RGB(0xFF, 0xFF, 0xFF); // white
3330+ gui.norm_pixel = gui.def_norm_pixel;
3331+ gui.back_pixel = gui.def_back_pixel;
3332+
3333+ gui.scrollbar_width = (int) B_V_SCROLL_BAR_WIDTH;
3334+ gui.scrollbar_height = (int) B_H_SCROLL_BAR_HEIGHT;
3335+#ifdef FEAT_MENU
3336+ gui.menu_height = 19; // initial guess -
3337+ // correct for my default settings
3338+#endif
3339+ gui.border_offset = 3; // coordinates are inside window borders
3340+
3341+ if (gui.vdcmp < B_OK)
3342+ return FAIL;
3343+ get_key_map(&keyMap, &keyMapChars);
3344+
3345+ gui.vimWindow = new VimWindow(); // hidden and locked
3346+ if (!gui.vimWindow)
3347+ return FAIL;
3348+
3349+ gui.vimWindow->Run(); // Run() unlocks but does not show
3350+
3351+ // Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3352+ // file)
3353+ set_normal_colors();
3354+
3355+ /*
3356+ * Check that none of the colors are the same as the background color
3357+ */
3358+ gui_check_colors();
3359+
3360+ // Get the colors for the highlight groups (gui_check_colors() might have
3361+ // changed them)
3362+ highlight_gui_started(); // re-init colors and fonts
3363+
3364+ gui_mch_new_colors(); // window must exist for this
3365+
3366+ return OK;
3367+}
3368+
3369+/*
3370+ * Called when the foreground or background color has been changed.
3371+ */
3372+ void
3373+gui_mch_new_colors()
3374+{
3375+ rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
3376+
3377+ if (gui.vimWindow->Lock()) {
3378+ gui.vimForm->SetViewColor(rgb);
3379+ // Does this not have too much effect for those small rectangles?
3380+ gui.vimForm->Invalidate();
3381+ gui.vimWindow->Unlock();
3382+ }
3383+}
3384+
3385+/*
3386+ * Open the GUI window which was created by a call to gui_mch_init().
3387+ */
3388+ int
3389+gui_mch_open()
3390+{
3391+ if (gui_win_x != -1 && gui_win_y != -1)
3392+ gui_mch_set_winpos(gui_win_x, gui_win_y);
3393+
3394+ // Actually open the window
3395+ if (gui.vimWindow->Lock()) {
3396+ gui.vimWindow->Show();
3397+ gui.vimWindow->Unlock();
3398+ return OK;
3399+ }
3400+
3401+ return FAIL;
3402+}
3403+
3404+ void
3405+gui_mch_exit(int vim_exitcode)
3406+{
3407+ if (gui.vimWindow) {
3408+ thread_id tid = gui.vimWindow->Thread();
3409+ gui.vimWindow->Lock();
3410+ gui.vimWindow->Quit();
3411+ // Wait until it is truely gone
3412+ int32 exitcode;
3413+ wait_for_thread(tid, &exitcode);
3414+ }
3415+ delete_port(gui.vdcmp);
3416+#if !RUN_BAPPLICATION_IN_NEW_THREAD
3417+ /*
3418+ * We are in the main() thread - quit the App thread and
3419+ * quit ourselves (passing on the exitcode). Use a global since the
3420+ * value from exit_thread() is only used if wait_for_thread() is
3421+ * called in time (race condition).
3422+ */
3423+#endif
3424+ if (gui.vimApp) {
3425+ VimTextAreaView::guiBlankMouse(false);
3426+
3427+ main_exitcode = vim_exitcode;
3428+#if RUN_BAPPLICATION_IN_NEW_THREAD
3429+ thread_id tid = gui.vimApp->Thread();
3430+ int32 exitcode;
3431+ gui.vimApp->Lock();
3432+ gui.vimApp->Quit();
3433+ gui.vimApp->Unlock();
3434+ wait_for_thread(tid, &exitcode);
3435+#else
3436+ gui.vimApp->Lock();
3437+ gui.vimApp->Quit();
3438+ gui.vimApp->Unlock();
3439+ // suicide
3440+ exit_thread(vim_exitcode);
3441+#endif
3442+ }
3443+ // If we are somehow still here, let mch_exit() handle things.
3444+}
3445+
3446+/*
3447+ * Get the position of the top left corner of the window.
3448+ */
3449+ int
3450+gui_mch_get_winpos(int *x, int *y)
3451+{
3452+ if (gui.vimWindow->Lock()) {
3453+ BRect r;
3454+ r = gui.vimWindow->Frame();
3455+ gui.vimWindow->Unlock();
3456+ *x = (int)r.left;
3457+ *y = (int)r.top;
3458+ return OK;
3459+ }
3460+ else
3461+ return FAIL;
3462+}
3463+
3464+/*
3465+ * Set the position of the top left corner of the window to the given
3466+ * coordinates.
3467+ */
3468+ void
3469+gui_mch_set_winpos(int x, int y)
3470+{
3471+ if (gui.vimWindow->Lock()) {
3472+ gui.vimWindow->MoveTo(x, y);
3473+ gui.vimWindow->Unlock();
3474+ }
3475+}
3476+
3477+/*
3478+ * Set the size of the window to the given width and height in pixels.
3479+ */
3480+void
3481+gui_mch_set_shellsize(
3482+ int width,
3483+ int height,
3484+ int min_width,
3485+ int min_height,
3486+ int base_width,
3487+ int base_height,
3488+ int direction) // TODO: utilize?
3489+{
3490+ /*
3491+ * We are basically given the size of the VimForm, if I understand
3492+ * correctly. Since it fills the window completely, this will also
3493+ * be the size of the window.
3494+ */
3495+ if (gui.vimWindow->Lock()) {
3496+ gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH);
3497+
3498+ // set size limits
3499+ float minWidth, maxWidth, minHeight, maxHeight;
3500+
3501+ gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth,
3502+ &minHeight, &maxHeight);
3503+ gui.vimWindow->SetSizeLimits(min_width, maxWidth,
3504+ min_height, maxHeight);
3505+
3506+ /*
3507+ * Set the resizing alignment depending on font size.
3508+ */
3509+ gui.vimWindow->SetWindowAlignment(
3510+ B_PIXEL_ALIGNMENT, // window_alignment mode,
3511+ 1, // int32 h,
3512+ 0, // int32 hOffset = 0,
3513+ gui.char_width, // int32 width = 0,
3514+ base_width, // int32 widthOffset = 0,
3515+ 1, // int32 v = 0,
3516+ 0, // int32 vOffset = 0,
3517+ gui.char_height, // int32 height = 0,
3518+ base_height // int32 heightOffset = 0
3519+ );
3520+
3521+ gui.vimWindow->Unlock();
3522+ }
3523+}
3524+
3525+void
3526+gui_mch_get_screen_dimensions(
3527+ int *screen_w,
3528+ int *screen_h)
3529+{
3530+ BRect frame;
3531+
3532+ {
3533+ BScreen screen(gui.vimWindow);
3534+
3535+ if (screen.IsValid()) {
3536+ frame = screen.Frame();
3537+ } else {
3538+ frame.right = 640;
3539+ frame.bottom = 480;
3540+ }
3541+ }
3542+
3543+ // XXX approximations...
3544+ *screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20;
3545+ *screen_h = (int) frame.bottom - gui.scrollbar_height
3546+#ifdef FEAT_MENU
3547+ - gui.menu_height
3548+#endif
3549+ - 30;
3550+}
3551+
3552+void
3553+gui_mch_set_text_area_pos(
3554+ int x,
3555+ int y,
3556+ int w,
3557+ int h)
3558+{
3559+ if (!gui.vimTextArea)
3560+ return;
3561+
3562+ if (gui.vimWindow->Lock()) {
3563+ gui.vimTextArea->MoveTo(x, y);
3564+ gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
3565+
3566+/*#ifdef FEAT_GUI_TABLINE
3567+ if(gui.vimForm->TabLine() != NULL) {
3568+ gui.vimForm->TabLine()->ResizeTo(w, gui.vimForm->TablineHeight());
3569+ }
3570+#endif // FEAT_GUI_TABLINE
3571+
3572+ gui.vimWindow->Unlock();
3573+ }
3574+}
3575+
3576+
3577+/*
3578+ * Scrollbar stuff:
3579+ */
3580+
3581+void
3582+gui_mch_enable_scrollbar(
3583+ scrollbar_T *sb,
3584+ int flag)
3585+{
3586+ VimScrollBar *vsb = sb->id;
3587+ if (gui.vimWindow->Lock()) {
3588+ /*
3589+ * This function is supposed to be idempotent, but Show()/Hide()
3590+ * is not. Therefore we test if they are needed.
3591+ */
3592+ if (flag) {
3593+ if (vsb->IsHidden()) {
3594+ vsb->Show();
3595+ }
3596+ } else {
3597+ if (!vsb->IsHidden()) {
3598+ vsb->Hide();
3599+ }
3600+ }
3601+ gui.vimWindow->Unlock();
3602+ }
3603+}
3604+
3605+void
3606+gui_mch_set_scrollbar_thumb(
3607+ scrollbar_T *sb,
3608+ int val,
3609+ int size,
3610+ int max)
3611+{
3612+ if (gui.vimWindow->Lock()) {
3613+ VimScrollBar *s = sb->id;
3614+ if (max == 0) {
3615+ s->SetValue(0);
3616+ s->SetRange(0.0, 0.0);
3617+ } else {
3618+ s->SetProportion((float)size / (max + 1.0));
3619+ s->SetSteps(1.0, size > 5 ? size - 2 : size);
3620+#ifndef SCROLL_PAST_END // really only defined in gui.c...
3621+ max = max + 1 - size;
3622+#endif
3623+ if (max < s->Value()) {
3624+ /*
3625+ * If the new maximum is lower than the current value,
3626+ * setting it would cause the value to be clipped and
3627+ * therefore a ValueChanged() call.
3628+ * We avoid this by setting the value first, because
3629+ * it presumably is <= max.
3630+ */
3631+ s->SetValue(val);
3632+ s->SetRange(0.0, max);
3633+ } else {
3634+ /*
3635+ * In the other case, set the range first, since the
3636+ * new value might be higher than the current max.
3637+ */
3638+ s->SetRange(0.0, max);
3639+ s->SetValue(val);
3640+ }
3641+ }
3642+ gui.vimWindow->Unlock();
3643+ }
3644+}
3645+
3646+void
3647+gui_mch_set_scrollbar_pos(
3648+ scrollbar_T *sb,
3649+ int x,
3650+ int y,
3651+ int w,
3652+ int h)
3653+{
3654+ if (gui.vimWindow->Lock()) {
3655+ BRect winb = gui.vimWindow->Bounds();
3656+ float vsbx = x, vsby = y;
3657+ VimScrollBar *vsb = sb->id;
3658+ vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
3659+ if(winb.right-(x+w)<w) vsbx = winb.right - (w - PEN_WIDTH);
3660+ vsb->MoveTo(vsbx, vsby);
3661+ gui.vimWindow->Unlock();
3662+ }
3663+}
3664+
3665+void
3666+gui_mch_create_scrollbar(
3667+ scrollbar_T *sb,
3668+ int orient) // SBAR_VERT or SBAR_HORIZ
3669+{
3670+ orientation posture =
3671+ (orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL;
3672+
3673+ VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture);
3674+ if (gui.vimWindow->Lock()) {
3675+ vsb->SetTarget(gui.vimTextArea);
3676+ vsb->Hide();
3677+ gui.vimForm->AddChild(vsb);
3678+ gui.vimWindow->Unlock();
3679+ }
3680+}
3681+
3682+#if defined(FEAT_WINDOWS) || defined(PROTO)
3683+void
3684+gui_mch_destroy_scrollbar(
3685+ scrollbar_T *sb)
3686+{
3687+ if (gui.vimWindow->Lock()) {
3688+ sb->id->RemoveSelf();
3689+ delete sb->id;
3690+ gui.vimWindow->Unlock();
3691+ }
3692+}
3693+#endif
3694+
3695+/*
3696+ * Cursor does not flash
3697+ */
3698+ int
3699+gui_mch_is_blink_off(void)
3700+{
3701+ return FALSE;
3702+}
3703+
3704+/*
3705+ * Cursor blink functions.
3706+ *
3707+ * This is a simple state machine:
3708+ * BLINK_NONE not blinking at all
3709+ * BLINK_OFF blinking, cursor is not shown
3710+ * BLINK_ON blinking, cursor is shown
3711+ */
3712+
3713+#define BLINK_NONE 0
3714+#define BLINK_OFF 1
3715+#define BLINK_ON 2
3716+
3717+static int blink_state = BLINK_NONE;
3718+static long_u blink_waittime = 700;
3719+static long_u blink_ontime = 400;
3720+static long_u blink_offtime = 250;
3721+static int blink_timer = 0;
3722+
3723+void
3724+gui_mch_set_blinking(
3725+ long waittime,
3726+ long on,
3727+ long off)
3728+{
3729+ // TODO
3730+ blink_waittime = waittime;
3731+ blink_ontime = on;
3732+ blink_offtime = off;
3733+}
3734+
3735+/*
3736+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
3737+ */
3738+ void
3739+gui_mch_stop_blink()
3740+{
3741+ // TODO
3742+ if (blink_timer != 0)
3743+ {
3744+ // XtRemoveTimeOut(blink_timer);
3745+ blink_timer = 0;
3746+ }
3747+ if (blink_state == BLINK_OFF)
3748+ gui_update_cursor(TRUE, FALSE);
3749+ blink_state = BLINK_NONE;
3750+}
3751+
3752+/*
3753+ * Start the cursor blinking. If it was already blinking, this restarts the
3754+ * waiting time and shows the cursor.
3755+ */
3756+ void
3757+gui_mch_start_blink()
3758+{
3759+ // TODO
3760+ if (blink_timer != 0)
3761+ ;// XtRemoveTimeOut(blink_timer);
3762+ // Only switch blinking on if none of the times is zero
3763+ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
3764+ {
3765+ blink_timer = 1; // XtAppAddTimeOut(app_context, blink_waittime,
3766+ blink_state = BLINK_ON;
3767+ gui_update_cursor(TRUE, FALSE);
3768+ }
3769+}
3770+
3771+/*
3772+ * Initialise vim to use the font with the given name. Return FAIL if the font
3773+ * could not be loaded, OK otherwise.
3774+ */
3775+int
3776+gui_mch_init_font(
3777+ char_u *font_name,
3778+ int fontset)
3779+{
3780+ if (gui.vimWindow->Lock())
3781+ {
3782+ int rc = gui.vimTextArea->mchInitFont(font_name);
3783+ gui.vimWindow->Unlock();
3784+
3785+ return rc;
3786+ }
3787+
3788+ return FAIL;
3789+}
3790+
3791+
3792+ int
3793+gui_mch_adjust_charsize()
3794+{
3795+ return FAIL;
3796+}
3797+
3798+
3799+ int
3800+gui_mch_font_dialog(font_family* family, font_style* style, float* size)
3801+{
3802+#if defined(FEAT_GUI_DIALOG)
3803+ // gui.vimWindow->Unlock();
3804+ VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size);
3805+ return dialog->Go();
3806+#else
3807+ return NOFONT;
3808+#endif // FEAT_GUI_DIALOG
3809+}
3810+
3811+
3812+GuiFont
3813+gui_mch_get_font(
3814+ char_u *name,
3815+ int giveErrorIfMissing)
3816+{
3817+ static VimFont *fontList = NULL;
3818+
3819+ if (!gui.in_use) // can't do this when GUI not running
3820+ return NOFONT;
3821+
3822+ // storage for locally modified name;
3823+ const int buff_size = B_FONT_FAMILY_LENGTH + B_FONT_STYLE_LENGTH + 20;
3824+ static char font_name[buff_size] = {0};
3825+ font_family family = {0};
3826+ font_style style = {0};
3827+ float size = 0.f;
3828+
3829+ if (name == 0 && be_fixed_font == 0) {
3830+ if(giveErrorIfMissing)
3831+ semsg(_(e_font), name);
3832+ return NOFONT;
3833+ }
3834+
3835+ bool useSelectGUI = false;
3836+ if (name != NULL)
3837+ if (STRCMP(name, "*") == 0) {
3838+ useSelectGUI = true;
3839+ STRNCPY(font_name, hl_get_font_name(), buff_size);
3840+ } else
3841+ STRNCPY(font_name, name, buff_size);
3842+
3843+ if (font_name[0] == 0) {
3844+ be_fixed_font->GetFamilyAndStyle(&family, &style);
3845+ size = be_fixed_font->Size();
3846+ vim_snprintf(font_name, buff_size,
3847+ (char*)"%s/%s/%.0f", family, style, size);
3848+ }
3849+
3850+ // replace underscores with spaces
3851+ char* end = 0;
3852+ while (end = strchr((char *)font_name, '_'))
3853+ *end = ' ';
3854+
3855+ // store the name before strtok corrupt the buffer ;-)
3856+ static char buff[buff_size] = {0};
3857+ STRNCPY(buff, font_name, buff_size);
3858+ STRNCPY(family, strtok(buff, "/\0"), B_FONT_FAMILY_LENGTH);
3859+ char* style_s = strtok(0, "/\0");
3860+ if (style_s != 0)
3861+ STRNCPY(style, style_s, B_FONT_STYLE_LENGTH);
3862+ size = atof((style_s != 0) ? strtok(0, "/\0") : "0");
3863+
3864+ if (useSelectGUI) {
3865+ if(gui_mch_font_dialog(&family, &style, &size) == NOFONT)
3866+ return FAIL;
3867+ // compose for further processing
3868+ vim_snprintf(font_name, buff_size,
3869+ (char*)"%s/%s/%.0f", family, style, size);
3870+ hl_set_font_name((char_u*)font_name);
3871+
3872+ // Set guifont to the name of the selected font.
3873+ char_u* new_p_guifont = alloc(STRLEN(font_name) + 1);
3874+ if (new_p_guifont != NULL) {
3875+ STRCPY(new_p_guifont, font_name);
3876+ vim_free(p_guifont);
3877+ p_guifont = new_p_guifont;
3878+ // Replace spaces in the font name with underscores.
3879+ for ( ; *new_p_guifont; ++new_p_guifont)
3880+ if (*new_p_guifont == ' ')
3881+ *new_p_guifont = '_';
3882+ }
3883+ }
3884+
3885+ VimFont *flp;
3886+ for (flp = fontList; flp; flp = flp->next) {
3887+ if (STRCMP(font_name, flp->name) == 0) {
3888+ flp->refcount++;
3889+ return (GuiFont)flp;
3890+ }
3891+ }
3892+
3893+ VimFont *font = new VimFont();
3894+ font->name = vim_strsave((char_u*)font_name);
3895+
3896+ if(count_font_styles(family) <= 0) {
3897+ if (giveErrorIfMissing)
3898+ semsg(_(e_font), font->name);
3899+ delete font;
3900+ return NOFONT;
3901+ }
3902+
3903+ // Remember font in the static list for later use
3904+ font->next = fontList;
3905+ fontList = font;
3906+
3907+ font->SetFamilyAndStyle(family, style);
3908+ if(size > 0.f)
3909+ font->SetSize(size);
3910+
3911+ font->SetSpacing(B_FIXED_SPACING);
3912+ font->SetEncoding(B_UNICODE_UTF8);
3913+
3914+ return (GuiFont)font;
3915+}
3916+
3917+/*
3918+ * Set the current text font.
3919+ */
3920+void
3921+gui_mch_set_font(
3922+ GuiFont font)
3923+{
3924+ if (gui.vimWindow->Lock()) {
3925+ VimFont *vf = (VimFont *)font;
3926+
3927+ gui.vimTextArea->SetFont(vf);
3928+
3929+ gui.char_width = (int) vf->StringWidth("n");
3930+ font_height fh;
3931+ vf->GetHeight(&fh);
3932+ gui.char_height = (int)(fh.ascent + 0.9999)
3933+ + (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999);
3934+ gui.char_ascent = (int)(fh.ascent + 0.9999);
3935+
3936+ gui.vimWindow->Unlock();
3937+ }
3938+}
3939+
3940+// XXX TODO This is apparently never called...
3941+void
3942+gui_mch_free_font(
3943+ GuiFont font)
3944+{
3945+ if(font == NOFONT)
3946+ return;
3947+ VimFont *f = (VimFont *)font;
3948+ if (--f->refcount <= 0) {
3949+ if (f->refcount < 0)
3950+ fprintf(stderr, "VimFont: refcount < 0\n");
3951+ delete f;
3952+ }
3953+}
3954+
3955+ char_u *
3956+gui_mch_get_fontname(GuiFont font, char_u *name)
3957+{
3958+ if (name == NULL)
3959+ return NULL;
3960+ return vim_strsave(name);
3961+}
3962+
3963+/*
3964+ * Adjust gui.char_height (after 'linespace' was changed).
3965+ */
3966+ int
3967+gui_mch_adjust_charheight()
3968+{
3969+
3970+ // TODO: linespace support?
3971+
3972+// #ifdef FEAT_XFONTSET
3973+// if (gui.fontset != NOFONTSET)
3974+// {
3975+// gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace;
3976+// gui.char_ascent = fontset_ascent((XFontSet)gui.fontset)
3977+// + p_linespace / 2;
3978+// }
3979+// else
3980+// #endif
3981+ {
3982+ VimFont *font = (VimFont *)gui.norm_font;
3983+ font_height fh = {0};
3984+ font->GetHeight(&fh);
3985+ gui.char_height = (int)(fh.ascent + fh.descent + 0.5) + p_linespace;
3986+ gui.char_ascent = (int)(fh.ascent + 0.5) + p_linespace / 2;
3987+ }
3988+ return OK;
3989+}
3990+
3991+/*
3992+ * Display the saved error message(s).
3993+ */
3994+#ifdef USE_MCH_ERRMSG
3995+ void
3996+display_errors(void)
3997+{
3998+ char *p;
3999+ char_u pError[256];
4000+
4001+ if (error_ga.ga_data == NULL)
4002+ return;
4003+
4004+ // avoid putting up a message box with blanks only
4005+ for (p = (char *)error_ga.ga_data; *p; ++p)
4006+ if (!isspace(*p))
4007+ {
4008+ if (STRLEN(p) > 255)
4009+ pError[0] = 255;
4010+ else
4011+ pError[0] = STRLEN(p);
4012+
4013+ STRNCPY(&pError[1], p, pError[0]);
4014+// ParamText(pError, nil, nil, nil);
4015+// Alert(128, nil);
4016+ break;
4017+ // TODO: handled message longer than 256 chars
4018+ // use auto-sizeable alert
4019+ // or dialog with scrollbars (TextEdit zone)
4020+ }
4021+ ga_clear(&error_ga);
4022+}
4023+#endif
4024+
4025+ void
4026+gui_mch_getmouse(int *x, int *y)
4027+{
4028+ fprintf(stderr, "gui_mch_getmouse");
4029+
4030+ /*int rootx, rooty, winx, winy;
4031+ Window root, child;
4032+ unsigned int mask;
4033+
4034+ if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
4035+ &rootx, &rooty, &winx, &winy, &mask)) {
4036+ *x = winx;
4037+ *y = winy;
4038+ } else*/ {
4039+ *x = -1;
4040+ *y = -1;
4041+ }
4042+}
4043+
4044+ void
4045+gui_mch_mousehide(int hide)
4046+{
4047+ fprintf(stderr, "gui_mch_getmouse");
4048+ // TODO
4049+}
4050+
4051+ static int
4052+hex_digit(int c)
4053+{
4054+ if (isdigit(c))
4055+ return c - '0';
4056+ c = TOLOWER_ASC(c);
4057+ if (c >= 'a' && c <= 'f')
4058+ return c - 'a' + 10;
4059+ return -1000;
4060+}
4061+
4062+/*
4063+ * This function has been lifted from gui_w32.c and extended a bit.
4064+ *
4065+ * Return the Pixel value (color) for the given color name.
4066+ * Return INVALCOLOR for error.
4067+ */
4068+guicolor_T
4069+gui_mch_get_color(
4070+ char_u *name)
4071+{
4072+ typedef struct GuiColourTable
4073+ {
4074+ const char *name;
4075+ guicolor_T colour;
4076+ } GuiColourTable;
4077+
4078+#define NSTATIC_COLOURS 50 // 32
4079+#define NDYNAMIC_COLOURS 33
4080+#define NCOLOURS (NSTATIC_COLOURS + NDYNAMIC_COLOURS)
4081+
4082+ static GuiColourTable table[NCOLOURS] =
4083+ {
4084+ {"Black", RGB(0x00, 0x00, 0x00)},
4085+ {"DarkGray", RGB(0x80, 0x80, 0x80)},
4086+ {"DarkGrey", RGB(0x80, 0x80, 0x80)},
4087+ {"Gray", RGB(0xC0, 0xC0, 0xC0)},
4088+ {"Grey", RGB(0xC0, 0xC0, 0xC0)},
4089+ {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
4090+ {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
4091+ {"Gray10", RGB(0x1A, 0x1A, 0x1A)},
4092+ {"Grey10", RGB(0x1A, 0x1A, 0x1A)},
4093+ {"Gray20", RGB(0x33, 0x33, 0x33)},
4094+ {"Grey20", RGB(0x33, 0x33, 0x33)},
4095+ {"Gray30", RGB(0x4D, 0x4D, 0x4D)},
4096+ {"Grey30", RGB(0x4D, 0x4D, 0x4D)},
4097+ {"Gray40", RGB(0x66, 0x66, 0x66)},
4098+ {"Grey40", RGB(0x66, 0x66, 0x66)},
4099+ {"Gray50", RGB(0x7F, 0x7F, 0x7F)},
4100+ {"Grey50", RGB(0x7F, 0x7F, 0x7F)},
4101+ {"Gray60", RGB(0x99, 0x99, 0x99)},
4102+ {"Grey60", RGB(0x99, 0x99, 0x99)},
4103+ {"Gray70", RGB(0xB3, 0xB3, 0xB3)},
4104+ {"Grey70", RGB(0xB3, 0xB3, 0xB3)},
4105+ {"Gray80", RGB(0xCC, 0xCC, 0xCC)},
4106+ {"Grey80", RGB(0xCC, 0xCC, 0xCC)},
4107+ {"Gray90", RGB(0xE5, 0xE5, 0xE5)},
4108+ {"Grey90", RGB(0xE5, 0xE5, 0xE5)},
4109+ {"White", RGB(0xFF, 0xFF, 0xFF)},
4110+ {"DarkRed", RGB(0x80, 0x00, 0x00)},
4111+ {"Red", RGB(0xFF, 0x00, 0x00)},
4112+ {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
4113+ {"DarkBlue", RGB(0x00, 0x00, 0x80)},
4114+ {"Blue", RGB(0x00, 0x00, 0xFF)},
4115+ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
4116+ {"DarkGreen", RGB(0x00, 0x80, 0x00)},
4117+ {"Green", RGB(0x00, 0xFF, 0x00)},
4118+ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
4119+ {"DarkCyan", RGB(0x00, 0x80, 0x80)},
4120+ {"Cyan", RGB(0x00, 0xFF, 0xFF)},
4121+ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
4122+ {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
4123+ {"Magenta", RGB(0xFF, 0x00, 0xFF)},
4124+ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
4125+ {"Brown", RGB(0x80, 0x40, 0x40)},
4126+ {"Yellow", RGB(0xFF, 0xFF, 0x00)},
4127+ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
4128+ {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
4129+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
4130+ {"Orange", RGB(0xFF, 0xA5, 0x00)},
4131+ {"Purple", RGB(0xA0, 0x20, 0xF0)},
4132+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
4133+ {"Violet", RGB(0xEE, 0x82, 0xEE)},
4134+ // NOTE: some entries are zero-allocated for NDDYNAMIC_COLORS
4135+ // in this table!
4136+ };
4137+
4138+ static int endColour = NSTATIC_COLOURS;
4139+ static int newColour = NSTATIC_COLOURS;
4140+
4141+ int r, g, b;
4142+ int i;
4143+
4144+ if (name[0] == '#' && STRLEN(name) == 7)
4145+ {
4146+ // Name is in "#rrggbb" format
4147+ r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
4148+ g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
4149+ b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
4150+ if (r < 0 || g < 0 || b < 0)
4151+ return INVALCOLOR;
4152+ return RGB(r, g, b);
4153+ }
4154+ else
4155+ {
4156+ // Check if the name is one of the colours we know
4157+ for (i = 0; i < endColour; i++)
4158+ if (STRICMP(name, table[i].name) == 0)
4159+ return table[i].colour;
4160+ }
4161+
4162+ /*
4163+ * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
4164+ */
4165+ {
4166+#define LINE_LEN 100
4167+ FILE *fd;
4168+ char line[LINE_LEN];
4169+ char_u *fname;
4170+
4171+ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
4172+ if (fname == NULL)
4173+ return INVALCOLOR;
4174+
4175+ fd = fopen((char *)fname, "rt");
4176+ vim_free(fname);
4177+ if (fd == NULL)
4178+ return INVALCOLOR;
4179+
4180+ while (!feof(fd))
4181+ {
4182+ int len;
4183+ int pos;
4184+ char *colour;
4185+
4186+ fgets(line, LINE_LEN, fd);
4187+ len = strlen(line);
4188+
4189+ if (len <= 1 || line[len-1] != '\n')
4190+ continue;
4191+
4192+ line[len-1] = '\0';
4193+
4194+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
4195+ if (i != 3)
4196+ continue;
4197+
4198+ colour = line + pos;
4199+
4200+ if (STRICMP(colour, name) == 0)
4201+ {
4202+ fclose(fd);
4203+ /*
4204+ * Now remember this colour in the table.
4205+ * A LRU scheme might be better but this is simpler.
4206+ * Or could use a growing array.
4207+ */
4208+ guicolor_T gcolour = RGB(r,g,b);
4209+
4210+ // NOTE: see note above in table allocation! We are working here with
4211+ // dynamically allocated names, not constant ones!
4212+ vim_free((char*)table[newColour].name);
4213+ table[newColour].name = (char *)vim_strsave((char_u *)colour);
4214+ table[newColour].colour = gcolour;
4215+
4216+ newColour++;
4217+ if (newColour >= NCOLOURS)
4218+ newColour = NSTATIC_COLOURS;
4219+ if (endColour < NCOLOURS)
4220+ endColour = newColour;
4221+
4222+ return gcolour;
4223+ }
4224+ }
4225+
4226+ fclose(fd);
4227+ }
4228+
4229+ return INVALCOLOR;
4230+}
4231+
4232+/*
4233+ * Set the current text foreground color.
4234+ */
4235+void
4236+gui_mch_set_fg_color(
4237+ guicolor_T color)
4238+{
4239+ rgb_color rgb = GUI_TO_RGB(color);
4240+ if (gui.vimWindow->Lock()) {
4241+ gui.vimTextArea->SetHighColor(rgb);
4242+ gui.vimWindow->Unlock();
4243+ }
4244+}
4245+
4246+/*
4247+ * Set the current text background color.
4248+ */
4249+void
4250+gui_mch_set_bg_color(
4251+ guicolor_T color)
4252+{
4253+ rgb_color rgb = GUI_TO_RGB(color);
4254+ if (gui.vimWindow->Lock()) {
4255+ gui.vimTextArea->SetLowColor(rgb);
4256+ gui.vimWindow->Unlock();
4257+ }
4258+}
4259+
4260+/*
4261+ * Set the current text special color.
4262+ */
4263+ void
4264+gui_mch_set_sp_color(guicolor_T color)
4265+{
4266+ // prev_sp_color = color;
4267+}
4268+
4269+void
4270+gui_mch_draw_string(
4271+ int row,
4272+ int col,
4273+ char_u *s,
4274+ int len,
4275+ int flags)
4276+{
4277+ if (gui.vimWindow->Lock()) {
4278+ gui.vimTextArea->mchDrawString(row, col, s, len, flags);
4279+ gui.vimWindow->Unlock();
4280+ }
4281+}
4282+
4283+ guicolor_T
4284+gui_mch_get_rgb_color(int r, int g, int b)
4285+{
4286+ return gui_get_rgb_color_cmn(r, g, b);
4287+}
4288+
4289+
4290+// Return OK if the key with the termcap name "name" is supported.
4291+int
4292+gui_mch_haskey(
4293+ char_u *name)
4294+{
4295+ int i;
4296+
4297+ for (i = 0; special_keys[i].BeKeys != 0; i++)
4298+ if (name[0] == special_keys[i].vim_code0 &&
4299+ name[1] == special_keys[i].vim_code1)
4300+ return OK;
4301+ return FAIL;
4302+}
4303+
4304+ void
4305+gui_mch_beep()
4306+{
4307+ ::beep();
4308+}
4309+
4310+ void
4311+gui_mch_flash(int msec)
4312+{
4313+ // Do a visual beep by reversing the foreground and background colors
4314+
4315+ if (gui.vimWindow->Lock()) {
4316+ BRect rect = gui.vimTextArea->Bounds();
4317+
4318+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
4319+ gui.vimTextArea->FillRect(rect);
4320+ gui.vimTextArea->Sync();
4321+ snooze(msec * 1000); // wait for a few msec
4322+ gui.vimTextArea->FillRect(rect);
4323+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
4324+ gui.vimTextArea->Flush();
4325+ gui.vimWindow->Unlock();
4326+ }
4327+}
4328+
4329+/*
4330+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
4331+ */
4332+void
4333+gui_mch_invert_rectangle(
4334+ int r,
4335+ int c,
4336+ int nr,
4337+ int nc)
4338+{
4339+ BRect rect;
4340+ rect.left = FILL_X(c);
4341+ rect.top = FILL_Y(r);
4342+ rect.right = rect.left + nc * gui.char_width - PEN_WIDTH;
4343+ rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH;
4344+
4345+ if (gui.vimWindow->Lock()) {
4346+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
4347+ gui.vimTextArea->FillRect(rect);
4348+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
4349+ gui.vimWindow->Unlock();
4350+ }
4351+}
4352+
4353+/*
4354+ * Iconify the GUI window.
4355+ */
4356+ void
4357+gui_mch_iconify()
4358+{
4359+ if (gui.vimWindow->Lock()) {
4360+ gui.vimWindow->Minimize(true);
4361+ gui.vimWindow->Unlock();
4362+ }
4363+}
4364+
4365+#if defined(FEAT_EVAL) || defined(PROTO)
4366+/*
4367+ * Bring the Vim window to the foreground.
4368+ */
4369+ void
4370+gui_mch_set_foreground(void)
4371+{
4372+ // TODO
4373+}
4374+#endif
4375+
4376+/*
4377+ * Set the window title
4378+ */
4379+void
4380+gui_mch_settitle(
4381+ char_u *title,
4382+ char_u *icon)
4383+{
4384+ if (gui.vimWindow->Lock()) {
4385+ gui.vimWindow->SetTitle((char *)title);
4386+ gui.vimWindow->Unlock();
4387+ }
4388+}
4389+
4390+/*
4391+ * Draw a cursor without focus.
4392+ */
4393+ void
4394+gui_mch_draw_hollow_cursor(guicolor_T color)
4395+{
4396+ gui_mch_set_fg_color(color);
4397+
4398+ BRect r;
4399+ r.left = FILL_X(gui.col);
4400+ r.top = FILL_Y(gui.row);
4401+ int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); // TODO-TODO
4402+ if(cells>=4) cells = 1;
4403+ r.right = r.left + cells*gui.char_width - PEN_WIDTH;
4404+ r.bottom = r.top + gui.char_height - PEN_WIDTH;
4405+
4406+ if (gui.vimWindow->Lock()) {
4407+ gui.vimTextArea->StrokeRect(r);
4408+ gui.vimWindow->Unlock();
4409+ // gui_mch_flush();
4410+ }
4411+}
4412+
4413+/*
4414+ * Draw part of a cursor, only w pixels wide, and h pixels high.
4415+ */
4416+void
4417+gui_mch_draw_part_cursor(
4418+ int w,
4419+ int h,
4420+ guicolor_T color)
4421+{
4422+ gui_mch_set_fg_color(color);
4423+
4424+ BRect r;
4425+ r.left =
4426+#ifdef FEAT_RIGHTLEFT
4427+ // vertical line should be on the right of current point
4428+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
4429+#endif
4430+ FILL_X(gui.col);
4431+ r.right = r.left + w - PEN_WIDTH;
4432+ r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH;
4433+ r.top = r.bottom - h + PEN_WIDTH;
4434+
4435+ if (gui.vimWindow->Lock()) {
4436+ gui.vimTextArea->FillRect(r);
4437+ gui.vimWindow->Unlock();
4438+ // gui_mch_flush();
4439+ }
4440+}
4441+
4442+/*
4443+ * Catch up with any queued events. This may put keyboard input into the
4444+ * input buffer, call resize call-backs, trigger timers etc. If there is
4445+ * nothing in the event queue (& no timers pending), then we return
4446+ * immediately.
4447+ */
4448+ void
4449+gui_mch_update()
4450+{
4451+ gui_mch_flush();
4452+ while (port_count(gui.vdcmp) > 0 &&
4453+ !vim_is_input_buf_full() &&
4454+ gui_haiku_process_event(0) >= B_OK)
4455+ /* nothing */ ;
4456+}
4457+
4458+/*
4459+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
4460+ * from the keyboard.
4461+ * wtime == -1 Wait forever.
4462+ * wtime == 0 This should never happen.
4463+ * wtime > 0 Wait wtime milliseconds for a character.
4464+ * Returns OK if a character was found to be available within the given time,
4465+ * or FAIL otherwise.
4466+ */
4467+int
4468+gui_mch_wait_for_chars(
4469+ int wtime)
4470+{
4471+ int focus;
4472+ bigtime_t until, timeout;
4473+ status_t st;
4474+
4475+ if (wtime >= 0) {
4476+ timeout = wtime * 1000;
4477+ until = system_time() + timeout;
4478+ } else {
4479+ timeout = B_INFINITE_TIMEOUT;
4480+ }
4481+
4482+ focus = gui.in_focus;
4483+ for (;;)
4484+ {
4485+ // Stop or start blinking when focus changes
4486+ if (gui.in_focus != focus)
4487+ {
4488+ if (gui.in_focus)
4489+ gui_mch_start_blink();
4490+ else
4491+ gui_mch_stop_blink();
4492+ focus = gui.in_focus;
4493+ }
4494+
4495+ gui_mch_flush();
4496+ /*
4497+ * Don't use gui_mch_update() because then we will spin-lock until a
4498+ * char arrives, instead we use gui_haiku_process_event() to hang until
4499+ * an event arrives. No need to check for input_buf_full because we
4500+ * are returning as soon as it contains a single char.
4501+ */
4502+ st = gui_haiku_process_event(timeout);
4503+
4504+ if (input_available())
4505+ return OK;
4506+ if (st < B_OK) // includes B_TIMED_OUT
4507+ return FAIL;
4508+
4509+ /*
4510+ * Calculate how much longer we're willing to wait for the
4511+ * next event.
4512+ */
4513+ if (wtime >= 0) {
4514+ timeout = until - system_time();
4515+ if (timeout < 0)
4516+ break;
4517+ }
4518+ }
4519+ return FAIL;
4520+
4521+}
4522+
4523+/*
4524+ * Output routines.
4525+ */
4526+
4527+/*
4528+ * Flush any output to the screen. This is typically called before
4529+ * the app goes to sleep.
4530+ */
4531+ void
4532+gui_mch_flush()
4533+{
4534+ // does this need to lock the window? Apparently not but be safe.
4535+ if (gui.vimWindow->Lock()) {
4536+ gui.vimWindow->Flush();
4537+ gui.vimWindow->Unlock();
4538+ }
4539+ return;
4540+}
4541+
4542+/*
4543+ * Clear a rectangular region of the screen from text pos (row1, col1) to
4544+ * (row2, col2) inclusive.
4545+ */
4546+void
4547+gui_mch_clear_block(
4548+ int row1,
4549+ int col1,
4550+ int row2,
4551+ int col2)
4552+{
4553+ if (gui.vimWindow->Lock()) {
4554+ gui.vimTextArea->mchClearBlock(row1, col1, row2, col2);
4555+ gui.vimWindow->Unlock();
4556+ }
4557+}
4558+
4559+ void
4560+gui_mch_clear_all()
4561+{
4562+ if (gui.vimWindow->Lock()) {
4563+ gui.vimTextArea->mchClearAll();
4564+ gui.vimWindow->Unlock();
4565+ }
4566+}
4567+
4568+/*
4569+ * Delete the given number of lines from the given row, scrolling up any
4570+ * text further down within the scroll region.
4571+ */
4572+void
4573+gui_mch_delete_lines(
4574+ int row,
4575+ int num_lines)
4576+{
4577+ gui.vimTextArea->mchDeleteLines(row, num_lines);
4578+}
4579+
4580+/*
4581+ * Insert the given number of lines before the given row, scrolling down any
4582+ * following text within the scroll region.
4583+ */
4584+void
4585+gui_mch_insert_lines(
4586+ int row,
4587+ int num_lines)
4588+{
4589+ gui.vimTextArea->mchInsertLines(row, num_lines);
4590+}
4591+
4592+#if defined(FEAT_MENU) || defined(PROTO)
4593+/*
4594+ * Menu stuff.
4595+ */
4596+
4597+void
4598+gui_mch_enable_menu(
4599+ int flag)
4600+{
4601+ if (gui.vimWindow->Lock())
4602+ {
4603+ BMenuBar *menubar = gui.vimForm->MenuBar();
4604+ menubar->SetEnabled(flag);
4605+ gui.vimWindow->Unlock();
4606+ }
4607+}
4608+
4609+void
4610+gui_mch_set_menu_pos(
4611+ int x,
4612+ int y,
4613+ int w,
4614+ int h)
4615+{
4616+ // It will be in the right place anyway
4617+}
4618+
4619+/*
4620+ * Add a sub menu to the menu bar.
4621+ */
4622+void
4623+gui_mch_add_menu(
4624+ vimmenu_T *menu,
4625+ int idx)
4626+{
4627+ vimmenu_T *parent = menu->parent;
4628+
4629+ // popup menu - just create it unattached
4630+ if (menu_is_popup(menu->name) && parent == NULL) {
4631+ BPopUpMenu* popUpMenu = new BPopUpMenu((const char*)menu->name, false, false);
4632+ menu->submenu_id = popUpMenu;
4633+ menu->id = NULL;
4634+ return;
4635+ }
4636+
4637+ if (!menu_is_menubar(menu->name)
4638+ || (parent != NULL && parent->submenu_id == NULL))
4639+ return;
4640+
4641+ if (gui.vimWindow->Lock())
4642+ {
4643+ // Major re-write of the menu code, it was failing with memory corruption when
4644+ // we started loading multiple files (the Buffer menu)
4645+ //
4646+ // Note we don't use the preference values yet, all are inserted into the
4647+ // menubar on a first come-first served basis...
4648+ //
4649+ // richard@whitequeen.com jul 99
4650+
4651+ BMenu *tmp;
4652+
4653+ if ( parent )
4654+ tmp = parent->submenu_id;
4655+ else
4656+ tmp = gui.vimForm->MenuBar();
4657+ // make sure we don't try and add the same menu twice. The Buffers menu tries to
4658+ // do this and Be starts to crash...
4659+
4660+ if ( ! tmp->FindItem((const char *) menu->dname)) {
4661+
4662+ BMenu *bmenu = new BMenu((char *)menu->dname);
4663+
4664+ menu->submenu_id = bmenu;
4665+
4666+ // when we add a BMenu to another Menu, it creates the interconnecting BMenuItem
4667+ tmp->AddItem(bmenu);
4668+
4669+ // Now its safe to query the menu for the associated MenuItem....
4670+ menu->id = tmp->FindItem((const char *) menu->dname);
4671+
4672+ }
4673+ gui.vimWindow->Unlock();
4674+ }
4675+}
4676+
4677+ void
4678+gui_mch_toggle_tearoffs(int enable)
4679+{
4680+ // no tearoff menus
4681+}
4682+
4683+ static BMessage *
4684+MenuMessage(vimmenu_T *menu)
4685+{
4686+ BMessage *m = new BMessage('menu');
4687+ m->AddPointer("VimMenu", (void *)menu);
4688+
4689+ return m;
4690+}
4691+
4692+/*
4693+ * Add a menu item to a menu
4694+ */
4695+void
4696+gui_mch_add_menu_item(
4697+ vimmenu_T *menu,
4698+ int idx)
4699+{
4700+ int mnemonic = 0;
4701+ vimmenu_T *parent = menu->parent;
4702+
4703+ // TODO: use menu->actext
4704+ // This is difficult, since on Be, an accelerator must be a single char
4705+ // and a lot of Vim ones are the standard VI commands.
4706+ //
4707+ // Punt for Now...
4708+ // richard@whiequeen.com jul 99
4709+ if (gui.vimWindow->Lock())
4710+ {
4711+#ifdef FEAT_TOOLBAR
4712+ if(menu_is_toolbar(parent->name)) {
4713+ VimToolbar *toolbar = gui.vimForm->ToolBar();
4714+ if(toolbar != NULL) {
4715+ toolbar->AddButton(idx, menu);
4716+ }
4717+ } else
4718+#endif
4719+
4720+ if (parent->submenu_id != NULL || menu_is_popup(parent->name)) {
4721+ if (menu_is_separator(menu->name)) {
4722+ BSeparatorItem *item = new BSeparatorItem();
4723+ parent->submenu_id->AddItem(item);
4724+ menu->id = item;
4725+ menu->submenu_id = NULL;
4726+ }
4727+ else {
4728+ BMenuItem *item = new BMenuItem((char *)menu->dname,
4729+ MenuMessage(menu));
4730+ item->SetTarget(gui.vimTextArea);
4731+ item->SetTrigger((char) menu->mnemonic);
4732+ parent->submenu_id->AddItem(item);
4733+ menu->id = item;
4734+ menu->submenu_id = NULL;
4735+ }
4736+ }
4737+ gui.vimWindow->Unlock();
4738+ }
4739+}
4740+
4741+/*
4742+ * Destroy the machine specific menu widget.
4743+ */
4744+void
4745+gui_mch_destroy_menu(
4746+ vimmenu_T *menu)
4747+{
4748+ if (gui.vimWindow->Lock())
4749+ {
4750+#ifdef FEAT_TOOLBAR
4751+ if(menu->parent && menu_is_toolbar(menu->parent->name)) {
4752+ VimToolbar *toolbar = gui.vimForm->ToolBar();
4753+ if(toolbar != NULL) {
4754+ toolbar->RemoveButton(menu);
4755+ }
4756+ } else
4757+#endif
4758+ {
4759+ assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0);
4760+ /*
4761+ * Detach this menu from its parent, so that it is not deleted
4762+ * twice once we get to delete that parent.
4763+ * Deleting a BMenuItem also deletes the associated BMenu, if any
4764+ * (which does not have any items anymore since they were
4765+ * removed and deleted before).
4766+ */
4767+ BMenu *bmenu = menu->id->Menu();
4768+ if (bmenu)
4769+ {
4770+ bmenu->RemoveItem(menu->id);
4771+ /*
4772+ * If we removed the last item from the menu bar,
4773+ * resize it out of sight.
4774+ */
4775+ if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0)
4776+ {
4777+ bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN);
4778+ }
4779+ }
4780+ delete menu->id;
4781+ menu->id = NULL;
4782+ menu->submenu_id = NULL;
4783+
4784+ gui.menu_height = (int) gui.vimForm->MenuHeight();
4785+ }
4786+ gui.vimWindow->Unlock();
4787+ }
4788+}
4789+
4790+/*
4791+ * Make a menu either grey or not grey.
4792+ */
4793+void
4794+gui_mch_menu_grey(
4795+ vimmenu_T *menu,
4796+ int grey)
4797+{
4798+#ifdef FEAT_TOOLBAR
4799+ if(menu->parent && menu_is_toolbar(menu->parent->name)) {
4800+ if (gui.vimWindow->Lock()) {
4801+ VimToolbar *toolbar = gui.vimForm->ToolBar();
4802+ if(toolbar != NULL) {
4803+ toolbar->GrayButton(menu, grey);
4804+ }
4805+ gui.vimWindow->Unlock();
4806+ }
4807+ } else
4808+#endif
4809+ if (menu->id != NULL)
4810+ menu->id->SetEnabled(!grey);
4811+}
4812+
4813+/*
4814+ * Make menu item hidden or not hidden
4815+ */
4816+void
4817+gui_mch_menu_hidden(
4818+ vimmenu_T *menu,
4819+ int hidden)
4820+{
4821+ if (menu->id != NULL)
4822+ menu->id->SetEnabled(!hidden);
4823+}
4824+
4825+/*
4826+ * This is called after setting all the menus to grey/hidden or not.
4827+ */
4828+ void
4829+gui_mch_draw_menubar()
4830+{
4831+ // Nothing to do in BeOS
4832+}
4833+
4834+ void
4835+gui_mch_show_popupmenu(vimmenu_T *menu)
4836+{
4837+ if (!menu_is_popup(menu->name) || menu->submenu_id == NULL)
4838+ return;
4839+
4840+ BPopUpMenu* popupMenu = dynamic_cast<BPopUpMenu*>(menu->submenu_id);
4841+ if (popupMenu == NULL)
4842+ return;
4843+
4844+ BPoint point;
4845+ if(gui.vimWindow->Lock()) {
4846+ uint32 buttons = 0;
4847+ gui.vimTextArea->GetMouse(&point, &buttons);
4848+ gui.vimTextArea->ConvertToScreen(&point);
4849+ gui.vimWindow->Unlock();
4850+ }
4851+ popupMenu->Go(point, true);
4852+}
4853+
4854+#endif // FEAT_MENU
4855+
4856+// Mouse stuff
4857+
4858+#ifdef FEAT_CLIPBOARD
4859+/*
4860+ * Clipboard stuff, for cutting and pasting text to other windows.
4861+ */
4862+char textplain[] = "text/plain";
4863+char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype";
4864+
4865+/*
4866+ * Get the current selection and put it in the clipboard register.
4867+ */
4868+ void
4869+clip_mch_request_selection(Clipboard_T *cbd)
4870+{
4871+ if (be_clipboard->Lock())
4872+ {
4873+ BMessage *m = be_clipboard->Data();
4874+ // m->PrintToStream();
4875+
4876+ char_u *string = NULL;
4877+ ssize_t stringlen = -1;
4878+
4879+ if (m->FindData(textplain, B_MIME_TYPE,
4880+ (const void **)&string, &stringlen) == B_OK
4881+ || m->FindString("text", (const char **)&string) == B_OK)
4882+ {
4883+ if (stringlen == -1)
4884+ stringlen = STRLEN(string);
4885+
4886+ int type;
4887+ char *seltype;
4888+ ssize_t seltypelen;
4889+
4890+ /*
4891+ * Try to get the special vim selection type first
4892+ */
4893+ if (m->FindData(vimselectiontype, B_MIME_TYPE,
4894+ (const void **)&seltype, &seltypelen) == B_OK)
4895+ {
4896+ switch (*seltype)
4897+ {
4898+ default:
4899+ case 'L': type = MLINE; break;
4900+ case 'C': type = MCHAR; break;
4901+#ifdef FEAT_VISUAL
4902+ case 'B': type = MBLOCK; break;
4903+#endif
4904+ }
4905+ }
4906+ else
4907+ {
4908+ // Otherwise use heuristic as documented
4909+ type = memchr(string, stringlen, '\n') ? MLINE : MCHAR;
4910+ }
4911+ clip_yank_selection(type, string, (long)stringlen, cbd);
4912+ }
4913+ be_clipboard->Unlock();
4914+ }
4915+}
4916+/*
4917+ * Make vim the owner of the current selection.
4918+ */
4919+ void
4920+clip_mch_lose_selection(Clipboard_T *cbd)
4921+{
4922+ // Nothing needs to be done here
4923+}
4924+
4925+/*
4926+ * Make vim the owner of the current selection. Return OK upon success.
4927+ */
4928+ int
4929+clip_mch_own_selection(Clipboard_T *cbd)
4930+{
4931+ /*
4932+ * Never actually own the clipboard. If another application sets the
4933+ * clipboard, we don't want to think that we still own it.
4934+ */
4935+ return FAIL;
4936+}
4937+
4938+/*
4939+ * Send the current selection to the clipboard.
4940+ */
4941+ void
4942+clip_mch_set_selection(Clipboard_T *cbd)
4943+{
4944+ if (be_clipboard->Lock())
4945+ {
4946+ be_clipboard->Clear();
4947+ BMessage *m = be_clipboard->Data();
4948+ assert(m);
4949+
4950+ // If the '*' register isn't already filled in, fill it in now
4951+ cbd->owned = TRUE;
4952+ clip_get_selection(cbd);
4953+ cbd->owned = FALSE;
4954+
4955+ char_u *str = NULL;
4956+ long_u count;
4957+ int type;
4958+
4959+ type = clip_convert_selection(&str, &count, cbd);
4960+
4961+ if (type < 0)
4962+ return;
4963+
4964+ m->AddData(textplain, B_MIME_TYPE, (void *)str, count);
4965+
4966+ // Add type of selection
4967+ char vtype;
4968+ switch (type)
4969+ {
4970+ default:
4971+ case MLINE: vtype = 'L'; break;
4972+ case MCHAR: vtype = 'C'; break;
4973+#ifdef FEAT_VISUAL
4974+ case MBLOCK: vtype = 'B'; break;
4975+#endif
4976+ }
4977+ m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1);
4978+
4979+ vim_free(str);
4980+
4981+ be_clipboard->Commit();
4982+ be_clipboard->Unlock();
4983+ }
4984+}
4985+
4986+#endif // FEAT_CLIPBOARD
4987+
4988+#ifdef FEAT_BROWSE
4989+/*
4990+ * Pop open a file browser and return the file selected, in allocated memory,
4991+ * or NULL if Cancel is hit.
4992+ * saving - TRUE if the file will be saved to, FALSE if it will be opened.
4993+ * title - Title message for the file browser dialog.
4994+ * dflt - Default name of file.
4995+ * ext - Default extension to be added to files without extensions.
4996+ * initdir - directory in which to open the browser (NULL = current dir)
4997+ * filter - Filter for matched files to choose from.
4998+ * Has a format like this:
4999+ * "C Files (*.c)\0*.c\0"
5000+ * "All Files\0*.*\0\0"
5001+ * If these two strings were concatenated, then a choice of two file
5002+ * filters will be selectable to the user. Then only matching files will
5003+ * be shown in the browser. If NULL, the default allows all files.
5004+ *
5005+ * *NOTE* - the filter string must be terminated with TWO nulls.
5006+ */
5007+char_u *
5008+gui_mch_browse(
5009+ int saving,
5010+ char_u *title,
5011+ char_u *dflt,
5012+ char_u *ext,
5013+ char_u *initdir,
5014+ char_u *filter)
5015+{
5016+ gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL,
5017+ NULL, NULL, 0, false,
5018+ new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true);
5019+
5020+ gui.vimApp->fBrowsedPath.Unset();
5021+
5022+ gui.vimApp->fFilePanel->Window()->SetTitle((char*)title);
5023+ gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir);
5024+
5025+ gui.vimApp->fFilePanel->Show();
5026+
5027+ gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem");
5028+
5029+ while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED);
5030+
5031+ char_u *fileName = NULL;
5032+ status_t result = gui.vimApp->fBrowsedPath.InitCheck();
5033+ if(result == B_OK) {
5034+ fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path());
5035+ } else
5036+ if(result != B_NO_INIT) {
5037+ fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n",
5038+ result, strerror(result));
5039+ }
5040+
5041+ delete gui.vimApp->fFilePanel;
5042+ gui.vimApp->fFilePanel = NULL;
5043+
5044+ return fileName;
5045+}
5046+#endif // FEAT_BROWSE
5047+
5048+
5049+#if defined(FEAT_GUI_DIALOG)
5050+
5051+/*
5052+ * Create a dialog dynamically from the parameter strings.
5053+ * type = type of dialog (question, alert, etc.)
5054+ * title = dialog title. may be NULL for default title.
5055+ * message = text to display. Dialog sizes to accommodate it.
5056+ * buttons = '\n' separated list of button captions, default first.
5057+ * dfltbutton = number of default button.
5058+ *
5059+ * This routine returns 1 if the first button is pressed,
5060+ * 2 for the second, etc.
5061+ *
5062+ * 0 indicates Esc was pressed.
5063+ * -1 for unexpected error
5064+ *
5065+ * If stubbing out this fn, return 1.
5066+ */
5067+
5068+int
5069+gui_mch_dialog(
5070+ int type,
5071+ char_u *title,
5072+ char_u *message,
5073+ char_u *buttons,
5074+ int dfltbutton,
5075+ char_u *textfield,
5076+ int ex_cmd)
5077+{
5078+ VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message,
5079+ (char*)buttons, dfltbutton, (char*)textfield, ex_cmd);
5080+ return dialog->Go();
5081+}
5082+
5083+#endif // FEAT_GUI_DIALOG
5084+
5085+
5086+/*
5087+ * Return the RGB value of a pixel as long.
5088+ */
5089+ guicolor_T
5090+gui_mch_get_rgb(guicolor_T pixel)
5091+{
5092+ rgb_color rgb = GUI_TO_RGB(pixel);
5093+
5094+ return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8)
5095+ + (rgb.blue & 0xff);
5096+}
5097+
5098+ void
5099+gui_mch_setmouse(int x, int y)
5100+{
5101+ TRACE();
5102+ // TODO
5103+}
5104+
5105+#ifdef FEAT_MBYTE_IME
5106+ void
5107+im_set_position(int row, int col)
5108+{
5109+ if(gui.vimWindow->Lock())
5110+ {
5111+ gui.vimTextArea->DrawIMString();
5112+ gui.vimWindow->Unlock();
5113+ }
5114+ return;
5115+}
5116+#endif
5117+
5118+ void
5119+gui_mch_show_toolbar(int showit)
5120+{
5121+ VimToolbar *toolbar = gui.vimForm->ToolBar();
5122+ gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.;
5123+}
5124+
5125+ void
5126+gui_mch_set_toolbar_pos(int x, int y, int w, int h)
5127+{
5128+ VimToolbar *toolbar = gui.vimForm->ToolBar();
5129+ if(toolbar != NULL) {
5130+ if (gui.vimWindow->Lock()) {
5131+ toolbar->MoveTo(x, y);
5132+ toolbar->ResizeTo(w - 1, h - 1);
5133+ gui.vimWindow->Unlock();
5134+ }
5135+ }
5136+}
5137+
5138+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
5139+
5140+/*
5141+ * Show or hide the tabline.
5142+ */
5143+ void
5144+gui_mch_show_tabline(int showit)
5145+{
5146+ VimTabLine *tabLine = gui.vimForm->TabLine();
5147+
5148+ if (tabLine == NULL)
5149+ return;
5150+
5151+ if (!showit != !gui.vimForm->IsShowingTabLine()) {
5152+ gui.vimForm->SetShowingTabLine(showit != 0);
5153+ gui.tabline_height = gui.vimForm->TablineHeight();
5154+ }
5155+}
5156+
5157+ void
5158+gui_mch_set_tabline_pos(int x, int y, int w, int h)
5159+{
5160+ VimTabLine *tabLine = gui.vimForm->TabLine();
5161+ if(tabLine != NULL) {
5162+ if (gui.vimWindow->Lock()) {
5163+ tabLine->MoveTo(x, y);
5164+ tabLine->ResizeTo(w - 1, h - 1);
5165+ gui.vimWindow->Unlock();
5166+ }
5167+ }
5168+}
5169+
5170+/*
5171+ * Return TRUE when tabline is displayed.
5172+ */
5173+ int
5174+gui_mch_showing_tabline()
5175+{
5176+ VimTabLine *tabLine = gui.vimForm->TabLine();
5177+ return tabLine != NULL && gui.vimForm->IsShowingTabLine();
5178+}
5179+
5180+/*
5181+ * Update the labels of the tabline.
5182+ */
5183+ void
5184+gui_mch_update_tabline()
5185+{
5186+ tabpage_T *tp;
5187+ int nr = 0;
5188+ int curtabidx = 0;
5189+
5190+ VimTabLine *tabLine = gui.vimForm->TabLine();
5191+
5192+ if (tabLine == NULL)
5193+ return;
5194+
5195+ gui.vimWindow->Lock();
5196+
5197+ // Add a label for each tab page. They all contain the same text area.
5198+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) {
5199+ if (tp == curtab)
5200+ curtabidx = nr;
5201+
5202+ BTab* tab = tabLine->TabAt(nr);
5203+
5204+ if (tab == NULL) {
5205+ tab = new VimTabLine::VimTab();
5206+ tabLine->AddTab(NULL, tab);
5207+ }
5208+
5209+ get_tabline_label(tp, FALSE);
5210+ tab->SetLabel((const char*)NameBuff);
5211+ tabLine->Invalidate();
5212+ }
5213+
5214+ // Remove any old labels.
5215+ while (nr < tabLine->CountTabs())
5216+ tabLine->RemoveTab(nr);
5217+
5218+ if(tabLine->Selection() != curtabidx)
5219+ tabLine->Select(curtabidx);
5220+
5221+ gui.vimWindow->Unlock();
5222+}
5223+
5224+/*
5225+ * Set the current tab to "nr". First tab is 1.
5226+ */
5227+ void
5228+gui_mch_set_curtab(int nr)
5229+{
5230+ VimTabLine *tabLine = gui.vimForm->TabLine();
5231+ if(tabLine == NULL)
5232+ return;
5233+
5234+ gui.vimWindow->Lock();
5235+
5236+ if(tabLine->Selection() != nr -1)
5237+ tabLine->Select(nr -1);
5238+
5239+ gui.vimWindow->Unlock();
5240+}
5241+
5242+#endif // FEAT_GUI_TABLINE
diff -r 619eb9bc3249 -r 22f0dda71638 src/gui_haiku.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui_haiku.h Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,51 @@
1+/* vi:set ts=8 sts=4 sw=4:
2+ *
3+ * VIM - Vi IMproved by Bram Moolenaar
4+ * GUI support by Olaf "Rhialto" Seibert
5+ *
6+ * Do ":help uganda" in Vim to read copying and usage conditions.
7+ * Do ":help credits" in Vim to see a list of people who contributed.
8+ *
9+ * Haiku GUI.
10+ *
11+ * Based on "GUI support for the Buzzword Enhanced Operating System for PPC."
12+ *
13+ */
14+
15+/*
16+ * This file must be acceptable both as C and C++.
17+ * The BeOS API is defined in terms of C++, but some classes
18+ * should be somewhat known in the common C code.
19+ */
20+
21+// System classes
22+
23+struct BMenu;
24+struct BMenuItem;
25+struct BPictureButton;
26+
27+// Our own Vim-related classes
28+
29+struct VimApp;
30+struct VimFormView;
31+struct VimTextAreaView;
32+struct VimWindow;
33+struct VimScrollBar;
34+
35+// Locking functions
36+
37+extern int vim_lock_screen();
38+extern void vim_unlock_screen();
39+
40+#ifndef __cplusplus
41+
42+typedef struct BMenu BMenu;
43+typedef struct BMenuItem BMenuItem;
44+typedef struct BPictureButton BPictureButton;
45+typedef struct VimWindow VimWindow;
46+typedef struct VimFormView VimFormView;
47+typedef struct VimTextAreaView VimTextAreaView;
48+typedef struct VimApp VimApp;
49+typedef struct VimScrollBar VimScrollBar;
50+
51+#endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/mbyte.c
--- a/src/mbyte.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/mbyte.c Wed Feb 26 16:30:04 2020 +0100
@@ -6488,7 +6488,7 @@
64886488 # endif
64896489 }
64906490
6491-# if defined(FEAT_GUI) && !defined(VIMDLL)
6491+# if defined(FEAT_GUI) && !defined(FEAT_GUI_HAIKU) && !defined(VIMDLL)
64926492 void
64936493 im_set_position(int row UNUSED, int col UNUSED)
64946494 {
diff -r 619eb9bc3249 -r 22f0dda71638 src/menu.c
--- a/src/menu.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/menu.c Wed Feb 26 16:30:04 2020 +0100
@@ -2525,7 +2525,7 @@
25252525 }
25262526
25272527 #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
2528- || defined(FEAT_TERM_POPUP_MENU) \
2528+ || defined(FEAT_TERM_POPUP_MENU) || defined(FEAT_GUI_HAIKU) \
25292529 || defined(FEAT_BEVAL_TIP) || defined(PROTO)
25302530 /*
25312531 * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy.
diff -r 619eb9bc3249 -r 22f0dda71638 src/misc1.c
--- a/src/misc1.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/misc1.c Wed Feb 26 16:30:04 2020 +0100
@@ -14,6 +14,10 @@
1414 #include "vim.h"
1515 #include "version.h"
1616
17+#if defined(__HAIKU__)
18+# include <storage/FindDirectory.h>
19+#endif
20+
1721 #if defined(MSWIN)
1822 # include <lm.h>
1923 #endif
@@ -1667,6 +1671,18 @@
16671671 // handling $VIMRUNTIME and $VIM is below, bail out if it's another name.
16681672 vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
16691673 if (!vimruntime && STRCMP(name, "VIM") != 0)
1674+#if defined(__HAIKU__)
1675+ // special handling for user settings directory...
1676+ if (STRCMP(name, "BE_USER_SETTINGS") == 0)
1677+ {
1678+ static char userSettingsPath[MAXPATHL] = {0};
1679+
1680+ if (B_OK == find_directory(B_USER_SETTINGS_DIRECTORY, 0,
1681+ false, userSettingsPath, MAXPATHL))
1682+ return userSettingsPath;
1683+ }
1684+ else
1685+#endif
16701686 return NULL;
16711687
16721688 /*
diff -r 619eb9bc3249 -r 22f0dda71638 src/mouse.c
--- a/src/mouse.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/mouse.c Wed Feb 26 16:30:04 2020 +0100
@@ -538,7 +538,7 @@
538538 // menu on the button down event.
539539 return FALSE;
540540 # endif
541-# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
541+# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
542542 if (is_click || is_drag)
543543 // Ignore right button down and drag mouse events. Windows
544544 // only shows the popup menu on the button up event.
diff -r 619eb9bc3249 -r 22f0dda71638 src/option.h
--- a/src/option.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/option.h Wed Feb 26 16:30:04 2020 +0100
@@ -10,6 +10,9 @@
1010 * option.h: definition of global variables for settable options
1111 */
1212
13+#ifndef _OPTION_H_
14+#define _OPTION_H_
15+
1316 //
1417 // Flags
1518 //
@@ -1290,3 +1293,5 @@
12901293
12911294 // Value for b_p_ul indicating the global value must be used.
12921295 #define NO_LOCAL_UNDOLEVEL -123456
1296+
1297+#endif // _OPTION_H_
diff -r 619eb9bc3249 -r 22f0dda71638 src/os_haiku.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_haiku.h Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,37 @@
1+/* vi:set ts=8 sts=4 sw=4:
2+ *
3+ * VIM - Vi IMproved by Bram Moolenaar
4+ * Haiku port by Siarzhuk Zharski
5+ *
6+ * Do ":help uganda" in Vim to read copying and usage conditions.
7+ * Do ":help credits" in Vim to see a list of people who contributed.
8+ */
9+
10+/*
11+ * os_haiku.h
12+ */
13+
14+#define USE_TERM_CONSOLE
15+
16+#define USR_VIM_DIR "$BE_USER_SETTINGS/vim"
17+
18+#define USR_EXRC_FILE USR_VIM_DIR "/exrc"
19+#define USR_EXRC_FILE2 USR_VIM_DIR "/vim/exrc"
20+#define USR_VIMRC_FILE USR_VIM_DIR "/vimrc"
21+#define USR_VIMRC_FILE2 USR_VIM_DIR "/vim/vimrc"
22+#define USR_GVIMRC_FILE USR_VIM_DIR "/gvimrc"
23+#define USR_GVIMRC_FILE2 USR_VIM_DIR "/vim/gvimrc"
24+#define VIMINFO_FILE USR_VIM_DIR "/viminfo"
25+
26+#ifdef RUNTIME_GLOBAL
27+# ifdef RUNTIME_GLOBAL_AFTER
28+# define DFLT_RUNTIMEPATH USR_VIM_DIR "," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "," USR_VIM_DIR "/after"
29+# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER
30+# else
31+# define DFLT_RUNTIMEPATH USR_VIM_DIR "," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after," USR_VIM_DIR "/after"
32+# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after"
33+# endif
34+#else
35+# define DFLT_RUNTIMEPATH USR_VIM_DIR ",$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after," USR_VIM_DIR "/after"
36+# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
37+#endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/os_haiku.rdef
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_haiku.rdef Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,143 @@
1+/*
2+ * os_haiku.rdef
3+ */
4+
5+resource app_signature "application/x-vnd.Haiku-Vim-8";
6+
7+resource app_version {
8+ major = @MAJOR@,
9+ middle = @MIDDLE@,
10+ minor = @MINOR@,
11+
12+ variety = B_APPV_FINAL,
13+ internal = 0,
14+
15+ short_info = "VIM Editor",
16+ long_info = "VI Improved Editor by Bram Moolenaar et al."
17+};
18+
19+resource app_flags B_MULTIPLE_LAUNCH;
20+
21+resource file_types message {
22+ "types" = "text",
23+ "types" = "text/plain",
24+ "types" = "text/x-source-code",
25+ "types" = "text/x-patch",
26+ "types" = "text/html",
27+ "types" = "text/xml",
28+ "types" = "text/x-makefile",
29+ "types" = "text/x-jamfile"
30+};
31+
32+resource vector_icon {
33+ $"6E636966050501020006023B8CFD3CB8E4BF59B63E2F604BACDB47A13E00FFFF"
34+ $"FFFF909DA702000603BAF8BA3CE3F6BF8EB9BDA8484BC75C4AEA1200C1C7CC79"
35+ $"D9E0E5FFC1C7CC020006020000003DC000C000000000004C000049FFFF00B3FF"
36+ $"B3FF026C52020006023BD04F3BD04FBED4133ED4134B6000462FB00053AB53FF"
37+ $"007F00060618FFFCFFFF63FF282528252725262726262627262B262B262C282D"
38+ $"272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA2659315ABA26595E"
39+ $"2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A254A254925482748"
40+ $"264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D3E2B3E2C3E2B3E"
41+ $"273E273E263C253D253C250618FFFCFFFF63FF28252825272526272626262726"
42+ $"2B262B262C282D272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA26"
43+ $"59315ABA26595E2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A25"
44+ $"4A254925482748264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D"
45+ $"3E2B3E2C3E2B3E273E273E263C253D253C250A08BEA359BE3D593C5A415AC03B"
46+ $"59BFD559434C404C06218A88888888C83E3F02484CC1D359C16D445A49C36B59"
47+ $"C305C3CA50C5C8C50359C49D4C5A51C69B59C635C6FA50C8F8C83359C7CD545A"
48+ $"59C9CB59C965CA6B4DCA6B4DCA804C5A4C584C584C574CC86D4DC8D34DC86D4D"
49+ $"C73B524C534C524C504C504C4F4CC53D4DC5A34DC53D4DC40B4B4C0608EBECC0"
50+ $"B64AC0B64AC11C4AC13349C14848C0F847C15E47C0F847C092C01648C02C47C0"
51+ $"1648C00149C0504ABFEA4AC0504A0A04405E5E40402222400A0A000105180015"
52+ $"01178600040A0001051815FF01178400040A030105000A0401051001157C0004"
53+ $"0A000100381D1F001501178600040A000100381D1F15FF01178300040A010101"
54+ $"201D1F0A020101301D1F01157E00040A0003020304381D1F15FF01178400040A"
55+ $"0203020304281D1F15FF"
56+};
57+
58+resource(1, "builtin-tools") #'PNG ' array {
59+ $"89504E470D0A1A0A0000000D494844520000022E0000001208030000004BB3A5"
60+ $"1200000300504C5445000000800000008000808000000080800080008080C0C0"
61+ $"C0C0DCC0A6CAF0402000602000802000A02000C02000E0200000400020400040"
62+ $"4000604000804000A04000C04000E04000006000206000406000606000806000"
63+ $"A06000C06000E06000008000208000408000608000808000A08000C08000E080"
64+ $"0000A00020A00040A00060A00080A000A0A000C0A000E0A00000C00020C00040"
65+ $"C00060C00080C000A0C000C0C000E0C00000E00020E00040E00060E00080E000"
66+ $"A0E000C0E000E0E000000040200040400040600040800040A00040C00040E000"
67+ $"40002040202040402040602040802040A02040C02040E0204000404020404040"
68+ $"4040604040804040A04040C04040E04040006040206040406040606040806040"
69+ $"A06040C06040E06040008040208040408040608040808040A08040C08040E080"
70+ $"4000A04020A04040A04060A04080A040A0A040C0A040E0A04000C04020C04040"
71+ $"C04060C04080C040A0C040C0C040E0C04000E04020E04040E04060E04080E040"
72+ $"A0E040C0E040E0E040000080200080400080600080800080A00080C00080E000"
73+ $"80002080202080402080602080802080A02080C02080E0208000408020408040"
74+ $"4080604080804080A04080C04080E04080006080206080406080606080806080"
75+ $"A06080C06080E06080008080208080408080608080808080A08080C08080E080"
76+ $"8000A08020A08040A08060A08080A080A0A080C0A080E0A08000C08020C08040"
77+ $"C08060C08080C080A0C080C0C080E0C08000E08020E08040E08060E08080E080"
78+ $"A0E080C0E080E0E0800000C02000C04000C06000C08000C0A000C0C000C0E000"
79+ $"C00020C02020C04020C06020C08020C0A020C0C020C0E020C00040C02040C040"
80+ $"40C06040C08040C0A040C0C040C0E040C00060C02060C04060C06060C08060C0"
81+ $"A060C0C060C0E060C00080C02080C04080C06080C08080C0A080C0C080C0E080"
82+ $"C000A0C020A0C040A0C060A0C080A0C0A0A0C0C0A0C0E0A0C000C0C020C0C040"
83+ $"C0C060C0C080C0C0A0C0C0FFFBF0A0A0A4808080FF000000FF00FFFF000000FF"
84+ $"FF00FF00FFFFFFFFFF58D234440000000874524E53FFFFFFFFFFFFFF00DE83BD"
85+ $"59000000097048597300000B1200000B1201D2DD7EFC0000070D494441546881"
86+ $"DD994B6E23390C86695880F6BDCD19BCCD3AD7CA7DB4CD197C965EE7044619D0"
87+ $"F0299192AA5C9907D018762776D12A3DA8AF7E520E64B382FFB792FF004BCD4E"
88+ $"DF02C1DC0717347779C3FFDB8D5F43A3705900FE8838FCDB868119C3F3E32EDA"
89+ $"BB5A1897CA916A1B566CA49DED7865B2E3E930FC6397A9AAEDE232F10409EA37"
90+ $"5B851A70793C020BB70C1B8CB4C436057EFFF6BCACE0BD0CAF75159D21567B6D"
91+ $"B2BB9EC73AF7E89C21013E3EF03F1A4CD339BDA77E390523594BE549EA7E55DD"
92+ $"E8793B68FEF332D4D3BD72BFE1B2D68D19171A87861F37ADB4163A3FEB87E6A7"
93+ $"06411B06146E37D8B60D6E9E176C121A212D81976930BAE5C231A657895D5B80"
94+ $"8735AE6BD5068729057FCC318FB5183DC682BB8924AC4D5AB456557F9771D647"
95+ $"066E0B378A6491FD65381017DDB2793BD2674A9F64E14950CF67DFD8941D3D5D"
96+ $"37DA62B1BB1B9ADFE4452BA3B3C41649D58BE6B77E58065C36B3EEC26C856D7A"
97+ $"3E2A332ECFA73E3BBD53EE955F5BB8F939B3F85B749D2DDA003A0A5E546B392D"
98+ $"6CE11962C1FD4412D6664C01702B990E4FA5C6591F18F4CDF1913475B1597975"
99+ $"498A4BB3B632E7EA7B5F5C2E620A83C4C0ED2AFB7BBD4268157191693455129A"
100+ $"BF6BD329C265918F461496EAF23219E5E7B3549977BF036FE1DFEDE9ACB2E7FB"
101+ $"819736D9B76152F8C7B6B95E5AE06DA99327C682FBF9289E04B46B306D2519AB"
102+ $"6480361D9A8ABDC0F291ABFE8271F916D9A849D505432FEA42D3E4965E5D1C2E"
103+ $"B486CE463247C025E54159436982B898395C26759970A9BE9386CB948FC64473"
104+ $"A676912AC06DFA53E5A51753C0A4D08F17730E6A734C81F7C94853BC3C8AF44B"
105+ $"79A9974B5C18EE6573795C86041E49405ACAE68CC72168AEF9FAF686BF4D5DDC"
106+ $"74CB98902AB8D7EA70112E0ACE076B1776DEFB7EA4BBE1B2509784893799BCA4"
107+ $"76ED71416971BBCEEA623DF1B21197DB50D2840662853E2A2E19E95C2C6883BA"
108+ $"A4B6DB63EDB23A19C536BCBF5E5ECAF329F2D22704C221DEE670113016C540DD"
109+ $"C18576B7B0BA202CC2CB85B410F9B085F1D5E3228F00F45880CC221891A04EA1"
110+ $"E55B7F181705081B15F12C71A9DC41FBC454489B414F4685D0D80A4E3F3E1789"
111+ $"9FFA1D7521509ABCC89BF439E2E28B9BA82E0D97F844AD6A17E969D09F1E3448"
112+ $"699EA2B0100FC9793C44E7E1B02DA50BA6A3E621655179E9B858FD32D1E11C75"
113+ $"74B567B0CB0AC55B4EA37425106AFDEC1D35F2A1692DF24224E8BBB221840117"
114+ $"038871F9DEC385122A83AF2E914B6B06E06B17C605E70F776760B8B45A32292E"
115+ $"76D01E710907F0E1F4B4A72ECEE3594D417103762C223D688A4B5497391F9CF0"
116+ $"80E1622393B290C0607CF2A1BA4CB84CAE6E8A4B257929242EF4CEE078F48599"
117+ $"E712F900417117976DC3021AA9907F084703E885BA48426D5955E432F78B880B"
118+ $"DD8AFEFB7BB32B182EDD64844299A74CB8D0C1903ED13594A1D47DA12E34B8B7"
119+ $"D223E28F0249C5A5056DA52EAEA7AF2FEEE88C87BEA42364DCC83D40D97059D5"
120+ $"2E7BC9A8F62D51EBC9A8B2C0DB01C9E8E80BEB7213F880F032E18240081C1D17"
121+ $"03E8585D72FE91BA6805E6707987515D4CE9932F598637EECCC7B8F8134D5DA9"
122+ $"8BC7E5F1F86A56DCF13AE022EAD282C6B844010CDC15DAFD331EE5C51FA5537D"
123+ $"3C727E704A7A3ED9B53A198DA56E0FEB949F7AA92B0072F552A463CA8C7D6156"
124+ $"BB0C7CF00E1EE0029BA41E4D47C8E9E6D5E5089755ED62CDD6B80CF21270F9F5"
125+ $"ABE3C2E7202970F3E8695B2CEAD28AD81D7571C9E8FEF5B5C4C59BA94B0B9AE0"
126+ $"1204D075F478281CAF3DB9A5A3968D522DC8CB0379C1B4C4BCACBF77C9FE201D"
127+ $"4F46D666719016846C9D720CF234C8C968E443867BDBC1C578E927A306D0212E"
128+ $"35984D09DCC54B5CDEF770E95FB3B883B439CCD3BE7751DD61D3A3D89EBAECE0"
129+ $"32ABCB58EA46010C1D8D70EC7A7AADDB78C1D9154E095E5D2EFAAA87AAF990CC"
130+ $"59B9D95E1BE0546747EA6CDFBB381AD2E4E158D02ADFDE022F0E17C9A81E5703"
131+ $"E8B07681F12EF9C85D2C71C130BAEF78F670B1435083A37DABDB1D599391952F"
132+ $"14BA78F0E1DD7500ADE73CE1A20F00DE2B995652909F22DC7B2784C2394FE6BF"
133+ $"01683A0237985717AC5D742297A02E1185D196B8F0BBFE374DB730A561F6F458"
134+ $"445E3C2E8155C65501A24612D60997D55DAE3399EF1A9769C7965B2867A0E2E2"
135+ $"A31E7759F41835B4E9C7A71120F0EA02E51017BA45FF3253665C5C19AB70BCF6"
136+ $"642D5B2423411F8C6B97868B8D9E5BED326AB84637E032B5E94A648AED17C634"
137+ $"CC1E178B7D5C661302A891ECBE4E07E6591FD81A9781B3A5A339E749F94BFF32"
138+ $"75AED701A01D71099DF832450BF94900492EBA3109273CD9FE02C03909FA6024"
139+ $"912D194D339C0EC9D6CCAD7AD166F2C485312E93671150B617B88C8D86DC731A"
140+ $"1767E7EEF90FEC3599BB77B416E3EAE7689CF114DBE3E262B898CB34FECE845E"
141+ $"4CFAEF79764372DC201F65AC97B792C14FE6F387DBB4F83918273C6E9B866FD9"
142+ $"FF17F6CF36F92F1B9E631E8B8F3FBC0000000049454E44AE426082"
143+};
diff -r 619eb9bc3249 -r 22f0dda71638 src/os_unix.c
--- a/src/os_unix.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/os_unix.c Wed Feb 26 16:30:04 2020 +0100
@@ -2151,7 +2151,8 @@
21512151 if (get_x11_windis() == OK)
21522152 type = 1;
21532153 #else
2154-# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
2154+# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
2155+ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
21552156 if (gui.in_use)
21562157 type = 1;
21572158 # endif
@@ -2184,7 +2185,7 @@
21842185 # endif
21852186 set_x11_title(title); // x11
21862187 #endif
2187-#if defined(FEAT_GUI_GTK) \
2188+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) \
21882189 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
21892190 else
21902191 gui_mch_settitle(title, icon);
@@ -4591,7 +4592,7 @@
45914592 {
45924593 SIGSET_DECL(curset)
45934594
4594-# ifdef __BEOS__
4595+# if defined(__BEOS__) && USE_THREAD_FOR_INPUT_WITH_TIMEOUT
45954596 beos_cleanup_read_thread();
45964597 # endif
45974598
diff -r 619eb9bc3249 -r 22f0dda71638 src/os_unix.h
--- a/src/os_unix.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/os_unix.h Wed Feb 26 16:30:04 2020 +0100
@@ -364,22 +364,26 @@
364364
365365 #define DFLT_ERRORFILE "errors.err"
366366
367-#ifdef VMS
368-# define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after"
369-# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
370-#else
371-# ifdef RUNTIME_GLOBAL
372-# ifdef RUNTIME_GLOBAL_AFTER
373-# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after"
374-# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER
367+#ifndef DFLT_RUNTIMEPATH
368+
369+# ifdef VMS
370+# define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after"
371+# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
372+# else
373+# ifdef RUNTIME_GLOBAL
374+# ifdef RUNTIME_GLOBAL_AFTER
375+# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after"
376+# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER
377+# else
378+# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after"
379+# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after"
380+# endif
375381 # else
376-# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after"
377-# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after"
382+# define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after"
383+# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
378384 # endif
379-# else
380-# define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after"
381-# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
382385 # endif
386+
383387 #endif
384388
385389 #ifdef VMS
diff -r 619eb9bc3249 -r 22f0dda71638 src/osdef1.h.in
--- a/src/osdef1.h.in Wed Feb 26 13:45:07 2020 +0100
+++ b/src/osdef1.h.in Wed Feb 26 16:30:04 2020 +0100
@@ -65,7 +65,7 @@
6565 # endif
6666 # endif
6767 #endif
68-#ifndef __BIONIC__ // Android's libc #defines bzero to memset.
68+#if !defined(__BIONIC__) && !defined(__HAIKU__) // Android's libc #defines bzero to memset.
6969 // used inside of FD_ZERO macro
7070 extern void bzero(void *, size_t);
7171 #endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/proto.h
--- a/src/proto.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/proto.h Wed Feb 26 16:30:04 2020 +0100
@@ -313,6 +313,9 @@
313313 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);
314314 # endif
315315 # endif
316+# ifdef FEAT_GUI_HAIKU
317+# include "gui_haiku.pro"
318+# endif
316319 # ifdef FEAT_GUI_MAC
317320 # include "gui_mac.pro"
318321 # endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/proto/gui_haiku.pro
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto/gui_haiku.pro Wed Feb 26 16:30:04 2020 +0100
@@ -0,0 +1,95 @@
1+/* gui_haiku.cc - hand crafted */
2+
3+void gui_mch_prepare(int *argc, char **argv);
4+int gui_mch_init(void);
5+int gui_mch_open(void);
6+void gui_mch_exit(int vim_exitcode);
7+int gui_mch_init_check(void);
8+void gui_mch_flush(void);
9+
10+void gui_mch_new_colors(void);
11+void gui_mch_set_bg_color(guicolor_T color);
12+void gui_mch_set_fg_color(guicolor_T color);
13+void gui_mch_set_sp_color(guicolor_T color);
14+guicolor_T gui_mch_get_rgb(guicolor_T pixel);
15+guicolor_T gui_mch_get_rgb_color(int r, int g, int b);
16+guicolor_T gui_mch_get_color(char_u *name);
17+
18+GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing);
19+void gui_mch_set_font(GuiFont font);
20+int gui_mch_init_font(char_u *font_name, int fontset);
21+void gui_mch_free_font(GuiFont font);
22+char_u *gui_mch_get_fontname(GuiFont font, char_u *name);
23+
24+void gui_mch_set_winpos(int x, int y);
25+int gui_mch_get_winpos(int *x, int *y);
26+void gui_mch_set_shellsize(int w, int h, int m_w, int m_h, int b_w, int b_h, int d);
27+void gui_mch_get_screen_dimensions(int* screen_w, int* screen_h);
28+void gui_mch_set_text_area_pos(int x, int y, int w, int h);
29+
30+void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag);
31+
32+//void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb,int val, int size, int max));
33+void gui_mch_set_scrollbar_thumb(scrollbar_T *sb, int val, int size, int max);
34+
35+void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h);
36+void gui_mch_create_scrollbar(scrollbar_T *sb, int orient);
37+void gui_mch_destroy_scrollbar(scrollbar_T *sb);
38+
39+void gui_mch_set_blinking(long waittime, long on, long off);
40+void gui_mch_stop_blink(int may_call_gui_update_cursor);
41+void gui_mch_start_blink(void);
42+
43+int gui_mch_adjust_charheight(void);
44+void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags);
45+int gui_mch_haskey(char_u *name);
46+void gui_mch_beep(void);
47+void gui_mch_flash(int msec);
48+void gui_mch_invert_rectangle(int r, int c, int nr, int nc);
49+void gui_mch_iconify(void);
50+void gui_mch_set_foreground(void);
51+void gui_mch_settitle(char_u *title, char_u *icon);
52+void gui_mch_draw_hollow_cursor(guicolor_T color);
53+void gui_mch_draw_part_cursor(int w, int h, guicolor_T color);
54+void gui_mch_update(void);
55+int gui_mch_wait_for_chars(int wtime);
56+void gui_mch_clear_block(int row1, int col1, int row2, int col2);
57+void gui_mch_clear_all(void);
58+void gui_mch_delete_lines(int row, int num_lines);
59+void gui_mch_insert_lines(int row, int num_lines);
60+
61+void gui_mch_getmouse(int *x, int *y);
62+void gui_mch_setmouse(int x, int y);
63+void gui_mch_mousehide(int hide);
64+
65+void gui_mch_enable_menu(int flag);
66+void gui_mch_set_menu_pos(int x, int y, int w, int h);
67+void gui_mch_add_menu(vimmenu_T *menu, int idx);
68+void gui_mch_add_menu_item(vimmenu_T *menu, int idx);
69+void gui_mch_destroy_menu(vimmenu_T *menu);
70+void gui_mch_menu_grey(vimmenu_T *menu, int grey);
71+void gui_mch_menu_hidden(vimmenu_T *menu, int hidden);
72+void gui_mch_draw_menubar(void);
73+void gui_mch_show_popupmenu(vimmenu_T *menu);
74+void gui_mch_toggle_tearoffs(int enable);
75+
76+void clip_mch_request_selection(Clipboard_T *cbd);
77+void clip_mch_set_selection(Clipboard_T *cbd);
78+void clip_mch_lose_selection(Clipboard_T *cbd);
79+int clip_mch_own_selection(Clipboard_T *cbd);
80+
81+char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter);
82+int gui_mch_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd);
83+
84+void im_set_position(int row, int col);
85+void im_set_active(int activate);
86+int im_get_status(void);
87+
88+void gui_mch_show_toolbar(int showit);
89+void gui_mch_set_toolbar_pos(int x, int y, int w, int h);
90+
91+void gui_mch_show_tabline(int showit);
92+void gui_mch_set_tabline_pos(int x, int y, int w, int h);
93+int gui_mch_showing_tabline(void);
94+void gui_mch_update_tabline(void);
95+void gui_mch_set_curtab(int nr);
diff -r 619eb9bc3249 -r 22f0dda71638 src/pty.c
--- a/src/pty.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/pty.c Wed Feb 26 16:30:04 2020 +0100
@@ -386,7 +386,7 @@
386386 static char PtyProto[] = "/dev/ptym/ptyXY";
387387 static char TtyProto[] = "/dev/pty/ttyXY";
388388 # else
389-# ifdef __BEOS__
389+# if defined (__BEOS__) || defined(__HAIKU__)
390390 static char PtyProto[] = "/dev/pt/XY";
391391 static char TtyProto[] = "/dev/tt/XY";
392392 # else
diff -r 619eb9bc3249 -r 22f0dda71638 src/screen.c
--- a/src/screen.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/screen.c Wed Feb 26 16:30:04 2020 +0100
@@ -2549,6 +2549,10 @@
25492549
25502550 win_new_shellsize(); // fit the windows in the new sized shell
25512551
2552+#ifdef FEAT_GUI_HAIKU
2553+ vim_lock_screen(); // be safe, put it here
2554+#endif
2555+
25522556 comp_col(); // recompute columns for shown command and ruler
25532557
25542558 /*
@@ -2799,6 +2803,10 @@
27992803 #endif
28002804 clear_TabPageIdxs();
28012805
2806+#ifdef FEAT_GUI_HAIKU
2807+ vim_unlock_screen();
2808+#endif
2809+
28022810 entered = FALSE;
28032811 --RedrawingDisabled;
28042812
@@ -3646,6 +3654,10 @@
36463654 clip_scroll_selection(-line_count);
36473655 #endif
36483656
3657+#ifdef FEAT_GUI_HAIKU
3658+ vim_lock_screen();
3659+#endif
3660+
36493661 #ifdef FEAT_GUI
36503662 // Don't update the GUI cursor here, ScreenLines[] is invalid until the
36513663 // scrolling is actually carried out.
@@ -3700,6 +3712,10 @@
37003712 }
37013713 }
37023714
3715+#ifdef FEAT_GUI_HAIKU
3716+ vim_unlock_screen();
3717+#endif
3718+
37033719 screen_stop_highlight();
37043720 windgoto(cursor_row, cursor_col);
37053721 if (clear_attr != 0)
@@ -3928,6 +3944,10 @@
39283944 }
39293945 }
39303946
3947+#ifdef FEAT_GUI_HAIKU
3948+ vim_unlock_screen();
3949+#endif
3950+
39313951 if (screen_attr != clear_attr)
39323952 screen_stop_highlight();
39333953 if (clear_attr != 0)
diff -r 619eb9bc3249 -r 22f0dda71638 src/structs.h
--- a/src/structs.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/structs.h Wed Feb 26 16:30:04 2020 +0100
@@ -3643,6 +3643,13 @@
36433643 HMENU submenu_id; // If this is submenu, add children here
36443644 HWND tearoff_handle; // hWnd of tearoff if created
36453645 #endif
3646+#if FEAT_GUI_HAIKU
3647+ BMenuItem *id; // Id of menu item
3648+ BMenu *submenu_id; // If this is submenu, add children here
3649+# ifdef FEAT_TOOLBAR
3650+ BPictureButton *button;
3651+# endif
3652+#endif
36463653 #ifdef FEAT_GUI_MAC
36473654 // MenuHandle id;
36483655 // short index; // the item index within the father menu
diff -r 619eb9bc3249 -r 22f0dda71638 src/term.c
--- a/src/term.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/term.c Wed Feb 26 16:30:04 2020 +0100
@@ -1420,6 +1420,11 @@
14201420 # define DEFAULT_TERM (char_u *)"beos-ansi"
14211421 #endif
14221422
1423+#ifdef __HAIKU__
1424+# undef DEFAULT_TERM
1425+# define DEFAULT_TERM (char_u *)"xterm"
1426+#endif
1427+
14231428 #ifndef DEFAULT_TERM
14241429 # define DEFAULT_TERM (char_u *)"dumb"
14251430 #endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/version.c
--- a/src/version.c Wed Feb 26 13:45:07 2020 +0100
+++ b/src/version.c Wed Feb 26 16:30:04 2020 +0100
@@ -739,6 +739,8 @@
739739 static int included_patches[] =
740740 { /* Add new patch number below this line */
741741 /**/
742+ 320,
743+/**/
742744 319,
743745 /**/
744746 318,
@@ -1722,6 +1724,9 @@
17221724 msg_puts(_("with X11-Athena GUI."));
17231725 # endif
17241726 # else
1727+# ifdef FEAT_GUI_HAIKU
1728+ msg_puts(_("with Haiku GUI."));
1729+# else
17251730 # ifdef FEAT_GUI_PHOTON
17261731 msg_puts(_("with Photon GUI."));
17271732 # else
@@ -1736,6 +1741,7 @@
17361741 # else
17371742 # endif
17381743 # endif
1744+# endif
17391745 # endif
17401746 # endif
17411747 # endif
diff -r 619eb9bc3249 -r 22f0dda71638 src/vim.h
--- a/src/vim.h Wed Feb 26 13:45:07 2020 +0100
+++ b/src/vim.h Wed Feb 26 16:30:04 2020 +0100
@@ -103,6 +103,7 @@
103103 #if defined(FEAT_GUI_MOTIF) \
104104 || defined(FEAT_GUI_GTK) \
105105 || defined(FEAT_GUI_ATHENA) \
106+ || defined(FEAT_GUI_HAIKU) \
106107 || defined(FEAT_GUI_MAC) \
107108 || defined(FEAT_GUI_MSWIN) \
108109 || defined(FEAT_GUI_PHOTON)
@@ -223,6 +224,11 @@
223224 # include "os_beos.h"
224225 #endif
225226
227+#ifdef __HAIKU__
228+# include "os_haiku.h"
229+# define __ARGS(x) x
230+#endif
231+
226232 #if (defined(UNIX) || defined(VMS)) \
227233 && (!defined(MACOS_X) || defined(HAVE_CONFIG_H))
228234 # include "os_unix.h" // bring lots of system header files
@@ -2075,6 +2081,9 @@
20752081 int_u format; // Vim's own special clipboard format
20762082 int_u format_raw; // Vim's raw text clipboard format
20772083 # endif
2084+# ifdef FEAT_GUI_HAIKU
2085+ // No clipboard at the moment. TODO?
2086+# endif
20782087 } Clipboard_T;
20792088 #else
20802089 typedef int Clipboard_T; // This is required for the prototypes.
@@ -2136,7 +2145,7 @@
21362145 // functions of these names. The declarations would break if the defines had
21372146 // been seen at that stage. But it must be before globals.h, where error_ga
21382147 // is declared.
2139-#if !defined(MSWIN) && !defined(FEAT_GUI_X11) \
2148+#if !defined(MSWIN) && !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_HAIKU) \
21402149 && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO)
21412150 # define mch_errmsg(str) fprintf(stderr, "%s", (str))
21422151 # define display_errors() fflush(stderr)
Show on old repository browser