aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/popupmnu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/popupmnu.c')
-rw-r--r--src/nvim/popupmnu.c158
1 files changed, 106 insertions, 52 deletions
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 5ad621e666..89180f76de 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -7,12 +7,12 @@
#include <stdbool.h>
#include "nvim/vim.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/popupmnu.h"
#include "nvim/charset.h"
#include "nvim/ex_cmds.h"
#include "nvim/memline.h"
-#include "nvim/misc2.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/screen.h"
@@ -21,6 +21,7 @@
#include "nvim/memory.h"
#include "nvim/window.h"
#include "nvim/edit.h"
+#include "nvim/ui.h"
static pumitem_T *pum_array = NULL; // items of displayed pum
static int pum_size; // nr of items in "pum_array"
@@ -36,8 +37,10 @@ static int pum_scrollbar; // TRUE when scrollbar present
static int pum_row; // top row of pum
static int pum_col; // left column of pum
-static int pum_do_redraw = FALSE; // do redraw anyway
+static bool pum_is_visible = false;
+static bool pum_external = false;
+static bool pum_wants_external = false;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "popupmnu.c.generated.h"
@@ -53,7 +56,10 @@ static int pum_do_redraw = FALSE; // do redraw anyway
/// @param array
/// @param size
/// @param selected index of initially selected item, none if out of range
-void pum_display(pumitem_T *array, int size, int selected)
+/// @param array_changed if true, array contains different items since last call
+/// if false, a new item is selected, but the array
+/// is the same
+void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
{
int w;
int def_width;
@@ -61,38 +67,77 @@ void pum_display(pumitem_T *array, int size, int selected)
int kind_width;
int extra_width;
int i;
- int top_clear;
int row;
int context_lines;
int col;
- int above_row = cmdline_row;
+ int above_row;
+ int below_row;
int redo_count = 0;
+ win_T *pvwin;
+
+ if (!pum_is_visible) {
+ // To keep the code simple, we only allow changing the
+ // draw mode when the popup menu is not being displayed
+ pum_external = pum_wants_external;
+ }
redo:
+ // Mark the pum as visible already here,
+ // to avoid that must_redraw is set when 'cursorcolumn' is on.
+ pum_is_visible = true;
+ validate_cursor_col();
+ above_row = 0;
+ below_row = cmdline_row;
+
+ // anchor position: the start of the completed word
+ row = curwin->w_wrow + curwin->w_winrow;
+ if (curwin->w_p_rl) {
+ col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
+ } else {
+ col = curwin->w_wincol + curwin->w_wcol;
+ }
+
+ if (pum_external) {
+ Array args = ARRAY_DICT_INIT;
+ if (array_changed) {
+ Array arr = ARRAY_DICT_INIT;
+ for (i = 0; i < size; i++) {
+ Array item = ARRAY_DICT_INIT;
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_text)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_kind)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_extra)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info)));
+ ADD(arr, ARRAY_OBJ(item));
+ }
+ ADD(args, ARRAY_OBJ(arr));
+ ADD(args, INTEGER_OBJ(selected));
+ ADD(args, INTEGER_OBJ(row));
+ ADD(args, INTEGER_OBJ(col));
+ ui_event("popupmenu_show", args);
+ } else {
+ ADD(args, INTEGER_OBJ(selected));
+ ui_event("popupmenu_select", args);
+ }
+ return;
+ }
+
def_width = PUM_DEF_WIDTH;
max_width = 0;
kind_width = 0;
extra_width = 0;
- // Pretend the pum is already there to avoid that must_redraw is set when
- // 'cuc' is on.
- pum_array = (pumitem_T *)1;
- validate_cursor_col();
- pum_array = NULL;
-
- row = curwin->w_wrow + curwin->w_winrow;
-
- if (firstwin->w_p_pvw) {
- top_clear = firstwin->w_height;
- } else {
- top_clear = 0;
+ FOR_ALL_WINDOWS(pvwin) {
+ if (pvwin->w_p_pvw) {
+ break;
+ }
}
- // When the preview window is at the bottom stop just above it. Also
- // avoid drawing over the status line so that it's clear there is a window
- // boundary.
- if (lastwin->w_p_pvw) {
- above_row -= lastwin->w_height + lastwin->w_status_height + 1;
+ if (pvwin != NULL) {
+ if (pvwin->w_wrow < curwin->w_wrow) {
+ above_row = pvwin->w_wrow + pvwin->w_height;
+ } else if (pvwin->w_wrow > pvwin->w_wrow + curwin->w_height) {
+ below_row = pvwin->w_wrow;
+ }
}
// Figure out the size and position of the pum.
@@ -108,8 +153,8 @@ redo:
// Put the pum below "row" if possible. If there are few lines decide on
// where there is more room.
- if ((row + 2 >= above_row - pum_height)
- && (row > (above_row - top_clear) / 2)) {
+ if (row + 2 >= below_row - pum_height
+ && row - above_row > (below_row - above_row) / 2) {
// pum above "row"
// Leave two lines of context if possible
@@ -143,8 +188,8 @@ redo:
}
pum_row = row + context_lines;
- if (size > above_row - pum_row) {
- pum_height = above_row - pum_row;
+ if (size > below_row - pum_row) {
+ pum_height = below_row - pum_row;
} else {
pum_height = size;
}
@@ -159,12 +204,10 @@ redo:
return;
}
- // If there is a preview window at the top avoid drawing over it.
- if (firstwin->w_p_pvw
- && (pum_row < firstwin->w_height)
- && (pum_height > firstwin->w_height + 4)) {
- pum_row += firstwin->w_height;
- pum_height -= firstwin->w_height;
+ // If there is a preview window at the above avoid drawing over it.
+ if (pvwin != NULL && pum_row < above_row && pum_height > above_row) {
+ pum_row += above_row;
+ pum_height -= above_row;
}
// Compute the width of the widest match and the widest extra.
@@ -194,13 +237,6 @@ redo:
pum_base_width = max_width;
pum_kind_width = kind_width;
- // Calculate column
- if (curwin->w_p_rl) {
- col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
- } else {
- col = curwin->w_wincol + curwin->w_wcol;
- }
-
// if there are more items than room we need a scrollbar
if (pum_height < size) {
pum_scrollbar = 1;
@@ -554,7 +590,9 @@ static int pum_set_selected(int n, int repeat)
g_do_tagpreview = 0;
if (curwin->w_p_pvw) {
- if ((curbuf->b_fname == NULL)
+ if (!resized
+ && (curbuf->b_nwindows == 1)
+ && (curbuf->b_fname == NULL)
&& (curbuf->b_p_bt[0] == 'n')
&& (curbuf->b_p_bt[2] == 'f')
&& (curbuf->b_p_bh[0] == 'w')) {
@@ -641,9 +679,9 @@ static int pum_set_selected(int n, int repeat)
// Update the screen before drawing the popup menu.
// Enable updating the status lines.
- pum_do_redraw = TRUE;
+ pum_is_visible = false;
update_screen(0);
- pum_do_redraw = FALSE;
+ pum_is_visible = true;
if (!resized && win_valid(curwin_save)) {
no_u_sync++;
@@ -653,9 +691,9 @@ static int pum_set_selected(int n, int repeat)
// May need to update the screen again when there are
// autocommands involved.
- pum_do_redraw = TRUE;
+ pum_is_visible = false;
update_screen(0);
- pum_do_redraw = FALSE;
+ pum_is_visible = true;
}
}
}
@@ -672,10 +710,17 @@ static int pum_set_selected(int n, int repeat)
/// Undisplay the popup menu (later).
void pum_undisplay(void)
{
+ pum_is_visible = false;
pum_array = NULL;
- redraw_all_later(SOME_VALID);
- redraw_tabline = TRUE;
- status_redraw_all();
+
+ if (pum_external) {
+ Array args = ARRAY_DICT_INIT;
+ ui_event("popupmenu_hide", args);
+ } else {
+ redraw_all_later(SOME_VALID);
+ redraw_tabline = true;
+ status_redraw_all();
+ }
}
/// Clear the popup menu. Currently only resets the offset to the first
@@ -685,12 +730,16 @@ void pum_clear(void)
pum_first = 0;
}
-/// Overruled when "pum_do_redraw" is set, used to redraw the status lines.
-///
-/// @return TRUE if the popup menu is displayed.
-int pum_visible(void)
+/// @return true if the popup menu is displayed.
+bool pum_visible(void)
+{
+ return pum_is_visible;
+}
+
+/// @return true if the popup menu is displayed and drawn on the grid.
+bool pum_drawn(void)
{
- return !pum_do_redraw && pum_array != NULL;
+ return pum_visible() && !pum_external;
}
/// Gets the height of the menu.
@@ -701,3 +750,8 @@ int pum_get_height(void)
{
return pum_height;
}
+
+void pum_set_external(bool external)
+{
+ pum_wants_external = external;
+}