Skip to content

Commit

Permalink
fix(float): make screen*() functions respect floating windows
Browse files Browse the repository at this point in the history
Resolves neovim#19013.
  • Loading branch information
echasnovski committed Jun 19, 2022
1 parent 7b2b44b commit 2ba7b6c
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 16 deletions.
49 changes: 33 additions & 16 deletions src/nvim/eval/funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include "nvim/tag.h"
#include "nvim/testing.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/version.h"
#include "nvim/vim.h"
Expand Down Expand Up @@ -8037,13 +8038,17 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)

int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
if (row < 0 || row >= default_grid.rows
|| col < 0 || col >= default_grid.cols) {

ScreenGrid *grid = ui_comp_get_grid_at_coord(row, col);
int grid_row = row - grid->comp_row;
int grid_col = col - grid->comp_col;

if (grid_row < 0 || grid_row >= grid->rows
|| grid_col < 0 || grid_col >= grid->cols) {
c = -1;
} else {
ScreenGrid *grid = &default_grid;
screenchar_adjust_grid(&grid, &row, &col);
c = grid->attrs[grid->line_offset[row] + col];
c = grid->attrs[grid->line_offset[grid_row] + grid_col];
}
rettv->vval.v_number = c;
}
Expand All @@ -8055,13 +8060,17 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)

int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
if (row < 0 || row >= default_grid.rows
|| col < 0 || col >= default_grid.cols) {

ScreenGrid *grid = ui_comp_get_grid_at_coord(row, col);
int grid_row = row - grid->comp_row;
int grid_col = col - grid->comp_col;

if (grid_row < 0 || grid_row >= grid->rows
|| grid_col < 0 || grid_col >= grid->cols) {
c = -1;
} else {
ScreenGrid *grid = &default_grid;
screenchar_adjust_grid(&grid, &row, &col);
c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + col]);
c = utf_ptr2char((char *)grid->chars[grid->line_offset[grid_row] + grid_col]);
}
rettv->vval.v_number = c;
}
Expand All @@ -8071,15 +8080,19 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
if (row < 0 || row >= default_grid.rows
|| col < 0 || col >= default_grid.cols) {

ScreenGrid *grid = ui_comp_get_grid_at_coord(row, col);
int grid_row = row - grid->comp_row;
int grid_col = col - grid->comp_col;

if (grid_row < 0 || grid_row >= grid->rows
|| grid_col < 0 || grid_col >= grid->cols) {
tv_list_alloc_ret(rettv, 0);
return;
}
ScreenGrid *grid = &default_grid;
screenchar_adjust_grid(&grid, &row, &col);
int pcc[MAX_MCO];
int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + col], pcc);
int c = utfc_ptr2char(grid->chars[grid->line_offset[grid_row] + grid_col], pcc);
int composing_len = 0;
while (pcc[composing_len] != 0) {
composing_len++;
Expand Down Expand Up @@ -8138,13 +8151,17 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
if (row < 0 || row >= default_grid.rows
|| col < 0 || col >= default_grid.cols) {

ScreenGrid *grid = ui_comp_get_grid_at_coord(row, col);
int grid_row = row - grid->comp_row;
int grid_col = col - grid->comp_col;
if (grid_row < 0 || grid_row >= grid->rows
|| grid_col < 0 || grid_col >= grid->cols) {
return;
}
ScreenGrid *grid = &default_grid;

screenchar_adjust_grid(&grid, &row, &col);
rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + col]);
rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[grid_row] + grid_col]);
}

/// "search()" function
Expand Down
12 changes: 12 additions & 0 deletions src/nvim/ui_compositor.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,18 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
return NULL;
}

ScreenGrid *ui_comp_get_grid_at_coord(int row, int col)
{
for (ssize_t i = (ssize_t)kv_size(layers) - 1; i > 0; i--) {
ScreenGrid *grid = kv_A(layers, i);
if (row >= grid->comp_row && row < grid->comp_row + grid->rows
&& col >= grid->comp_col && col < grid->comp_col + grid->cols) {
return grid;
}
}
return &default_grid;
}

/// Baseline implementation. This is always correct, but we can sometimes
/// do something more efficient (where efficiency means smaller deltas to
/// the downstream UI.)
Expand Down
77 changes: 77 additions & 0 deletions test/functional/vimscript/screenchar_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, meths = helpers.clear, helpers.eq, helpers.meths
local command, funcs = helpers.command, helpers.funcs

local global_helpers = require('test.helpers')
local neq = global_helpers.neq

-- Set up two overlapping floating windows
local setup_floating_windows = function()
local base_opts = {
relative = 'editor',
height = 1,
width = 2,
anchor = 'NW',
style = 'minimal',
border = 'none',
}

local bufnr_1 = meths.create_buf(false, true)
meths.buf_set_lines(bufnr_1, 0, -1, true, { 'aa' })
local opts_1 = global_helpers.tbl_deep_extend('force', { row = 0, col = 0, zindex = 11 }, base_opts)
meths.open_win(bufnr_1, false, opts_1)

local bufnr_2 = meths.create_buf(false, true)
meths.buf_set_lines(bufnr_2, 0, -1, true, { 'bb' })
local opts_2 = global_helpers.tbl_deep_extend('force', { row = 0, col = 1, zindex = 10 }, base_opts)
meths.open_win(bufnr_2, false, opts_2)

command('redraw')
end

before_each(function()
clear()
-- These commands result into visible text `aabc`.
-- `aab` - from floating windows, `c` - from text in regular window.
meths.buf_set_lines(0, 0, -1, true, { 'cccc' })
setup_floating_windows()
end)

describe('screenattr()', function()
it('respects floating windows', function()
local attr_1 = funcs.screenattr(1, 1)
local attr_2 = funcs.screenattr(1, 2)
local attr_3 = funcs.screenattr(1, 3)
local attr_4 = funcs.screenattr(1, 4)
eq(attr_1, attr_2)
eq(attr_1, attr_3)
neq(attr_1, attr_4)
end)
end)

describe('screenchar()', function()
it('respects floating windows', function()
eq(97, funcs.screenchar(1, 1))
eq(97, funcs.screenchar(1, 2))
eq(98, funcs.screenchar(1, 3))
eq(99, funcs.screenchar(1, 4))
end)
end)

describe('screenchars()', function()
it('respects floating windows', function()
eq({ 97 }, funcs.screenchars(1, 1))
eq({ 97 }, funcs.screenchars(1, 2))
eq({ 98 }, funcs.screenchars(1, 3))
eq({ 99 }, funcs.screenchars(1, 4))
end)
end)

describe('screenstring()', function()
it('respects floating windows', function()
eq('a', funcs.screenstring(1, 1))
eq('a', funcs.screenstring(1, 2))
eq('b', funcs.screenstring(1, 3))
eq('c', funcs.screenstring(1, 4))
end)
end)

0 comments on commit 2ba7b6c

Please sign in to comment.