mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
floats: add borders (MS-DOS MODE)
This commit is contained in:
parent
e5cfc7f3a0
commit
243820ebd0
@ -1645,6 +1645,20 @@ bool api_object_to_bool(Object obj, const char *what,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int object_to_hl_id(Object obj, const char *what, Error *err)
|
||||||
|
{
|
||||||
|
if (obj.type == kObjectTypeString) {
|
||||||
|
String str = obj.data.string;
|
||||||
|
return str.size ? syn_check_group((char_u *)str.data, (int)str.size) : 0;
|
||||||
|
} else if (obj.type == kObjectTypeInteger) {
|
||||||
|
return (int)obj.data.integer;
|
||||||
|
} else {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"%s is not a valid highlight", what);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HlMessage parse_hl_msg(Array chunks, Error *err)
|
HlMessage parse_hl_msg(Array chunks, Error *err)
|
||||||
{
|
{
|
||||||
HlMessage hl_msg = KV_INITIAL_VALUE;
|
HlMessage hl_msg = KV_INITIAL_VALUE;
|
||||||
@ -1768,6 +1782,91 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
schar_T chars[8];
|
||||||
|
} defaults[] = {
|
||||||
|
{ "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" } },
|
||||||
|
{ "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" } },
|
||||||
|
{ NULL, { { NUL } } },
|
||||||
|
};
|
||||||
|
|
||||||
|
schar_T *chars = fconfig->border_chars;
|
||||||
|
int *hl_ids = fconfig->border_hl_ids;
|
||||||
|
|
||||||
|
fconfig->border = true;
|
||||||
|
|
||||||
|
if (style.type == kObjectTypeArray) {
|
||||||
|
Array arr = style.data.array;
|
||||||
|
size_t size = arr.size;
|
||||||
|
if (!size || size > 8 || (size & (size-1))) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"invalid number of border chars");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
Object iytem = arr.items[i];
|
||||||
|
String string = NULL_STRING;
|
||||||
|
int hl_id = 0;
|
||||||
|
if (iytem.type == kObjectTypeArray) {
|
||||||
|
Array iarr = iytem.data.array;
|
||||||
|
if (!iarr.size || iarr.size > 2) {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "invalid border char");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iarr.items[0].type != kObjectTypeString) {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "invalid border char");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string = iarr.items[0].data.string;
|
||||||
|
if (iarr.size == 2) {
|
||||||
|
hl_id = object_to_hl_id(iarr.items[1], "border char highlight", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (iytem.type == kObjectTypeString) {
|
||||||
|
string = iytem.data.string;
|
||||||
|
} else {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "invalid border char");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.size
|
||||||
|
|| mb_string2cells_len((char_u *)string.data, string.size) != 1) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"border chars must be one cell");
|
||||||
|
}
|
||||||
|
size_t len = MIN(string.size, sizeof(*chars)-1);
|
||||||
|
memcpy(chars[i], string.data, len);
|
||||||
|
chars[i][len] = NUL;
|
||||||
|
hl_ids[i] = hl_id;
|
||||||
|
}
|
||||||
|
while (size < 8) {
|
||||||
|
memcpy(chars+size, chars, sizeof(*chars) * size);
|
||||||
|
memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size);
|
||||||
|
size <<= 1;
|
||||||
|
}
|
||||||
|
} else if (style.type == kObjectTypeString) {
|
||||||
|
String str = style.data.string;
|
||||||
|
if (str.size == 0 || strequal(str.data, "none")) {
|
||||||
|
fconfig->border = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; defaults[i].name; i++) {
|
||||||
|
if (strequal(str.data, defaults[i].name)) {
|
||||||
|
memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars));
|
||||||
|
memset(hl_ids, 0, 8 * sizeof(*hl_ids));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"invalid border style \"%s\"", str.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
|
bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
|
||||||
Error *err)
|
Error *err)
|
||||||
{
|
{
|
||||||
@ -1890,7 +1989,7 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(key, "border")) {
|
} else if (!strcmp(key, "border")) {
|
||||||
fconfig->border = api_object_to_bool(val, "border", false, err);
|
parse_border_style(val, fconfig, err);
|
||||||
if (ERROR_SET(err)) {
|
if (ERROR_SET(err)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1416,6 +1416,25 @@ void nvim_chan_send(Integer chan, String data, Error *err)
|
|||||||
/// end-of-buffer region is hidden by setting `eob` flag of
|
/// end-of-buffer region is hidden by setting `eob` flag of
|
||||||
/// 'fillchars' to a space char, and clearing the
|
/// 'fillchars' to a space char, and clearing the
|
||||||
/// |EndOfBuffer| region in 'winhighlight'.
|
/// |EndOfBuffer| region in 'winhighlight'.
|
||||||
|
/// - `border`: style of (optional) window border. This can either be a string
|
||||||
|
/// or an array. the string values are:
|
||||||
|
/// - "none" No border. This is the default
|
||||||
|
/// - "single" a single line box
|
||||||
|
/// - "double" a double line box
|
||||||
|
/// If it is an array it should be an array of eight items or any divisor of
|
||||||
|
/// eight. The array will specifify the eight chars building up the border
|
||||||
|
/// in a clockwise fashion starting with the top-left corner. As, an
|
||||||
|
/// example, the double box style could be specified as:
|
||||||
|
/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ]
|
||||||
|
/// if the number of chars are less than eight, they will be repeated. Thus
|
||||||
|
/// an ASCII border could be specified as:
|
||||||
|
/// [ "/", "-", "\\", "|" ]
|
||||||
|
/// or all chars the same as:
|
||||||
|
/// [ "x" ]
|
||||||
|
/// By default `FloatBorder` highlight is used which links to `VertSplit`
|
||||||
|
/// when not defined. It could also be specified by character:
|
||||||
|
/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ]
|
||||||
|
///
|
||||||
/// @param[out] err Error details, if any
|
/// @param[out] err Error details, if any
|
||||||
///
|
///
|
||||||
/// @return Window handle, or 0 on error
|
/// @return Window handle, or 0 on error
|
||||||
|
@ -1079,6 +1079,10 @@ typedef struct {
|
|||||||
bool external;
|
bool external;
|
||||||
bool focusable;
|
bool focusable;
|
||||||
WinStyle style;
|
WinStyle style;
|
||||||
|
bool border;
|
||||||
|
schar_T border_chars[8];
|
||||||
|
int border_hl_ids[8];
|
||||||
|
int border_attr[8];
|
||||||
} FloatConfig;
|
} FloatConfig;
|
||||||
|
|
||||||
#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
|
#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
|
||||||
@ -1256,6 +1260,11 @@ struct window_S {
|
|||||||
int w_height_request;
|
int w_height_request;
|
||||||
int w_width_request;
|
int w_width_request;
|
||||||
|
|
||||||
|
int w_border_adj;
|
||||||
|
// outer size of window grid, including border
|
||||||
|
int w_height_outer;
|
||||||
|
int w_width_outer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* === start of cached values ====
|
* === start of cached values ====
|
||||||
*/
|
*/
|
||||||
@ -1331,7 +1340,8 @@ struct window_S {
|
|||||||
// w_redr_type is REDRAW_TOP
|
// w_redr_type is REDRAW_TOP
|
||||||
linenr_T w_redraw_top; // when != 0: first line needing redraw
|
linenr_T w_redraw_top; // when != 0: first line needing redraw
|
||||||
linenr_T w_redraw_bot; // when != 0: last line needing redraw
|
linenr_T w_redraw_bot; // when != 0: last line needing redraw
|
||||||
int w_redr_status; // if TRUE status line must be redrawn
|
bool w_redr_status; // if true status line must be redrawn
|
||||||
|
bool w_redr_border; // if true border must be redrawn
|
||||||
|
|
||||||
// remember what is shown in the ruler for this window (if 'ruler' set)
|
// remember what is shown in the ruler for this window (if 'ruler' set)
|
||||||
pos_T w_ru_cursor; // cursor position shown in ruler
|
pos_T w_ru_cursor; // cursor position shown in ruler
|
||||||
|
@ -8501,7 +8501,7 @@ static bool tv_is_luafunc(typval_T *tv)
|
|||||||
int check_luafunc_name(const char *str, bool paren)
|
int check_luafunc_name(const char *str, bool paren)
|
||||||
{
|
{
|
||||||
const char *p = str;
|
const char *p = str;
|
||||||
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.') {
|
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.' || *p == '\'') {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
if (*p != (paren ? '(' : NUL)) {
|
if (*p != (paren ? '(' : NUL)) {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "nvim/types.h"
|
#include "nvim/types.h"
|
||||||
|
|
||||||
#define MAX_MCO 6 // maximum value for 'maxcombine'
|
#define MAX_MCO 6 // fixed value for 'maxcombine'
|
||||||
|
|
||||||
// The characters and attributes drawn on grids.
|
// The characters and attributes drawn on grids.
|
||||||
typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
|
typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
|
||||||
|
@ -341,6 +341,17 @@ void update_window_hl(win_T *wp, bool invalid)
|
|||||||
}
|
}
|
||||||
wp->w_hl_attrs[hlf] = attr;
|
wp->w_hl_attrs[hlf] = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wp->w_floating && wp->w_float_config.border) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
int attr = wp->w_hl_attrs[HLF_BORDER];
|
||||||
|
if (wp->w_float_config.border_hl_ids[i]) {
|
||||||
|
attr = hl_get_ui_attr(HLF_BORDER, wp->w_float_config.border_hl_ids[i],
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
wp->w_float_config.border_attr[i] = attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets HL_UNDERLINE highlight.
|
/// Gets HL_UNDERLINE highlight.
|
||||||
|
@ -101,6 +101,7 @@ typedef enum {
|
|||||||
, HLF_MSGSEP // message separator line
|
, HLF_MSGSEP // message separator line
|
||||||
, HLF_NFLOAT // Floating window
|
, HLF_NFLOAT // Floating window
|
||||||
, HLF_MSG // Message area
|
, HLF_MSG // Message area
|
||||||
|
, HLF_BORDER // Floating window border
|
||||||
, HLF_COUNT // MUST be the last one
|
, HLF_COUNT // MUST be the last one
|
||||||
} hlf_T;
|
} hlf_T;
|
||||||
|
|
||||||
@ -155,6 +156,7 @@ EXTERN const char *hlf_names[] INIT(= {
|
|||||||
[HLF_MSGSEP] = "MsgSeparator",
|
[HLF_MSGSEP] = "MsgSeparator",
|
||||||
[HLF_NFLOAT] = "NormalFloat",
|
[HLF_NFLOAT] = "NormalFloat",
|
||||||
[HLF_MSG] = "MsgArea",
|
[HLF_MSG] = "MsgArea",
|
||||||
|
[HLF_BORDER] = "FloatBorder",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -571,11 +571,12 @@ size_t mb_string2cells(const char_u *str)
|
|||||||
/// @param size maximum length of string. It will terminate on earlier NUL.
|
/// @param size maximum length of string. It will terminate on earlier NUL.
|
||||||
/// @return The number of cells occupied by string `str`
|
/// @return The number of cells occupied by string `str`
|
||||||
size_t mb_string2cells_len(const char_u *str, size_t size)
|
size_t mb_string2cells_len(const char_u *str, size_t size)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
size_t clen = 0;
|
size_t clen = 0;
|
||||||
|
|
||||||
for (const char_u *p = str; *p != NUL && p < str+size;
|
for (const char_u *p = str; *p != NUL && p < str+size;
|
||||||
p += utf_ptr2len_len(p, size+(p-str))) {
|
p += utfc_ptr2len_len(p, size+(p-str))) {
|
||||||
clen += utf_ptr2cells(p);
|
clen += utf_ptr2cells(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,8 +472,8 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
|
|||||||
win_T *wp = get_win_by_grid_handle(*gridp);
|
win_T *wp = get_win_by_grid_handle(*gridp);
|
||||||
if (wp && wp->w_grid_alloc.chars
|
if (wp && wp->w_grid_alloc.chars
|
||||||
&& !(wp->w_floating && !wp->w_float_config.focusable)) {
|
&& !(wp->w_floating && !wp->w_float_config.focusable)) {
|
||||||
*rowp = MIN(*rowp, wp->w_grid.Rows-1);
|
*rowp = MIN(*rowp-wp->w_grid.row_offset, wp->w_grid.Rows-1);
|
||||||
*colp = MIN(*colp, wp->w_grid.Columns-1);
|
*colp = MIN(*colp-wp->w_grid.col_offset, wp->w_grid.Columns-1);
|
||||||
return wp;
|
return wp;
|
||||||
}
|
}
|
||||||
} else if (*gridp == 0) {
|
} else if (*gridp == 0) {
|
||||||
@ -483,8 +483,8 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*gridp = grid->handle;
|
*gridp = grid->handle;
|
||||||
*rowp -= grid->comp_row;
|
*rowp -= grid->comp_row+wp->w_grid.row_offset;
|
||||||
*colp -= grid->comp_col;
|
*colp -= grid->comp_col+wp->w_grid.col_offset;
|
||||||
return wp;
|
return wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4287,7 +4287,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
|
|||||||
// 'floatblend'
|
// 'floatblend'
|
||||||
curwin->w_p_winbl = MAX(MIN(curwin->w_p_winbl, 100), 0);
|
curwin->w_p_winbl = MAX(MIN(curwin->w_p_winbl, 100), 0);
|
||||||
curwin->w_hl_needs_update = true;
|
curwin->w_hl_needs_update = true;
|
||||||
curwin->w_grid.blending = curwin->w_p_winbl > 0;
|
curwin->w_grid_alloc.blending = curwin->w_p_winbl > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5800,7 +5800,7 @@ void didset_window_options(win_T *wp)
|
|||||||
set_chars_option(wp, &wp->w_p_fcs, true);
|
set_chars_option(wp, &wp->w_p_fcs, true);
|
||||||
set_chars_option(wp, &wp->w_p_lcs, true);
|
set_chars_option(wp, &wp->w_p_lcs, true);
|
||||||
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
|
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
|
||||||
wp->w_grid.blending = wp->w_p_winbl > 0;
|
wp->w_grid_alloc.blending = wp->w_p_winbl > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed,
|
|||||||
|
|
||||||
pum_anchor_grid = (int)curwin->w_grid.target->handle;
|
pum_anchor_grid = (int)curwin->w_grid.target->handle;
|
||||||
if (!ui_has(kUIMultigrid)) {
|
if (!ui_has(kUIMultigrid)) {
|
||||||
|
pum_anchor_grid = (int)default_grid.handle;
|
||||||
pum_win_row += curwin->w_winrow;
|
pum_win_row += curwin->w_winrow;
|
||||||
cursor_col += curwin->w_wincol;
|
cursor_col += curwin->w_wincol;
|
||||||
}
|
}
|
||||||
|
@ -587,6 +587,13 @@ int update_screen(int type)
|
|||||||
wp->w_redr_type = NOT_VALID;
|
wp->w_redr_type = NOT_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reallocate grid if needed.
|
||||||
|
win_grid_alloc(wp);
|
||||||
|
|
||||||
|
if (wp->w_redr_border || wp->w_redr_type >= NOT_VALID) {
|
||||||
|
win_redr_border(wp);
|
||||||
|
}
|
||||||
|
|
||||||
if (wp->w_redr_type != 0) {
|
if (wp->w_redr_type != 0) {
|
||||||
if (!did_one) {
|
if (!did_one) {
|
||||||
did_one = TRUE;
|
did_one = TRUE;
|
||||||
@ -774,8 +781,6 @@ static void win_update(win_T *wp, Providers *providers)
|
|||||||
|
|
||||||
type = wp->w_redr_type;
|
type = wp->w_redr_type;
|
||||||
|
|
||||||
win_grid_alloc(wp);
|
|
||||||
|
|
||||||
if (type >= NOT_VALID) {
|
if (type >= NOT_VALID) {
|
||||||
wp->w_redr_status = true;
|
wp->w_redr_status = true;
|
||||||
wp->w_lines_valid = 0;
|
wp->w_lines_valid = 0;
|
||||||
@ -5411,6 +5416,46 @@ theend:
|
|||||||
entered = FALSE;
|
entered = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void win_redr_border(win_T *wp)
|
||||||
|
{
|
||||||
|
wp->w_redr_border = false;
|
||||||
|
if (!(wp->w_floating && wp->w_float_config.border)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenGrid *grid = &wp->w_grid_alloc;
|
||||||
|
|
||||||
|
schar_T *chars = wp->w_float_config.border_chars;
|
||||||
|
int *attrs = wp->w_float_config.border_attr;
|
||||||
|
|
||||||
|
int endrow = grid->Rows-1, endcol = grid->Columns-1;
|
||||||
|
|
||||||
|
grid_puts_line_start(grid, 0);
|
||||||
|
grid_put_schar(grid, 0, 0, chars[0], attrs[0]);
|
||||||
|
for (int i = 1; i < endcol; i++) {
|
||||||
|
grid_put_schar(grid, 0, i, chars[1], attrs[1]);
|
||||||
|
}
|
||||||
|
grid_put_schar(grid, 0, endcol, chars[2], attrs[2]);
|
||||||
|
grid_puts_line_flush(false);
|
||||||
|
|
||||||
|
for (int i = 1; i < endrow; i++) {
|
||||||
|
grid_puts_line_start(grid, i);
|
||||||
|
grid_put_schar(grid, i, 0, chars[7], attrs[7]);
|
||||||
|
grid_puts_line_flush(false);
|
||||||
|
grid_puts_line_start(grid, i);
|
||||||
|
grid_put_schar(grid, i, endcol, chars[3], attrs[3]);
|
||||||
|
grid_puts_line_flush(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
grid_puts_line_start(grid, endrow);
|
||||||
|
grid_put_schar(grid, endrow, 0, chars[6], attrs[6]);
|
||||||
|
for (int i = 1; i < endcol; i++) {
|
||||||
|
grid_put_schar(grid, endrow, i, chars[5], attrs[5]);
|
||||||
|
}
|
||||||
|
grid_put_schar(grid, endrow, endcol, chars[4], attrs[4]);
|
||||||
|
grid_puts_line_flush(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Low-level functions to manipulate invidual character cells on the
|
// Low-level functions to manipulate invidual character cells on the
|
||||||
// screen grid.
|
// screen grid.
|
||||||
|
|
||||||
@ -5548,6 +5593,20 @@ void grid_puts_line_start(ScreenGrid *grid, int row)
|
|||||||
put_dirty_grid = grid;
|
put_dirty_grid = grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr)
|
||||||
|
{
|
||||||
|
assert(put_dirty_row == row);
|
||||||
|
unsigned int off = grid->line_offset[row] + col;
|
||||||
|
if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) {
|
||||||
|
schar_copy(grid->chars[off], schar);
|
||||||
|
grid->attrs[off] = attr;
|
||||||
|
|
||||||
|
put_dirty_first = MIN(put_dirty_first, col);
|
||||||
|
// TODO(bfredl): Y U NO DOUBLEWIDTH?
|
||||||
|
put_dirty_last = MAX(put_dirty_last, col+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
|
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
|
||||||
/// a NUL.
|
/// a NUL.
|
||||||
void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
|
void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
|
||||||
@ -6143,6 +6202,8 @@ void win_grid_alloc(win_T *wp)
|
|||||||
|
|
||||||
int rows = wp->w_height_inner;
|
int rows = wp->w_height_inner;
|
||||||
int cols = wp->w_width_inner;
|
int cols = wp->w_width_inner;
|
||||||
|
int total_rows = wp->w_height_outer;
|
||||||
|
int total_cols = wp->w_width_outer;
|
||||||
|
|
||||||
bool want_allocation = ui_has(kUIMultigrid) || wp->w_floating;
|
bool want_allocation = ui_has(kUIMultigrid) || wp->w_floating;
|
||||||
bool has_allocation = (grid_allocated->chars != NULL);
|
bool has_allocation = (grid_allocated->chars != NULL);
|
||||||
@ -6153,14 +6214,16 @@ void win_grid_alloc(win_T *wp)
|
|||||||
wp->w_lines = xcalloc(rows+1, sizeof(wline_T));
|
wp->w_lines = xcalloc(rows+1, sizeof(wline_T));
|
||||||
}
|
}
|
||||||
|
|
||||||
int total_rows = rows, total_cols = cols;
|
|
||||||
|
|
||||||
int was_resized = false;
|
int was_resized = false;
|
||||||
if (want_allocation && (!has_allocation
|
if (want_allocation && (!has_allocation
|
||||||
|| grid_allocated->Rows != total_rows
|
|| grid_allocated->Rows != total_rows
|
||||||
|| grid_allocated->Columns != total_cols)) {
|
|| grid_allocated->Columns != total_cols)) {
|
||||||
grid_alloc(grid_allocated, total_rows, total_cols, wp->w_grid_alloc.valid, false);
|
grid_alloc(grid_allocated, total_rows, total_cols,
|
||||||
|
wp->w_grid_alloc.valid, false);
|
||||||
grid_allocated->valid = true;
|
grid_allocated->valid = true;
|
||||||
|
if (wp->w_border_adj) {
|
||||||
|
wp->w_redr_border = true;
|
||||||
|
}
|
||||||
was_resized = true;
|
was_resized = true;
|
||||||
} else if (!want_allocation && has_allocation) {
|
} else if (!want_allocation && has_allocation) {
|
||||||
// Single grid mode, all rendering will be redirected to default_grid.
|
// Single grid mode, all rendering will be redirected to default_grid.
|
||||||
@ -6178,8 +6241,8 @@ void win_grid_alloc(win_T *wp)
|
|||||||
|
|
||||||
if (want_allocation) {
|
if (want_allocation) {
|
||||||
grid->target = grid_allocated;
|
grid->target = grid_allocated;
|
||||||
grid->row_offset = 0;
|
grid->row_offset = wp->w_border_adj;
|
||||||
grid->col_offset = 0;
|
grid->col_offset = wp->w_border_adj;
|
||||||
} else {
|
} else {
|
||||||
grid->target = &default_grid;
|
grid->target = &default_grid;
|
||||||
grid->row_offset = wp->w_winrow;
|
grid->row_offset = wp->w_winrow;
|
||||||
@ -6191,7 +6254,8 @@ void win_grid_alloc(win_T *wp)
|
|||||||
// - screen_resize was called and all grid sizes must be sent
|
// - screen_resize was called and all grid sizes must be sent
|
||||||
// - the UI wants multigrid event (necessary)
|
// - the UI wants multigrid event (necessary)
|
||||||
if ((send_grid_resize || was_resized) && want_allocation) {
|
if ((send_grid_resize || was_resized) && want_allocation) {
|
||||||
ui_call_grid_resize(grid_allocated->handle, grid_allocated->Columns, grid_allocated->Rows);
|
ui_call_grid_resize(grid_allocated->handle,
|
||||||
|
grid_allocated->Columns, grid_allocated->Rows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6046,6 +6046,7 @@ static const char *highlight_init_both[] = {
|
|||||||
"default link Whitespace NonText",
|
"default link Whitespace NonText",
|
||||||
"default link MsgSeparator StatusLine",
|
"default link MsgSeparator StatusLine",
|
||||||
"default link NormalFloat Pmenu",
|
"default link NormalFloat Pmenu",
|
||||||
|
"default link FloatBorder VertSplit",
|
||||||
"RedrawDebugNormal cterm=reverse gui=reverse",
|
"RedrawDebugNormal cterm=reverse gui=reverse",
|
||||||
"RedrawDebugClear ctermbg=Yellow guibg=Yellow",
|
"RedrawDebugClear ctermbg=Yellow guibg=Yellow",
|
||||||
"RedrawDebugComposed ctermbg=Green guibg=Green",
|
"RedrawDebugComposed ctermbg=Green guibg=Green",
|
||||||
|
@ -605,6 +605,7 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
|
|||||||
wp->w_vsep_width = 0;
|
wp->w_vsep_width = 0;
|
||||||
|
|
||||||
win_config_float(wp, fconfig);
|
win_config_float(wp, fconfig);
|
||||||
|
win_set_inner_size(wp);
|
||||||
wp->w_pos_changed = true;
|
wp->w_pos_changed = true;
|
||||||
redraw_later(wp, VALID);
|
redraw_later(wp, VALID);
|
||||||
return wp;
|
return wp;
|
||||||
@ -667,6 +668,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool change_external = fconfig.external != wp->w_float_config.external;
|
bool change_external = fconfig.external != wp->w_float_config.external;
|
||||||
|
bool change_border = fconfig.border != wp->w_float_config.border;
|
||||||
|
|
||||||
wp->w_float_config = fconfig;
|
wp->w_float_config = fconfig;
|
||||||
|
|
||||||
if (!ui_has(kUIMultigrid)) {
|
if (!ui_has(kUIMultigrid)) {
|
||||||
@ -676,11 +679,18 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
|
|||||||
|
|
||||||
win_set_inner_size(wp);
|
win_set_inner_size(wp);
|
||||||
must_redraw = MAX(must_redraw, VALID);
|
must_redraw = MAX(must_redraw, VALID);
|
||||||
|
|
||||||
wp->w_pos_changed = true;
|
wp->w_pos_changed = true;
|
||||||
if (change_external) {
|
if (change_external || change_border) {
|
||||||
wp->w_hl_needs_update = true;
|
wp->w_hl_needs_update = true;
|
||||||
redraw_later(wp, NOT_VALID);
|
redraw_later(wp, NOT_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// changing border style while keeping border only requires redrawing border
|
||||||
|
if (fconfig.border) {
|
||||||
|
wp->w_redr_border = true;
|
||||||
|
redraw_later(wp, VALID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void win_check_anchored_floats(win_T *win)
|
void win_check_anchored_floats(win_T *win)
|
||||||
@ -743,8 +753,8 @@ void ui_ext_win_position(win_T *wp)
|
|||||||
}
|
}
|
||||||
if (ui_has(kUIMultigrid)) {
|
if (ui_has(kUIMultigrid)) {
|
||||||
String anchor = cstr_to_string(float_anchor_str[c.anchor]);
|
String anchor = cstr_to_string(float_anchor_str[c.anchor]);
|
||||||
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor, grid->handle,
|
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor,
|
||||||
row, col, c.focusable);
|
grid->handle, row, col, c.focusable);
|
||||||
} else {
|
} else {
|
||||||
// TODO(bfredl): ideally, compositor should work like any multigrid UI
|
// TODO(bfredl): ideally, compositor should work like any multigrid UI
|
||||||
// and use standard win_pos events.
|
// and use standard win_pos events.
|
||||||
@ -759,8 +769,8 @@ void ui_ext_win_position(win_T *wp)
|
|||||||
wp->w_wincol = comp_col;
|
wp->w_wincol = comp_col;
|
||||||
bool valid = (wp->w_redr_type == 0);
|
bool valid = (wp->w_redr_type == 0);
|
||||||
bool on_top = (curwin == wp) || !curwin->w_floating;
|
bool on_top = (curwin == wp) || !curwin->w_floating;
|
||||||
ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col, wp->w_height,
|
ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col,
|
||||||
wp->w_width, valid, on_top);
|
wp->w_height_outer, wp->w_width_outer, valid, on_top);
|
||||||
ui_check_cursor_grid(wp->w_grid_alloc.handle);
|
ui_check_cursor_grid(wp->w_grid_alloc.handle);
|
||||||
wp->w_grid_alloc.focusable = wp->w_float_config.focusable;
|
wp->w_grid_alloc.focusable = wp->w_float_config.focusable;
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
@ -3515,9 +3525,11 @@ void win_init_size(void)
|
|||||||
{
|
{
|
||||||
firstwin->w_height = ROWS_AVAIL;
|
firstwin->w_height = ROWS_AVAIL;
|
||||||
firstwin->w_height_inner = firstwin->w_height;
|
firstwin->w_height_inner = firstwin->w_height;
|
||||||
|
firstwin->w_height_outer = firstwin->w_height;
|
||||||
topframe->fr_height = ROWS_AVAIL;
|
topframe->fr_height = ROWS_AVAIL;
|
||||||
firstwin->w_width = Columns;
|
firstwin->w_width = Columns;
|
||||||
firstwin->w_width_inner = firstwin->w_width;
|
firstwin->w_width_inner = firstwin->w_width;
|
||||||
|
firstwin->w_width_outer = firstwin->w_width;
|
||||||
topframe->fr_width = Columns;
|
topframe->fr_width = Columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5714,6 +5726,10 @@ void win_set_inner_size(win_T *wp)
|
|||||||
if (wp->w_buffer->terminal) {
|
if (wp->w_buffer->terminal) {
|
||||||
terminal_check_size(wp->w_buffer->terminal);
|
terminal_check_size(wp->w_buffer->terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wp->w_border_adj = wp->w_floating && wp->w_float_config.border ? 1 : 0;
|
||||||
|
wp->w_height_outer = wp->w_height_inner + 2 * wp->w_border_adj;
|
||||||
|
wp->w_width_outer = wp->w_width_inner + 2 * wp->w_border_adj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the width of a window.
|
/// Set the width of a window.
|
||||||
|
@ -212,10 +212,10 @@ describe('ui/cursor', function()
|
|||||||
if m.blinkwait then m.blinkwait = 700 end
|
if m.blinkwait then m.blinkwait = 700 end
|
||||||
end
|
end
|
||||||
if m.hl_id then
|
if m.hl_id then
|
||||||
m.hl_id = 55
|
m.hl_id = 56
|
||||||
m.attr = {background = Screen.colors.DarkGray}
|
m.attr = {background = Screen.colors.DarkGray}
|
||||||
end
|
end
|
||||||
if m.id_lm then m.id_lm = 56 end
|
if m.id_lm then m.id_lm = 57 end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Assert the new expectation.
|
-- Assert the new expectation.
|
||||||
|
@ -14,7 +14,7 @@ local funcs = helpers.funcs
|
|||||||
local run = helpers.run
|
local run = helpers.run
|
||||||
local pcall_err = helpers.pcall_err
|
local pcall_err = helpers.pcall_err
|
||||||
|
|
||||||
describe('floatwin', function()
|
describe('float window', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear()
|
clear()
|
||||||
end)
|
end)
|
||||||
@ -131,7 +131,7 @@ describe('floatwin', function()
|
|||||||
local screen
|
local screen
|
||||||
before_each(function()
|
before_each(function()
|
||||||
screen = Screen.new(40,7)
|
screen = Screen.new(40,7)
|
||||||
screen:attach({ext_multigrid=multigrid})
|
screen:attach {ext_multigrid=multigrid}
|
||||||
screen:set_default_attr_ids(attrs)
|
screen:set_default_attr_ids(attrs)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -595,6 +595,185 @@ describe('floatwin', function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can have border', function()
|
||||||
|
local buf = meths.create_buf(false, false)
|
||||||
|
meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
|
||||||
|
' BORDAA '})
|
||||||
|
local win = meths.open_win(buf, false, {relative='editor', width=9, height=2, row=2, col=5, border="double"})
|
||||||
|
|
||||||
|
if multigrid then
|
||||||
|
screen:expect{grid=[[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 5
|
||||||
|
{5:╔═════════╗}|
|
||||||
|
{5:║}{1: halloj! }{5:║}|
|
||||||
|
{5:║}{1: BORDAA }{5:║}|
|
||||||
|
{5:╚═════════╝}|
|
||||||
|
]], float_pos={
|
||||||
|
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
[5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
}}
|
||||||
|
else
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }{5:╔═════════╗}{0: }|
|
||||||
|
{0:~ }{5:║}{1: halloj! }{5:║}{0: }|
|
||||||
|
{0:~ }{5:║}{1: BORDAA }{5:║}{0: }|
|
||||||
|
{0:~ }{5:╚═════════╝}{0: }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end
|
||||||
|
|
||||||
|
meths.win_set_config(win, {border="single"})
|
||||||
|
|
||||||
|
if multigrid then
|
||||||
|
screen:expect{grid=[[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 5
|
||||||
|
{5:┌─────────┐}|
|
||||||
|
{5:│}{1: halloj! }{5:│}|
|
||||||
|
{5:│}{1: BORDAA }{5:│}|
|
||||||
|
{5:└─────────┘}|
|
||||||
|
]], float_pos={
|
||||||
|
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
[5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
}}
|
||||||
|
else
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }{5:┌─────────┐}{0: }|
|
||||||
|
{0:~ }{5:│}{1: halloj! }{5:│}{0: }|
|
||||||
|
{0:~ }{5:│}{1: BORDAA }{5:│}{0: }|
|
||||||
|
{0:~ }{5:└─────────┘}{0: }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- support: ascii char, UTF-8 char, composed char, highlight per char
|
||||||
|
meths.win_set_config(win, {border={"x", {"å", "ErrorMsg"}, {"\\"}, {"n̈̊", "Search"}}})
|
||||||
|
|
||||||
|
if multigrid then
|
||||||
|
screen:expect{grid=[[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 5
|
||||||
|
{5:xååååååååå\}|
|
||||||
|
{5:n̈̊}{1: halloj! }{5:n̈̊}|
|
||||||
|
{5:n̈̊}{1: BORDAA }{5:n̈̊}|
|
||||||
|
{5:\åååååååååx}|
|
||||||
|
]], float_pos={
|
||||||
|
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
[5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
}}
|
||||||
|
else
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }{5:x}{7:ååååååååå}{5:\}{0: }|
|
||||||
|
{0:~ }{17:n̈̊}{1: halloj! }{17:n̈̊}{0: }|
|
||||||
|
{0:~ }{17:n̈̊}{1: BORDAA }{17:n̈̊}{0: }|
|
||||||
|
{0:~ }{5:\}{7:ååååååååå}{5:x}{0: }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end
|
||||||
|
|
||||||
|
meths.win_set_config(win, {border="none"})
|
||||||
|
if multigrid then
|
||||||
|
screen:expect{grid=[[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[2:----------------------------------------]|
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 5
|
||||||
|
{1: halloj! }|
|
||||||
|
{1: BORDAA }|
|
||||||
|
]], float_pos={
|
||||||
|
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
[5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
|
||||||
|
}}
|
||||||
|
else
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }{1: halloj! }{0: }|
|
||||||
|
{0:~ }{1: BORDAA }{0: }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
it('can have minimum size', function()
|
it('can have minimum size', function()
|
||||||
insert("the background text")
|
insert("the background text")
|
||||||
local buf = meths.create_buf(false, true)
|
local buf = meths.create_buf(false, true)
|
||||||
|
Loading…
Reference in New Issue
Block a user