patch 9.1.1250: cannot set the maximum popup menu width
Problem: cannot set the maximum popup menu width
(Lucas Mior)
Solution: add the new global option value 'pummaxwidth'
(glepnir)
fixes: #10901
closes: #16943
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/popupmenu.c b/src/popupmenu.c
index 443223d..d69c7bd 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -115,6 +115,8 @@
do
{
def_width = p_pw;
+ if (p_pmw > 0 && def_width > p_pmw)
+ def_width = p_pmw;
above_row = 0;
below_row = cmdline_row;
@@ -226,6 +228,8 @@
pum_size = size;
pum_compute_size();
max_width = pum_base_width;
+ if (p_pmw > 0 && max_width > p_pmw)
+ max_width = p_pmw;
// Calculate column
if (State == MODE_CMDLINE)
@@ -275,8 +279,12 @@
content_width = max_width + pum_kind_width + pum_extra_width + 1;
if (pum_width > content_width && pum_width > p_pw)
+ {
// Reduce width to fit item
- pum_width = MAX(content_width , p_pw);
+ pum_width = MAX(content_width, p_pw);
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
+ }
else if (((cursor_col > p_pw || cursor_col > max_width)
#ifdef FEAT_RIGHTLEFT
&& !pum_rl)
@@ -313,6 +321,8 @@
if (pum_width < p_pw)
{
pum_width = p_pw;
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
{
@@ -327,7 +337,11 @@
}
}
else if (pum_width > content_width && pum_width > p_pw)
+ {
pum_width = MAX(content_width, p_pw);
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
+ }
}
}
@@ -341,11 +355,15 @@
#endif
pum_col = 0;
pum_width = Columns - 1;
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
}
else
{
if (max_width > p_pw)
max_width = p_pw; // truncate
+ if (p_pmw > 0 && max_width > p_pmw)
+ max_width = p_pmw;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
pum_col = max_width - 1;
@@ -582,6 +600,13 @@
int last_isabbr = FALSE;
int orig_attr = -1;
int scroll_range = pum_size - pum_height;
+ int need_ellipsis = FALSE;
+ int char_cells = 0;
+ int ellipsis_width = 3;
+ int over_cell = 0;
+ char_u *new_str = NULL;
+ int kept_len = 0;
+ char_u *last_char = NULL;
hlf_T hlfsNorm[3];
hlf_T hlfsSel[3];
@@ -698,8 +723,14 @@
{
char_u *rt_start = rt;
int cells;
+ int used_cells = 0;
+ char_u *old_rt = NULL;
+ char_u *orig_rt = NULL;
cells = vim_strsize(rt);
+ need_ellipsis = p_pmw > ellipsis_width
+ && pum_width == p_pmw
+ && cells > pum_width;
if (cells > pum_width)
{
do
@@ -709,7 +740,42 @@
MB_PTR_ADV(rt);
} while (cells > pum_width);
- if (cells < pum_width)
+ if (need_ellipsis)
+ {
+ orig_rt = rt;
+ while (*orig_rt != NUL)
+ {
+ char_cells = has_mbyte ? (*mb_ptr2cells)(orig_rt) : 1;
+ if (used_cells + char_cells > ellipsis_width)
+ break;
+ used_cells += char_cells;
+ MB_PTR_ADV(orig_rt);
+ last_char = orig_rt;
+ }
+
+ if (last_char != NULL)
+ {
+ if (used_cells < ellipsis_width)
+ {
+ over_cell = ellipsis_width - used_cells;
+ MB_PTR_ADV(orig_rt);
+ last_char = orig_rt;
+ }
+ kept_len = STRLEN(last_char);
+ new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
+ if (!new_str)
+ return;
+ vim_memset(new_str, '.', ellipsis_width);
+ if (over_cell > 0)
+ vim_memset(new_str + ellipsis_width, ' ', over_cell);
+ memcpy(new_str + ellipsis_width + over_cell, last_char, kept_len);
+ new_str[ellipsis_width + kept_len + over_cell] = NUL;
+ old_rt = rt_start;
+ rt = rt_start = new_str;
+ vim_free(old_rt);
+ }
+ }
+ else if (cells < pum_width)
{
// Most left character requires 2-cells
// but only 1 cell is available on
@@ -739,8 +805,13 @@
{
if (st != NULL)
{
- int size = (int)STRLEN(st);
- int cells = (*mb_string2cells)(st, size);
+ int size = (int)STRLEN(st);
+ int cells = (*mb_string2cells)(st, size);
+ int used_cells = 0;
+ char_u *st_end = NULL;
+ need_ellipsis = p_pmw > ellipsis_width
+ && pum_width == p_pmw
+ && col + cells > pum_col + pum_width;
// only draw the text that fits
while (size > 0
@@ -756,6 +827,42 @@
--cells;
}
+ // Add '...' indicator if truncated due to p_pmw
+ if (need_ellipsis)
+ {
+ st_end = st + size;
+ while (st_end > st)
+ {
+ char_cells = has_mbyte ? (*mb_ptr2cells)(st_end) : 1;
+ if (used_cells + char_cells > ellipsis_width)
+ break;
+ used_cells += char_cells;
+ MB_PTR_BACK(st, st_end);
+ last_char = st_end;
+ }
+
+ if (last_char != NULL)
+ {
+ if (used_cells < ellipsis_width)
+ {
+ MB_PTR_BACK(st, st_end);
+ last_char = st_end;
+ over_cell = ellipsis_width - used_cells;
+ }
+ kept_len = last_char - st;
+ new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
+ if (!new_str)
+ return;
+ memcpy(new_str, st, kept_len);
+ if (over_cell > 0)
+ vim_memset(new_str + kept_len, ' ', over_cell);
+ vim_memset(new_str + kept_len + over_cell, '.', ellipsis_width);
+ new_str[kept_len + ellipsis_width + over_cell] = NUL;
+ vim_free(st);
+ st = new_str;
+ }
+ }
+
if (attrs == NULL)
screen_puts_len(st, size, row, col, attr);
else