diff --git a/app-editors/vim/patches/vim-8.0.1176.patchset b/app-editors/vim/patches/vim-8.0.1176.patchset new file mode 100644 index 000000000..e23056e9c --- /dev/null +++ b/app-editors/vim/patches/vim-8.0.1176.patchset @@ -0,0 +1,6960 @@ +From cffc035f69371fff65bc4c956b5191baa92e95bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zolt=C3=A1n=20Mizsei?= +Date: Fri, 21 Jul 2017 17:03:57 +0200 +Subject: Applied patchset + + +diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt +index edc12ef..56404e5 100644 +--- a/runtime/doc/eval.txt ++++ b/runtime/doc/eval.txt +@@ -8850,12 +8850,14 @@ gui_gnome Compiled with Gnome support (gui_gtk is also defined). + gui_gtk Compiled with GTK+ GUI (any version). + gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined). + gui_gtk3 Compiled with GTK+ 3 GUI (gui_gtk is also defined). ++gui_haiku Compiled with Haiku GUI. + gui_mac Compiled with Macintosh GUI. + gui_motif Compiled with Motif GUI. + gui_photon Compiled with Photon GUI. + gui_running Vim is running in the GUI, or it will start soon. + gui_win32 Compiled with MS Windows Win32 GUI. + gui_win32s idem, and Win32s system being used (Windows 3.1) ++haiku Haiku version of Vim. + hangul_input Compiled with Hangul input support. |hangul| + iconv Can use iconv() for conversion. + insert_expand Compiled with support for CTRL-X expansion commands in +diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt +index df02c5c..99d90ed 100644 +--- a/runtime/doc/gui.txt ++++ b/runtime/doc/gui.txt +@@ -101,6 +101,7 @@ Recommended place for your personal GUI initializations: + or $VIM/_gvimrc + Amiga s:.gvimrc, home:.gvimrc, home:vimfiles:gvimrc + or $VIM/.gvimrc ++ Haiku $HOME/config/settings/vim/gvimrc + + The personal initialization files are searched in the order specified above + and only the first one that is found is read. +diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt +index 2be3ced..a687a9f 100644 +--- a/runtime/doc/help.txt ++++ b/runtime/doc/help.txt +@@ -192,6 +192,7 @@ Remarks about specific systems ~ + |os_os2.txt| OS/2 + |os_qnx.txt| QNX + |os_risc.txt| RISC-OS ++|os_haiku.txt| Haiku + |os_unix.txt| Unix + |os_vms.txt| VMS + |os_win32.txt| MS-Windows 95/98/NT +diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt +index 56697d5..5cc2dc2 100644 +--- a/runtime/doc/options.txt ++++ b/runtime/doc/options.txt +@@ -3875,7 +3875,7 @@ A jump table for the options with a short description can be found at |Q_op|. + 'guitablabel' can be used to change the text in the labels. + When 'e' is missing a non-GUI tab pages line may be used. + The GUI tabs are only supported on some systems, currently +- GTK, Motif, Mac OS/X and MS-Windows. ++ GTK, Motif, Mac OS/X, Haiku and MS-Windows. + *'go-f'* + 'f' Foreground: Don't use fork() to detach the GUI from the shell + where it was started. Use this for programs that wait for the +@@ -6257,7 +6257,12 @@ A jump table for the options with a short description can be found at |Q_op|. + $VIM/vimfiles, + $VIMRUNTIME, + $VIM/vimfiles/after, +- sys$login:vimfiles/after") ++ sys$login:vimfiles/after" ++ Haiku: "$BE_USER_SETTINGS/vim, ++ $VIM/vimfiles, ++ $VIMRUNTIME, ++ $VIM/vimfiles/after, ++ $BE_USER_SETTINGS/vim/after") + global + {not in Vi} + This is a list of directories which will be searched for runtime +@@ -7715,6 +7720,7 @@ A jump table for the options with a short description can be found at |Q_op|. + on MiNT: "vt52" + on MS-DOS: "pcterm" + on OS/2: "os2ansi" ++ on Haiku: "xterm" + on Unix: "ansi" + on VMS: "ansi" + on Win 32: "win32") +diff --git a/runtime/doc/os_haiku.txt b/runtime/doc/os_haiku.txt +new file mode 100644 +index 0000000..ebcb247 +--- /dev/null ++++ b/runtime/doc/os_haiku.txt +@@ -0,0 +1,223 @@ ++*os_haiku.txt* For Vim version 7.4. Last change: 2013 Sep 12 ++ ++ ++ VIM REFERENCE MANUAL by Bram Moolenaar ++ ++ *Haiku* ++ ++This file contains the particularities for the Haiku version of Vim. For ++matters not discussed in this file, Vim behaves very much like the Unix ++|os_unix.txt| version. ++ ++ 1. General |haiku-general| ++ 2. Compiling Vim |haiku-compiling| ++ 3. The Haiku GUI |haiku-gui| ++ 4. The $VIM directory |haiku-vimdir| ++ 5. The $BE_USER_SETTINGS ++ directory |haiku-user-settings-dir| ++ 6. Drag & Drop |haiku-dragndrop| ++ 7. Single Launch vs. Multiple ++ Launch |haiku-launch| ++ 8. Fonts |haiku-fonts| ++ 9. The meta key modifier |haiku-meta| ++10. Mouse key mappings |haiku-mouse| ++11. Color names |haiku-colors| ++12. Credits |haiku-support-credits| ++13. Bugs & things To Do |haiku-bugs| ++ ++ ++1. General *haiku-general* ++ ++The default syntax highlighting mostly works with different foreground colors ++to highlight items. This works best if you set your Terminal window to a ++darkish background and light letters. Some middle-grey background (for ++instance (r,g,b)=(168,168,168)) with black letters also works nicely. ++ ++ ++2. Compiling Vim *haiku-compiling* ++ ++Vim can be compiled using the standard configure/make approach. Running ++./configure without any arguments or passing --enable-gui=haiku, will compile ++vim with the Haiku GUI support. Run ./configure --help , to find out other ++features you can enable/disable. ++ ++Now you should use "make" to compile Vim, then "make install" to install it. ++For seamless integration into the Haiku the GUI-less vim binary should be ++additionally installed over the GUI version. Typical build commands are: > ++ ++ ./configure --prefix=`finddir B_COMMON_DIRECTORY` \ ++ --datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \ ++ --mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \ ++ make clean ++ make install ++ ++ ./configure --prefix=`finddir B_COMMON_DIRECTORY` \ ++ --datarootdir=`finddir B_COMMON_DATA_DIRECTORY` \ ++ --mandir=`finddir B_COMMON_DOCUMENTATION_DIRECTORY`/man \ ++ --disable-gui ++ make clean ++ make install ++ ++ ++3. The Haiku GUI *haiku-gui* ++ ++Normally Vim starts with the GUI if you start it as gvim or vim -g. The vim ++version with GUI tries to determine if it was started from the Tracker instead ++of the Terminal, and if so, use the GUI anyway. However, the current detection ++scheme is fooled if you use the command "vim - ++ ++ :version ++ ++The normal value is /boot/common/data/vim. If you don't like it you can ++set the VIM environment variable to override this, or set 'helpfile' in your ++.vimrc: > ++ ++ :if version >= 500 ++ : set helpfile=~/vim/vim74/doc/help.txt ++ : syntax on ++ :endif ++ ++ ++5. The $USER_SETTINGS_DIR directory *haiku-user-settings-dir* ++ ++$USER_SETTINGS_DIR is the symbolic name for the place where Haiku ++configuration and settings files are stored. ++ ++The normal value is /boot/home/config/settings. ++ ++ ++6. Drag & Drop *haiku-dragndrop* ++ ++You can drop files and directories on either the Vim icon (starts a new Vim ++session, unless you use the File Types application to set Vim to be "Single ++Launch") or on the Vim window (starts editing the files). Dropping a folder ++sets Vim's current working directory. |:cd| |:pwd| If you drop files or ++folders with either SHIFT key pressed, Vim changes directory to the folder ++that contains the first item dropped. When starting Vim, there is no need to ++press shift: Vim behaves as if you do. ++ ++Files dropped set the current argument list. |argument-list| ++ ++ ++7. Single Launch vs. Multiple Launch *haiku-launch* ++ ++As distributed Vim's Application Flags (as seen in the FileTypes preference) ++are set to Multiple Launch. If you prefer, you can set them to Single Launch ++instead. Attempts to start a second copy of Vim will cause the first Vim to ++open the files instead. This works from the Tracker but also from the command ++line. In the latter case, non-file (option) arguments are not supported. ++Another drawback of the Single Launch is silent ignore of "Open With ..." ++requests by vim instance that running as non-GUI application even GUI support ++was compiled in. Vim instance running with GUI has no such problems. ++ ++NB: Only the GUI version has a BApplication (and hence Application Flags). ++This section does not apply to the GUI-less version, should you compile one. ++ ++ ++8. Fonts *haiku-fonts* ++ ++Set fonts with > ++ ++ :set guifont=DejaVu_Sans_Mono/Book/12 ++ ++where the first part is the font family, the second part the style, and the ++third part the size. You can use underscores instead of spaces in family and ++style. ++ ++Best results are obtained with monospaced fonts. Vim attempts to use all ++fonts in B_FIXED_SPACING mode but apparently this does not work for ++proportional fonts (despite what the BeBook says). ++ ++To verify which encodings are supported by the current font give the > ++ ++ :digraphs ++ ++command, which lists a bunch of characters with their ISO Latin 1 encoding. ++If, for instance, there are "box" characters among them, or the last character ++isn't a dotted-y, then for this font the encoding does not work. ++ ++If the font you specify is unavailable, you get the system fixed font. ++ ++GUI Font Selection Dialog is available at giving the > ++ ++ :set guifont=* ++ ++command. ++ ++ ++9. The meta key modifier *haiku-meta* ++ ++The META key modifier is obtained by the left or right OPTION keys. This is ++because the ALT (aka COMMAND) keys are not passed to applications. ++ ++ ++10. Mouse key mappings *haiku-mouse* ++ ++Vim calls the various mouse buttons LeftMouse, MiddleMouse and RightMouse. If ++you use the default Mouse preference settings these names indeed correspond to ++reality. Vim uses this mapping: ++ ++ Button 1 -> LeftMouse, ++ Button 2 -> RightMouse, ++ Button 3 -> MiddleMouse. ++ ++If your mouse has fewer than 3 buttons you can provide your own mapping from ++mouse clicks with modifier(s) to other mouse buttons. See the file ++$VIM/macros/swapmous.vim for an example. |gui-mouse-mapping| ++ ++ ++11. Color names *haiku-colors* ++ ++Vim has a number of color names built-in. Additional names are read from the ++file $VIMRUNTIME/rgb.txt, if present. This file is basically the color ++database from X. Names used from this file are cached for efficiency. ++ ++ ++12. GUI Toolbar Images *haiku-toolbar-images* ++ ++Alternative set of toolbar images should be the PNG image of any height you ++like. Image width is calculated to contain at least 32 buttons in one-row ++cells. ++The image should be stored under the name $VIRUNTIME/bitmaps/builtin-tools.png ++More info about the buttons assignment are at |builtin-tools|. ++ ++ ++13. Credits *haiku-support-credits* ++ ++Haiku port is based on work done for BeOS version by many people ++ - BeBox GUI support Copyright 1998 by Olaf Seibert; ++ - Ported to R4 by Richard Offer Jul 99; ++ - Those who contributed, not listed above but not forgotten; ++ - Haiku support by Siarzhuk Zharski Apr-Mai 2009. ++ ++Thank you, all! ++ ++ ++13. Bugs & things To Do *haiku-bugs* ++ ++The port is under development now and far away from the perfect state. Bug ++reports, patches and wishes are welcome. ++ ++ ++ -Siarzhuk Zharski ++ ++ ++ vim:tw=78:ts=8:ft=help:norl: +diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt +index 0ea6ea2..da21a1f 100644 +--- a/runtime/doc/starting.txt ++++ b/runtime/doc/starting.txt +@@ -798,6 +798,7 @@ accordingly. Vim proceeds in this order: + or $VIM/_vimrc + Amiga s:.vimrc, home:.vimrc, home:vimfiles:vimrc + or $VIM/.vimrc ++ Haiku $HOME/config/settings/vim/vimrc + + The files are searched in the order specified above and only the first + one that is found is read. +@@ -844,6 +845,7 @@ accordingly. Vim proceeds in this order: + "$HOME/_vimrc" (for MS-DOS and Win32) (*) + "$HOME/vimfiles/vimrc" (for MS-DOS and Win32) (*) + "$VIM/_vimrc" (for MS-DOS and Win32) (*) ++ "$HOME/config/settings/vim/vimrc" (for Haiku) (*) + Note: For Unix, OS/2 and Amiga, when ".vimrc" does not exist, + "_vimrc" is also tried, in case an MS-DOS compatible file + system is used. For MS-DOS and Win32 ".vimrc" is checked +@@ -955,6 +957,7 @@ sessions. Put it in a place so that it will be found by 3b: + ~/.vimrc (Unix and OS/2) + s:.vimrc (Amiga) + $VIM\_vimrc (MS-DOS and Win32) ++ ~/config/settings/vim/vimrc (Haiku) + Note that creating a vimrc file will cause the 'compatible' option to be off + by default. See |compatible-default|. + +diff --git a/runtime/doc/tags b/runtime/doc/tags +index 1099b81..6a08ccc 100644 +--- a/runtime/doc/tags ++++ b/runtime/doc/tags +@@ -4619,6 +4619,7 @@ GetLatestVimScripts-copyright pi_getscript.txt /*GetLatestVimScripts-copyright* + GetLatestVimScripts_dat pi_getscript.txt /*GetLatestVimScripts_dat* + Gnome gui_x11.txt /*Gnome* + H motion.txt /*H* ++Haiku os_haiku.txt /*Haiku* + I insert.txt /*I* + ICCF uganda.txt /*ICCF* + IM-server mbyte.txt /*IM-server* +@@ -6699,6 +6700,20 @@ g~ change.txt /*g~* + g~g~ change.txt /*g~g~* + g~~ change.txt /*g~~* + h motion.txt /*h* ++haiku-bugs os_haiku.txt /*haiku-bugs* ++haiku-colors os_haiku.txt /*haiku-colors* ++haiku-compiling os_haiku.txt /*haiku-compiling* ++haiku-dragndrop os_haiku.txt /*haiku-dragndrop* ++haiku-fonts os_haiku.txt /*haiku-fonts* ++haiku-general os_haiku.txt /*haiku-general* ++haiku-gui os_haiku.txt /*haiku-gui* ++haiku-launch os_haiku.txt /*haiku-launch* ++haiku-meta os_haiku.txt /*haiku-meta* ++haiku-mouse os_haiku.txt /*haiku-mouse* ++haiku-support-credits os_haiku.txt /*haiku-support-credits* ++haiku-toolbar-images os_haiku.txt /*haiku-toolbar-images* ++haiku-user-settings-dir os_haiku.txt /*haiku-user-settings-dir* ++haiku-vimdir os_haiku.txt /*haiku-vimdir* + hangul hangulin.txt /*hangul* + hangulin.txt hangulin.txt /*hangulin.txt* + has() eval.txt /*has()* +@@ -7810,6 +7825,7 @@ os_390.txt os_390.txt /*os_390.txt* + os_amiga.txt os_amiga.txt /*os_amiga.txt* + os_beos.txt os_beos.txt /*os_beos.txt* + os_dos.txt os_dos.txt /*os_dos.txt* ++os_haiku.txt os_haiku.txt /*os_haiku.txt* + os_mac.txt os_mac.txt /*os_mac.txt* + os_mint.txt os_mint.txt /*os_mint.txt* + os_msdos.txt os_msdos.txt /*os_msdos.txt* +diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt +index 9a4981f..7f3e415 100644 +--- a/runtime/doc/vi_diff.txt ++++ b/runtime/doc/vi_diff.txt +@@ -140,6 +140,7 @@ Support for different systems. + - Atari MiNT + - VMS + - BeOS ++ - Haiku + - Macintosh + - Risc OS + - IBM OS/390 +@@ -167,7 +168,7 @@ Graphical User Interface (GUI). |gui| + define your own menus. Better support for CTRL/SHIFT/ALT keys in + combination with special keys and mouse. Supported for various + platforms, such as X11 (with Motif and Athena interfaces), GTK, Win32 +- (Windows 95 and later), BeOS, Amiga and Macintosh. ++ (Windows 95 and later), Haiku, Amiga and Macintosh. + + Multiple windows and buffers. |windows.txt| + Vim can split the screen into several windows, each editing a +diff --git a/runtime/gvimrc_example.vim b/runtime/gvimrc_example.vim +index fa0f685..a7975f9 100644 +--- a/runtime/gvimrc_example.vim ++++ b/runtime/gvimrc_example.vim +@@ -10,6 +10,7 @@ + " for Amiga: s:.gvimrc + " for MS-DOS and Win32: $VIM\_gvimrc + " for OpenVMS: sys$login:.gvimrc ++" for Haiku OS: ~/config/settings/vim/gvimrc + + " Make external commands work through a pipe instead of a pseudo-tty + "set noguipty +diff --git a/runtime/lang/menu_pl.utf-8.vim b/runtime/lang/menu_pl.utf-8.vim +new file mode 100644 +index 0000000..a746df2 +--- /dev/null ++++ b/runtime/lang/menu_pl.utf-8.vim +@@ -0,0 +1,3 @@ ++" Menu Translations: Polish ++ ++source :p:h/menu_pl_pl.utf-8.vim +diff --git a/runtime/vimrc_example.vim b/runtime/vimrc_example.vim +index a68ebe5..10a6b4a 100644 +--- a/runtime/vimrc_example.vim ++++ b/runtime/vimrc_example.vim +@@ -8,6 +8,7 @@ + " for Amiga: s:.vimrc + " for MS-DOS and Win32: $VIM\_vimrc + " for OpenVMS: sys$login:.vimrc ++" for Haiku OS: ~/config/settings/vim/vimrc + + " When started as "evim", evim.vim will already have done these settings. + if v:progname =~? "evim" +diff --git a/src/Makefile b/src/Makefile +index 06204bd..8a5f726 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -1373,6 +1373,23 @@ CARBONGUI_BUNDLE = gui_bundle + APPDIR = $(VIMNAME).app + CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET) + ++### Haiku GUI ++HAIKUGUI_SRC = gui.c gui_haiku.cc ++HAIKUGUI_OBJ = objects/gui.o objects/gui_haiku.o ++HAIKUGUI_DEFS = -DFEAT_GUI_HAIKU ++HAIKUGUI_IPATH = ++HAIKUGUI_LIBS_DIR = ++HAIKUGUI_LIBS1 = -lbe -lroot -ltracker -ltranslation ++ifeq ($(strip $(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))), 5) ++HAIKUGUI_LIBS1 += -lsupc++ -lstdc++ ++endif ++HAIKUGUI_LIBS2 = ++HAIKUGUI_INSTALL = install_normal install_haiku_extra ++HAIKUGUI_TARGETS = installglinks_haiku ++HAIKUGUI_MAN_TARGETS = ++HAIKUGUI_TESTTARGET = gui ++HAIKUGUI_BUNDLE = ++ + # All GUI files + ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c + ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w32.pro gui_photon.pro +@@ -3090,6 +3107,9 @@ objects/gui_gtk_gresources.o: auto/gui_gtk_gresources.c + objects/gui_gtk_x11.o: gui_gtk_x11.c + $(CCC) -o $@ gui_gtk_x11.c + ++objects/gui_haiku.o: gui_haiku.cc ++ $(CCC) -o $@ gui_haiku.cc ++ + objects/gui_motif.o: gui_motif.c + $(CCC) -o $@ gui_motif.c + +@@ -3213,6 +3233,9 @@ objects/option.o: option.c + objects/os_beos.o: os_beos.c + $(CCC) -o $@ os_beos.c + ++objects/os_haiku.rsrc: os_haiku.rdef ++ cat $< | $(CCC) -E - | grep -v '^#' | rc -o "$@" - ++ + objects/os_qnx.o: os_qnx.c + $(CCC) -o $@ os_qnx.c + +@@ -3415,6 +3438,63 @@ $(APPDIR)/Contents: + + + ############################################################################### ++### ++### Haiku installation ++### ++### This rule: ++### - add resources to already installed vim binary to avoid stripping ++### them during install; ++### - copy rgb.txt to runtime directory; ++### - update system MIME database with info about vim application. ++### ++install_haiku_extra: $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc ++ xres -o $(DEST_BIN)/$(VIMTARGET) objects/os_haiku.rsrc ++ $(INSTALL_DATA) $(SCRIPTSOURCE)/rgb.txt $(DEST_RT) ++ mimeset $(DEST_BIN)/$(VIMTARGET) ++ ++### ++### List of g*-links that should be replaced with shell script equivalents. ++### This solves the problem of them from Tracker. ++### ++HAIKU_GLINKS = $(DEST_BIN)/$(GVIMTARGET) \ ++ $(DEST_BIN)/$(GVIEWTARGET) \ ++ $(DEST_BIN)/$(GVIMDIFFTARGET) \ ++ $(DEST_BIN)/$(RGVIMTARGET) \ ++ $(DEST_BIN)/$(RGVIEWTARGET) ++### ++### This rule: ++### - Replace gvim link with copy of vim binary. ++### - Replace g*-links with shell script equivalents to solve the problem ++### of calling them from Tracker, ++### - Add icon resources to mentioned g*-link shell scripts ++### - in case gui-less vim.con executable available use it. ++### ++installglinks_haiku: $(HAIKU_GLINKS) install_haiku_extra ++ @catattr -r "BEOS:ICON" $(DEST_BIN)/$(GVIMTARGET) > ~icon.attr ++ for i in $(HAIKU_GLINKS); do \ ++ rm $$i ; \ ++ echo "#!/bin/sh" > $$i ; \ ++ case $$i in \ ++ $(DEST_BIN)/$(GVIMTARGET)) \ ++ cp $(DEST_BIN)/$(VIMTARGET) $$i ; \ ++ if [ -f $(VIMTARGET).con ] ; then \ ++ $(STRIP) $(VIMTARGET).con ; \ ++ mv $(VIMTARGET).con $(DEST_BIN)/$(VIMTARGET) ; \ ++ fi ;; \ ++ $(DEST_BIN)/$(GVIEWTARGET)) printf "%s -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \ ++ $(DEST_BIN)/$(GVIMDIFFTARGET)) printf "%s -d %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \ ++ $(DEST_BIN)/$(RGVIMTARGET)) printf "%s -Z %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \ ++ $(DEST_BIN)/$(RGVIEWTARGET)) printf "%s -Z -R %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \ ++ *) printf "%s %c%c" $(GVIMTARGET) '$$' '*' >> $$i;; \ ++ esac ; \ ++ chmod $(BINMOD) $$i ; \ ++ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $$i ; \ ++ done ++ addattr -f ~icon.attr -t \'VICN\' BEOS:ICON $(DEST_BIN)/$(VIMNAME)tutor ++ @rm ~icon.attr ++ ++############################################################################### ++ + ### (automatically generated by 'make depend') + ### Dependencies: + objects/arabic.o: arabic.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \ +diff --git a/src/configure.ac b/src/configure.ac +index 76714b1..d7bcd38 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -118,6 +118,12 @@ case `uname` in + *) BEOS=no; AC_MSG_RESULT(no);; + esac + ++AC_MSG_CHECKING(for Haiku) ++case `uname` in ++ Haiku) HAIKU=yes; AC_MSG_RESULT(yes);; ++ *) HAIKU=no; AC_MSG_RESULT(no);; ++esac ++ + dnl If QNX is found, assume we don't want to use Xphoton + dnl unless it was specifically asked for (--with-x) + AC_MSG_CHECKING(for QNX) +@@ -1987,7 +1993,11 @@ fi + + if test "$enable_channel" = "yes"; then + dnl On Solaris we need the socket and nsl library. +- AC_CHECK_LIB(socket, socket) ++ if test "x$HAIKU" = "xyes"; then ++ AC_CHECK_LIB(network, socket) ++ else ++ AC_CHECK_LIB(socket, socket) ++ fi + AC_CHECK_LIB(nsl, gethostbyname) + AC_MSG_CHECKING(whether compiling with process communication is possible) + AC_TRY_LINK([ +@@ -2224,11 +2234,11 @@ else + fi + fi + +-test "x$with_x" = xno -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no ++test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no + + AC_MSG_CHECKING(--enable-gui argument) + AC_ARG_ENABLE(gui, +- [ --enable-gui[=OPTS] X11 GUI. [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto") ++ [ --enable-gui[=OPTS] X11 GUI. [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/haiku/photon/carbon]], , enable_gui="auto") + + dnl Canonicalize the --enable-gui= argument so that it can be easily compared. + dnl Do not use character classes for portability with old tools. +@@ -2243,10 +2253,23 @@ SKIP_MOTIF=YES + SKIP_ATHENA=YES + SKIP_NEXTAW=YES + SKIP_PHOTON=YES ++SKIP_HAIKU=YES + SKIP_CARBON=YES + GUITYPE=NONE + +-if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then ++if test "x$HAIKU" = "xyes"; then ++ SKIP_HAIKU= ++ case "$enable_gui_canon" in ++ no) AC_MSG_RESULT(no GUI support) ++ SKIP_HAIKU=YES ;; ++ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;; ++ auto) AC_MSG_RESULT(auto - automatic GUI support) ;; ++ haiku) AC_MSG_RESULT(Haiku GUI support) ;; ++ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported]) ++ SKIP_HAIKU=YES ;; ++ esac ++ ++elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then + SKIP_PHOTON= + case "$enable_gui_canon" in + no) AC_MSG_RESULT(no GUI support) +@@ -2410,6 +2433,7 @@ if test "x$MACOSX" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then + SKIP_ATHENA=YES; + SKIP_NEXTAW=YES; + SKIP_PHOTON=YES; ++ SKIP_HAIKU=YES; + SKIP_CARBON=YES + fi + +@@ -3025,6 +3049,11 @@ if test "x$GUITYPE:$enable_fontset" = "xGTK:yes"; then + enable_fontset="no" + fi + ++dnl There is no test for the Haiku GUI, if it's selected it's used ++if test -z "$SKIP_HAIKU"; then ++ GUITYPE=HAIKUGUI ++fi ++ + if test -z "$SKIP_PHOTON"; then + GUITYPE=PHOTONGUI + fi +diff --git a/src/evalfunc.c b/src/evalfunc.c +index 55d2295..d031a72 100644 +--- a/src/evalfunc.c ++++ b/src/evalfunc.c +@@ -5539,6 +5539,9 @@ f_has(typval_T *argvars, typval_T *rettv) + #ifdef __BEOS__ + "beos", + #endif ++#ifdef __HAIKU__ ++ "haiku", ++#endif + #ifdef MACOS + "mac", + #endif +@@ -5716,6 +5719,9 @@ f_has(typval_T *argvars, typval_T *rettv) + #ifdef FEAT_GUI_GNOME + "gui_gnome", + #endif ++#ifdef FEAT_GUI_HAIKU ++ "gui_haiku", ++#endif + #ifdef FEAT_GUI_MAC + "gui_mac", + #endif +diff --git a/src/ex_cmds.c b/src/ex_cmds.c +index b4351b2..2e6ce28 100644 +--- a/src/ex_cmds.c ++++ b/src/ex_cmds.c +@@ -14,6 +14,9 @@ + #include "vim.h" + #include "version.h" + ++#include ++#include ++ + #ifdef FEAT_FLOAT + # include + #endif +@@ -1837,6 +1840,8 @@ write_viminfo(char_u *file, int forceit) + int hidden = FALSE; + #endif + ++char* filenameSeparatorPos; ++ + if (no_viminfo()) + return; + +@@ -1844,6 +1849,19 @@ write_viminfo(char_u *file, int forceit) + if (fname == NULL) + return; + ++ /* Ensure that configuration folder(for viminfo) exist */ ++ filenameSeparatorPos = strrchr(fname, '/'); ++ if(filenameSeparatorPos != NULL && ++ filenameSeparatorPos - (char*)fname > 1) { ++ // > 1 because root directory always exists anyway ++ *filenameSeparatorPos = '\0'; ++ // 1020))) + # define FEAT_GUI_TABLINE +@@ -767,7 +777,8 @@ + */ + #if defined(FEAT_NORMAL) + # define FEAT_BROWSE_CMD +-# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) ++# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ ++ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + # define FEAT_BROWSE + # endif + #endif +@@ -791,6 +802,7 @@ + && defined(HAVE_X11_XPM_H)) \ + || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_PHOTON) \ ++ || defined(FEAT_GUI_HAIKU) \ + || defined(FEAT_GUI_MSWIN) \ + || defined(FEAT_GUI_MAC) + # define FEAT_CON_DIALOG +@@ -808,7 +820,8 @@ + #if defined(FEAT_GUI_DIALOG) && \ + (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ + || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \ +- || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)) ++ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))\ ++ || defined(FEAT_GUI_HAIKU) + # define FEAT_GUI_TEXTDIALOG + # ifndef ALWAYS_USE_GUI + # define FEAT_CON_DIALOG +diff --git a/src/gui.c b/src/gui.c +index fe91062..3e96a7d 100644 +--- a/src/gui.c ++++ b/src/gui.c +@@ -424,7 +424,7 @@ gui_init_check(void) + gui.menu_width = 0; + # endif + #endif +-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) ++#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)) + gui.toolbar_height = 0; + #endif + #if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF) +@@ -1355,10 +1355,10 @@ gui_position_components(int total_width UNUSED) + text_area_y += gui.tabline_height; + #endif + +-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) ++#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)) + if (vim_strchr(p_go, GO_TOOLBAR) != NULL) + { +-# ifdef FEAT_GUI_ATHENA ++# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU) + gui_mch_set_toolbar_pos(0, text_area_y, + gui.menu_width, gui.toolbar_height); + # endif +@@ -1366,6 +1366,13 @@ gui_position_components(int total_width UNUSED) + } + #endif + ++# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_HAIKU)) ++ gui_mch_set_tabline_pos(0, text_area_y, ++ gui.menu_width, gui.tabline_height); ++ if (gui_has_tabline()) ++ text_area_y += gui.tabline_height; ++#endif ++ + text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2; + text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2; + +@@ -1437,7 +1444,7 @@ gui_get_base_height(void) + # endif + # endif + # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ +- || defined(FEAT_GUI_MOTIF)) ++ || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU)) + if (gui_has_tabline()) + base_height += gui.tabline_height; + # endif +@@ -1480,6 +1487,10 @@ again: + new_pixel_height = 0; + busy = TRUE; + ++ #ifdef FEAT_GUI_HAIKU ++ vim_lock_screen(); ++ #endif ++ + /* Flush pending output before redrawing */ + out_flush(); + +@@ -1502,6 +1513,10 @@ again: + || gui.num_rows != Rows || gui.num_cols != Columns) + shell_resized(); + ++#ifdef FEAT_GUI_HAIKU ++ vim_unlock_screen(); ++#endif ++ + gui_update_scrollbars(TRUE); + gui_update_cursor(FALSE, TRUE); + #if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK) +@@ -4236,9 +4251,9 @@ gui_update_scrollbars( + y += gui.menu_height; + #endif + +-#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA)) ++#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)) + if (vim_strchr(p_go, GO_TOOLBAR) != NULL) +-# ifdef FEAT_GUI_ATHENA ++# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU) + y += gui.toolbar_height; + # else + # ifdef FEAT_GUI_MSWIN +@@ -4247,7 +4262,7 @@ gui_update_scrollbars( + # endif + #endif + +-#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) ++#if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)) + if (gui_has_tabline()) + y += gui.tabline_height; + #endif +@@ -4958,9 +4973,10 @@ ex_gui(exarg_T *eap) + } + + #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) \ +- || defined(FEAT_GUI_PHOTON)) && defined(FEAT_TOOLBAR)) || defined(PROTO) ++ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_HAIKU)) \ ++ && defined(FEAT_TOOLBAR)) || defined(PROTO) + /* +- * This is shared between Athena, Motif and GTK. ++ * This is shared between Athena, Haiku, Motif and GTK. + */ + static void gfp_setname(char_u *fname, void *cookie); + +diff --git a/src/gui.h b/src/gui.h +index 91b4c22..0c352ef 100644 +--- a/src/gui.h ++++ b/src/gui.h +@@ -33,6 +33,10 @@ + # include + #endif + ++#ifdef FEAT_GUI_HAIKU ++# include "gui_haiku.h" ++#endif ++ + #ifdef FEAT_GUI_MAC + # include + /*# include */ +@@ -70,7 +74,7 @@ + * GUIs that support dropping files on a running Vim. + */ + #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) \ +- || defined(FEAT_GUI_GTK) ++ || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_GTK) + # define HAVE_DROP_FILE + #endif + +@@ -197,6 +201,9 @@ typedef struct GuiScrollbar + scroll_shift is set to the number of shifts + to reduce the count. */ + #endif ++#if FEAT_GUI_HAIKU ++ VimScrollBar *id; /* Pointer to real scroll bar */ ++#endif + #ifdef FEAT_GUI_MAC + ControlHandle id; /* A handle to the scrollbar */ + #endif +@@ -410,7 +417,7 @@ typedef struct Gui + + #if defined(FEAT_GUI_TABLINE) \ + && (defined(FEAT_GUI_W32) || defined(FEAT_GUI_MOTIF) \ +- || defined(FEAT_GUI_MAC)) ++ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_HAIKU)) + int tabline_height; + #endif + +@@ -419,7 +426,7 @@ typedef struct Gui + #endif + + #if defined(FEAT_TOOLBAR) \ +- && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)) ++ && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU)) + int toolbar_height; /* height of the toolbar */ + #endif + +@@ -440,6 +447,14 @@ typedef struct Gui + guicolor_T currSpColor; /* Current special text color */ + #endif + ++#ifdef FEAT_GUI_HAIKU ++ VimApp *vimApp; ++ VimWindow *vimWindow; ++ VimFormView *vimForm; ++ VimTextAreaView *vimTextArea; ++ int vdcmp; /* Vim Direct Communication Message Port */ ++#endif ++ + #ifdef FEAT_GUI_MAC + WindowPtr VimWindow; + MenuHandle MacOSHelpMenu; /* Help menu provided by the MacOS */ +diff --git a/src/gui_haiku.cc b/src/gui_haiku.cc +new file mode 100644 +index 0000000..ef0ec7d +--- /dev/null ++++ b/src/gui_haiku.cc +@@ -0,0 +1,5292 @@ ++/* vi:set ts=8 sts=4 sw=4: ++ * ++ * VIM - Vi IMproved by Bram Moolenaar ++ * BeBox GUI support Copyright 1998 by Olaf Seibert. ++ * All Rights Reserved. ++ * ++ * Do ":help uganda" in Vim to read copying and usage conditions. ++ * Do ":help credits" in Vim to see a list of people who contributed. ++ * ++ * Based on "GUI support for the Buzzword Enhanced Operating System." ++ * ++ * Ported to R4 by Richard Offer Jul 99 ++ * ++ * Haiku support by Siarzhuk Zharski Apr-Mai 2009 ++ * ++ */ ++ ++/* ++ * Structure of the Haiku GUI code: ++ * ++ * There are 3 threads. ++ * 1. The initial thread. In gui_mch_prepare() this gets to run the ++ * BApplication message loop. But before it starts doing that, ++ * it creates thread 2 ++ * 2. The main() thread. This thread is created in gui_mch_prepare() ++ * and its purpose in life is to call main(argc, argv) again. ++ * This thread is doing the bulk of the work. ++ * 3. Sooner or later, a window is opened by the main() thread. This ++ * causes a second message loop to be created: the window thread. ++ * ++ * == alternatively === ++ * ++ * #if RUN_BAPPLICATION_IN_NEW_THREAD... ++ * ++ * 1. The initial thread. In gui_mch_prepare() this gets to spawn ++ * thread 2. After doing that, it returns to main() to do the ++ * bulk of the work, being the main() thread. ++ * 2. Runs the BApplication. ++ * 3. The window thread, just like in the first case. ++ * ++ * This second alternative is cleaner from Vim's viewpoint. However, ++ * the BeBook seems to assume everywhere that the BApplication *must* ++ * run in the initial thread. So perhaps doing otherwise is very wrong. ++ * ++ * However, from a B_SINGLE_LAUNCH viewpoint, the first is better. ++ * If Vim is marked "Single Launch" in its application resources, ++ * and a file is dropped on the Vim icon, and another Vim is already ++ * running, the file is passed on to the earlier Vim. This happens ++ * in BApplication::Run(). So we want Vim to terminate if ++ * BApplication::Run() terminates. (See the BeBook, on BApplication. ++ * However, it seems that the second copy of Vim isn't even started ++ * in this case... which is for the better since I wouldn't know how ++ * to detect this case.) ++ * ++ * Communication between these threads occurs mostly by translating ++ * BMessages that come in and posting an appropriate translation on ++ * the VDCMP (Vim Direct Communication Message Port). Therefore the ++ * actions required for keypresses and window resizes, etc, are mostly ++ * performed in the main() thread. ++ * ++ * A notable exception to this is the Draw() event. The redrawing of ++ * the window contents is performed asynchronously from the window ++ * thread. To make this work correctly, a locking protocol is used when ++ * any thread is accessing the essential variables that are used by ++ * the window thread. ++ * ++ * This locking protocol consists of locking Vim's window. This is both ++ * convenient and necessary. ++ */ ++ ++extern "C" { ++ ++#include ++#include ++#include ++ ++#include "vim.h" ++#include "globals.h" ++#include "proto.h" ++#include "version.h" ++ ++} /* extern "C" */ ++ ++/* ---------------- start of header part ---------------- */ ++ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++//#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++//#include ++//#include ++#include ++#include ++#include ++//#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++class VimApp; ++class VimFormView; ++class VimTextAreaView; ++class VimWindow; ++class VimToolbar; ++class VimTabLine; ++ ++extern key_map *keyMap; ++extern char *keyMapChars; ++ ++extern int main(int argc, char **argv); ++ ++#ifndef B_MAX_PORT_COUNT ++#define B_MAX_PORT_COUNT 255 ++#endif ++ ++/* ++ * VimApp seems comparable to the X "vimShell" ++ */ ++class VimApp: public BApplication ++{ ++ typedef BApplication Inherited; ++ public: ++ VimApp(const char *appsig); ++ ~VimApp(); ++ ++ // callbacks: ++#if 0 ++ virtual void DispatchMessage(BMessage *m, BHandler *h) ++ { ++ m->PrintToStream(); ++ Inherited::DispatchMessage(m, h); ++ } ++#endif ++ virtual void ReadyToRun(); ++ virtual void ArgvReceived(int32 argc, char **argv); ++ virtual void RefsReceived(BMessage *m); ++ virtual bool QuitRequested(); ++ virtual void MessageReceived(BMessage *m); ++ ++ static void SendRefs(BMessage *m, bool changedir); ++ ++ sem_id fFilePanelSem; ++ BFilePanel* fFilePanel; ++ BPath fBrowsedPath; ++ private: ++}; ++ ++class VimWindow: public BWindow ++{ ++ typedef BWindow Inherited; ++ public: ++ VimWindow(); ++ ~VimWindow(); ++ ++ // virtual void DispatchMessage(BMessage *m, BHandler *h); ++ virtual void WindowActivated(bool active); ++ virtual bool QuitRequested(); ++ ++ VimFormView *formView; ++ ++ private: ++ void init(); ++ ++}; ++ ++class VimFormView: public BView ++{ ++ typedef BView Inherited; ++ public: ++ VimFormView(BRect frame); ++ ~VimFormView(); ++ ++ // callbacks: ++ virtual void AllAttached(); ++ virtual void FrameResized(float new_width, float new_height); ++ ++#define MENUBAR_MARGIN 1 ++ float MenuHeight() const ++ { return menuBar ? menuBar->Frame().Height() + MENUBAR_MARGIN: 0; } ++ BMenuBar *MenuBar() const ++ { return menuBar; } ++ ++ private: ++ void init(BRect); ++ ++ BMenuBar *menuBar; ++ VimTextAreaView *textArea; ++ ++#ifdef FEAT_TOOLBAR ++ public: ++ float ToolbarHeight() const; ++ VimToolbar *ToolBar() const ++ { return toolBar; } ++ private: ++ VimToolbar *toolBar; ++#endif ++ ++#ifdef FEAT_GUI_TABLINE ++ public: ++ VimTabLine *TabLine() const { return tabLine; } ++ bool IsShowingTabLine() const { return showingTabLine; } ++ void SetShowingTabLine(bool showing) { showingTabLine = showing; } ++ float TablineHeight() const; ++ private: ++ VimTabLine *tabLine; ++ int showingTabLine; ++#endif ++}; ++ ++class VimTextAreaView: public BView ++{ ++ typedef BView Inherited; ++ public: ++ VimTextAreaView(BRect frame); ++ ~VimTextAreaView(); ++ ++ // callbacks: ++ virtual void Draw(BRect updateRect); ++ virtual void KeyDown(const char *bytes, int32 numBytes); ++ virtual void MouseDown(BPoint point); ++ virtual void MouseUp(BPoint point); ++ virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); ++ virtual void MessageReceived(BMessage *m); ++ ++ // own functions: ++ int mchInitFont(char_u *name); ++ void mchDrawString(int row, int col, char_u *s, int len, int flags); ++ void mchClearBlock(int row1, int col1, int row2, int col2); ++ void mchClearAll(); ++ void mchDeleteLines(int row, int num_lines); ++ void mchInsertLines(int row, int num_lines); ++ ++ static void guiSendMouseEvent(int button, int x, int y, int repeated_click, int_u modifiers); ++ static void guiMouseMoved(int x, int y); ++ static void guiBlankMouse(bool should_hide); ++ static int_u mouseModifiersToVim(int32 beModifiers); ++ ++ int32 mouseDragEventCount; ++ ++#ifdef FEAT_MBYTE_IME ++ void DrawIMString(void); ++#endif ++ ++ private: ++ void init(BRect); ++ ++ int_u vimMouseButton; ++ int_u vimMouseModifiers; ++ ++#ifdef FEAT_MBYTE_IME ++ struct { ++ BMessenger* messenger; ++ BMessage* message; ++ BPoint location; ++ int row; ++ int col; ++ int count; ++ } IMData; ++#endif ++}; ++ ++class VimScrollBar: public BScrollBar ++{ ++ typedef BScrollBar Inherited; ++ public: ++ VimScrollBar(scrollbar_T *gsb, orientation posture); ++ ~VimScrollBar(); ++ ++ virtual void ValueChanged(float newValue); ++ virtual void MouseUp(BPoint where); ++ void SetValue(float newval); ++ scrollbar_T *getGsb() ++ { return gsb; } ++ ++ int32 scrollEventCount; ++ ++ private: ++ scrollbar_T *gsb; ++ float ignoreValue; ++}; ++ ++ ++#ifdef FEAT_TOOLBAR ++ ++class VimToolbar : public BBox ++{ ++ static BBitmap *normalButtonsBitmap; ++ static BBitmap *grayedButtonsBitmap; ++ ++ BBitmap *LoadVimBitmap(const char* fileName); ++ bool GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed); ++ bool ModifyBitmapToGrayed(BBitmap *bitmap); ++ ++ BList fButtonsList; ++ void InvalidateLayout(); ++ ++ public: ++ VimToolbar(BRect frame, const char * name); ++ ~VimToolbar(); ++ ++ bool PrepareButtonBitmaps(); ++ ++ bool AddButton(int32 index, vimmenu_T *menu); ++ bool RemoveButton(vimmenu_T *menu); ++ bool GrayButton(vimmenu_T *menu, int grey); ++ ++ float ToolbarHeight() const; ++ virtual void AttachedToWindow(); ++}; ++ ++BBitmap *VimToolbar::normalButtonsBitmap = NULL; ++BBitmap *VimToolbar::grayedButtonsBitmap = NULL; ++ ++const float ToolbarMargin = 3.; ++const float ButtonMargin = 3.; ++ ++#endif /*FEAT_TOOLBAR*/ ++ ++#ifdef FEAT_GUI_TABLINE ++ ++class VimTabLine : public BTabView ++{ ++ public: ++ class VimTab : public BTab { ++ public: ++ VimTab() : BTab(new BView(BRect(), "-Empty-", 0, 0)) {} ++ ++ virtual void Select(BView* owner); ++ }; ++ ++ VimTabLine(BRect r) : BTabView(r, "vimTabLine", B_WIDTH_FROM_LABEL, ++ B_FOLLOW_LEFT | B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS) {} ++ ++ float TablineHeight() const; ++ virtual void MouseDown(BPoint point); ++}; ++ ++#endif //FEAT_GUI_TABLINE ++ ++ ++/* ++ * For caching the fonts that are used; ++ * Vim seems rather sloppy in this regard. ++ */ ++class VimFont: public BFont ++{ ++ typedef BFont Inherited; ++ public: ++ VimFont(); ++ VimFont(const VimFont *rhs); ++ VimFont(const BFont *rhs); ++ VimFont(const VimFont &rhs); ++ ~VimFont(); ++ ++ VimFont *next; ++ int refcount; ++ char_u *name; ++ ++ private: ++ void init(); ++}; ++ ++#if defined(FEAT_GUI_DIALOG) ++ ++class VimDialog : public BWindow ++{ ++ typedef BWindow Inherited; ++ ++ BButton* _CreateButton(int32 which, const char* label); ++ ++ public: ++ ++ class View : public BView { ++ typedef BView Inherited; ++ ++ public: ++ View(BRect frame); ++ ~View(); ++ ++ virtual void Draw(BRect updateRect); ++ void InitIcon(int32 type); ++ ++ private: ++ BBitmap* fIconBitmap; ++ }; ++ ++ VimDialog(int type, const char *title, const char *message, ++ const char *buttons, int dfltbutton, const char *textfield, ++ int ex_cmd); ++ ~VimDialog(); ++ ++ int Go(); ++ ++ virtual void MessageReceived(BMessage *msg); ++ ++ private: ++ sem_id fDialogSem; ++ int fDialogValue; ++ BList fButtonsList; ++ BTextView* fMessageView; ++ BTextControl* fInputControl; ++ const char* fInputValue; ++}; ++ ++class VimSelectFontDialog : public BWindow ++{ ++ typedef BWindow Inherited; ++ ++ void _CleanList(BListView* list); ++ void _UpdateFontStyles(); ++ void _UpdateSizeInputPreview(); ++ void _UpdateFontPreview(); ++ bool _UpdateFromListItem(BListView* list, char* text, int textSize); ++ public: ++ ++ VimSelectFontDialog(font_family* family, font_style* style, float* size); ++ ~VimSelectFontDialog(); ++ ++ bool Go(); ++ ++ virtual void MessageReceived(BMessage *msg); ++ ++ private: ++ status_t fStatus; ++ sem_id fDialogSem; ++ bool fDialogValue; ++ font_family* fFamily; ++ font_style* fStyle; ++ float* fSize; ++ font_family fFontFamily; ++ font_style fFontStyle; ++ float fFontSize; ++ BStringView* fPreview; ++ BListView* fFamiliesList; ++ BListView* fStylesList; ++ BListView* fSizesList; ++ BTextControl* fSizesInput; ++}; ++ ++#endif /* FEAT_GUI_DIALOG */ ++ ++/* ---------------- end of GUI classes ---------------- */ ++ ++struct MainArgs { ++ int argc; ++ char **argv; ++}; ++ ++/* ++ * These messages are copied through the VDCMP. ++ * Therefore they ought not to have anything fancy. ++ * They must be of POD type (Plain Old Data) ++ * as the C++ standard calls them. ++ */ ++ ++#define KEY_MSG_BUFSIZ 7 ++#if KEY_MSG_BUFSIZ < MAX_KEY_CODE_LEN ++#error Increase KEY_MSG_BUFSIZ! ++#endif ++ ++struct VimKeyMsg { ++ char_u length; ++ char_u chars[KEY_MSG_BUFSIZ]; /* contains Vim encoding */ ++#ifdef FEAT_MBYTE ++ bool csi_escape; ++#endif ++}; ++ ++struct VimResizeMsg { ++ int width; ++ int height; ++}; ++ ++struct VimScrollBarMsg { ++ VimScrollBar *sb; ++ long value; ++ int stillDragging; ++}; ++ ++struct VimMenuMsg { ++ vimmenu_T *guiMenu; ++}; ++ ++struct VimMouseMsg { ++ int button; ++ int x; ++ int y; ++ int repeated_click; ++ int_u modifiers; ++}; ++ ++struct VimMouseMovedMsg { ++ int x; ++ int y; ++}; ++ ++struct VimFocusMsg { ++ bool active; ++}; ++ ++struct VimRefsMsg { ++ BMessage *message; ++ bool changedir; ++}; ++ ++struct VimTablineMsg { ++ int index; ++}; ++ ++struct VimTablineMenuMsg { ++ int index; ++ int event; ++}; ++ ++struct VimMsg { ++ enum VimMsgType { ++ Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu ++ }; ++ ++ union { ++ struct VimKeyMsg Key; ++ struct VimResizeMsg NewSize; ++ struct VimScrollBarMsg Scroll; ++ struct VimMenuMsg Menu; ++ struct VimMouseMsg Mouse; ++ struct VimMouseMovedMsg MouseMoved; ++ struct VimFocusMsg Focus; ++ struct VimRefsMsg Refs; ++ struct VimTablineMsg Tabline; ++ struct VimTablineMenuMsg TablineMenu; ++ } u; ++}; ++ ++#define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0) ++#define GUI_TO_RGB(g) { (g) >> 16, (g) >> 8, (g) >> 0, 255 } ++ ++/* ---------------- end of header part ---------------- */ ++ ++static struct specialkey ++{ ++ uint16 BeKeys; ++#define KEY(a,b) ((a)<<8|(b)) ++#define K(a) KEY(0,a) // for ASCII codes ++#define F(b) KEY(1,b) // for scancodes ++ char_u vim_code0; ++ char_u vim_code1; ++} special_keys[] = ++{ ++ {K(B_UP_ARROW), 'k', 'u'}, ++ {K(B_DOWN_ARROW), 'k', 'd'}, ++ {K(B_LEFT_ARROW), 'k', 'l'}, ++ {K(B_RIGHT_ARROW), 'k', 'r'}, ++ {K(B_BACKSPACE), 'k', 'b'}, ++ {K(B_INSERT), 'k', 'I'}, ++ {K(B_DELETE), 'k', 'D'}, ++ {K(B_HOME), 'k', 'h'}, ++ {K(B_END), '@', '7'}, ++ {K(B_PAGE_UP), 'k', 'P'}, /* XK_Prior */ ++ {K(B_PAGE_DOWN), 'k', 'N'}, /* XK_Next, */ ++ ++#define FIRST_FUNCTION_KEY 11 ++ {F(B_F1_KEY), 'k', '1'}, ++ {F(B_F2_KEY), 'k', '2'}, ++ {F(B_F3_KEY), 'k', '3'}, ++ {F(B_F4_KEY), 'k', '4'}, ++ {F(B_F5_KEY), 'k', '5'}, ++ {F(B_F6_KEY), 'k', '6'}, ++ {F(B_F7_KEY), 'k', '7'}, ++ {F(B_F8_KEY), 'k', '8'}, ++ {F(B_F9_KEY), 'k', '9'}, ++ {F(B_F10_KEY), 'k', ';'}, ++ ++ {F(B_F11_KEY), 'F', '1'}, ++ {F(B_F12_KEY), 'F', '2'}, ++ // {XK_F13, 'F', '3'}, /* would be print screen/ */ ++ /* sysreq */ ++ {F(0x0F), 'F', '4'}, /* scroll lock */ ++ {F(0x10), 'F', '5'}, /* pause/break */ ++ // {XK_F16, 'F', '6'}, ++ // {XK_F17, 'F', '7'}, ++ // {XK_F18, 'F', '8'}, ++ // {XK_F19, 'F', '9'}, ++ // {XK_F20, 'F', 'A'}, ++ // ++ // {XK_F21, 'F', 'B'}, ++ // {XK_F22, 'F', 'C'}, ++ // {XK_F23, 'F', 'D'}, ++ // {XK_F24, 'F', 'E'}, ++ // {XK_F25, 'F', 'F'}, ++ // {XK_F26, 'F', 'G'}, ++ // {XK_F27, 'F', 'H'}, ++ // {XK_F28, 'F', 'I'}, ++ // {XK_F29, 'F', 'J'}, ++ // {XK_F30, 'F', 'K'}, ++ // ++ // {XK_F31, 'F', 'L'}, ++ // {XK_F32, 'F', 'M'}, ++ // {XK_F33, 'F', 'N'}, ++ // {XK_F34, 'F', 'O'}, ++ // {XK_F35, 'F', 'P'}, /* keysymdef.h defines up to F35 */ ++ ++ // {XK_Help, '%', '1'}, /* XK_Help */ ++ {F(B_PRINT_KEY), '%', '9'}, ++ ++#if 0 ++ /* Keypad keys: */ ++ {F(0x48), 'k', 'l'}, /* XK_KP_Left */ ++ {F(0x4A), 'k', 'r'}, /* XK_KP_Right */ ++ {F(0x38), 'k', 'u'}, /* XK_KP_Up */ ++ {F(0x59), 'k', 'd'}, /* XK_KP_Down */ ++ {F(0x64), 'k', 'I'}, /* XK_KP_Insert */ ++ {F(0x65), 'k', 'D'}, /* XK_KP_Delete */ ++ {F(0x37), 'k', 'h'}, /* XK_KP_Home */ ++ {F(0x58), '@', '7'}, /* XK_KP_End */ ++ {F(0x39), 'k', 'P'}, /* XK_KP_Prior */ ++ {F(0x60), 'k', 'N'}, /* XK_KP_Next */ ++ {F(0x49), '&', '8'}, /* XK_Undo, keypad 5 */ ++#endif ++ ++ /* End of list marker: */ ++ {0, 0, 0} ++}; ++ ++#define NUM_SPECIAL_KEYS (sizeof(special_keys)/sizeof(special_keys[0])) ++ ++/* ---------------- VimApp ---------------- */ ++ ++ static void ++docd(BPath &path) ++{ ++ mch_chdir((char *)path.Path()); ++ /* Do this to get the side effects of a :cd command */ ++ do_cmdline_cmd((char_u *)"cd ."); ++} ++ ++/* ++ * Really handle dropped files and folders. ++ */ ++ static void ++RefsReceived(BMessage *m, bool changedir) ++{ ++ uint32 type; ++ int32 count; ++ ++ m->PrintToStream(); ++ switch (m->what) { ++ case B_REFS_RECEIVED: ++ case B_SIMPLE_DATA: ++ m->GetInfo("refs", &type, &count); ++ if (type != B_REF_TYPE) ++ goto bad; ++ break; ++ case B_ARGV_RECEIVED: ++ m->GetInfo("argv", &type, &count); ++ if (type != B_STRING_TYPE) ++ goto bad; ++ if (changedir) { ++ char *dirname; ++ if (m->FindString("cwd", (const char **) &dirname) == B_OK) { ++ chdir(dirname); ++ do_cmdline_cmd((char_u *)"cd ."); ++ } ++ } ++ break; ++ default: ++bad: ++ //fprintf(stderr, "bad!\n"); ++ delete m; ++ return; ++ } ++ ++#ifdef FEAT_VISUAL ++ reset_VIsual(); ++#endif ++ ++ char_u **fnames; ++ fnames = (char_u **) alloc(count * sizeof(char_u *)); ++ int fname_index = 0; ++ ++ switch (m->what) { ++ case B_REFS_RECEIVED: ++ case B_SIMPLE_DATA: ++ //fprintf(stderr, "case B_REFS_RECEIVED\n"); ++ for (int i = 0; i < count; ++i) ++ { ++ entry_ref ref; ++ if (m->FindRef("refs", i, &ref) == B_OK) { ++ BEntry entry(&ref, false); ++ BPath path; ++ entry.GetPath(&path); ++ ++ /* Change to parent directory? */ ++ if (changedir) { ++ BPath parentpath; ++ path.GetParent(&parentpath); ++ docd(parentpath); ++ } ++ ++ /* Is it a directory? If so, cd into it. */ ++ BDirectory bdir(&ref); ++ if (bdir.InitCheck() == B_OK) { ++ /* don't cd if we already did it */ ++ if (!changedir) ++ docd(path); ++ } else { ++ mch_dirname(IObuff, IOSIZE); ++ char_u *fname = shorten_fname((char_u *)path.Path(), IObuff); ++ if (fname == NULL) ++ fname = (char_u *)path.Path(); ++ fnames[fname_index++] = vim_strsave(fname); ++ //fprintf(stderr, "%s\n", fname); ++ } ++ ++ /* Only do it for the first file/dir */ ++ changedir = false; ++ } ++ } ++ break; ++ case B_ARGV_RECEIVED: ++ //fprintf(stderr, "case B_ARGV_RECEIVED\n"); ++ for (int i = 1; i < count; ++i) ++ { ++ char *fname; ++ ++ if (m->FindString("argv", i, (const char **) &fname) == B_OK) { ++ fnames[fname_index++] = vim_strsave((char_u *)fname); ++ } ++ } ++ break; ++ default: ++ //fprintf(stderr, "case default\n"); ++ break; ++ } ++ ++ delete m; ++ ++ /* Handle the drop, :edit to get to the file */ ++ if (fname_index > 0) { ++ handle_drop(fname_index, fnames, FALSE); ++ ++ /* Update the screen display */ ++ update_screen(NOT_VALID); ++ setcursor(); ++ out_flush(); ++ } else { ++ vim_free(fnames); ++ } ++} ++ ++VimApp::VimApp(const char *appsig): ++ BApplication(appsig), ++ fFilePanelSem(-1), ++ fFilePanel(NULL) ++{ ++} ++ ++VimApp::~VimApp() ++{ ++} ++ ++ void ++VimApp::ReadyToRun() ++{ ++ /* ++ * Apparently signals are inherited by the created thread - ++ * disable the most annoying ones. ++ */ ++ signal(SIGINT, SIG_IGN); ++ signal(SIGQUIT, SIG_IGN); ++} ++ ++ void ++VimApp::ArgvReceived(int32 arg_argc, char **arg_argv) ++{ ++ if (!IsLaunching()) { ++ /* ++ * This can happen if we are set to Single or Exclusive ++ * Launch. Be nice and open the file(s). ++ */ ++ if (gui.vimWindow) ++ gui.vimWindow->Minimize(false); ++ BMessage *m = CurrentMessage(); ++ DetachCurrentMessage(); ++ SendRefs(m, true); ++ } ++} ++ ++ void ++VimApp::RefsReceived(BMessage *m) ++{ ++ /* Horrible hack!!! XXX XXX XXX ++ * The real problem is that b_start_ffc is set too late for ++ * the initial empty buffer. As a result the window will be ++ * split instead of abandoned. ++ */ ++ int limit = 15; ++ while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0)) ++ snooze(100000); // 0.1 s ++ if (gui.vimWindow) ++ gui.vimWindow->Minimize(false); ++ DetachCurrentMessage(); ++ SendRefs(m, true); ++} ++ ++/* ++ * Pass a BMessage on to the main() thread. ++ * Caller must have detached the message. ++ */ ++ void ++VimApp::SendRefs(BMessage *m, bool changedir) ++{ ++ VimRefsMsg rm; ++ rm.message = m; ++ rm.changedir = changedir; ++ ++ write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm)); ++ // calls ::RefsReceived ++} ++ ++ void ++VimApp::MessageReceived(BMessage *m) ++{ ++ switch (m->what) { ++ case 'save': ++ { ++ entry_ref refDirectory; ++ m->FindRef("directory", &refDirectory); ++ fBrowsedPath.SetTo(&refDirectory); ++ BString strName; ++ m->FindString("name", &strName); ++ fBrowsedPath.Append(strName.String()); ++ } ++ break; ++ case 'open': ++ { ++ entry_ref ref; ++ m->FindRef("refs", &ref); ++ fBrowsedPath.SetTo(&ref); ++ } ++ break; ++ case B_CANCEL: ++ { ++ BFilePanel *panel; ++ m->FindPointer("source", (void**)&panel); ++ if(fFilePanelSem != -1 && panel == fFilePanel) ++ { ++ delete_sem(fFilePanelSem); ++ fFilePanelSem = -1; ++ } ++ ++ } ++ break; ++ default: ++ Inherited::MessageReceived(m); ++ break; ++ } ++} ++ ++ bool ++VimApp::QuitRequested() ++{ ++ (void)Inherited::QuitRequested(); ++ return false; ++} ++ ++/* ---------------- VimWindow ---------------- */ ++ ++VimWindow::VimWindow(): ++ BWindow(BRect(40, 40, 150, 150), ++ "Vim", ++ B_TITLED_WINDOW, ++ 0, ++ B_CURRENT_WORKSPACE) ++ ++{ ++ init(); ++} ++ ++VimWindow::~VimWindow() ++{ ++ if (formView) { ++ RemoveChild(formView); ++ delete formView; ++ } ++ gui.vimWindow = NULL; ++} ++ ++ void ++VimWindow::init() ++{ ++ /* Attach the VimFormView */ ++ formView = new VimFormView(Bounds()); ++ if (formView != NULL) { ++ AddChild(formView); ++ } ++} ++ ++#if 0 // disabled in zeta patch ++ void ++VimWindow::DispatchMessage(BMessage *m, BHandler *h) ++{ ++ /* ++ * Route B_MOUSE_UP messages to MouseUp(), in ++ * a manner that should be compatible with the ++ * intended future system behaviour. ++ */ ++ switch (m->what) { ++ case B_MOUSE_UP: ++ // if (!h) h = PreferredHandler(); ++ // gcc isn't happy without this extra set of braces, complains about ++ // jump to case label crosses init of 'class BView * v' ++ // richard@whitequeen.com jul 99 ++ { ++ BView *v = dynamic_cast(h); ++ if (v) { ++ //m->PrintToStream(); ++ BPoint where; ++ m->FindPoint("where", &where); ++ v->MouseUp(where); ++ } else { ++ Inherited::DispatchMessage(m, h); ++ } ++ } ++ break; ++ default: ++ Inherited::DispatchMessage(m, h); ++ } ++} ++#endif ++ ++ void ++VimWindow::WindowActivated(bool active) ++{ ++ Inherited::WindowActivated(active); ++ /* the textArea gets the keyboard action */ ++ if (active && gui.vimTextArea) ++ gui.vimTextArea->MakeFocus(true); ++ ++ struct VimFocusMsg fm; ++ fm.active = active; ++ ++ write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm)); ++} ++ ++ bool ++VimWindow::QuitRequested() ++{ ++ struct VimKeyMsg km; ++ km.length = 5; ++ memcpy((char *)km.chars, "\033:qa\r", km.length); ++ ++#ifdef FEAT_MBYTE ++ km.csi_escape = false; ++#endif ++ ++ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); ++ ++ return false; ++} ++ ++/* ---------------- VimFormView ---------------- */ ++ ++VimFormView::VimFormView(BRect frame): ++ BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES, ++ B_WILL_DRAW | B_FRAME_EVENTS), ++ menuBar(NULL), ++#ifdef FEAT_TOOLBAR ++ toolBar(NULL), ++#endif ++#ifdef FEAT_GUI_TABLINE ++// showingTabLine(false), ++ tabLine(NULL), ++#endif ++ textArea(NULL) ++{ ++ init(frame); ++} ++ ++VimFormView::~VimFormView() ++{ ++ if (menuBar) { ++ RemoveChild(menuBar); ++#ifdef never ++ // deleting the menuBar leads to SEGV on exit ++ // richard@whitequeen.com Jul 99 ++ delete menuBar; ++#endif ++ } ++ ++#ifdef FEAT_TOOLBAR ++ delete toolBar; ++#endif ++ ++#ifdef FEAT_GUI_TABLINE ++ delete tabLine; ++#endif ++ ++ if (textArea) { ++ RemoveChild(textArea); ++ delete textArea; ++ } ++ gui.vimForm = NULL; ++} ++ ++ void ++VimFormView::init(BRect frame) ++{ ++ menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN), ++ "VimMenuBar"); ++ ++ AddChild(menuBar); ++ ++#ifdef FEAT_TOOLBAR ++ toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar"); ++ toolBar->PrepareButtonBitmaps(); ++ AddChild(toolBar); ++#endif ++ ++#ifdef FEAT_GUI_TABLINE ++ tabLine = new VimTabLine(BRect(0,0,0,0)); ++// tabLine->PrepareButtonBitmaps(); ++ AddChild(tabLine); ++#endif ++ ++ BRect remaining = frame; ++ textArea = new VimTextAreaView(remaining); ++ AddChild(textArea); ++ /* The textArea will be resized later when menus are added */ ++ ++ gui.vimForm = this; ++} ++ ++#ifdef FEAT_TOOLBAR ++ float ++VimFormView::ToolbarHeight() const ++{ ++ return toolBar ? toolBar->ToolbarHeight() : 0.; ++} ++#endif ++ ++#ifdef FEAT_GUI_TABLINE ++ float ++VimFormView::TablineHeight() const ++{ ++ return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.; ++} ++#endif ++ ++ void ++VimFormView::AllAttached() ++{ ++ /* ++ * Apparently signals are inherited by the created thread - ++ * disable the most annoying ones. ++ */ ++ signal(SIGINT, SIG_IGN); ++ signal(SIGQUIT, SIG_IGN); ++ ++ if (menuBar && textArea) { ++ /* ++ * Resize the textArea to fill the space left over by the menu. ++ * This is somewhat futile since it will be done again once ++ * menus are added to the menu bar. ++ */ ++ BRect remaining = Bounds(); ++ ++#ifdef FEAT_MENU ++ remaining.top += MenuHeight(); ++ menuBar->ResizeTo(remaining.right, remaining.top); ++ gui.menu_height = (int) MenuHeight(); ++#endif ++ ++#ifdef FEAT_TOOLBAR ++ toolBar->MoveTo(remaining.left, remaining.top); ++ toolBar->ResizeTo(remaining.right, ToolbarHeight()); ++ remaining.top += ToolbarHeight(); ++ gui.toolbar_height = ToolbarHeight(); ++#endif ++ ++#ifdef FEAT_GUI_TABLINE ++ tabLine->MoveTo(remaining.left, remaining.top); ++ tabLine->ResizeTo(remaining.right + 1, TablineHeight()); ++ remaining.top += TablineHeight(); ++ gui.tabline_height = TablineHeight(); ++#endif ++ ++ textArea->ResizeTo(remaining.Width(), remaining.Height()); ++ textArea->MoveTo(remaining.left, remaining.top); ++ } ++ ++ ++ Inherited::AllAttached(); ++} ++ ++ void ++VimFormView::FrameResized(float new_width, float new_height) ++{ ++ struct VimResizeMsg sm; ++ int adjust_h, adjust_w; ++ ++ new_width += 1; // adjust from width to number of pixels occupied ++ new_height += 1; ++ ++ sm.width = (int) new_width; ++ sm.height = (int) new_height; ++ adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width; ++ adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height; ++ ++ if (adjust_w > 0 || adjust_h > 0) { ++ sm.width -= adjust_w; ++ sm.height -= adjust_h; ++ } ++ ++ write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm)); ++ // calls gui_resize_shell(new_width, new_height); ++ ++ return; ++ ++ /* ++ * The area below the vertical scrollbar is erased to the colour ++ * set with SetViewColor() automatically, because we had set ++ * B_WILL_DRAW. Resizing the window tight around the vertical ++ * scroll bar also helps to avoid debris. ++ */ ++} ++ ++/* ---------------- VimTextAreaView ---------------- */ ++ ++VimTextAreaView::VimTextAreaView(BRect frame): ++ BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES, ++#ifdef FEAT_MBYTE_IME ++ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INPUT_METHOD_AWARE), ++#else ++ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), ++#endif ++ mouseDragEventCount(0) ++{ ++#ifdef FEAT_MBYTE_IME ++ IMData.messenger = NULL; ++ IMData.message = NULL; ++#endif ++ init(frame); ++} ++ ++VimTextAreaView::~VimTextAreaView() ++{ ++ gui.vimTextArea = NULL; ++} ++ ++ void ++VimTextAreaView::init(BRect frame) ++{ ++ /* set up global var for fast access */ ++ gui.vimTextArea = this; ++ ++ /* ++ * Tell the app server not to erase the view: we will ++ * fill it in completely by ourselves. ++ * (Does this really work? Even if not, it won't harm either.) ++ */ ++ SetViewColor(B_TRANSPARENT_32_BIT); ++#define PEN_WIDTH 1 ++ SetPenSize(PEN_WIDTH); ++} ++ ++ void ++VimTextAreaView::Draw(BRect updateRect) ++{ ++ /* ++ * XXX Other ports call here: ++ * out_flush(); * make sure all output has been processed * ++ * but we can't do that, since it involves too much information ++ * that is owned by other threads... ++ */ ++ ++ /* ++ * No need to use gui.vimWindow->Lock(): we are locked already. ++ * However, it would not hurt. ++ */ ++ rgb_color rgb = GUI_TO_RGB(gui.back_pixel); ++ SetLowColor(rgb); ++ FillRect(updateRect, B_SOLID_LOW); ++ gui_redraw((int) updateRect.left, (int) updateRect.top, ++ (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH)); ++ ++ /* Clear the border areas if needed */ ++ SetLowColor(rgb); ++ ++ if (updateRect.left < FILL_X(0)) // left border ++ FillRect(BRect(updateRect.left, updateRect.top, ++ FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW); ++ if (updateRect.top < FILL_Y(0)) // top border ++ FillRect(BRect(updateRect.left, updateRect.top, ++ updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW); ++ if (updateRect.right >= FILL_X(Columns)) // right border ++ FillRect(BRect(FILL_X((int)Columns), updateRect.top, ++ updateRect.right, updateRect.bottom), B_SOLID_LOW); ++ if (updateRect.bottom >= FILL_Y(Rows)) // bottom border ++ FillRect(BRect(updateRect.left, FILL_Y((int)Rows), ++ updateRect.right, updateRect.bottom), B_SOLID_LOW); ++ ++#ifdef FEAT_MBYTE_IME ++ DrawIMString(); ++#endif ++} ++ ++ void ++VimTextAreaView::KeyDown(const char *bytes, int32 numBytes) ++{ ++ struct VimKeyMsg km; ++ char_u *dest = km.chars; ++ ++ bool canHaveVimModifiers = false; ++ ++ BMessage *msg = Window()->CurrentMessage(); ++ assert(msg); ++ //msg->PrintToStream(); ++ ++ /* ++ * Convert special keys to Vim codes. ++ * I think it is better to do it in the window thread ++ * so we use at least a little bit of the potential ++ * of our 2 CPUs. Besides, due to the fantastic mapping ++ * of special keys to UTF-8, we have quite some work to ++ * do... ++ * TODO: I'm not quite happy with detection of special ++ * keys. Perhaps I should use scan codes after all... ++ */ ++ if (numBytes > 1) { ++ /* This cannot be a special key */ ++ if (numBytes > KEY_MSG_BUFSIZ) ++ numBytes = KEY_MSG_BUFSIZ; // should never happen... ??? ++ km.length = numBytes; ++ memcpy((char *)dest, bytes, numBytes); ++#ifdef FEAT_MBYTE ++ km.csi_escape = true; ++#endif ++ } else { ++ int32 scancode = 0; ++ msg->FindInt32("key", &scancode); ++ ++ int32 beModifiers = 0; ++ msg->FindInt32("modifiers", &beModifiers); ++ ++ char_u string[3]; ++ int len = 0; ++ km.length = 0; ++ ++ /* ++ * For normal, printable ASCII characters, don't look them up ++ * to check if they might be a special key. They aren't. ++ */ ++ assert(B_BACKSPACE <= 0x20); ++ assert(B_DELETE == 0x7F); ++ if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) && ++ numBytes == 1) { ++ /* ++ * Due to the great nature of Be's mapping of special keys, ++ * viz. into the range of the control characters, ++ * we can only be sure it is *really* a special key if ++ * if it is special without using ctrl. So, only if ctrl is ++ * used, we need to check it unmodified. ++ */ ++ if (beModifiers & B_CONTROL_KEY) { ++ int index = keyMap->normal_map[scancode]; ++ int newNumBytes = keyMapChars[index]; ++ char_u *newBytes = (char_u *)&keyMapChars[index + 1]; ++ ++ /* ++ * Check if still special without the control key. ++ * This is needed for BACKSPACE: that key does produce ++ * different values with modifiers (DEL). ++ * Otherwise we could simply have checked for equality. ++ */ ++ if (newNumBytes != 1 || (*newBytes > 0x20 && ++ *newBytes != 0x7F )) { ++ goto notspecial; ++ } ++ bytes = (char *)newBytes; ++ } ++ canHaveVimModifiers = true; ++ ++ uint16 beoskey; ++ int first, last; ++ ++ /* ++ * If numBytes == 0 that probably always indicates a special key. ++ * (does not happen yet) ++ */ ++ if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) { ++ beoskey = F(scancode); ++ first = FIRST_FUNCTION_KEY; ++ last = NUM_SPECIAL_KEYS; ++ } else if (*bytes == '\n' && scancode == 0x47) { ++ /* remap the (non-keypad) ENTER key from \n to \r. */ ++ string[0] = '\r'; ++ len = 1; ++ first = last = 0; ++ } else { ++ beoskey = K(bytes[0]); ++ first = 0; ++ last = FIRST_FUNCTION_KEY; ++ } ++ ++ for (int i = first; i < last; i++) { ++ if (special_keys[i].BeKeys == beoskey) { ++ string[0] = CSI; ++ string[1] = special_keys[i].vim_code0; ++ string[2] = special_keys[i].vim_code1; ++ len = 3; ++ } ++ } ++ } ++notspecial: ++ if (len == 0) { ++ string[0] = bytes[0]; ++ len = 1; ++ } ++ ++ /* Special keys (and a few others) may have modifiers */ ++#if 0 ++ if (len == 3 || ++ bytes[0] == B_SPACE || bytes[0] == B_TAB || ++ bytes[0] == B_RETURN || bytes[0] == '\r' || ++ bytes[0] == B_ESCAPE) ++#else ++ if (canHaveVimModifiers) ++#endif ++ { ++ int modifiers; ++ modifiers = 0; ++ if (beModifiers & B_SHIFT_KEY) ++ modifiers |= MOD_MASK_SHIFT; ++ if (beModifiers & B_CONTROL_KEY) ++ modifiers |= MOD_MASK_CTRL; ++ if (beModifiers & B_OPTION_KEY) ++ modifiers |= MOD_MASK_ALT; ++ ++ /* ++ * For some keys a shift modifier is translated into another key ++ * code. Do we need to handle the case where len != 1 and ++ * string[0] != CSI? (Not for BeOS, since len == 3 implies ++ * string[0] == CSI...) ++ */ ++ int key; ++ if (string[0] == CSI && len == 3) ++ key = TO_SPECIAL(string[1], string[2]); ++ else ++ key = string[0]; ++ key = simplify_key(key, &modifiers); ++ if (IS_SPECIAL(key)) ++ { ++ string[0] = CSI; ++ string[1] = K_SECOND(key); ++ string[2] = K_THIRD(key); ++ len = 3; ++ } ++ else ++ { ++ string[0] = key; ++ len = 1; ++ } ++ ++ if (modifiers) ++ { ++ *dest++ = CSI; ++ *dest++ = KS_MODIFIER; ++ *dest++ = modifiers; ++ km.length = 3; ++ } ++ } ++ memcpy((char *)dest, string, len); ++ km.length += len; ++#ifdef FEAT_MBYTE ++ km.csi_escape = false; ++#endif ++ } ++ ++ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); ++ ++ /* ++ * blank out the pointer if necessary ++ */ ++ if (p_mh && !gui.pointer_hidden) ++ { ++ guiBlankMouse(true); ++ gui.pointer_hidden = TRUE; ++ } ++} ++void ++VimTextAreaView::guiSendMouseEvent( ++ int button, ++ int x, ++ int y, ++ int repeated_click, ++ int_u modifiers) ++{ ++ VimMouseMsg mm; ++ ++ mm.button = button; ++ mm.x = x; ++ mm.y = y; ++ mm.repeated_click = repeated_click; ++ mm.modifiers = modifiers; ++ ++ write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm)); ++ // calls gui_send_mouse_event() ++ ++ /* ++ * if our pointer is currently hidden, then we should show it. ++ */ ++ if (gui.pointer_hidden) ++ { ++ guiBlankMouse(false); ++ gui.pointer_hidden = FALSE; ++ } ++} ++ ++void ++VimTextAreaView::guiMouseMoved( ++ int x, ++ int y) ++{ ++ VimMouseMovedMsg mm; ++ ++ mm.x = x; ++ mm.y = y; ++ ++ write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm)); ++ ++ if (gui.pointer_hidden) ++ { ++ guiBlankMouse(false); ++ gui.pointer_hidden = FALSE; ++ } ++} ++ ++ void ++VimTextAreaView::guiBlankMouse(bool should_hide) ++{ ++ if (should_hide) { ++ //gui.vimApp->HideCursor(); ++ gui.vimApp->ObscureCursor(); ++ /* ++ * ObscureCursor() would even be easier, but then ++ * Vim's idea of mouse visibility does not necessarily ++ * correspond to reality. ++ */ ++ } else { ++ //gui.vimApp->ShowCursor(); ++ } ++} ++ ++ int_u ++VimTextAreaView::mouseModifiersToVim(int32 beModifiers) ++{ ++ int_u vim_modifiers = 0x0; ++ ++ if (beModifiers & B_SHIFT_KEY) ++ vim_modifiers |= MOUSE_SHIFT; ++ if (beModifiers & B_CONTROL_KEY) ++ vim_modifiers |= MOUSE_CTRL; ++ if (beModifiers & B_OPTION_KEY) /* Alt or Meta key */ ++ vim_modifiers |= MOUSE_ALT; ++ ++ return vim_modifiers; ++} ++ ++ void ++VimTextAreaView::MouseDown(BPoint point) ++{ ++ BMessage *m = Window()->CurrentMessage(); ++ assert(m); ++ ++ int32 buttons = 0; ++ m->FindInt32("buttons", &buttons); ++ ++ int vimButton; ++ ++ if (buttons & B_PRIMARY_MOUSE_BUTTON) ++ vimButton = MOUSE_LEFT; ++ else if (buttons & B_SECONDARY_MOUSE_BUTTON) ++ vimButton = MOUSE_RIGHT; ++ else if (buttons & B_TERTIARY_MOUSE_BUTTON) ++ vimButton = MOUSE_MIDDLE; ++ else ++ return; /* Unknown button */ ++ ++ vimMouseButton = 1; /* don't care which one */ ++ ++ /* Handle multiple clicks */ ++ int32 clicks = 0; ++ m->FindInt32("clicks", &clicks); ++ ++ int32 modifiers = 0; ++ m->FindInt32("modifiers", &modifiers); ++ ++ vimMouseModifiers = mouseModifiersToVim(modifiers); ++ ++ guiSendMouseEvent(vimButton, point.x, point.y, ++ clicks > 1 /* = repeated_click*/, vimMouseModifiers); ++} ++ ++ void ++VimTextAreaView::MouseUp(BPoint point) ++{ ++ vimMouseButton = 0; ++ ++ BMessage *m = Window()->CurrentMessage(); ++ assert(m); ++ //m->PrintToStream(); ++ ++ int32 modifiers = 0; ++ m->FindInt32("modifiers", &modifiers); ++ ++ vimMouseModifiers = mouseModifiersToVim(modifiers); ++ ++ guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y, ++ 0 /* = repeated_click*/, vimMouseModifiers); ++ ++ Inherited::MouseUp(point); ++} ++ ++ void ++VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) ++{ ++ /* ++ * if our pointer is currently hidden, then we should show it. ++ */ ++ if (gui.pointer_hidden) ++ { ++ guiBlankMouse(false); ++ gui.pointer_hidden = FALSE; ++ } ++ ++ if (!vimMouseButton) { /* could also check m->"buttons" */ ++ guiMouseMoved(point.x, point.y); ++ return; ++ } ++ ++ atomic_add(&mouseDragEventCount, 1); ++ ++ /* Don't care much about "transit" */ ++ guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers); ++} ++ ++ void ++VimTextAreaView::MessageReceived(BMessage *m) ++{ ++ switch (m->what) { ++ case 'menu': ++ { ++ VimMenuMsg mm; ++ mm.guiMenu = NULL; /* in case no pointer in msg */ ++ m->FindPointer("VimMenu", (void **)&mm.guiMenu); ++ write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm)); ++ } ++ break; ++ case B_MOUSE_WHEEL_CHANGED: ++ { ++ VimScrollBar* scb = curwin->w_scrollbars[1].id; ++ float small=0, big=0, dy=0; ++ m->FindFloat("be:wheel_delta_y", &dy); ++ scb->GetSteps(&small, &big); ++ scb->SetValue(scb->Value()+small*dy*3); ++ scb->ValueChanged(scb->Value()); ++#if 0 ++ scb = curwin->w_scrollbars[0].id; ++ scb->GetSteps(&small, &big); ++ scb->SetValue(scb->Value()+small*dy); ++ scb->ValueChanged(scb->Value()); ++#endif ++ } ++ break; ++#ifdef FEAT_MBYTE_IME ++ case B_INPUT_METHOD_EVENT: ++ { ++ int32 opcode; ++ m->FindInt32("be:opcode", &opcode); ++ switch(opcode) ++ { ++ case B_INPUT_METHOD_STARTED: ++ if(!IMData.messenger) delete IMData.messenger; ++ IMData.messenger = new BMessenger(); ++ m->FindMessenger("be:reply_to", IMData.messenger); ++ break; ++ case B_INPUT_METHOD_CHANGED: ++ { ++ BString str; ++ bool confirmed; ++ if(IMData.message) *(IMData.message) = *m; ++ else IMData.message = new BMessage(*m); ++ DrawIMString(); ++ m->FindBool("be:confirmed", &confirmed); ++ if (confirmed) ++ { ++ m->FindString("be:string", &str); ++ char_u *chars = (char_u*)str.String(); ++ struct VimKeyMsg km; ++ km.csi_escape = true; ++ int clen; ++ int i = 0; ++ while (i < str.Length()) ++ { ++ clen = utf_ptr2len(chars+i); ++ memcpy(km.chars, chars+i, clen); ++ km.length = clen; ++ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); ++ i += clen; ++ } ++ } ++ } ++ break; ++ case B_INPUT_METHOD_LOCATION_REQUEST: ++ { ++ BMessage msg(B_INPUT_METHOD_EVENT); ++ msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST); ++ msg.AddPoint("be:location_reply", IMData.location); ++ msg.AddFloat("be:height_reply", FILL_Y(1)); ++ IMData.messenger->SendMessage(&msg); ++ } ++ break; ++ case B_INPUT_METHOD_STOPPED: ++ delete IMData.messenger; ++ delete IMData.message; ++ IMData.messenger = NULL; ++ IMData.message = NULL; ++ break; ++ } ++ } ++ //TODO: sz: break here??? ++#endif ++ default: ++ if (m->WasDropped()) { ++ BWindow *w = Window(); ++ w->DetachCurrentMessage(); ++ w->Minimize(false); ++ VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0); ++ } else { ++ Inherited::MessageReceived(m); ++ } ++ break; ++ } ++} ++ ++ int ++VimTextAreaView::mchInitFont(char_u *name) ++{ ++ VimFont *newFont = (VimFont *)gui_mch_get_font(name, 1); ++ if(newFont != NOFONT) { ++ gui.norm_font = (GuiFont)newFont; ++ gui_mch_set_font((GuiFont)newFont); ++ if (name && STRCMP(name, "*") != 0) ++ hl_set_font_name(name); ++ ++ SetDrawingMode(B_OP_COPY); ++ ++ /* ++ * Try to load other fonts for bold, italic, and bold-italic. ++ * We should also try to work out what font to use for these when they are ++ * not specified by X resources, but we don't yet. ++ */ ++ return OK; ++ } ++ return FAIL; ++} ++ ++ void ++VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags) ++{ ++ /* ++ * First we must erase the area, because DrawString won't do ++ * that for us. XXX Most of the time this is a waste of effort ++ * since the bachground has been erased already... DRAW_TRANSP ++ * should be set when appropriate!!! ++ * (Rectangles include the bottom and right edge) ++ */ ++ if (!(flags & DRAW_TRANSP)) { ++ int cells; ++#ifdef FEAT_MBYTE ++ cells = 0; ++ for(int i=0; iGetFont(&font); ++ if(!font.IsFixed()) ++ { ++ char* p = (char*)s; ++ int32 clen, lastpos = 0; ++ BPoint where; ++ int cells; ++ while((p - (char*)s) < len) { ++#ifdef FEAT_MBYTE ++ clen = utf_ptr2len((u_char*)p); ++#else ++ clen = 1; ++#endif ++ where.Set(TEXT_X(col+lastpos), TEXT_Y(row)); ++ DrawString(p, clen, where); ++ if (flags & DRAW_BOLD) { ++ where.x += 1.0; ++ SetDrawingMode(B_OP_BLEND); ++ DrawString(p, clen, where); ++ SetDrawingMode(B_OP_COPY); ++ } ++#ifdef FEAT_MBYTE ++ cells = utf_ptr2cells((char_u *)p); ++ if(cells<4) lastpos += cells; ++ else lastpos++; ++#else ++ lastpos++; ++#endif ++ p += clen; ++ } ++ } ++ else ++ { ++ BPoint where(TEXT_X(col), TEXT_Y(row)); ++ DrawString((char*)s, len, where); ++ if (flags & DRAW_BOLD) { ++ where.x += 1.0; ++ SetDrawingMode(B_OP_BLEND); ++ DrawString((char*)s, len, where); ++ SetDrawingMode(B_OP_COPY); ++ } ++ } ++ ++ if (flags & DRAW_UNDERL) { ++ int cells; ++#ifdef FEAT_MBYTE ++ cells = 0; ++ for(int i=0; iLock()) { ++ /* Clear one column more for when bold has spilled over */ ++ CopyBits(source, dest); ++ gui_clear_block(gui.scroll_region_bot - num_lines + 1, ++ gui.scroll_region_left, ++ gui.scroll_region_bot, gui.scroll_region_right); ++ ++ ++ gui.vimWindow->Unlock(); ++ /* ++ * The Draw() callback will be called now if some of the source ++ * bits were not in the visible region. ++ */ ++ } ++ //gui_x11_check_copy_area(); ++ // } ++} ++ ++/* ++ * mchInsertLines() Lock()s the window by itself. ++ */ ++ void ++VimTextAreaView::mchInsertLines(int row, int num_lines) ++{ ++ BRect source, dest; ++ ++ /* XXX Attempt at a hack: */ ++ gui.vimWindow->UpdateIfNeeded(); ++ source.left = FILL_X(gui.scroll_region_left); ++ source.top = FILL_Y(row); ++ source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH; ++ source.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH; ++ ++ dest.left = FILL_X(gui.scroll_region_left); ++ dest.top = FILL_Y(row + num_lines); ++ dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH; ++ dest.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH; ++ ++ if (gui.vimWindow->Lock()) { ++ /* Clear one column more for when bold has spilled over */ ++ CopyBits(source, dest); ++ gui_clear_block(row, gui.scroll_region_left, ++ row + num_lines - 1, gui.scroll_region_right); ++ ++ gui.vimWindow->Unlock(); ++ /* ++ * The Draw() callback will be called now if some of the source ++ * bits were not in the visible region. ++ * However, if we scroll too fast it can't keep up and the ++ * update region gets messed up. This seems to be because copying ++ * un-Draw()n bits does not generate Draw() calls for the copy... ++ * I moved the hack to before the CopyBits() to reduce the ++ * amount of additional waiting needed. ++ */ ++ ++ //gui_x11_check_copy_area(); ++ ++ } ++} ++ ++#ifdef FEAT_MBYTE_IME ++/* ++ * DrawIMString draws string with IMData.message. ++ */ ++void VimTextAreaView::DrawIMString(void) ++{ ++ static const rgb_color r_highlight = {255, 152, 152, 255}, ++ b_highlight = {152, 203, 255, 255}; ++ BString str; ++ const char* s; ++ int len; ++ BMessage* msg = IMData.message; ++ if (!msg) ++ return; ++ gui_redraw_block(IMData.row, 0, ++ IMData.row + IMData.count, curwin->w_width, GUI_MON_NOCLEAR); ++ bool confirmed = false; ++ msg->FindBool("be:confirmed", &confirmed); ++ if (confirmed) ++ return; ++ rgb_color hcolor = HighColor(), lcolor = LowColor(); ++ msg->FindString("be:string", &str); ++ s = str.String(); ++ len = str.Length(); ++ SetHighColor(0, 0, 0); ++ IMData.row = gui.row; ++ IMData.col = gui.col; ++ int32 sel_start = 0, sel_end = 0; ++ msg->FindInt32("be:selection", 0, &sel_start); ++ msg->FindInt32("be:selection", 1, &sel_end); ++ int clen, cn; ++ BPoint pos(IMData.col, 0); ++ BRect r; ++ BPoint where; ++ IMData.location = ConvertToScreen( ++ BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y))); ++ for (int i=0; i curwin->w_width) ++ { ++ pos.y++; ++ pos.x = 0; ++ } ++ if (sel_start<=i && i= 0.0 && newValue == ignoreValue) { ++ ignoreValue = -1; ++ return; ++ } ++ ignoreValue = -1; ++ /* ++ * We want to throttle the amount of scroll messages generated. ++ * Normally I presume you won't get a new message before we've ++ * handled the previous one, but because we're passing them on this ++ * happens very quickly. So instead we keep a counter of how many ++ * scroll events there are (or will be) in the VDCMP, and the ++ * throttling happens at the receiving end. ++ */ ++ atomic_add(&scrollEventCount, 1); ++ ++ struct VimScrollBarMsg sm; ++ ++ sm.sb = this; ++ sm.value = (long) newValue; ++ sm.stillDragging = TRUE; ++ ++ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm)); ++ ++ // calls gui_drag_scrollbar(sb, newValue, TRUE); ++} ++ ++/* ++ * When the mouse goes up, report that scrolling has stopped. ++ * MouseUp() is NOT called when the mouse-up occurs outside ++ * the window, even though the thumb does move while the mouse ++ * is outside... This has some funny effects... XXX ++ * So we do special processing when the window de/activates. ++ */ ++ void ++VimScrollBar::MouseUp(BPoint where) ++{ ++ //BMessage *m = Window()->CurrentMessage(); ++ //m->PrintToStream(); ++ ++ atomic_add(&scrollEventCount, 1); ++ ++ struct VimScrollBarMsg sm; ++ ++ sm.sb = this; ++ sm.value = (long) Value(); ++ sm.stillDragging = FALSE; ++ ++ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm)); ++ ++ // calls gui_drag_scrollbar(sb, newValue, FALSE); ++ ++ Inherited::MouseUp(where); ++} ++ ++ void ++VimScrollBar::SetValue(float newValue) ++{ ++ if (newValue == Value()) ++ return; ++ ++ ignoreValue = newValue; ++ Inherited::SetValue(newValue); ++} ++ ++/* ---------------- VimFont ---------------- */ ++ ++VimFont::VimFont(): BFont() ++{ ++ init(); ++} ++ ++VimFont::VimFont(const VimFont *rhs): BFont(rhs) ++{ ++ init(); ++} ++ ++VimFont::VimFont(const BFont *rhs): BFont(rhs) ++{ ++ init(); ++} ++ ++VimFont::VimFont(const VimFont &rhs): BFont(rhs) ++{ ++ init(); ++} ++ ++VimFont::~VimFont() ++{ ++} ++ ++ void ++VimFont::init() ++{ ++ next = NULL; ++ refcount = 1; ++ name = NULL; ++} ++ ++/* ---------------- VimDialog ---------------- */ ++ ++#if defined(FEAT_GUI_DIALOG) ++ ++const unsigned int kVimDialogButtonMsg = 'VMDB'; ++const unsigned int kVimDialogIconStripeWidth = 30; ++const unsigned int kVimDialogButtonsSpacingX = 9; ++const unsigned int kVimDialogButtonsSpacingY = 4; ++const unsigned int kVimDialogSpacingX = 6; ++const unsigned int kVimDialogSpacingY = 10; ++const unsigned int kVimDialogMinimalWidth = 310; ++const unsigned int kVimDialogMinimalHeight = 75; ++const BRect kDefaultRect = ++BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight); ++ ++VimDialog::VimDialog(int type, const char *title, const char *message, ++ const char *buttons, int dfltbutton, const char *textfield, int ex_cmd) ++: BWindow(kDefaultRect, title, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, ++ B_NOT_CLOSABLE | B_NOT_RESIZABLE | ++ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS) ++ , fDialogSem(-1) ++ , fDialogValue(dfltbutton) ++ , fMessageView(NULL) ++ , fInputControl(NULL) ++ , fInputValue(textfield) ++{ ++ // master view ++ VimDialog::View* view = new VimDialog::View(Bounds()); ++ if(view == NULL) ++ return; ++ ++ if(title == NULL) ++ SetTitle("Vim " VIM_VERSION_MEDIUM); ++ ++ AddChild(view); ++ ++ // icon ++ view->InitIcon(type); ++ ++ // buttons ++ int32 which = 1; ++ float maxButtonWidth = 0; ++ float maxButtonHeight = 0; ++ float buttonsWidth = 0; ++ float buttonsHeight = 0; ++ BString strButtons(buttons); ++ strButtons.RemoveAll("&"); ++ do { ++ int32 end = strButtons.FindFirst('\n'); ++ if(end != B_ERROR) ++ strButtons.SetByteAt(end, '\0'); ++ ++ BButton *button = _CreateButton(which++, strButtons.String()); ++ view->AddChild(button); ++ fButtonsList.AddItem(button); ++ ++ maxButtonWidth = max_c(maxButtonWidth, button->Bounds().Width()); ++ maxButtonHeight = max_c(maxButtonHeight, button->Bounds().Height()); ++ buttonsWidth += button->Bounds().Width(); ++ buttonsHeight += button->Bounds().Height(); ++ ++ if(end == B_ERROR) ++ break; ++ ++ strButtons.Remove(0, end + 1); ++ } while(true); ++ ++ int32 buttonsCount = fButtonsList.CountItems(); ++ buttonsWidth += kVimDialogButtonsSpacingX * (buttonsCount - 1); ++ buttonsHeight += kVimDialogButtonsSpacingY * (buttonsCount - 1); ++ float dialogWidth = buttonsWidth + kVimDialogIconStripeWidth + ++ kVimDialogSpacingX * 2; ++ float dialogHeight = maxButtonHeight + kVimDialogSpacingY * 3; ++ ++ /* Check 'v' flag in 'guioptions': vertical button placement. */ ++ bool vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL) || ++ dialogWidth >= gui.vimWindow->Bounds().Width(); ++ if(vertical) { ++ dialogWidth -= buttonsWidth; ++ dialogWidth += maxButtonWidth; ++ dialogHeight -= maxButtonHeight; ++ dialogHeight += buttonsHeight; ++ } ++ ++ dialogWidth = max_c(dialogWidth, kVimDialogMinimalWidth); ++ ++ // message view ++ BRect rect(0, 0, dialogWidth, 0); ++ rect.left += kVimDialogIconStripeWidth + 16 + kVimDialogSpacingX; ++ rect.top += kVimDialogSpacingY; ++ rect.right -= kVimDialogSpacingX; ++ rect.bottom = rect.top; ++ fMessageView = new BTextView(rect, "_tv_", rect.OffsetByCopy(B_ORIGIN), ++ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); ++ ++ fMessageView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); ++ rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); ++ fMessageView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor); ++ fMessageView->SetText(message); ++ fMessageView->MakeEditable(false); ++ fMessageView->MakeSelectable(false); ++ fMessageView->SetWordWrap(true); ++ AddChild(fMessageView); ++ ++ float messageHeight = fMessageView->TextHeight(0, fMessageView->CountLines()); ++ fMessageView->ResizeBy(0, messageHeight); ++ fMessageView->SetTextRect(BRect(0, 0, rect.Width(), messageHeight)); ++ ++ dialogHeight += messageHeight; ++ ++ // input view ++ if(fInputValue != NULL) { ++ rect.top = ++ rect.bottom += messageHeight + kVimDialogSpacingY; ++ fInputControl = new BTextControl(rect, "_iv_", NULL, fInputValue, NULL, ++ B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED); ++ fInputControl->TextView()->SetText(fInputValue); ++ fInputControl->TextView()->SetWordWrap(false); ++ AddChild(fInputControl); ++ ++ float width = 0.f, height = 0.f; ++ fInputControl->GetPreferredSize(&width, &height); ++ fInputControl->MakeFocus(true); ++ ++ dialogHeight += height + kVimDialogSpacingY * 1.5; ++ } ++ ++ dialogHeight = max_c(dialogHeight, kVimDialogMinimalHeight); ++ ++ ResizeTo(dialogWidth, dialogHeight); ++ MoveTo((gui.vimWindow->Bounds().Width() - dialogWidth) / 2, ++ (gui.vimWindow->Bounds().Height() - dialogHeight) / 2); ++ ++ // adjust layout of buttons ++ float buttonWidth = max_c(maxButtonWidth, rect.Width() * 0.66); ++ BPoint origin(dialogWidth, dialogHeight); ++ origin.x -= kVimDialogSpacingX + (vertical ? buttonWidth : buttonsWidth); ++ origin.y -= kVimDialogSpacingY + (vertical ? buttonsHeight : maxButtonHeight); ++ ++ for(int32 i = 0 ; i < buttonsCount; i++) { ++ BButton *button = (BButton*)fButtonsList.ItemAt(i); ++ button->MoveTo(origin); ++ if(vertical) { ++ origin.y += button->Frame().Height() + kVimDialogButtonsSpacingY; ++ button->ResizeTo(buttonWidth, button->Frame().Height()); ++ } else ++ origin.x += button->Frame().Width() + kVimDialogButtonsSpacingX; ++ ++ if(dfltbutton == i + 1) { ++ button->MakeDefault(true); ++ button->MakeFocus(fInputControl == NULL); ++ } ++ } ++} ++ ++VimDialog::~VimDialog() ++{ ++ if(fDialogSem > B_OK) ++ delete_sem(fDialogSem); ++} ++ ++ int ++VimDialog::Go() ++{ ++ fDialogSem = create_sem(0, "VimDialogSem"); ++ if(fDialogSem < B_OK) { ++ Quit(); ++ return fDialogValue; ++ } ++ ++ Show(); ++ ++ while(acquire_sem(fDialogSem) == B_INTERRUPTED); ++ ++ int retValue = fDialogValue; ++ if(fInputValue != NULL) ++ vim_strncpy((char_u*)fInputValue, (char_u*)fInputControl->Text(), IOSIZE - 1); ++ ++ if(Lock()) ++ Quit(); ++ ++ return retValue; ++} ++ ++void VimDialog::MessageReceived(BMessage *msg) ++{ ++ int32 which = 0; ++ if(msg->what != kVimDialogButtonMsg || ++ msg->FindInt32("which", &which) != B_OK) ++ return BWindow::MessageReceived(msg); ++ ++ fDialogValue = which; ++ delete_sem(fDialogSem); ++ fDialogSem = -1; ++} ++ ++BButton* VimDialog::_CreateButton(int32 which, const char* label) ++{ ++ BMessage *message = new BMessage(kVimDialogButtonMsg); ++ message->AddInt32("which", which); ++ ++ BRect rect(0, 0, 0, 0); ++ BString name; ++ name << "_b" << which << "_"; ++ ++ BButton* button = new BButton(rect, name.String(), label, message, ++ B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); ++ ++ float width = 0.f, height = 0.f; ++ button->GetPreferredSize(&width, &height); ++ button->ResizeTo(width, height); ++ ++ return button; ++} ++ ++VimDialog::View::View(BRect frame) ++ : BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), ++ fIconBitmap(NULL) ++{ ++ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); ++} ++ ++VimDialog::View::~View() ++{ ++ delete fIconBitmap; ++} ++ ++void VimDialog::View::Draw(BRect updateRect) ++{ ++ BRect stripeRect = Bounds(); ++ stripeRect.right = kVimDialogIconStripeWidth; ++ SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); ++ FillRect(stripeRect); ++ ++ if(fIconBitmap == NULL) ++ return; ++ ++ SetDrawingMode(B_OP_ALPHA); ++ SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); ++ DrawBitmapAsync(fIconBitmap, BPoint(18, 6)); ++} ++ ++void VimDialog::View::InitIcon(int32 type) ++{ ++ if(type == VIM_GENERIC) ++ return; ++ ++ BPath path; ++ status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path); ++ if(status != B_OK) { ++ fprintf(stderr, "Cannot retrieve app info:%s\n", strerror(status)); ++ return; ++ } ++ ++ path.Append("app_server"); ++ ++ BFile file(path.Path(), O_RDONLY); ++ if(file.InitCheck() != B_OK) { ++ fprintf(stderr, "App file assignment failed:%s\n", ++ strerror(file.InitCheck())); ++ return; ++ } ++ ++ BResources resources(&file); ++ if(resources.InitCheck() != B_OK) { ++ fprintf(stderr, "App server resources assignment failed:%s\n", ++ strerror(resources.InitCheck())); ++ return; ++ } ++ ++ const char *name = ""; ++ switch(type) { ++ case VIM_ERROR: name = "stop"; break; ++ case VIM_WARNING: name = "warn"; break; ++ case VIM_INFO: name = "info"; break; ++ case VIM_QUESTION: name = "idea"; break; ++ default: return; ++ } ++ ++ int32 iconSize = 32; ++ fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32); ++ if(fIconBitmap == NULL || fIconBitmap->InitCheck() != B_OK) { ++ fprintf(stderr, "Icon bitmap allocation failed:%s\n", ++ (fIconBitmap == NULL) ? "null" : strerror(fIconBitmap->InitCheck())); ++ return; ++ } ++ ++ size_t size = 0; ++ const uint8* iconData = NULL; ++ // try vector icon first? ++ iconData = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, name, &size); ++ if(iconData != NULL && BIconUtils::GetVectorIcon(iconData, size, fIconBitmap) == B_OK) ++ return; ++ ++ // try bitmap icon now ++ iconData = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE, name, &size); ++ if(iconData == NULL) { ++ fprintf(stderr, "Bitmap icon resource not found\n"); ++ delete fIconBitmap; ++ fIconBitmap = NULL; ++ return; ++ } ++ ++ if(fIconBitmap->ColorSpace() != B_CMAP8) ++ BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap); ++} ++ ++const unsigned int kVimDialogOKButtonMsg = 'FDOK'; ++const unsigned int kVimDialogCancelButtonMsg = 'FDCN'; ++const unsigned int kVimDialogSizeInputMsg = 'SICH'; ++const unsigned int kVimDialogFamilySelectMsg = 'MSFM'; ++const unsigned int kVimDialogStyleSelectMsg = 'MSST'; ++const unsigned int kVimDialogSizeSelectMsg = 'MSSZ'; ++ ++VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size) ++: BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, ++ B_NOT_CLOSABLE | B_NOT_RESIZABLE | ++ B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS) ++ , fStatus(B_NO_INIT) ++ , fDialogSem(-1) ++ , fDialogValue(false) ++ , fFamily(family) ++ , fStyle(style) ++ , fSize(size) ++ , fFontSize(*size) ++ , fPreview(0) ++ , fFamiliesList(0) ++ , fStylesList(0) ++ , fSizesList(0) ++ , fSizesInput(0) ++{ ++ strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH); ++ strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH); ++ ++ // "client" area view ++ BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES, ++ B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED, ++ B_PLAIN_BORDER); ++ AddChild(clientBox); ++ ++ // client view ++ BRect RC = clientBox->Bounds(); ++ RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY); ++ BRect rc(RC.LeftTop(), RC.LeftTop()); ++ ++ // at first create all controls ++ fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono"); ++ clientBox->AddChild(fPreview); ++ ++ BBox* boxDivider = new BBox(rc, B_EMPTY_STRING, ++ B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER); ++ clientBox->AddChild(boxDivider); ++ ++ BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:"); ++ clientBox->AddChild(labelFamily); ++ labelFamily->ResizeToPreferred(); ++ ++ BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:"); ++ clientBox->AddChild(labelStyle); ++ labelStyle->ResizeToPreferred(); ++ ++ BStringView *labelSize = new BStringView(rc, "labelSize", "Size:"); ++ clientBox->AddChild(labelSize); ++ labelSize->ResizeToPreferred(); ++ ++ fFamiliesList = new BListView(rc, "listFamily", ++ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES); ++ BScrollView *scrollFamilies = new BScrollView("scrollFamily", ++ fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true); ++ clientBox->AddChild(scrollFamilies); ++ ++ fStylesList= new BListView(rc, "listStyles", ++ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES); ++ BScrollView *scrollStyles = new BScrollView("scrollStyle", ++ fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true); ++ clientBox->AddChild(scrollStyles); ++ ++ fSizesInput = new BTextControl(rc, "inputSize", NULL, "???", ++ new BMessage(kVimDialogSizeInputMsg)); ++ clientBox->AddChild(fSizesInput); ++ fSizesInput->ResizeToPreferred(); ++ ++ fSizesList = new BListView(rc, "listSizes", ++ B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES); ++ BScrollView *scrollSizes = new BScrollView("scrollSize", ++ fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true); ++ clientBox->AddChild(scrollSizes); ++ ++ BButton *buttonOK = new BButton(rc, "buttonOK", "OK", ++ new BMessage(kVimDialogOKButtonMsg)); ++ clientBox->AddChild(buttonOK); ++ buttonOK->ResizeToPreferred(); ++ ++ BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel", ++ new BMessage(kVimDialogCancelButtonMsg)); ++ clientBox->AddChild(buttonCancel); ++ buttonCancel->ResizeToPreferred(); ++ ++ // layout controls ++ float lineHeight = labelFamily->Bounds().Height(); ++ float previewHeight = lineHeight * 3; ++ float offsetYLabels = previewHeight + kVimDialogSpacingY; ++ float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2; ++ float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2; ++ float listsHeight = lineHeight * 9; ++ float offsetYButtons = offsetYLists + listsHeight + kVimDialogSpacingY; ++ float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height(); ++ float familiesWidth = labelFamily->Bounds().Width() * 5; ++ float offsetXStyles = familiesWidth + kVimDialogSpacingX; ++ float stylesWidth = labelStyle->Bounds().Width() * 4; ++ float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX; ++ float sizesWidth = labelSize->Bounds().Width() * 2; ++ float maxControlsWidth = offsetXSizes + sizesWidth; ++ ++ ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2, ++ maxControlsHeight + kVimDialogSpacingY * 2); ++ ++ BRect rcVim = gui.vimWindow->Frame(); ++ MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2, ++ rcVim.top + (rcVim.Height() - Frame().Height()) / 2); ++ ++ fPreview->ResizeTo(maxControlsWidth, previewHeight); ++ fPreview->SetAlignment(B_ALIGN_CENTER); ++ ++ boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2); ++ boxDivider->ResizeTo(maxControlsWidth, 1.f); ++ ++ labelFamily->MoveBy(0.f, offsetYLabels); ++ labelStyle->MoveBy(offsetXStyles, offsetYLabels); ++ labelSize->MoveBy(offsetXSizes, offsetYLabels); ++ ++ // text control alignment issues ++ float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width(); ++ float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width(); ++ ++ scrollFamilies->MoveBy(0.f, offsetYLists); ++ scrollStyles->MoveBy(offsetXStyles, offsetYLists); ++ fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2); ++ scrollSizes->MoveBy(offsetXSizes, offsetYSizes); ++ ++ fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER); ++ ++ scrollFamilies->ResizeTo(familiesWidth, listsHeight); ++ scrollStyles->ResizeTo(stylesWidth, listsHeight); ++ fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height()); ++ scrollSizes->ResizeTo(sizesWidth, ++ listsHeight - (offsetYSizes - offsetYLists)); ++ ++ buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons); ++ buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width() ++ - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons); ++ ++ // fill lists ++ int selIndex = -1; ++ int count = count_font_families(); ++ for (int i = 0; i < count; i++) { ++ font_family family; ++ if (get_font_family(i, &family ) == B_OK) { ++ fFamiliesList->AddItem(new BStringItem((const char*)family)); ++ if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0) ++ selIndex = i; ++ } ++ } ++ ++ if (selIndex >= 0) { ++ fFamiliesList->Select(selIndex); ++ fFamiliesList->ScrollToSelection(); ++ } ++ ++ _UpdateFontStyles(); ++ ++ selIndex = -1; ++ for (int size = 8, index = 0; size <= 18; size++, index++) { ++ BString str; ++ str << size; ++ fSizesList->AddItem(new BStringItem(str)); ++ if (size == fFontSize) ++ selIndex = index; ++ ++ } ++ ++ if (selIndex >= 0) { ++ fSizesList->Select(selIndex); ++ fSizesList->ScrollToSelection(); ++ } ++ ++ fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg)); ++ fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg)); ++ fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg)); ++ fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg)); ++ ++ _UpdateSizeInputPreview(); ++ _UpdateFontPreview(); ++ ++ fStatus = B_OK; ++} ++ ++VimSelectFontDialog::~VimSelectFontDialog() ++{ ++ _CleanList(fFamiliesList); ++ _CleanList(fStylesList); ++ _CleanList(fSizesList); ++ ++ if (fDialogSem > B_OK) ++ delete_sem(fDialogSem); ++} ++ ++ void ++VimSelectFontDialog::_CleanList(BListView* list) ++{ ++ while(0 < list->CountItems()) ++ delete (dynamic_cast(list->RemoveItem((int32)0))); ++} ++ ++ bool ++VimSelectFontDialog::Go() ++{ ++ if (fStatus != B_OK) { ++ Quit(); ++ return NOFONT; ++ } ++ ++ fDialogSem = create_sem(0, "VimFontSelectDialogSem"); ++ if(fDialogSem < B_OK) { ++ Quit(); ++ return fDialogValue; ++ } ++ ++ Show(); ++ ++ while(acquire_sem(fDialogSem) == B_INTERRUPTED); ++ ++ bool retValue = fDialogValue; ++ ++ if(Lock()) ++ Quit(); ++ ++ return retValue; ++} ++ ++ ++void VimSelectFontDialog::_UpdateFontStyles() ++{ ++ _CleanList(fStylesList); ++ ++ int32 selIndex = -1; ++ int32 count = count_font_styles(fFontFamily); ++ for (int32 i = 0; i < count; i++) { ++ font_style style; ++ uint32 flags = 0; ++ if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) { ++ fStylesList->AddItem(new BStringItem((const char*)style)); ++ if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0) ++ selIndex = i; ++ } ++ } ++ ++ if (selIndex >= 0) { ++ fStylesList->Select(selIndex); ++ fStylesList->ScrollToSelection(); ++ } else ++ fStylesList->Select(0); ++} ++ ++ ++void VimSelectFontDialog::_UpdateSizeInputPreview() ++{ ++ char buf[10] = {0}; ++ vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize); ++ fSizesInput->SetText(buf); ++} ++ ++ ++void VimSelectFontDialog::_UpdateFontPreview() ++{ ++ BFont font; ++ fPreview->GetFont(&font); ++ font.SetSize(fFontSize); ++ font.SetFamilyAndStyle(fFontFamily, fFontStyle); ++ fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE); ++ ++ BString str; ++ str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt."; ++ fPreview->SetText(str); ++} ++ ++ ++ bool ++VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize) ++{ ++ int32 index = list->CurrentSelection(); ++ if (index < 0) ++ return false; ++ BStringItem* item = (BStringItem*)list->ItemAt(index); ++ if (item == NULL) ++ return false; ++ strncpy(text, item->Text(), textSize); ++ return true; ++} ++ ++ ++void VimSelectFontDialog::MessageReceived(BMessage *msg) ++{ ++ switch (msg->what) { ++ case kVimDialogOKButtonMsg: ++ strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH); ++ strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH); ++ *fSize = fFontSize; ++ fDialogValue = true; ++ case kVimDialogCancelButtonMsg: ++ delete_sem(fDialogSem); ++ fDialogSem = -1; ++ return; ++ case B_KEY_UP: ++ { ++ int32 key = 0; ++ if (msg->FindInt32("raw_char", &key) == B_OK ++ && key == B_ESCAPE) { ++ delete_sem(fDialogSem); ++ fDialogSem = -1; ++ } ++ } ++ break; ++ ++ case kVimDialogFamilySelectMsg: ++ if (_UpdateFromListItem(fFamiliesList, ++ fFontFamily, B_FONT_FAMILY_LENGTH)) { ++ _UpdateFontStyles(); ++ _UpdateFontPreview(); ++ } ++ break; ++ case kVimDialogStyleSelectMsg: ++ if (_UpdateFromListItem(fStylesList, ++ fFontStyle, B_FONT_STYLE_LENGTH)) ++ _UpdateFontPreview(); ++ break; ++ case kVimDialogSizeSelectMsg: ++ { ++ char buf[10] = {0}; ++ if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) { ++ float size = atof(buf); ++ if (size > 0.f) { ++ fFontSize = size; ++ _UpdateSizeInputPreview(); ++ _UpdateFontPreview(); ++ } ++ } ++ } ++ break; ++ case kVimDialogSizeInputMsg: ++ { ++ float size = atof(fSizesInput->Text()); ++ if (size > 0.f) { ++ fFontSize = size; ++ _UpdateFontPreview(); ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return BWindow::MessageReceived(msg); ++} ++ ++#endif /* FEAT_GUI_DIALOG */ ++ ++#ifdef FEAT_TOOLBAR ++ ++// some forward declaration required by toolbar functions... ++static BMessage * MenuMessage(vimmenu_T *menu); ++ ++VimToolbar::VimToolbar(BRect frame, const char *name) : ++ BBox(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER) ++{ ++} ++ ++VimToolbar::~VimToolbar() ++{ ++ int32 count = fButtonsList.CountItems(); ++ for(int32 i = 0; i < count; i++) ++ delete (BPictureButton*)fButtonsList.ItemAt(i); ++ fButtonsList.MakeEmpty(); ++ ++ delete normalButtonsBitmap; ++ delete grayedButtonsBitmap; ++ normalButtonsBitmap = NULL; ++ grayedButtonsBitmap = NULL; ++} ++ ++ void ++VimToolbar::AttachedToWindow() ++{ ++ BBox::AttachedToWindow(); ++ ++ SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); ++} ++ ++ float ++VimToolbar::ToolbarHeight() const ++{ ++ float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height(); ++ return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1; ++} ++ ++ bool ++VimToolbar::ModifyBitmapToGrayed(BBitmap *bitmap) ++{ ++ float height = bitmap->Bounds().Height(); ++ float width = bitmap->Bounds().Width(); ++ ++ rgb_color *bits = (rgb_color*)bitmap->Bits(); ++ int32 pixels = bitmap->BitsLength() / 4; ++ for(int32 i = 0; i < pixels; i++) { ++ bits[i].red = bits[i].green = ++ bits[i].blue = ((uint32)bits[i].red + bits[i].green + bits[i].blue) / 3; ++ bits[i].alpha /= 4; ++ } ++ ++ return true; ++} ++ ++ bool ++VimToolbar::PrepareButtonBitmaps() ++{ ++ // first try to load potentially customized $VIRUNTIME/bitmaps/builtin-tools.png ++ normalButtonsBitmap = LoadVimBitmap("builtin-tools.png"); ++ if(normalButtonsBitmap == NULL) ++ // customized not found? dig application resources for "builtin-tools" one ++ normalButtonsBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "builtin-tools"); ++ ++ if(normalButtonsBitmap == NULL) ++ return false; ++ ++ BMessage archive; ++ normalButtonsBitmap->Archive(&archive); ++ ++ grayedButtonsBitmap = new BBitmap(&archive); ++ if(grayedButtonsBitmap == NULL) ++ return false; ++ ++ // modify grayed bitmap ++ ModifyBitmapToGrayed(grayedButtonsBitmap); ++ ++ return true; ++} ++ ++BBitmap *VimToolbar::LoadVimBitmap(const char* fileName) ++{ ++ BBitmap *bitmap = NULL; ++ ++ int mustfree = 0; ++ char_u* runtimePath = vim_getenv((char_u*)"VIMRUNTIME", &mustfree); ++ if(runtimePath != NULL && fileName != NULL) { ++ BString strPath((char*)runtimePath); ++ strPath << "/bitmaps/" << fileName; ++ bitmap = BTranslationUtils::GetBitmap(strPath.String()); ++ } ++ ++ if(mustfree) ++ vim_free(runtimePath); ++ ++ return bitmap; ++} ++ ++ bool ++VimToolbar::GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed) ++{ ++ float size = bitmapFrom->Bounds().Height() + 1.; ++ ++ BView view(BRect(0, 0, size, size), "", 0, 0); ++ ++ AddChild(&view); ++ view.BeginPicture(pictureTo); ++ ++ view.SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); ++ view.FillRect(view.Bounds()); ++ view.SetDrawingMode(B_OP_OVER); ++ ++ BRect source(0, 0, size - 1, size - 1); ++ BRect destination(source); ++ ++ source.OffsetBy(size * index, 0); ++ destination.OffsetBy(ButtonMargin, ButtonMargin); ++ ++ view.DrawBitmap(bitmapFrom, source, destination); ++ ++ if(pressed) { ++ rgb_color shineColor = ui_color(B_SHINE_COLOR); ++ rgb_color shadowColor = ui_color(B_SHADOW_COLOR); ++ size += ButtonMargin * 2 - 1; ++ view.BeginLineArray(4); ++ view.AddLine(BPoint(0, 0), BPoint(size, 0), shadowColor); ++ view.AddLine(BPoint(size, 0), BPoint(size, size), shineColor); ++ view.AddLine(BPoint(size, size), BPoint(0, size), shineColor); ++ view.AddLine(BPoint(0, size), BPoint(0, 0), shadowColor); ++ view.EndLineArray(); ++ } ++ ++ view.EndPicture(); ++ RemoveChild(&view); ++ ++ return true; ++} ++ ++ bool ++VimToolbar::AddButton(int32 index, vimmenu_T *menu) ++{ ++ BPictureButton *button = NULL; ++ if(!menu_is_separator(menu->name)) { ++ float size = normalButtonsBitmap ? ++ normalButtonsBitmap->Bounds().Height() + 1. + ButtonMargin * 2 : 18.; ++ BRect frame(0, 0, size, size); ++ BPicture pictureOn; ++ BPicture pictureOff; ++ BPicture pictureGray; ++ ++ if(menu->iconfile == NULL && menu->iconidx >= 0 && normalButtonsBitmap) { ++ GetPictureFromBitmap(&pictureOn, menu->iconidx, normalButtonsBitmap, true); ++ GetPictureFromBitmap(&pictureOff, menu->iconidx, normalButtonsBitmap, false); ++ GetPictureFromBitmap(&pictureGray, menu->iconidx, grayedButtonsBitmap, false); ++ } else { ++ ++ char_u buffer[MAXPATHL] = {0}; ++ BBitmap *bitmap = NULL; ++ ++ if(menu->iconfile) { ++ gui_find_iconfile(menu->iconfile, buffer, (char*)"png"); ++ bitmap = BTranslationUtils::GetBitmap((char*)buffer); ++ } ++ ++ if(bitmap == NULL && gui_find_bitmap(menu->name, buffer, (char*)"png") == OK) ++ bitmap = BTranslationUtils::GetBitmap((char*)buffer); ++ ++ if(bitmap == NULL) ++ bitmap = new BBitmap(BRect(0, 0, size, size), B_RGB32); ++ ++ GetPictureFromBitmap(&pictureOn, 0, bitmap, true); ++ GetPictureFromBitmap(&pictureOff, 0, bitmap, false); ++ ModifyBitmapToGrayed(bitmap); ++ GetPictureFromBitmap(&pictureGray, 0, bitmap, false); ++ ++ delete bitmap; ++ } ++ ++ button = new BPictureButton(frame, (char*)menu->name, ++ &pictureOff, &pictureOn, MenuMessage(menu)); ++ ++ button->SetDisabledOn(&pictureGray); ++ button->SetDisabledOff(&pictureGray); ++ ++ button->SetTarget(gui.vimTextArea); ++ ++ AddChild(button); ++ ++ menu->button = button; ++ } ++ ++ bool result = fButtonsList.AddItem(button, index); ++ InvalidateLayout(); ++ return result; ++} ++ ++ bool ++VimToolbar::RemoveButton(vimmenu_T *menu) ++{ ++ if(menu->button) { ++ if(fButtonsList.RemoveItem(menu->button)) { ++ delete menu->button; ++ menu->button = NULL; ++ } ++ } ++} ++ ++ bool ++VimToolbar::GrayButton(vimmenu_T *menu, int grey) ++{ ++ if(menu->button) { ++ int32 index = fButtonsList.IndexOf(menu->button); ++ if(index >= 0) ++ menu->button->SetEnabled(grey ? false : true); ++ } ++} ++ ++ void ++VimToolbar::InvalidateLayout() ++{ ++ int32 offset = ToolbarMargin; ++ int32 count = fButtonsList.CountItems(); ++ for(int32 i = 0; i < count; i++) { ++ BPictureButton *button = (BPictureButton *)fButtonsList.ItemAt(i); ++ if(button) { ++ button->MoveTo(offset, ToolbarMargin); ++ offset += button->Bounds().Width() + ToolbarMargin; ++ } else ++ offset += ToolbarMargin * 3; ++ } ++} ++ ++#endif /*FEAT_TOOLBAR*/ ++ ++#if defined(FEAT_GUI_TABLINE) ++ ++ float ++VimTabLine::TablineHeight() const ++{ ++// float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height(); ++// return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1; ++ return TabHeight();// + ToolbarMargin; ++} ++ ++void ++VimTabLine::MouseDown(BPoint point) ++{ ++ if(!gui_mch_showing_tabline()) ++ return; ++ ++ BMessage *m = Window()->CurrentMessage(); ++ assert(m); ++ ++ int32 buttons = 0; ++ m->FindInt32("buttons", &buttons); ++ ++ int32 clicks = 0; ++ m->FindInt32("clicks", &clicks); ++ ++ int index = 0; // 0 means here - no tab found ++ for (int i = 0; i < CountTabs(); i++) { ++ if(TabFrame(i).Contains(point)) { ++ index = i + 1; // indexes are 1-based ++ break; ++ } ++ } ++ ++ int event = -1; ++ ++ if ((buttons & B_PRIMARY_MOUSE_BUTTON) && clicks > 1) ++ // left button double click on - create new tab ++ event = TABLINE_MENU_NEW; ++ ++ else if (buttons & B_TERTIARY_MOUSE_BUTTON) ++ // middle button click - close the pointed tab ++ // or create new one in case empty space ++ event = index > 0 ? TABLINE_MENU_CLOSE : TABLINE_MENU_NEW; ++ ++ else if (buttons & B_SECONDARY_MOUSE_BUTTON) { ++ // right button click - show context menu ++ BPopUpMenu* popUpMenu = new BPopUpMenu("tabLineContextMenu", false, false); ++ popUpMenu->AddItem(new BMenuItem(_("Close tabi R"), new BMessage(TABLINE_MENU_CLOSE))); ++ popUpMenu->AddItem(new BMenuItem(_("New tab T"), new BMessage(TABLINE_MENU_NEW))); ++ popUpMenu->AddItem(new BMenuItem(_("Open tab..."), new BMessage(TABLINE_MENU_OPEN))); ++ ++ ConvertToScreen(&point); ++ BMenuItem* item = popUpMenu->Go(point); ++ if (item != NULL) { ++ event = item->Command(); ++ } ++ ++ delete popUpMenu; ++ ++ } else { ++ // default processing ++ BTabView::MouseDown(point); ++ return; ++ } ++ ++ if (event < 0) ++ return; ++ ++ VimTablineMenuMsg tmm; ++ tmm.index = index; ++ tmm.event = event; ++ write_port(gui.vdcmp, VimMsg::TablineMenu, &tmm, sizeof(tmm)); ++} ++ ++void ++VimTabLine::VimTab::Select(BView* owner) ++{ ++ BTab::Select(owner); ++ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ if(tabLine != NULL) { ++ ++ int32 i = 0; ++ for (; i < tabLine->CountTabs(); i++) ++ if(this == tabLine->TabAt(i)) ++ break; ++ ++// printf("%d:%d:%s\n", i, tabLine->CountTabs(), tabLine->TabAt(i)->Label()); ++ if(i < tabLine->CountTabs()) { ++ VimTablineMsg tm; ++ tm.index = i + 1; ++ write_port(gui.vdcmp, VimMsg::Tabline, &tm, sizeof(tm)); ++ } ++ } ++} ++ ++#endif // defined(FEAT_GUI_TABLINE) ++ ++/* ---------------- ---------------- */ ++ ++// some global variables ++static char appsig[] = "application/x-vnd.Haiku-Vim-8"; ++key_map *keyMap; ++char *keyMapChars; ++int main_exitcode = 127; ++ ++ status_t ++gui_haiku_process_event(bigtime_t timeout) ++{ ++ struct VimMsg vm; ++ int32 what; ++ ssize_t size; ++ ++ size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm), ++ B_TIMEOUT, timeout); ++ ++ if (size >= 0) { ++ switch (what) { ++ case VimMsg::Key: ++ { ++ char_u *string = vm.u.Key.chars; ++ int len = vm.u.Key.length; ++ if (len == 1 && string[0] == Ctrl_chr('C')) { ++ trash_input_buf(); ++ got_int = TRUE; ++ } ++ ++#ifdef FEAT_MBYTE ++ if (vm.u.Key.csi_escape) ++#ifndef FEAT_MBYTE_IME ++ { ++ int i; ++ char_u buf[2]; ++ ++ for (i = 0; i < len; ++i) ++ { ++ add_to_input_buf(string + i, 1); ++ if (string[i] == CSI) ++ { ++ /* Turn CSI into K_CSI. */ ++ buf[0] = KS_EXTRA; ++ buf[1] = (int)KE_CSI; ++ add_to_input_buf(buf, 2); ++ } ++ } ++ } ++#else ++ add_to_input_buf_csi(string, len); ++#endif ++ else ++#endif ++ add_to_input_buf(string, len); ++ } ++ break; ++ case VimMsg::Resize: ++ gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height); ++ break; ++ case VimMsg::ScrollBar: ++ { ++ /* ++ * If loads of scroll messages queue up, use only the last ++ * one. Always report when the scrollbar stops dragging. ++ * This is not perfect yet anyway: these events are queued ++ * yet again, this time in the keyboard input buffer. ++ */ ++ int32 oldCount = ++ atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1); ++ if (oldCount <= 1 || !vm.u.Scroll.stillDragging) ++ gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(), ++ vm.u.Scroll.value, vm.u.Scroll.stillDragging); ++ } ++ break; ++#if defined(FEAT_MENU) ++ case VimMsg::Menu: ++ gui_menu_cb(vm.u.Menu.guiMenu); ++ break; ++#endif ++ case VimMsg::Mouse: ++ { ++ int32 oldCount; ++ if (vm.u.Mouse.button == MOUSE_DRAG) ++ oldCount = ++ atomic_add(&gui.vimTextArea->mouseDragEventCount, -1); ++ else ++ oldCount = 0; ++ if (oldCount <= 1) ++ gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x, ++ vm.u.Mouse.y, vm.u.Mouse.repeated_click, ++ vm.u.Mouse.modifiers); ++ } ++ break; ++ case VimMsg::MouseMoved: ++ { ++ gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y); ++ } ++ break; ++ case VimMsg::Focus: ++ gui.in_focus = vm.u.Focus.active; ++ /* XXX Signal that scrollbar dragging has stopped? ++ * This is needed because we don't get a MouseUp if ++ * that happens while outside the window... :-( ++ */ ++ if (gui.dragged_sb) { ++ gui.dragged_sb = SBAR_NONE; ++ } ++ // gui_update_cursor(TRUE, FALSE); ++ break; ++ case VimMsg::Refs: ++ ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir); ++ break; ++ case VimMsg::Tabline: ++ send_tabline_event(vm.u.Tabline.index); ++ break; ++ case VimMsg::TablineMenu: ++ send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event); ++ break; ++ default: ++ // unrecognised message, ignore it ++ break; ++ } ++ } ++ ++ /* ++ * If size < B_OK, it is an error code. ++ */ ++ return size; ++} ++ ++/* ++ * Here are some functions to protect access to ScreenLines[] and ++ * LineOffset[]. These are used from the window thread to respond ++ * to a Draw() callback. When that occurs, the window is already ++ * locked by the system. ++ * ++ * Other code that needs to lock is any code that changes these ++ * variables. Other read-only access, or access merely to the ++ * contents of the screen buffer, need not be locked. ++ * ++ * If there is no window, don't call Lock() but do succeed. ++ */ ++ ++ int ++vim_lock_screen() ++{ ++ return !gui.vimWindow || gui.vimWindow->Lock(); ++} ++ ++ void ++vim_unlock_screen() ++{ ++ if (gui.vimWindow) ++ gui.vimWindow->Unlock(); ++} ++ ++#define RUN_BAPPLICATION_IN_NEW_THREAD 0 ++ ++#if RUN_BAPPLICATION_IN_NEW_THREAD ++ ++ int32 ++run_vimapp(void *args) ++{ ++ VimApp app(appsig); ++ ++ gui.vimApp = &app; ++ app.Run(); /* Run until Quit() called */ ++ ++ return 0; ++} ++ ++#else ++ ++ int32 ++call_main(void *args) ++{ ++ struct MainArgs *ma = (MainArgs *)args; ++ ++ return main(ma->argc, ma->argv); ++} ++#endif ++ ++/* ++ * Parse the GUI related command-line arguments. Any arguments used are ++ * deleted from argv, and *argc is decremented accordingly. This is called ++ * when vim is started, whether or not the GUI has been started. ++ */ ++ void ++gui_mch_prepare( ++ int *argc, ++ char **argv) ++{ ++ /* ++ * We don't have any command line arguments for the BeOS GUI yet, ++ * but this is an excellent place to create our Application object. ++ */ ++ if (!gui.vimApp) { ++ thread_info tinfo; ++ get_thread_info(find_thread(NULL), &tinfo); ++ ++ /* May need the port very early on to process RefsReceived() */ ++ gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP"); ++ ++#if RUN_BAPPLICATION_IN_NEW_THREAD ++ thread_id tid = spawn_thread(run_vimapp, "vim VimApp", ++ tinfo.priority, NULL); ++ if (tid >= B_OK) { ++ resume_thread(tid); ++ } else { ++ getout(1); ++ } ++#else ++ MainArgs ma = { *argc, argv }; ++ thread_id tid = spawn_thread(call_main, "vim main()", ++ tinfo.priority, &ma); ++ if (tid >= B_OK) { ++ VimApp app(appsig); ++ ++ gui.vimApp = &app; ++ resume_thread(tid); ++ /* ++ * This is rather horrible. ++ * call_main will call main() again... ++ * There will be no infinite recursion since ++ * gui.vimApp is set now. ++ */ ++ app.Run(); /* Run until Quit() called */ ++ //fprintf(stderr, "app.Run() returned...\n"); ++ status_t dummy_exitcode; ++ (void)wait_for_thread(tid, &dummy_exitcode); ++ ++ /* ++ * This path should be the normal one taken to exit Vim. ++ * The main() thread calls mch_exit() which calls ++ * gui_mch_exit() which terminates its thread. ++ */ ++ exit(main_exitcode); ++ } ++#endif ++ } ++ /* Don't fork() when starting the GUI. Spawned threads are not ++ * duplicated with a fork(). The result is a mess. ++ */ ++ gui.dofork = FALSE; ++ /* ++ * XXX Try to determine whether we were started from ++ * the Tracker or the terminal. ++ * It would be nice to have this work, because the Tracker ++ * follows symlinks, so even if you double-click on gvim, ++ * when it is a link to vim it will still pass a command name ++ * of vim... ++ * We try here to see if stdin comes from /dev/null. If so, ++ * (or if there is an error, which should never happen) start the GUI. ++ * This does the wrong thing for vim - Run(); /* Run() unlocks but does not show */ ++ ++ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc ++ * file) */ ++ set_normal_colors(); ++ ++ /* ++ * Check that none of the colors are the same as the background color ++ */ ++ gui_check_colors(); ++ ++ /* Get the colors for the highlight groups (gui_check_colors() might have ++ * changed them) */ ++ highlight_gui_started(); /* re-init colors and fonts */ ++ ++ gui_mch_new_colors(); /* window must exist for this */ ++ ++ return OK; ++} ++ ++/* ++ * Called when the foreground or background color has been changed. ++ */ ++ void ++gui_mch_new_colors() ++{ ++ rgb_color rgb = GUI_TO_RGB(gui.back_pixel); ++ ++ if (gui.vimWindow->Lock()) { ++ gui.vimForm->SetViewColor(rgb); ++ // Does this not have too much effect for those small rectangles? ++ gui.vimForm->Invalidate(); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Open the GUI window which was created by a call to gui_mch_init(). ++ */ ++ int ++gui_mch_open() ++{ ++ if (gui_win_x != -1 && gui_win_y != -1) ++ gui_mch_set_winpos(gui_win_x, gui_win_y); ++ ++ /* Actually open the window */ ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->Show(); ++ gui.vimWindow->Unlock(); ++ return OK; ++ } ++ ++ return FAIL; ++} ++ ++ void ++gui_mch_exit(int vim_exitcode) ++{ ++ if (gui.vimWindow) { ++ thread_id tid = gui.vimWindow->Thread(); ++ gui.vimWindow->Lock(); ++ gui.vimWindow->Quit(); ++ /* Wait until it is truely gone */ ++ int32 exitcode; ++ wait_for_thread(tid, &exitcode); ++ } ++ delete_port(gui.vdcmp); ++#if !RUN_BAPPLICATION_IN_NEW_THREAD ++ /* ++ * We are in the main() thread - quit the App thread and ++ * quit ourselves (passing on the exitcode). Use a global since the ++ * value from exit_thread() is only used if wait_for_thread() is ++ * called in time (race condition). ++ */ ++#endif ++ if (gui.vimApp) { ++ VimTextAreaView::guiBlankMouse(false); ++ ++ main_exitcode = vim_exitcode; ++#if RUN_BAPPLICATION_IN_NEW_THREAD ++ thread_id tid = gui.vimApp->Thread(); ++ int32 exitcode; ++ gui.vimApp->Lock(); ++ gui.vimApp->Quit(); ++ gui.vimApp->Unlock(); ++ wait_for_thread(tid, &exitcode); ++#else ++ gui.vimApp->Lock(); ++ gui.vimApp->Quit(); ++ gui.vimApp->Unlock(); ++ /* suicide */ ++ exit_thread(vim_exitcode); ++#endif ++ } ++ /* If we are somehow still here, let mch_exit() handle things. */ ++} ++ ++/* ++ * Get the position of the top left corner of the window. ++ */ ++ int ++gui_mch_get_winpos(int *x, int *y) ++{ ++ if (gui.vimWindow->Lock()) { ++ BRect r; ++ r = gui.vimWindow->Frame(); ++ gui.vimWindow->Unlock(); ++ *x = (int)r.left; ++ *y = (int)r.top; ++ return OK; ++ } ++ else ++ return FAIL; ++} ++ ++/* ++ * Set the position of the top left corner of the window to the given ++ * coordinates. ++ */ ++ void ++gui_mch_set_winpos(int x, int y) ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->MoveTo(x, y); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Set the size of the window to the given width and height in pixels. ++ */ ++void ++gui_mch_set_shellsize( ++ int width, ++ int height, ++ int min_width, ++ int min_height, ++ int base_width, ++ int base_height, ++ int direction) //TODO: utilize? ++{ ++ /* ++ * We are basically given the size of the VimForm, if I understand ++ * correctly. Since it fills the window completely, this will also ++ * be the size of the window. ++ */ ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH); ++ ++ /* set size limits */ ++ float minWidth, maxWidth, minHeight, maxHeight; ++ ++ gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth, ++ &minHeight, &maxHeight); ++ gui.vimWindow->SetSizeLimits(min_width, maxWidth, ++ min_height, maxHeight); ++ ++ /* ++ * Set the resizing alignment depending on font size. ++ */ ++ gui.vimWindow->SetWindowAlignment( ++ B_PIXEL_ALIGNMENT, // window_alignment mode, ++ 1, // int32 h, ++ 0, // int32 hOffset = 0, ++ gui.char_width, // int32 width = 0, ++ base_width, // int32 widthOffset = 0, ++ 1, // int32 v = 0, ++ 0, // int32 vOffset = 0, ++ gui.char_height, // int32 height = 0, ++ base_height // int32 heightOffset = 0 ++ ); ++ ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_get_screen_dimensions( ++ int *screen_w, ++ int *screen_h) ++{ ++ BRect frame; ++ ++ { ++ BScreen screen(gui.vimWindow); ++ ++ if (screen.IsValid()) { ++ frame = screen.Frame(); ++ } else { ++ frame.right = 640; ++ frame.bottom = 480; ++ } ++ } ++ ++ /* XXX approximations... */ ++ *screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20; ++ *screen_h = (int) frame.bottom - gui.scrollbar_height ++#ifdef FEAT_MENU ++ - gui.menu_height ++#endif ++ - 30; ++} ++ ++void ++gui_mch_set_text_area_pos( ++ int x, ++ int y, ++ int w, ++ int h) ++{ ++ if (!gui.vimTextArea) ++ return; ++ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->MoveTo(x, y); ++ gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH); ++ ++/*#ifdef FEAT_GUI_TABLINE ++ if(gui.vimForm->TabLine() != NULL) { ++ gui.vimForm->TabLine()->ResizeTo(w, gui.vimForm->TablineHeight()); ++ } ++#endif //FEAT_GUI_TABLINE*/ ++ ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++ ++/* ++ * Scrollbar stuff: ++ */ ++ ++void ++gui_mch_enable_scrollbar( ++ scrollbar_T *sb, ++ int flag) ++{ ++ VimScrollBar *vsb = sb->id; ++ if (gui.vimWindow->Lock()) { ++ /* ++ * This function is supposed to be idempotent, but Show()/Hide() ++ * is not. Therefore we test if they are needed. ++ */ ++ if (flag) { ++ if (vsb->IsHidden()) { ++ vsb->Show(); ++ } ++ } else { ++ if (!vsb->IsHidden()) { ++ vsb->Hide(); ++ } ++ } ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_set_scrollbar_thumb( ++ scrollbar_T *sb, ++ int val, ++ int size, ++ int max) ++{ ++ if (gui.vimWindow->Lock()) { ++ VimScrollBar *s = sb->id; ++ if (max == 0) { ++ s->SetValue(0); ++ s->SetRange(0.0, 0.0); ++ } else { ++ s->SetProportion((float)size / (max + 1.0)); ++ s->SetSteps(1.0, size > 5 ? size - 2 : size); ++#ifndef SCROLL_PAST_END // really only defined in gui.c... ++ max = max + 1 - size; ++#endif ++ if (max < s->Value()) { ++ /* ++ * If the new maximum is lower than the current value, ++ * setting it would cause the value to be clipped and ++ * therefore a ValueChanged() call. ++ * We avoid this by setting the value first, because ++ * it presumably is <= max. ++ */ ++ s->SetValue(val); ++ s->SetRange(0.0, max); ++ } else { ++ /* ++ * In the other case, set the range first, since the ++ * new value might be higher than the current max. ++ */ ++ s->SetRange(0.0, max); ++ s->SetValue(val); ++ } ++ } ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_set_scrollbar_pos( ++ scrollbar_T *sb, ++ int x, ++ int y, ++ int w, ++ int h) ++{ ++ if (gui.vimWindow->Lock()) { ++ BRect winb = gui.vimWindow->Bounds(); ++ float vsbx = x, vsby = y; ++ VimScrollBar *vsb = sb->id; ++ vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH); ++ if(winb.right-(x+w)MoveTo(vsbx, vsby); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_create_scrollbar( ++ scrollbar_T *sb, ++ int orient) /* SBAR_VERT or SBAR_HORIZ */ ++{ ++ orientation posture = ++ (orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL; ++ ++ VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture); ++ if (gui.vimWindow->Lock()) { ++ vsb->SetTarget(gui.vimTextArea); ++ vsb->Hide(); ++ gui.vimForm->AddChild(vsb); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_destroy_scrollbar( ++ scrollbar_T *sb) ++{ ++ if (gui.vimWindow->Lock()) { ++ sb->id->RemoveSelf(); ++ delete sb->id; ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++ int ++gui_mch_is_blink_off(void) ++{ ++ return FALSE; ++} ++ ++/* ++ * Cursor blink functions. ++ * ++ * This is a simple state machine: ++ * BLINK_NONE not blinking at all ++ * BLINK_OFF blinking, cursor is not shown ++ * BLINK_ON blinking, cursor is shown ++ */ ++ ++#define BLINK_NONE 0 ++#define BLINK_OFF 1 ++#define BLINK_ON 2 ++ ++static int blink_state = BLINK_NONE; ++static long_u blink_waittime = 700; ++static long_u blink_ontime = 400; ++static long_u blink_offtime = 250; ++static int blink_timer = 0; ++ ++void ++gui_mch_set_blinking( ++ long waittime, ++ long on, ++ long off) ++{ ++ /* TODO */ ++ blink_waittime = waittime; ++ blink_ontime = on; ++ blink_offtime = off; ++} ++ ++/* ++ * Stop the cursor blinking. Show the cursor if it wasn't shown. ++ */ ++ void ++gui_mch_stop_blink() ++{ ++ /* TODO */ ++ if (blink_timer != 0) ++ { ++ //XtRemoveTimeOut(blink_timer); ++ blink_timer = 0; ++ } ++ if (blink_state == BLINK_OFF) ++ gui_update_cursor(TRUE, FALSE); ++ blink_state = BLINK_NONE; ++} ++ ++/* ++ * Start the cursor blinking. If it was already blinking, this restarts the ++ * waiting time and shows the cursor. ++ */ ++ void ++gui_mch_start_blink() ++{ ++ /* TODO */ ++ if (blink_timer != 0) ++ ;//XtRemoveTimeOut(blink_timer); ++ /* Only switch blinking on if none of the times is zero */ ++ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) ++ { ++ blink_timer = 1; //XtAppAddTimeOut(app_context, blink_waittime, ++ blink_state = BLINK_ON; ++ gui_update_cursor(TRUE, FALSE); ++ } ++} ++ ++/* ++ * Initialise vim to use the font with the given name. Return FAIL if the font ++ * could not be loaded, OK otherwise. ++ */ ++int ++gui_mch_init_font( ++ char_u *font_name, ++ int fontset) ++{ ++ if (gui.vimWindow->Lock()) ++ { ++ int rc = gui.vimTextArea->mchInitFont(font_name); ++ gui.vimWindow->Unlock(); ++ ++ return rc; ++ } ++ ++ return FAIL; ++} ++ ++ ++ int ++gui_mch_adjust_charsize() ++{ ++ return FAIL; ++} ++ ++ ++ int ++gui_mch_font_dialog(font_family* family, font_style* style, float* size) ++{ ++#if defined(FEAT_GUI_DIALOG) ++ //gui.vimWindow->Unlock(); ++ VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size); ++ return dialog->Go(); ++#else ++ return NOFONT; ++#endif /* FEAT_GUI_DIALOG */ ++} ++ ++ ++GuiFont ++gui_mch_get_font( ++ char_u *name, ++ int giveErrorIfMissing) ++{ ++ static VimFont *fontList = NULL; ++ ++ if (!gui.in_use) // can't do this when GUI not running ++ return NOFONT; ++ ++ // storage for locally modified name; ++ const int buff_size = B_FONT_FAMILY_LENGTH + B_FONT_STYLE_LENGTH + 20; ++ static char font_name[buff_size] = {0}; ++ font_family family = {0}; ++ font_style style = {0}; ++ float size = 0.f; ++ ++ if (name == 0 && be_fixed_font == 0) { ++ if(giveErrorIfMissing) ++ EMSG2("(fe0) default font is not defined", name); ++ return NOFONT; ++ } ++ ++ bool useSelectGUI = false; ++ if (name != NULL) ++ if (STRCMP(name, "*") == 0) { ++ useSelectGUI = true; ++ STRNCPY(font_name, hl_get_font_name(), buff_size); ++ } else ++ STRNCPY(font_name, name, buff_size); ++ ++ if (font_name[0] == 0) { ++ be_fixed_font->GetFamilyAndStyle(&family, &style); ++ size = be_fixed_font->Size(); ++ vim_snprintf(font_name, buff_size, ++ (char*)"%s/%s/%.0f", family, style, size); ++ } ++ ++ // replace underscores with spaces ++ char* end = 0; ++ while (end = strchr((char *)font_name, '_')) ++ *end = ' '; ++ ++ // store the name before strtok corrupt the buffer ;-) ++ static char buff[buff_size] = {0}; ++ STRNCPY(buff, font_name, buff_size); ++ STRNCPY(family, strtok(buff, "/\0"), B_FONT_FAMILY_LENGTH); ++ char* style_s = strtok(0, "/\0"); ++ if (style_s != 0) ++ STRNCPY(style, style_s, B_FONT_STYLE_LENGTH); ++ size = atof((style_s != 0) ? strtok(0, "/\0") : "0"); ++ ++ if (useSelectGUI) { ++ if(gui_mch_font_dialog(&family, &style, &size) == NOFONT) ++ return FAIL; ++ // compose for further processing ++ vim_snprintf(font_name, buff_size, ++ (char*)"%s/%s/%.0f", family, style, size); ++ hl_set_font_name((char_u*)font_name); ++ ++ // Set guifont to the name of the selected font. ++ char_u* new_p_guifont = alloc(STRLEN(font_name) + 1); ++ if (new_p_guifont != NULL) { ++ STRCPY(new_p_guifont, font_name); ++ vim_free(p_guifont); ++ p_guifont = new_p_guifont; ++ // Replace spaces in the font name with underscores. ++ for ( ; *new_p_guifont; ++new_p_guifont) ++ if (*new_p_guifont == ' ') ++ *new_p_guifont = '_'; ++ } ++ } ++ ++ VimFont *flp; ++ for (flp = fontList; flp; flp = flp->next) { ++ if (STRCMP(font_name, flp->name) == 0) { ++ flp->refcount++; ++ return (GuiFont)flp; ++ } ++ } ++ ++ VimFont *font = new VimFont(); ++ font->name = vim_strsave((char_u*)font_name); ++ ++ if(count_font_styles(family) <= 0) { ++ if (giveErrorIfMissing) ++ EMSG2("(fe0) Specified font %s is not found", font->name); ++ delete font; ++ return NOFONT; ++ } ++ ++ // Remember font in the static list for later use ++ font->next = fontList; ++ fontList = font; ++ ++ font->SetFamilyAndStyle(family, style); ++ if(size > 0.f) ++ font->SetSize(size); ++ ++ font->SetSpacing(B_FIXED_SPACING); ++ font->SetEncoding(B_UNICODE_UTF8); ++ ++ return (GuiFont)font; ++} ++ ++/* ++ * Set the current text font. ++ */ ++void ++gui_mch_set_font( ++ GuiFont font) ++{ ++ if (gui.vimWindow->Lock()) { ++ VimFont *vf = (VimFont *)font; ++ ++ gui.vimTextArea->SetFont(vf); ++ ++ gui.char_width = (int) vf->StringWidth("n"); ++ font_height fh; ++ vf->GetHeight(&fh); ++ gui.char_height = (int)(fh.ascent + 0.9999) ++ + (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999); ++ gui.char_ascent = (int)(fh.ascent + 0.9999); ++ ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* XXX TODO This is apparently never called... */ ++void ++gui_mch_free_font( ++ GuiFont font) ++{ ++ if(font == NOFONT) ++ return; ++ VimFont *f = (VimFont *)font; ++ if (--f->refcount <= 0) { ++ if (f->refcount < 0) ++ fprintf(stderr, "VimFont: refcount < 0\n"); ++ delete f; ++ } ++} ++ ++ char_u * ++gui_mch_get_fontname(GuiFont font, char_u *name) ++{ ++ if (name == NULL) ++ return NULL; ++ return vim_strsave(name); ++} ++ ++/* ++ * Adjust gui.char_height (after 'linespace' was changed). ++ */ ++ int ++gui_mch_adjust_charheight() ++{ ++ ++ //TODO: linespace support? ++ ++//#ifdef FEAT_XFONTSET ++// if (gui.fontset != NOFONTSET) ++// { ++// gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace; ++// gui.char_ascent = fontset_ascent((XFontSet)gui.fontset) ++// + p_linespace / 2; ++// } ++// else ++//#endif ++ { ++ VimFont *font = (VimFont *)gui.norm_font; ++ font_height fh = {0}; ++ font->GetHeight(&fh); ++ gui.char_height = (int)(fh.ascent + fh.descent + 0.5) + p_linespace; ++ gui.char_ascent = (int)(fh.ascent + 0.5) + p_linespace / 2; ++ } ++ return OK; ++} ++ ++/* ++ * Display the saved error message(s). ++ */ ++#ifdef USE_MCH_ERRMSG ++ void ++display_errors(void) ++{ ++ char *p; ++ char_u pError[256]; ++ ++ if (error_ga.ga_data == NULL) ++ return; ++ ++ /* avoid putting up a message box with blanks only */ ++ for (p = (char *)error_ga.ga_data; *p; ++p) ++ if (!isspace(*p)) ++ { ++ if (STRLEN(p) > 255) ++ pError[0] = 255; ++ else ++ pError[0] = STRLEN(p); ++ ++ STRNCPY(&pError[1], p, pError[0]); ++// ParamText(pError, nil, nil, nil); ++// Alert(128, nil); ++ break; ++ /* TODO: handled message longer than 256 chars ++ * use auto-sizeable alert ++ * or dialog with scrollbars (TextEdit zone) ++ */ ++ } ++ ga_clear(&error_ga); ++} ++#endif ++ ++ void ++gui_mch_getmouse(int *x, int *y) ++{ ++ fprintf(stderr, "gui_mch_getmouse"); ++ ++ /*int rootx, rooty, winx, winy; ++ Window root, child; ++ unsigned int mask; ++ ++ if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child, ++ &rootx, &rooty, &winx, &winy, &mask)) { ++ *x = winx; ++ *y = winy; ++ } else*/ { ++ *x = -1; ++ *y = -1; ++ } ++} ++ ++ void ++gui_mch_mousehide(int hide) ++{ ++ fprintf(stderr, "gui_mch_getmouse"); ++ // TODO ++} ++ ++ static int ++hex_digit(int c) ++{ ++ if (isdigit(c)) ++ return c - '0'; ++ c = TOLOWER_ASC(c); ++ if (c >= 'a' && c <= 'f') ++ return c - 'a' + 10; ++ return -1000; ++} ++ ++/* ++ * This function has been lifted from gui_w32.c and extended a bit. ++ * ++ * Return the Pixel value (color) for the given color name. ++ * Return INVALCOLOR for error. ++ */ ++guicolor_T ++gui_mch_get_color( ++ char_u *name) ++{ ++ typedef struct GuiColourTable ++ { ++ const char *name; ++ guicolor_T colour; ++ } GuiColourTable; ++ ++#define NSTATIC_COLOURS 50 //32 ++#define NDYNAMIC_COLOURS 33 ++#define NCOLOURS (NSTATIC_COLOURS + NDYNAMIC_COLOURS) ++ ++ static GuiColourTable table[NCOLOURS] = ++ { ++ {"Black", RGB(0x00, 0x00, 0x00)}, ++ {"DarkGray", RGB(0x80, 0x80, 0x80)}, ++ {"DarkGrey", RGB(0x80, 0x80, 0x80)}, ++ {"Gray", RGB(0xC0, 0xC0, 0xC0)}, ++ {"Grey", RGB(0xC0, 0xC0, 0xC0)}, ++ {"LightGray", RGB(0xD3, 0xD3, 0xD3)}, ++ {"LightGrey", RGB(0xD3, 0xD3, 0xD3)}, ++ {"Gray10", RGB(0x1A, 0x1A, 0x1A)}, ++ {"Grey10", RGB(0x1A, 0x1A, 0x1A)}, ++ {"Gray20", RGB(0x33, 0x33, 0x33)}, ++ {"Grey20", RGB(0x33, 0x33, 0x33)}, ++ {"Gray30", RGB(0x4D, 0x4D, 0x4D)}, ++ {"Grey30", RGB(0x4D, 0x4D, 0x4D)}, ++ {"Gray40", RGB(0x66, 0x66, 0x66)}, ++ {"Grey40", RGB(0x66, 0x66, 0x66)}, ++ {"Gray50", RGB(0x7F, 0x7F, 0x7F)}, ++ {"Grey50", RGB(0x7F, 0x7F, 0x7F)}, ++ {"Gray60", RGB(0x99, 0x99, 0x99)}, ++ {"Grey60", RGB(0x99, 0x99, 0x99)}, ++ {"Gray70", RGB(0xB3, 0xB3, 0xB3)}, ++ {"Grey70", RGB(0xB3, 0xB3, 0xB3)}, ++ {"Gray80", RGB(0xCC, 0xCC, 0xCC)}, ++ {"Grey80", RGB(0xCC, 0xCC, 0xCC)}, ++ {"Gray90", RGB(0xE5, 0xE5, 0xE5)}, ++ {"Grey90", RGB(0xE5, 0xE5, 0xE5)}, ++ {"White", RGB(0xFF, 0xFF, 0xFF)}, ++ {"DarkRed", RGB(0x80, 0x00, 0x00)}, ++ {"Red", RGB(0xFF, 0x00, 0x00)}, ++ {"LightRed", RGB(0xFF, 0xA0, 0xA0)}, ++ {"DarkBlue", RGB(0x00, 0x00, 0x80)}, ++ {"Blue", RGB(0x00, 0x00, 0xFF)}, ++ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)}, ++ {"DarkGreen", RGB(0x00, 0x80, 0x00)}, ++ {"Green", RGB(0x00, 0xFF, 0x00)}, ++ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)}, ++ {"DarkCyan", RGB(0x00, 0x80, 0x80)}, ++ {"Cyan", RGB(0x00, 0xFF, 0xFF)}, ++ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)}, ++ {"DarkMagenta", RGB(0x80, 0x00, 0x80)}, ++ {"Magenta", RGB(0xFF, 0x00, 0xFF)}, ++ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)}, ++ {"Brown", RGB(0x80, 0x40, 0x40)}, ++ {"Yellow", RGB(0xFF, 0xFF, 0x00)}, ++ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)}, ++ {"DarkYellow", RGB(0xBB, 0xBB, 0x00)}, ++ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, ++ {"Orange", RGB(0xFF, 0xA5, 0x00)}, ++ {"Purple", RGB(0xA0, 0x20, 0xF0)}, ++ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, ++ {"Violet", RGB(0xEE, 0x82, 0xEE)}, ++ // NOTE: some entries are zero-allocated for NDDYNAMIC_COLORS ++ // in this table! ++ }; ++ ++ static int endColour = NSTATIC_COLOURS; ++ static int newColour = NSTATIC_COLOURS; ++ ++ int r, g, b; ++ int i; ++ ++ if (name[0] == '#' && STRLEN(name) == 7) ++ { ++ /* Name is in "#rrggbb" format */ ++ r = hex_digit(name[1]) * 16 + hex_digit(name[2]); ++ g = hex_digit(name[3]) * 16 + hex_digit(name[4]); ++ b = hex_digit(name[5]) * 16 + hex_digit(name[6]); ++ if (r < 0 || g < 0 || b < 0) ++ return INVALCOLOR; ++ return RGB(r, g, b); ++ } ++ else ++ { ++ /* Check if the name is one of the colours we know */ ++ for (i = 0; i < endColour; i++) ++ if (STRICMP(name, table[i].name) == 0) ++ return table[i].colour; ++ } ++ ++ /* ++ * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt". ++ */ ++ { ++#define LINE_LEN 100 ++ FILE *fd; ++ char line[LINE_LEN]; ++ char_u *fname; ++ ++ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt"); ++ if (fname == NULL) ++ return INVALCOLOR; ++ ++ fd = fopen((char *)fname, "rt"); ++ vim_free(fname); ++ if (fd == NULL) ++ return INVALCOLOR; ++ ++ while (!feof(fd)) ++ { ++ int len; ++ int pos; ++ char *colour; ++ ++ fgets(line, LINE_LEN, fd); ++ len = strlen(line); ++ ++ if (len <= 1 || line[len-1] != '\n') ++ continue; ++ ++ line[len-1] = '\0'; ++ ++ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos); ++ if (i != 3) ++ continue; ++ ++ colour = line + pos; ++ ++ if (STRICMP(colour, name) == 0) ++ { ++ fclose(fd); ++ /* ++ * Now remember this colour in the table. ++ * A LRU scheme might be better but this is simpler. ++ * Or could use a growing array. ++ */ ++ guicolor_T gcolour = RGB(r,g,b); ++ ++ //NOTE: see note above in table allocation! We are working here with ++ // dynamically allocated names, not constant ones! ++ vim_free((char*)table[newColour].name); ++ table[newColour].name = (char *)vim_strsave((char_u *)colour); ++ table[newColour].colour = gcolour; ++ ++ newColour++; ++ if (newColour >= NCOLOURS) ++ newColour = NSTATIC_COLOURS; ++ if (endColour < NCOLOURS) ++ endColour = newColour; ++ ++ return gcolour; ++ } ++ } ++ ++ fclose(fd); ++ } ++ ++ return INVALCOLOR; ++} ++ ++/* ++ * Set the current text foreground color. ++ */ ++void ++gui_mch_set_fg_color( ++ guicolor_T color) ++{ ++ rgb_color rgb = GUI_TO_RGB(color); ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->SetHighColor(rgb); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Set the current text background color. ++ */ ++void ++gui_mch_set_bg_color( ++ guicolor_T color) ++{ ++ rgb_color rgb = GUI_TO_RGB(color); ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->SetLowColor(rgb); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Set the current text special color. ++ */ ++ void ++gui_mch_set_sp_color(guicolor_T color) ++{ ++ //prev_sp_color = color; ++} ++ ++void ++gui_mch_draw_string( ++ int row, ++ int col, ++ char_u *s, ++ int len, ++ int flags) ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->mchDrawString(row, col, s, len, flags); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Return OK if the key with the termcap name "name" is supported. ++ */ ++int ++gui_mch_haskey( ++ char_u *name) ++{ ++ int i; ++ ++ for (i = 0; special_keys[i].BeKeys != 0; i++) ++ if (name[0] == special_keys[i].vim_code0 && ++ name[1] == special_keys[i].vim_code1) ++ return OK; ++ return FAIL; ++} ++ ++ void ++gui_mch_beep() ++{ ++ ::beep(); ++} ++ ++ void ++gui_mch_flash(int msec) ++{ ++ /* Do a visual beep by reversing the foreground and background colors */ ++ ++ if (gui.vimWindow->Lock()) { ++ BRect rect = gui.vimTextArea->Bounds(); ++ ++ gui.vimTextArea->SetDrawingMode(B_OP_INVERT); ++ gui.vimTextArea->FillRect(rect); ++ gui.vimTextArea->Sync(); ++ snooze(msec * 1000); /* wait for a few msec */ ++ gui.vimTextArea->FillRect(rect); ++ gui.vimTextArea->SetDrawingMode(B_OP_COPY); ++ gui.vimTextArea->Flush(); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Invert a rectangle from row r, column c, for nr rows and nc columns. ++ */ ++void ++gui_mch_invert_rectangle( ++ int r, ++ int c, ++ int nr, ++ int nc) ++{ ++ BRect rect; ++ rect.left = FILL_X(c); ++ rect.top = FILL_Y(r); ++ rect.right = rect.left + nc * gui.char_width - PEN_WIDTH; ++ rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH; ++ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->SetDrawingMode(B_OP_INVERT); ++ gui.vimTextArea->FillRect(rect); ++ gui.vimTextArea->SetDrawingMode(B_OP_COPY); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Iconify the GUI window. ++ */ ++ void ++gui_mch_iconify() ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->Minimize(true); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++#if defined(FEAT_EVAL) || defined(PROTO) ++/* ++ * Bring the Vim window to the foreground. ++ */ ++ void ++gui_mch_set_foreground() ++{ ++ /* TODO */ ++} ++#endif ++ ++/* ++ * Set the window title ++ */ ++void ++gui_mch_settitle( ++ char_u *title, ++ char_u *icon) ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->SetTitle((char *)title); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Draw a cursor without focus. ++ */ ++ void ++gui_mch_draw_hollow_cursor(guicolor_T color) ++{ ++ gui_mch_set_fg_color(color); ++ ++ BRect r; ++ r.left = FILL_X(gui.col); ++ r.top = FILL_Y(gui.row); ++#ifdef FEAT_MBYTE ++ int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); //TODO-TODO ++ if(cells>=4) cells = 1; ++ r.right = r.left + cells*gui.char_width - PEN_WIDTH; ++#else ++ r.right = r.left + gui.char_width - PEN_WIDTH; ++#endif ++ r.bottom = r.top + gui.char_height - PEN_WIDTH; ++ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->StrokeRect(r); ++ gui.vimWindow->Unlock(); ++ //gui_mch_flush(); ++ } ++} ++ ++/* ++ * Draw part of a cursor, only w pixels wide, and h pixels high. ++ */ ++void ++gui_mch_draw_part_cursor( ++ int w, ++ int h, ++ guicolor_T color) ++{ ++ gui_mch_set_fg_color(color); ++ ++ BRect r; ++ r.left = ++#ifdef FEAT_RIGHTLEFT ++ /* vertical line should be on the right of current point */ ++ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : ++#endif ++ FILL_X(gui.col); ++ r.right = r.left + w - PEN_WIDTH; ++ r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH; ++ r.top = r.bottom - h + PEN_WIDTH; ++ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->FillRect(r); ++ gui.vimWindow->Unlock(); ++ //gui_mch_flush(); ++ } ++} ++ ++/* ++ * Catch up with any queued events. This may put keyboard input into the ++ * input buffer, call resize call-backs, trigger timers etc. If there is ++ * nothing in the event queue (& no timers pending), then we return ++ * immediately. ++ */ ++ void ++gui_mch_update() ++{ ++ gui_mch_flush(); ++ while (port_count(gui.vdcmp) > 0 && ++ !vim_is_input_buf_full() && ++ gui_haiku_process_event(0) >= B_OK) ++ /* nothing */ ; ++} ++ ++/* ++ * GUI input routine called by gui_wait_for_chars(). Waits for a character ++ * from the keyboard. ++ * wtime == -1 Wait forever. ++ * wtime == 0 This should never happen. ++ * wtime > 0 Wait wtime milliseconds for a character. ++ * Returns OK if a character was found to be available within the given time, ++ * or FAIL otherwise. ++ */ ++int ++gui_mch_wait_for_chars( ++ int wtime) ++{ ++ int focus; ++ bigtime_t until, timeout; ++ status_t st; ++ ++ if (wtime >= 0) { ++ timeout = wtime * 1000; ++ until = system_time() + timeout; ++ } else { ++ timeout = B_INFINITE_TIMEOUT; ++ } ++ ++ focus = gui.in_focus; ++ for (;;) ++ { ++ /* Stop or start blinking when focus changes */ ++ if (gui.in_focus != focus) ++ { ++ if (gui.in_focus) ++ gui_mch_start_blink(); ++ else ++ gui_mch_stop_blink(); ++ focus = gui.in_focus; ++ } ++ ++ gui_mch_flush(); ++ /* ++ * Don't use gui_mch_update() because then we will spin-lock until a ++ * char arrives, instead we use gui_haiku_process_event() to hang until ++ * an event arrives. No need to check for input_buf_full because we ++ * are returning as soon as it contains a single char. ++ */ ++ st = gui_haiku_process_event(timeout); ++ ++ if (input_available()) ++ return OK; ++ if (st < B_OK) /* includes B_TIMED_OUT */ ++ return FAIL; ++ ++ /* ++ * Calculate how much longer we're willing to wait for the ++ * next event. ++ */ ++ if (wtime >= 0) { ++ timeout = until - system_time(); ++ if (timeout < 0) ++ break; ++ } ++ } ++ return FAIL; ++ ++} ++ ++/* ++ * Output routines. ++ */ ++ ++/* ++ * Flush any output to the screen. This is typically called before ++ * the app goes to sleep. ++ */ ++ void ++gui_mch_flush() ++{ ++ // does this need to lock the window? Apparently not but be safe. ++ if (gui.vimWindow->Lock()) { ++ gui.vimWindow->Flush(); ++ gui.vimWindow->Unlock(); ++ } ++ return; ++} ++ ++/* ++ * Clear a rectangular region of the screen from text pos (row1, col1) to ++ * (row2, col2) inclusive. ++ */ ++void ++gui_mch_clear_block( ++ int row1, ++ int col1, ++ int row2, ++ int col2) ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->mchClearBlock(row1, col1, row2, col2); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++ void ++gui_mch_clear_all() ++{ ++ if (gui.vimWindow->Lock()) { ++ gui.vimTextArea->mchClearAll(); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Delete the given number of lines from the given row, scrolling up any ++ * text further down within the scroll region. ++ */ ++void ++gui_mch_delete_lines( ++ int row, ++ int num_lines) ++{ ++ gui.vimTextArea->mchDeleteLines(row, num_lines); ++} ++ ++/* ++ * Insert the given number of lines before the given row, scrolling down any ++ * following text within the scroll region. ++ */ ++void ++gui_mch_insert_lines( ++ int row, ++ int num_lines) ++{ ++ gui.vimTextArea->mchInsertLines(row, num_lines); ++} ++ ++#if defined(FEAT_MENU) || defined(PROTO) ++/* ++ * Menu stuff. ++ */ ++ ++void ++gui_mch_enable_menu( ++ int flag) ++{ ++ if (gui.vimWindow->Lock()) ++ { ++ BMenuBar *menubar = gui.vimForm->MenuBar(); ++ menubar->SetEnabled(flag); ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++void ++gui_mch_set_menu_pos( ++ int x, ++ int y, ++ int w, ++ int h) ++{ ++ /* It will be in the right place anyway */ ++} ++ ++/* ++ * Add a sub menu to the menu bar. ++ */ ++void ++gui_mch_add_menu( ++ vimmenu_T *menu, ++ int idx) ++{ ++ vimmenu_T *parent = menu->parent; ++ ++ // popup menu - just create it unattached ++ if (menu_is_popup(menu->name) && parent == NULL) { ++ BPopUpMenu* popUpMenu = new BPopUpMenu((const char*)menu->name, false, false); ++ menu->submenu_id = popUpMenu; ++ menu->id = NULL; ++ return; ++ } ++ ++ if (!menu_is_menubar(menu->name) ++ || (parent != NULL && parent->submenu_id == NULL)) ++ return; ++ ++ if (gui.vimWindow->Lock()) ++ { ++ /* Major re-write of the menu code, it was failing with memory corruption when ++ * we started loading multiple files (the Buffer menu) ++ * ++ * Note we don't use the preference values yet, all are inserted into the ++ * menubar on a first come-first served basis... ++ * ++ * richard@whitequeen.com jul 99 ++ */ ++ ++ BMenu *tmp; ++ ++ if ( parent ) ++ tmp = parent->submenu_id; ++ else ++ tmp = gui.vimForm->MenuBar(); ++ // make sure we don't try and add the same menu twice. The Buffers menu tries to ++ // do this and Be starts to crash... ++ ++ if ( ! tmp->FindItem((const char *) menu->dname)) { ++ ++ BMenu *bmenu = new BMenu((char *)menu->dname); ++ ++ menu->submenu_id = bmenu; ++ ++ // when we add a BMenu to another Menu, it creates the interconnecting BMenuItem ++ tmp->AddItem(bmenu); ++ ++ // Now its safe to query the menu for the associated MenuItem.... ++ menu->id = tmp->FindItem((const char *) menu->dname); ++ ++ } ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++ void ++gui_mch_toggle_tearoffs(int enable) ++{ ++ /* no tearoff menus */ ++} ++ ++ static BMessage * ++MenuMessage(vimmenu_T *menu) ++{ ++ BMessage *m = new BMessage('menu'); ++ m->AddPointer("VimMenu", (void *)menu); ++ ++ return m; ++} ++ ++/* ++ * Add a menu item to a menu ++ */ ++void ++gui_mch_add_menu_item( ++ vimmenu_T *menu, ++ int idx) ++{ ++ int mnemonic = 0; ++ vimmenu_T *parent = menu->parent; ++ ++ /* TODO: use menu->actext */ ++ /* This is difficult, since on Be, an accelerator must be a single char ++ * and a lot of Vim ones are the standard VI commands. ++ * ++ * Punt for Now... ++ * richard@whiequeen.com jul 99 ++ */ ++ if (gui.vimWindow->Lock()) ++ { ++#ifdef FEAT_TOOLBAR ++ if(menu_is_toolbar(parent->name)) { ++ VimToolbar *toolbar = gui.vimForm->ToolBar(); ++ if(toolbar != NULL) { ++ toolbar->AddButton(idx, menu); ++ } ++ } else ++#endif ++ ++ if (parent->submenu_id != NULL || menu_is_popup(parent->name)) { ++ if (menu_is_separator(menu->name)) { ++ BSeparatorItem *item = new BSeparatorItem(); ++ parent->submenu_id->AddItem(item); ++ menu->id = item; ++ menu->submenu_id = NULL; ++ } ++ else { ++ BMenuItem *item = new BMenuItem((char *)menu->dname, ++ MenuMessage(menu)); ++ item->SetTarget(gui.vimTextArea); ++ item->SetTrigger((char) menu->mnemonic); ++ parent->submenu_id->AddItem(item); ++ menu->id = item; ++ menu->submenu_id = NULL; ++ } ++ } ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Destroy the machine specific menu widget. ++ */ ++void ++gui_mch_destroy_menu( ++ vimmenu_T *menu) ++{ ++ if (gui.vimWindow->Lock()) ++ { ++#ifdef FEAT_TOOLBAR ++ if(menu->parent && menu_is_toolbar(menu->parent->name)) { ++ VimToolbar *toolbar = gui.vimForm->ToolBar(); ++ if(toolbar != NULL) { ++ toolbar->RemoveButton(menu); ++ } ++ } else ++#endif ++ { ++ assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0); ++ /* ++ * Detach this menu from its parent, so that it is not deleted ++ * twice once we get to delete that parent. ++ * Deleting a BMenuItem also deletes the associated BMenu, if any ++ * (which does not have any items anymore since they were ++ * removed and deleted before). ++ */ ++ BMenu *bmenu = menu->id->Menu(); ++ if (bmenu) ++ { ++ bmenu->RemoveItem(menu->id); ++ /* ++ * If we removed the last item from the menu bar, ++ * resize it out of sight. ++ */ ++ if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0) ++ { ++ bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN); ++ } ++ } ++ delete menu->id; ++ menu->id = NULL; ++ menu->submenu_id = NULL; ++ ++ gui.menu_height = (int) gui.vimForm->MenuHeight(); ++ } ++ gui.vimWindow->Unlock(); ++ } ++} ++ ++/* ++ * Make a menu either grey or not grey. ++ */ ++void ++gui_mch_menu_grey( ++ vimmenu_T *menu, ++ int grey) ++{ ++#ifdef FEAT_TOOLBAR ++ if(menu->parent && menu_is_toolbar(menu->parent->name)) { ++ if (gui.vimWindow->Lock()) { ++ VimToolbar *toolbar = gui.vimForm->ToolBar(); ++ if(toolbar != NULL) { ++ toolbar->GrayButton(menu, grey); ++ } ++ gui.vimWindow->Unlock(); ++ } ++ } else ++#endif ++ if (menu->id != NULL) ++ menu->id->SetEnabled(!grey); ++} ++ ++/* ++ * Make menu item hidden or not hidden ++ */ ++void ++gui_mch_menu_hidden( ++ vimmenu_T *menu, ++ int hidden) ++{ ++ if (menu->id != NULL) ++ menu->id->SetEnabled(!hidden); ++} ++ ++/* ++ * This is called after setting all the menus to grey/hidden or not. ++ */ ++ void ++gui_mch_draw_menubar() ++{ ++ /* Nothing to do in BeOS */ ++} ++ ++ void ++gui_mch_show_popupmenu(vimmenu_T *menu) ++{ ++ if (!menu_is_popup(menu->name) || menu->submenu_id == NULL) ++ return; ++ ++ BPopUpMenu* popupMenu = dynamic_cast(menu->submenu_id); ++ if (popupMenu == NULL) ++ return; ++ ++ BPoint point; ++ if(gui.vimWindow->Lock()) { ++ uint32 buttons = 0; ++ gui.vimTextArea->GetMouse(&point, &buttons); ++ gui.vimTextArea->ConvertToScreen(&point); ++ gui.vimWindow->Unlock(); ++ } ++ popupMenu->Go(point, true); ++} ++ ++#endif /* FEAT_MENU */ ++ ++/* Mouse stuff */ ++ ++#ifdef FEAT_CLIPBOARD ++/* ++ * Clipboard stuff, for cutting and pasting text to other windows. ++ */ ++char textplain[] = "text/plain"; ++char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype"; ++ ++/* ++ * Get the current selection and put it in the clipboard register. ++ */ ++ void ++clip_mch_request_selection(VimClipboard *cbd) ++{ ++ if (be_clipboard->Lock()) ++ { ++ BMessage *m = be_clipboard->Data(); ++ //m->PrintToStream(); ++ ++ char_u *string = NULL; ++ ssize_t stringlen = -1; ++ ++ if (m->FindData(textplain, B_MIME_TYPE, ++ (const void **)&string, &stringlen) == B_OK ++ || m->FindString("text", (const char **)&string) == B_OK) ++ { ++ if (stringlen == -1) ++ stringlen = STRLEN(string); ++ ++ int type; ++ char *seltype; ++ ssize_t seltypelen; ++ ++ /* ++ * Try to get the special vim selection type first ++ */ ++ if (m->FindData(vimselectiontype, B_MIME_TYPE, ++ (const void **)&seltype, &seltypelen) == B_OK) ++ { ++ switch (*seltype) ++ { ++ default: ++ case 'L': type = MLINE; break; ++ case 'C': type = MCHAR; break; ++#ifdef FEAT_VISUAL ++ case 'B': type = MBLOCK; break; ++#endif ++ } ++ } ++ else ++ { ++ /* Otherwise use heuristic as documented */ ++ type = memchr(string, stringlen, '\n') ? MLINE : MCHAR; ++ } ++ clip_yank_selection(type, string, (long)stringlen, cbd); ++ } ++ be_clipboard->Unlock(); ++ } ++} ++/* ++ * Make vim the owner of the current selection. ++ */ ++ void ++clip_mch_lose_selection(VimClipboard *cbd) ++{ ++ /* Nothing needs to be done here */ ++} ++ ++/* ++ * Make vim the owner of the current selection. Return OK upon success. ++ */ ++ int ++clip_mch_own_selection(VimClipboard *cbd) ++{ ++ /* ++ * Never actually own the clipboard. If another application sets the ++ * clipboard, we don't want to think that we still own it. ++ */ ++ return FAIL; ++} ++ ++/* ++ * Send the current selection to the clipboard. ++ */ ++ void ++clip_mch_set_selection(VimClipboard *cbd) ++{ ++ if (be_clipboard->Lock()) ++ { ++ be_clipboard->Clear(); ++ BMessage *m = be_clipboard->Data(); ++ assert(m); ++ ++ /* If the '*' register isn't already filled in, fill it in now */ ++ cbd->owned = TRUE; ++ clip_get_selection(cbd); ++ cbd->owned = FALSE; ++ ++ char_u *str = NULL; ++ long_u count; ++ int type; ++ ++ type = clip_convert_selection(&str, &count, cbd); ++ ++ if (type < 0) ++ return; ++ ++ m->AddData(textplain, B_MIME_TYPE, (void *)str, count); ++ ++ /* Add type of selection */ ++ char vtype; ++ switch (type) ++ { ++ default: ++ case MLINE: vtype = 'L'; break; ++ case MCHAR: vtype = 'C'; break; ++#ifdef FEAT_VISUAL ++ case MBLOCK: vtype = 'B'; break; ++#endif ++ } ++ m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1); ++ ++ vim_free(str); ++ ++ be_clipboard->Commit(); ++ be_clipboard->Unlock(); ++ } ++} ++ ++#endif /* FEAT_CLIPBOARD */ ++ ++#ifdef FEAT_BROWSE ++/* ++ * Pop open a file browser and return the file selected, in allocated memory, ++ * or NULL if Cancel is hit. ++ * saving - TRUE if the file will be saved to, FALSE if it will be opened. ++ * title - Title message for the file browser dialog. ++ * dflt - Default name of file. ++ * ext - Default extension to be added to files without extensions. ++ * initdir - directory in which to open the browser (NULL = current dir) ++ * filter - Filter for matched files to choose from. ++ * Has a format like this: ++ * "C Files (*.c)\0*.c\0" ++ * "All Files\0*.*\0\0" ++ * If these two strings were concatenated, then a choice of two file ++ * filters will be selectable to the user. Then only matching files will ++ * be shown in the browser. If NULL, the default allows all files. ++ * ++ * *NOTE* - the filter string must be terminated with TWO nulls. ++ */ ++char_u * ++gui_mch_browse( ++ int saving, ++ char_u *title, ++ char_u *dflt, ++ char_u *ext, ++ char_u *initdir, ++ char_u *filter) ++{ ++ gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL, ++ NULL, NULL, 0, false, ++ new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true); ++ ++ gui.vimApp->fBrowsedPath.Unset(); ++ ++ gui.vimApp->fFilePanel->Window()->SetTitle((char*)title); ++ gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir); ++ ++ gui.vimApp->fFilePanel->Show(); ++ ++ gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem"); ++ ++ while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED); ++ ++ char_u *fileName = NULL; ++ status_t result = gui.vimApp->fBrowsedPath.InitCheck(); ++ if(result == B_OK) { ++ fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path()); ++ } else ++ if(result != B_NO_INIT) { ++ fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n", ++ result, strerror(result)); ++ } ++ ++ delete gui.vimApp->fFilePanel; ++ gui.vimApp->fFilePanel = NULL; ++ ++ return fileName; ++} ++#endif /* FEAT_BROWSE */ ++ ++ ++#if defined(FEAT_GUI_DIALOG) ++ ++/* ++ * Create a dialog dynamically from the parameter strings. ++ * type = type of dialog (question, alert, etc.) ++ * title = dialog title. may be NULL for default title. ++ * message = text to display. Dialog sizes to accommodate it. ++ * buttons = '\n' separated list of button captions, default first. ++ * dfltbutton = number of default button. ++ * ++ * This routine returns 1 if the first button is pressed, ++ * 2 for the second, etc. ++ * ++ * 0 indicates Esc was pressed. ++ * -1 for unexpected error ++ * ++ * If stubbing out this fn, return 1. ++ */ ++ ++int ++gui_mch_dialog( ++ int type, ++ char_u *title, ++ char_u *message, ++ char_u *buttons, ++ int dfltbutton, ++ char_u *textfield, ++ int ex_cmd) ++{ ++ VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message, ++ (char*)buttons, dfltbutton, (char*)textfield, ex_cmd); ++ return dialog->Go(); ++} ++ ++#endif /* FEAT_GUI_DIALOG */ ++ ++ ++/* ++ * Return the RGB value of a pixel as long. ++ */ ++ guicolor_T ++gui_mch_get_rgb(guicolor_T pixel) ++{ ++ rgb_color rgb = GUI_TO_RGB(pixel); ++ ++ return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8) ++ + (rgb.blue & 0xff); ++} ++ ++ void ++gui_mch_setmouse(int x, int y) ++{ ++ TRACE(); ++ /* TODO */ ++} ++ ++#ifdef FEAT_MBYTE_IME ++ void ++im_set_position(int row, int col) ++{ ++ if(gui.vimWindow->Lock()) ++ { ++ gui.vimTextArea->DrawIMString(); ++ gui.vimWindow->Unlock(); ++ } ++ return; ++} ++ ++ void ++im_set_active(int activate) ++{ ++ //TODO: ++#if 0 ++ if(activate) ++ printf("IME ON\n"); ++ else ++ printf("IME OFF\n"); ++#endif ++ return; ++} ++ ++ int ++im_get_status() ++{ ++ //TODO: ++ return(1); ++} ++#endif ++ ++ void ++gui_mch_show_toolbar(int showit) ++{ ++ VimToolbar *toolbar = gui.vimForm->ToolBar(); ++ gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.; ++} ++ ++ void ++gui_mch_set_toolbar_pos(int x, int y, int w, int h) ++{ ++ VimToolbar *toolbar = gui.vimForm->ToolBar(); ++ if(toolbar != NULL) { ++ if (gui.vimWindow->Lock()) { ++ toolbar->MoveTo(x, y); ++ toolbar->ResizeTo(w - 1, h - 1); ++ gui.vimWindow->Unlock(); ++ } ++ } ++} ++ ++#if defined(FEAT_GUI_TABLINE) || defined(PROTO) ++ ++/* ++ * Show or hide the tabline. ++ */ ++ void ++gui_mch_show_tabline(int showit) ++{ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ ++ if (tabLine == NULL) ++ return; ++ ++ if (!showit != !gui.vimForm->IsShowingTabLine()) { ++ gui.vimForm->SetShowingTabLine(showit != 0); ++ gui.tabline_height = gui.vimForm->TablineHeight(); ++ } ++} ++ ++ void ++gui_mch_set_tabline_pos(int x, int y, int w, int h) ++{ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ if(tabLine != NULL) { ++ if (gui.vimWindow->Lock()) { ++ tabLine->MoveTo(x, y); ++ tabLine->ResizeTo(w - 1, h - 1); ++ gui.vimWindow->Unlock(); ++ } ++ } ++} ++ ++/* ++ * Return TRUE when tabline is displayed. ++ */ ++ int ++gui_mch_showing_tabline() ++{ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ return tabLine != NULL && gui.vimForm->IsShowingTabLine(); ++} ++ ++/* ++ * Update the labels of the tabline. ++ */ ++ void ++gui_mch_update_tabline() ++{ ++ tabpage_T *tp; ++ int nr = 0; ++ int curtabidx = 0; ++ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ ++ if (tabLine == NULL) ++ return; ++ ++ gui.vimWindow->Lock(); ++ ++ /* Add a label for each tab page. They all contain the same text area. */ ++ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) { ++ if (tp == curtab) ++ curtabidx = nr; ++ ++ BTab* tab = tabLine->TabAt(nr); ++ ++ if (tab == NULL) { ++ tab = new VimTabLine::VimTab(); ++ tabLine->AddTab(NULL, tab); ++ } ++ ++ get_tabline_label(tp, FALSE); ++ tab->SetLabel((const char*)NameBuff); ++ tabLine->Invalidate(); ++ } ++ ++ /* Remove any old labels. */ ++ while (nr < tabLine->CountTabs()) ++ tabLine->RemoveTab(nr); ++ ++ if(tabLine->Selection() != curtabidx) ++ tabLine->Select(curtabidx); ++ ++ gui.vimWindow->Unlock(); ++} ++ ++/* ++ * Set the current tab to "nr". First tab is 1. ++ */ ++ void ++gui_mch_set_curtab(int nr) ++{ ++ VimTabLine *tabLine = gui.vimForm->TabLine(); ++ if(tabLine == NULL) ++ return; ++ ++ gui.vimWindow->Lock(); ++ ++ if(tabLine->Selection() != nr -1) ++ tabLine->Select(nr -1); ++ ++ gui.vimWindow->Unlock(); ++} ++ ++#endif //FEAT_GUI_TABLINE +diff --git a/src/gui_haiku.h b/src/gui_haiku.h +new file mode 100644 +index 0000000..414d127 +--- /dev/null ++++ b/src/gui_haiku.h +@@ -0,0 +1,51 @@ ++/* vi:set ts=8 sts=4 sw=4: ++ * ++ * VIM - Vi IMproved by Bram Moolenaar ++ * GUI support by Olaf "Rhialto" Seibert ++ * ++ * Do ":help uganda" in Vim to read copying and usage conditions. ++ * Do ":help credits" in Vim to see a list of people who contributed. ++ * ++ * Haiku GUI. ++ * ++ * Based on "GUI support for the Buzzword Enhanced Operating System for PPC." ++ * ++ */ ++ ++/* ++ * This file must be acceptable both as C and C++. ++ * The BeOS API is defined in terms of C++, but some classes ++ * should be somewhat known in the common C code. ++ */ ++ ++/* System classes */ ++ ++struct BMenu; ++struct BMenuItem; ++struct BPictureButton; ++ ++/* Our own Vim-related classes */ ++ ++struct VimApp; ++struct VimFormView; ++struct VimTextAreaView; ++struct VimWindow; ++struct VimScrollBar; ++ ++/* Locking functions */ ++ ++extern int vim_lock_screen(); ++extern void vim_unlock_screen(); ++ ++#ifndef __cplusplus ++ ++typedef struct BMenu BMenu; ++typedef struct BMenuItem BMenuItem; ++typedef struct BPictureButton BPictureButton; ++typedef struct VimWindow VimWindow; ++typedef struct VimFormView VimFormView; ++typedef struct VimTextAreaView VimTextAreaView; ++typedef struct VimApp VimApp; ++typedef struct VimScrollBar VimScrollBar; ++ ++#endif +diff --git a/src/misc1.c b/src/misc1.c +index f7789ff..1ef3f2e 100644 +--- a/src/misc1.c ++++ b/src/misc1.c +@@ -14,6 +14,10 @@ + #include "vim.h" + #include "version.h" + ++#if defined(__HAIKU__) ++#include ++#endif ++ + static char_u *vim_version_dir(char_u *vimdir); + static char_u *remove_tail(char_u *p, char_u *pend, char_u *name); + #if defined(FEAT_CMDL_COMPL) +@@ -4228,7 +4232,16 @@ vim_getenv(char_u *name, int *mustfree) + + vimruntime = (STRCMP(name, "VIMRUNTIME") == 0); + if (!vimruntime && STRCMP(name, "VIM") != 0) +- return NULL; ++#if defined(__HAIKU__) ++ // special handling for user settings directory... ++ if(STRCMP(name, "BE_USER_SETTINGS") == 0) { ++ static char userSettingsPath[MAXPATHL] = {0}; ++ if(B_OK == find_directory(B_USER_SETTINGS_DIRECTORY, 0, ++ false, userSettingsPath, MAXPATHL)) ++ return userSettingsPath; ++ } else ++#endif ++ return NULL; + + /* + * When expanding $VIMRUNTIME fails, try using $VIM/vim or $VIM. +diff --git a/src/normal.c b/src/normal.c +index d78a53b..2e428d9 100644 +--- a/src/normal.c ++++ b/src/normal.c +@@ -2656,13 +2656,14 @@ do_mouse( + if (!is_click) + return FALSE; + #endif +-#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) ++#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU) + if (is_click || is_drag) + return FALSE; + #endif + #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ +- || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) ++ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \ ++ || defined(FEAT_GUI_HAIKU) + if (gui.in_use) + { + jump_flags = 0; +diff --git a/src/option.h b/src/option.h +index ecd70dc..87a50c3 100644 +--- a/src/option.h ++++ b/src/option.h +@@ -10,6 +10,8 @@ + * option.h: definition of global variables for settable options + */ + ++#ifndef _OPTION_H_ ++#define _OPTION_H_ + /* + * Default values for 'errorformat'. + * The "%f|%l| %m" one is used for when the contents of the quickfix window is +@@ -1181,5 +1183,7 @@ enum + , WV_COUNT /* must be the last one */ + }; + ++#endif //_OPTION_H_ ++ + /* Value for b_p_ul indicating the global value must be used. */ + #define NO_LOCAL_UNDOLEVEL -123456 +diff --git a/src/os_haiku.h b/src/os_haiku.h +new file mode 100644 +index 0000000..c9bfe75 +--- /dev/null ++++ b/src/os_haiku.h +@@ -0,0 +1,29 @@ ++/* vi:set ts=8 sts=4 sw=4: ++ * ++ * VIM - Vi IMproved by Bram Moolenaar ++ * Haiku port by Siarzhuk Zharski ++ * ++ * Do ":help uganda" in Vim to read copying and usage conditions. ++ * Do ":help credits" in Vim to see a list of people who contributed. ++ */ ++ ++/* ++ * os_haiku.h ++ */ ++ ++#define USE_TERM_CONSOLE ++ ++#define USR_VIM_DIR "$BE_USER_SETTINGS/vim" ++ ++#define USR_EXRC_FILE USR_VIM_DIR "/exrc" ++#define USR_VIMRC_FILE USR_VIM_DIR "/vimrc" ++#define USR_GVIMRC_FILE USR_VIM_DIR "/gvimrc" ++#define VIMINFO_FILE USR_VIM_DIR "/viminfo" ++ ++#ifdef RUNTIME_GLOBAL ++# define DFLT_RUNTIMEPATH USR_VIM_DIR "/vimfiles," RUNTIME_GLOBAL \ ++ ",$VIMRUNTIME," RUNTIME_GLOBAL "/after," USR_VIM_DIR "/vimfiles/after" ++#else ++# define DFLT_RUNTIMEPATH USR_VIM_DIR "/vimfiles," "$VIM/vimfiles" \ ++ ",$VIMRUNTIME," "$VIM/vimfiles/after," USR_VIM_DIR "/vimfiles/after" ++#endif +diff --git a/src/os_haiku.rdef b/src/os_haiku.rdef +new file mode 100644 +index 0000000..bf55aa9 +--- /dev/null ++++ b/src/os_haiku.rdef +@@ -0,0 +1,143 @@ ++/* ++ * os_haiku.rdef ++ */ ++ ++resource app_signature "application/x-vnd.Haiku-Vim-8"; ++ ++resource app_version { ++ major = @MAJOR@, ++ middle = @MIDDLE@, ++ minor = @MINOR@, ++ ++ variety = B_APPV_FINAL, ++ internal = 0, ++ ++ short_info = "VIM Editor", ++ long_info = "VI Improved Editor by Bram Moolenaar et al." ++}; ++ ++resource app_flags B_MULTIPLE_LAUNCH; ++ ++resource file_types message { ++ "types" = "text", ++ "types" = "text/plain", ++ "types" = "text/x-source-code", ++ "types" = "text/x-patch", ++ "types" = "text/html", ++ "types" = "text/xml", ++ "types" = "text/x-makefile", ++ "types" = "text/x-jamfile" ++}; ++ ++resource vector_icon { ++ $"6E636966050501020006023B8CFD3CB8E4BF59B63E2F604BACDB47A13E00FFFF" ++ $"FFFF909DA702000603BAF8BA3CE3F6BF8EB9BDA8484BC75C4AEA1200C1C7CC79" ++ $"D9E0E5FFC1C7CC020006020000003DC000C000000000004C000049FFFF00B3FF" ++ $"B3FF026C52020006023BD04F3BD04FBED4133ED4134B6000462FB00053AB53FF" ++ $"007F00060618FFFCFFFF63FF282528252725262726262627262B262B262C282D" ++ $"272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA2659315ABA26595E" ++ $"2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A254A254925482748" ++ $"264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D3E2B3E2C3E2B3E" ++ $"273E273E263C253D253C250618FFFCFFFF63FF28252825272526272626262726" ++ $"2B262B262C282D272D282D2B2B582B582B592D5A2C5A2D5A2F5A2F5A305ABA26" ++ $"59315ABA26595E2D5E2D5F2C5F2A5F2B5F2A5F275F275F265D255E255D254A25" ++ $"4A254925482748264827482B482B482C4A2D492D4A2D4C3A3F2D3C2D3C2D3D2D" ++ $"3E2B3E2C3E2B3E273E273E263C253D253C250A08BEA359BE3D593C5A415AC03B" ++ $"59BFD559434C404C06218A88888888C83E3F02484CC1D359C16D445A49C36B59" ++ $"C305C3CA50C5C8C50359C49D4C5A51C69B59C635C6FA50C8F8C83359C7CD545A" ++ $"59C9CB59C965CA6B4DCA6B4DCA804C5A4C584C584C574CC86D4DC8D34DC86D4D" ++ $"C73B524C534C524C504C504C4F4CC53D4DC5A34DC53D4DC40B4B4C0608EBECC0" ++ $"B64AC0B64AC11C4AC13349C14848C0F847C15E47C0F847C092C01648C02C47C0" ++ $"1648C00149C0504ABFEA4AC0504A0A04405E5E40402222400A0A000105180015" ++ $"01178600040A0001051815FF01178400040A030105000A0401051001157C0004" ++ $"0A000100381D1F001501178600040A000100381D1F15FF01178300040A010101" ++ $"201D1F0A020101301D1F01157E00040A0003020304381D1F15FF01178400040A" ++ $"0203020304281D1F15FF" ++}; ++ ++resource(1, "builtin-tools") #'PNG ' array { ++ $"89504E470D0A1A0A0000000D494844520000022E0000001208030000004BB3A5" ++ $"1200000300504C5445000000800000008000808000000080800080008080C0C0" ++ $"C0C0DCC0A6CAF0402000602000802000A02000C02000E0200000400020400040" ++ $"4000604000804000A04000C04000E04000006000206000406000606000806000" ++ $"A06000C06000E06000008000208000408000608000808000A08000C08000E080" ++ $"0000A00020A00040A00060A00080A000A0A000C0A000E0A00000C00020C00040" ++ $"C00060C00080C000A0C000C0C000E0C00000E00020E00040E00060E00080E000" ++ $"A0E000C0E000E0E000000040200040400040600040800040A00040C00040E000" ++ $"40002040202040402040602040802040A02040C02040E0204000404020404040" ++ $"4040604040804040A04040C04040E04040006040206040406040606040806040" ++ $"A06040C06040E06040008040208040408040608040808040A08040C08040E080" ++ $"4000A04020A04040A04060A04080A040A0A040C0A040E0A04000C04020C04040" ++ $"C04060C04080C040A0C040C0C040E0C04000E04020E04040E04060E04080E040" ++ $"A0E040C0E040E0E040000080200080400080600080800080A00080C00080E000" ++ $"80002080202080402080602080802080A02080C02080E0208000408020408040" ++ $"4080604080804080A04080C04080E04080006080206080406080606080806080" ++ $"A06080C06080E06080008080208080408080608080808080A08080C08080E080" ++ $"8000A08020A08040A08060A08080A080A0A080C0A080E0A08000C08020C08040" ++ $"C08060C08080C080A0C080C0C080E0C08000E08020E08040E08060E08080E080" ++ $"A0E080C0E080E0E0800000C02000C04000C06000C08000C0A000C0C000C0E000" ++ $"C00020C02020C04020C06020C08020C0A020C0C020C0E020C00040C02040C040" ++ $"40C06040C08040C0A040C0C040C0E040C00060C02060C04060C06060C08060C0" ++ $"A060C0C060C0E060C00080C02080C04080C06080C08080C0A080C0C080C0E080" ++ $"C000A0C020A0C040A0C060A0C080A0C0A0A0C0C0A0C0E0A0C000C0C020C0C040" ++ $"C0C060C0C080C0C0A0C0C0FFFBF0A0A0A4808080FF000000FF00FFFF000000FF" ++ $"FF00FF00FFFFFFFFFF58D234440000000874524E53FFFFFFFFFFFFFF00DE83BD" ++ $"59000000097048597300000B1200000B1201D2DD7EFC0000070D494441546881" ++ $"DD994B6E23390C86695880F6BDCD19BCCD3AD7CA7DB4CD197C965EE7044619D0" ++ $"F0299192AA5C9907D018762776D12A3DA8AF7E520E64B382FFB792FF004BCD4E" ++ $"DF02C1DC0717347779C3FFDB8D5F43A3705900FE8838FCDB868119C3F3E32EDA" ++ $"BB5A1897CA916A1B566CA49DED7865B2E3E930FC6397A9AAEDE232F10409EA37" ++ $"5B851A70793C020BB70C1B8CB4C436057EFFF6BCACE0BD0CAF75159D21567B6D" ++ $"B2BB9EC73AF7E89C21013E3EF03F1A4CD339BDA77E390523594BE549EA7E55DD" ++ $"E8793B68FEF332D4D3BD72BFE1B2D68D19171A87861F37ADB4163A3FEB87E6A7" ++ $"06411B06146E37D8B60D6E9E176C121A212D81976930BAE5C231A657895D5B80" ++ $"8735AE6BD5068729057FCC318FB5183DC682BB8924AC4D5AB456557F9771D647" ++ $"066E0B378A6491FD65381017DDB2793BD2674A9F64E14950CF67DFD8941D3D5D" ++ $"37DA62B1BB1B9ADFE4452BA3B3C41649D58BE6B77E58065C36B3EEC26C856D7A" ++ $"3E2A332ECFA73E3BBD53EE955F5BB8F939B3F85B749D2DDA003A0A5E546B392D" ++ $"6CE11962C1FD4412D6664C01702B990E4FA5C6591F18F4CDF1913475B1597975" ++ $"498A4BB3B632E7EA7B5F5C2E620A83C4C0ED2AFB7BBD4268157191693455129A" ++ $"BF6BD329C265918F461496EAF23219E5E7B3549977BF036FE1DFEDE9ACB2E7FB" ++ $"819736D9B76152F8C7B6B95E5AE06DA99327C682FBF9289E04B46B306D2519AB" ++ $"6480361D9A8ABDC0F291ABFE8271F916D9A849D505432FEA42D3E4965E5D1C2E" ++ $"B486CE463247C025E54159436982B898395C26759970A9BE9386CB948FC64473" ++ $"A676912AC06DFA53E5A51753C0A4D08F17730E6A734C81F7C94853BC3C8AF44B" ++ $"79A9974B5C18EE6573795C86041E49405ACAE68CC72168AEF9FAF686BF4D5DDC" ++ $"74CB98902AB8D7EA70112E0ACE076B1776DEFB7EA4BBE1B2509784893799BCA4" ++ $"76ED71416971BBCEEA623DF1B21197DB50D2840662853E2A2E19E95C2C6883BA" ++ $"A4B6DB63EDB23A19C536BCBF5E5ECAF329F2D22704C221DEE670113016C540DD" ++ $"C18576B7B0BA202CC2CB85B410F9B085F1D5E3228F00F45880CC221891A04EA1" ++ $"E55B7F181705081B15F12C71A9DC41FBC454489B414F4685D0D80A4E3F3E1789" ++ $"9FFA1D7521509ABCC89BF439E2E28B9BA82E0D97F844AD6A17E969D09F1E3448" ++ $"699EA2B0100FC9793C44E7E1B02DA50BA6A3E621655179E9B858FD32D1E11C75" ++ $"74B567B0CB0AC55B4EA37425106AFDEC1D35F2A1692DF24224E8BBB221840117" ++ $"038871F9DEC385122A83AF2E914B6B06E06B17C605E70F776760B8B45A32292E" ++ $"76D01E710907F0E1F4B4A72ECEE3594D417103762C223D688A4B5497391F9CF0" ++ $"80E1622393B290C0607CF2A1BA4CB84CAE6E8A4B257929242EF4CEE078F48599" ++ $"E712F900417117976DC3021AA9907F084703E885BA48426D5955E432F78B880B" ++ $"DD8AFEFB7BB32B182EDD64844299A74CB8D0C1903ED13594A1D47DA12E34B8B7" ++ $"D223E28F0249C5A5056DA52EAEA7AF2FEEE88C87BEA42364DCC83D40D97059D5" ++ $"2E7BC9A8F62D51EBC9A8B2C0DB01C9E8E80BEB7213F880F032E18240081C1D17" ++ $"03E8585D72FE91BA6805E6707987515D4CE9932F598637EECCC7B8F8134D5DA9" ++ $"8BC7E5F1F86A56DCF13AE022EAD282C6B844010CDC15DAFD331EE5C51FA5537D" ++ $"3C727E704A7A3ED9B53A198DA56E0FEB949F7AA92B0072F552A463CA8C7D6156" ++ $"BB0C7CF00E1EE0029BA41E4D47C8E9E6D5E5089755ED62CDD6B80CF21270F9F5" ++ $"ABE3C2E7202970F3E8695B2CEAD28AD81D7571C9E8FEF5B5C4C59BA94B0B9AE0" ++ $"1204D075F478281CAF3DB9A5A3968D522DC8CB0379C1B4C4BCACBF77C9FE201D" ++ $"4F46D666719016846C9D720CF234C8C968E443867BDBC1C578E927A306D0212E" ++ $"35984D09DCC54B5CDEF770E95FB3B883B439CCD3BE7751DD61D3A3D89EBAECE0" ++ $"32ABCB58EA46010C1D8D70EC7A7AADDB78C1D9154E095E5D2EFAAA87AAF990CC" ++ $"59B9D95E1BE0546747EA6CDFBB381AD2E4E158D02ADFDE022F0E17C9A81E5703" ++ $"E8B07681F12EF9C85D2C71C130BAEF78F670B1435083A37DABDB1D599391952F" ++ $"14BA78F0E1DD7500ADE73CE1A20F00DE2B995652909F22DC7B2784C2394FE6BF" ++ $"01683A0237985717AC5D742297A02E1185D196B8F0BBFE374DB730A561F6F458" ++ $"445E3C2E8155C65501A24612D60997D55DAE3399EF1A9769C7965B2867A0E2E2" ++ $"A31E7759F41835B4E9C7A71120F0EA02E51017BA45FF3253665C5C19AB70BCF6" ++ $"642D5B2423411F8C6B97868B8D9E5BED326AB84637E032B5E94A648AED17C634" ++ $"CC1E178B7D5C661302A891ECBE4E07E6591FD81A9781B3A5A339E749F94BFF32" ++ $"75AED701A01D71099DF832450BF94900492EBA3109273CD9FE02C03909FA6024" ++ $"912D194D339C0EC9D6CCAD7AD166F2C485312E93671150B617B88C8D86DC731A" ++ $"1767E7EEF90FEC3599BB77B416E3EAE7689CF114DBE3E262B898CB34FECE845E" ++ $"4CFAEF79764372DC201F65AC97B792C14FE6F387DBB4F83918273C6E9B866FD9" ++ $"FF17F6CF36F92F1B9E631E8B8F3FBC0000000049454E44AE426082" ++}; +diff --git a/src/os_unix.c b/src/os_unix.c +index 59e5745..9c695b1 100644 +--- a/src/os_unix.c ++++ b/src/os_unix.c +@@ -2184,7 +2184,7 @@ mch_settitle(char_u *title, char_u *icon) + if (get_x11_windis() == OK) + type = 1; + #else +-# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) ++# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) + if (gui.in_use) + type = 1; + # endif +@@ -2212,7 +2212,7 @@ mch_settitle(char_u *title, char_u *icon) + # endif + set_x11_title(title); /* x11 */ + #endif +-#if defined(FEAT_GUI_GTK) \ ++#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)\ + || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + else + gui_mch_settitle(title, icon); +@@ -4469,7 +4469,7 @@ mch_call_shell( + { + SIGSET_DECL(curset) + +-# ifdef __BEOS__ ++# if defined(__BEOS__) && USE_THREAD_FOR_INPUT_WITH_TIMEOUT + beos_cleanup_read_thread(); + # endif + +diff --git a/src/os_unix.h b/src/os_unix.h +index 695affa..b9bc2e3 100644 +--- a/src/os_unix.h ++++ b/src/os_unix.h +@@ -364,6 +364,8 @@ typedef struct dsc$descriptor DESC; + + #define DFLT_ERRORFILE "errors.err" + ++#ifndef DFLT_RUNTIMEPATH ++ + #ifdef VMS + # define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after" + #else +@@ -374,6 +376,8 @@ typedef struct dsc$descriptor DESC; + # endif + #endif + ++#endif ++ + #ifdef VMS + # ifndef VAX + # define VMS_TEMPNAM /* to fix default .LIS extension */ +diff --git a/src/osdef1.h.in b/src/osdef1.h.in +index 5519104..9820c7b 100644 +--- a/src/osdef1.h.in ++++ b/src/osdef1.h.in +@@ -66,7 +66,9 @@ extern void memmove(char *, char *, int); + # endif + #endif + /* used inside of FD_ZERO macro: */ ++#ifndef __HAIKU__ + extern void bzero(void *, size_t); ++#endif + #ifdef HAVE_SETSID + extern pid_t setsid(void); + #endif +diff --git a/src/proto.h b/src/proto.h +index 92e3f60..0c91cdb 100644 +--- a/src/proto.h ++++ b/src/proto.h +@@ -243,6 +243,9 @@ extern char_u *vimpty_getenv(const char_u *string); /* in misc2.c */ + extern char *vim_SelFile(Widget toplevel, char *prompt, char *init_path, int (*show_entry)(), int x, int y, guicolor_T fg, guicolor_T bg, guicolor_T scroll_fg, guicolor_T scroll_bg); + # endif + # endif ++# ifdef FEAT_GUI_HAIKU ++# include "gui_haiku.pro" ++# endif + # ifdef FEAT_GUI_MAC + # include "gui_mac.pro" + # endif +diff --git a/src/proto/gui_haiku.pro b/src/proto/gui_haiku.pro +new file mode 100644 +index 0000000..deb412b +--- /dev/null ++++ b/src/proto/gui_haiku.pro +@@ -0,0 +1,92 @@ ++/* gui_haiku.cc - hand crafted */ ++void gui_mch_prepare __ARGS((int *argc, char **argv)); ++int gui_mch_init __ARGS((void)); ++int gui_mch_open __ARGS((void)); ++void gui_mch_exit __ARGS((int vim_exitcode)); ++int gui_mch_init_check __ARGS((void)); ++void gui_mch_flush __ARGS((void)); ++ ++void gui_mch_new_colors __ARGS((void)); ++void gui_mch_set_bg_color __ARGS((guicolor_T color)); ++void gui_mch_set_fg_color __ARGS((guicolor_T color)); ++void gui_mch_set_sp_color __ARGS((guicolor_T color)); ++/*long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));*/ ++guicolor_T gui_mch_get_rgb(guicolor_T pixel); ++guicolor_T gui_mch_get_color __ARGS((char_u *name)); ++ ++GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing)); ++void gui_mch_set_font __ARGS((GuiFont font)); ++int gui_mch_init_font __ARGS((char_u* font_name, int fontset)); ++void gui_mch_free_font __ARGS((GuiFont font)); ++char_u* gui_mch_get_fontname __ARGS((GuiFont font, char_u *name)); ++ ++void gui_mch_set_winpos __ARGS((int x, int y)); ++int gui_mch_get_winpos __ARGS((int *x, int *y)); ++void gui_mch_set_shellsize __ARGS((int w, int h, int m_w, int m_h, int b_w, int b_h, int d)); ++void gui_mch_get_screen_dimensions __ARGS((int* screen_w, int* screen_h)); ++void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h)); ++ ++void gui_mch_enable_scrollbar __ARGS((scrollbar_T* sb, int flag)); ++void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb,int val, int size, int max)); ++void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h)); ++void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient)); ++void gui_mch_destroy_scrollbar __ARGS((scrollbar_T* sb)); ++ ++void gui_mch_set_blinking __ARGS((long waittime, long on, long off)); ++void gui_mch_stop_blink __ARGS(()); ++void gui_mch_start_blink __ARGS(()); ++ ++int gui_mch_adjust_charheight __ARGS(()); ++void gui_mch_draw_string __ARGS((int row, int col, char_u* s, int len, int flags)); ++int gui_mch_haskey __ARGS((char_u* name)); ++void gui_mch_beep __ARGS(()); ++void gui_mch_flash __ARGS((int msec)); ++void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc)); ++void gui_mch_iconify __ARGS(()); ++void gui_mch_set_foreground __ARGS(()); ++void gui_mch_settitle __ARGS((char_u* title, char_u* icon)); ++void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color)); ++void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color)); ++void gui_mch_update __ARGS(()); ++int gui_mch_wait_for_chars __ARGS((int wtime)); ++void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2)); ++void gui_mch_clear_all __ARGS(()); ++void gui_mch_delete_lines __ARGS((int row, int num_lines)); ++void gui_mch_insert_lines __ARGS((int row, int num_lines)); ++ ++void gui_mch_getmouse __ARGS((int *x, int *y)); ++void gui_mch_setmouse __ARGS((int x, int y)); ++void gui_mch_mousehide __ARGS((int hide)); ++ ++void gui_mch_enable_menu __ARGS((int flag)); ++void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h)); ++void gui_mch_add_menu __ARGS((vimmenu_T* menu, int idx)); ++void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx)); ++void gui_mch_destroy_menu __ARGS((vimmenu_T *menu)); ++void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey)); ++void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden)); ++void gui_mch_draw_menubar __ARGS(()); ++void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu)); ++void gui_mch_toggle_tearoffs __ARGS((int enable)); ++ ++void clip_mch_request_selection __ARGS((VimClipboard *cbd)); ++void clip_mch_set_selection __ARGS((VimClipboard *cbd)); ++void clip_mch_lose_selection __ARGS((VimClipboard *cbd)); ++int clip_mch_own_selection __ARGS((VimClipboard *cbd)); ++ ++char_u* gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter)); ++int gui_mch_dialog __ARGS((int type, char_u *title, char_u* message, char_u *buttons, int dfltbutton, char_u* textfield, int ex_cmd)); ++ ++void im_set_position __ARGS((int row, int col)); ++void im_set_active __ARGS((int activate)); ++int im_get_status __ARGS(()); ++ ++void gui_mch_show_toolbar __ARGS((int showit)); ++void gui_mch_set_toolbar_pos __ARGS((int x, int y, int w, int h)); ++ ++void gui_mch_show_tabline __ARGS((int showit)); ++void gui_mch_set_tabline_pos __ARGS((int x, int y, int w, int h)); ++int gui_mch_showing_tabline __ARGS((void)); ++void gui_mch_update_tabline __ARGS((void)); ++void gui_mch_set_curtab __ARGS((int nr)); ++// char_u *gui_mch_font_dialog __ARGS((char_u *oldval)); +diff --git a/src/pty.c b/src/pty.c +index 151a278..8072499 100644 +--- a/src/pty.c ++++ b/src/pty.c +@@ -351,7 +351,7 @@ OpenPTY(char **ttyn) + static char PtyProto[] = "/dev/ptym/ptyXY"; + static char TtyProto[] = "/dev/pty/ttyXY"; + # else +-# ifdef __BEOS__ ++# if defined(__BEOS__) || defined(__HAIKU__) + static char PtyProto[] = "/dev/pt/XY"; + static char TtyProto[] = "/dev/tt/XY"; + # else +diff --git a/src/screen.c b/src/screen.c +index 3e08b60..d7a9df8 100644 +--- a/src/screen.c ++++ b/src/screen.c +@@ -89,6 +89,15 @@ + + #include "vim.h" + ++#ifdef __HAIKU__ ++// FIXME!!! ++ int ++gui_mch_is_blink_off(void) ++{ ++ return FALSE; ++} ++#endif ++ + #define MB_FILLER_CHAR '<' /* character used when a double-width character + * doesn't fit. */ + +@@ -8746,6 +8755,10 @@ retry: + + win_new_shellsize(); /* fit the windows in the new sized shell */ + ++#ifdef FEAT_GUI_HAIKU ++ vim_lock_screen(); /* be safe, put it here */ ++#endif ++ + comp_col(); /* recompute columns for shown command and ruler */ + + /* +@@ -8977,6 +8990,10 @@ give_up: + } + #endif + ++#ifdef FEAT_GUI_HAIKU ++ vim_unlock_screen(); ++#endif ++ + entered = FALSE; + --RedrawingDisabled; + +@@ -9811,6 +9828,10 @@ screen_ins_lines( + clip_scroll_selection(-line_count); + #endif + ++#ifdef FEAT_GUI_HAIKU ++ vim_lock_screen(); ++#endif ++ + #ifdef FEAT_GUI + /* Don't update the GUI cursor here, ScreenLines[] is invalid until the + * scrolling is actually carried out. */ +@@ -9862,6 +9883,10 @@ screen_ins_lines( + } + } + ++#ifdef FEAT_GUI_HAIKU ++ vim_unlock_screen(); ++#endif ++ + screen_stop_highlight(); + windgoto(cursor_row, 0); + if (clear_attr != 0) +@@ -10027,6 +10052,10 @@ screen_del_lines( + clip_scroll_selection(line_count); + #endif + ++#ifdef FEAT_GUI_HAIKU ++ vim_lock_screen(); ++#endif ++ + #ifdef FEAT_GUI + /* Don't update the GUI cursor here, ScreenLines[] is invalid until the + * scrolling is actually carried out. */ +@@ -10086,6 +10115,10 @@ screen_del_lines( + } + } + ++#ifdef FEAT_GUI_HAIKU ++ vim_unlock_screen(); ++#endif ++ + if (screen_attr != clear_attr) + screen_stop_highlight(); + if (clear_attr != 0) +diff --git a/src/structs.h b/src/structs.h +index 7b0f70c..ae9865b 100644 +--- a/src/structs.h ++++ b/src/structs.h +@@ -3137,6 +3137,13 @@ struct VimMenu + HMENU submenu_id; /* If this is submenu, add children here */ + HWND tearoff_handle; /* hWnd of tearoff if created */ + #endif ++#if FEAT_GUI_HAIKU ++ BMenuItem *id; /* Id of menu item */ ++ BMenu *submenu_id; /* If this is submenu, add children here */ ++# ifdef FEAT_TOOLBAR ++ BPictureButton *button; ++# endif ++#endif + #ifdef FEAT_GUI_MAC + /* MenuHandle id; */ + /* short index; */ /* the item index within the father menu */ +diff --git a/src/term.c b/src/term.c +index 9925b0a..5254b71 100644 +--- a/src/term.c ++++ b/src/term.c +@@ -1354,6 +1354,11 @@ termgui_mch_get_rgb(guicolor_T color) + # define DEFAULT_TERM (char_u *)"beos-ansi" + #endif + ++#ifdef __HAIKU__ ++# undef DEFAULT_TERM ++# define DEFAULT_TERM (char_u *)"xterm" ++#endif ++ + #ifndef DEFAULT_TERM + # define DEFAULT_TERM (char_u *)"dumb" + #endif +diff --git a/src/ui.c b/src/ui.c +index f175e1a..caab0b5 100644 +--- a/src/ui.c ++++ b/src/ui.c +@@ -3151,7 +3151,7 @@ mouse_find_win(int *rowp, int *colp UNUSED) + + #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ +- || defined(FEAT_GUI_PHOTON) || defined(PROTO) ++ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_HAIKU) || defined(PROTO) + /* + * Translate window coordinates to buffer position without any side effects + */ +diff --git a/src/version.c b/src/version.c +index 8d7a5e5..1619a41 100644 +--- a/src/version.c ++++ b/src/version.c +@@ -3400,6 +3400,9 @@ list_version(void) + MSG_PUTS(_("with X11-Athena GUI.")); + # endif + # else ++# ifdef FEAT_GUI_HAIKU ++ MSG_PUTS(_("with Haiku GUI.")); ++# else + # ifdef FEAT_GUI_PHOTON + MSG_PUTS(_("with Photon GUI.")); + # else +@@ -3417,6 +3420,7 @@ list_version(void) + # endif + # endif + # endif ++# endif + # endif + # endif + # endif +diff --git a/src/vim.h b/src/vim.h +index 4567c36..a194194 100644 +--- a/src/vim.h ++++ b/src/vim.h +@@ -115,6 +115,7 @@ + || defined(FEAT_GUI_ATHENA) \ + || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_W32) \ ++ || defined(FEAT_GUI_HAIKU) \ + || defined(FEAT_GUI_PHOTON) + # define FEAT_GUI_ENABLED /* also defined with NO_X11_INCLUDES */ + # if !defined(FEAT_GUI) && !defined(NO_X11_INCLUDES) +@@ -255,6 +256,11 @@ + # include "os_beos.h" + #endif + ++#ifdef __HAIKU__ ++# include "os_haiku.h" ++# define __ARGS(x) x ++#endif ++ + #if (defined(UNIX) || defined(VMS)) \ + && (!defined(MACOS_X) || defined(HAVE_CONFIG_H)) + # include "os_unix.h" /* bring lots of system header files */ +@@ -2077,6 +2083,9 @@ typedef struct VimClipboard + int_u format; /* Vim's own special clipboard format */ + int_u format_raw; /* Vim's raw text clipboard format */ + # endif ++# ifdef FEAT_GUI_HAIKU ++ /* no clipboard at the moment. TODO???? */ ++# endif + } VimClipboard; + #else + typedef int VimClipboard; /* This is required for the prototypes. */ +@@ -2117,7 +2126,7 @@ typedef enum { + * been seen at that stage. But it must be before globals.h, where error_ga + * is declared. */ + #if !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_X11) \ +- && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) ++ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) && !defined(FEAT_GUI_HAIKU) + # define mch_errmsg(str) fprintf(stderr, "%s", (str)) + # define display_errors() fflush(stderr) + # define mch_msg(str) printf("%s", (str)) +-- +2.14.2 + diff --git a/app-editors/vim/vim-8.0.1176.recipe b/app-editors/vim/vim-8.0.1176.recipe new file mode 100644 index 000000000..b4b577feb --- /dev/null +++ b/app-editors/vim/vim-8.0.1176.recipe @@ -0,0 +1,146 @@ +SUMMARY="A highly configurable text editor" +DESCRIPTION="Vim is a highly configurable text editor built to enable \ +efficient text editing. It is an improved version of the vi editor \ +distributed with most UNIX systems. + +Vim is often called a \"programmer's editor,\" and so useful for programming \ +that many consider it an entire IDE. It's not just for programmers, though. \ +Vim is perfect for all kinds of text editing, from composing email to editing \ +configuration files. +Despite this, Vim can be configured to work in a very simple (Notepad-like) \ +way, called evim or Easy Vim." +HOMEPAGE="http://www.vim.org" +COPYRIGHT="1991-2017 Bram Moleenar et al." +LICENSE="Vim" +REVISION="1" +SOURCE_URI="https://github.com/vim/vim/archive/v$portVersion.tar.gz" +CHECKSUM_SHA256="1485524d747b2046b9e1ea3bfcf80148e6a9a65e29d972d23cf88152ad9dcca2" +SOURCE_DIR="vim-$portVersion" +PATCHES="vim-$portVersion.patchset" + +ARCHITECTURES="?x86_gcc2 ?x86 x86_64" + +PROVIDES=" + vim = $portVersion + cmd:ex = $portVersion + cmd:gview = $portVersion + cmd:gvim = $portVersion + cmd:gvimdiff = $portVersion + cmd:rgview = $portVersion + cmd:rgvim = $portVersion + cmd:rview = $portVersion + cmd:rvim = $portVersion + cmd:vi = $portVersion + cmd:view = $portVersion + cmd:vim = $portVersion + cmd:vimdiff = $portVersion + cmd:vimtutor = $portVersion + cmd:xxd = $portVersion + " +REQUIRES=" + haiku + lib:libiconv + lib:libintl + lib:libncurses + " + +BUILD_REQUIRES=" + haiku_devel + devel:libiconv + devel:libintl +# devel:liblua + devel:libncurses + devel:libruby + devel:libtclstub8.5 + " +BUILD_PREREQUIRES=" + cmd:autoconf + cmd:find + cmd:gcc + cmd:gettext + cmd:grep + cmd:make +# cmd:perl + cmd:pkg_config$secondaryArchSuffix + cmd:python2 +# cmd:python3 + cmd:ruby + cmd:sed + " + +BUILD() +{ + +# Global ---------------------------------------- + + cd src + autoconf + + export CFLAGS="\ + `pkg-config --cflags python2` \ + -fPIC" + +# CLI ------------------------------------------- + + runConfigure ./configure \ + --disable-gui \ + --with-features=big \ + --enable-cscope \ + --enable-multibyte \ + --enable-pythoninterp=dynamic \ + --enable-rubyinterp=dynamic \ + --enable-tclinterp=dynamic \ + --with-compiledby=Haikuports +# --enable-luainterp=dynamic +# --enable-python3interp=dynamic currently broken +# --enable-perlinterp=dynamic not dynamic yet + + + make $jobArgs + cp vim vim.con # preserve gui-less executable + rm objects/*.o + +# GUI ------------------------------------------- + + MAJOR="`echo "$portVersion" | cut -d. -f1`" + MIDDLE="`echo "$portVersion" | cut -d. -f2`" + MINOR="`echo "$portVersion" | cut -d. -f3`" + sed -i "s|@MAJOR@|$MAJOR|" os_haiku.rdef + sed -i "s|@MIDDLE@|$MIDDLE|" os_haiku.rdef + sed -i "s|@MINOR@|$MINOR|" os_haiku.rdef + + runConfigure ./configure \ + --with-features=big \ + --enable-cscope \ + --enable-multibyte \ + --enable-pythoninterp=dynamic \ + --enable-rubyinterp=dynamic \ + --enable-tclinterp==dynamic \ + --with-compiledby=Haikuports +# --enable-luainterp=dynamic +# --enable-python3interp=dynamic currently broken +# --enable-perlinterp=dynamic not dynamic yet + + make $jobArgs +} + +INSTALL() +{ + make install + + # Make arrow keys, backspace, delete, etc behave as expected. + echo "set nocompatible" > $dataDir/vim/vimrc + + # Workaround to get the themes and plugins work + echo "set runtimepath+=`finddir B_USER_SETTINGS_DIRECTORY`/vim" > $dataDir/vim/vimrc + + ln -s vim $binDir/vi + + addAppDeskbarSymlink $binDir/gvim Vim +} + +TEST() +{ + cd src + make check +}