mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
ui: Extract mouse.c/mouse.h
This commit is contained in:
parent
1865b8c1c1
commit
a3534138a8
@ -25,6 +25,8 @@ src/nvim/map_defs.h
|
||||
src/nvim/memfile.c
|
||||
src/nvim/memfile.h
|
||||
src/nvim/memfile_defs.h
|
||||
src/nvim/mouse.c
|
||||
src/nvim/mouse.h
|
||||
src/nvim/msgpack_rpc/channel.c
|
||||
src/nvim/msgpack_rpc/channel.h
|
||||
src/nvim/msgpack_rpc/helpers.c
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "nvim/tag.h"
|
||||
#include "nvim/term.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/undo.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/os/event.h"
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include "nvim/tempfile.h"
|
||||
#include "nvim/term.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/undo.h"
|
||||
#include "nvim/version.h"
|
||||
#include "nvim/window.h"
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/term.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/time.h"
|
||||
|
438
src/nvim/mouse.c
Normal file
438
src/nvim/mouse.c
Normal file
@ -0,0 +1,438 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/screen.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/term.h"
|
||||
#include "nvim/fold.h"
|
||||
#include "nvim/diff.h"
|
||||
#include "nvim/move.h"
|
||||
#include "nvim/misc1.h"
|
||||
#include "nvim/cursor.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "mouse.c.generated.h"
|
||||
#endif
|
||||
|
||||
// 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,
|
||||
bool *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
|
||||
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;
|
||||
bool first;
|
||||
int row = mouse_row;
|
||||
int col = mouse_col;
|
||||
int mouse_char;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (flags & MOUSE_MAY_STOP_VIS) {
|
||||
end_visual_mode();
|
||||
redraw_curbuf_later(INVERTED); // delete the inversion
|
||||
}
|
||||
return IN_BUFFER;
|
||||
}
|
||||
|
||||
prev_row = mouse_row;
|
||||
prev_col = mouse_col;
|
||||
|
||||
if (flags & MOUSE_SETPOS)
|
||||
goto retnomove; // ugly goto...
|
||||
|
||||
// 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] + (unsigned)col];
|
||||
else
|
||||
mouse_char = ' ';
|
||||
|
||||
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
|
||||
wp = mouse_find_win(&row, &col);
|
||||
dragwin = NULL;
|
||||
// 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
|
||||
&& (
|
||||
wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
|
||||
col >= wp->w_p_fdc
|
||||
+ (cmdwin_type == 0 && wp ==
|
||||
curwin ? 0 : 1)
|
||||
)
|
||||
&& (flags & MOUSE_MAY_STOP_VIS)))) {
|
||||
end_visual_mode();
|
||||
redraw_curbuf_later(INVERTED); // delete the inversion
|
||||
}
|
||||
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;
|
||||
row = 0;
|
||||
col += wp->w_wincol;
|
||||
wp = curwin;
|
||||
}
|
||||
// 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!
|
||||
# ifdef CHECK_DOUBLE_CLICK
|
||||
// set topline, to be able to check for double click ourselves
|
||||
if (curwin != old_curwin)
|
||||
set_mouse_topline(curwin);
|
||||
# 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;
|
||||
} 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
|
||||
} 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
|
||||
}
|
||||
|
||||
|
||||
row -= curwin->w_winrow;
|
||||
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; ) {
|
||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
|
||||
++count;
|
||||
else
|
||||
count += plines(curwin->w_topline - 1);
|
||||
if (!first && count > -row)
|
||||
break;
|
||||
first = false;
|
||||
hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
|
||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) {
|
||||
++curwin->w_topfill;
|
||||
} else {
|
||||
--curwin->w_topline;
|
||||
curwin->w_topfill = 0;
|
||||
}
|
||||
}
|
||||
check_topfill(curwin, false);
|
||||
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; ) {
|
||||
if (curwin->w_topfill > 0) {
|
||||
++count;
|
||||
} else {
|
||||
count += plines(curwin->w_topline);
|
||||
}
|
||||
|
||||
if (!first && count > row - curwin->w_height + 1) {
|
||||
break;
|
||||
}
|
||||
first = false;
|
||||
|
||||
if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
|
||||
&& curwin->w_topline == curbuf->b_ml.ml_line_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (curwin->w_topfill > 0) {
|
||||
--curwin->w_topfill;
|
||||
} else {
|
||||
++curwin->w_topline;
|
||||
curwin->w_topfill =
|
||||
diff_check_fill(curwin, curwin->w_topline);
|
||||
}
|
||||
}
|
||||
check_topfill(curwin, false);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for position outside of the fold column.
|
||||
if (curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
|
||||
col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)) {
|
||||
mouse_char = ' ';
|
||||
}
|
||||
|
||||
// compute the position in the buffer line from the posn on the screen
|
||||
if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) {
|
||||
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
|
||||
}
|
||||
|
||||
if (mouse_char == '+') {
|
||||
count |= MOUSE_FOLD_OPEN;
|
||||
} else if (mouse_char != ' ') {
|
||||
count |= MOUSE_FOLD_CLOSE;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Compute the position in the buffer line from the posn on the screen in
|
||||
// window "win".
|
||||
// Returns true if the position is below the last line.
|
||||
bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
|
||||
{
|
||||
int col = *colp;
|
||||
int row = *rowp;
|
||||
linenr_T lnum;
|
||||
bool retval = false;
|
||||
int off;
|
||||
int count;
|
||||
|
||||
if (win->w_p_rl)
|
||||
col = win->w_width - 1 - col;
|
||||
|
||||
lnum = win->w_topline;
|
||||
|
||||
while (row > 0) {
|
||||
// Don't include filler lines in "count"
|
||||
if (win->w_p_diff
|
||||
&& !hasFoldingWin(win, lnum, NULL, NULL, true, NULL)) {
|
||||
if (lnum == win->w_topline) {
|
||||
row -= win->w_topfill;
|
||||
} else {
|
||||
row -= diff_check_fill(win, lnum);
|
||||
}
|
||||
count = plines_win_nofill(win, lnum, true);
|
||||
} else {
|
||||
count = plines_win(win, lnum, true);
|
||||
}
|
||||
|
||||
if (count > row) {
|
||||
break; // Position is in this buffer line.
|
||||
}
|
||||
|
||||
(void)hasFoldingWin(win, lnum, NULL, &lnum, true, NULL);
|
||||
|
||||
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) {
|
||||
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.
|
||||
win_T *mouse_find_win(int *rowp, int *colp)
|
||||
{
|
||||
frame_T *fp;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fp->fr_win;
|
||||
}
|
32
src/nvim/mouse.h
Normal file
32
src/nvim/mouse.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef NVIM_MOUSE_H
|
||||
#define NVIM_MOUSE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
|
||||
// jump_to_mouse() returns one of first four these values, possibly with
|
||||
// some of the other three added.
|
||||
#define IN_UNKNOWN 0
|
||||
#define IN_BUFFER 1
|
||||
#define IN_STATUS_LINE 2 // on status or command line
|
||||
#define IN_SEP_LINE 4 // on vertical separator line
|
||||
#define IN_OTHER_WIN 8 // in other window but can't go there
|
||||
#define CURSOR_MOVED 0x100
|
||||
#define MOUSE_FOLD_CLOSE 0x200 // clicked on '-' in fold column
|
||||
#define MOUSE_FOLD_OPEN 0x400 // clicked on '+' in fold column
|
||||
|
||||
// flags for jump_to_mouse()
|
||||
#define MOUSE_FOCUS 0x01 // need to stay in this window
|
||||
#define MOUSE_MAY_VIS 0x02 // may start Visual mode
|
||||
#define MOUSE_DID_MOVE 0x04 // only act when mouse has moved
|
||||
#define MOUSE_SETPOS 0x08 // only set current mouse position
|
||||
#define MOUSE_MAY_STOP_VIS 0x10 // may stop Visual mode
|
||||
#define MOUSE_RELEASED 0x20 // button was released
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "mouse.h.generated.h"
|
||||
#endif
|
||||
|
||||
#endif // NVIM_MOUSE_H
|
@ -57,6 +57,7 @@
|
||||
#include "nvim/tag.h"
|
||||
#include "nvim/term.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/undo.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/os/event.h"
|
||||
|
415
src/nvim/ui.c
415
src/nvim/ui.c
@ -137,421 +137,6 @@ int check_row(int row)
|
||||
return row;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff for the X clipboard. Shared between VMS and Unix.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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,
|
||||
bool *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 */
|
||||
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;
|
||||
bool first;
|
||||
int row = mouse_row;
|
||||
int col = mouse_col;
|
||||
int mouse_char;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (flags & MOUSE_MAY_STOP_VIS) {
|
||||
end_visual_mode();
|
||||
redraw_curbuf_later(INVERTED); /* delete the inversion */
|
||||
}
|
||||
return IN_BUFFER;
|
||||
}
|
||||
|
||||
prev_row = mouse_row;
|
||||
prev_col = mouse_col;
|
||||
|
||||
if (flags & MOUSE_SETPOS)
|
||||
goto retnomove; /* ugly goto... */
|
||||
|
||||
/* 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 = ' ';
|
||||
|
||||
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 */
|
||||
wp = mouse_find_win(&row, &col);
|
||||
dragwin = NULL;
|
||||
/*
|
||||
* 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
|
||||
&& (
|
||||
wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
|
||||
col >= wp->w_p_fdc
|
||||
+ (cmdwin_type == 0 && wp ==
|
||||
curwin ? 0 : 1)
|
||||
)
|
||||
&& (flags & MOUSE_MAY_STOP_VIS)))) {
|
||||
end_visual_mode();
|
||||
redraw_curbuf_later(INVERTED); /* delete the inversion */
|
||||
}
|
||||
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;
|
||||
row = 0;
|
||||
col += wp->w_wincol;
|
||||
wp = curwin;
|
||||
}
|
||||
/* 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! */
|
||||
# ifdef CHECK_DOUBLE_CLICK
|
||||
/* set topline, to be able to check for double click ourselves */
|
||||
if (curwin != old_curwin)
|
||||
set_mouse_topline(curwin);
|
||||
# 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;
|
||||
} 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 */
|
||||
} 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 */
|
||||
}
|
||||
|
||||
|
||||
row -= curwin->w_winrow;
|
||||
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; ) {
|
||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
|
||||
++count;
|
||||
else
|
||||
count += plines(curwin->w_topline - 1);
|
||||
if (!first && count > -row)
|
||||
break;
|
||||
first = false;
|
||||
hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
|
||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
|
||||
++curwin->w_topfill;
|
||||
else {
|
||||
--curwin->w_topline;
|
||||
curwin->w_topfill = 0;
|
||||
}
|
||||
}
|
||||
check_topfill(curwin, false);
|
||||
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; ) {
|
||||
if (curwin->w_topfill > 0)
|
||||
++count;
|
||||
else
|
||||
count += plines(curwin->w_topline);
|
||||
if (!first && count > row - curwin->w_height + 1)
|
||||
break;
|
||||
first = false;
|
||||
if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
|
||||
&& curwin->w_topline == curbuf->b_ml.ml_line_count)
|
||||
break;
|
||||
if (curwin->w_topfill > 0)
|
||||
--curwin->w_topfill;
|
||||
else {
|
||||
++curwin->w_topline;
|
||||
curwin->w_topfill =
|
||||
diff_check_fill(curwin, curwin->w_topline);
|
||||
}
|
||||
}
|
||||
check_topfill(curwin, false);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for position outside of the fold column. */
|
||||
if (
|
||||
curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
|
||||
col >= curwin->w_p_fdc
|
||||
+ (cmdwin_type == 0 ? 0 : 1)
|
||||
)
|
||||
mouse_char = ' ';
|
||||
|
||||
/* compute the position in the buffer line from the posn on the screen */
|
||||
if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum))
|
||||
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 */
|
||||
|
||||
if (mouse_char == '+')
|
||||
count |= MOUSE_FOLD_OPEN;
|
||||
else if (mouse_char != ' ')
|
||||
count |= MOUSE_FOLD_CLOSE;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the position in the buffer line from the posn on the screen in
|
||||
* window "win".
|
||||
* Returns TRUE if the position is below the last line.
|
||||
*/
|
||||
bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
|
||||
{
|
||||
int col = *colp;
|
||||
int row = *rowp;
|
||||
linenr_T lnum;
|
||||
bool retval = false;
|
||||
int off;
|
||||
int count;
|
||||
|
||||
if (win->w_p_rl)
|
||||
col = win->w_width - 1 - col;
|
||||
|
||||
lnum = win->w_topline;
|
||||
|
||||
while (row > 0) {
|
||||
/* Don't include filler lines in "count" */
|
||||
if (win->w_p_diff
|
||||
&& !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
|
||||
) {
|
||||
if (lnum == win->w_topline)
|
||||
row -= win->w_topfill;
|
||||
else
|
||||
row -= diff_check_fill(win, lnum);
|
||||
count = plines_win_nofill(win, lnum, TRUE);
|
||||
} else
|
||||
count = plines_win(win, lnum, TRUE);
|
||||
if (count > row)
|
||||
break; /* Position is in this buffer line. */
|
||||
(void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
win_T *mouse_find_win(int *rowp, int *colp)
|
||||
{
|
||||
frame_T *fp;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fp->fr_win;
|
||||
}
|
||||
|
||||
#if defined(USE_IM_CONTROL) || defined(PROTO)
|
||||
/*
|
||||
|
@ -3,27 +3,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* jump_to_mouse() returns one of first four these values, possibly with
|
||||
* some of the other three added.
|
||||
*/
|
||||
#define IN_UNKNOWN 0
|
||||
#define IN_BUFFER 1
|
||||
#define IN_STATUS_LINE 2 /* on status or command line */
|
||||
#define IN_SEP_LINE 4 /* on vertical separator line */
|
||||
#define IN_OTHER_WIN 8 /* in other window but can't go there */
|
||||
#define CURSOR_MOVED 0x100
|
||||
#define MOUSE_FOLD_CLOSE 0x200 /* clicked on '-' in fold column */
|
||||
#define MOUSE_FOLD_OPEN 0x400 /* clicked on '+' in fold column */
|
||||
|
||||
/* flags for jump_to_mouse() */
|
||||
#define MOUSE_FOCUS 0x01 /* need to stay in this window */
|
||||
#define MOUSE_MAY_VIS 0x02 /* may start Visual mode */
|
||||
#define MOUSE_DID_MOVE 0x04 /* only act when mouse has moved */
|
||||
#define MOUSE_SETPOS 0x08 /* only set current mouse position */
|
||||
#define MOUSE_MAY_STOP_VIS 0x10 /* may stop Visual mode */
|
||||
#define MOUSE_RELEASED 0x20 /* button was released */
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ui.h.generated.h"
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user