comparison src/popupwin.c @ 16855:19162ff4eacd v8.1.1429

patch 8.1.1429: "pos" option of popup window not supported yet commit https://github.com/vim/vim/commit/ac1f1bc222b7de3cb2d3f1f2aa076f11c75e69de Author: Bram Moolenaar <Bram@vim.org> Date: Thu May 30 21:24:26 2019 +0200 patch 8.1.1429: "pos" option of popup window not supported yet Problem: "pos" option of popup window not supported yet. Solution: Implement the option. Rename popup_getposition() to popup_getpos().
author Bram Moolenaar <Bram@vim.org>
date Thu, 30 May 2019 21:30:04 +0200
parents e6bcccccbf7b
children 4de94f6161f2
comparison
equal deleted inserted replaced
16854:a84036f2d3ec 16855:19162ff4eacd
13 13
14 #include "vim.h" 14 #include "vim.h"
15 15
16 #ifdef FEAT_TEXT_PROP 16 #ifdef FEAT_TEXT_PROP
17 17
18 typedef struct {
19 char *pp_name;
20 poppos_T pp_val;
21 } poppos_entry_T;
22
23 static poppos_entry_T poppos_entries[] = {
24 {"botleft", POPPOS_BOTLEFT},
25 {"topleft", POPPOS_TOPLEFT},
26 {"botright", POPPOS_BOTRIGHT},
27 {"topright", POPPOS_TOPRIGHT},
28 {"center", POPPOS_CENTER}
29 };
30
18 /* 31 /*
19 * Get option value for"key", which is "line" or "col". 32 * Get option value for"key", which is "line" or "col".
20 * Handles "cursor+N" and "cursor-N". 33 * Handles "cursor+N" and "cursor-N".
21 */ 34 */
22 static int 35 static int
23 popup_options_pos(dict_T *dict, char_u *key) 36 popup_options_one(dict_T *dict, char_u *key)
24 { 37 {
25 dictitem_T *di; 38 dictitem_T *di;
26 char_u *val; 39 char_u *val;
27 char_u *s; 40 char_u *s;
28 char_u *endp; 41 char_u *endp;
56 if (n < 1) 69 if (n < 1)
57 n = 1; 70 n = 1;
58 return n; 71 return n;
59 } 72 }
60 73
74 static void
75 get_pos_options(win_T *wp, dict_T *dict)
76 {
77 char_u *str;
78 int nr;
79
80 nr = popup_options_one(dict, (char_u *)"line");
81 if (nr > 0)
82 wp->w_wantline = nr;
83 nr = popup_options_one(dict, (char_u *)"col");
84 if (nr > 0)
85 wp->w_wantcol = nr;
86
87 str = dict_get_string(dict, (char_u *)"pos", FALSE);
88 if (str != NULL)
89 {
90 for (nr = 0;
91 nr < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
92 ++nr)
93 if (STRCMP(str, poppos_entries[nr].pp_name) == 0)
94 {
95 wp->w_popup_pos = poppos_entries[nr].pp_val;
96 nr = -1;
97 break;
98 }
99 if (nr != -1)
100 semsg(_(e_invarg2), str);
101 }
102 }
103
61 /* 104 /*
62 * Go through the options in "dict" and apply them to buffer "buf" displayed in 105 * Go through the options in "dict" and apply them to buffer "buf" displayed in
63 * popup window "wp". 106 * popup window "wp".
64 * When called from f_popup_atcursor() "atcursor" is TRUE. 107 * When called from f_popup_atcursor() "atcursor" is TRUE.
65 */ 108 */
66 static void 109 static void
67 apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor) 110 apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor)
68 { 111 {
112 #if defined(FEAT_TIMERS)
69 int nr; 113 int nr;
114 #endif
70 char_u *str; 115 char_u *str;
71 116
72 wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth"); 117 wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth");
73 wp->w_minheight = dict_get_number(dict, (char_u *)"minheight"); 118 wp->w_minheight = dict_get_number(dict, (char_u *)"minheight");
74 wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth"); 119 wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth");
75 wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight"); 120 wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight");
76 121
77 if (atcursor) 122 if (atcursor)
78 { 123 {
124 wp->w_popup_pos = POPPOS_BOTLEFT;
79 setcursor_mayforce(TRUE); 125 setcursor_mayforce(TRUE);
80 wp->w_wantline = screen_screenrow(); 126 wp->w_wantline = screen_screenrow();
127 if (wp->w_wantline == 0) // cursor in first line
128 {
129 wp->w_wantline = 2;
130 wp->w_popup_pos = POPPOS_TOPLEFT;
131 }
81 wp->w_wantcol = screen_screencol() + 1; 132 wp->w_wantcol = screen_screencol() + 1;
82 } 133 }
83 134
84 nr = popup_options_pos(dict, (char_u *)"line"); 135 get_pos_options(wp, dict);
85 if (nr > 0)
86 wp->w_wantline = nr;
87 nr = popup_options_pos(dict, (char_u *)"col");
88 if (nr > 0)
89 wp->w_wantcol = nr;
90 136
91 wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); 137 wp->w_zindex = dict_get_number(dict, (char_u *)"zindex");
92 138
93 #if defined(FEAT_TIMERS) 139 #if defined(FEAT_TIMERS)
94 // Add timer to close the popup after some time. 140 // Add timer to close the popup after some time.
210 popup_adjust_position(win_T *wp) 256 popup_adjust_position(win_T *wp)
211 { 257 {
212 linenr_T lnum; 258 linenr_T lnum;
213 int wrapped = 0; 259 int wrapped = 0;
214 int maxwidth; 260 int maxwidth;
215 261 int center_vert = FALSE;
216 // TODO: Compute the size and position properly. 262 int center_hor = FALSE;
217 if (wp->w_wantline > 0) 263
218 wp->w_winrow = wp->w_wantline - 1; 264 wp->w_winrow = 0;
265 wp->w_wincol = 0;
266 if (wp->w_popup_pos == POPPOS_CENTER)
267 {
268 // center after computing the size
269 center_vert = TRUE;
270 center_hor = TRUE;
271 }
219 else 272 else
220 // TODO: better default 273 {
221 wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0; 274 if (wp->w_wantline == 0)
222 if (wp->w_winrow >= Rows) 275 center_vert = TRUE;
223 wp->w_winrow = Rows - 1; 276 else if (wp->w_popup_pos == POPPOS_TOPLEFT
224 277 || wp->w_popup_pos == POPPOS_TOPRIGHT)
225 if (wp->w_wantcol > 0) 278 {
226 wp->w_wincol = wp->w_wantcol - 1; 279 wp->w_winrow = wp->w_wantline - 1;
227 else 280 if (wp->w_winrow >= Rows)
228 // TODO: better default 281 wp->w_winrow = Rows - 1;
229 wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0; 282 }
230 if (wp->w_wincol >= Columns - 3) 283
231 wp->w_wincol = Columns - 3; 284 if (wp->w_wantcol == 0)
232 285 center_hor = TRUE;
286 else if (wp->w_popup_pos == POPPOS_TOPLEFT
287 || wp->w_popup_pos == POPPOS_BOTLEFT)
288 {
289 wp->w_wincol = wp->w_wantcol - 1;
290 if (wp->w_wincol >= Columns - 3)
291 wp->w_wincol = Columns - 3;
292 }
293 }
294
295 // When centering or right aligned, use maximum width.
296 // When left aligned use the space available.
233 maxwidth = Columns - wp->w_wincol; 297 maxwidth = Columns - wp->w_wincol;
234 if (wp->w_maxwidth > 0 && maxwidth > wp->w_maxwidth) 298 if (wp->w_maxwidth > 0 && maxwidth > wp->w_maxwidth)
235 maxwidth = wp->w_maxwidth; 299 maxwidth = wp->w_maxwidth;
236 300
237 // Compute width based on longest text line and the 'wrap' option. 301 // Compute width based on longest text line and the 'wrap' option.
253 317
254 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth) 318 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth)
255 wp->w_width = wp->w_minwidth; 319 wp->w_width = wp->w_minwidth;
256 if (wp->w_width > maxwidth) 320 if (wp->w_width > maxwidth)
257 wp->w_width = maxwidth; 321 wp->w_width = maxwidth;
322 if (center_hor)
323 wp->w_wincol = (Columns - wp->w_width) / 2;
324 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
325 || wp->w_popup_pos == POPPOS_TOPRIGHT)
326 {
327 // Right aligned: move to the right if needed.
328 // No truncation, because that would change the height.
329 if (wp->w_width < wp->w_wantcol)
330 wp->w_wincol = wp->w_wantcol - wp->w_width;
331 }
258 332
259 if (wp->w_height <= 1) 333 if (wp->w_height <= 1)
260 wp->w_height = wp->w_buffer->b_ml.ml_line_count + wrapped; 334 wp->w_height = wp->w_buffer->b_ml.ml_line_count + wrapped;
261 if (wp->w_minheight > 0 && wp->w_height < wp->w_minheight) 335 if (wp->w_minheight > 0 && wp->w_height < wp->w_minheight)
262 wp->w_height = wp->w_minheight; 336 wp->w_height = wp->w_minheight;
263 if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight) 337 if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight)
264 wp->w_height = wp->w_maxheight; 338 wp->w_height = wp->w_maxheight;
265 if (wp->w_height > Rows - wp->w_winrow) 339 if (wp->w_height > Rows - wp->w_winrow)
266 wp->w_height = Rows - wp->w_winrow; 340 wp->w_height = Rows - wp->w_winrow;
267 341
342 if (center_vert)
343 wp->w_winrow = (Rows - wp->w_height) / 2;
344 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
345 || wp->w_popup_pos == POPPOS_BOTLEFT)
346 {
347 if (wp->w_height <= wp->w_wantline)
348 // bottom aligned: may move down
349 wp->w_winrow = wp->w_wantline - wp->w_height;
350 else
351 // not enough space, make top aligned
352 wp->w_winrow = wp->w_wantline + 1;
353 }
354
268 wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer); 355 wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer);
269 } 356 }
270 357
271 /* 358 /*
272 * popup_create({text}, {options}) 359 * popup_create({text}, {options})
302 // Create the window and buffer. 389 // Create the window and buffer.
303 wp = win_alloc_popup_win(); 390 wp = win_alloc_popup_win();
304 if (wp == NULL) 391 if (wp == NULL)
305 return; 392 return;
306 rettv->vval.v_number = wp->w_id; 393 rettv->vval.v_number = wp->w_id;
307 wp->w_p_wrap = TRUE; // 'wrap' is default on 394 wp->w_popup_pos = POPPOS_TOPLEFT;
308 395
309 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY); 396 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY);
310 if (buf == NULL) 397 if (buf == NULL)
311 return; 398 return;
312 ml_open(buf); 399 ml_open(buf);
320 (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0); 407 (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
321 buf->b_p_ul = -1; // no undo 408 buf->b_p_ul = -1; // no undo
322 buf->b_p_swf = FALSE; // no swap file 409 buf->b_p_swf = FALSE; // no swap file
323 buf->b_p_bl = FALSE; // unlisted buffer 410 buf->b_p_bl = FALSE; // unlisted buffer
324 buf->b_locked = TRUE; 411 buf->b_locked = TRUE;
412 wp->w_p_wrap = TRUE; // 'wrap' is default on
413
325 // Avoid that 'buftype' is reset when this buffer is entered. 414 // Avoid that 'buftype' is reset when this buffer is entered.
326 buf->b_p_initialized = TRUE; 415 buf->b_p_initialized = TRUE;
327 416
328 nr = (int)dict_get_number(d, (char_u *)"tab"); 417 nr = (int)dict_get_number(d, (char_u *)"tab");
329 if (nr == 0) 418 if (nr == 0)
576 wp->w_minheight = nr; 665 wp->w_minheight = nr;
577 if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0) 666 if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0)
578 wp->w_maxwidth = nr; 667 wp->w_maxwidth = nr;
579 if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0) 668 if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0)
580 wp->w_maxheight = nr; 669 wp->w_maxheight = nr;
581 if ((nr = dict_get_number(d, (char_u *)"line")) > 0) 670 get_pos_options(wp, d);
582 wp->w_wantline = nr;
583 if ((nr = dict_get_number(d, (char_u *)"col")) > 0)
584 wp->w_wantcol = nr;
585 // TODO: "pos"
586 671
587 if (wp->w_winrow + wp->w_height >= cmdline_row) 672 if (wp->w_winrow + wp->w_height >= cmdline_row)
588 clear_cmdline = TRUE; 673 clear_cmdline = TRUE;
589 popup_adjust_position(wp); 674 popup_adjust_position(wp);
590 redraw_all_later(NOT_VALID); 675 redraw_all_later(NOT_VALID);
591 } 676 }
592 677
593 /* 678 /*
594 * popup_getposition({id}) 679 * popup_getpos({id})
595 */ 680 */
596 void 681 void
597 f_popup_getposition(typval_T *argvars, typval_T *rettv) 682 f_popup_getpos(typval_T *argvars, typval_T *rettv)
598 { 683 {
599 dict_T *dict; 684 dict_T *dict;
600 int id = (int)tv_get_number(argvars); 685 int id = (int)tv_get_number(argvars);
601 win_T *wp = find_popup_win(id); 686 win_T *wp = find_popup_win(id);
602 687
621 f_popup_getoptions(typval_T *argvars, typval_T *rettv) 706 f_popup_getoptions(typval_T *argvars, typval_T *rettv)
622 { 707 {
623 dict_T *dict; 708 dict_T *dict;
624 int id = (int)tv_get_number(argvars); 709 int id = (int)tv_get_number(argvars);
625 win_T *wp = find_popup_win(id); 710 win_T *wp = find_popup_win(id);
711 int i;
626 712
627 if (rettv_dict_alloc(rettv) == OK) 713 if (rettv_dict_alloc(rettv) == OK)
628 { 714 {
629 if (wp == NULL) 715 if (wp == NULL)
630 return; 716 return;
635 dict_add_number(dict, "minwidth", wp->w_minwidth); 721 dict_add_number(dict, "minwidth", wp->w_minwidth);
636 dict_add_number(dict, "minheight", wp->w_minheight); 722 dict_add_number(dict, "minheight", wp->w_minheight);
637 dict_add_number(dict, "maxheight", wp->w_maxheight); 723 dict_add_number(dict, "maxheight", wp->w_maxheight);
638 dict_add_number(dict, "maxwidth", wp->w_maxwidth); 724 dict_add_number(dict, "maxwidth", wp->w_maxwidth);
639 dict_add_number(dict, "zindex", wp->w_zindex); 725 dict_add_number(dict, "zindex", wp->w_zindex);
726
727 for (i = 0; i < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
728 ++i)
729 if (wp->w_popup_pos == poppos_entries[i].pp_val)
730 {
731 dict_add_string(dict, "pos",
732 (char_u *)poppos_entries[i].pp_name);
733 break;
734 }
735
640 # if defined(FEAT_TIMERS) 736 # if defined(FEAT_TIMERS)
641 dict_add_number(dict, "time", wp->w_popup_timer != NULL 737 dict_add_number(dict, "time", wp->w_popup_timer != NULL
642 ? (long)wp->w_popup_timer->tr_interval : 0L); 738 ? (long)wp->w_popup_timer->tr_interval : 0L);
643 # endif 739 # endif
644 } 740 }