To: vim_dev@googlegroups.com Subject: Patch 8.2.0320 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0320 Problem: No Haiku support. Solution: Add support for Haiku. (Emir Sari, closes #5605) Files: Filelist, runtime/doc/Makefile, runtime/doc/eval.txt, runtime/doc/gui.txt, runtime/doc/help.txt, runtime/doc/options.txt, runtime/doc/os_haiku.txt, runtime/doc/starting.txt, runtime/doc/tags, runtime/gvimrc_example.vim, runtime/vimrc_example.vim, src/INSTALL, src/Makefile, src/auto/configure, src/configure.ac, src/evalfunc.c, src/feature.h, src/fileio.c, src/globals.h, src/gui.c, src/gui.h, src/gui_haiku.cc, src/gui_haiku.h, src/mbyte.c, src/menu.c, src/misc1.c, src/mouse.c, src/option.h, src/os_haiku.h, src/os_haiku.rdef, src/os_unix.c, src/os_unix.h, src/osdef1.h.in, src/proto.h, src/proto/gui_haiku.pro, src/pty.c, src/screen.c, src/structs.h, src/term.c, src/version.c, src/vim.h *** ../vim-8.2.0319/Filelist 2020-02-26 13:43:48.642089655 +0100 --- Filelist 2020-02-26 15:04:22.045672588 +0100 *************** *** 599,604 **** --- 599,612 ---- src/testdir/amiga.vim \ src/xxd/Make_amiga.mak \ + # source files for Haiku (also in the extra archive) + SRC_HAIKU = \ + src/os_haiku.h \ + src/os_haiku.rdef \ + src/gui_haiku.cc \ + src/gui_haiku.h \ + src/proto/gui_haiku.pro \ + # source files for the Mac (also in the extra archive) SRC_MAC = \ src/INSTALLmac.txt \ *************** *** 634,646 **** src/proto/gui_photon.pro \ src/proto/os_qnx.pro \ - # source files for the extra archive (all sources that are not for Unix) SRC_EXTRA = \ $(SRC_AMI) \ $(SRC_AMI_DOS) \ $(SRC_DOS) \ $(SRC_DOS_BIN) \ $(SRC_MAC) \ $(SRC_QNX) \ $(SRC_VMS) \ --- 642,654 ---- src/proto/gui_photon.pro \ src/proto/os_qnx.pro \ # source files for the extra archive (all sources that are not for Unix) SRC_EXTRA = \ $(SRC_AMI) \ $(SRC_AMI_DOS) \ $(SRC_DOS) \ $(SRC_DOS_BIN) \ + $(SRC_HAIKU) \ $(SRC_MAC) \ $(SRC_QNX) \ $(SRC_VMS) \ *** ../vim-8.2.0319/runtime/doc/Makefile 2020-01-26 15:52:33.007833314 +0100 --- runtime/doc/Makefile 2020-02-26 15:04:22.049672574 +0100 *************** *** 64,69 **** --- 64,70 ---- os_amiga.txt \ os_beos.txt \ os_dos.txt \ + os_haiku.txt \ os_mac.txt \ os_mint.txt \ os_msdos.txt \ *************** *** 204,209 **** --- 205,211 ---- os_amiga.html \ os_beos.html \ os_dos.html \ + os_haiku.html \ os_mac.html \ os_mint.html \ os_msdos.html \ *************** *** 422,427 **** --- 424,432 ---- os_dos.txt: touch os_dos.txt + os_haiku.txt: + touch os_haiku.txt + os_mac.txt: touch os_mac.txt *** ../vim-8.2.0319/runtime/doc/eval.txt 2020-02-22 19:07:24.397786814 +0100 --- runtime/doc/eval.txt 2020-02-26 15:04:22.049672574 +0100 *************** *** 10756,10767 **** --- 10766,10779 ---- 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| hpux HP-UX version of Vim. iconv Can use iconv() for conversion. *** ../vim-8.2.0319/runtime/doc/gui.txt 2019-12-17 21:27:14.686319918 +0100 --- runtime/doc/gui.txt 2020-02-26 15:04:22.049672574 +0100 *************** *** 99,104 **** --- 99,105 ---- 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. *** ../vim-8.2.0319/runtime/doc/help.txt 2019-12-12 12:49:05.000000000 +0100 --- runtime/doc/help.txt 2020-02-26 15:04:22.049672574 +0100 *************** *** 197,212 **** |os_390.txt| OS/390 Unix |os_amiga.txt| Amiga |os_beos.txt| BeOS and BeBox ! |os_dos.txt| MS-DOS and MS-Windows NT/95 common items |os_mac.txt| Macintosh |os_mint.txt| Atari MiNT |os_msdos.txt| MS-DOS (plain DOS and DOS box under Windows) |os_os2.txt| OS/2 |os_qnx.txt| QNX |os_risc.txt| RISC-OS |os_unix.txt| Unix |os_vms.txt| VMS ! |os_win32.txt| MS-Windows 95/98/NT *standard-plugin-list* Standard plugins ~ |pi_getscript.txt| Downloading latest version of Vim scripts --- 197,213 ---- |os_390.txt| OS/390 Unix |os_amiga.txt| Amiga |os_beos.txt| BeOS and BeBox ! |os_dos.txt| MS-DOS and MS-Windows common items |os_mac.txt| Macintosh |os_mint.txt| Atari MiNT |os_msdos.txt| MS-DOS (plain DOS and DOS box under Windows) |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 *standard-plugin-list* Standard plugins ~ |pi_getscript.txt| Downloading latest version of Vim scripts *** ../vim-8.2.0319/runtime/doc/options.txt 2020-01-26 15:52:33.011833294 +0100 --- runtime/doc/options.txt 2020-02-26 15:04:22.049672574 +0100 *************** *** 3768,3774 **** '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. *'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 --- 3769,3775 ---- '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, 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 *************** *** 6206,6214 **** Macintosh: "$VIM:vimfiles, $VIMRUNTIME, $VIM:vimfiles:after" ! RISC-OS: "Choices:vimfiles, $VIMRUNTIME, ! Choices:vimfiles/after" VMS: "sys$login:vimfiles, $VIM/vimfiles, $VIMRUNTIME, --- 6207,6217 ---- Macintosh: "$VIM:vimfiles, $VIMRUNTIME, $VIM:vimfiles:after" ! Haiku: "$BE_USER_SETTINGS/vim, ! $VIM/vimfiles, $VIMRUNTIME, ! $VIM/vimfiles/after, ! $BE_USER_SETTINGS/vim/after") VMS: "sys$login:vimfiles, $VIM/vimfiles, $VIMRUNTIME, *************** *** 7669,7677 **** in the GUI: "builtin_gui" on Amiga: "amiga" on BeOS: "beos-ansi" on Mac: "mac-ansi" on MiNT: "vt52" - on MS-DOS: "pcterm" on Unix: "ansi" on VMS: "ansi" on Win 32: "win32") --- 7670,7678 ---- in the GUI: "builtin_gui" on Amiga: "amiga" on BeOS: "beos-ansi" + on Haiku: "xterm" on Mac: "mac-ansi" on MiNT: "vt52" on Unix: "ansi" on VMS: "ansi" on Win 32: "win32") *** ../vim-8.2.0319/runtime/doc/os_haiku.txt 2020-02-26 16:11:39.241157487 +0100 --- runtime/doc/os_haiku.txt 2020-02-26 15:07:57.936937504 +0100 *************** *** 0 **** --- 1,228 ---- + *os_haiku.txt* For Vim version 8.2. Last change: 2020 Feb 26 + + + 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. + + Haiku is an open-source operating system inspired by BeOS, that specifically + targets personal computing. + + 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_SYSTEM_NONPACKAGED_DIRECTORY` \ + --datarootdir=`finddir B_SYSTEM_NONPACKAGED_DATA_DIRECTORY` \ + --mandir=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY`/documentation/man \ + make clean + make install + + ./configure --prefix=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY` \ + --datarootdir=`finddir B_SYSTEM_NONPACKAGED_DATA_DIRECTORY` \ + --mandir=`finddir B_SYSTEM_NONPACKAGED_DIRECTORY`/documentation/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, uses 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/runtime/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. + + All the changes and patches released under vim-license. + + 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: *** ../vim-8.2.0319/runtime/doc/starting.txt 2019-12-17 21:27:14.690319902 +0100 --- runtime/doc/starting.txt 2020-02-26 15:04:22.049672574 +0100 *************** *** 788,793 **** --- 790,796 ---- 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. *************** *** 834,839 **** --- 836,843 ---- "$HOME/_vimrc" (for Win32) (*) "$HOME/vimfiles/vimrc" (for Win32) (*) "$VIM/_vimrc" (for Win32) (*) + "$HOME/config/settings/vim/vimrc" (for Haiku) (*) + Note: For Unix and Amiga, when ".vimrc" does not exist, "_vimrc" is also tried, in case an MS-DOS compatible file system is used. For MS-Windows ".vimrc" is checked after *************** *** 949,962 **** ~/.vimrc (Unix) s:.vimrc (Amiga) $VIM\_vimrc (Win32) Note that creating a vimrc file will cause the 'compatible' option to be off by default. See |compatible-default|. Local setup: Put all commands that you need for editing a specific directory only into a vimrc file and place it in that directory under the name ".vimrc" ("_vimrc" ! for MS-DOS and Win32). NOTE: To make Vim look for these special files you ! have to turn on the option 'exrc'. See |trojan-horse| too. System setup: This only applies if you are managing a Unix system with several users and --- 953,968 ---- ~/.vimrc (Unix) s:.vimrc (Amiga) $VIM\_vimrc (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|. Local setup: Put all commands that you need for editing a specific directory only into a vimrc file and place it in that directory under the name ".vimrc" ("_vimrc" ! for Win32). NOTE: To make Vim look for these special files you have to turn ! on the option 'exrc'. See |trojan-horse| too. System setup: This only applies if you are managing a Unix system with several users and *** ../vim-8.2.0319/runtime/doc/tags 2020-01-26 15:52:33.011833294 +0100 --- runtime/doc/tags 2020-02-26 15:39:11.355990300 +0100 *************** *** 2313,2318 **** --- 2313,2319 ---- :debug-name repeat.txt /*:debug-name* :debugg repeat.txt /*:debugg* :debuggreedy repeat.txt /*:debuggreedy* + :def vim9.txt /*:def* :del change.txt /*:del* :delc map.txt /*:delc* :delcommand map.txt /*:delcommand* *************** *** 2340,2345 **** --- 2341,2348 ---- :diffupdate diff.txt /*:diffupdate* :dig digraph.txt /*:dig* :digraphs digraph.txt /*:digraphs* + :disa vim9.txt /*:disa* + :disassemble vim9.txt /*:disassemble* :display change.txt /*:display* :dj tagsrch.txt /*:dj* :djump tagsrch.txt /*:djump* *************** *** 2384,2389 **** --- 2387,2393 ---- :emenu gui.txt /*:emenu* :en eval.txt /*:en* :end eval.txt /*:end* + :enddef vim9.txt /*:enddef* :endf eval.txt /*:endf* :endfo eval.txt /*:endfo* :endfor eval.txt /*:endfor* *************** *** 2404,2409 **** --- 2408,2415 ---- :execute eval.txt /*:execute* :exi editing.txt /*:exi* :exit editing.txt /*:exit* + :exp vim9.txt /*:exp* + :export vim9.txt /*:export* :exu helphelp.txt /*:exu* :exusage helphelp.txt /*:exusage* :f editing.txt /*:f* *************** *** 2506,2511 **** --- 2512,2520 ---- :imapclear map.txt /*:imapclear* :ime gui.txt /*:ime* :imenu gui.txt /*:imenu* + :imp vim9.txt /*:imp* + :import vim9.txt /*:import* + :import-cycle vim9.txt /*:import-cycle* :in insert.txt /*:in* :index index.txt /*:index* :ino map.txt /*:ino* *************** *** 3354,3359 **** --- 3363,3370 ---- :vie editing.txt /*:vie* :view editing.txt /*:view* :vim quickfix.txt /*:vim* + :vim9 vim9.txt /*:vim9* + :vim9script vim9.txt /*:vim9script* :vimgrep quickfix.txt /*:vimgrep* :vimgrepa quickfix.txt /*:vimgrepa* :vimgrepadd quickfix.txt /*:vimgrepadd* *************** *** 3834,3839 **** --- 3845,3851 ---- Command-line-mode cmdline.txt /*Command-line-mode* CompleteChanged autocmd.txt /*CompleteChanged* CompleteDone autocmd.txt /*CompleteDone* + CompleteDonePre autocmd.txt /*CompleteDonePre* ConPTY terminal.txt /*ConPTY* Contents quickref.txt /*Contents* Cscope if_cscop.txt /*Cscope* *************** *** 4661,4666 **** --- 4673,4679 ---- E859 eval.txt /*E859* E86 windows.txt /*E86* E862 eval.txt /*E862* + E863 popup.txt /*E863* E864 pattern.txt /*E864* E865 pattern.txt /*E865* E866 pattern.txt /*E866* *************** *** 4858,4863 **** --- 4871,4877 ---- 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* *************** *** 6097,6102 **** --- 6111,6117 ---- dying-variable eval.txt /*dying-variable* e motion.txt /*e* easy starting.txt /*easy* + echoraw() eval.txt /*echoraw()* echospace-variable eval.txt /*echospace-variable* edit-a-file editing.txt /*edit-a-file* edit-binary editing.txt /*edit-binary* *************** *** 7039,7044 **** --- 7054,7073 ---- 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()* *************** *** 8146,8151 **** --- 8175,8181 ---- null-variable eval.txt /*null-variable* number_relativenumber options.txt /*number_relativenumber* numbered-function eval.txt /*numbered-function* + numbersize-variable eval.txt /*numbersize-variable* o insert.txt /*o* o_CTRL-V motion.txt /*o_CTRL-V* o_V motion.txt /*o_V* *************** *** 8196,8201 **** --- 8226,8232 ---- 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* *************** *** 8233,8238 **** --- 8264,8270 ---- pathshorten() eval.txt /*pathshorten()* pattern pattern.txt /*pattern* pattern-atoms pattern.txt /*pattern-atoms* + pattern-delimiter change.txt /*pattern-delimiter* pattern-multi-byte pattern.txt /*pattern-multi-byte* pattern-multi-items pattern.txt /*pattern-multi-items* pattern-overview pattern.txt /*pattern-overview* *************** *** 8316,8321 **** --- 8348,8354 ---- popup-position popup.txt /*popup-position* popup-props popup.txt /*popup-props* popup-scrollbar popup.txt /*popup-scrollbar* + popup-terminal popup.txt /*popup-terminal* popup-textprop-pos popup.txt /*popup-textprop-pos* popup-usage popup.txt /*popup-usage* popup-window popup.txt /*popup-window* *************** *** 9473,9478 **** --- 9506,9514 ---- test_scrollbar() testing.txt /*test_scrollbar()* test_setmouse() testing.txt /*test_setmouse()* test_settime() testing.txt /*test_settime()* + test_srand_seed() testing.txt /*test_srand_seed()* + test_unknown() testing.txt /*test_unknown()* + test_void() testing.txt /*test_void()* testing testing.txt /*testing* testing-support testing.txt /*testing-support* testing-variable eval.txt /*testing-variable* *************** *** 9673,9678 **** --- 9709,9715 ---- v:mouse_winid eval.txt /*v:mouse_winid* v:none eval.txt /*v:none* v:null eval.txt /*v:null* + v:numbersize eval.txt /*v:numbersize* v:oldfiles eval.txt /*v:oldfiles* v:operator eval.txt /*v:operator* v:option_command eval.txt /*v:option_command* *************** *** 9909,9918 **** --- 9946,9959 ---- vim.vim syntax.txt /*vim.vim* vim7 version7.txt /*vim7* vim8 version8.txt /*vim8* + vim9-differences vim9.txt /*vim9-differences* + vim9-export vim9.txt /*vim9-export* + vim9-import vim9.txt /*vim9-import* vim9-rationale vim9.txt /*vim9-rationale* vim9-script vim9.txt /*vim9-script* vim9-types vim9.txt /*vim9-types* vim9.txt vim9.txt /*vim9.txt* + vim9script vim9.txt /*vim9script* vim: options.txt /*vim:* vim_announce intro.txt /*vim_announce* vim_dev intro.txt /*vim_dev* *************** *** 10034,10039 **** --- 10075,10081 ---- win_execute() eval.txt /*win_execute()* win_findbuf() eval.txt /*win_findbuf()* win_getid() eval.txt /*win_getid()* + win_gettype() eval.txt /*win_gettype()* win_gotoid() eval.txt /*win_gotoid()* win_id2tabwin() eval.txt /*win_id2tabwin()* win_id2win() eval.txt /*win_id2win()* *** ../vim-8.2.0319/runtime/gvimrc_example.vim 2019-12-17 21:27:14.690319902 +0100 --- runtime/gvimrc_example.vim 2020-02-26 15:04:22.053672558 +0100 *************** *** 6,15 **** " Last change: 2016 Apr 05 " " To use it, copy it to ! " for Unix: ~/.gvimrc ! " for Amiga: s:.gvimrc ! " for MS-DOS and Win32: $VIM\_gvimrc ! " for OpenVMS: sys$login:.gvimrc " Make external commands work through a pipe instead of a pseudo-tty "set noguipty --- 6,16 ---- " Last change: 2016 Apr 05 " " To use it, copy it to ! " for Unix: ~/.gvimrc ! " for Amiga: s:.gvimrc ! " for MS-Windows: $VIM\_gvimrc ! " for Haiku: ~/config/settings/vim/gvimrc ! " for OpenVMS: sys$login:.gvimrc " Make external commands work through a pipe instead of a pseudo-tty "set noguipty *** ../vim-8.2.0319/runtime/vimrc_example.vim 2019-12-17 21:27:14.690319902 +0100 --- runtime/vimrc_example.vim 2020-02-26 15:04:22.053672558 +0100 *************** *** 7,12 **** --- 7,13 ---- " for Unix: ~/.vimrc " for Amiga: s:.vimrc " for MS-Windows: $VIM\_vimrc + " for Haiku: ~/config/settings/vim/vimrc " for OpenVMS: sys$login:.vimrc " When started as "evim", evim.vim will already have done these settings, bail *** ../vim-8.2.0319/src/INSTALL 2018-09-08 15:56:45.000000000 +0200 --- src/INSTALL 2020-02-26 15:04:22.053672558 +0100 *************** *** 16,22 **** See INSTALLx.txt for cross-compiling on Unix See ../READMEdir/README_390.txt for z/OS and OS/390 Unix See ../runtime/doc/os_beos.txt for BeBox ! 1. Generic ========== --- 16,22 ---- See INSTALLx.txt for cross-compiling on Unix See ../READMEdir/README_390.txt for z/OS and OS/390 Unix See ../runtime/doc/os_beos.txt for BeBox ! See ../runtime/doc/os_haiku.txt for Haiku 1. Generic ========== *** ../vim-8.2.0319/src/Makefile 2020-02-14 13:21:55.642197064 +0100 --- src/Makefile 2020-02-26 15:41:54.087492637 +0100 *************** *** 1385,1390 **** --- 1385,1404 ---- 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 -lsupc++ -lstdc++ + 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 *************** *** 3217,3222 **** --- 3231,3239 ---- 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 *************** *** 3349,3354 **** --- 3366,3374 ---- objects/os_qnx.o: os_qnx.c $(CCC) -o $@ os_qnx.c + objects/os_haiku.rsrc: os_haiku.rdef + cat $< | $(CCC) -E - | grep -v '^#' | rc -o "$@" - + objects/os_macosx.o: os_macosx.m $(CCC) -o $@ os_macosx.m *************** *** 3617,3622 **** --- 3637,3697 ---- objects/gui_gtk_x11.o: version.h ############################################################################### + # + # 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 protodef.h auto/config.h feature.h os_unix.h \ *** ../vim-8.2.0319/src/auto/configure 2020-02-07 20:50:03.652182318 +0100 --- src/auto/configure 2020-02-26 15:09:33.972610986 +0100 *************** *** 1501,1507 **** --disable-farsi Deprecated. --enable-xim Include XIM input support. --enable-fontset Include X fontset output support. ! --enable-gui=OPTS X11 GUI. default=auto OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon --enable-gtk2-check If auto-select GUI, check for GTK+ 2 default=yes --enable-gnome-check If GTK GUI, check for GNOME default=no --enable-gtk3-check If auto-select GUI, check for GTK+ 3 default=yes --- 1501,1507 ---- --disable-farsi Deprecated. --enable-xim Include XIM input support. --enable-fontset Include X fontset output support. ! --enable-gui=OPTS X11 GUI. default=auto OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/haiku/photon/carbon --enable-gtk2-check If auto-select GUI, check for GTK+ 2 default=yes --enable-gnome-check If GTK GUI, check for GNOME default=no --enable-gtk3-check If auto-select GUI, check for GTK+ 3 default=yes *************** *** 4543,4548 **** --- 4543,4557 ---- $as_echo "no" >&6; };; esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Haiku" >&5 + $as_echo_n "checking for Haiku... " >&6; } + case `uname` in + Haiku) HAIKU=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + $as_echo "yes" >&6; };; + *) HAIKU=no; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + $as_echo "no" >&6; };; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for QNX" >&5 $as_echo_n "checking for QNX... " >&6; } case `uname` in *************** *** 7714,7720 **** fi if test "$enable_channel" = "yes"; then ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 --- 7723,7777 ---- fi if test "$enable_channel" = "yes"; then ! ! if test "x$HAIKU" = "xyes"; then ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 ! $as_echo_n "checking for socket in -lnetwork... " >&6; } ! if ${ac_cv_lib_network_socket+:} false; then : ! $as_echo_n "(cached) " >&6 ! else ! ac_check_lib_save_LIBS=$LIBS ! LIBS="-lnetwork $LIBS" ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! ! /* Override any GCC internal prototype to avoid an error. ! Use char because int might match the return type of a GCC ! builtin and then its argument prototype would still apply. */ ! #ifdef __cplusplus ! extern "C" ! #endif ! char socket (); ! int ! main () ! { ! return socket (); ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_link "$LINENO"; then : ! ac_cv_lib_network_socket=yes ! else ! ac_cv_lib_network_socket=no ! fi ! rm -f core conftest.err conftest.$ac_objext \ ! conftest$ac_exeext conftest.$ac_ext ! LIBS=$ac_check_lib_save_LIBS ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 ! $as_echo "$ac_cv_lib_network_socket" >&6; } ! if test "x$ac_cv_lib_network_socket" = xyes; then : ! cat >>confdefs.h <<_ACEOF ! #define HAVE_LIBNETWORK 1 ! _ACEOF ! ! LIBS="-lnetwork $LIBS" ! ! fi ! ! else ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 *************** *** 7759,7764 **** --- 7816,7823 ---- fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : *************** *** 9034,9040 **** as_fn_error $? "could not configure X" "$LINENO" 5 fi ! test "x$with_x" = xno -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-gui argument" >&5 $as_echo_n "checking --enable-gui argument... " >&6; } --- 9093,9099 ---- as_fn_error $? "could not configure X" "$LINENO" 5 fi ! test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOS_X" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-gui argument" >&5 $as_echo_n "checking --enable-gui argument... " >&6; } *************** *** 9056,9065 **** SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES SKIP_CARBON=YES GUITYPE=NONE ! if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then SKIP_PHOTON= case "$enable_gui_canon" in no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5 --- 9115,9141 ---- SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES + SKIP_HAIKU=YES SKIP_CARBON=YES GUITYPE=NONE ! if test "x$HAIKU" = "xyes"; then ! SKIP_HAIKU= ! case "$enable_gui_canon" in ! no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5 ! $as_echo "no GUI support" >&6; } ! SKIP_HAIKU=YES ;; ! yes|"") { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - automatic GUI support" >&5 ! $as_echo "yes - automatic GUI support" >&6; } ;; ! auto) { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto - automatic GUI support" >&5 ! $as_echo "auto - automatic GUI support" >&6; } ;; ! haiku) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Haiku GUI support" >&5 ! $as_echo "Haiku GUI support" >&6; } ;; ! *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Sorry, $enable_gui GUI is not supported" >&5 ! $as_echo "Sorry, $enable_gui GUI is not supported" >&6; } ! SKIP_HAIKU=YES ;; ! esac ! elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then SKIP_PHOTON= case "$enable_gui_canon" in no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5 *************** *** 9283,9288 **** --- 9359,9365 ---- SKIP_ATHENA=YES; SKIP_NEXTAW=YES; SKIP_PHOTON=YES; + SKIP_HAIKU=YES; SKIP_CARBON=YES fi *************** *** 10589,10594 **** --- 10666,10675 ---- enable_fontset="no" fi + if test -z "$SKIP_HAIKU"; then + GUITYPE=HAIKUGUI + fi + if test -z "$SKIP_PHOTON"; then GUITYPE=PHOTONGUI fi *** ../vim-8.2.0319/src/configure.ac 2020-02-07 20:50:03.648182335 +0100 --- src/configure.ac 2020-02-26 15:04:22.053672558 +0100 *************** *** 154,159 **** --- 154,165 ---- *) 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) *************** *** 2033,2039 **** if test "$enable_channel" = "yes"; then dnl On Solaris we need the socket and nsl library. ! AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(nsl, gethostbyname) AC_MSG_CHECKING(whether compiling with process communication is possible) AC_TRY_LINK([ --- 2039,2051 ---- if test "$enable_channel" = "yes"; then dnl On Solaris we need the socket and nsl library. ! ! 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([ *************** *** 2311,2321 **** AC_MSG_ERROR([could not configure X]) fi ! test "x$with_x" = xno -a "x$MACOS_X" != "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") dnl Canonicalize the --enable-gui= argument so that it can be easily compared. dnl Do not use character classes for portability with old tools. --- 2323,2333 ---- AC_MSG_ERROR([could not configure X]) fi ! test "x$with_x" = xno -a "x$HAIKU" != "xyes" -a "x$MACOS_X" != "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/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. *************** *** 2330,2339 **** SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES SKIP_CARBON=YES GUITYPE=NONE ! if test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then SKIP_PHOTON= case "$enable_gui_canon" in no) AC_MSG_RESULT(no GUI support) --- 2342,2363 ---- SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES + SKIP_HAIKU=YES SKIP_CARBON=YES GUITYPE=NONE ! 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) *************** *** 2499,2504 **** --- 2523,2529 ---- SKIP_ATHENA=YES; SKIP_NEXTAW=YES; SKIP_PHOTON=YES; + SKIP_HAIKU=YES; SKIP_CARBON=YES fi *************** *** 3112,3117 **** --- 3137,3147 ---- 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 *** ../vim-8.2.0319/src/evalfunc.c 2020-02-22 19:07:24.393786830 +0100 --- src/evalfunc.c 2020-02-26 15:04:22.057672547 +0100 *************** *** 3264,3269 **** --- 3264,3272 ---- #ifdef __BEOS__ "beos", #endif + #ifdef __HAIKU__ + "haiku", + #endif #if defined(BSD) && !defined(MACOS_X) "bsd", #endif *************** *** 3450,3455 **** --- 3453,3461 ---- #ifdef FEAT_GUI_GNOME "gui_gnome", #endif + #ifdef FEAT_GUI_HAIKU + "gui_haiku", + #endif #ifdef FEAT_GUI_MAC "gui_mac", #endif *** ../vim-8.2.0319/src/feature.h 2020-02-17 22:11:39.666644199 +0100 --- src/feature.h 2020-02-26 15:04:22.057672547 +0100 *************** *** 514,520 **** */ #if defined(FEAT_GUI_MSWIN) && !defined(FEAT_MBYTE_IME) // #define FEAT_MBYTE_IME ! # endif // Use iconv() when it's available. #if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV) --- 514,524 ---- */ #if defined(FEAT_GUI_MSWIN) && !defined(FEAT_MBYTE_IME) // #define FEAT_MBYTE_IME ! #endif ! ! #if defined(FEAT_BIG) && defined(FEAT_GUI_HAIKU) && !defined(FEAT_MBYTE_IME) ! # define FEAT_MBYTE_IME ! #endif // Use iconv() when it's available. #if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV) *************** *** 604,610 **** || defined(FEAT_GUI_MSWIN) \ || ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \ && defined(HAVE_XPM)) \ ! || defined(FEAT_GUI_PHOTON)) # define FEAT_TOOLBAR #endif --- 608,616 ---- || defined(FEAT_GUI_MSWIN) \ || ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \ && defined(HAVE_XPM)) \ ! || defined(FEAT_GUI_PHOTON) \ ! || defined(FEAT_GUI_HAIKU)) ! # define FEAT_TOOLBAR #endif *************** *** 627,632 **** --- 633,639 ---- && (defined(FEAT_GUI_GTK) \ || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \ || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_HAIKU) \ || (defined(FEAT_GUI_MSWIN) \ && (!defined(_MSC_VER) || _MSC_VER > 1020))) # define FEAT_GUI_TABLINE *************** *** 638,644 **** */ #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) # define FEAT_BROWSE # endif #endif --- 645,653 ---- */ #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_HAIKU) || defined(FEAT_GUI_PHOTON) \ ! || defined(FEAT_GUI_MAC) # define FEAT_BROWSE # endif #endif *************** *** 663,668 **** --- 672,678 ---- && 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 *************** *** 680,686 **** #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)) # define FEAT_GUI_TEXTDIALOG # ifndef ALWAYS_USE_GUI # define FEAT_CON_DIALOG --- 690,697 ---- #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_HAIKU)) # define FEAT_GUI_TEXTDIALOG # ifndef ALWAYS_USE_GUI # define FEAT_CON_DIALOG *** ../vim-8.2.0319/src/fileio.c 2020-02-22 14:26:39.244757847 +0100 --- src/fileio.c 2020-02-26 15:50:48.053578327 +0100 *************** *** 3367,3372 **** --- 3367,3373 ---- #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ || defined(FEAT_GUI_MSWIN) \ || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_HAIKU) \ || defined(PROTO) /* * Shorten all filenames in "fnames[count]" by current directory. *************** *** 4422,4551 **** void *context, int (*checkitem)(void *context, char_u *name)) { ! int failed = FALSE; ! # ifdef MSWIN ! char_u *buf, *p; ! int ok; ! HANDLE hFind = INVALID_HANDLE_VALUE; ! WIN32_FIND_DATAW wfb; ! WCHAR *wn = NULL; // UTF-16 name, NULL when not used. ! # endif ga_init2(gap, (int)sizeof(char *), 20); # ifdef MSWIN - buf = alloc(MAXPATHL); - if (buf == NULL) - return FAIL; - STRNCPY(buf, path, MAXPATHL-5); - p = buf + STRLEN(buf); - MB_PTR_BACK(buf, p); - if (*p == '\\' || *p == '/') - *p = NUL; - STRCAT(buf, "\\*"); - - wn = enc_to_utf16(buf, NULL); - if (wn != NULL) - hFind = FindFirstFileW(wn, &wfb); - ok = (hFind != INVALID_HANDLE_VALUE); - if (!ok) { ! failed = TRUE; ! smsg(_(e_notopen), path); ! } ! else ! { ! while (ok) { ! int ignore; ! ! p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here ! if (p == NULL) ! break; // out of memory ! ! ignore = p[0] == '.' && (p[1] == NUL ! || (p[1] == '.' && p[2] == NUL)); ! if (!ignore && checkitem != NULL) { ! int r = checkitem(context, p); ! if (r < 0) { ! vim_free(p); ! break; } - if (r == 0) - ignore = TRUE; - } ! if (!ignore) ! { ! if (ga_grow(gap, 1) == OK) ! ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); ! else { ! failed = TRUE; ! vim_free(p); ! break; } - } ! vim_free(p); ! ok = FindNextFileW(hFind, &wfb); } - FindClose(hFind); - } ! vim_free(buf); ! vim_free(wn); ! # else ! DIR *dirp; ! struct dirent *dp; ! char_u *p; ! ! dirp = opendir((char *)path); ! if (dirp == NULL) ! { ! failed = TRUE; ! smsg(_(e_notopen), path); } ! else { ! for (;;) ! { ! int ignore; ! dp = readdir(dirp); ! if (dp == NULL) ! break; ! p = (char_u *)dp->d_name; ! ! ignore = p[0] == '.' && ! (p[1] == NUL || ! (p[1] == '.' && p[2] == NUL)); ! if (!ignore && checkitem != NULL) { ! int r = checkitem(context, p); ! if (r < 0) break; ! if (r == 0) ! ignore = TRUE; ! } ! if (!ignore) ! { ! if (ga_grow(gap, 1) == OK) ! ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); ! else { ! failed = TRUE; ! break; } } - } ! closedir(dirp); } # endif --- 4423,4555 ---- void *context, int (*checkitem)(void *context, char_u *name)) { ! int failed = FALSE; ! char_u *p; ga_init2(gap, (int)sizeof(char *), 20); # ifdef MSWIN { ! char_u *buf; ! int ok; ! HANDLE hFind = INVALID_HANDLE_VALUE; ! WIN32_FIND_DATAW wfb; ! WCHAR *wn = NULL; // UTF-16 name, NULL when not used. ! ! buf = alloc(MAXPATHL); ! if (buf == NULL) ! return FAIL; ! STRNCPY(buf, path, MAXPATHL-5); ! p = buf + STRLEN(buf); ! MB_PTR_BACK(buf, p); ! if (*p == '\\' || *p == '/') ! *p = NUL; ! STRCAT(buf, "\\*"); ! ! wn = enc_to_utf16(buf, NULL); ! if (wn != NULL) ! hFind = FindFirstFileW(wn, &wfb); ! ok = (hFind != INVALID_HANDLE_VALUE); ! if (!ok) { ! failed = TRUE; ! smsg(_(e_notopen), path); ! } ! else ! { ! while (ok) { ! int ignore; ! p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here ! if (p == NULL) ! break; // out of memory ! ! ignore = p[0] == '.' && (p[1] == NUL ! || (p[1] == '.' && p[2] == NUL)); ! if (!ignore && checkitem != NULL) { ! int r = checkitem(context, p); ! ! if (r < 0) ! { ! vim_free(p); ! break; ! } ! if (r == 0) ! ignore = TRUE; } ! if (!ignore) { ! if (ga_grow(gap, 1) == OK) ! ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); ! else ! { ! failed = TRUE; ! vim_free(p); ! break; ! } } ! vim_free(p); ! ok = FindNextFileW(hFind, &wfb); ! } ! FindClose(hFind); } ! vim_free(buf); ! vim_free(wn); } ! # else { ! DIR *dirp; ! struct dirent *dp; ! dirp = opendir((char *)path); ! if (dirp == NULL) ! { ! failed = TRUE; ! smsg(_(e_notopen), path); ! } ! else ! { ! for (;;) { ! int ignore; ! dp = readdir(dirp); ! if (dp == NULL) break; ! p = (char_u *)dp->d_name; ! ignore = p[0] == '.' && ! (p[1] == NUL || ! (p[1] == '.' && p[2] == NUL)); ! if (!ignore && checkitem != NULL) { ! int r = checkitem(context, p); ! ! if (r < 0) ! break; ! if (r == 0) ! ignore = TRUE; ! } ! ! if (!ignore) ! { ! if (ga_grow(gap, 1) == OK) ! ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); ! else ! { ! failed = TRUE; ! break; ! } } } ! closedir(dirp); ! } } # endif *** ../vim-8.2.0319/src/globals.h 2020-02-25 22:58:25.607851771 +0100 --- src/globals.h 2020-02-26 15:04:22.057672547 +0100 *************** *** 1524,1530 **** EXTERN char e_fontset[] INIT(= N_("E234: Unknown fontset: %s")); #endif #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ ! || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN) EXTERN char e_font[] INIT(= N_("E235: Unknown font: %s")); #endif #if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) --- 1524,1530 ---- EXTERN char e_fontset[] INIT(= N_("E234: Unknown fontset: %s")); #endif #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ ! || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU) EXTERN char e_font[] INIT(= N_("E235: Unknown font: %s")); #endif #if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) *** ../vim-8.2.0319/src/gui.c 2020-02-21 21:30:33.867979726 +0100 --- src/gui.c 2020-02-26 15:54:12.224793202 +0100 *************** *** 446,452 **** gui.menu_width = 0; # endif #endif ! #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) gui.toolbar_height = 0; #endif #if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF) --- 446,453 ---- gui.menu_width = 0; # endif #endif ! #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) *************** *** 1371,1380 **** text_area_y += gui.tabline_height; #endif ! #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) if (vim_strchr(p_go, GO_TOOLBAR) != NULL) { ! # ifdef FEAT_GUI_ATHENA gui_mch_set_toolbar_pos(0, text_area_y, gui.menu_width, gui.toolbar_height); # endif --- 1372,1382 ---- text_area_y += gui.tabline_height; #endif ! #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ ! || defined(FEAT_GUI_HAIKU)) if (vim_strchr(p_go, GO_TOOLBAR) != NULL) { ! # 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 *************** *** 1382,1387 **** --- 1384,1396 ---- } #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; *************** *** 1453,1459 **** # endif # endif # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ ! || defined(FEAT_GUI_MOTIF)) if (gui_has_tabline()) base_height += gui.tabline_height; # endif --- 1462,1468 ---- # endif # endif # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ ! || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU)) if (gui_has_tabline()) base_height += gui.tabline_height; # endif *************** *** 1496,1501 **** --- 1505,1514 ---- new_pixel_height = 0; busy = TRUE; + #ifdef FEAT_GUI_HAIKU + vim_lock_screen(); + #endif + // Flush pending output before redrawing out_flush(); *************** *** 1518,1523 **** --- 1531,1540 ---- || 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) *************** *** 4254,4262 **** y += gui.menu_height; #endif ! #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA)) if (vim_strchr(p_go, GO_TOOLBAR) != NULL) ! # ifdef FEAT_GUI_ATHENA y += gui.toolbar_height; # else # ifdef FEAT_GUI_MSWIN --- 4271,4280 ---- y += gui.menu_height; #endif ! #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) \ ! || defined(FEAT_GUI_HAIKU)) if (vim_strchr(p_go, GO_TOOLBAR) != NULL) ! # if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU) y += gui.toolbar_height; # else # ifdef FEAT_GUI_MSWIN *************** *** 4265,4271 **** # endif #endif ! #if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) if (gui_has_tabline()) y += gui.tabline_height; #endif --- 4283,4289 ---- # endif #endif ! #if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU) if (gui_has_tabline()) y += gui.tabline_height; #endif *************** *** 5035,5044 **** } #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ ! || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)) \ && defined(FEAT_TOOLBAR)) || defined(PROTO) /* ! * This is shared between Athena, Motif and GTK. */ /* --- 5053,5063 ---- } #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ ! || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON) \ ! || defined(FEAT_GUI_HAIKU)) \ && defined(FEAT_TOOLBAR)) || defined(PROTO) /* ! * This is shared between Athena, Haiku, Motif, and GTK. */ /* *** ../vim-8.2.0319/src/gui.h 2019-11-30 18:25:47.000000000 +0100 --- src/gui.h 2020-02-26 15:55:41.644462152 +0100 *************** *** 29,34 **** --- 29,38 ---- # include #endif + #ifdef FEAT_GUI_HAIKU + # include "gui_haiku.h" + #endif + // Needed when generating prototypes, since FEAT_GUI is always defined then. #if defined(FEAT_XCLIPBOARD) && !defined(FEAT_GUI_MOTIF) \ && !defined(FEAT_GUI_ATHENA) && !defined(FEAT_GUI_GTK) *************** *** 73,79 **** */ #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ || defined(FEAT_GUI_MSWIN) \ ! || defined(FEAT_GUI_MAC) # define HAVE_DROP_FILE #endif --- 77,84 ---- */ #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ || defined(FEAT_GUI_MSWIN) \ ! || defined(FEAT_GUI_MAC) \ ! || defined(FEAT_GUI_HAIKU) # define HAVE_DROP_FILE #endif *************** *** 200,205 **** --- 205,214 ---- // 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 *************** *** 426,432 **** #if defined(FEAT_GUI_TABLINE) \ && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \ ! || defined(FEAT_GUI_MAC)) int tabline_height; #endif --- 435,441 ---- #if defined(FEAT_GUI_TABLINE) \ && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \ ! || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_HAIKU)) int tabline_height; #endif *************** *** 435,441 **** #endif #if defined(FEAT_TOOLBAR) \ ! && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)) int toolbar_height; // height of the toolbar #endif --- 444,450 ---- #endif #if defined(FEAT_TOOLBAR) \ ! && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU)) int toolbar_height; // height of the toolbar #endif *************** *** 456,461 **** --- 465,478 ---- 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 *** ../vim-8.2.0319/src/gui_haiku.cc 2020-02-26 16:11:39.329157191 +0100 --- src/gui_haiku.cc 2020-02-26 16:04:18.322643299 +0100 *************** *** 0 **** --- 1,5242 ---- + /* 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 + bool csi_escape; + }; + + struct VimResizeMsg { + int width; + int height; + }; + + struct VimScrollBarMsg { + VimScrollBar *sb; + long value; + int stillDragging; + }; + + struct VimMenuMsg { + vimmenu_T *guiMenu; + }; + + struct VimMouseMsg { + int button; + int x; + int y; + int repeated_click; + int_u modifiers; + }; + + struct VimMouseMovedMsg { + int x; + int y; + }; + + struct VimFocusMsg { + bool active; + }; + + struct VimRefsMsg { + BMessage *message; + bool changedir; + }; + + struct VimTablineMsg { + int index; + }; + + struct VimTablineMenuMsg { + int index; + int event; + }; + + struct VimMsg { + enum VimMsgType { + Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu + }; + + union { + struct VimKeyMsg Key; + struct VimResizeMsg NewSize; + struct VimScrollBarMsg Scroll; + struct VimMenuMsg Menu; + struct VimMouseMsg Mouse; + struct VimMouseMovedMsg MouseMoved; + struct VimFocusMsg Focus; + struct VimRefsMsg Refs; + struct VimTablineMsg Tabline; + struct VimTablineMenuMsg TablineMenu; + } u; + }; + + #define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0) + #define GUI_TO_RGB(g) { (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 ."); + } + + static void + drop_callback(void *cookie) + { + // TODO here we could handle going to a specific position in the dropped + // file (see src/gui_mac.c) + // Update the screen display + update_screen(NOT_VALID); + } + + // Really handle dropped files and folders. + static void + RefsReceived(BMessage *m, bool changedir) + { + uint32 type; + int32 count; + + m->PrintToStream(); + switch (m->what) { + case B_REFS_RECEIVED: + case B_SIMPLE_DATA: + m->GetInfo("refs", &type, &count); + if (type != B_REF_TYPE) + goto bad; + break; + case B_ARGV_RECEIVED: + m->GetInfo("argv", &type, &count); + if (type != B_STRING_TYPE) + goto bad; + if (changedir) { + char *dirname; + if (m->FindString("cwd", (const char **) &dirname) == B_OK) { + chdir(dirname); + do_cmdline_cmd((char_u *)"cd ."); + } + } + break; + default: + bad: + /*fprintf(stderr, "bad!\n"); */ + delete m; + return; + } + + #ifdef FEAT_VISUAL + reset_VIsual(); + #endif + + char_u **fnames; + fnames = (char_u **) alloc(count * sizeof(char_u *)); + int fname_index = 0; + + switch (m->what) { + case B_REFS_RECEIVED: + case B_SIMPLE_DATA: + // fprintf(stderr, "case B_REFS_RECEIVED\n"); + for (int i = 0; i < count; ++i) + { + entry_ref ref; + if (m->FindRef("refs", i, &ref) == B_OK) { + BEntry entry(&ref, false); + BPath path; + entry.GetPath(&path); + + // Change to parent directory? + if (changedir) { + BPath parentpath; + path.GetParent(&parentpath); + docd(parentpath); + } + + // Is it a directory? If so, cd into it. + BDirectory bdir(&ref); + if (bdir.InitCheck() == B_OK) { + // don't cd if we already did it + if (!changedir) + docd(path); + } else { + mch_dirname(IObuff, IOSIZE); + char_u *fname = shorten_fname((char_u *)path.Path(), IObuff); + if (fname == NULL) + fname = (char_u *)path.Path(); + fnames[fname_index++] = vim_strsave(fname); + // fprintf(stderr, "%s\n", fname); + } + + // Only do it for the first file/dir + changedir = false; + } + } + break; + case B_ARGV_RECEIVED: + // fprintf(stderr, "case B_ARGV_RECEIVED\n"); + for (int i = 1; i < count; ++i) + { + char *fname; + + if (m->FindString("argv", i, (const char **) &fname) == B_OK) { + fnames[fname_index++] = vim_strsave((char_u *)fname); + } + } + break; + default: + // fprintf(stderr, "case default\n"); + break; + } + + delete m; + + // Handle the drop, :edit to get to the file + if (fname_index > 0) { + handle_drop(fname_index, fnames, FALSE, drop_callback, NULL); + + setcursor(); + out_flush(); + } else { + vim_free(fnames); + } + } + + VimApp::VimApp(const char *appsig): + BApplication(appsig), + fFilePanelSem(-1), + fFilePanel(NULL) + { + } + + VimApp::~VimApp() + { + } + + void + VimApp::ReadyToRun() + { + /* + * Apparently signals are inherited by the created thread - + * disable the most annoying ones. + */ + 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); + km.csi_escape = false; + write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); + return false; + } + + // ---------------- VimFormView ---------------- + + VimFormView::VimFormView(BRect frame): + BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS), + menuBar(NULL), + #ifdef FEAT_TOOLBAR + toolBar(NULL), + #endif + #ifdef FEAT_GUI_TABLINE + // showingTabLine(false), + tabLine(NULL), + #endif + textArea(NULL) + { + init(frame); + } + + VimFormView::~VimFormView() + { + if (menuBar) { + RemoveChild(menuBar); + #ifdef never + // deleting the menuBar leads to SEGV on exit + // richard@whitequeen.com Jul 99 + delete menuBar; + #endif + } + + #ifdef FEAT_TOOLBAR + delete toolBar; + #endif + + #ifdef FEAT_GUI_TABLINE + delete tabLine; + #endif + + if (textArea) { + RemoveChild(textArea); + delete textArea; + } + gui.vimForm = NULL; + } + + void + VimFormView::init(BRect frame) + { + menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN), + "VimMenuBar"); + + AddChild(menuBar); + + #ifdef FEAT_TOOLBAR + toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar"); + toolBar->PrepareButtonBitmaps(); + AddChild(toolBar); + #endif + + #ifdef FEAT_GUI_TABLINE + tabLine = new VimTabLine(BRect(0,0,0,0)); + // tabLine->PrepareButtonBitmaps(); + AddChild(tabLine); + #endif + + BRect remaining = frame; + textArea = new VimTextAreaView(remaining); + AddChild(textArea); + // The textArea will be resized later when menus are added + + gui.vimForm = this; + } + + #ifdef FEAT_TOOLBAR + float + VimFormView::ToolbarHeight() const + { + return toolBar ? toolBar->ToolbarHeight() : 0.; + } + #endif + + #ifdef FEAT_GUI_TABLINE + float + VimFormView::TablineHeight() const + { + return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.; + } + #endif + + void + VimFormView::AllAttached() + { + /* + * Apparently signals are inherited by the created thread - + * disable the most annoying ones. + */ + 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); + #define W_WIDTH(curwin) 0 + } + + void + VimTextAreaView::Draw(BRect updateRect) + { + /* + * XXX Other ports call here: + * out_flush(); * make sure all output has been processed * + * but we can't do that, since it involves too much information + * that is owned by other threads... + */ + + /* + * No need to use gui.vimWindow->Lock(): we are locked already. + * However, it would not hurt. + */ + rgb_color rgb = GUI_TO_RGB(gui.back_pixel); + SetLowColor(rgb); + FillRect(updateRect, B_SOLID_LOW); + gui_redraw((int) updateRect.left, (int) updateRect.top, + (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH)); + + // Clear the border areas if needed + SetLowColor(rgb); + + if (updateRect.left < FILL_X(0)) // left border + FillRect(BRect(updateRect.left, updateRect.top, + FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW); + if (updateRect.top < FILL_Y(0)) // top border + FillRect(BRect(updateRect.left, updateRect.top, + updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW); + if (updateRect.right >= FILL_X(Columns)) // right border + FillRect(BRect(FILL_X((int)Columns), updateRect.top, + updateRect.right, updateRect.bottom), B_SOLID_LOW); + if (updateRect.bottom >= FILL_Y(Rows)) // bottom border + FillRect(BRect(updateRect.left, FILL_Y((int)Rows), + updateRect.right, updateRect.bottom), B_SOLID_LOW); + + #ifdef FEAT_MBYTE_IME + DrawIMString(); + #endif + } + + void + VimTextAreaView::KeyDown(const char *bytes, int32 numBytes) + { + struct VimKeyMsg km; + char_u *dest = km.chars; + + bool canHaveVimModifiers = false; + + BMessage *msg = Window()->CurrentMessage(); + assert(msg); + // msg->PrintToStream(); + + /* + * Convert special keys to Vim codes. + * I think it is better to do it in the window thread + * so we use at least a little bit of the potential + * of our 2 CPUs. Besides, due to the fantastic mapping + * of special keys to UTF-8, we have quite some work to + * do... + * TODO: I'm not quite happy with detection of special + * keys. Perhaps I should use scan codes after all... + */ + if (numBytes > 1) { + // This cannot be a special key + if (numBytes > KEY_MSG_BUFSIZ) + numBytes = KEY_MSG_BUFSIZ; // should never happen... ??? + km.length = numBytes; + memcpy((char *)dest, bytes, numBytes); + km.csi_escape = true; + } else { + int32 scancode = 0; + msg->FindInt32("key", &scancode); + + int32 beModifiers = 0; + msg->FindInt32("modifiers", &beModifiers); + + char_u string[3]; + int len = 0; + km.length = 0; + + /* + * For normal, printable ASCII characters, don't look them up + * to check if they might be a special key. They aren't. + */ + assert(B_BACKSPACE <= 0x20); + assert(B_DELETE == 0x7F); + if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) && + numBytes == 1) { + /* + * Due to the great nature of Be's mapping of special keys, + * viz. into the range of the control characters, + * we can only be sure it is *really* a special key if + * if it is special without using ctrl. So, only if ctrl is + * used, we need to check it unmodified. + */ + if (beModifiers & B_CONTROL_KEY) { + int index = keyMap->normal_map[scancode]; + int newNumBytes = keyMapChars[index]; + char_u *newBytes = (char_u *)&keyMapChars[index + 1]; + + /* + * Check if still special without the control key. + * This is needed for BACKSPACE: that key does produce + * different values with modifiers (DEL). + * Otherwise we could simply have checked for equality. + */ + if (newNumBytes != 1 || (*newBytes > 0x20 && + *newBytes != 0x7F )) { + goto notspecial; + } + bytes = (char *)newBytes; + } + canHaveVimModifiers = true; + + uint16 beoskey; + int first, last; + + /* + * If numBytes == 0 that probably always indicates a special key. + * (does not happen yet) + */ + if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) { + beoskey = F(scancode); + first = FIRST_FUNCTION_KEY; + last = NUM_SPECIAL_KEYS; + } else if (*bytes == '\n' && scancode == 0x47) { + // remap the (non-keypad) ENTER key from \n to \r. + string[0] = '\r'; + len = 1; + first = last = 0; + } else { + beoskey = K(bytes[0]); + first = 0; + last = FIRST_FUNCTION_KEY; + } + + for (int i = first; i < last; i++) { + if (special_keys[i].BeKeys == beoskey) { + string[0] = CSI; + string[1] = special_keys[i].vim_code0; + string[2] = special_keys[i].vim_code1; + len = 3; + } + } + } + notspecial: + if (len == 0) { + string[0] = bytes[0]; + len = 1; + } + + // Special keys (and a few others) may have modifiers + #if 0 + if (len == 3 || + bytes[0] == B_SPACE || bytes[0] == B_TAB || + bytes[0] == B_RETURN || bytes[0] == '\r' || + bytes[0] == B_ESCAPE) + #else + if (canHaveVimModifiers) + #endif + { + int modifiers; + modifiers = 0; + if (beModifiers & B_SHIFT_KEY) + modifiers |= MOD_MASK_SHIFT; + if (beModifiers & B_CONTROL_KEY) + modifiers |= MOD_MASK_CTRL; + if (beModifiers & B_OPTION_KEY) + modifiers |= MOD_MASK_ALT; + + /* + * For some keys a shift modifier is translated into another key + * code. Do we need to handle the case where len != 1 and + * string[0] != CSI? (Not for BeOS, since len == 3 implies + * string[0] == CSI...) + */ + int key; + if (string[0] == CSI && len == 3) + key = TO_SPECIAL(string[1], string[2]); + else + key = string[0]; + key = simplify_key(key, &modifiers); + if (IS_SPECIAL(key)) + { + string[0] = CSI; + string[1] = K_SECOND(key); + string[2] = K_THIRD(key); + len = 3; + } + else + { + string[0] = key; + len = 1; + } + + if (modifiers) + { + *dest++ = CSI; + *dest++ = KS_MODIFIER; + *dest++ = modifiers; + km.length = 3; + } + } + memcpy((char *)dest, string, len); + km.length += len; + km.csi_escape = false; + } + + write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); + + /* + * blank out the pointer if necessary + */ + if (p_mh && !gui.pointer_hidden) + { + guiBlankMouse(true); + gui.pointer_hidden = TRUE; + } + } + void + VimTextAreaView::guiSendMouseEvent( + int button, + int x, + int y, + int repeated_click, + int_u modifiers) + { + VimMouseMsg mm; + + mm.button = button; + mm.x = x; + mm.y = y; + mm.repeated_click = repeated_click; + mm.modifiers = modifiers; + + write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm)); + // calls gui_send_mouse_event() + + /* + * if our pointer is currently hidden, then we should show it. + */ + if (gui.pointer_hidden) + { + guiBlankMouse(false); + gui.pointer_hidden = FALSE; + } + } + + void + VimTextAreaView::guiMouseMoved( + int x, + int y) + { + VimMouseMovedMsg mm; + + mm.x = x; + mm.y = y; + + write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm)); + + if (gui.pointer_hidden) + { + guiBlankMouse(false); + gui.pointer_hidden = FALSE; + } + } + + void + VimTextAreaView::guiBlankMouse(bool should_hide) + { + if (should_hide) { + // gui.vimApp->HideCursor(); + gui.vimApp->ObscureCursor(); + /* + * ObscureCursor() would even be easier, but then + * Vim's idea of mouse visibility does not necessarily + * correspond to reality. + */ + } else { + // gui.vimApp->ShowCursor(); + } + } + + int_u + VimTextAreaView::mouseModifiersToVim(int32 beModifiers) + { + int_u vim_modifiers = 0x0; + + if (beModifiers & B_SHIFT_KEY) + vim_modifiers |= MOUSE_SHIFT; + if (beModifiers & B_CONTROL_KEY) + vim_modifiers |= MOUSE_CTRL; + if (beModifiers & B_OPTION_KEY) // Alt or Meta key + vim_modifiers |= MOUSE_ALT; + + return vim_modifiers; + } + + void + VimTextAreaView::MouseDown(BPoint point) + { + BMessage *m = Window()->CurrentMessage(); + assert(m); + + int32 buttons = 0; + m->FindInt32("buttons", &buttons); + + int vimButton; + + if (buttons & B_PRIMARY_MOUSE_BUTTON) + vimButton = MOUSE_LEFT; + else if (buttons & B_SECONDARY_MOUSE_BUTTON) + vimButton = MOUSE_RIGHT; + else if (buttons & B_TERTIARY_MOUSE_BUTTON) + vimButton = MOUSE_MIDDLE; + else + return; // Unknown button + + vimMouseButton = 1; // don't care which one + + // Handle multiple clicks + int32 clicks = 0; + m->FindInt32("clicks", &clicks); + + int32 modifiers = 0; + m->FindInt32("modifiers", &modifiers); + + vimMouseModifiers = mouseModifiersToVim(modifiers); + + guiSendMouseEvent(vimButton, point.x, point.y, + clicks > 1 /* = repeated_click*/, vimMouseModifiers); + } + + void + VimTextAreaView::MouseUp(BPoint point) + { + vimMouseButton = 0; + + BMessage *m = Window()->CurrentMessage(); + assert(m); + // m->PrintToStream(); + + int32 modifiers = 0; + m->FindInt32("modifiers", &modifiers); + + vimMouseModifiers = mouseModifiersToVim(modifiers); + + guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y, + 0 /* = repeated_click*/, vimMouseModifiers); + + Inherited::MouseUp(point); + } + + void + VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) + { + /* + * if our pointer is currently hidden, then we should show it. + */ + if (gui.pointer_hidden) + { + guiBlankMouse(false); + gui.pointer_hidden = FALSE; + } + + if (!vimMouseButton) { // could also check m->"buttons" + guiMouseMoved(point.x, point.y); + return; + } + + atomic_add(&mouseDragEventCount, 1); + + // Don't care much about "transit" + guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers); + } + + void + VimTextAreaView::MessageReceived(BMessage *m) + { + switch (m->what) { + case 'menu': + { + VimMenuMsg mm; + mm.guiMenu = NULL; // in case no pointer in msg + m->FindPointer("VimMenu", (void **)&mm.guiMenu); + write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm)); + } + break; + case B_MOUSE_WHEEL_CHANGED: + { + VimScrollBar* scb = curwin->w_scrollbars[1].id; + float small=0, big=0, dy=0; + m->FindFloat("be:wheel_delta_y", &dy); + scb->GetSteps(&small, &big); + scb->SetValue(scb->Value()+small*dy*3); + scb->ValueChanged(scb->Value()); + #if 0 + scb = curwin->w_scrollbars[0].id; + scb->GetSteps(&small, &big); + scb->SetValue(scb->Value()+small*dy); + scb->ValueChanged(scb->Value()); + #endif + } + break; + #ifdef FEAT_MBYTE_IME + case B_INPUT_METHOD_EVENT: + { + int32 opcode; + m->FindInt32("be:opcode", &opcode); + switch(opcode) + { + case B_INPUT_METHOD_STARTED: + if(!IMData.messenger) delete IMData.messenger; + IMData.messenger = new BMessenger(); + m->FindMessenger("be:reply_to", IMData.messenger); + break; + case B_INPUT_METHOD_CHANGED: + { + BString str; + bool confirmed; + if(IMData.message) *(IMData.message) = *m; + else IMData.message = new BMessage(*m); + DrawIMString(); + m->FindBool("be:confirmed", &confirmed); + if (confirmed) + { + m->FindString("be:string", &str); + char_u *chars = (char_u*)str.String(); + struct VimKeyMsg km; + km.csi_escape = true; + int clen; + int i = 0; + while (i < str.Length()) + { + clen = utf_ptr2len(chars+i); + memcpy(km.chars, chars+i, clen); + km.length = clen; + write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km)); + i += clen; + } + } + } + break; + case B_INPUT_METHOD_LOCATION_REQUEST: + { + BMessage msg(B_INPUT_METHOD_EVENT); + msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST); + msg.AddPoint("be:location_reply", IMData.location); + msg.AddFloat("be:height_reply", FILL_Y(1)); + IMData.messenger->SendMessage(&msg); + } + break; + case B_INPUT_METHOD_STOPPED: + delete IMData.messenger; + delete IMData.message; + IMData.messenger = NULL; + IMData.message = NULL; + break; + } + } + // TODO: sz: break here??? + #endif + default: + if (m->WasDropped()) { + BWindow *w = Window(); + w->DetachCurrentMessage(); + w->Minimize(false); + VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0); + } else { + Inherited::MessageReceived(m); + } + break; + } + } + + int + VimTextAreaView::mchInitFont(char_u *name) + { + VimFont *newFont = (VimFont *)gui_mch_get_font(name, 1); + if(newFont != NOFONT) { + gui.norm_font = (GuiFont)newFont; + gui_mch_set_font((GuiFont)newFont); + if (name && STRCMP(name, "*") != 0) + hl_set_font_name(name); + + SetDrawingMode(B_OP_COPY); + + /* + * Try to load other fonts for bold, italic, and bold-italic. + * We should also try to work out what font to use for these when they are + * not specified by X resources, but we don't yet. + */ + return OK; + } + return FAIL; + } + + void + VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags) + { + /* + * First we must erase the area, because DrawString won't do + * that for us. XXX Most of the time this is a waste of effort + * since the bachground has been erased already... DRAW_TRANSP + * should be set when appropriate!!! + * (Rectangles include the bottom and right edge) + */ + if (!(flags & DRAW_TRANSP)) { + int cells; + cells = 0; + for(int i=0; iGetFont(&font); + if(!font.IsFixed()) + { + char* p = (char*)s; + int32 clen, lastpos = 0; + BPoint where; + int cells; + while((p - (char*)s) < len) { + clen = utf_ptr2len((u_char*)p); + where.Set(TEXT_X(col+lastpos), TEXT_Y(row)); + DrawString(p, clen, where); + if (flags & DRAW_BOLD) { + where.x += 1.0; + SetDrawingMode(B_OP_BLEND); + DrawString(p, clen, where); + SetDrawingMode(B_OP_COPY); + } + cells = utf_ptr2cells((char_u *)p); + if(cells<4) lastpos += cells; + else lastpos++; + p += clen; + } + } + else + { + BPoint where(TEXT_X(col), TEXT_Y(row)); + DrawString((char*)s, len, where); + if (flags & DRAW_BOLD) { + where.x += 1.0; + SetDrawingMode(B_OP_BLEND); + DrawString((char*)s, len, where); + SetDrawingMode(B_OP_COPY); + } + } + + if (flags & DRAW_UNDERL) { + int cells; + cells = 0; + for(int i=0; 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, W_WIDTH(curwin), GUI_MON_NOCLEAR); + bool confirmed = false; + msg->FindBool("be:confirmed", &confirmed); + if (confirmed) + return; + rgb_color hcolor = HighColor(), lcolor = LowColor(); + msg->FindString("be:string", &str); + s = str.String(); + len = str.Length(); + SetHighColor(0, 0, 0); + IMData.row = gui.row; + IMData.col = gui.col; + int32 sel_start = 0, sel_end = 0; + msg->FindInt32("be:selection", 0, &sel_start); + msg->FindInt32("be:selection", 1, &sel_end); + int clen, cn; + BPoint pos(IMData.col, 0); + BRect r; + BPoint where; + IMData.location = ConvertToScreen( + BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y))); + for (int i=0; i W_WIDTH(curwin)) + { + 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; + } + + if (vm.u.Key.csi_escape) + #ifndef FEAT_MBYTE_IME + { + int i; + char_u buf[2]; + + for (i = 0; i < len; ++i) + { + add_to_input_buf(string + i, 1); + if (string[i] == CSI) + { + // Turn CSI into K_CSI. + buf[0] = KS_EXTRA; + buf[1] = (int)KE_CSI; + add_to_input_buf(buf, 2); + } + } + } + #else + add_to_input_buf_csi(string, len); + #endif + else + add_to_input_buf(string, len); + } + break; + case VimMsg::Resize: + gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height); + break; + case VimMsg::ScrollBar: + { + /* + * If loads of scroll messages queue up, use only the last + * one. Always report when the scrollbar stops dragging. + * This is not perfect yet anyway: these events are queued + * yet again, this time in the keyboard input buffer. + */ + int32 oldCount = + atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1); + if (oldCount <= 1 || !vm.u.Scroll.stillDragging) + gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(), + vm.u.Scroll.value, vm.u.Scroll.stillDragging); + } + break; + #if defined(FEAT_MENU) + case VimMsg::Menu: + gui_menu_cb(vm.u.Menu.guiMenu); + break; + #endif + case VimMsg::Mouse: + { + int32 oldCount; + if (vm.u.Mouse.button == MOUSE_DRAG) + oldCount = + atomic_add(&gui.vimTextArea->mouseDragEventCount, -1); + else + oldCount = 0; + if (oldCount <= 1) + gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x, + vm.u.Mouse.y, vm.u.Mouse.repeated_click, + vm.u.Mouse.modifiers); + } + break; + case VimMsg::MouseMoved: + { + gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y); + } + break; + case VimMsg::Focus: + gui.in_focus = vm.u.Focus.active; + // XXX Signal that scrollbar dragging has stopped? + // This is needed because we don't get a MouseUp if + // that happens while outside the window... :-( + if (gui.dragged_sb) { + gui.dragged_sb = SBAR_NONE; + } + // gui_update_cursor(TRUE, FALSE); + break; + case VimMsg::Refs: + ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir); + break; + case VimMsg::Tabline: + send_tabline_event(vm.u.Tabline.index); + break; + case VimMsg::TablineMenu: + send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event); + break; + default: + // unrecognised message, ignore it + break; + } + } + + /* + * If size < B_OK, it is an error code. + */ + return size; + } + + /* + * Here are some functions to protect access to ScreenLines[] and + * LineOffset[]. These are used from the window thread to respond + * to a Draw() callback. When that occurs, the window is already + * locked by the system. + * + * Other code that needs to lock is any code that changes these + * variables. Other read-only access, or access merely to the + * contents of the screen buffer, need not be locked. + * + * If there is no window, don't call Lock() but do succeed. + */ + + int + vim_lock_screen() + { + return !gui.vimWindow || gui.vimWindow->Lock(); + } + + void + vim_unlock_screen() + { + if (gui.vimWindow) + gui.vimWindow->Unlock(); + } + + #define RUN_BAPPLICATION_IN_NEW_THREAD 0 + + #if RUN_BAPPLICATION_IN_NEW_THREAD + + int32 + run_vimapp(void *args) + { + VimApp app(appsig); + + gui.vimApp = &app; + app.Run(); // Run until Quit() called + + return 0; + } + + #else + + int32 + call_main(void *args) + { + struct MainArgs *ma = (MainArgs *)args; + + return main(ma->argc, ma->argv); + } + #endif + + /* + * Parse the GUI related command-line arguments. Any arguments used are + * deleted from argv, and *argc is decremented accordingly. This is called + * when vim is started, whether or not the GUI has been started. + */ + void + gui_mch_prepare( + int *argc, + char **argv) + { + /* + * We don't have any command line arguments for the BeOS GUI yet, + * but this is an excellent place to create our Application object. + */ + if (!gui.vimApp) { + thread_info tinfo; + get_thread_info(find_thread(NULL), &tinfo); + + // May need the port very early on to process RefsReceived() + gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP"); + + #if RUN_BAPPLICATION_IN_NEW_THREAD + thread_id tid = spawn_thread(run_vimapp, "vim VimApp", + tinfo.priority, NULL); + if (tid >= B_OK) { + resume_thread(tid); + } else { + getout(1); + } + #else + MainArgs ma = { *argc, argv }; + thread_id tid = spawn_thread(call_main, "vim main()", + tinfo.priority, &ma); + if (tid >= B_OK) { + VimApp app(appsig); + + gui.vimApp = &app; + resume_thread(tid); + /* + * This is rather horrible. + * call_main will call main() again... + * There will be no infinite recursion since + * gui.vimApp is set now. + */ + app.Run(); // Run until Quit() called + // fprintf(stderr, "app.Run() returned...\n"); + status_t dummy_exitcode; + (void)wait_for_thread(tid, &dummy_exitcode); + + /* + * This path should be the normal one taken to exit Vim. + * The main() thread calls mch_exit() which calls + * gui_mch_exit() which terminates its thread. + */ + exit(main_exitcode); + } + #endif + } + // Don't fork() when starting the GUI. Spawned threads are not + // duplicated with a fork(). The result is a mess. + gui.dofork = FALSE; + /* + * XXX Try to determine whether we were started from + * the Tracker or the terminal. + * It would be nice to have this work, because the Tracker + * follows symlinks, so even if you double-click on gvim, + * when it is a link to vim it will still pass a command name + * of vim... + * We try here to see if stdin comes from /dev/null. If so, + * (or if there is an error, which should never happen) start the GUI. + * This does the wrong thing for vim - 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(); + } + } + + #if defined(FEAT_WINDOWS) || defined(PROTO) + void + gui_mch_destroy_scrollbar( + scrollbar_T *sb) + { + if (gui.vimWindow->Lock()) { + sb->id->RemoveSelf(); + delete sb->id; + gui.vimWindow->Unlock(); + } + } + #endif + + /* + * Cursor does not flash + */ + int + gui_mch_is_blink_off(void) + { + return FALSE; + } + + /* + * Cursor blink functions. + * + * This is a simple state machine: + * BLINK_NONE not blinking at all + * BLINK_OFF blinking, cursor is not shown + * BLINK_ON blinking, cursor is shown + */ + + #define BLINK_NONE 0 + #define BLINK_OFF 1 + #define BLINK_ON 2 + + static int blink_state = BLINK_NONE; + static long_u blink_waittime = 700; + static long_u blink_ontime = 400; + static long_u blink_offtime = 250; + static int blink_timer = 0; + + void + gui_mch_set_blinking( + long waittime, + long on, + long off) + { + // TODO + blink_waittime = waittime; + blink_ontime = on; + blink_offtime = off; + } + + /* + * Stop the cursor blinking. Show the cursor if it wasn't shown. + */ + void + gui_mch_stop_blink() + { + // TODO + if (blink_timer != 0) + { + // XtRemoveTimeOut(blink_timer); + blink_timer = 0; + } + if (blink_state == BLINK_OFF) + gui_update_cursor(TRUE, FALSE); + blink_state = BLINK_NONE; + } + + /* + * Start the cursor blinking. If it was already blinking, this restarts the + * waiting time and shows the cursor. + */ + void + gui_mch_start_blink() + { + // TODO + if (blink_timer != 0) + ;// XtRemoveTimeOut(blink_timer); + // Only switch blinking on if none of the times is zero + if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) + { + blink_timer = 1; // XtAppAddTimeOut(app_context, blink_waittime, + blink_state = BLINK_ON; + gui_update_cursor(TRUE, FALSE); + } + } + + /* + * Initialise vim to use the font with the given name. Return FAIL if the font + * could not be loaded, OK otherwise. + */ + int + gui_mch_init_font( + char_u *font_name, + int fontset) + { + if (gui.vimWindow->Lock()) + { + int rc = gui.vimTextArea->mchInitFont(font_name); + gui.vimWindow->Unlock(); + + return rc; + } + + return FAIL; + } + + + int + gui_mch_adjust_charsize() + { + return FAIL; + } + + + int + gui_mch_font_dialog(font_family* family, font_style* style, float* size) + { + #if defined(FEAT_GUI_DIALOG) + // gui.vimWindow->Unlock(); + VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size); + return dialog->Go(); + #else + return NOFONT; + #endif // FEAT_GUI_DIALOG + } + + + GuiFont + gui_mch_get_font( + char_u *name, + int giveErrorIfMissing) + { + static VimFont *fontList = NULL; + + if (!gui.in_use) // can't do this when GUI not running + return NOFONT; + + // storage for locally modified name; + const int buff_size = B_FONT_FAMILY_LENGTH + B_FONT_STYLE_LENGTH + 20; + static char font_name[buff_size] = {0}; + font_family family = {0}; + font_style style = {0}; + float size = 0.f; + + if (name == 0 && be_fixed_font == 0) { + if(giveErrorIfMissing) + semsg(_(e_font), 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) + semsg(_(e_font), 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(); + } + } + + guicolor_T + gui_mch_get_rgb_color(int r, int g, int b) + { + return gui_get_rgb_color_cmn(r, g, b); + } + + + // Return OK if the key with the termcap name "name" is supported. + int + gui_mch_haskey( + char_u *name) + { + int i; + + for (i = 0; special_keys[i].BeKeys != 0; i++) + if (name[0] == special_keys[i].vim_code0 && + name[1] == special_keys[i].vim_code1) + return OK; + return FAIL; + } + + void + gui_mch_beep() + { + ::beep(); + } + + void + gui_mch_flash(int msec) + { + // Do a visual beep by reversing the foreground and background colors + + if (gui.vimWindow->Lock()) { + BRect rect = gui.vimTextArea->Bounds(); + + gui.vimTextArea->SetDrawingMode(B_OP_INVERT); + gui.vimTextArea->FillRect(rect); + gui.vimTextArea->Sync(); + snooze(msec * 1000); // wait for a few msec + gui.vimTextArea->FillRect(rect); + gui.vimTextArea->SetDrawingMode(B_OP_COPY); + gui.vimTextArea->Flush(); + gui.vimWindow->Unlock(); + } + } + + /* + * Invert a rectangle from row r, column c, for nr rows and nc columns. + */ + void + gui_mch_invert_rectangle( + int r, + int c, + int nr, + int nc) + { + BRect rect; + rect.left = FILL_X(c); + rect.top = FILL_Y(r); + rect.right = rect.left + nc * gui.char_width - PEN_WIDTH; + rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH; + + if (gui.vimWindow->Lock()) { + gui.vimTextArea->SetDrawingMode(B_OP_INVERT); + gui.vimTextArea->FillRect(rect); + gui.vimTextArea->SetDrawingMode(B_OP_COPY); + gui.vimWindow->Unlock(); + } + } + + /* + * Iconify the GUI window. + */ + void + gui_mch_iconify() + { + if (gui.vimWindow->Lock()) { + gui.vimWindow->Minimize(true); + gui.vimWindow->Unlock(); + } + } + + #if defined(FEAT_EVAL) || defined(PROTO) + /* + * Bring the Vim window to the foreground. + */ + void + gui_mch_set_foreground(void) + { + // TODO + } + #endif + + /* + * Set the window title + */ + void + gui_mch_settitle( + char_u *title, + char_u *icon) + { + if (gui.vimWindow->Lock()) { + gui.vimWindow->SetTitle((char *)title); + gui.vimWindow->Unlock(); + } + } + + /* + * Draw a cursor without focus. + */ + void + gui_mch_draw_hollow_cursor(guicolor_T color) + { + gui_mch_set_fg_color(color); + + BRect r; + r.left = FILL_X(gui.col); + r.top = FILL_Y(gui.row); + int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); // TODO-TODO + if(cells>=4) cells = 1; + r.right = r.left + cells*gui.char_width - PEN_WIDTH; + r.bottom = r.top + gui.char_height - PEN_WIDTH; + + if (gui.vimWindow->Lock()) { + gui.vimTextArea->StrokeRect(r); + gui.vimWindow->Unlock(); + // gui_mch_flush(); + } + } + + /* + * Draw part of a cursor, only w pixels wide, and h pixels high. + */ + void + gui_mch_draw_part_cursor( + int w, + int h, + guicolor_T color) + { + gui_mch_set_fg_color(color); + + BRect r; + r.left = + #ifdef FEAT_RIGHTLEFT + // vertical line should be on the right of current point + CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : + #endif + FILL_X(gui.col); + r.right = r.left + w - PEN_WIDTH; + r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH; + r.top = r.bottom - h + PEN_WIDTH; + + if (gui.vimWindow->Lock()) { + gui.vimTextArea->FillRect(r); + gui.vimWindow->Unlock(); + // gui_mch_flush(); + } + } + + /* + * Catch up with any queued events. This may put keyboard input into the + * input buffer, call resize call-backs, trigger timers etc. If there is + * nothing in the event queue (& no timers pending), then we return + * immediately. + */ + void + gui_mch_update() + { + gui_mch_flush(); + while (port_count(gui.vdcmp) > 0 && + !vim_is_input_buf_full() && + gui_haiku_process_event(0) >= B_OK) + /* nothing */ ; + } + + /* + * GUI input routine called by gui_wait_for_chars(). Waits for a character + * from the keyboard. + * wtime == -1 Wait forever. + * wtime == 0 This should never happen. + * wtime > 0 Wait wtime milliseconds for a character. + * Returns OK if a character was found to be available within the given time, + * or FAIL otherwise. + */ + int + gui_mch_wait_for_chars( + int wtime) + { + int focus; + bigtime_t until, timeout; + status_t st; + + if (wtime >= 0) { + timeout = wtime * 1000; + until = system_time() + timeout; + } else { + timeout = B_INFINITE_TIMEOUT; + } + + focus = gui.in_focus; + for (;;) + { + // Stop or start blinking when focus changes + if (gui.in_focus != focus) + { + if (gui.in_focus) + gui_mch_start_blink(); + else + gui_mch_stop_blink(); + 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(Clipboard_T *cbd) + { + if (be_clipboard->Lock()) + { + BMessage *m = be_clipboard->Data(); + // m->PrintToStream(); + + char_u *string = NULL; + ssize_t stringlen = -1; + + if (m->FindData(textplain, B_MIME_TYPE, + (const void **)&string, &stringlen) == B_OK + || m->FindString("text", (const char **)&string) == B_OK) + { + if (stringlen == -1) + stringlen = STRLEN(string); + + int type; + char *seltype; + ssize_t seltypelen; + + /* + * Try to get the special vim selection type first + */ + if (m->FindData(vimselectiontype, B_MIME_TYPE, + (const void **)&seltype, &seltypelen) == B_OK) + { + switch (*seltype) + { + default: + case 'L': type = MLINE; break; + case 'C': type = MCHAR; break; + #ifdef FEAT_VISUAL + case 'B': type = MBLOCK; break; + #endif + } + } + else + { + // Otherwise use heuristic as documented + type = memchr(string, stringlen, '\n') ? MLINE : MCHAR; + } + clip_yank_selection(type, string, (long)stringlen, cbd); + } + be_clipboard->Unlock(); + } + } + /* + * Make vim the owner of the current selection. + */ + void + clip_mch_lose_selection(Clipboard_T *cbd) + { + // Nothing needs to be done here + } + + /* + * Make vim the owner of the current selection. Return OK upon success. + */ + int + clip_mch_own_selection(Clipboard_T *cbd) + { + /* + * Never actually own the clipboard. If another application sets the + * clipboard, we don't want to think that we still own it. + */ + return FAIL; + } + + /* + * Send the current selection to the clipboard. + */ + void + clip_mch_set_selection(Clipboard_T *cbd) + { + if (be_clipboard->Lock()) + { + be_clipboard->Clear(); + BMessage *m = be_clipboard->Data(); + assert(m); + + // If the '*' register isn't already filled in, fill it in now + cbd->owned = TRUE; + clip_get_selection(cbd); + cbd->owned = FALSE; + + char_u *str = NULL; + long_u count; + int type; + + type = clip_convert_selection(&str, &count, cbd); + + if (type < 0) + return; + + m->AddData(textplain, B_MIME_TYPE, (void *)str, count); + + // Add type of selection + char vtype; + switch (type) + { + default: + case MLINE: vtype = 'L'; break; + case MCHAR: vtype = 'C'; break; + #ifdef FEAT_VISUAL + case MBLOCK: vtype = 'B'; break; + #endif + } + m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1); + + vim_free(str); + + be_clipboard->Commit(); + be_clipboard->Unlock(); + } + } + + #endif // FEAT_CLIPBOARD + + #ifdef FEAT_BROWSE + /* + * Pop open a file browser and return the file selected, in allocated memory, + * or NULL if Cancel is hit. + * saving - TRUE if the file will be saved to, FALSE if it will be opened. + * title - Title message for the file browser dialog. + * dflt - Default name of file. + * ext - Default extension to be added to files without extensions. + * initdir - directory in which to open the browser (NULL = current dir) + * filter - Filter for matched files to choose from. + * Has a format like this: + * "C Files (*.c)\0*.c\0" + * "All Files\0*.*\0\0" + * If these two strings were concatenated, then a choice of two file + * filters will be selectable to the user. Then only matching files will + * be shown in the browser. If NULL, the default allows all files. + * + * *NOTE* - the filter string must be terminated with TWO nulls. + */ + char_u * + gui_mch_browse( + int saving, + char_u *title, + char_u *dflt, + char_u *ext, + char_u *initdir, + char_u *filter) + { + gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL, + NULL, NULL, 0, false, + new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true); + + gui.vimApp->fBrowsedPath.Unset(); + + gui.vimApp->fFilePanel->Window()->SetTitle((char*)title); + gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir); + + gui.vimApp->fFilePanel->Show(); + + gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem"); + + while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED); + + char_u *fileName = NULL; + status_t result = gui.vimApp->fBrowsedPath.InitCheck(); + if(result == B_OK) { + fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path()); + } else + if(result != B_NO_INIT) { + fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n", + result, strerror(result)); + } + + delete gui.vimApp->fFilePanel; + gui.vimApp->fFilePanel = NULL; + + return fileName; + } + #endif // FEAT_BROWSE + + + #if defined(FEAT_GUI_DIALOG) + + /* + * Create a dialog dynamically from the parameter strings. + * type = type of dialog (question, alert, etc.) + * title = dialog title. may be NULL for default title. + * message = text to display. Dialog sizes to accommodate it. + * buttons = '\n' separated list of button captions, default first. + * dfltbutton = number of default button. + * + * This routine returns 1 if the first button is pressed, + * 2 for the second, etc. + * + * 0 indicates Esc was pressed. + * -1 for unexpected error + * + * If stubbing out this fn, return 1. + */ + + int + gui_mch_dialog( + int type, + char_u *title, + char_u *message, + char_u *buttons, + int dfltbutton, + char_u *textfield, + int ex_cmd) + { + VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message, + (char*)buttons, dfltbutton, (char*)textfield, ex_cmd); + return dialog->Go(); + } + + #endif // FEAT_GUI_DIALOG + + + /* + * Return the RGB value of a pixel as long. + */ + guicolor_T + gui_mch_get_rgb(guicolor_T pixel) + { + rgb_color rgb = GUI_TO_RGB(pixel); + + return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8) + + (rgb.blue & 0xff); + } + + void + gui_mch_setmouse(int x, int y) + { + TRACE(); + // TODO + } + + #ifdef FEAT_MBYTE_IME + void + im_set_position(int row, int col) + { + if(gui.vimWindow->Lock()) + { + gui.vimTextArea->DrawIMString(); + gui.vimWindow->Unlock(); + } + return; + } + #endif + + void + gui_mch_show_toolbar(int showit) + { + VimToolbar *toolbar = gui.vimForm->ToolBar(); + gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.; + } + + void + gui_mch_set_toolbar_pos(int x, int y, int w, int h) + { + VimToolbar *toolbar = gui.vimForm->ToolBar(); + if(toolbar != NULL) { + if (gui.vimWindow->Lock()) { + toolbar->MoveTo(x, y); + toolbar->ResizeTo(w - 1, h - 1); + gui.vimWindow->Unlock(); + } + } + } + + #if defined(FEAT_GUI_TABLINE) || defined(PROTO) + + /* + * Show or hide the tabline. + */ + void + gui_mch_show_tabline(int showit) + { + VimTabLine *tabLine = gui.vimForm->TabLine(); + + if (tabLine == NULL) + return; + + if (!showit != !gui.vimForm->IsShowingTabLine()) { + gui.vimForm->SetShowingTabLine(showit != 0); + gui.tabline_height = gui.vimForm->TablineHeight(); + } + } + + void + gui_mch_set_tabline_pos(int x, int y, int w, int h) + { + VimTabLine *tabLine = gui.vimForm->TabLine(); + if(tabLine != NULL) { + if (gui.vimWindow->Lock()) { + tabLine->MoveTo(x, y); + tabLine->ResizeTo(w - 1, h - 1); + gui.vimWindow->Unlock(); + } + } + } + + /* + * Return TRUE when tabline is displayed. + */ + int + gui_mch_showing_tabline() + { + VimTabLine *tabLine = gui.vimForm->TabLine(); + return tabLine != NULL && gui.vimForm->IsShowingTabLine(); + } + + /* + * Update the labels of the tabline. + */ + void + gui_mch_update_tabline() + { + tabpage_T *tp; + int nr = 0; + int curtabidx = 0; + + VimTabLine *tabLine = gui.vimForm->TabLine(); + + if (tabLine == NULL) + return; + + gui.vimWindow->Lock(); + + // Add a label for each tab page. They all contain the same text area. + for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) { + if (tp == curtab) + curtabidx = nr; + + BTab* tab = tabLine->TabAt(nr); + + if (tab == NULL) { + tab = new VimTabLine::VimTab(); + tabLine->AddTab(NULL, tab); + } + + get_tabline_label(tp, FALSE); + tab->SetLabel((const char*)NameBuff); + tabLine->Invalidate(); + } + + // Remove any old labels. + while (nr < tabLine->CountTabs()) + tabLine->RemoveTab(nr); + + if(tabLine->Selection() != curtabidx) + tabLine->Select(curtabidx); + + gui.vimWindow->Unlock(); + } + + /* + * Set the current tab to "nr". First tab is 1. + */ + void + gui_mch_set_curtab(int nr) + { + VimTabLine *tabLine = gui.vimForm->TabLine(); + if(tabLine == NULL) + return; + + gui.vimWindow->Lock(); + + if(tabLine->Selection() != nr -1) + tabLine->Select(nr -1); + + gui.vimWindow->Unlock(); + } + + #endif // FEAT_GUI_TABLINE *** ../vim-8.2.0319/src/gui_haiku.h 2020-02-26 16:11:39.333157180 +0100 --- src/gui_haiku.h 2020-02-26 15:04:22.057672547 +0100 *************** *** 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 *** ../vim-8.2.0319/src/mbyte.c 2020-01-26 21:59:25.624718145 +0100 --- src/mbyte.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 6488,6494 **** # endif } ! # if defined(FEAT_GUI) && !defined(VIMDLL) void im_set_position(int row UNUSED, int col UNUSED) { --- 6488,6494 ---- # endif } ! # if defined(FEAT_GUI) && !defined(FEAT_GUI_HAIKU) && !defined(VIMDLL) void im_set_position(int row UNUSED, int col UNUSED) { *** ../vim-8.2.0319/src/menu.c 2019-12-04 21:56:33.000000000 +0100 --- src/menu.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 2525,2531 **** } #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \ ! || defined(FEAT_TERM_POPUP_MENU) \ || defined(FEAT_BEVAL_TIP) || defined(PROTO) /* * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy. --- 2525,2531 ---- } #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \ ! || defined(FEAT_TERM_POPUP_MENU) || defined(FEAT_GUI_HAIKU) \ || defined(FEAT_BEVAL_TIP) || defined(PROTO) /* * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy. *** ../vim-8.2.0319/src/misc1.c 2020-02-14 13:21:55.646197062 +0100 --- src/misc1.c 2020-02-26 15:58:27.151864968 +0100 *************** *** 14,19 **** --- 14,23 ---- #include "vim.h" #include "version.h" + #if defined(__HAIKU__) + # include + #endif + #if defined(MSWIN) # include #endif *************** *** 1667,1672 **** --- 1671,1688 ---- // handling $VIMRUNTIME and $VIM is below, bail out if it's another name. vimruntime = (STRCMP(name, "VIMRUNTIME") == 0); if (!vimruntime && STRCMP(name, "VIM") != 0) + #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; /* *** ../vim-8.2.0319/src/mouse.c 2020-02-01 21:57:00.848520936 +0100 --- src/mouse.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 538,544 **** // menu on the button down event. return FALSE; # endif ! # if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) if (is_click || is_drag) // Ignore right button down and drag mouse events. Windows // only shows the popup menu on the button up event. --- 538,544 ---- // menu on the button down event. return FALSE; # endif ! # if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU) if (is_click || is_drag) // Ignore right button down and drag mouse events. Windows // only shows the popup menu on the button up event. *** ../vim-8.2.0319/src/option.h 2020-01-26 21:59:25.628718127 +0100 --- src/option.h 2020-02-26 16:00:27.071442055 +0100 *************** *** 10,15 **** --- 10,18 ---- * option.h: definition of global variables for settable options */ + #ifndef _OPTION_H_ + #define _OPTION_H_ + // // Flags // *************** *** 1290,1292 **** --- 1293,1297 ---- // Value for b_p_ul indicating the global value must be used. #define NO_LOCAL_UNDOLEVEL -123456 + + #endif // _OPTION_H_ *** ../vim-8.2.0319/src/os_haiku.h 2020-02-26 16:11:39.365157074 +0100 --- src/os_haiku.h 2020-02-26 15:15:29.303754268 +0100 *************** *** 0 **** --- 1,37 ---- + /* 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_EXRC_FILE2 USR_VIM_DIR "/vim/exrc" + #define USR_VIMRC_FILE USR_VIM_DIR "/vimrc" + #define USR_VIMRC_FILE2 USR_VIM_DIR "/vim/vimrc" + #define USR_GVIMRC_FILE USR_VIM_DIR "/gvimrc" + #define USR_GVIMRC_FILE2 USR_VIM_DIR "/vim/gvimrc" + #define VIMINFO_FILE USR_VIM_DIR "/viminfo" + + #ifdef RUNTIME_GLOBAL + # ifdef RUNTIME_GLOBAL_AFTER + # define DFLT_RUNTIMEPATH USR_VIM_DIR "," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "," USR_VIM_DIR "/after" + # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER + # else + # define DFLT_RUNTIMEPATH USR_VIM_DIR "," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after," USR_VIM_DIR "/after" + # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after" + # endif + #else + # define DFLT_RUNTIMEPATH USR_VIM_DIR ",$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after," USR_VIM_DIR "/after" + # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" + #endif *** ../vim-8.2.0319/src/os_haiku.rdef 2020-02-26 16:11:39.369157058 +0100 --- src/os_haiku.rdef 2020-02-26 15:04:22.061672533 +0100 *************** *** 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" + }; *** ../vim-8.2.0319/src/os_unix.c 2020-02-15 23:06:40.822770278 +0100 --- src/os_unix.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 2151,2157 **** if (get_x11_windis() == OK) type = 1; #else ! # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) if (gui.in_use) type = 1; # endif --- 2151,2158 ---- if (get_x11_windis() == OK) type = 1; #else ! # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \ ! || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) if (gui.in_use) type = 1; # endif *************** *** 2184,2190 **** # endif set_x11_title(title); // x11 #endif ! #if defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) else gui_mch_settitle(title, icon); --- 2185,2191 ---- # endif set_x11_title(title); // x11 #endif ! #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) \ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) else gui_mch_settitle(title, icon); *************** *** 4591,4597 **** { SIGSET_DECL(curset) ! # ifdef __BEOS__ beos_cleanup_read_thread(); # endif --- 4592,4598 ---- { SIGSET_DECL(curset) ! # if defined(__BEOS__) && USE_THREAD_FOR_INPUT_WITH_TIMEOUT beos_cleanup_read_thread(); # endif *** ../vim-8.2.0319/src/os_unix.h 2019-11-30 18:51:58.000000000 +0100 --- src/os_unix.h 2020-02-26 16:01:11.491287101 +0100 *************** *** 364,385 **** #define DFLT_ERRORFILE "errors.err" ! #ifdef VMS ! # define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after" ! # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" ! #else ! # ifdef RUNTIME_GLOBAL ! # ifdef RUNTIME_GLOBAL_AFTER ! # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after" ! # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER # else ! # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after" ! # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after" # endif - # else - # define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after" - # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" # endif #endif #ifdef VMS --- 364,389 ---- #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" ! # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" ! # else ! # ifdef RUNTIME_GLOBAL ! # ifdef RUNTIME_GLOBAL_AFTER ! # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after" ! # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ! # else ! # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after" ! # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after" ! # endif # else ! # define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after" ! # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" # endif # endif + #endif #ifdef VMS *** ../vim-8.2.0319/src/osdef1.h.in 2018-08-22 21:54:20.000000000 +0200 --- src/osdef1.h.in 2020-02-26 15:04:22.061672533 +0100 *************** *** 65,71 **** # endif # endif #endif ! #ifndef __BIONIC__ // Android's libc #defines bzero to memset. // used inside of FD_ZERO macro extern void bzero(void *, size_t); #endif --- 65,71 ---- # endif # endif #endif ! #if !defined(__BIONIC__) && !defined(__HAIKU__) // Android's libc #defines bzero to memset. // used inside of FD_ZERO macro extern void bzero(void *, size_t); #endif *** ../vim-8.2.0319/src/proto.h 2020-02-14 13:21:55.646197062 +0100 --- src/proto.h 2020-02-26 15:04:22.061672533 +0100 *************** *** 313,318 **** --- 313,321 ---- 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 *** ../vim-8.2.0319/src/proto/gui_haiku.pro 2020-02-26 16:11:39.389156990 +0100 --- src/proto/gui_haiku.pro 2020-02-26 15:04:22.061672533 +0100 *************** *** 0 **** --- 1,95 ---- + /* gui_haiku.cc - hand crafted */ + + void gui_mch_prepare(int *argc, char **argv); + int gui_mch_init(void); + int gui_mch_open(void); + void gui_mch_exit(int vim_exitcode); + int gui_mch_init_check(void); + void gui_mch_flush(void); + + void gui_mch_new_colors(void); + void gui_mch_set_bg_color(guicolor_T color); + void gui_mch_set_fg_color(guicolor_T color); + void gui_mch_set_sp_color(guicolor_T color); + guicolor_T gui_mch_get_rgb(guicolor_T pixel); + guicolor_T gui_mch_get_rgb_color(int r, int g, int b); + guicolor_T gui_mch_get_color(char_u *name); + + GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing); + void gui_mch_set_font(GuiFont font); + int gui_mch_init_font(char_u *font_name, int fontset); + void gui_mch_free_font(GuiFont font); + char_u *gui_mch_get_fontname(GuiFont font, char_u *name); + + void gui_mch_set_winpos(int x, int y); + int gui_mch_get_winpos(int *x, int *y); + void gui_mch_set_shellsize(int w, int h, int m_w, int m_h, int b_w, int b_h, int d); + void gui_mch_get_screen_dimensions(int* screen_w, int* screen_h); + void gui_mch_set_text_area_pos(int x, int y, int w, int h); + + void gui_mch_enable_scrollbar(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_thumb(scrollbar_T *sb, int val, int size, int max); + + void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h); + void gui_mch_create_scrollbar(scrollbar_T *sb, int orient); + void gui_mch_destroy_scrollbar(scrollbar_T *sb); + + void gui_mch_set_blinking(long waittime, long on, long off); + void gui_mch_stop_blink(int may_call_gui_update_cursor); + void gui_mch_start_blink(void); + + int gui_mch_adjust_charheight(void); + void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags); + int gui_mch_haskey(char_u *name); + void gui_mch_beep(void); + void gui_mch_flash(int msec); + void gui_mch_invert_rectangle(int r, int c, int nr, int nc); + void gui_mch_iconify(void); + void gui_mch_set_foreground(void); + void gui_mch_settitle(char_u *title, char_u *icon); + void gui_mch_draw_hollow_cursor(guicolor_T color); + void gui_mch_draw_part_cursor(int w, int h, guicolor_T color); + void gui_mch_update(void); + int gui_mch_wait_for_chars(int wtime); + void gui_mch_clear_block(int row1, int col1, int row2, int col2); + void gui_mch_clear_all(void); + void gui_mch_delete_lines(int row, int num_lines); + void gui_mch_insert_lines(int row, int num_lines); + + void gui_mch_getmouse(int *x, int *y); + void gui_mch_setmouse(int x, int y); + void gui_mch_mousehide(int hide); + + void gui_mch_enable_menu(int flag); + void gui_mch_set_menu_pos(int x, int y, int w, int h); + void gui_mch_add_menu(vimmenu_T *menu, int idx); + void gui_mch_add_menu_item(vimmenu_T *menu, int idx); + void gui_mch_destroy_menu(vimmenu_T *menu); + void gui_mch_menu_grey(vimmenu_T *menu, int grey); + void gui_mch_menu_hidden(vimmenu_T *menu, int hidden); + void gui_mch_draw_menubar(void); + void gui_mch_show_popupmenu(vimmenu_T *menu); + void gui_mch_toggle_tearoffs(int enable); + + void clip_mch_request_selection(Clipboard_T *cbd); + void clip_mch_set_selection(Clipboard_T *cbd); + void clip_mch_lose_selection(Clipboard_T *cbd); + int clip_mch_own_selection(Clipboard_T *cbd); + + char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter); + int gui_mch_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd); + + void im_set_position(int row, int col); + void im_set_active(int activate); + int im_get_status(void); + + void gui_mch_show_toolbar(int showit); + void gui_mch_set_toolbar_pos(int x, int y, int w, int h); + + void gui_mch_show_tabline(int showit); + void gui_mch_set_tabline_pos(int x, int y, int w, int h); + int gui_mch_showing_tabline(void); + void gui_mch_update_tabline(void); + void gui_mch_set_curtab(int nr); *** ../vim-8.2.0319/src/pty.c 2019-12-05 20:55:12.000000000 +0100 --- src/pty.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 386,392 **** static char PtyProto[] = "/dev/ptym/ptyXY"; static char TtyProto[] = "/dev/pty/ttyXY"; # else ! # ifdef __BEOS__ static char PtyProto[] = "/dev/pt/XY"; static char TtyProto[] = "/dev/tt/XY"; # else --- 386,392 ---- static char PtyProto[] = "/dev/ptym/ptyXY"; static char TtyProto[] = "/dev/pty/ttyXY"; # else ! # if defined (__BEOS__) || defined(__HAIKU__) static char PtyProto[] = "/dev/pt/XY"; static char TtyProto[] = "/dev/tt/XY"; # else *** ../vim-8.2.0319/src/screen.c 2019-12-06 19:04:54.000000000 +0100 --- src/screen.c 2020-02-26 16:04:26.470615479 +0100 *************** *** 2549,2554 **** --- 2549,2558 ---- 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 /* *************** *** 2799,2804 **** --- 2803,2812 ---- #endif clear_TabPageIdxs(); + #ifdef FEAT_GUI_HAIKU + vim_unlock_screen(); + #endif + entered = FALSE; --RedrawingDisabled; *************** *** 3646,3651 **** --- 3654,3663 ---- 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. *************** *** 3700,3705 **** --- 3712,3721 ---- } } + #ifdef FEAT_GUI_HAIKU + vim_unlock_screen(); + #endif + screen_stop_highlight(); windgoto(cursor_row, cursor_col); if (clear_attr != 0) *************** *** 3928,3933 **** --- 3944,3953 ---- } } + #ifdef FEAT_GUI_HAIKU + vim_unlock_screen(); + #endif + if (screen_attr != clear_attr) screen_stop_highlight(); if (clear_attr != 0) *** ../vim-8.2.0319/src/structs.h 2020-02-25 21:26:46.275580512 +0100 --- src/structs.h 2020-02-26 15:04:22.061672533 +0100 *************** *** 3643,3648 **** --- 3643,3655 ---- 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 *** ../vim-8.2.0319/src/term.c 2020-02-22 22:45:52.206471481 +0100 --- src/term.c 2020-02-26 15:04:22.061672533 +0100 *************** *** 1420,1425 **** --- 1420,1430 ---- # 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 *** ../vim-8.2.0319/src/version.c 2020-02-26 13:43:48.646089639 +0100 --- src/version.c 2020-02-26 15:14:03.219888557 +0100 *************** *** 1722,1727 **** --- 1724,1732 ---- 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 *************** *** 1736,1741 **** --- 1741,1747 ---- # else # endif # endif + # endif # endif # endif # endif *** ../vim-8.2.0319/src/vim.h 2020-02-22 14:26:39.244757847 +0100 --- src/vim.h 2020-02-26 15:04:22.061672533 +0100 *************** *** 103,108 **** --- 103,109 ---- #if defined(FEAT_GUI_MOTIF) \ || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_ATHENA) \ + || defined(FEAT_GUI_HAIKU) \ || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_MSWIN) \ || defined(FEAT_GUI_PHOTON) *************** *** 223,228 **** --- 224,234 ---- # 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 *************** *** 2075,2080 **** --- 2081,2089 ---- 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 } Clipboard_T; #else typedef int Clipboard_T; // This is required for the prototypes. *************** *** 2136,2142 **** // functions of these names. The declarations would break if the defines had // been seen at that stage. But it must be before globals.h, where error_ga // is declared. ! #if !defined(MSWIN) && !defined(FEAT_GUI_X11) \ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) # define mch_errmsg(str) fprintf(stderr, "%s", (str)) # define display_errors() fflush(stderr) --- 2145,2151 ---- // functions of these names. The declarations would break if the defines had // been seen at that stage. But it must be before globals.h, where error_ga // is declared. ! #if !defined(MSWIN) && !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_HAIKU) \ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) # define mch_errmsg(str) fprintf(stderr, "%s", (str)) # define display_errors() fflush(stderr) *** ../vim-8.2.0319/src/version.c 2020-02-26 13:43:48.646089639 +0100 --- src/version.c 2020-02-26 15:14:03.219888557 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 320, /**/ -- Would you care for a drink? I mean, if it were, like, disabled and you had to look after it? /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///