To: vim_dev@googlegroups.com Subject: Patch 8.1.2062 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2062 Problem: The mouse code is spread out. Solution: Move all the mouse code to mouse.c. (Yegappan Lakshmanan, closes #4959) Files: Filelist, src/Make_cyg_ming.mak, src/Make_morph.mak, src/Make_mvc.mak, src/Make_vms.mms, src/Makefile, src/README.md, src/auto/configure, src/configure.ac, src/edit.c, src/ex_cmds.c, src/ex_docmd.c, src/ex_getln.c, src/insexpand.c, src/libvterm/src/termmouse.c, src/libvterm/src/mouse.c, src/main.c, src/message.c, src/misc1.c, src/misc2.c, src/mouse.c, src/normal.c, src/proto.h, src/proto/edit.pro, src/proto/misc1.pro, src/proto/misc2.pro, src/proto/mouse.pro, src/proto/normal.pro, src/proto/term.pro, src/proto/ui.pro, src/search.c, src/term.c, src/ui.c, src/vim.h, src/window.c *** ../vim-8.1.2061/Filelist 2019-09-19 23:05:56.467034962 +0200 --- Filelist 2019-09-21 20:13:48.593908424 +0200 *************** *** 80,85 **** --- 80,86 ---- src/message_test.c \ src/misc1.c \ src/misc2.c \ + src/mouse.c \ src/move.c \ src/mysign \ src/nbdebug.c \ *************** *** 231,236 **** --- 232,238 ---- src/proto/message.pro \ src/proto/misc1.pro \ src/proto/misc2.pro \ + src/proto/mouse.pro \ src/proto/move.pro \ src/proto/netbeans.pro \ src/proto/normal.pro \ *** ../vim-8.1.2061/src/Make_cyg_ming.mak 2019-09-19 23:05:56.467034962 +0200 --- src/Make_cyg_ming.mak 2019-09-21 20:13:48.593908424 +0200 *************** *** 754,759 **** --- 754,760 ---- $(OUTDIR)/message.o \ $(OUTDIR)/misc1.o \ $(OUTDIR)/misc2.o \ + $(OUTDIR)/mouse.o \ $(OUTDIR)/move.o \ $(OUTDIR)/mbyte.o \ $(OUTDIR)/normal.o \ *************** *** 866,872 **** OBJ += $(OUTDIR)/terminal.o \ $(OUTDIR)/encoding.o \ $(OUTDIR)/keyboard.o \ ! $(OUTDIR)/mouse.o \ $(OUTDIR)/parser.o \ $(OUTDIR)/pen.o \ $(OUTDIR)/termscreen.o \ --- 867,873 ---- OBJ += $(OUTDIR)/terminal.o \ $(OUTDIR)/encoding.o \ $(OUTDIR)/keyboard.o \ ! $(OUTDIR)/termmouse.o \ $(OUTDIR)/parser.o \ $(OUTDIR)/pen.o \ $(OUTDIR)/termscreen.o \ *** ../vim-8.1.2061/src/Make_morph.mak 2019-09-19 23:05:56.467034962 +0200 --- src/Make_morph.mak 2019-09-21 20:13:48.593908424 +0200 *************** *** 74,79 **** --- 74,80 ---- message.c \ misc1.c \ misc2.c \ + mouse.c \ move.c \ normal.c \ ops.c \ *** ../vim-8.1.2061/src/Make_mvc.mak 2019-09-19 23:05:56.467034962 +0200 --- src/Make_mvc.mak 2019-09-21 20:13:48.593908424 +0200 *************** *** 365,371 **** $(OBJDIR)/terminal.obj \ $(OBJDIR)/encoding.obj \ $(OBJDIR)/keyboard.obj \ ! $(OBJDIR)/mouse.obj \ $(OBJDIR)/parser.obj \ $(OBJDIR)/pen.obj \ $(OBJDIR)/termscreen.obj \ --- 365,371 ---- $(OBJDIR)/terminal.obj \ $(OBJDIR)/encoding.obj \ $(OBJDIR)/keyboard.obj \ ! $(OBJDIR)/termmouse.obj \ $(OBJDIR)/parser.obj \ $(OBJDIR)/pen.obj \ $(OBJDIR)/termscreen.obj \ *************** *** 762,767 **** --- 762,768 ---- $(OUTDIR)\message.obj \ $(OUTDIR)\misc1.obj \ $(OUTDIR)\misc2.obj \ + $(OUTDIR)\mouse.obj \ $(OUTDIR)\move.obj \ $(OUTDIR)\normal.obj \ $(OUTDIR)\ops.obj \ *************** *** 1601,1606 **** --- 1602,1609 ---- $(OUTDIR)/misc2.obj: $(OUTDIR) misc2.c $(INCL) + $(OUTDIR)/mouse.obj: $(OUTDIR) mouse.c $(INCL) + $(OUTDIR)/move.obj: $(OUTDIR) move.c $(INCL) $(OUTDIR)/mbyte.obj: $(OUTDIR) mbyte.c $(INCL) *************** *** 1736,1742 **** $(OUTDIR)/keyboard.obj: $(OUTDIR) libvterm/src/keyboard.c $(TERM_DEPS) ! $(OUTDIR)/mouse.obj: $(OUTDIR) libvterm/src/mouse.c $(TERM_DEPS) $(OUTDIR)/parser.obj: $(OUTDIR) libvterm/src/parser.c $(TERM_DEPS) --- 1739,1745 ---- $(OUTDIR)/keyboard.obj: $(OUTDIR) libvterm/src/keyboard.c $(TERM_DEPS) ! $(OUTDIR)/termmouse.obj: $(OUTDIR) libvterm/src/termmouse.c $(TERM_DEPS) $(OUTDIR)/parser.obj: $(OUTDIR) libvterm/src/parser.c $(TERM_DEPS) *************** *** 1822,1827 **** --- 1825,1831 ---- proto/message.pro \ proto/misc1.pro \ proto/misc2.pro \ + proto/mouse.pro \ proto/move.pro \ proto/mbyte.pro \ proto/normal.pro \ *** ../vim-8.1.2061/src/Make_vms.mms 2019-09-19 23:05:56.467034962 +0200 --- src/Make_vms.mms 2019-09-21 20:13:48.593908424 +0200 *************** *** 316,322 **** if_cscope.c if_xcmdsrv.c fileio.c filepath.c, findfile.c fold.c \ getchar.c hardcopy.c hashtab.c highlight.c \ indent.c insexpand.c json.c list.c main.c map.c mark.c menu.c mbyte.c \ ! memfile.c memline.c message.c misc1.c misc2.c move.c normal.c ops.c \ option.c optionstr.c popupmnu.c popupwin.c profiler.c quickfix.c \ regexp.c scriptfile.c \ search.c session.c sha256.c sign.c spell.c spellfile.c syntax.c tag.c \ --- 316,323 ---- if_cscope.c if_xcmdsrv.c fileio.c filepath.c, findfile.c fold.c \ getchar.c hardcopy.c hashtab.c highlight.c \ indent.c insexpand.c json.c list.c main.c map.c mark.c menu.c mbyte.c \ ! memfile.c memline.c message.c misc1.c misc2.c mouse.c move.c normal.c \ ! ops.c \ option.c optionstr.c popupmnu.c popupwin.c profiler.c quickfix.c \ regexp.c scriptfile.c \ search.c session.c sha256.c sign.c spell.c spellfile.c syntax.c tag.c \ *************** *** 336,342 **** findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \ highlight.obj indent.obj insexpand.obj json.obj list.obj main.obj \ map.obj mark.obj menu.obj memfile.obj memline.obj message.obj \ ! misc1.obj misc2.obj move.obj mbyte.obj normal.obj ops.obj option.obj \ optionstr.obj popupmnu.obj popupwin.obj profiler.obj quickfix.obj \ regexp.obj scriptfile.obj \ search.obj session.obj sha256.obj sign.obj spell.obj spellfile.obj \ --- 337,344 ---- findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \ highlight.obj indent.obj insexpand.obj json.obj list.obj main.obj \ map.obj mark.obj menu.obj memfile.obj memline.obj message.obj \ ! misc1.obj misc2.obj mouse.obj move.obj mbyte.obj normal.obj ops.obj \ ! option.obj \ optionstr.obj popupmnu.obj popupwin.obj profiler.obj quickfix.obj \ regexp.obj scriptfile.obj \ search.obj session.obj sha256.obj sign.obj spell.obj spellfile.obj \ *************** *** 697,702 **** --- 699,707 ---- misc2.obj : misc2.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h + mouse.obj : mouse.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ + [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h move.obj : move.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h *** ../vim-8.1.2061/src/Makefile 2019-09-19 23:05:56.467034962 +0200 --- src/Makefile 2019-09-21 20:13:48.593908424 +0200 *************** *** 1629,1634 **** --- 1631,1637 ---- message.c \ misc1.c \ misc2.c \ + mouse.c \ move.c \ mbyte.c \ normal.c \ *************** *** 1762,1767 **** --- 1765,1771 ---- objects/menu.o \ objects/misc1.o \ objects/misc2.o \ + objects/mouse.o \ objects/move.o \ objects/mbyte.o \ objects/normal.o \ *************** *** 1921,1926 **** --- 1925,1931 ---- message.pro \ misc1.pro \ misc2.pro \ + mouse.pro \ move.pro \ normal.pro \ ops.pro \ *************** *** 3287,3292 **** --- 3292,3300 ---- objects/misc2.o: misc2.c $(CCC) -o $@ misc2.c + objects/mouse.o: mouse.c + $(CCC) -o $@ mouse.c + objects/move.o: move.c $(CCC) -o $@ move.c *************** *** 3430,3437 **** objects/keyboard.o: libvterm/src/keyboard.c $(TERM_DEPS) $(CCCTERM) -o $@ libvterm/src/keyboard.c ! objects/mouse.o: libvterm/src/mouse.c $(TERM_DEPS) ! $(CCCTERM) -o $@ libvterm/src/mouse.c objects/parser.o: libvterm/src/parser.c $(TERM_DEPS) $(CCCTERM) -o $@ libvterm/src/parser.c --- 3438,3445 ---- objects/keyboard.o: libvterm/src/keyboard.c $(TERM_DEPS) $(CCCTERM) -o $@ libvterm/src/keyboard.c ! objects/termmouse.o: libvterm/src/termmouse.c $(TERM_DEPS) ! $(CCCTERM) -o $@ libvterm/src/termmouse.c objects/parser.o: libvterm/src/parser.c $(TERM_DEPS) $(CCCTERM) -o $@ libvterm/src/parser.c *************** *** 3769,3774 **** --- 3777,3786 ---- auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h + objects/mouse.o: mouse.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h objects/move.o: move.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ *************** *** 4063,4069 **** objects/keyboard.o: libvterm/src/keyboard.c libvterm/src/vterm_internal.h \ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h \ libvterm/src/utf8.h ! objects/mouse.o: libvterm/src/mouse.c libvterm/src/vterm_internal.h \ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h \ libvterm/src/utf8.h objects/parser.o: libvterm/src/parser.c libvterm/src/vterm_internal.h \ --- 4075,4081 ---- objects/keyboard.o: libvterm/src/keyboard.c libvterm/src/vterm_internal.h \ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h \ libvterm/src/utf8.h ! objects/termmouse.o: libvterm/src/termmouse.c libvterm/src/vterm_internal.h \ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h \ libvterm/src/utf8.h objects/parser.o: libvterm/src/parser.c libvterm/src/vterm_internal.h \ *** ../vim-8.1.2061/src/README.md 2019-09-19 23:05:56.467034962 +0200 --- src/README.md 2019-09-21 20:13:48.593908424 +0200 *************** *** 54,59 **** --- 54,60 ---- memline.c | storing lines for buffers in memory menu.c | menus message.c | (error) messages + mouse.c | handling the mouse ops.c | handling operators ("d", "y", "p") option.c | options optionstr.c | handling string options *************** *** 63,69 **** quickfix.c | quickfix commands (":make", ":cn") regexp.c | pattern matching scriptfile.c | runtime directory handling and sourcing scripts ! screen.c | updating the windows search.c | pattern searching session.c | sessions and views sign.c | signs --- 64,70 ---- quickfix.c | quickfix commands (":make", ":cn") regexp.c | pattern matching scriptfile.c | runtime directory handling and sourcing scripts ! screen.c | lower level screen functions search.c | pattern searching session.c | sessions and views sign.c | signs *** ../vim-8.1.2061/src/auto/configure 2019-06-18 22:53:19.014129858 +0200 --- src/auto/configure 2019-09-21 20:25:09.294756830 +0200 *************** *** 7909,7915 **** TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/termscreen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c" ! TERM_OBJ="objects/encoding.o objects/keyboard.o objects/mouse.o objects/parser.o objects/pen.o objects/termscreen.o objects/state.o objects/unicode.o objects/vterm.o" fi --- 7909,7915 ---- TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/termscreen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c" ! TERM_OBJ="objects/encoding.o objects/keyboard.o objects/termmouse.o objects/parser.o objects/pen.o objects/termscreen.o objects/state.o objects/unicode.o objects/vterm.o" fi *** ../vim-8.1.2061/src/configure.ac 2019-06-18 22:53:19.014129858 +0200 --- src/configure.ac 2019-09-21 20:13:48.597908408 +0200 *************** *** 2106,2112 **** AC_DEFINE(FEAT_TERMINAL) TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/termscreen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c" AC_SUBST(TERM_SRC) ! TERM_OBJ="objects/encoding.o objects/keyboard.o objects/mouse.o objects/parser.o objects/pen.o objects/termscreen.o objects/state.o objects/unicode.o objects/vterm.o" AC_SUBST(TERM_OBJ) fi --- 2106,2112 ---- AC_DEFINE(FEAT_TERMINAL) TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/termscreen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c" AC_SUBST(TERM_SRC) ! TERM_OBJ="objects/encoding.o objects/keyboard.o objects/termmouse.o objects/parser.o objects/pen.o objects/termscreen.o objects/state.o objects/unicode.o objects/vterm.o" AC_SUBST(TERM_OBJ) fi *** ../vim-8.1.2061/src/edit.c 2019-09-15 23:02:00.387231965 +0200 --- src/edit.c 2019-09-21 20:34:42.843920324 +0200 *************** *** 27,33 **** #ifdef FEAT_JOB_CHANNEL static void init_prompt(int cmdchar_todo); #endif - static void undisplay_dollar(void); static void insert_special(int, int, int); static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c); static void check_auto_format(int); --- 27,32 ---- *************** *** 56,65 **** static void ins_shift(int c, int lastc); static void ins_del(void); static int ins_bs(int c, int mode, int *inserted_space_p); - #ifdef FEAT_MOUSE - static void ins_mouse(int c); - static void ins_mousescroll(int dir); - #endif #if defined(FEAT_GUI_TABLINE) || defined(PROTO) static void ins_tabline(int c); #endif --- 55,60 ---- *************** *** 322,330 **** im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); #endif - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef FEAT_CMDL_INFO clear_showcmd(); #endif --- 317,323 ---- *************** *** 1759,1765 **** * Call this function before moving the cursor from the normal insert position * in insert mode. */ ! static void undisplay_dollar(void) { if (dollar_vcol >= 0) --- 1752,1758 ---- * Call this function before moving the cursor from the normal insert position * in insert mode. */ ! void undisplay_dollar(void) { if (dollar_vcol >= 0) *************** *** 4508,4516 **** /* need to position cursor again (e.g. when on a TAB ) */ changed_cline_bef_curs(); - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef CURSOR_SHAPE ui_cursor_shape(); /* may show different cursor shape */ #endif --- 4501,4507 ---- *************** *** 5157,5290 **** return did_backspace; } - #ifdef FEAT_MOUSE - static void - ins_mouse(int c) - { - pos_T tpos; - win_T *old_curwin = curwin; - - # ifdef FEAT_GUI - /* When GUI is active, also move/paste when 'mouse' is empty */ - if (!gui.in_use) - # endif - if (!mouse_has(MOUSE_INSERT)) - return; - - undisplay_dollar(); - tpos = curwin->w_cursor; - if (do_mouse(NULL, c, BACKWARD, 1L, 0)) - { - win_T *new_curwin = curwin; - - if (curwin != old_curwin && win_valid(old_curwin)) - { - /* Mouse took us to another window. We need to go back to the - * previous one to stop insert there properly. */ - curwin = old_curwin; - curbuf = curwin->w_buffer; - #ifdef FEAT_JOB_CHANNEL - if (bt_prompt(curbuf)) - // Restart Insert mode when re-entering the prompt buffer. - curbuf->b_prompt_insert = 'A'; - #endif - } - start_arrow(curwin == old_curwin ? &tpos : NULL); - if (curwin != new_curwin && win_valid(new_curwin)) - { - curwin = new_curwin; - curbuf = curwin->w_buffer; - } - # ifdef FEAT_CINDENT - can_cindent = TRUE; - # endif - } - - /* redraw status lines (in case another window became active) */ - redraw_statuslines(); - } - - static void - ins_mousescroll(int dir) - { - pos_T tpos; - win_T *old_curwin = curwin, *wp; - int did_scroll = FALSE; - - tpos = curwin->w_cursor; - - if (mouse_row >= 0 && mouse_col >= 0) - { - int row, col; - - row = mouse_row; - col = mouse_col; - - /* find the window at the pointer coordinates */ - wp = mouse_find_win(&row, &col, FIND_POPUP); - if (wp == NULL) - return; - curwin = wp; - curbuf = curwin->w_buffer; - } - if (curwin == old_curwin) - undisplay_dollar(); - - /* Don't scroll the window in which completion is being done. */ - if (!pum_visible() || curwin != old_curwin) - { - if (dir == MSCR_DOWN || dir == MSCR_UP) - { - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) - scroll_redraw(dir, - (long)(curwin->w_botline - curwin->w_topline)); - else - scroll_redraw(dir, 3L); - # ifdef FEAT_TEXT_PROP - if (WIN_IS_POPUP(curwin)) - popup_set_firstline(curwin); - # endif - } - #ifdef FEAT_GUI - else - { - int val, step = 6; - - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) - step = curwin->w_width; - val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step); - if (val < 0) - val = 0; - gui_do_horiz_scroll(val, TRUE); - } - #endif - did_scroll = TRUE; - } - - curwin->w_redr_status = TRUE; - - curwin = old_curwin; - curbuf = curwin->w_buffer; - - /* The popup menu may overlay the window, need to redraw it. - * TODO: Would be more efficient to only redraw the windows that are - * overlapped by the popup menu. */ - if (pum_visible() && did_scroll) - { - redraw_all_later(NOT_VALID); - ins_compl_show_pum(); - } - - if (!EQUAL_POS(curwin->w_cursor, tpos)) - { - start_arrow(&tpos); - # ifdef FEAT_CINDENT - can_cindent = TRUE; - # endif - } - } - #endif - /* * Handle receiving P_PS: start paste mode. Inserts the following text up to * P_PE literally. --- 5148,5153 ---- *************** *** 6401,6410 **** #if defined(FEAT_CINDENT) || defined(PROTO) int ! can_cindent_get(void) { return can_cindent; } #endif /* --- 6264,6279 ---- #if defined(FEAT_CINDENT) || defined(PROTO) int ! get_can_cindent(void) { return can_cindent; } + + void + set_can_cindent(int val) + { + can_cindent = val; + } #endif /* *** ../vim-8.1.2061/src/ex_cmds.c 2019-08-21 18:30:58.878719490 +0200 --- src/ex_cmds.c 2019-09-21 20:35:16.111753773 +0200 *************** *** 4221,4229 **** * properly */ save_State = State; State = CONFIRM; ! #ifdef FEAT_MOUSE ! setmouse(); /* disable mouse in xterm */ ! #endif curwin->w_cursor.col = regmatch.startpos[0].col; if (curwin->w_p_crb) do_check_cursorbind(); --- 4221,4227 ---- * properly */ save_State = State; State = CONFIRM; ! setmouse(); // disable mouse in xterm curwin->w_cursor.col = regmatch.startpos[0].col; if (curwin->w_p_crb) do_check_cursorbind(); *************** *** 4397,4405 **** scrolldown_clamp(); } State = save_State; - #ifdef FEAT_MOUSE setmouse(); - #endif if (vim_strchr(p_cpo, CPO_UNDO) != NULL) --no_u_sync; --- 4395,4401 ---- *** ../vim-8.1.2061/src/ex_docmd.c 2019-09-05 21:28:58.491157322 +0200 --- src/ex_docmd.c 2019-09-21 20:35:28.927689566 +0200 *************** *** 7578,7586 **** restore_current_state(&save_state); --ex_normal_busy; - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef CURSOR_SHAPE ui_cursor_shape(); /* may show different cursor shape */ #endif --- 7578,7584 ---- *** ../vim-8.1.2061/src/ex_getln.c 2019-09-15 23:02:00.387231965 +0200 --- src/ex_getln.c 2019-09-21 20:35:53.283567518 +0200 *************** *** 924,932 **** im_set_active(TRUE); #endif - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef CURSOR_SHAPE ui_cursor_shape(); /* may show different cursor shape */ #endif --- 924,930 ---- *************** *** 2389,2397 **** im_save_status(b_im_ptr); im_set_active(FALSE); #endif - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef CURSOR_SHAPE ui_cursor_shape(); /* may show different cursor shape */ #endif --- 2387,2393 ---- *************** *** 4160,4168 **** exmode_active = 0; State = NORMAL; - # ifdef FEAT_MOUSE setmouse(); - # endif // Trigger CmdwinEnter autocommands. trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINENTER); --- 4156,4162 ---- *************** *** 4290,4298 **** # endif State = save_State; - # ifdef FEAT_MOUSE setmouse(); - # endif return cmdwin_result; } --- 4284,4290 ---- *** ../vim-8.1.2061/src/insexpand.c 2019-08-21 15:30:41.883967057 +0200 --- src/insexpand.c 2019-09-21 20:13:48.597908408 +0200 *************** *** 1995,2001 **** } #ifdef FEAT_CINDENT ! want_cindent = (can_cindent_get() && cindent_on()); #endif // When completing whole lines: fix indent for 'cindent'. // Otherwise, break line if it's too long. --- 1995,2001 ---- } #ifdef FEAT_CINDENT ! want_cindent = (get_can_cindent() && cindent_on()); #endif // When completing whole lines: fix indent for 'cindent'. // Otherwise, break line if it's too long. *** ../vim-8.1.2061/src/libvterm/src/termmouse.c 2019-09-21 20:44:58.860689791 +0200 --- src/libvterm/src/termmouse.c 2019-09-21 20:13:48.597908408 +0200 *************** *** 0 **** --- 1,98 ---- + #include "vterm_internal.h" + + #include "utf8.h" + + static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row) + { + modifiers <<= 2; + + switch(state->mouse_protocol) { + case MOUSE_X10: + if(col + 0x21 > 0xff) + col = 0xff - 0x21; + if(row + 0x21 > 0xff) + row = 0xff - 0x21; + + if(!pressed) + code = 3; + + vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c", + (code | modifiers) + 0x20, col + 0x21, row + 0x21); + break; + + case MOUSE_UTF8: + { + char utf8[18]; size_t len = 0; + + if(!pressed) + code = 3; + + len += fill_utf8((code | modifiers) + 0x20, utf8 + len); + len += fill_utf8(col + 0x21, utf8 + len); + len += fill_utf8(row + 0x21, utf8 + len); + utf8[len] = 0; + + vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8); + } + break; + + case MOUSE_SGR: + vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c", + code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm'); + break; + + case MOUSE_RXVT: + if(!pressed) + code = 3; + + vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM", + code | modifiers, col + 1, row + 1); + break; + } + } + + void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod) + { + VTermState *state = vt->state; + + if(col == state->mouse_col && row == state->mouse_row) + return; + + state->mouse_col = col; + state->mouse_row = row; + + if((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) || + (state->mouse_flags & MOUSE_WANT_MOVE)) { + int button = state->mouse_buttons & MOUSE_BUTTON_LEFT ? 1 : + state->mouse_buttons & MOUSE_BUTTON_MIDDLE ? 2 : + state->mouse_buttons & MOUSE_BUTTON_RIGHT ? 3 : 4; + output_mouse(state, button-1 + 0x20, 1, mod, col, row); + } + } + + void vterm_mouse_button(VTerm *vt, int button, int pressed, VTermModifier mod) + { + VTermState *state = vt->state; + + int old_buttons = state->mouse_buttons; + + if(button > 0 && button <= 3) { + if(pressed) + state->mouse_buttons |= (1 << (button-1)); + else + state->mouse_buttons &= ~(1 << (button-1)); + } + + // Most of the time we don't get button releases from 4/5 + if(state->mouse_buttons == old_buttons && button < 4) + return; + if (!(state->mouse_flags & MOUSE_WANT_CLICK)) + return; + + if(button < 4) { + output_mouse(state, button-1, pressed, mod, state->mouse_col, state->mouse_row); + } + else if(button < 6) { + output_mouse(state, button-4 + 0x40, pressed, mod, state->mouse_col, state->mouse_row); + } + } *** ../vim-8.1.2061/src/libvterm/src/mouse.c 2019-08-18 20:41:10.692526067 +0200 --- src/libvterm/src/mouse.c 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,98 **** - #include "vterm_internal.h" - - #include "utf8.h" - - static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row) - { - modifiers <<= 2; - - switch(state->mouse_protocol) { - case MOUSE_X10: - if(col + 0x21 > 0xff) - col = 0xff - 0x21; - if(row + 0x21 > 0xff) - row = 0xff - 0x21; - - if(!pressed) - code = 3; - - vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c", - (code | modifiers) + 0x20, col + 0x21, row + 0x21); - break; - - case MOUSE_UTF8: - { - char utf8[18]; size_t len = 0; - - if(!pressed) - code = 3; - - len += fill_utf8((code | modifiers) + 0x20, utf8 + len); - len += fill_utf8(col + 0x21, utf8 + len); - len += fill_utf8(row + 0x21, utf8 + len); - utf8[len] = 0; - - vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8); - } - break; - - case MOUSE_SGR: - vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c", - code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm'); - break; - - case MOUSE_RXVT: - if(!pressed) - code = 3; - - vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM", - code | modifiers, col + 1, row + 1); - break; - } - } - - void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod) - { - VTermState *state = vt->state; - - if(col == state->mouse_col && row == state->mouse_row) - return; - - state->mouse_col = col; - state->mouse_row = row; - - if((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) || - (state->mouse_flags & MOUSE_WANT_MOVE)) { - int button = state->mouse_buttons & MOUSE_BUTTON_LEFT ? 1 : - state->mouse_buttons & MOUSE_BUTTON_MIDDLE ? 2 : - state->mouse_buttons & MOUSE_BUTTON_RIGHT ? 3 : 4; - output_mouse(state, button-1 + 0x20, 1, mod, col, row); - } - } - - void vterm_mouse_button(VTerm *vt, int button, int pressed, VTermModifier mod) - { - VTermState *state = vt->state; - - int old_buttons = state->mouse_buttons; - - if(button > 0 && button <= 3) { - if(pressed) - state->mouse_buttons |= (1 << (button-1)); - else - state->mouse_buttons &= ~(1 << (button-1)); - } - - // Most of the time we don't get button releases from 4/5 - if(state->mouse_buttons == old_buttons && button < 4) - return; - if (!(state->mouse_flags & MOUSE_WANT_CLICK)) - return; - - if(button < 4) { - output_mouse(state, button-1, pressed, mod, state->mouse_col, state->mouse_row); - } - else if(button < 6) { - output_mouse(state, button-4 + 0x40, pressed, mod, state->mouse_col, state->mouse_row); - } - } --- 0 ---- *** ../vim-8.1.2061/src/main.c 2019-09-18 21:15:25.409966545 +0200 --- src/main.c 2019-09-21 20:36:19.751434789 +0200 *************** *** 684,692 **** starttermcap(); /* start termcap if not done by wait_return() */ TIME_MSG("start termcap"); ! #ifdef FEAT_MOUSE ! setmouse(); /* may start using the mouse */ ! #endif if (scroll_region) scroll_region_reset(); /* In case Rows changed */ scroll_start(); /* may scroll the screen to the right position */ --- 684,690 ---- starttermcap(); /* start termcap if not done by wait_return() */ TIME_MSG("start termcap"); ! setmouse(); // may start using the mouse if (scroll_region) scroll_region_reset(); /* In case Rows changed */ scroll_start(); /* may scroll the screen to the right position */ *************** *** 1182,1190 **** emsg_skip = 0; # endif emsg_off = 0; - # ifdef FEAT_MOUSE setmouse(); - # endif settmode(TMODE_RAW); starttermcap(); scroll_start(); --- 1180,1186 ---- *** ../vim-8.1.2061/src/message.c 2019-09-09 20:04:04.738340561 +0200 --- src/message.c 2019-09-21 20:37:11.243176332 +0200 *************** *** 1058,1066 **** screenalloc(FALSE); State = HITRETURN; - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef USE_ON_FLY_SCROLL dont_scroll = TRUE; /* disallow scrolling here */ #endif --- 1058,1064 ---- *************** *** 1216,1224 **** */ tmpState = State; State = oldState; /* restore State before set_shellsize */ - #ifdef FEAT_MOUSE setmouse(); - #endif msg_check(); #if defined(UNIX) || defined(VMS) --- 1214,1220 ---- *************** *** 2684,2692 **** } State = ASKMORE; - #ifdef FEAT_MOUSE setmouse(); - #endif if (typed_char == NUL) msg_moremsg(FALSE); for (;;) --- 2680,2686 ---- *************** *** 2902,2910 **** /* clear the --more-- message */ screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); State = oldState; - #ifdef FEAT_MOUSE setmouse(); - #endif if (quit_more) { msg_row = Rows - 1; --- 2896,2902 ---- *************** *** 3608,3616 **** oldState = State; State = CONFIRM; - #ifdef FEAT_MOUSE setmouse(); - #endif /* * Since we wait for a keypress, don't make the --- 3600,3606 ---- *************** *** 3673,3681 **** } State = oldState; - #ifdef FEAT_MOUSE setmouse(); - #endif --no_wait_return; msg_end_prompt(); --- 3663,3669 ---- *** ../vim-8.1.2061/src/misc1.c 2019-09-16 22:55:57.728006887 +0200 --- src/misc1.c 2019-09-21 20:37:42.499019341 +0200 *************** *** 1148,1161 **** settmode(TMODE_RAW); ++no_wait_return; #ifdef USE_ON_FLY_SCROLL ! dont_scroll = TRUE; /* disallow scrolling here */ ! #endif ! State = CONFIRM; /* mouse behaves like with :confirm */ ! #ifdef FEAT_MOUSE ! setmouse(); /* disables mouse for xterm */ #endif ++no_mapping; ! ++allow_keys; /* no mapping here, but recognize keys */ while (r != 'y' && r != 'n') { --- 1148,1159 ---- settmode(TMODE_RAW); ++no_wait_return; #ifdef USE_ON_FLY_SCROLL ! dont_scroll = TRUE; // disallow scrolling here #endif + State = CONFIRM; // mouse behaves like with :confirm + setmouse(); // disables mouse for xterm ++no_mapping; ! ++allow_keys; // no mapping here, but recognize keys while (r != 'y' && r != 'n') { *************** *** 1172,1218 **** } --no_wait_return; State = save_State; - #ifdef FEAT_MOUSE setmouse(); - #endif --no_mapping; --allow_keys; return r; } - #if defined(FEAT_MOUSE) || defined(PROTO) - /* - * Return TRUE if "c" is a mouse key. - */ - int - is_mouse_key(int c) - { - return c == K_LEFTMOUSE - || c == K_LEFTMOUSE_NM - || c == K_LEFTDRAG - || c == K_LEFTRELEASE - || c == K_LEFTRELEASE_NM - || c == K_MOUSEMOVE - || c == K_MIDDLEMOUSE - || c == K_MIDDLEDRAG - || c == K_MIDDLERELEASE - || c == K_RIGHTMOUSE - || c == K_RIGHTDRAG - || c == K_RIGHTRELEASE - || c == K_MOUSEDOWN - || c == K_MOUSEUP - || c == K_MOUSELEFT - || c == K_MOUSERIGHT - || c == K_X1MOUSE - || c == K_X1DRAG - || c == K_X1RELEASE - || c == K_X2MOUSE - || c == K_X2DRAG - || c == K_X2RELEASE; - } - #endif - #if defined(FEAT_EVAL) || defined(PROTO) /* --- 1170,1182 ---- *************** *** 1340,1345 **** --- 1304,1311 ---- if (channel_in_blocking_wait()) may_add_state_char(&ga, include, 'w'); # endif + if (!get_was_safe_state()) + may_add_state_char(&ga, include, 'S'); for (i = 0; i < get_callback_depth() && i < 3; ++i) may_add_state_char(&ga, include, 'c'); if (msg_scrolled > 0) *************** *** 1572,1581 **** cmdline_row = 0; save_State = State; State = CMDLINE; - #ifdef FEAT_MOUSE // May show different mouse shape. setmouse(); - #endif i = get_number(TRUE, mouse_used); if (KeyTyped) --- 1538,1545 ---- *************** *** 1590,1599 **** else cmdline_row = save_cmdline_row; State = save_State; - #ifdef FEAT_MOUSE // May need to restore mouse shape. setmouse(); - #endif return i; } --- 1554,1561 ---- *** ../vim-8.1.2061/src/misc2.c 2019-09-15 21:00:51.362604284 +0200 --- src/misc2.c 2019-09-21 20:13:48.597908408 +0200 *************** *** 2491,2534 **** #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry)) - #ifdef FEAT_MOUSE - static struct mousetable - { - int pseudo_code; /* Code for pseudo mouse event */ - int button; /* Which mouse button is it? */ - int is_click; /* Is it a mouse button click event? */ - int is_drag; /* Is it a mouse drag event? */ - } mouse_table[] = - { - {(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE}, - #ifdef FEAT_GUI - {(int)KE_LEFTMOUSE_NM, MOUSE_LEFT, TRUE, FALSE}, - #endif - {(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE}, - {(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE}, - #ifdef FEAT_GUI - {(int)KE_LEFTRELEASE_NM, MOUSE_LEFT, FALSE, FALSE}, - #endif - {(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE}, - {(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE}, - {(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE}, - {(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE}, - {(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE}, - {(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE}, - {(int)KE_X1MOUSE, MOUSE_X1, TRUE, FALSE}, - {(int)KE_X1DRAG, MOUSE_X1, FALSE, TRUE}, - {(int)KE_X1RELEASE, MOUSE_X1, FALSE, FALSE}, - {(int)KE_X2MOUSE, MOUSE_X2, TRUE, FALSE}, - {(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE}, - {(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE}, - /* DRAG without CLICK */ - {(int)KE_MOUSEMOVE, MOUSE_RELEASE, FALSE, TRUE}, - /* RELEASE without CLICK */ - {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE}, - {0, 0, 0, 0}, - }; - #endif /* FEAT_MOUSE */ - /* * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given * modifier name ('S' for Shift, 'C' for Ctrl etc). --- 2491,2496 ---- *************** *** 3050,3115 **** return key_names_table[i].name; } - #if defined(FEAT_MOUSE) || defined(PROTO) - /* - * Look up the given mouse code to return the relevant information in the other - * arguments. Return which button is down or was released. - */ - int - get_mouse_button(int code, int *is_click, int *is_drag) - { - int i; - - for (i = 0; mouse_table[i].pseudo_code; i++) - if (code == mouse_table[i].pseudo_code) - { - *is_click = mouse_table[i].is_click; - *is_drag = mouse_table[i].is_drag; - return mouse_table[i].button; - } - return 0; /* Shouldn't get here */ - } - - /* - * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on - * the given information about which mouse button is down, and whether the - * mouse was clicked, dragged or released. - */ - int - get_pseudo_mouse_code( - int button, /* eg MOUSE_LEFT */ - int is_click, - int is_drag) - { - int i; - - for (i = 0; mouse_table[i].pseudo_code; i++) - if (button == mouse_table[i].button - && is_click == mouse_table[i].is_click - && is_drag == mouse_table[i].is_drag) - { - #ifdef FEAT_GUI - /* Trick: a non mappable left click and release has mouse_col -1 - * or added MOUSE_COLOFF. Used for 'mousefocus' in - * gui_mouse_moved() */ - if (mouse_col < 0 || mouse_col > MOUSE_COLOFF) - { - if (mouse_col < 0) - mouse_col = 0; - else - mouse_col -= MOUSE_COLOFF; - if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE) - return (int)KE_LEFTMOUSE_NM; - if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE) - return (int)KE_LEFTRELEASE_NM; - } - #endif - return mouse_table[i].pseudo_code; - } - return (int)KE_IGNORE; /* not recognized, ignore it */ - } - #endif /* FEAT_MOUSE */ - /* * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC. */ --- 3012,3017 ---- *** ../vim-8.1.2061/src/mouse.c 2019-09-21 20:44:58.884689657 +0200 --- src/mouse.c 2019-09-21 20:34:15.724055964 +0200 *************** *** 0 **** --- 1,2314 ---- + /* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + + /* + * mouse.c: mouse handling functions + */ + + #include "vim.h" + + #if defined(FEAT_MOUSE) || defined(PROTO) + + static int get_fpos_of_mouse(pos_T *mpos); + + /* + * Get class of a character for selection: same class means same word. + * 0: blank + * 1: punctuation groups + * 2: normal word character + * >2: multi-byte word character. + */ + static int + get_mouse_class(char_u *p) + { + int c; + + if (has_mbyte && MB_BYTE2LEN(p[0]) > 1) + return mb_get_class(p); + + c = *p; + if (c == ' ' || c == '\t') + return 0; + + if (vim_iswordc(c)) + return 2; + + // There are a few special cases where we want certain combinations of + // characters to be considered as a single word. These are things like + // "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each + // character is in its own class. + if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL) + return 1; + return c; + } + + /* + * Move "pos" back to the start of the word it's in. + */ + static void + find_start_of_word(pos_T *pos) + { + char_u *line; + int cclass; + int col; + + line = ml_get(pos->lnum); + cclass = get_mouse_class(line + pos->col); + + while (pos->col > 0) + { + col = pos->col - 1; + col -= (*mb_head_off)(line, line + col); + if (get_mouse_class(line + col) != cclass) + break; + pos->col = col; + } + } + + /* + * Move "pos" forward to the end of the word it's in. + * When 'selection' is "exclusive", the position is just after the word. + */ + static void + find_end_of_word(pos_T *pos) + { + char_u *line; + int cclass; + int col; + + line = ml_get(pos->lnum); + if (*p_sel == 'e' && pos->col > 0) + { + --pos->col; + pos->col -= (*mb_head_off)(line, line + pos->col); + } + cclass = get_mouse_class(line + pos->col); + while (line[pos->col] != NUL) + { + col = pos->col + (*mb_ptr2len)(line + pos->col); + if (get_mouse_class(line + col) != cclass) + { + if (*p_sel == 'e') + pos->col = col; + break; + } + pos->col = col; + } + } + + /* + * Do the appropriate action for the current mouse click in the current mode. + * Not used for Command-line mode. + * + * Normal and Visual Mode: + * event modi- position visual change action + * fier cursor window + * left press - yes end yes + * left press C yes end yes "^]" (2) + * left press S yes end (popup: extend) yes "*" (2) + * left drag - yes start if moved no + * left relse - yes start if moved no + * middle press - yes if not active no put register + * middle press - yes if active no yank and put + * right press - yes start or extend yes + * right press S yes no change yes "#" (2) + * right drag - yes extend no + * right relse - yes extend no + * + * Insert or Replace Mode: + * event modi- position visual change action + * fier cursor window + * left press - yes (cannot be active) yes + * left press C yes (cannot be active) yes "CTRL-O^]" (2) + * left press S yes (cannot be active) yes "CTRL-O*" (2) + * left drag - yes start or extend (1) no CTRL-O (1) + * left relse - yes start or extend (1) no CTRL-O (1) + * middle press - no (cannot be active) no put register + * right press - yes start or extend yes CTRL-O + * right press S yes (cannot be active) yes "CTRL-O#" (2) + * + * (1) only if mouse pointer moved since press + * (2) only if click is in same buffer + * + * Return TRUE if start_arrow() should be called for edit mode. + */ + int + do_mouse( + oparg_T *oap, // operator argument, can be NULL + int c, // K_LEFTMOUSE, etc + int dir, // Direction to 'put' if necessary + long count, + int fixindent) // PUT_FIXINDENT if fixing indent necessary + { + static int do_always = FALSE; // ignore 'mouse' setting next time + static int got_click = FALSE; // got a click some time back + + int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT + int is_click = FALSE; // If FALSE it's a drag or release event + int is_drag = FALSE; // If TRUE it's a drag event + int jump_flags = 0; // flags for jump_to_mouse() + pos_T start_visual; + int moved; // Has cursor moved? + int in_status_line; // mouse in status line + static int in_tab_line = FALSE; // mouse clicked in tab line + int in_sep_line; // mouse in vertical separator line + int c1, c2; + #if defined(FEAT_FOLDING) + pos_T save_cursor; + #endif + win_T *old_curwin = curwin; + static pos_T orig_cursor; + colnr_T leftcol, rightcol; + pos_T end_visual; + int diff; + int old_active = VIsual_active; + int old_mode = VIsual_mode; + int regname; + + #if defined(FEAT_FOLDING) + save_cursor = curwin->w_cursor; + #endif + + // When GUI is active, always recognize mouse events, otherwise: + // - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'. + // - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'. + // - For command line and insert mode 'mouse' is checked before calling + // do_mouse(). + if (do_always) + do_always = FALSE; + else + #ifdef FEAT_GUI + if (!gui.in_use) + #endif + { + if (VIsual_active) + { + if (!mouse_has(MOUSE_VISUAL)) + return FALSE; + } + else if (State == NORMAL && !mouse_has(MOUSE_NORMAL)) + return FALSE; + } + + for (;;) + { + which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); + if (is_drag) + { + // If the next character is the same mouse event then use that + // one. Speeds up dragging the status line. + if (vpeekc() != NUL) + { + int nc; + int save_mouse_row = mouse_row; + int save_mouse_col = mouse_col; + + // Need to get the character, peeking doesn't get the actual + // one. + nc = safe_vgetc(); + if (c == nc) + continue; + vungetc(nc); + mouse_row = save_mouse_row; + mouse_col = save_mouse_col; + } + } + break; + } + + if (c == K_MOUSEMOVE) + { + // Mouse moved without a button pressed. + #ifdef FEAT_BEVAL_TERM + ui_may_remove_balloon(); + if (p_bevalterm) + { + profile_setlimit(p_bdlay, &bevalexpr_due); + bevalexpr_due_set = TRUE; + } + #endif + #ifdef FEAT_TEXT_PROP + popup_handle_mouse_moved(); + #endif + return FALSE; + } + + #ifdef FEAT_MOUSESHAPE + // May have stopped dragging the status or separator line. The pointer is + // most likely still on the status or separator line. + if (!is_drag && drag_status_line) + { + drag_status_line = FALSE; + update_mouseshape(SHAPE_IDX_STATUS); + } + if (!is_drag && drag_sep_line) + { + drag_sep_line = FALSE; + update_mouseshape(SHAPE_IDX_VSEP); + } + #endif + + // Ignore drag and release events if we didn't get a click. + if (is_click) + got_click = TRUE; + else + { + if (!got_click) // didn't get click, ignore + return FALSE; + if (!is_drag) // release, reset got_click + { + got_click = FALSE; + if (in_tab_line) + { + in_tab_line = FALSE; + return FALSE; + } + } + } + + // CTRL right mouse button does CTRL-T + if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT) + { + if (State & INSERT) + stuffcharReadbuff(Ctrl_O); + if (count > 1) + stuffnumReadbuff(count); + stuffcharReadbuff(Ctrl_T); + got_click = FALSE; // ignore drag&release now + return FALSE; + } + + // CTRL only works with left mouse button + if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT) + return FALSE; + + // When a modifier is down, ignore drag and release events, as well as + // multiple clicks and the middle mouse button. + // Accept shift-leftmouse drags when 'mousemodel' is "popup.*". + if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT + | MOD_MASK_META)) + && (!is_click + || (mod_mask & MOD_MASK_MULTI_CLICK) + || which_button == MOUSE_MIDDLE) + && !((mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)) + && mouse_model_popup() + && which_button == MOUSE_LEFT) + && !((mod_mask & MOD_MASK_ALT) + && !mouse_model_popup() + && which_button == MOUSE_RIGHT) + ) + return FALSE; + + // If the button press was used as the movement command for an operator + // (eg "d"), or it is the middle button that is held down, ignore + // drag/release events. + if (!is_click && which_button == MOUSE_MIDDLE) + return FALSE; + + if (oap != NULL) + regname = oap->regname; + else + regname = 0; + + // Middle mouse button does a 'put' of the selected text + if (which_button == MOUSE_MIDDLE) + { + if (State == NORMAL) + { + // If an operator was pending, we don't know what the user wanted + // to do. Go back to normal mode: Clear the operator and beep(). + if (oap != NULL && oap->op_type != OP_NOP) + { + clearopbeep(oap); + return FALSE; + } + + // If visual was active, yank the highlighted text and put it + // before the mouse pointer position. + // In Select mode replace the highlighted text with the clipboard. + if (VIsual_active) + { + if (VIsual_select) + { + stuffcharReadbuff(Ctrl_G); + stuffReadbuff((char_u *)"\"+p"); + } + else + { + stuffcharReadbuff('y'); + stuffcharReadbuff(K_MIDDLEMOUSE); + } + do_always = TRUE; // ignore 'mouse' setting next time + return FALSE; + } + // The rest is below jump_to_mouse() + } + + else if ((State & INSERT) == 0) + return FALSE; + + // Middle click in insert mode doesn't move the mouse, just insert the + // contents of a register. '.' register is special, can't insert that + // with do_put(). + // Also paste at the cursor if the current mode isn't in 'mouse' (only + // happens for the GUI). + if ((State & INSERT) || !mouse_has(MOUSE_NORMAL)) + { + if (regname == '.') + insert_reg(regname, TRUE); + else + { + #ifdef FEAT_CLIPBOARD + if (clip_star.available && regname == 0) + regname = '*'; + #endif + if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) + insert_reg(regname, TRUE); + else + { + do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND); + + // Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r + AppendCharToRedobuff(Ctrl_R); + AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O); + AppendCharToRedobuff(regname == 0 ? '"' : regname); + } + } + return FALSE; + } + } + + // When dragging or button-up stay in the same window. + if (!is_click) + jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE; + + start_visual.lnum = 0; + + // Check for clicking in the tab page line. + if (mouse_row == 0 && firstwin->w_winrow > 0) + { + if (is_drag) + { + if (in_tab_line) + { + c1 = TabPageIdxs[mouse_col]; + tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab) + ? c1 - 1 : c1); + } + return FALSE; + } + + // click in a tab selects that tab page + if (is_click + # ifdef FEAT_CMDWIN + && cmdwin_type == 0 + # endif + && mouse_col < Columns) + { + in_tab_line = TRUE; + c1 = TabPageIdxs[mouse_col]; + if (c1 >= 0) + { + if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) + { + // double click opens new page + end_visual_mode(); + tabpage_new(); + tabpage_move(c1 == 0 ? 9999 : c1 - 1); + } + else + { + // Go to specified tab page, or next one if not clicking + // on a label. + goto_tabpage(c1); + + // It's like clicking on the status line of a window. + if (curwin != old_curwin) + end_visual_mode(); + } + } + else + { + tabpage_T *tp; + + // Close the current or specified tab page. + if (c1 == -999) + tp = curtab; + else + tp = find_tabpage(-c1); + if (tp == curtab) + { + if (first_tabpage->tp_next != NULL) + tabpage_close(FALSE); + } + else if (tp != NULL) + tabpage_close_other(tp, FALSE); + } + } + return TRUE; + } + else if (is_drag && in_tab_line) + { + c1 = TabPageIdxs[mouse_col]; + tabpage_move(c1 <= 0 ? 9999 : c1 - 1); + return FALSE; + } + + // When 'mousemodel' is "popup" or "popup_setpos", translate mouse events: + // right button up -> pop-up menu + // shift-left button -> right button + // alt-left button -> alt-right button + if (mouse_model_popup()) + { + if (which_button == MOUSE_RIGHT + && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) + { + #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ + || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \ + || defined(FEAT_TERM_POPUP_MENU) + # ifdef FEAT_GUI + if (gui.in_use) + { + # if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + if (!is_click) + // Ignore right button release events, only shows the popup + // 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. + return FALSE; + # endif + } + # endif + # if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU) + else + # endif + # if defined(FEAT_TERM_POPUP_MENU) + if (!is_click) + // Ignore right button release events, only shows the popup + // menu on the button down event. + return FALSE; + #endif + + jump_flags = 0; + if (STRCMP(p_mousem, "popup_setpos") == 0) + { + // First set the cursor position before showing the popup + // menu. + if (VIsual_active) + { + pos_T m_pos; + + // set MOUSE_MAY_STOP_VIS if we are outside the + // selection or the current window (might have false + // negative here) + if (mouse_row < curwin->w_winrow + || mouse_row + > (curwin->w_winrow + curwin->w_height)) + jump_flags = MOUSE_MAY_STOP_VIS; + else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) + jump_flags = MOUSE_MAY_STOP_VIS; + else + { + if ((LT_POS(curwin->w_cursor, VIsual) + && (LT_POS(m_pos, curwin->w_cursor) + || LT_POS(VIsual, m_pos))) + || (LT_POS(VIsual, curwin->w_cursor) + && (LT_POS(m_pos, VIsual) + || LT_POS(curwin->w_cursor, m_pos)))) + { + jump_flags = MOUSE_MAY_STOP_VIS; + } + else if (VIsual_mode == Ctrl_V) + { + getvcols(curwin, &curwin->w_cursor, &VIsual, + &leftcol, &rightcol); + getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); + if (m_pos.col < leftcol || m_pos.col > rightcol) + jump_flags = MOUSE_MAY_STOP_VIS; + } + } + } + else + jump_flags = MOUSE_MAY_STOP_VIS; + } + if (jump_flags) + { + jump_flags = jump_to_mouse(jump_flags, NULL, which_button); + update_curbuf(VIsual_active ? INVERTED : VALID); + setcursor(); + out_flush(); // Update before showing popup menu + } + # ifdef FEAT_MENU + show_popupmenu(); + got_click = FALSE; // ignore release events + # endif + return (jump_flags & CURSOR_MOVED) != 0; + #else + return FALSE; + #endif + } + if (which_button == MOUSE_LEFT + && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))) + { + which_button = MOUSE_RIGHT; + mod_mask &= ~MOD_MASK_SHIFT; + } + } + + if ((State & (NORMAL | INSERT)) + && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) + { + if (which_button == MOUSE_LEFT) + { + if (is_click) + { + // stop Visual mode for a left click in a window, but not when + // on a status line + if (VIsual_active) + jump_flags |= MOUSE_MAY_STOP_VIS; + } + else if (mouse_has(MOUSE_VISUAL)) + jump_flags |= MOUSE_MAY_VIS; + } + else if (which_button == MOUSE_RIGHT) + { + if (is_click && VIsual_active) + { + // Remember the start and end of visual before moving the + // cursor. + if (LT_POS(curwin->w_cursor, VIsual)) + { + start_visual = curwin->w_cursor; + end_visual = VIsual; + } + else + { + start_visual = VIsual; + end_visual = curwin->w_cursor; + } + } + jump_flags |= MOUSE_FOCUS; + if (mouse_has(MOUSE_VISUAL)) + jump_flags |= MOUSE_MAY_VIS; + } + } + + // If an operator is pending, ignore all drags and releases until the + // next mouse click. + if (!is_drag && oap != NULL && oap->op_type != OP_NOP) + { + got_click = FALSE; + oap->motion_type = MCHAR; + } + + // When releasing the button let jump_to_mouse() know. + if (!is_click && !is_drag) + jump_flags |= MOUSE_RELEASED; + + // JUMP! + jump_flags = jump_to_mouse(jump_flags, + oap == NULL ? NULL : &(oap->inclusive), which_button); + + #ifdef FEAT_MENU + // A click in the window toolbar has no side effects. + if (jump_flags & MOUSE_WINBAR) + return FALSE; + #endif + moved = (jump_flags & CURSOR_MOVED); + in_status_line = (jump_flags & IN_STATUS_LINE); + in_sep_line = (jump_flags & IN_SEP_LINE); + + #ifdef FEAT_NETBEANS_INTG + if (isNetbeansBuffer(curbuf) + && !(jump_flags & (IN_STATUS_LINE | IN_SEP_LINE))) + { + int key = KEY2TERMCAP1(c); + + if (key == (int)KE_LEFTRELEASE || key == (int)KE_MIDDLERELEASE + || key == (int)KE_RIGHTRELEASE) + netbeans_button_release(which_button); + } + #endif + + // When jumping to another window, clear a pending operator. That's a bit + // friendlier than beeping and not jumping to that window. + if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP) + clearop(oap); + + #ifdef FEAT_FOLDING + if (mod_mask == 0 + && !is_drag + && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN)) + && which_button == MOUSE_LEFT) + { + // open or close a fold at this line + if (jump_flags & MOUSE_FOLD_OPEN) + openFold(curwin->w_cursor.lnum, 1L); + else + closeFold(curwin->w_cursor.lnum, 1L); + // don't move the cursor if still in the same window + if (curwin == old_curwin) + curwin->w_cursor = save_cursor; + } + #endif + + #if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN) + if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available) + { + clip_modeless(which_button, is_click, is_drag); + return FALSE; + } + #endif + + // Set global flag that we are extending the Visual area with mouse + // dragging; temporarily minimize 'scrolloff'. + if (VIsual_active && is_drag && get_scrolloff_value()) + { + // In the very first line, allow scrolling one line + if (mouse_row == 0) + mouse_dragging = 2; + else + mouse_dragging = 1; + } + + // When dragging the mouse above the window, scroll down. + if (is_drag && mouse_row < 0 && !in_status_line) + { + scroll_redraw(FALSE, 1L); + mouse_row = 0; + } + + if (start_visual.lnum) // right click in visual mode + { + // When ALT is pressed make Visual mode blockwise. + if (mod_mask & MOD_MASK_ALT) + VIsual_mode = Ctrl_V; + + // In Visual-block mode, divide the area in four, pick up the corner + // that is in the quarter that the cursor is in. + if (VIsual_mode == Ctrl_V) + { + getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol); + if (curwin->w_curswant > (leftcol + rightcol) / 2) + end_visual.col = leftcol; + else + end_visual.col = rightcol; + if (curwin->w_cursor.lnum >= + (start_visual.lnum + end_visual.lnum) / 2) + end_visual.lnum = start_visual.lnum; + + // move VIsual to the right column + start_visual = curwin->w_cursor; // save the cursor pos + curwin->w_cursor = end_visual; + coladvance(end_visual.col); + VIsual = curwin->w_cursor; + curwin->w_cursor = start_visual; // restore the cursor + } + else + { + // If the click is before the start of visual, change the start. + // If the click is after the end of visual, change the end. If + // the click is inside the visual, change the closest side. + if (LT_POS(curwin->w_cursor, start_visual)) + VIsual = end_visual; + else if (LT_POS(end_visual, curwin->w_cursor)) + VIsual = start_visual; + else + { + // In the same line, compare column number + if (end_visual.lnum == start_visual.lnum) + { + if (curwin->w_cursor.col - start_visual.col > + end_visual.col - curwin->w_cursor.col) + VIsual = start_visual; + else + VIsual = end_visual; + } + + // In different lines, compare line number + else + { + diff = (curwin->w_cursor.lnum - start_visual.lnum) - + (end_visual.lnum - curwin->w_cursor.lnum); + + if (diff > 0) // closest to end + VIsual = start_visual; + else if (diff < 0) // closest to start + VIsual = end_visual; + else // in the middle line + { + if (curwin->w_cursor.col < + (start_visual.col + end_visual.col) / 2) + VIsual = end_visual; + else + VIsual = start_visual; + } + } + } + } + } + // If Visual mode started in insert mode, execute "CTRL-O" + else if ((State & INSERT) && VIsual_active) + stuffcharReadbuff(Ctrl_O); + + // Middle mouse click: Put text before cursor. + if (which_button == MOUSE_MIDDLE) + { + #ifdef FEAT_CLIPBOARD + if (clip_star.available && regname == 0) + regname = '*'; + #endif + if (yank_register_mline(regname)) + { + if (mouse_past_bottom) + dir = FORWARD; + } + else if (mouse_past_eol) + dir = FORWARD; + + if (fixindent) + { + c1 = (dir == BACKWARD) ? '[' : ']'; + c2 = 'p'; + } + else + { + c1 = (dir == FORWARD) ? 'p' : 'P'; + c2 = NUL; + } + prep_redo(regname, count, NUL, c1, NUL, c2, NUL); + + // Remember where the paste started, so in edit() Insstart can be set + // to this position + if (restart_edit != 0) + where_paste_started = curwin->w_cursor; + do_put(regname, dir, count, fixindent | PUT_CURSEND); + } + + #if defined(FEAT_QUICKFIX) + // Ctrl-Mouse click or double click in a quickfix window jumps to the + // error under the mouse pointer. + else if (((mod_mask & MOD_MASK_CTRL) + || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) + && bt_quickfix(curbuf)) + { + if (curwin->w_llist_ref == NULL) // quickfix window + do_cmdline_cmd((char_u *)".cc"); + else // location list window + do_cmdline_cmd((char_u *)".ll"); + got_click = FALSE; // ignore drag&release now + } + #endif + + // Ctrl-Mouse click (or double click in a help window) jumps to the tag + // under the mouse pointer. + else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help + && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) + { + if (State & INSERT) + stuffcharReadbuff(Ctrl_O); + stuffcharReadbuff(Ctrl_RSB); + got_click = FALSE; // ignore drag&release now + } + + // Shift-Mouse click searches for the next occurrence of the word under + // the mouse pointer + else if ((mod_mask & MOD_MASK_SHIFT)) + { + if ((State & INSERT) || (VIsual_active && VIsual_select)) + stuffcharReadbuff(Ctrl_O); + if (which_button == MOUSE_LEFT) + stuffcharReadbuff('*'); + else // MOUSE_RIGHT + stuffcharReadbuff('#'); + } + + // Handle double clicks, unless on status line + else if (in_status_line) + { + #ifdef FEAT_MOUSESHAPE + if ((is_drag || is_click) && !drag_status_line) + { + drag_status_line = TRUE; + update_mouseshape(-1); + } + #endif + } + else if (in_sep_line) + { + #ifdef FEAT_MOUSESHAPE + if ((is_drag || is_click) && !drag_sep_line) + { + drag_sep_line = TRUE; + update_mouseshape(-1); + } + #endif + } + else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)) + && mouse_has(MOUSE_VISUAL)) + { + if (is_click || !VIsual_active) + { + if (VIsual_active) + orig_cursor = VIsual; + else + { + check_visual_highlight(); + VIsual = curwin->w_cursor; + orig_cursor = VIsual; + VIsual_active = TRUE; + VIsual_reselect = TRUE; + // start Select mode if 'selectmode' contains "mouse" + may_start_select('o'); + setmouse(); + } + if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) + { + // Double click with ALT pressed makes it blockwise. + if (mod_mask & MOD_MASK_ALT) + VIsual_mode = Ctrl_V; + else + VIsual_mode = 'v'; + } + else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK) + VIsual_mode = 'V'; + else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK) + VIsual_mode = Ctrl_V; + #ifdef FEAT_CLIPBOARD + // Make sure the clipboard gets updated. Needed because start and + // end may still be the same, and the selection needs to be owned + clip_star.vmode = NUL; + #endif + } + // A double click selects a word or a block. + if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) + { + pos_T *pos = NULL; + int gc; + + if (is_click) + { + // If the character under the cursor (skipping white space) is + // not a word character, try finding a match and select a (), + // {}, [], #if/#endif, etc. block. + end_visual = curwin->w_cursor; + while (gc = gchar_pos(&end_visual), VIM_ISWHITE(gc)) + inc(&end_visual); + if (oap != NULL) + oap->motion_type = MCHAR; + if (oap != NULL + && VIsual_mode == 'v' + && !vim_iswordc(gchar_pos(&end_visual)) + && EQUAL_POS(curwin->w_cursor, VIsual) + && (pos = findmatch(oap, NUL)) != NULL) + { + curwin->w_cursor = *pos; + if (oap->motion_type == MLINE) + VIsual_mode = 'V'; + else if (*p_sel == 'e') + { + if (LT_POS(curwin->w_cursor, VIsual)) + ++VIsual.col; + else + ++curwin->w_cursor.col; + } + } + } + + if (pos == NULL && (is_click || is_drag)) + { + // When not found a match or when dragging: extend to include + // a word. + if (LT_POS(curwin->w_cursor, orig_cursor)) + { + find_start_of_word(&curwin->w_cursor); + find_end_of_word(&VIsual); + } + else + { + find_start_of_word(&VIsual); + if (*p_sel == 'e' && *ml_get_cursor() != NUL) + curwin->w_cursor.col += + (*mb_ptr2len)(ml_get_cursor()); + find_end_of_word(&curwin->w_cursor); + } + } + curwin->w_set_curswant = TRUE; + } + if (is_click) + redraw_curbuf_later(INVERTED); // update the inversion + } + else if (VIsual_active && !old_active) + { + if (mod_mask & MOD_MASK_ALT) + VIsual_mode = Ctrl_V; + else + VIsual_mode = 'v'; + } + + // If Visual mode changed show it later. + if ((!VIsual_active && old_active && mode_displayed) + || (VIsual_active && p_smd && msg_silent == 0 + && (!old_active || VIsual_mode != old_mode))) + redraw_cmdline = TRUE; + + return moved; + } + + void + ins_mouse(int c) + { + pos_T tpos; + win_T *old_curwin = curwin; + + # ifdef FEAT_GUI + // When GUI is active, also move/paste when 'mouse' is empty + if (!gui.in_use) + # endif + if (!mouse_has(MOUSE_INSERT)) + return; + + undisplay_dollar(); + tpos = curwin->w_cursor; + if (do_mouse(NULL, c, BACKWARD, 1L, 0)) + { + win_T *new_curwin = curwin; + + if (curwin != old_curwin && win_valid(old_curwin)) + { + // Mouse took us to another window. We need to go back to the + // previous one to stop insert there properly. + curwin = old_curwin; + curbuf = curwin->w_buffer; + #ifdef FEAT_JOB_CHANNEL + if (bt_prompt(curbuf)) + // Restart Insert mode when re-entering the prompt buffer. + curbuf->b_prompt_insert = 'A'; + #endif + } + start_arrow(curwin == old_curwin ? &tpos : NULL); + if (curwin != new_curwin && win_valid(new_curwin)) + { + curwin = new_curwin; + curbuf = curwin->w_buffer; + } + # ifdef FEAT_CINDENT + set_can_cindent(TRUE); + # endif + } + + // redraw status lines (in case another window became active) + redraw_statuslines(); + } + + void + ins_mousescroll(int dir) + { + pos_T tpos; + win_T *old_curwin = curwin, *wp; + int did_scroll = FALSE; + + tpos = curwin->w_cursor; + + if (mouse_row >= 0 && mouse_col >= 0) + { + int row, col; + + row = mouse_row; + col = mouse_col; + + // find the window at the pointer coordinates + wp = mouse_find_win(&row, &col, FIND_POPUP); + if (wp == NULL) + return; + curwin = wp; + curbuf = curwin->w_buffer; + } + if (curwin == old_curwin) + undisplay_dollar(); + + // Don't scroll the window in which completion is being done. + if (!pum_visible() || curwin != old_curwin) + { + if (dir == MSCR_DOWN || dir == MSCR_UP) + { + if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) + scroll_redraw(dir, + (long)(curwin->w_botline - curwin->w_topline)); + else + scroll_redraw(dir, 3L); + # ifdef FEAT_TEXT_PROP + if (WIN_IS_POPUP(curwin)) + popup_set_firstline(curwin); + # endif + } + #ifdef FEAT_GUI + else + { + int val, step = 6; + + if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) + step = curwin->w_width; + val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step); + if (val < 0) + val = 0; + gui_do_horiz_scroll(val, TRUE); + } + #endif + did_scroll = TRUE; + } + + curwin->w_redr_status = TRUE; + + curwin = old_curwin; + curbuf = curwin->w_buffer; + + // The popup menu may overlay the window, need to redraw it. + // TODO: Would be more efficient to only redraw the windows that are + // overlapped by the popup menu. + if (pum_visible() && did_scroll) + { + redraw_all_later(NOT_VALID); + ins_compl_show_pum(); + } + + if (!EQUAL_POS(curwin->w_cursor, tpos)) + { + start_arrow(&tpos); + # ifdef FEAT_CINDENT + set_can_cindent(TRUE); + # endif + } + } + + /* + * Return TRUE if "c" is a mouse key. + */ + int + is_mouse_key(int c) + { + return c == K_LEFTMOUSE + || c == K_LEFTMOUSE_NM + || c == K_LEFTDRAG + || c == K_LEFTRELEASE + || c == K_LEFTRELEASE_NM + || c == K_MOUSEMOVE + || c == K_MIDDLEMOUSE + || c == K_MIDDLEDRAG + || c == K_MIDDLERELEASE + || c == K_RIGHTMOUSE + || c == K_RIGHTDRAG + || c == K_RIGHTRELEASE + || c == K_MOUSEDOWN + || c == K_MOUSEUP + || c == K_MOUSELEFT + || c == K_MOUSERIGHT + || c == K_X1MOUSE + || c == K_X1DRAG + || c == K_X1RELEASE + || c == K_X2MOUSE + || c == K_X2DRAG + || c == K_X2RELEASE; + } + + static struct mousetable + { + int pseudo_code; // Code for pseudo mouse event + int button; // Which mouse button is it? + int is_click; // Is it a mouse button click event? + int is_drag; // Is it a mouse drag event? + } mouse_table[] = + { + {(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE}, + #ifdef FEAT_GUI + {(int)KE_LEFTMOUSE_NM, MOUSE_LEFT, TRUE, FALSE}, + #endif + {(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE}, + {(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE}, + #ifdef FEAT_GUI + {(int)KE_LEFTRELEASE_NM, MOUSE_LEFT, FALSE, FALSE}, + #endif + {(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE}, + {(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE}, + {(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE}, + {(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE}, + {(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE}, + {(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE}, + {(int)KE_X1MOUSE, MOUSE_X1, TRUE, FALSE}, + {(int)KE_X1DRAG, MOUSE_X1, FALSE, TRUE}, + {(int)KE_X1RELEASE, MOUSE_X1, FALSE, FALSE}, + {(int)KE_X2MOUSE, MOUSE_X2, TRUE, FALSE}, + {(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE}, + {(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE}, + // DRAG without CLICK + {(int)KE_MOUSEMOVE, MOUSE_RELEASE, FALSE, TRUE}, + // RELEASE without CLICK + {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE}, + {0, 0, 0, 0}, + }; + + /* + * Look up the given mouse code to return the relevant information in the other + * arguments. Return which button is down or was released. + */ + int + get_mouse_button(int code, int *is_click, int *is_drag) + { + int i; + + for (i = 0; mouse_table[i].pseudo_code; i++) + if (code == mouse_table[i].pseudo_code) + { + *is_click = mouse_table[i].is_click; + *is_drag = mouse_table[i].is_drag; + return mouse_table[i].button; + } + return 0; // Shouldn't get here + } + + /* + * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on + * the given information about which mouse button is down, and whether the + * mouse was clicked, dragged or released. + */ + int + get_pseudo_mouse_code( + int button, // eg MOUSE_LEFT + int is_click, + int is_drag) + { + int i; + + for (i = 0; mouse_table[i].pseudo_code; i++) + if (button == mouse_table[i].button + && is_click == mouse_table[i].is_click + && is_drag == mouse_table[i].is_drag) + { + #ifdef FEAT_GUI + // Trick: a non mappable left click and release has mouse_col -1 + // or added MOUSE_COLOFF. Used for 'mousefocus' in + // gui_mouse_moved() + if (mouse_col < 0 || mouse_col > MOUSE_COLOFF) + { + if (mouse_col < 0) + mouse_col = 0; + else + mouse_col -= MOUSE_COLOFF; + if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE) + return (int)KE_LEFTMOUSE_NM; + if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE) + return (int)KE_LEFTRELEASE_NM; + } + #endif + return mouse_table[i].pseudo_code; + } + return (int)KE_IGNORE; // not recognized, ignore it + } + + # ifdef FEAT_MOUSE_TTY + # define HMT_NORMAL 1 + # define HMT_NETTERM 2 + # define HMT_DEC 4 + # define HMT_JSBTERM 8 + # define HMT_PTERM 16 + # define HMT_URXVT 32 + # define HMT_GPM 64 + # define HMT_SGR 128 + # define HMT_SGR_REL 256 + static int has_mouse_termcode = 0; + # endif + + # if (!defined(UNIX) || defined(FEAT_MOUSE_TTY)) || defined(PROTO) + void + set_mouse_termcode( + int n, // KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE + char_u *s) + { + char_u name[2]; + + name[0] = n; + name[1] = KE_FILLER; + add_termcode(name, s, FALSE); + # ifdef FEAT_MOUSE_TTY + # ifdef FEAT_MOUSE_JSB + if (n == KS_JSBTERM_MOUSE) + has_mouse_termcode |= HMT_JSBTERM; + else + # endif + # ifdef FEAT_MOUSE_NET + if (n == KS_NETTERM_MOUSE) + has_mouse_termcode |= HMT_NETTERM; + else + # endif + # ifdef FEAT_MOUSE_DEC + if (n == KS_DEC_MOUSE) + has_mouse_termcode |= HMT_DEC; + else + # endif + # ifdef FEAT_MOUSE_PTERM + if (n == KS_PTERM_MOUSE) + has_mouse_termcode |= HMT_PTERM; + else + # endif + # ifdef FEAT_MOUSE_URXVT + if (n == KS_URXVT_MOUSE) + has_mouse_termcode |= HMT_URXVT; + else + # endif + # ifdef FEAT_MOUSE_GPM + if (n == KS_GPM_MOUSE) + has_mouse_termcode |= HMT_GPM; + else + # endif + if (n == KS_SGR_MOUSE) + has_mouse_termcode |= HMT_SGR; + else if (n == KS_SGR_MOUSE_RELEASE) + has_mouse_termcode |= HMT_SGR_REL; + else + has_mouse_termcode |= HMT_NORMAL; + # endif + } + # endif + + # if ((defined(UNIX) || defined(VMS)) \ + && defined(FEAT_MOUSE_TTY)) || defined(PROTO) + void + del_mouse_termcode( + int n) // KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE + { + char_u name[2]; + + name[0] = n; + name[1] = KE_FILLER; + del_termcode(name); + # ifdef FEAT_MOUSE_TTY + # ifdef FEAT_MOUSE_JSB + if (n == KS_JSBTERM_MOUSE) + has_mouse_termcode &= ~HMT_JSBTERM; + else + # endif + # ifdef FEAT_MOUSE_NET + if (n == KS_NETTERM_MOUSE) + has_mouse_termcode &= ~HMT_NETTERM; + else + # endif + # ifdef FEAT_MOUSE_DEC + if (n == KS_DEC_MOUSE) + has_mouse_termcode &= ~HMT_DEC; + else + # endif + # ifdef FEAT_MOUSE_PTERM + if (n == KS_PTERM_MOUSE) + has_mouse_termcode &= ~HMT_PTERM; + else + # endif + # ifdef FEAT_MOUSE_URXVT + if (n == KS_URXVT_MOUSE) + has_mouse_termcode &= ~HMT_URXVT; + else + # endif + # ifdef FEAT_MOUSE_GPM + if (n == KS_GPM_MOUSE) + has_mouse_termcode &= ~HMT_GPM; + else + # endif + if (n == KS_SGR_MOUSE) + has_mouse_termcode &= ~HMT_SGR; + else if (n == KS_SGR_MOUSE_RELEASE) + has_mouse_termcode &= ~HMT_SGR_REL; + else + has_mouse_termcode &= ~HMT_NORMAL; + # endif + } + # endif + + /* + * setmouse() - switch mouse on/off depending on current mode and 'mouse' + */ + void + setmouse(void) + { + # ifdef FEAT_MOUSE_TTY + int checkfor; + # endif + + # ifdef FEAT_MOUSESHAPE + update_mouseshape(-1); + # endif + + # ifdef FEAT_MOUSE_TTY // Should be outside proc, but may break MOUSESHAPE + # ifdef FEAT_GUI + // In the GUI the mouse is always enabled. + if (gui.in_use) + return; + # endif + // be quick when mouse is off + if (*p_mouse == NUL || has_mouse_termcode == 0) + return; + + // don't switch mouse on when not in raw mode (Ex mode) + if (cur_tmode != TMODE_RAW) + { + mch_setmouse(FALSE); + return; + } + + if (VIsual_active) + checkfor = MOUSE_VISUAL; + else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) + checkfor = MOUSE_RETURN; + else if (State & INSERT) + checkfor = MOUSE_INSERT; + else if (State & CMDLINE) + checkfor = MOUSE_COMMAND; + else if (State == CONFIRM || State == EXTERNCMD) + checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd" + else + checkfor = MOUSE_NORMAL; // assume normal mode + + if (mouse_has(checkfor)) + mch_setmouse(TRUE); + else + mch_setmouse(FALSE); + # endif + } + + /* + * Return TRUE if + * - "c" is in 'mouse', or + * - 'a' is in 'mouse' and "c" is in MOUSE_A, or + * - the current buffer is a help file and 'h' is in 'mouse' and we are in a + * normal editing mode (not at hit-return message). + */ + int + mouse_has(int c) + { + char_u *p; + + for (p = p_mouse; *p; ++p) + switch (*p) + { + case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) + return TRUE; + break; + case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) + return TRUE; + break; + default: if (c == *p) return TRUE; break; + } + return FALSE; + } + + /* + * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos". + */ + int + mouse_model_popup(void) + { + return (p_mousem[0] == 'p'); + } + + /* + * Move the cursor to the specified row and column on the screen. + * Change current window if necessary. Returns an integer with the + * CURSOR_MOVED bit set if the cursor has moved or unset otherwise. + * + * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column. + * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column. + * + * If flags has MOUSE_FOCUS, then the current window will not be changed, and + * if the mouse is outside the window then the text will scroll, or if the + * mouse was previously on a status line, then the status line may be dragged. + * + * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the + * cursor is moved unless the cursor was on a status line. + * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or + * IN_SEP_LINE depending on where the cursor was clicked. + * + * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless + * the mouse is on the status line of the same window. + * + * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since + * the last call. + * + * If flags has MOUSE_SETPOS, nothing is done, only the current position is + * remembered. + */ + int + jump_to_mouse( + int flags, + int *inclusive, // used for inclusive operator, can be NULL + int which_button) // MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE + { + static int on_status_line = 0; // #lines below bottom of window + static int on_sep_line = 0; // on separator right of window + #ifdef FEAT_MENU + static int in_winbar = FALSE; + #endif + #ifdef FEAT_TEXT_PROP + static int in_popup_win = FALSE; + static win_T *click_in_popup_win = NULL; + #endif + static int prev_row = -1; + static int prev_col = -1; + static win_T *dragwin = NULL; // window being dragged + static int did_drag = FALSE; // drag was noticed + + win_T *wp, *old_curwin; + pos_T old_cursor; + int count; + int first; + int row = mouse_row; + int col = mouse_col; + #ifdef FEAT_FOLDING + int mouse_char; + #endif + + mouse_past_bottom = FALSE; + mouse_past_eol = FALSE; + + if (flags & MOUSE_RELEASED) + { + // On button release we may change window focus if positioned on a + // status line and no dragging happened. + if (dragwin != NULL && !did_drag) + flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE); + dragwin = NULL; + did_drag = FALSE; + #ifdef FEAT_TEXT_PROP + if (click_in_popup_win != NULL && popup_dragwin == NULL) + popup_close_for_mouse_click(click_in_popup_win); + + popup_dragwin = NULL; + click_in_popup_win = NULL; + #endif + } + + if ((flags & MOUSE_DID_MOVE) + && prev_row == mouse_row + && prev_col == mouse_col) + { + retnomove: + // before moving the cursor for a left click which is NOT in a status + // line, stop Visual mode + if (on_status_line) + return IN_STATUS_LINE; + if (on_sep_line) + return IN_SEP_LINE; + #ifdef FEAT_MENU + if (in_winbar) + { + // A quick second click may arrive as a double-click, but we use it + // as a second click in the WinBar. + if ((mod_mask & MOD_MASK_MULTI_CLICK) && !(flags & MOUSE_RELEASED)) + { + wp = mouse_find_win(&row, &col, FAIL_POPUP); + if (wp == NULL) + return IN_UNKNOWN; + winbar_click(wp, col); + } + return IN_OTHER_WIN | MOUSE_WINBAR; + } + #endif + if (flags & MOUSE_MAY_STOP_VIS) + { + end_visual_mode(); + redraw_curbuf_later(INVERTED); // delete the inversion + } + #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) + // Continue a modeless selection in another window. + if (cmdwin_type != 0 && row < curwin->w_winrow) + return IN_OTHER_WIN; + #endif + #ifdef FEAT_TEXT_PROP + // Continue a modeless selection in a popup window or dragging it. + if (in_popup_win) + { + click_in_popup_win = NULL; // don't close it on release + if (popup_dragwin != NULL) + { + // dragging a popup window + popup_drag(popup_dragwin); + return IN_UNKNOWN; + } + return IN_OTHER_WIN; + } + #endif + return IN_BUFFER; + } + + prev_row = mouse_row; + prev_col = mouse_col; + + if (flags & MOUSE_SETPOS) + goto retnomove; // ugly goto... + + #ifdef FEAT_FOLDING + // Remember the character under the mouse, it might be a '-' or '+' in the + // fold column. + if (row >= 0 && row < Rows && col >= 0 && col <= Columns + && ScreenLines != NULL) + mouse_char = ScreenLines[LineOffset[row] + col]; + else + mouse_char = ' '; + #endif + + old_curwin = curwin; + old_cursor = curwin->w_cursor; + + if (!(flags & MOUSE_FOCUS)) + { + if (row < 0 || col < 0) // check if it makes sense + return IN_UNKNOWN; + + // find the window where the row is in and adjust "row" and "col" to be + // relative to top-left of the window + wp = mouse_find_win(&row, &col, FIND_POPUP); + if (wp == NULL) + return IN_UNKNOWN; + dragwin = NULL; + + #ifdef FEAT_TEXT_PROP + // Click in a popup window may start dragging or modeless selection, + // but not much else. + if (WIN_IS_POPUP(wp)) + { + on_sep_line = 0; + in_popup_win = TRUE; + if (which_button == MOUSE_LEFT && popup_close_if_on_X(wp, row, col)) + { + return IN_UNKNOWN; + } + else if ((wp->w_popup_flags & (POPF_DRAG | POPF_RESIZE)) + && popup_on_border(wp, row, col)) + { + popup_dragwin = wp; + popup_start_drag(wp, row, col); + return IN_UNKNOWN; + } + // Only close on release, otherwise it's not possible to drag or do + // modeless selection. + else if (wp->w_popup_close == POPCLOSE_CLICK + && which_button == MOUSE_LEFT) + { + click_in_popup_win = wp; + } + else if (which_button == MOUSE_LEFT) + // If the click is in the scrollbar, may scroll up/down. + popup_handle_scrollbar_click(wp, row, col); + # ifdef FEAT_CLIPBOARD + return IN_OTHER_WIN; + # else + return IN_UNKNOWN; + # endif + } + in_popup_win = FALSE; + popup_dragwin = NULL; + #endif + #ifdef FEAT_MENU + if (row == -1) + { + // A click in the window toolbar does not enter another window or + // change Visual highlighting. + winbar_click(wp, col); + in_winbar = TRUE; + return IN_OTHER_WIN | MOUSE_WINBAR; + } + in_winbar = FALSE; + #endif + + // winpos and height may change in win_enter()! + if (row >= wp->w_height) // In (or below) status line + { + on_status_line = row - wp->w_height + 1; + dragwin = wp; + } + else + on_status_line = 0; + if (col >= wp->w_width) // In separator line + { + on_sep_line = col - wp->w_width + 1; + dragwin = wp; + } + else + on_sep_line = 0; + + // The rightmost character of the status line might be a vertical + // separator character if there is no connecting window to the right. + if (on_status_line && on_sep_line) + { + if (stl_connected(wp)) + on_sep_line = 0; + else + on_status_line = 0; + } + + // Before jumping to another buffer, or moving the cursor for a left + // click, stop Visual mode. + if (VIsual_active + && (wp->w_buffer != curwin->w_buffer + || (!on_status_line && !on_sep_line + #ifdef FEAT_FOLDING + && ( + # ifdef FEAT_RIGHTLEFT + wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc : + # endif + col >= wp->w_p_fdc + # ifdef FEAT_CMDWIN + + (cmdwin_type == 0 && wp == curwin ? 0 : 1) + # endif + ) + #endif + && (flags & MOUSE_MAY_STOP_VIS)))) + { + end_visual_mode(); + redraw_curbuf_later(INVERTED); // delete the inversion + } + #ifdef FEAT_CMDWIN + if (cmdwin_type != 0 && wp != curwin) + { + // A click outside the command-line window: Use modeless + // selection if possible. Allow dragging the status lines. + on_sep_line = 0; + # ifdef FEAT_CLIPBOARD + if (on_status_line) + return IN_STATUS_LINE; + return IN_OTHER_WIN; + # else + row = 0; + col += wp->w_wincol; + wp = curwin; + # endif + } + #endif + // Only change window focus when not clicking on or dragging the + // status line. Do change focus when releasing the mouse button + // (MOUSE_FOCUS was set above if we dragged first). + if (dragwin == NULL || (flags & MOUSE_RELEASED)) + win_enter(wp, TRUE); // can make wp invalid! + + if (curwin != old_curwin) + { + #ifdef CHECK_DOUBLE_CLICK + // set topline, to be able to check for double click ourselves + set_mouse_topline(curwin); + #endif + #ifdef FEAT_TERMINAL + // when entering a terminal window may change state + term_win_entered(); + #endif + } + if (on_status_line) // In (or below) status line + { + // Don't use start_arrow() if we're in the same window + if (curwin == old_curwin) + return IN_STATUS_LINE; + else + return IN_STATUS_LINE | CURSOR_MOVED; + } + if (on_sep_line) // In (or below) status line + { + // Don't use start_arrow() if we're in the same window + if (curwin == old_curwin) + return IN_SEP_LINE; + else + return IN_SEP_LINE | CURSOR_MOVED; + } + + curwin->w_cursor.lnum = curwin->w_topline; + #ifdef FEAT_GUI + // remember topline, needed for double click + gui_prev_topline = curwin->w_topline; + # ifdef FEAT_DIFF + gui_prev_topfill = curwin->w_topfill; + # endif + #endif + } + else if (on_status_line && which_button == MOUSE_LEFT) + { + if (dragwin != NULL) + { + // Drag the status line + count = row - dragwin->w_winrow - dragwin->w_height + 1 + - on_status_line; + win_drag_status_line(dragwin, count); + did_drag |= count; + } + return IN_STATUS_LINE; // Cursor didn't move + } + else if (on_sep_line && which_button == MOUSE_LEFT) + { + if (dragwin != NULL) + { + // Drag the separator column + count = col - dragwin->w_wincol - dragwin->w_width + 1 + - on_sep_line; + win_drag_vsep_line(dragwin, count); + did_drag |= count; + } + return IN_SEP_LINE; // Cursor didn't move + } + #ifdef FEAT_MENU + else if (in_winbar) + { + // After a click on the window toolbar don't start Visual mode. + return IN_OTHER_WIN | MOUSE_WINBAR; + } + #endif + else // keep_window_focus must be TRUE + { + // before moving the cursor for a left click, stop Visual mode + if (flags & MOUSE_MAY_STOP_VIS) + { + end_visual_mode(); + redraw_curbuf_later(INVERTED); // delete the inversion + } + + #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) + // Continue a modeless selection in another window. + if (cmdwin_type != 0 && row < curwin->w_winrow) + return IN_OTHER_WIN; + #endif + #ifdef FEAT_TEXT_PROP + if (in_popup_win) + { + if (popup_dragwin != NULL) + { + // dragging a popup window + popup_drag(popup_dragwin); + return IN_UNKNOWN; + } + // continue a modeless selection in a popup window + click_in_popup_win = NULL; + return IN_OTHER_WIN; + } + #endif + + row -= W_WINROW(curwin); + col -= curwin->w_wincol; + + // When clicking beyond the end of the window, scroll the screen. + // Scroll by however many rows outside the window we are. + if (row < 0) + { + count = 0; + for (first = TRUE; curwin->w_topline > 1; ) + { + #ifdef FEAT_DIFF + if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) + ++count; + else + #endif + count += plines(curwin->w_topline - 1); + if (!first && count > -row) + break; + first = FALSE; + #ifdef FEAT_FOLDING + (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); + #endif + #ifdef FEAT_DIFF + if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) + ++curwin->w_topfill; + else + #endif + { + --curwin->w_topline; + #ifdef FEAT_DIFF + curwin->w_topfill = 0; + #endif + } + } + #ifdef FEAT_DIFF + check_topfill(curwin, FALSE); + #endif + curwin->w_valid &= + ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); + redraw_later(VALID); + row = 0; + } + else if (row >= curwin->w_height) + { + count = 0; + for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; ) + { + #ifdef FEAT_DIFF + if (curwin->w_topfill > 0) + ++count; + else + #endif + count += plines(curwin->w_topline); + if (!first && count > row - curwin->w_height + 1) + break; + first = FALSE; + #ifdef FEAT_FOLDING + if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline) + && curwin->w_topline == curbuf->b_ml.ml_line_count) + break; + #endif + #ifdef FEAT_DIFF + if (curwin->w_topfill > 0) + --curwin->w_topfill; + else + #endif + { + ++curwin->w_topline; + #ifdef FEAT_DIFF + curwin->w_topfill = + diff_check_fill(curwin, curwin->w_topline); + #endif + } + } + #ifdef FEAT_DIFF + check_topfill(curwin, FALSE); + #endif + redraw_later(VALID); + curwin->w_valid &= + ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); + row = curwin->w_height - 1; + } + else if (row == 0) + { + // When dragging the mouse, while the text has been scrolled up as + // far as it goes, moving the mouse in the top line should scroll + // the text down (done later when recomputing w_topline). + if (mouse_dragging > 0 + && curwin->w_cursor.lnum + == curwin->w_buffer->b_ml.ml_line_count + && curwin->w_cursor.lnum == curwin->w_topline) + curwin->w_valid &= ~(VALID_TOPLINE); + } + } + + #ifdef FEAT_FOLDING + // Check for position outside of the fold column. + if ( + # ifdef FEAT_RIGHTLEFT + curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc : + # endif + col >= curwin->w_p_fdc + # ifdef FEAT_CMDWIN + + (cmdwin_type == 0 ? 0 : 1) + # endif + ) + mouse_char = ' '; + #endif + + // compute the position in the buffer line from the posn on the screen + if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum, NULL)) + mouse_past_bottom = TRUE; + + // Start Visual mode before coladvance(), for when 'sel' != "old" + if ((flags & MOUSE_MAY_VIS) && !VIsual_active) + { + check_visual_highlight(); + VIsual = old_cursor; + VIsual_active = TRUE; + VIsual_reselect = TRUE; + // if 'selectmode' contains "mouse", start Select mode + may_start_select('o'); + setmouse(); + if (p_smd && msg_silent == 0) + redraw_cmdline = TRUE; // show visual mode later + } + + curwin->w_curswant = col; + curwin->w_set_curswant = FALSE; // May still have been TRUE + if (coladvance(col) == FAIL) // Mouse click beyond end of line + { + if (inclusive != NULL) + *inclusive = TRUE; + mouse_past_eol = TRUE; + } + else if (inclusive != NULL) + *inclusive = FALSE; + + count = IN_BUFFER; + if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum + || curwin->w_cursor.col != old_cursor.col) + count |= CURSOR_MOVED; // Cursor has moved + + # ifdef FEAT_FOLDING + if (mouse_char == '+') + count |= MOUSE_FOLD_OPEN; + else if (mouse_char != ' ') + count |= MOUSE_FOLD_CLOSE; + # endif + + return count; + } + + /* + * Mouse scroll wheel: Default action is to scroll three lines, or one page + * when Shift or Ctrl is used. + * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or + * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2) + */ + void + nv_mousescroll(cmdarg_T *cap) + { + win_T *old_curwin = curwin, *wp; + + if (mouse_row >= 0 && mouse_col >= 0) + { + int row, col; + + row = mouse_row; + col = mouse_col; + + // find the window at the pointer coordinates + wp = mouse_find_win(&row, &col, FIND_POPUP); + if (wp == NULL) + return; + #ifdef FEAT_TEXT_PROP + if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar) + return; + #endif + curwin = wp; + curbuf = curwin->w_buffer; + } + + if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) + { + # ifdef FEAT_TERMINAL + if (term_use_loop()) + // This window is a terminal window, send the mouse event there. + // Set "typed" to FALSE to avoid an endless loop. + send_keys_to_term(curbuf->b_term, cap->cmdchar, FALSE); + else + # endif + if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) + { + (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L); + } + else + { + // Don't scroll more than half the window height. + if (curwin->w_height < 6) + { + cap->count1 = curwin->w_height / 2; + if (cap->count1 == 0) + cap->count1 = 1; + } + else + cap->count1 = 3; + cap->count0 = cap->count1; + nv_scroll_line(cap); + } + #ifdef FEAT_TEXT_PROP + if (WIN_IS_POPUP(curwin)) + popup_set_firstline(curwin); + #endif + } + # ifdef FEAT_GUI + else + { + // Horizontal scroll - only allowed when 'wrap' is disabled + if (!curwin->w_p_wrap) + { + int val, step = 6; + + if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) + step = curwin->w_width; + val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step); + if (val < 0) + val = 0; + + gui_do_horiz_scroll(val, TRUE); + } + } + # endif + # ifdef FEAT_SYN_HL + if (curwin != old_curwin && curwin->w_p_cul) + redraw_for_cursorline(curwin); + # endif + + curwin->w_redr_status = TRUE; + + curwin = old_curwin; + curbuf = curwin->w_buffer; + } + + /* + * Mouse clicks and drags. + */ + void + nv_mouse(cmdarg_T *cap) + { + (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0); + } + #endif // FEAT_MOUSE + + // Functions also used for popup windows. + #if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO) + + /* + * Compute the buffer line position from the screen position "rowp" / "colp" in + * window "win". + * "plines_cache" can be NULL (no cache) or an array with "win->w_height" + * entries that caches the plines_win() result from a previous call. Entry is + * zero if not computed yet. There must be no text or setting changes since + * the entry is put in the cache. + * Returns TRUE if the position is below the last line. + */ + int + mouse_comp_pos( + win_T *win, + int *rowp, + int *colp, + linenr_T *lnump, + int *plines_cache) + { + int col = *colp; + int row = *rowp; + linenr_T lnum; + int retval = FALSE; + int off; + int count; + + #ifdef FEAT_RIGHTLEFT + if (win->w_p_rl) + col = win->w_width - 1 - col; + #endif + + lnum = win->w_topline; + + while (row > 0) + { + int cache_idx = lnum - win->w_topline; + + if (plines_cache != NULL && plines_cache[cache_idx] > 0) + count = plines_cache[cache_idx]; + else + { + #ifdef FEAT_DIFF + // Don't include filler lines in "count" + if (win->w_p_diff + # ifdef FEAT_FOLDING + && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL) + # endif + ) + { + if (lnum == win->w_topline) + row -= win->w_topfill; + else + row -= diff_check_fill(win, lnum); + count = plines_win_nofill(win, lnum, TRUE); + } + else + #endif + count = plines_win(win, lnum, TRUE); + if (plines_cache != NULL) + plines_cache[cache_idx] = count; + } + if (count > row) + break; // Position is in this buffer line. + #ifdef FEAT_FOLDING + (void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL); + #endif + if (lnum == win->w_buffer->b_ml.ml_line_count) + { + retval = TRUE; + break; // past end of file + } + row -= count; + ++lnum; + } + + if (!retval) + { + // Compute the column without wrapping. + off = win_col_off(win) - win_col_off2(win); + if (col < off) + col = off; + col += row * (win->w_width - off); + // add skip column (for long wrapping line) + col += win->w_skipcol; + } + + if (!win->w_p_wrap) + col += win->w_leftcol; + + // skip line number and fold column in front of the line + col -= win_col_off(win); + if (col < 0) + { + #ifdef FEAT_NETBEANS_INTG + netbeans_gutter_click(lnum); + #endif + col = 0; + } + + *colp = col; + *rowp = row; + *lnump = lnum; + return retval; + } + + /* + * Find the window at screen position "*rowp" and "*colp". The positions are + * updated to become relative to the top-left of the window. + * When "popup" is FAIL_POPUP and the position is in a popup window then NULL + * is returned. When "popup" is IGNORE_POPUP then do not even check popup + * windows. + * Returns NULL when something is wrong. + */ + win_T * + mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED) + { + frame_T *fp; + win_T *wp; + + #ifdef FEAT_TEXT_PROP + win_T *pwp = NULL; + + if (popup != IGNORE_POPUP) + { + popup_reset_handled(); + while ((wp = find_next_popup(TRUE)) != NULL) + { + if (*rowp >= wp->w_winrow && *rowp < wp->w_winrow + popup_height(wp) + && *colp >= wp->w_wincol + && *colp < wp->w_wincol + popup_width(wp)) + pwp = wp; + } + if (pwp != NULL) + { + if (popup == FAIL_POPUP) + return NULL; + *rowp -= pwp->w_winrow; + *colp -= pwp->w_wincol; + return pwp; + } + } + #endif + + fp = topframe; + *rowp -= firstwin->w_winrow; + for (;;) + { + if (fp->fr_layout == FR_LEAF) + break; + if (fp->fr_layout == FR_ROW) + { + for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) + { + if (*colp < fp->fr_width) + break; + *colp -= fp->fr_width; + } + } + else // fr_layout == FR_COL + { + for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) + { + if (*rowp < fp->fr_height) + break; + *rowp -= fp->fr_height; + } + } + } + // When using a timer that closes a window the window might not actually + // exist. + FOR_ALL_WINDOWS(wp) + if (wp == fp->fr_win) + { + #ifdef FEAT_MENU + *rowp -= wp->w_winbar_height; + #endif + return wp; + } + return NULL; + } + + #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ + || defined(FEAT_GUI_PHOTON) || defined(FEAT_TERM_POPUP_MENU) \ + || defined(PROTO) + # define NEED_VCOL2COL + + /* + * Translate window coordinates to buffer position without any side effects + */ + static int + get_fpos_of_mouse(pos_T *mpos) + { + win_T *wp; + int row = mouse_row; + int col = mouse_col; + + if (row < 0 || col < 0) // check if it makes sense + return IN_UNKNOWN; + + // find the window where the row is in + wp = mouse_find_win(&row, &col, FAIL_POPUP); + if (wp == NULL) + return IN_UNKNOWN; + // winpos and height may change in win_enter()! + if (row >= wp->w_height) // In (or below) status line + return IN_STATUS_LINE; + if (col >= wp->w_width) // In vertical separator line + return IN_SEP_LINE; + + if (wp != curwin) + return IN_UNKNOWN; + + // compute the position in the buffer line from the posn on the screen + if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum, NULL)) + return IN_STATUS_LINE; // past bottom + + mpos->col = vcol2col(wp, mpos->lnum, col); + + if (mpos->col > 0) + --mpos->col; + mpos->coladd = 0; + return IN_BUFFER; + } + #endif + + #if defined(NEED_VCOL2COL) || defined(FEAT_BEVAL) || defined(FEAT_TEXT_PROP) \ + || defined(PROTO) + /* + * Convert a virtual (screen) column to a character column. + * The first column is one. + */ + int + vcol2col(win_T *wp, linenr_T lnum, int vcol) + { + // try to advance to the specified column + int count = 0; + char_u *ptr; + char_u *line; + + line = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); + while (count < vcol && *ptr != NUL) + { + count += win_lbr_chartabsize(wp, line, ptr, count, NULL); + MB_PTR_ADV(ptr); + } + return (int)(ptr - line); + } + #endif + + #else // FEAT_MOUSE + + /* + * Dummy implementation of setmouse() to avoid lots of #ifdefs. + */ + void + setmouse(void) + { + } + + #endif // FEAT_MOUSE *** ../vim-8.1.2061/src/normal.c 2019-09-20 13:40:10.784920381 +0200 --- src/normal.c 2019-09-21 20:40:09.534279693 +0200 *************** *** 30,43 **** static int nv_compare(const void *s1, const void *s2); static void op_colon(oparg_T *oap); static void op_function(oparg_T *oap); - #if defined(FEAT_MOUSE) - static void find_start_of_word(pos_T *); - static void find_end_of_word(pos_T *); - static int get_mouse_class(char_u *p); - #endif - static void prep_redo(int regname, long, int, int, int, int, int); - static void clearop(oparg_T *oap); - static void clearopbeep(oparg_T *oap); static void unshift_special(cmdarg_T *cap); static void may_clear_cmdline(void); #ifdef FEAT_CMDL_INFO --- 30,35 ---- *************** *** 55,65 **** static void nv_help(cmdarg_T *cap); static void nv_addsub(cmdarg_T *cap); static void nv_page(cmdarg_T *cap); - #ifdef FEAT_MOUSE - static void nv_mousescroll(cmdarg_T *cap); - static void nv_mouse(cmdarg_T *cap); - #endif - static void nv_scroll_line(cmdarg_T *cap); static void nv_zet(cmdarg_T *cap); #ifdef FEAT_GUI static void nv_ver_scrollbar(cmdarg_T *cap); --- 47,52 ---- *************** *** 2201,3210 **** #endif } - #if defined(FEAT_MOUSE) || defined(PROTO) - /* - * Do the appropriate action for the current mouse click in the current mode. - * Not used for Command-line mode. - * - * Normal and Visual Mode: - * event modi- position visual change action - * fier cursor window - * left press - yes end yes - * left press C yes end yes "^]" (2) - * left press S yes end (popup: extend) yes "*" (2) - * left drag - yes start if moved no - * left relse - yes start if moved no - * middle press - yes if not active no put register - * middle press - yes if active no yank and put - * right press - yes start or extend yes - * right press S yes no change yes "#" (2) - * right drag - yes extend no - * right relse - yes extend no - * - * Insert or Replace Mode: - * event modi- position visual change action - * fier cursor window - * left press - yes (cannot be active) yes - * left press C yes (cannot be active) yes "CTRL-O^]" (2) - * left press S yes (cannot be active) yes "CTRL-O*" (2) - * left drag - yes start or extend (1) no CTRL-O (1) - * left relse - yes start or extend (1) no CTRL-O (1) - * middle press - no (cannot be active) no put register - * right press - yes start or extend yes CTRL-O - * right press S yes (cannot be active) yes "CTRL-O#" (2) - * - * (1) only if mouse pointer moved since press - * (2) only if click is in same buffer - * - * Return TRUE if start_arrow() should be called for edit mode. - */ - int - do_mouse( - oparg_T *oap, /* operator argument, can be NULL */ - int c, /* K_LEFTMOUSE, etc */ - int dir, /* Direction to 'put' if necessary */ - long count, - int fixindent) /* PUT_FIXINDENT if fixing indent necessary */ - { - static int do_always = FALSE; /* ignore 'mouse' setting next time */ - static int got_click = FALSE; /* got a click some time back */ - - int which_button; /* MOUSE_LEFT, _MIDDLE or _RIGHT */ - int is_click; /* If FALSE it's a drag or release event */ - int is_drag; /* If TRUE it's a drag event */ - int jump_flags = 0; /* flags for jump_to_mouse() */ - pos_T start_visual; - int moved; /* Has cursor moved? */ - int in_status_line; /* mouse in status line */ - static int in_tab_line = FALSE; /* mouse clicked in tab line */ - int in_sep_line; /* mouse in vertical separator line */ - int c1, c2; - #if defined(FEAT_FOLDING) - pos_T save_cursor; - #endif - win_T *old_curwin = curwin; - static pos_T orig_cursor; - colnr_T leftcol, rightcol; - pos_T end_visual; - int diff; - int old_active = VIsual_active; - int old_mode = VIsual_mode; - int regname; - - #if defined(FEAT_FOLDING) - save_cursor = curwin->w_cursor; - #endif - - /* - * When GUI is active, always recognize mouse events, otherwise: - * - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'. - * - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'. - * - For command line and insert mode 'mouse' is checked before calling - * do_mouse(). - */ - if (do_always) - do_always = FALSE; - else - #ifdef FEAT_GUI - if (!gui.in_use) - #endif - { - if (VIsual_active) - { - if (!mouse_has(MOUSE_VISUAL)) - return FALSE; - } - else if (State == NORMAL && !mouse_has(MOUSE_NORMAL)) - return FALSE; - } - - for (;;) - { - which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); - if (is_drag) - { - /* If the next character is the same mouse event then use that - * one. Speeds up dragging the status line. */ - if (vpeekc() != NUL) - { - int nc; - int save_mouse_row = mouse_row; - int save_mouse_col = mouse_col; - - /* Need to get the character, peeking doesn't get the actual - * one. */ - nc = safe_vgetc(); - if (c == nc) - continue; - vungetc(nc); - mouse_row = save_mouse_row; - mouse_col = save_mouse_col; - } - } - break; - } - - if (c == K_MOUSEMOVE) - { - // Mouse moved without a button pressed. - #ifdef FEAT_BEVAL_TERM - ui_may_remove_balloon(); - if (p_bevalterm) - { - profile_setlimit(p_bdlay, &bevalexpr_due); - bevalexpr_due_set = TRUE; - } - #endif - #ifdef FEAT_TEXT_PROP - popup_handle_mouse_moved(); - #endif - return FALSE; - } - - #ifdef FEAT_MOUSESHAPE - /* May have stopped dragging the status or separator line. The pointer is - * most likely still on the status or separator line. */ - if (!is_drag && drag_status_line) - { - drag_status_line = FALSE; - update_mouseshape(SHAPE_IDX_STATUS); - } - if (!is_drag && drag_sep_line) - { - drag_sep_line = FALSE; - update_mouseshape(SHAPE_IDX_VSEP); - } - #endif - - /* - * Ignore drag and release events if we didn't get a click. - */ - if (is_click) - got_click = TRUE; - else - { - if (!got_click) /* didn't get click, ignore */ - return FALSE; - if (!is_drag) /* release, reset got_click */ - { - got_click = FALSE; - if (in_tab_line) - { - in_tab_line = FALSE; - return FALSE; - } - } - } - - /* - * CTRL right mouse button does CTRL-T - */ - if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT) - { - if (State & INSERT) - stuffcharReadbuff(Ctrl_O); - if (count > 1) - stuffnumReadbuff(count); - stuffcharReadbuff(Ctrl_T); - got_click = FALSE; /* ignore drag&release now */ - return FALSE; - } - - /* - * CTRL only works with left mouse button - */ - if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT) - return FALSE; - - /* - * When a modifier is down, ignore drag and release events, as well as - * multiple clicks and the middle mouse button. - * Accept shift-leftmouse drags when 'mousemodel' is "popup.*". - */ - if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT - | MOD_MASK_META)) - && (!is_click - || (mod_mask & MOD_MASK_MULTI_CLICK) - || which_button == MOUSE_MIDDLE) - && !((mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)) - && mouse_model_popup() - && which_button == MOUSE_LEFT) - && !((mod_mask & MOD_MASK_ALT) - && !mouse_model_popup() - && which_button == MOUSE_RIGHT) - ) - return FALSE; - - /* - * If the button press was used as the movement command for an operator - * (eg "d"), or it is the middle button that is held down, ignore - * drag/release events. - */ - if (!is_click && which_button == MOUSE_MIDDLE) - return FALSE; - - if (oap != NULL) - regname = oap->regname; - else - regname = 0; - - /* - * Middle mouse button does a 'put' of the selected text - */ - if (which_button == MOUSE_MIDDLE) - { - if (State == NORMAL) - { - /* - * If an operator was pending, we don't know what the user wanted - * to do. Go back to normal mode: Clear the operator and beep(). - */ - if (oap != NULL && oap->op_type != OP_NOP) - { - clearopbeep(oap); - return FALSE; - } - - /* - * If visual was active, yank the highlighted text and put it - * before the mouse pointer position. - * In Select mode replace the highlighted text with the clipboard. - */ - if (VIsual_active) - { - if (VIsual_select) - { - stuffcharReadbuff(Ctrl_G); - stuffReadbuff((char_u *)"\"+p"); - } - else - { - stuffcharReadbuff('y'); - stuffcharReadbuff(K_MIDDLEMOUSE); - } - do_always = TRUE; /* ignore 'mouse' setting next time */ - return FALSE; - } - /* - * The rest is below jump_to_mouse() - */ - } - - else if ((State & INSERT) == 0) - return FALSE; - - /* - * Middle click in insert mode doesn't move the mouse, just insert the - * contents of a register. '.' register is special, can't insert that - * with do_put(). - * Also paste at the cursor if the current mode isn't in 'mouse' (only - * happens for the GUI). - */ - if ((State & INSERT) || !mouse_has(MOUSE_NORMAL)) - { - if (regname == '.') - insert_reg(regname, TRUE); - else - { - #ifdef FEAT_CLIPBOARD - if (clip_star.available && regname == 0) - regname = '*'; - #endif - if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) - insert_reg(regname, TRUE); - else - { - do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND); - - /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */ - AppendCharToRedobuff(Ctrl_R); - AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O); - AppendCharToRedobuff(regname == 0 ? '"' : regname); - } - } - return FALSE; - } - } - - /* When dragging or button-up stay in the same window. */ - if (!is_click) - jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE; - - start_visual.lnum = 0; - - /* Check for clicking in the tab page line. */ - if (mouse_row == 0 && firstwin->w_winrow > 0) - { - if (is_drag) - { - if (in_tab_line) - { - c1 = TabPageIdxs[mouse_col]; - tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab) - ? c1 - 1 : c1); - } - return FALSE; - } - - /* click in a tab selects that tab page */ - if (is_click - # ifdef FEAT_CMDWIN - && cmdwin_type == 0 - # endif - && mouse_col < Columns) - { - in_tab_line = TRUE; - c1 = TabPageIdxs[mouse_col]; - if (c1 >= 0) - { - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) - { - /* double click opens new page */ - end_visual_mode(); - tabpage_new(); - tabpage_move(c1 == 0 ? 9999 : c1 - 1); - } - else - { - /* Go to specified tab page, or next one if not clicking - * on a label. */ - goto_tabpage(c1); - - /* It's like clicking on the status line of a window. */ - if (curwin != old_curwin) - end_visual_mode(); - } - } - else - { - tabpage_T *tp; - - /* Close the current or specified tab page. */ - if (c1 == -999) - tp = curtab; - else - tp = find_tabpage(-c1); - if (tp == curtab) - { - if (first_tabpage->tp_next != NULL) - tabpage_close(FALSE); - } - else if (tp != NULL) - tabpage_close_other(tp, FALSE); - } - } - return TRUE; - } - else if (is_drag && in_tab_line) - { - c1 = TabPageIdxs[mouse_col]; - tabpage_move(c1 <= 0 ? 9999 : c1 - 1); - return FALSE; - } - - /* - * When 'mousemodel' is "popup" or "popup_setpos", translate mouse events: - * right button up -> pop-up menu - * shift-left button -> right button - * alt-left button -> alt-right button - */ - if (mouse_model_popup()) - { - if (which_button == MOUSE_RIGHT - && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) - { - #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ - || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \ - || defined(FEAT_TERM_POPUP_MENU) - # ifdef FEAT_GUI - if (gui.in_use) - { - # if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) - if (!is_click) - /* Ignore right button release events, only shows the popup - * 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. */ - return FALSE; - # endif - } - # endif - # if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU) - else - # endif - # if defined(FEAT_TERM_POPUP_MENU) - if (!is_click) - /* Ignore right button release events, only shows the popup - * menu on the button down event. */ - return FALSE; - #endif - - jump_flags = 0; - if (STRCMP(p_mousem, "popup_setpos") == 0) - { - /* First set the cursor position before showing the popup - * menu. */ - if (VIsual_active) - { - pos_T m_pos; - - /* - * set MOUSE_MAY_STOP_VIS if we are outside the - * selection or the current window (might have false - * negative here) - */ - if (mouse_row < curwin->w_winrow - || mouse_row - > (curwin->w_winrow + curwin->w_height)) - jump_flags = MOUSE_MAY_STOP_VIS; - else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) - jump_flags = MOUSE_MAY_STOP_VIS; - else - { - if ((LT_POS(curwin->w_cursor, VIsual) - && (LT_POS(m_pos, curwin->w_cursor) - || LT_POS(VIsual, m_pos))) - || (LT_POS(VIsual, curwin->w_cursor) - && (LT_POS(m_pos, VIsual) - || LT_POS(curwin->w_cursor, m_pos)))) - { - jump_flags = MOUSE_MAY_STOP_VIS; - } - else if (VIsual_mode == Ctrl_V) - { - getvcols(curwin, &curwin->w_cursor, &VIsual, - &leftcol, &rightcol); - getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); - if (m_pos.col < leftcol || m_pos.col > rightcol) - jump_flags = MOUSE_MAY_STOP_VIS; - } - } - } - else - jump_flags = MOUSE_MAY_STOP_VIS; - } - if (jump_flags) - { - jump_flags = jump_to_mouse(jump_flags, NULL, which_button); - update_curbuf(VIsual_active ? INVERTED : VALID); - setcursor(); - out_flush(); /* Update before showing popup menu */ - } - # ifdef FEAT_MENU - show_popupmenu(); - got_click = FALSE; /* ignore release events */ - # endif - return (jump_flags & CURSOR_MOVED) != 0; - #else - return FALSE; - #endif - } - if (which_button == MOUSE_LEFT - && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))) - { - which_button = MOUSE_RIGHT; - mod_mask &= ~MOD_MASK_SHIFT; - } - } - - if ((State & (NORMAL | INSERT)) - && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) - { - if (which_button == MOUSE_LEFT) - { - if (is_click) - { - /* stop Visual mode for a left click in a window, but not when - * on a status line */ - if (VIsual_active) - jump_flags |= MOUSE_MAY_STOP_VIS; - } - else if (mouse_has(MOUSE_VISUAL)) - jump_flags |= MOUSE_MAY_VIS; - } - else if (which_button == MOUSE_RIGHT) - { - if (is_click && VIsual_active) - { - /* - * Remember the start and end of visual before moving the - * cursor. - */ - if (LT_POS(curwin->w_cursor, VIsual)) - { - start_visual = curwin->w_cursor; - end_visual = VIsual; - } - else - { - start_visual = VIsual; - end_visual = curwin->w_cursor; - } - } - jump_flags |= MOUSE_FOCUS; - if (mouse_has(MOUSE_VISUAL)) - jump_flags |= MOUSE_MAY_VIS; - } - } - - /* - * If an operator is pending, ignore all drags and releases until the - * next mouse click. - */ - if (!is_drag && oap != NULL && oap->op_type != OP_NOP) - { - got_click = FALSE; - oap->motion_type = MCHAR; - } - - /* When releasing the button let jump_to_mouse() know. */ - if (!is_click && !is_drag) - jump_flags |= MOUSE_RELEASED; - - /* - * JUMP! - */ - jump_flags = jump_to_mouse(jump_flags, - oap == NULL ? NULL : &(oap->inclusive), which_button); - - #ifdef FEAT_MENU - /* A click in the window toolbar has no side effects. */ - if (jump_flags & MOUSE_WINBAR) - return FALSE; - #endif - moved = (jump_flags & CURSOR_MOVED); - in_status_line = (jump_flags & IN_STATUS_LINE); - in_sep_line = (jump_flags & IN_SEP_LINE); - - #ifdef FEAT_NETBEANS_INTG - if (isNetbeansBuffer(curbuf) - && !(jump_flags & (IN_STATUS_LINE | IN_SEP_LINE))) - { - int key = KEY2TERMCAP1(c); - - if (key == (int)KE_LEFTRELEASE || key == (int)KE_MIDDLERELEASE - || key == (int)KE_RIGHTRELEASE) - netbeans_button_release(which_button); - } - #endif - - /* When jumping to another window, clear a pending operator. That's a bit - * friendlier than beeping and not jumping to that window. */ - if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP) - clearop(oap); - - #ifdef FEAT_FOLDING - if (mod_mask == 0 - && !is_drag - && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN)) - && which_button == MOUSE_LEFT) - { - /* open or close a fold at this line */ - if (jump_flags & MOUSE_FOLD_OPEN) - openFold(curwin->w_cursor.lnum, 1L); - else - closeFold(curwin->w_cursor.lnum, 1L); - /* don't move the cursor if still in the same window */ - if (curwin == old_curwin) - curwin->w_cursor = save_cursor; - } - #endif - - #if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN) - if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available) - { - clip_modeless(which_button, is_click, is_drag); - return FALSE; - } - #endif - - /* Set global flag that we are extending the Visual area with mouse - * dragging; temporarily minimize 'scrolloff'. */ - if (VIsual_active && is_drag && get_scrolloff_value()) - { - /* In the very first line, allow scrolling one line */ - if (mouse_row == 0) - mouse_dragging = 2; - else - mouse_dragging = 1; - } - - /* When dragging the mouse above the window, scroll down. */ - if (is_drag && mouse_row < 0 && !in_status_line) - { - scroll_redraw(FALSE, 1L); - mouse_row = 0; - } - - if (start_visual.lnum) /* right click in visual mode */ - { - /* When ALT is pressed make Visual mode blockwise. */ - if (mod_mask & MOD_MASK_ALT) - VIsual_mode = Ctrl_V; - - /* - * In Visual-block mode, divide the area in four, pick up the corner - * that is in the quarter that the cursor is in. - */ - if (VIsual_mode == Ctrl_V) - { - getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol); - if (curwin->w_curswant > (leftcol + rightcol) / 2) - end_visual.col = leftcol; - else - end_visual.col = rightcol; - if (curwin->w_cursor.lnum >= - (start_visual.lnum + end_visual.lnum) / 2) - end_visual.lnum = start_visual.lnum; - - /* move VIsual to the right column */ - start_visual = curwin->w_cursor; /* save the cursor pos */ - curwin->w_cursor = end_visual; - coladvance(end_visual.col); - VIsual = curwin->w_cursor; - curwin->w_cursor = start_visual; /* restore the cursor */ - } - else - { - /* - * If the click is before the start of visual, change the start. - * If the click is after the end of visual, change the end. If - * the click is inside the visual, change the closest side. - */ - if (LT_POS(curwin->w_cursor, start_visual)) - VIsual = end_visual; - else if (LT_POS(end_visual, curwin->w_cursor)) - VIsual = start_visual; - else - { - /* In the same line, compare column number */ - if (end_visual.lnum == start_visual.lnum) - { - if (curwin->w_cursor.col - start_visual.col > - end_visual.col - curwin->w_cursor.col) - VIsual = start_visual; - else - VIsual = end_visual; - } - - /* In different lines, compare line number */ - else - { - diff = (curwin->w_cursor.lnum - start_visual.lnum) - - (end_visual.lnum - curwin->w_cursor.lnum); - - if (diff > 0) /* closest to end */ - VIsual = start_visual; - else if (diff < 0) /* closest to start */ - VIsual = end_visual; - else /* in the middle line */ - { - if (curwin->w_cursor.col < - (start_visual.col + end_visual.col) / 2) - VIsual = end_visual; - else - VIsual = start_visual; - } - } - } - } - } - /* - * If Visual mode started in insert mode, execute "CTRL-O" - */ - else if ((State & INSERT) && VIsual_active) - stuffcharReadbuff(Ctrl_O); - - /* - * Middle mouse click: Put text before cursor. - */ - if (which_button == MOUSE_MIDDLE) - { - #ifdef FEAT_CLIPBOARD - if (clip_star.available && regname == 0) - regname = '*'; - #endif - if (yank_register_mline(regname)) - { - if (mouse_past_bottom) - dir = FORWARD; - } - else if (mouse_past_eol) - dir = FORWARD; - - if (fixindent) - { - c1 = (dir == BACKWARD) ? '[' : ']'; - c2 = 'p'; - } - else - { - c1 = (dir == FORWARD) ? 'p' : 'P'; - c2 = NUL; - } - prep_redo(regname, count, NUL, c1, NUL, c2, NUL); - - /* - * Remember where the paste started, so in edit() Insstart can be set - * to this position - */ - if (restart_edit != 0) - where_paste_started = curwin->w_cursor; - do_put(regname, dir, count, fixindent | PUT_CURSEND); - } - - #if defined(FEAT_QUICKFIX) - /* - * Ctrl-Mouse click or double click in a quickfix window jumps to the - * error under the mouse pointer. - */ - else if (((mod_mask & MOD_MASK_CTRL) - || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) - && bt_quickfix(curbuf)) - { - if (curwin->w_llist_ref == NULL) /* quickfix window */ - do_cmdline_cmd((char_u *)".cc"); - else /* location list window */ - do_cmdline_cmd((char_u *)".ll"); - got_click = FALSE; /* ignore drag&release now */ - } - #endif - - /* - * Ctrl-Mouse click (or double click in a help window) jumps to the tag - * under the mouse pointer. - */ - else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help - && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) - { - if (State & INSERT) - stuffcharReadbuff(Ctrl_O); - stuffcharReadbuff(Ctrl_RSB); - got_click = FALSE; /* ignore drag&release now */ - } - - /* - * Shift-Mouse click searches for the next occurrence of the word under - * the mouse pointer - */ - else if ((mod_mask & MOD_MASK_SHIFT)) - { - if ((State & INSERT) || (VIsual_active && VIsual_select)) - stuffcharReadbuff(Ctrl_O); - if (which_button == MOUSE_LEFT) - stuffcharReadbuff('*'); - else /* MOUSE_RIGHT */ - stuffcharReadbuff('#'); - } - - /* Handle double clicks, unless on status line */ - else if (in_status_line) - { - #ifdef FEAT_MOUSESHAPE - if ((is_drag || is_click) && !drag_status_line) - { - drag_status_line = TRUE; - update_mouseshape(-1); - } - #endif - } - else if (in_sep_line) - { - #ifdef FEAT_MOUSESHAPE - if ((is_drag || is_click) && !drag_sep_line) - { - drag_sep_line = TRUE; - update_mouseshape(-1); - } - #endif - } - else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)) - && mouse_has(MOUSE_VISUAL)) - { - if (is_click || !VIsual_active) - { - if (VIsual_active) - orig_cursor = VIsual; - else - { - check_visual_highlight(); - VIsual = curwin->w_cursor; - orig_cursor = VIsual; - VIsual_active = TRUE; - VIsual_reselect = TRUE; - /* start Select mode if 'selectmode' contains "mouse" */ - may_start_select('o'); - setmouse(); - } - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) - { - /* Double click with ALT pressed makes it blockwise. */ - if (mod_mask & MOD_MASK_ALT) - VIsual_mode = Ctrl_V; - else - VIsual_mode = 'v'; - } - else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK) - VIsual_mode = 'V'; - else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK) - VIsual_mode = Ctrl_V; - #ifdef FEAT_CLIPBOARD - /* Make sure the clipboard gets updated. Needed because start and - * end may still be the same, and the selection needs to be owned */ - clip_star.vmode = NUL; - #endif - } - /* - * A double click selects a word or a block. - */ - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) - { - pos_T *pos = NULL; - int gc; - - if (is_click) - { - /* If the character under the cursor (skipping white space) is - * not a word character, try finding a match and select a (), - * {}, [], #if/#endif, etc. block. */ - end_visual = curwin->w_cursor; - while (gc = gchar_pos(&end_visual), VIM_ISWHITE(gc)) - inc(&end_visual); - if (oap != NULL) - oap->motion_type = MCHAR; - if (oap != NULL - && VIsual_mode == 'v' - && !vim_iswordc(gchar_pos(&end_visual)) - && EQUAL_POS(curwin->w_cursor, VIsual) - && (pos = findmatch(oap, NUL)) != NULL) - { - curwin->w_cursor = *pos; - if (oap->motion_type == MLINE) - VIsual_mode = 'V'; - else if (*p_sel == 'e') - { - if (LT_POS(curwin->w_cursor, VIsual)) - ++VIsual.col; - else - ++curwin->w_cursor.col; - } - } - } - - if (pos == NULL && (is_click || is_drag)) - { - /* When not found a match or when dragging: extend to include - * a word. */ - if (LT_POS(curwin->w_cursor, orig_cursor)) - { - find_start_of_word(&curwin->w_cursor); - find_end_of_word(&VIsual); - } - else - { - find_start_of_word(&VIsual); - if (*p_sel == 'e' && *ml_get_cursor() != NUL) - curwin->w_cursor.col += - (*mb_ptr2len)(ml_get_cursor()); - find_end_of_word(&curwin->w_cursor); - } - } - curwin->w_set_curswant = TRUE; - } - if (is_click) - redraw_curbuf_later(INVERTED); /* update the inversion */ - } - else if (VIsual_active && !old_active) - { - if (mod_mask & MOD_MASK_ALT) - VIsual_mode = Ctrl_V; - else - VIsual_mode = 'v'; - } - - /* If Visual mode changed show it later. */ - if ((!VIsual_active && old_active && mode_displayed) - || (VIsual_active && p_smd && msg_silent == 0 - && (!old_active || VIsual_mode != old_mode))) - redraw_cmdline = TRUE; - - return moved; - } - - /* - * Move "pos" back to the start of the word it's in. - */ - static void - find_start_of_word(pos_T *pos) - { - char_u *line; - int cclass; - int col; - - line = ml_get(pos->lnum); - cclass = get_mouse_class(line + pos->col); - - while (pos->col > 0) - { - col = pos->col - 1; - col -= (*mb_head_off)(line, line + col); - if (get_mouse_class(line + col) != cclass) - break; - pos->col = col; - } - } - - /* - * Move "pos" forward to the end of the word it's in. - * When 'selection' is "exclusive", the position is just after the word. - */ - static void - find_end_of_word(pos_T *pos) - { - char_u *line; - int cclass; - int col; - - line = ml_get(pos->lnum); - if (*p_sel == 'e' && pos->col > 0) - { - --pos->col; - pos->col -= (*mb_head_off)(line, line + pos->col); - } - cclass = get_mouse_class(line + pos->col); - while (line[pos->col] != NUL) - { - col = pos->col + (*mb_ptr2len)(line + pos->col); - if (get_mouse_class(line + col) != cclass) - { - if (*p_sel == 'e') - pos->col = col; - break; - } - pos->col = col; - } - } - - /* - * Get class of a character for selection: same class means same word. - * 0: blank - * 1: punctuation groups - * 2: normal word character - * >2: multi-byte word character. - */ - static int - get_mouse_class(char_u *p) - { - int c; - - if (has_mbyte && MB_BYTE2LEN(p[0]) > 1) - return mb_get_class(p); - - c = *p; - if (c == ' ' || c == '\t') - return 0; - - if (vim_iswordc(c)) - return 2; - - /* - * There are a few special cases where we want certain combinations of - * characters to be considered as a single word. These are things like - * "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each - * character is in its own class. - */ - if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL) - return 1; - return c; - } - #endif /* FEAT_MOUSE */ - /* * Check if highlighting for visual mode is possible, give a warning message * if not. --- 2188,2193 ---- *************** *** 3531,3537 **** * Prepare for redo of any command. * Note that only the last argument can be a multi-byte char. */ ! static void prep_redo( int regname, long num, --- 2514,2520 ---- * Prepare for redo of any command. * Note that only the last argument can be a multi-byte char. */ ! void prep_redo( int regname, long num, *************** *** 3590,3596 **** return TRUE; } ! static void clearop(oparg_T *oap) { oap->op_type = OP_NOP; --- 2573,2579 ---- return TRUE; } ! void clearop(oparg_T *oap) { oap->op_type = OP_NOP; *************** *** 3599,3605 **** oap->use_reg_one = FALSE; } ! static void clearopbeep(oparg_T *oap) { clearop(oap); --- 2582,2588 ---- oap->use_reg_one = FALSE; } ! void clearopbeep(oparg_T *oap) { clearop(oap); *************** *** 4513,4625 **** return retval; } - #ifdef FEAT_MOUSE - /* - * Mouse scroll wheel: Default action is to scroll three lines, or one page - * when Shift or Ctrl is used. - * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or - * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2) - */ - static void - nv_mousescroll(cmdarg_T *cap) - { - win_T *old_curwin = curwin, *wp; - - if (mouse_row >= 0 && mouse_col >= 0) - { - int row, col; - - row = mouse_row; - col = mouse_col; - - /* find the window at the pointer coordinates */ - wp = mouse_find_win(&row, &col, FIND_POPUP); - if (wp == NULL) - return; - #ifdef FEAT_TEXT_PROP - if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar) - return; - #endif - curwin = wp; - curbuf = curwin->w_buffer; - } - - if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) - { - # ifdef FEAT_TERMINAL - if (term_use_loop()) - /* This window is a terminal window, send the mouse event there. - * Set "typed" to FALSE to avoid an endless loop. */ - send_keys_to_term(curbuf->b_term, cap->cmdchar, FALSE); - else - # endif - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) - { - (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L); - } - else - { - // Don't scroll more than half the window height. - if (curwin->w_height < 6) - { - cap->count1 = curwin->w_height / 2; - if (cap->count1 == 0) - cap->count1 = 1; - } - else - cap->count1 = 3; - cap->count0 = cap->count1; - nv_scroll_line(cap); - } - #ifdef FEAT_TEXT_PROP - if (WIN_IS_POPUP(curwin)) - popup_set_firstline(curwin); - #endif - } - # ifdef FEAT_GUI - else - { - /* Horizontal scroll - only allowed when 'wrap' is disabled */ - if (!curwin->w_p_wrap) - { - int val, step = 6; - - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) - step = curwin->w_width; - val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step); - if (val < 0) - val = 0; - - gui_do_horiz_scroll(val, TRUE); - } - } - # endif - # ifdef FEAT_SYN_HL - if (curwin != old_curwin && curwin->w_p_cul) - redraw_for_cursorline(curwin); - # endif - - curwin->w_redr_status = TRUE; - - curwin = old_curwin; - curbuf = curwin->w_buffer; - } - - /* - * Mouse clicks and drags. - */ - static void - nv_mouse(cmdarg_T *cap) - { - (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0); - } - #endif - /* * Handle CTRL-E and CTRL-Y commands: scroll a line up or down. * cap->arg must be TRUE for CTRL-E. */ ! static void nv_scroll_line(cmdarg_T *cap) { if (!checkclearop(cap->oap)) --- 3496,3506 ---- return retval; } /* * Handle CTRL-E and CTRL-Y commands: scroll a line up or down. * cap->arg must be TRUE for CTRL-E. */ ! void nv_scroll_line(cmdarg_T *cap) { if (!checkclearop(cap->oap)) *************** *** 7572,7580 **** if (!cap->arg) /* start Select mode when 'selectmode' contains "cmd" */ may_start_select('c'); - #ifdef FEAT_MOUSE setmouse(); - #endif if (p_smd && msg_silent == 0) redraw_cmdline = TRUE; /* show visual mode later */ /* --- 6453,6459 ---- *************** *** 7687,7695 **** foldAdjustVisual(); #endif - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef FEAT_CONCEAL /* Check for redraw after changing the state. */ conceal_check_cursor_line(); --- 6566,6572 ---- *************** *** 7854,7862 **** VIsual_select = TRUE; else may_start_select('c'); - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef FEAT_CLIPBOARD /* Make sure the clipboard gets updated. Needed because start and * end are still the same, and the selection needs to be owned */ --- 6731,6737 ---- *** ../vim-8.1.2061/src/proto.h 2019-09-19 23:05:56.471034946 +0200 --- src/proto.h 2019-09-21 20:13:48.601908392 +0200 *************** *** 175,180 **** --- 175,181 ---- /* Use our own qsort(), don't define the prototype when not used. */ void qsort(void *base, size_t elm_count, size_t elm_size, int (*cmp)(const void *, const void *)); #endif + # include "mouse.pro" # include "move.pro" # include "mbyte.pro" # include "normal.pro" *** ../vim-8.1.2061/src/proto/edit.pro 2019-03-30 13:53:26.174425093 +0100 --- src/proto/edit.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 7,12 **** --- 7,13 ---- int prompt_curpos_editable(void); void edit_unputchar(void); void display_dollar(colnr_T col); + void undisplay_dollar(void); void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes); void truncate_spaces(char_u *line); void backspace_until_column(int col); *************** *** 36,41 **** int ins_eol(int c); int ins_copychar(linenr_T lnum); colnr_T get_nolist_virtcol(void); ! int can_cindent_get(void); int ins_apply_autocmds(event_T event); /* vim: set ft=c : */ --- 37,43 ---- int ins_eol(int c); int ins_copychar(linenr_T lnum); colnr_T get_nolist_virtcol(void); ! int get_can_cindent(void); ! void set_can_cindent(int val); int ins_apply_autocmds(event_T event); /* vim: set ft=c : */ *** ../vim-8.1.2061/src/proto/misc1.pro 2019-09-16 22:55:57.728006887 +0200 --- src/proto/misc1.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 23,29 **** char_u *skip_to_option_part(char_u *p); void check_status(buf_T *buf); int ask_yesno(char_u *str, int direct); - int is_mouse_key(int c); void f_mode(typval_T *argvars, typval_T *rettv); void f_state(typval_T *argvars, typval_T *rettv); int get_keystroke(void); --- 23,28 ---- *** ../vim-8.1.2061/src/proto/misc2.pro 2019-09-15 21:00:51.362604284 +0200 --- src/proto/misc2.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 74,81 **** int find_special_key_in_table(int c); int get_special_key_code(char_u *name); char_u *get_key_name(int i); - int get_mouse_button(int code, int *is_click, int *is_drag); - int get_pseudo_mouse_code(int button, int is_click, int is_drag); int get_fileformat(buf_T *buf); int get_fileformat_force(buf_T *buf, exarg_T *eap); void set_fileformat(int t, int opt_flags); --- 74,79 ---- *** ../vim-8.1.2061/src/proto/mouse.pro 2019-09-21 20:44:58.908689526 +0200 --- src/proto/mouse.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 0 **** --- 1,19 ---- + /* mouse.c */ + int do_mouse(oparg_T *oap, int c, int dir, long count, int fixindent); + void ins_mouse(int c); + void ins_mousescroll(int dir); + int is_mouse_key(int c); + int get_mouse_button(int code, int *is_click, int *is_drag); + int get_pseudo_mouse_code(int button, int is_click, int is_drag); + void set_mouse_termcode(int n, char_u *s); + void del_mouse_termcode(int n); + void setmouse(void); + int mouse_has(int c); + int mouse_model_popup(void); + int jump_to_mouse(int flags, int *inclusive, int which_button); + void nv_mousescroll(cmdarg_T *cap); + void nv_mouse(cmdarg_T *cap); + int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int *plines_cache); + win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup); + int vcol2col(win_T *wp, linenr_T lnum, int vcol); + /* vim: set ft=c : */ *** ../vim-8.1.2061/src/proto/normal.pro 2019-09-05 21:28:58.495157310 +0200 --- src/proto/normal.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 2,14 **** void init_normal_cmds(void); void normal_cmd(oparg_T *oap, int toplevel); void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank); - int do_mouse(oparg_T *oap, int c, int dir, long count, int fixindent); void check_visual_highlight(void); void end_visual_mode(void); void reset_VIsual_and_resel(void); void reset_VIsual(void); int find_ident_under_cursor(char_u **text, int find_type); int find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char_u **text, int *textcol, int find_type); void clear_showcmd(void); int add_to_showcmd(int c); void add_to_showcmd_c(int c); --- 2,16 ---- void init_normal_cmds(void); void normal_cmd(oparg_T *oap, int toplevel); void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank); void check_visual_highlight(void); void end_visual_mode(void); void reset_VIsual_and_resel(void); void reset_VIsual(void); int find_ident_under_cursor(char_u **text, int find_type); int find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char_u **text, int *textcol, int find_type); + void prep_redo(int regname, long, int, int, int, int, int); + void clearop(oparg_T *oap); + void clearopbeep(oparg_T *oap); void clear_showcmd(void); int add_to_showcmd(int c); void add_to_showcmd_c(int c); *************** *** 17,22 **** --- 19,25 ---- void do_check_scrollbind(int check); void check_scrollbind(linenr_T topline_diff, long leftcol_diff); int find_decl(char_u *ptr, int len, int locally, int thisblock, int flags_arg); + void nv_scroll_line(cmdarg_T *cap); void scroll_redraw(int up, long count); void handle_tabmenu(void); void do_nv_ident(int c1, int c2); *** ../vim-8.1.2061/src/proto/term.pro 2019-08-20 20:13:40.334821916 +0200 --- src/proto/term.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 2,9 **** guicolor_T termgui_get_color(char_u *name); guicolor_T termgui_mch_get_rgb(guicolor_T color); int set_termname(char_u *term); - void set_mouse_termcode(int n, char_u *s); - void del_mouse_termcode(int n); void getlinecol(long *cp, long *rp); int add_termcap_entry(char_u *name, int force); int term_is_8bit(char_u *name); --- 2,7 ---- *************** *** 47,55 **** void may_req_ambiguous_char_width(void); void may_req_bg_color(void); int swapping_screen(void); - void setmouse(void); - int mouse_has(int c); - int mouse_model_popup(void); void scroll_start(void); void cursor_on_force(void); void cursor_on(void); --- 45,50 ---- *************** *** 64,69 **** --- 59,65 ---- void add_termcode(char_u *name, char_u *string, int flags); char_u *find_termcode(char_u *name); char_u *get_termcode(int i); + void del_termcode(char_u *name); void set_mouse_topline(win_T *wp); int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen); void term_get_fg_color(char_u *r, char_u *g, char_u *b); *** ../vim-8.1.2061/src/proto/ui.pro 2019-08-20 20:13:40.334821916 +0200 --- src/proto/ui.pro 2019-09-21 20:13:48.601908392 +0200 *************** *** 60,70 **** int clip_x11_own_selection(Widget myShell, Clipboard_T *cbd); void clip_x11_set_selection(Clipboard_T *cbd); void yank_cut_buffer0(Display *dpy, Clipboard_T *cbd); - int jump_to_mouse(int flags, int *inclusive, int which_button); - int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int *plines_cache); - win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup); - int get_fpos_of_mouse(pos_T *mpos); - int vcol2col(win_T *wp, linenr_T lnum, int vcol); void ui_focus_change(int in_focus); void im_save_status(long *psave); /* vim: set ft=c : */ --- 60,65 ---- *** ../vim-8.1.2061/src/search.c 2019-09-06 20:40:17.759227838 +0200 --- src/search.c 2019-09-21 20:38:56.390647868 +0200 *************** *** 4803,4811 **** #endif may_start_select('c'); - #ifdef FEAT_MOUSE setmouse(); - #endif #ifdef FEAT_CLIPBOARD /* Make sure the clipboard gets updated. Needed because start and * end are still the same, and the selection needs to be owned */ --- 4803,4809 ---- *** ../vim-8.1.2061/src/term.c 2019-08-21 14:36:29.395376065 +0200 --- src/term.c 2019-09-21 20:39:16.802545167 +0200 *************** *** 87,93 **** || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE))) static int get_bytes_from_buf(char_u *, char_u *, int); #endif - static void del_termcode(char_u *name); static void del_termcode_idx(int idx); static int find_term_bykeys(char_u *src); static int term_is_builtin(char_u *name); --- 87,92 ---- *************** *** 2048,2056 **** if (starting != NO_SCREEN) { starttermcap(); /* may change terminal mode */ - #ifdef FEAT_MOUSE setmouse(); /* may start using the mouse */ - #endif #ifdef FEAT_TITLE maketitle(); /* may display window title */ #endif --- 2047,2053 ---- *************** *** 2101,2226 **** return OK; } - #if defined(FEAT_MOUSE) || defined(PROTO) - - # ifdef FEAT_MOUSE_TTY - # define HMT_NORMAL 1 - # define HMT_NETTERM 2 - # define HMT_DEC 4 - # define HMT_JSBTERM 8 - # define HMT_PTERM 16 - # define HMT_URXVT 32 - # define HMT_GPM 64 - # define HMT_SGR 128 - # define HMT_SGR_REL 256 - static int has_mouse_termcode = 0; - # endif - - # if (!defined(UNIX) || defined(FEAT_MOUSE_TTY)) || defined(PROTO) - void - set_mouse_termcode( - int n, /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */ - char_u *s) - { - char_u name[2]; - - name[0] = n; - name[1] = KE_FILLER; - add_termcode(name, s, FALSE); - # ifdef FEAT_MOUSE_TTY - # ifdef FEAT_MOUSE_JSB - if (n == KS_JSBTERM_MOUSE) - has_mouse_termcode |= HMT_JSBTERM; - else - # endif - # ifdef FEAT_MOUSE_NET - if (n == KS_NETTERM_MOUSE) - has_mouse_termcode |= HMT_NETTERM; - else - # endif - # ifdef FEAT_MOUSE_DEC - if (n == KS_DEC_MOUSE) - has_mouse_termcode |= HMT_DEC; - else - # endif - # ifdef FEAT_MOUSE_PTERM - if (n == KS_PTERM_MOUSE) - has_mouse_termcode |= HMT_PTERM; - else - # endif - # ifdef FEAT_MOUSE_URXVT - if (n == KS_URXVT_MOUSE) - has_mouse_termcode |= HMT_URXVT; - else - # endif - # ifdef FEAT_MOUSE_GPM - if (n == KS_GPM_MOUSE) - has_mouse_termcode |= HMT_GPM; - else - # endif - if (n == KS_SGR_MOUSE) - has_mouse_termcode |= HMT_SGR; - else if (n == KS_SGR_MOUSE_RELEASE) - has_mouse_termcode |= HMT_SGR_REL; - else - has_mouse_termcode |= HMT_NORMAL; - # endif - } - # endif - - # if ((defined(UNIX) || defined(VMS)) \ - && defined(FEAT_MOUSE_TTY)) || defined(PROTO) - void - del_mouse_termcode( - int n) /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */ - { - char_u name[2]; - - name[0] = n; - name[1] = KE_FILLER; - del_termcode(name); - # ifdef FEAT_MOUSE_TTY - # ifdef FEAT_MOUSE_JSB - if (n == KS_JSBTERM_MOUSE) - has_mouse_termcode &= ~HMT_JSBTERM; - else - # endif - # ifdef FEAT_MOUSE_NET - if (n == KS_NETTERM_MOUSE) - has_mouse_termcode &= ~HMT_NETTERM; - else - # endif - # ifdef FEAT_MOUSE_DEC - if (n == KS_DEC_MOUSE) - has_mouse_termcode &= ~HMT_DEC; - else - # endif - # ifdef FEAT_MOUSE_PTERM - if (n == KS_PTERM_MOUSE) - has_mouse_termcode &= ~HMT_PTERM; - else - # endif - # ifdef FEAT_MOUSE_URXVT - if (n == KS_URXVT_MOUSE) - has_mouse_termcode &= ~HMT_URXVT; - else - # endif - # ifdef FEAT_MOUSE_GPM - if (n == KS_GPM_MOUSE) - has_mouse_termcode &= ~HMT_GPM; - else - # endif - if (n == KS_SGR_MOUSE) - has_mouse_termcode &= ~HMT_SGR; - else if (n == KS_SGR_MOUSE_RELEASE) - has_mouse_termcode &= ~HMT_SGR_REL; - else - has_mouse_termcode &= ~HMT_NORMAL; - # endif - } - # endif - #endif - #ifdef HAVE_TGETENT /* * Call tgetent() --- 2098,2103 ---- *************** *** 3574,3583 **** out_flush(); mch_settmode(tmode); // machine specific function cur_tmode = tmode; - #ifdef FEAT_MOUSE if (tmode == TMODE_RAW) setmouse(); // may switch mouse on - #endif out_flush(); } #ifdef FEAT_TERMRESPONSE --- 3451,3458 ---- *************** *** 3811,3904 **** return (full_screen && *T_TI != NUL); } - #if defined(FEAT_MOUSE) || defined(PROTO) - /* - * setmouse() - switch mouse on/off depending on current mode and 'mouse' - */ - void - setmouse(void) - { - # ifdef FEAT_MOUSE_TTY - int checkfor; - # endif - - # ifdef FEAT_MOUSESHAPE - update_mouseshape(-1); - # endif - - # ifdef FEAT_MOUSE_TTY /* Should be outside proc, but may break MOUSESHAPE */ - # ifdef FEAT_GUI - /* In the GUI the mouse is always enabled. */ - if (gui.in_use) - return; - # endif - /* be quick when mouse is off */ - if (*p_mouse == NUL || has_mouse_termcode == 0) - return; - - /* don't switch mouse on when not in raw mode (Ex mode) */ - if (cur_tmode != TMODE_RAW) - { - mch_setmouse(FALSE); - return; - } - - if (VIsual_active) - checkfor = MOUSE_VISUAL; - else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) - checkfor = MOUSE_RETURN; - else if (State & INSERT) - checkfor = MOUSE_INSERT; - else if (State & CMDLINE) - checkfor = MOUSE_COMMAND; - else if (State == CONFIRM || State == EXTERNCMD) - checkfor = ' '; /* don't use mouse for ":confirm" or ":!cmd" */ - else - checkfor = MOUSE_NORMAL; /* assume normal mode */ - - if (mouse_has(checkfor)) - mch_setmouse(TRUE); - else - mch_setmouse(FALSE); - # endif - } - - /* - * Return TRUE if - * - "c" is in 'mouse', or - * - 'a' is in 'mouse' and "c" is in MOUSE_A, or - * - the current buffer is a help file and 'h' is in 'mouse' and we are in a - * normal editing mode (not at hit-return message). - */ - int - mouse_has(int c) - { - char_u *p; - - for (p = p_mouse; *p; ++p) - switch (*p) - { - case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) - return TRUE; - break; - case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) - return TRUE; - break; - default: if (c == *p) return TRUE; break; - } - return FALSE; - } - - /* - * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos". - */ - int - mouse_model_popup(void) - { - return (p_mousem[0] == 'p'); - } - #endif - /* * By outputting the 'cursor very visible' termcap code, for some windowed * terminals this makes the screen scrolled to the correct position. --- 3686,3691 ---- *************** *** 4307,4313 **** return &termcodes[i].name[0]; } ! static void del_termcode(char_u *name) { int i; --- 4094,4100 ---- return &termcodes[i].name[0]; } ! void del_termcode(char_u *name) { int i; *************** *** 5298,5320 **** * are decimal instead of bytes. * * \033[%d;%d;%dM ! * ^-- row ! * ^----- column ! * ^-------- code * * SGR 1006 mouse reporting mode: * Almost identical to xterm mouse mode, except the values * are decimal instead of bytes. * * \033[<%d;%d;%dM ! * ^-- row ! * ^----- column ! * ^-------- code * * \033[<%d;%d;%dm : mouse release event ! * ^-- row ! * ^----- column ! * ^-------- code */ p = modifiers_start; if (p == NULL) --- 5085,5107 ---- * are decimal instead of bytes. * * \033[%d;%d;%dM ! * ^-- row ! * ^----- column ! * ^-------- code * * SGR 1006 mouse reporting mode: * Almost identical to xterm mouse mode, except the values * are decimal instead of bytes. * * \033[<%d;%d;%dM ! * ^-- row ! * ^----- column ! * ^-------- code * * \033[<%d;%d;%dm : mouse release event ! * ^-- row ! * ^----- column ! * ^-------- code */ p = modifiers_start; if (p == NULL) *** ../vim-8.1.2061/src/ui.c 2019-09-07 23:25:05.708270305 +0200 --- src/ui.c 2019-09-21 20:13:48.601908392 +0200 *************** *** 2917,3713 **** } #endif - #if defined(FEAT_MOUSE) || defined(PROTO) - - /* - * Move the cursor to the specified row and column on the screen. - * Change current window if necessary. Returns an integer with the - * CURSOR_MOVED bit set if the cursor has moved or unset otherwise. - * - * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column. - * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column. - * - * If flags has MOUSE_FOCUS, then the current window will not be changed, and - * if the mouse is outside the window then the text will scroll, or if the - * mouse was previously on a status line, then the status line may be dragged. - * - * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the - * cursor is moved unless the cursor was on a status line. - * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or - * IN_SEP_LINE depending on where the cursor was clicked. - * - * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless - * the mouse is on the status line of the same window. - * - * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since - * the last call. - * - * If flags has MOUSE_SETPOS, nothing is done, only the current position is - * remembered. - */ - int - jump_to_mouse( - int flags, - int *inclusive, /* used for inclusive operator, can be NULL */ - int which_button) /* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */ - { - static int on_status_line = 0; /* #lines below bottom of window */ - static int on_sep_line = 0; /* on separator right of window */ - #ifdef FEAT_MENU - static int in_winbar = FALSE; - #endif - #ifdef FEAT_TEXT_PROP - static int in_popup_win = FALSE; - static win_T *click_in_popup_win = NULL; - #endif - static int prev_row = -1; - static int prev_col = -1; - static win_T *dragwin = NULL; /* window being dragged */ - static int did_drag = FALSE; /* drag was noticed */ - - win_T *wp, *old_curwin; - pos_T old_cursor; - int count; - int first; - int row = mouse_row; - int col = mouse_col; - #ifdef FEAT_FOLDING - int mouse_char; - #endif - - mouse_past_bottom = FALSE; - mouse_past_eol = FALSE; - - if (flags & MOUSE_RELEASED) - { - /* On button release we may change window focus if positioned on a - * status line and no dragging happened. */ - if (dragwin != NULL && !did_drag) - flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE); - dragwin = NULL; - did_drag = FALSE; - #ifdef FEAT_TEXT_PROP - if (click_in_popup_win != NULL && popup_dragwin == NULL) - popup_close_for_mouse_click(click_in_popup_win); - - popup_dragwin = NULL; - click_in_popup_win = NULL; - #endif - } - - if ((flags & MOUSE_DID_MOVE) - && prev_row == mouse_row - && prev_col == mouse_col) - { - retnomove: - /* before moving the cursor for a left click which is NOT in a status - * line, stop Visual mode */ - if (on_status_line) - return IN_STATUS_LINE; - if (on_sep_line) - return IN_SEP_LINE; - #ifdef FEAT_MENU - if (in_winbar) - { - /* A quick second click may arrive as a double-click, but we use it - * as a second click in the WinBar. */ - if ((mod_mask & MOD_MASK_MULTI_CLICK) && !(flags & MOUSE_RELEASED)) - { - wp = mouse_find_win(&row, &col, FAIL_POPUP); - if (wp == NULL) - return IN_UNKNOWN; - winbar_click(wp, col); - } - return IN_OTHER_WIN | MOUSE_WINBAR; - } - #endif - if (flags & MOUSE_MAY_STOP_VIS) - { - end_visual_mode(); - redraw_curbuf_later(INVERTED); /* delete the inversion */ - } - #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) - // Continue a modeless selection in another window. - if (cmdwin_type != 0 && row < curwin->w_winrow) - return IN_OTHER_WIN; - #endif - #ifdef FEAT_TEXT_PROP - // Continue a modeless selection in a popup window or dragging it. - if (in_popup_win) - { - click_in_popup_win = NULL; // don't close it on release - if (popup_dragwin != NULL) - { - // dragging a popup window - popup_drag(popup_dragwin); - return IN_UNKNOWN; - } - return IN_OTHER_WIN; - } - #endif - return IN_BUFFER; - } - - prev_row = mouse_row; - prev_col = mouse_col; - - if (flags & MOUSE_SETPOS) - goto retnomove; /* ugly goto... */ - - #ifdef FEAT_FOLDING - /* Remember the character under the mouse, it might be a '-' or '+' in the - * fold column. */ - if (row >= 0 && row < Rows && col >= 0 && col <= Columns - && ScreenLines != NULL) - mouse_char = ScreenLines[LineOffset[row] + col]; - else - mouse_char = ' '; - #endif - - old_curwin = curwin; - old_cursor = curwin->w_cursor; - - if (!(flags & MOUSE_FOCUS)) - { - if (row < 0 || col < 0) // check if it makes sense - return IN_UNKNOWN; - - // find the window where the row is in and adjust "row" and "col" to be - // relative to top-left of the window - wp = mouse_find_win(&row, &col, FIND_POPUP); - if (wp == NULL) - return IN_UNKNOWN; - dragwin = NULL; - - #ifdef FEAT_TEXT_PROP - // Click in a popup window may start dragging or modeless selection, - // but not much else. - if (WIN_IS_POPUP(wp)) - { - on_sep_line = 0; - in_popup_win = TRUE; - if (which_button == MOUSE_LEFT && popup_close_if_on_X(wp, row, col)) - { - return IN_UNKNOWN; - } - else if ((wp->w_popup_flags & (POPF_DRAG | POPF_RESIZE)) - && popup_on_border(wp, row, col)) - { - popup_dragwin = wp; - popup_start_drag(wp, row, col); - return IN_UNKNOWN; - } - // Only close on release, otherwise it's not possible to drag or do - // modeless selection. - else if (wp->w_popup_close == POPCLOSE_CLICK - && which_button == MOUSE_LEFT) - { - click_in_popup_win = wp; - } - else if (which_button == MOUSE_LEFT) - // If the click is in the scrollbar, may scroll up/down. - popup_handle_scrollbar_click(wp, row, col); - # ifdef FEAT_CLIPBOARD - return IN_OTHER_WIN; - # else - return IN_UNKNOWN; - # endif - } - in_popup_win = FALSE; - popup_dragwin = NULL; - #endif - #ifdef FEAT_MENU - if (row == -1) - { - /* A click in the window toolbar does not enter another window or - * change Visual highlighting. */ - winbar_click(wp, col); - in_winbar = TRUE; - return IN_OTHER_WIN | MOUSE_WINBAR; - } - in_winbar = FALSE; - #endif - - /* - * winpos and height may change in win_enter()! - */ - if (row >= wp->w_height) /* In (or below) status line */ - { - on_status_line = row - wp->w_height + 1; - dragwin = wp; - } - else - on_status_line = 0; - if (col >= wp->w_width) /* In separator line */ - { - on_sep_line = col - wp->w_width + 1; - dragwin = wp; - } - else - on_sep_line = 0; - - /* The rightmost character of the status line might be a vertical - * separator character if there is no connecting window to the right. */ - if (on_status_line && on_sep_line) - { - if (stl_connected(wp)) - on_sep_line = 0; - else - on_status_line = 0; - } - - /* Before jumping to another buffer, or moving the cursor for a left - * click, stop Visual mode. */ - if (VIsual_active - && (wp->w_buffer != curwin->w_buffer - || (!on_status_line && !on_sep_line - #ifdef FEAT_FOLDING - && ( - # ifdef FEAT_RIGHTLEFT - wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc : - # endif - col >= wp->w_p_fdc - # ifdef FEAT_CMDWIN - + (cmdwin_type == 0 && wp == curwin ? 0 : 1) - # endif - ) - #endif - && (flags & MOUSE_MAY_STOP_VIS)))) - { - end_visual_mode(); - redraw_curbuf_later(INVERTED); /* delete the inversion */ - } - #ifdef FEAT_CMDWIN - if (cmdwin_type != 0 && wp != curwin) - { - /* A click outside the command-line window: Use modeless - * selection if possible. Allow dragging the status lines. */ - on_sep_line = 0; - # ifdef FEAT_CLIPBOARD - if (on_status_line) - return IN_STATUS_LINE; - return IN_OTHER_WIN; - # else - row = 0; - col += wp->w_wincol; - wp = curwin; - # endif - } - #endif - /* Only change window focus when not clicking on or dragging the - * status line. Do change focus when releasing the mouse button - * (MOUSE_FOCUS was set above if we dragged first). */ - if (dragwin == NULL || (flags & MOUSE_RELEASED)) - win_enter(wp, TRUE); /* can make wp invalid! */ - - if (curwin != old_curwin) - { - #ifdef CHECK_DOUBLE_CLICK - /* set topline, to be able to check for double click ourselves */ - set_mouse_topline(curwin); - #endif - #ifdef FEAT_TERMINAL - /* when entering a terminal window may change state */ - term_win_entered(); - #endif - } - if (on_status_line) /* In (or below) status line */ - { - /* Don't use start_arrow() if we're in the same window */ - if (curwin == old_curwin) - return IN_STATUS_LINE; - else - return IN_STATUS_LINE | CURSOR_MOVED; - } - if (on_sep_line) /* In (or below) status line */ - { - /* Don't use start_arrow() if we're in the same window */ - if (curwin == old_curwin) - return IN_SEP_LINE; - else - return IN_SEP_LINE | CURSOR_MOVED; - } - - curwin->w_cursor.lnum = curwin->w_topline; - #ifdef FEAT_GUI - /* remember topline, needed for double click */ - gui_prev_topline = curwin->w_topline; - # ifdef FEAT_DIFF - gui_prev_topfill = curwin->w_topfill; - # endif - #endif - } - else if (on_status_line && which_button == MOUSE_LEFT) - { - if (dragwin != NULL) - { - /* Drag the status line */ - count = row - dragwin->w_winrow - dragwin->w_height + 1 - - on_status_line; - win_drag_status_line(dragwin, count); - did_drag |= count; - } - return IN_STATUS_LINE; /* Cursor didn't move */ - } - else if (on_sep_line && which_button == MOUSE_LEFT) - { - if (dragwin != NULL) - { - /* Drag the separator column */ - count = col - dragwin->w_wincol - dragwin->w_width + 1 - - on_sep_line; - win_drag_vsep_line(dragwin, count); - did_drag |= count; - } - return IN_SEP_LINE; /* Cursor didn't move */ - } - #ifdef FEAT_MENU - else if (in_winbar) - { - /* After a click on the window toolbar don't start Visual mode. */ - return IN_OTHER_WIN | MOUSE_WINBAR; - } - #endif - else /* keep_window_focus must be TRUE */ - { - /* before moving the cursor for a left click, stop Visual mode */ - if (flags & MOUSE_MAY_STOP_VIS) - { - end_visual_mode(); - redraw_curbuf_later(INVERTED); /* delete the inversion */ - } - - #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) - /* Continue a modeless selection in another window. */ - if (cmdwin_type != 0 && row < curwin->w_winrow) - return IN_OTHER_WIN; - #endif - #ifdef FEAT_TEXT_PROP - if (in_popup_win) - { - if (popup_dragwin != NULL) - { - // dragging a popup window - popup_drag(popup_dragwin); - return IN_UNKNOWN; - } - // continue a modeless selection in a popup window - click_in_popup_win = NULL; - return IN_OTHER_WIN; - } - #endif - - row -= W_WINROW(curwin); - col -= curwin->w_wincol; - - /* - * When clicking beyond the end of the window, scroll the screen. - * Scroll by however many rows outside the window we are. - */ - if (row < 0) - { - count = 0; - for (first = TRUE; curwin->w_topline > 1; ) - { - #ifdef FEAT_DIFF - if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) - ++count; - else - #endif - count += plines(curwin->w_topline - 1); - if (!first && count > -row) - break; - first = FALSE; - #ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); - #endif - #ifdef FEAT_DIFF - if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) - ++curwin->w_topfill; - else - #endif - { - --curwin->w_topline; - #ifdef FEAT_DIFF - curwin->w_topfill = 0; - #endif - } - } - #ifdef FEAT_DIFF - check_topfill(curwin, FALSE); - #endif - curwin->w_valid &= - ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); - redraw_later(VALID); - row = 0; - } - else if (row >= curwin->w_height) - { - count = 0; - for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; ) - { - #ifdef FEAT_DIFF - if (curwin->w_topfill > 0) - ++count; - else - #endif - count += plines(curwin->w_topline); - if (!first && count > row - curwin->w_height + 1) - break; - first = FALSE; - #ifdef FEAT_FOLDING - if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline) - && curwin->w_topline == curbuf->b_ml.ml_line_count) - break; - #endif - #ifdef FEAT_DIFF - if (curwin->w_topfill > 0) - --curwin->w_topfill; - else - #endif - { - ++curwin->w_topline; - #ifdef FEAT_DIFF - curwin->w_topfill = - diff_check_fill(curwin, curwin->w_topline); - #endif - } - } - #ifdef FEAT_DIFF - check_topfill(curwin, FALSE); - #endif - redraw_later(VALID); - curwin->w_valid &= - ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); - row = curwin->w_height - 1; - } - else if (row == 0) - { - /* When dragging the mouse, while the text has been scrolled up as - * far as it goes, moving the mouse in the top line should scroll - * the text down (done later when recomputing w_topline). */ - if (mouse_dragging > 0 - && curwin->w_cursor.lnum - == curwin->w_buffer->b_ml.ml_line_count - && curwin->w_cursor.lnum == curwin->w_topline) - curwin->w_valid &= ~(VALID_TOPLINE); - } - } - - #ifdef FEAT_FOLDING - /* Check for position outside of the fold column. */ - if ( - # ifdef FEAT_RIGHTLEFT - curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc : - # endif - col >= curwin->w_p_fdc - # ifdef FEAT_CMDWIN - + (cmdwin_type == 0 ? 0 : 1) - # endif - ) - mouse_char = ' '; - #endif - - /* compute the position in the buffer line from the posn on the screen */ - if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum, NULL)) - mouse_past_bottom = TRUE; - - /* Start Visual mode before coladvance(), for when 'sel' != "old" */ - if ((flags & MOUSE_MAY_VIS) && !VIsual_active) - { - check_visual_highlight(); - VIsual = old_cursor; - VIsual_active = TRUE; - VIsual_reselect = TRUE; - /* if 'selectmode' contains "mouse", start Select mode */ - may_start_select('o'); - setmouse(); - if (p_smd && msg_silent == 0) - redraw_cmdline = TRUE; /* show visual mode later */ - } - - curwin->w_curswant = col; - curwin->w_set_curswant = FALSE; /* May still have been TRUE */ - if (coladvance(col) == FAIL) /* Mouse click beyond end of line */ - { - if (inclusive != NULL) - *inclusive = TRUE; - mouse_past_eol = TRUE; - } - else if (inclusive != NULL) - *inclusive = FALSE; - - count = IN_BUFFER; - if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum - || curwin->w_cursor.col != old_cursor.col) - count |= CURSOR_MOVED; /* Cursor has moved */ - - # ifdef FEAT_FOLDING - if (mouse_char == '+') - count |= MOUSE_FOLD_OPEN; - else if (mouse_char != ' ') - count |= MOUSE_FOLD_CLOSE; - # endif - - return count; - } - #endif - - // Functions also used for popup windows. - #if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO) - - /* - * Compute the buffer line position from the screen position "rowp" / "colp" in - * window "win". - * "plines_cache" can be NULL (no cache) or an array with "win->w_height" - * entries that caches the plines_win() result from a previous call. Entry is - * zero if not computed yet. There must be no text or setting changes since - * the entry is put in the cache. - * Returns TRUE if the position is below the last line. - */ - int - mouse_comp_pos( - win_T *win, - int *rowp, - int *colp, - linenr_T *lnump, - int *plines_cache) - { - int col = *colp; - int row = *rowp; - linenr_T lnum; - int retval = FALSE; - int off; - int count; - - #ifdef FEAT_RIGHTLEFT - if (win->w_p_rl) - col = win->w_width - 1 - col; - #endif - - lnum = win->w_topline; - - while (row > 0) - { - int cache_idx = lnum - win->w_topline; - - if (plines_cache != NULL && plines_cache[cache_idx] > 0) - count = plines_cache[cache_idx]; - else - { - #ifdef FEAT_DIFF - /* Don't include filler lines in "count" */ - if (win->w_p_diff - # ifdef FEAT_FOLDING - && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL) - # endif - ) - { - if (lnum == win->w_topline) - row -= win->w_topfill; - else - row -= diff_check_fill(win, lnum); - count = plines_win_nofill(win, lnum, TRUE); - } - else - #endif - count = plines_win(win, lnum, TRUE); - if (plines_cache != NULL) - plines_cache[cache_idx] = count; - } - if (count > row) - break; /* Position is in this buffer line. */ - #ifdef FEAT_FOLDING - (void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL); - #endif - if (lnum == win->w_buffer->b_ml.ml_line_count) - { - retval = TRUE; - break; /* past end of file */ - } - row -= count; - ++lnum; - } - - if (!retval) - { - /* Compute the column without wrapping. */ - off = win_col_off(win) - win_col_off2(win); - if (col < off) - col = off; - col += row * (win->w_width - off); - /* add skip column (for long wrapping line) */ - col += win->w_skipcol; - } - - if (!win->w_p_wrap) - col += win->w_leftcol; - - /* skip line number and fold column in front of the line */ - col -= win_col_off(win); - if (col < 0) - { - #ifdef FEAT_NETBEANS_INTG - netbeans_gutter_click(lnum); - #endif - col = 0; - } - - *colp = col; - *rowp = row; - *lnump = lnum; - return retval; - } - - /* - * Find the window at screen position "*rowp" and "*colp". The positions are - * updated to become relative to the top-left of the window. - * When "popup" is FAIL_POPUP and the position is in a popup window then NULL - * is returned. When "popup" is IGNORE_POPUP then do not even check popup - * windows. - * Returns NULL when something is wrong. - */ - win_T * - mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED) - { - frame_T *fp; - win_T *wp; - - #ifdef FEAT_TEXT_PROP - win_T *pwp = NULL; - - if (popup != IGNORE_POPUP) - { - popup_reset_handled(); - while ((wp = find_next_popup(TRUE)) != NULL) - { - if (*rowp >= wp->w_winrow && *rowp < wp->w_winrow + popup_height(wp) - && *colp >= wp->w_wincol - && *colp < wp->w_wincol + popup_width(wp)) - pwp = wp; - } - if (pwp != NULL) - { - if (popup == FAIL_POPUP) - return NULL; - *rowp -= pwp->w_winrow; - *colp -= pwp->w_wincol; - return pwp; - } - } - #endif - - fp = topframe; - *rowp -= firstwin->w_winrow; - for (;;) - { - if (fp->fr_layout == FR_LEAF) - break; - if (fp->fr_layout == FR_ROW) - { - for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) - { - if (*colp < fp->fr_width) - break; - *colp -= fp->fr_width; - } - } - else /* fr_layout == FR_COL */ - { - for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) - { - if (*rowp < fp->fr_height) - break; - *rowp -= fp->fr_height; - } - } - } - /* When using a timer that closes a window the window might not actually - * exist. */ - FOR_ALL_WINDOWS(wp) - if (wp == fp->fr_win) - { - #ifdef FEAT_MENU - *rowp -= wp->w_winbar_height; - #endif - return wp; - } - return NULL; - } - - #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ - || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_TERM_POPUP_MENU) \ - || defined(PROTO) - # define NEED_VCOL2COL - - /* - * Translate window coordinates to buffer position without any side effects - */ - int - get_fpos_of_mouse(pos_T *mpos) - { - win_T *wp; - int row = mouse_row; - int col = mouse_col; - - if (row < 0 || col < 0) /* check if it makes sense */ - return IN_UNKNOWN; - - /* find the window where the row is in */ - wp = mouse_find_win(&row, &col, FAIL_POPUP); - if (wp == NULL) - return IN_UNKNOWN; - /* - * winpos and height may change in win_enter()! - */ - if (row >= wp->w_height) /* In (or below) status line */ - return IN_STATUS_LINE; - if (col >= wp->w_width) /* In vertical separator line */ - return IN_SEP_LINE; - - if (wp != curwin) - return IN_UNKNOWN; - - /* compute the position in the buffer line from the posn on the screen */ - if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum, NULL)) - return IN_STATUS_LINE; /* past bottom */ - - mpos->col = vcol2col(wp, mpos->lnum, col); - - if (mpos->col > 0) - --mpos->col; - mpos->coladd = 0; - return IN_BUFFER; - } - #endif - - #if defined(NEED_VCOL2COL) || defined(FEAT_BEVAL) || defined(FEAT_TEXT_PROP) \ - || defined(PROTO) - /* - * Convert a virtual (screen) column to a character column. - * The first column is one. - */ - int - vcol2col(win_T *wp, linenr_T lnum, int vcol) - { - /* try to advance to the specified column */ - int count = 0; - char_u *ptr; - char_u *line; - - line = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); - while (count < vcol && *ptr != NUL) - { - count += win_lbr_chartabsize(wp, line, ptr, count, NULL); - MB_PTR_ADV(ptr); - } - return (int)(ptr - line); - } - #endif - - #endif /* FEAT_MOUSE */ - #if defined(FEAT_GUI) || defined(MSWIN) || defined(PROTO) /* * Called when focus changed. Used for the GUI or for systems where this can --- 2917,2922 ---- *** ../vim-8.1.2061/src/vim.h 2019-09-19 23:05:56.475034930 +0200 --- src/vim.h 2019-09-21 20:13:48.601908392 +0200 *************** *** 229,236 **** // Mark unused function arguments with UNUSED, so that gcc -Wunused-parameter // can be used to check for mistakes. ! #ifdef HAVE_ATTRIBUTE_UNUSED ! # define UNUSED __attribute__((unused)) #else # define UNUSED #endif --- 229,238 ---- // Mark unused function arguments with UNUSED, so that gcc -Wunused-parameter // can be used to check for mistakes. ! #if defined(HAVE_ATTRIBUTE_UNUSED) || defined(__MINGW32__) ! # if !defined(UNUSED) ! # define UNUSED __attribute__((unused)) ! # endif #else # define UNUSED #endif *** ../vim-8.1.2061/src/window.c 2019-09-07 15:45:09.977228927 +0200 --- src/window.c 2019-09-21 20:39:32.742464934 +0200 *************** *** 4672,4680 **** if (curwin->w_width < p_wiw && !curwin->w_p_wfw) win_setwidth((int)p_wiw); ! #ifdef FEAT_MOUSE ! setmouse(); /* in case jumped to/from help buffer */ ! #endif /* Change directories when the 'acd' option is set. */ DO_AUTOCHDIR; --- 4672,4678 ---- if (curwin->w_width < p_wiw && !curwin->w_p_wfw) win_setwidth((int)p_wiw); ! setmouse(); // in case jumped to/from help buffer /* Change directories when the 'acd' option is set. */ DO_AUTOCHDIR; *** ../vim-8.1.2061/src/version.c 2019-09-20 17:19:51.581551957 +0200 --- src/version.c 2019-09-21 20:16:49.453112941 +0200 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 2062, /**/ -- Back up my hard drive? I can't find the reverse switch! /// 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 ///