mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
Merge 6d96c4da987694c72f924cbdee7a3fdf5eec9162 into 29b29c6b303c891fa32ac14b0317fa4a342e0418
This commit is contained in:
commit
592181f70d
@ -575,7 +575,7 @@ typedef struct {
|
|||||||
// A line was pushed off the top of the window.
|
// A line was pushed off the top of the window.
|
||||||
// "cells[cols]" contains the cells of that line.
|
// "cells[cols]" contains the cells of that line.
|
||||||
// Return value is unused.
|
// Return value is unused.
|
||||||
int (*sb_pushline)(int cols, const VTermScreenCell *cells, void *user);
|
int (*sb_pushline)(int cols, const VTermScreenCell *cells, const VTermLineInfo *newinfo, void *user);
|
||||||
int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
|
int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
|
||||||
int (*sb_clear)(void* user);
|
int (*sb_clear)(void* user);
|
||||||
} VTermScreenCallbacks;
|
} VTermScreenCallbacks;
|
||||||
|
@ -212,11 +212,13 @@ static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
|
|||||||
static void sb_pushline_from_row(VTermScreen *screen, int row)
|
static void sb_pushline_from_row(VTermScreen *screen, int row)
|
||||||
{
|
{
|
||||||
VTermPos pos;
|
VTermPos pos;
|
||||||
|
const VTermLineInfo *info;
|
||||||
pos.row = row;
|
pos.row = row;
|
||||||
for(pos.col = 0; pos.col < screen->cols; pos.col++)
|
for(pos.col = 0; pos.col < screen->cols; pos.col++)
|
||||||
vterm_screen_get_cell(screen, pos, screen->sb_buffer + pos.col);
|
vterm_screen_get_cell(screen, pos, screen->sb_buffer + pos.col);
|
||||||
|
|
||||||
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
|
info = vterm_state_get_lineinfo(screen->state, row);
|
||||||
|
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, info, screen->cbdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moverect_internal(VTermRect dest, VTermRect src, void *user)
|
static int moverect_internal(VTermRect dest, VTermRect src, void *user)
|
||||||
|
@ -48,10 +48,12 @@ static void erase(VTermState *state, VTermRect rect, int selective)
|
|||||||
if(rect.end_col == state->cols) {
|
if(rect.end_col == state->cols) {
|
||||||
int row;
|
int row;
|
||||||
/* If we're erasing the final cells of any lines, cancel the continuation
|
/* If we're erasing the final cells of any lines, cancel the continuation
|
||||||
* marker on the subsequent line
|
* marker on the subsequent line, and similarly the marker of a fully erased line
|
||||||
*/
|
*/
|
||||||
for(row = rect.start_row + 1; row < rect.end_row + 1 && row < state->rows; row++)
|
for(row = rect.start_row + 1; row < rect.end_row + 1 && row < state->rows; row++)
|
||||||
state->lineinfo[row].continuation = 0;
|
state->lineinfo[row].continuation = 0;
|
||||||
|
if (rect.start_col == 0)
|
||||||
|
state->lineinfo[rect.start_row].continuation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state->callbacks && state->callbacks->erase)
|
if(state->callbacks && state->callbacks->erase)
|
||||||
@ -118,6 +120,7 @@ static void scroll(VTermState *state, VTermRect rect, int downward, int rightwar
|
|||||||
{
|
{
|
||||||
int rows;
|
int rows;
|
||||||
int cols;
|
int cols;
|
||||||
|
int state_scrollrect_success;
|
||||||
if(!downward && !rightward)
|
if(!downward && !rightward)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -133,6 +136,15 @@ static void scroll(VTermState *state, VTermRect rect, int downward, int rightwar
|
|||||||
else if(rightward < -cols)
|
else if(rightward < -cols)
|
||||||
rightward = -cols;
|
rightward = -cols;
|
||||||
|
|
||||||
|
if(state->callbacks && state->callbacks->scrollrect)
|
||||||
|
state_scrollrect_success = (*state->callbacks->scrollrect)(rect, downward, rightward, state->cbdata);
|
||||||
|
else if (state->callbacks)
|
||||||
|
state_scrollrect_success = 0;
|
||||||
|
|
||||||
|
if(state->callbacks && !state_scrollrect_success)
|
||||||
|
vterm_scroll_rect(rect, downward, rightward,
|
||||||
|
state->callbacks->moverect, state->callbacks->erase, state->cbdata);
|
||||||
|
|
||||||
// Update lineinfo if full line
|
// Update lineinfo if full line
|
||||||
if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
|
if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
|
||||||
int height = rect.end_row - rect.start_row - abs(downward);
|
int height = rect.end_row - rect.start_row - abs(downward);
|
||||||
@ -143,25 +155,23 @@ static void scroll(VTermState *state, VTermRect rect, int downward, int rightwar
|
|||||||
memmove(state->lineinfo + rect.start_row,
|
memmove(state->lineinfo + rect.start_row,
|
||||||
state->lineinfo + rect.start_row + downward,
|
state->lineinfo + rect.start_row + downward,
|
||||||
height * sizeof(state->lineinfo[0]));
|
height * sizeof(state->lineinfo[0]));
|
||||||
for(row = rect.end_row - downward; row < rect.end_row; row++)
|
for(row = rect.end_row - downward; row < rect.end_row; row++) {
|
||||||
|
if(state->callbacks && state->callbacks->setlineinfo)
|
||||||
|
(*state->callbacks->setlineinfo)(row, &zeroLineInfo, state->lineinfo + row, state->cbdata);
|
||||||
state->lineinfo[row] = zeroLineInfo;
|
state->lineinfo[row] = zeroLineInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memmove(state->lineinfo + rect.start_row - downward,
|
memmove(state->lineinfo + rect.start_row - downward,
|
||||||
state->lineinfo + rect.start_row,
|
state->lineinfo + rect.start_row,
|
||||||
height * sizeof(state->lineinfo[0]));
|
height * sizeof(state->lineinfo[0]));
|
||||||
for(row = rect.start_row; row < rect.start_row - downward; row++)
|
for(row = rect.start_row; row < rect.start_row - downward; row++) {
|
||||||
|
if(state->callbacks && state->callbacks->setlineinfo)
|
||||||
|
(*state->callbacks->setlineinfo)(row, &zeroLineInfo, state->lineinfo + row, state->cbdata);
|
||||||
state->lineinfo[row] = zeroLineInfo;
|
state->lineinfo[row] = zeroLineInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state->callbacks && state->callbacks->scrollrect)
|
|
||||||
if((*state->callbacks->scrollrect)(rect, downward, rightward, state->cbdata))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(state->callbacks)
|
|
||||||
vterm_scroll_rect(rect, downward, rightward,
|
|
||||||
state->callbacks->moverect, state->callbacks->erase, state->cbdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linefeed(VTermState *state)
|
static void linefeed(VTermState *state)
|
||||||
|
18
src/libvterm/t/70screen_pushline.test
Normal file
18
src/libvterm/t/70screen_pushline.test
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
INIT
|
||||||
|
RESIZE 5,10
|
||||||
|
WANTSTATE
|
||||||
|
WANTSCREEN b
|
||||||
|
|
||||||
|
RESET
|
||||||
|
|
||||||
|
!Spillover text marks continuation on second line
|
||||||
|
PUSH "A"x15
|
||||||
|
PUSH "\r\n"
|
||||||
|
?lineinfo 0 =
|
||||||
|
?lineinfo 1 = cont
|
||||||
|
|
||||||
|
!Continuation mark sent to sb_pushline
|
||||||
|
PUSH "\n"x3
|
||||||
|
sb_pushline 10 = 41 41 41 41 41 41 41 41 41 41
|
||||||
|
PUSH "\n"
|
||||||
|
sb_pushline 10 cont = 41 41 41 41 41
|
@ -590,7 +590,7 @@ static int screen_damage(VTermRect rect, void *user UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int want_screen_scrollback = 0;
|
static int want_screen_scrollback = 0;
|
||||||
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user UNUSED)
|
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, const VTermLineInfo *lineinfo, void *user UNUSED)
|
||||||
{
|
{
|
||||||
int eol;
|
int eol;
|
||||||
int c;
|
int c;
|
||||||
@ -602,7 +602,7 @@ static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user
|
|||||||
while(eol && !cells[eol-1].chars[0])
|
while(eol && !cells[eol-1].chars[0])
|
||||||
eol--;
|
eol--;
|
||||||
|
|
||||||
printf("sb_pushline %d =", cols);
|
printf("sb_pushline %d %s=", cols, lineinfo->continuation ? "cont " : "");
|
||||||
for(c = 0; c < eol; c++)
|
for(c = 0; c < eol; c++)
|
||||||
printf(" %02X", cells[c].chars[0]);
|
printf(" %02X", cells[c].chars[0]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
274
src/terminal.c
274
src/terminal.c
@ -61,9 +61,11 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct sb_line_S {
|
typedef struct sb_line_S {
|
||||||
int sb_cols; // can differ per line
|
int sb_cols; // can differ per line
|
||||||
|
int sb_bytes; // length in bytes of text
|
||||||
cellattr_T *sb_cells; // allocated
|
cellattr_T *sb_cells; // allocated
|
||||||
cellattr_T sb_fill_attr; // for short line
|
cellattr_T sb_fill_attr; // for short line
|
||||||
char_u *sb_text; // for tl_scrollback_postponed
|
char_u *sb_text; // for tl_scrollback_postponed
|
||||||
|
char_u continuation;
|
||||||
} sb_line_T;
|
} sb_line_T;
|
||||||
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
@ -148,6 +150,8 @@ struct terminal_S {
|
|||||||
garray_T tl_scrollback;
|
garray_T tl_scrollback;
|
||||||
int tl_scrollback_scrolled;
|
int tl_scrollback_scrolled;
|
||||||
garray_T tl_scrollback_postponed;
|
garray_T tl_scrollback_postponed;
|
||||||
|
int tl_scrollback_snapshot;
|
||||||
|
int tl_buffer_scrolled;
|
||||||
|
|
||||||
char_u *tl_highlight_name; // replaces "Terminal"; allocated
|
char_u *tl_highlight_name; // replaces "Terminal"; allocated
|
||||||
|
|
||||||
@ -1380,6 +1384,110 @@ update_cursor(term_T *term, int redraw)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the location of a scrollbackline in the buffer
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
scrollbackline_pos_in_buf(term_T *term, int row, linenr_T *lnum, int *start_col, size_t *start_pos)
|
||||||
|
{
|
||||||
|
sb_line_T *lines = (sb_line_T *)term->tl_scrollback.ga_data;
|
||||||
|
linenr_T calc_lnum = term->tl_buffer_scrolled;
|
||||||
|
size_t calc_pos = 0;
|
||||||
|
int calc_col = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (row < 0 || row >= term->tl_scrollback.ga_len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (row > term->tl_scrollback_scrolled)
|
||||||
|
{
|
||||||
|
// Lookback how far along in the top line we are
|
||||||
|
for (i = term->tl_scrollback_scrolled + 1; i > 0 && lines[i].continuation; --i)
|
||||||
|
{
|
||||||
|
calc_pos += lines[i - 1].sb_bytes;
|
||||||
|
calc_col += lines[i - 1].sb_cols;
|
||||||
|
}
|
||||||
|
i = term->tl_scrollback_scrolled + 1;
|
||||||
|
calc_lnum = term->tl_buffer_scrolled + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = 1;
|
||||||
|
calc_lnum = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i <= row; ++i)
|
||||||
|
{
|
||||||
|
if (!lines[i].continuation)
|
||||||
|
{
|
||||||
|
++calc_lnum;
|
||||||
|
calc_pos = 0;
|
||||||
|
calc_col = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calc_pos += lines[i - 1].sb_bytes;
|
||||||
|
calc_col += lines[i - 1].sb_cols;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*lnum = calc_lnum;
|
||||||
|
if (start_col)
|
||||||
|
*start_col = calc_col;
|
||||||
|
if (start_pos)
|
||||||
|
*start_pos = calc_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the location of a buffer line in the scrollback
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bufline_pos_in_scrollback(term_T *term, linenr_T lnum, int col, int *row, int *wrapped_col)
|
||||||
|
{
|
||||||
|
buf_T *buf = term->tl_buffer;
|
||||||
|
sb_line_T *lines = (sb_line_T *)term->tl_scrollback.ga_data;
|
||||||
|
linenr_T calc_row = term->tl_scrollback_scrolled;
|
||||||
|
int calc_col = col;
|
||||||
|
linenr_T l;
|
||||||
|
|
||||||
|
if (lnum > buf->b_ml.ml_line_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lnum > term->tl_buffer_scrolled)
|
||||||
|
{
|
||||||
|
calc_row = term->tl_scrollback_scrolled;
|
||||||
|
l = term->tl_buffer_scrolled + 1;
|
||||||
|
|
||||||
|
while (calc_row < term->tl_scrollback.ga_len && lines[calc_row].continuation)
|
||||||
|
++calc_row;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calc_row = 0;
|
||||||
|
l = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (calc_row < term->tl_scrollback.ga_len && l < lnum)
|
||||||
|
{
|
||||||
|
++calc_row;
|
||||||
|
if (!lines[calc_row].continuation)
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (calc_row + 1 < term->tl_scrollback.ga_len && lines[calc_row + 1].continuation
|
||||||
|
&& calc_col >= lines[calc_row].sb_cols)
|
||||||
|
{
|
||||||
|
calc_col -= lines[calc_row].sb_cols;
|
||||||
|
++calc_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row)
|
||||||
|
*row = calc_row;
|
||||||
|
if (wrapped_col)
|
||||||
|
*wrapped_col = calc_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoked when "msg" output from a job was received. Write it to the terminal
|
* Invoked when "msg" output from a job was received. Write it to the terminal
|
||||||
* of "buffer".
|
* of "buffer".
|
||||||
@ -1879,13 +1987,14 @@ term_try_stop_job(buf_T *buf)
|
|||||||
* Add the last line of the scrollback buffer to the buffer in the window.
|
* Add the last line of the scrollback buffer to the buffer in the window.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
add_scrollback_line_to_buffer(term_T *term, char_u *text, int len)
|
add_scrollback_line_to_buffer(term_T *term, char_u *text, int len, int append)
|
||||||
{
|
{
|
||||||
buf_T *buf = term->tl_buffer;
|
buf_T *buf = term->tl_buffer;
|
||||||
int empty = (buf->b_ml.ml_flags & ML_EMPTY);
|
int empty = (buf->b_ml.ml_flags & ML_EMPTY);
|
||||||
linenr_T lnum = buf->b_ml.ml_line_count;
|
linenr_T lnum = buf->b_ml.ml_line_count;
|
||||||
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
|
char_u *tmp = text;
|
||||||
if (!enc_utf8 && enc_codepage > 0)
|
if (!enc_utf8 && enc_codepage > 0)
|
||||||
{
|
{
|
||||||
WCHAR *ret = NULL;
|
WCHAR *ret = NULL;
|
||||||
@ -1898,13 +2007,30 @@ add_scrollback_line_to_buffer(term_T *term, char_u *text, int len)
|
|||||||
WideCharToMultiByte_alloc(enc_codepage, 0,
|
WideCharToMultiByte_alloc(enc_codepage, 0,
|
||||||
ret, length, (char **)&text, &len, 0, 0);
|
ret, length, (char **)&text, &len, 0, 0);
|
||||||
vim_free(ret);
|
vim_free(ret);
|
||||||
ml_append_buf(term->tl_buffer, lnum, text, len, FALSE);
|
|
||||||
vim_free(text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
ml_append_buf(term->tl_buffer, lnum, text, len + 1, FALSE);
|
|
||||||
|
if (append)
|
||||||
|
{
|
||||||
|
char_u *prev_text = ml_get_buf(buf, lnum, FALSE);
|
||||||
|
int prev_len = STRLEN(prev_text);
|
||||||
|
|
||||||
|
char_u *both = alloc(len + prev_len + 2);
|
||||||
|
vim_strncpy(both, prev_text, prev_len + 1);
|
||||||
|
vim_strncpy(both + prev_len, text, len + 1);
|
||||||
|
|
||||||
|
curbuf = buf;
|
||||||
|
ml_replace(lnum, both, FALSE);
|
||||||
|
curbuf = curwin->w_buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ml_append_buf(buf, lnum, text, len + 1, FALSE);
|
||||||
|
|
||||||
|
#ifdef MSWIN
|
||||||
|
if (tmp != text)
|
||||||
|
vim_free(text);
|
||||||
|
#endif
|
||||||
if (empty)
|
if (empty)
|
||||||
{
|
{
|
||||||
// Delete the empty line that was in the empty buffer.
|
// Delete the empty line that was in the empty buffer.
|
||||||
@ -1960,6 +2086,7 @@ add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
line->sb_cols = 0;
|
line->sb_cols = 0;
|
||||||
|
line->sb_bytes = 0;
|
||||||
line->sb_cells = NULL;
|
line->sb_cells = NULL;
|
||||||
line->sb_fill_attr = *fill_attr;
|
line->sb_fill_attr = *fill_attr;
|
||||||
++term->tl_scrollback.ga_len;
|
++term->tl_scrollback.ga_len;
|
||||||
@ -1976,16 +2103,31 @@ cleanup_scrollback(term_T *term)
|
|||||||
{
|
{
|
||||||
sb_line_T *line;
|
sb_line_T *line;
|
||||||
garray_T *gap;
|
garray_T *gap;
|
||||||
|
char_u *bufline;
|
||||||
|
size_t bufline_length;
|
||||||
|
|
||||||
curbuf = term->tl_buffer;
|
curbuf = term->tl_buffer;
|
||||||
gap = &term->tl_scrollback;
|
gap = &term->tl_scrollback;
|
||||||
while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled
|
bufline = ml_get_buf(curbuf, curbuf->b_ml.ml_line_count, FALSE);
|
||||||
&& gap->ga_len > 0)
|
bufline_length = STRLEN(bufline);
|
||||||
|
while (term->tl_scrollback_snapshot && gap->ga_len > 0)
|
||||||
{
|
{
|
||||||
ml_delete(curbuf->b_ml.ml_line_count);
|
|
||||||
line = (sb_line_T *)gap->ga_data + gap->ga_len - 1;
|
line = (sb_line_T *)gap->ga_data + gap->ga_len - 1;
|
||||||
|
bufline_length -= line->sb_bytes;
|
||||||
|
if (!bufline_length)
|
||||||
|
{
|
||||||
|
ml_delete(curbuf->b_ml.ml_line_count);
|
||||||
|
bufline = ml_get_buf(curbuf, curbuf->b_ml.ml_line_count, FALSE);
|
||||||
|
bufline_length = STRLEN(bufline);
|
||||||
|
}
|
||||||
vim_free(line->sb_cells);
|
vim_free(line->sb_cells);
|
||||||
--gap->ga_len;
|
--gap->ga_len;
|
||||||
|
--term->tl_scrollback_snapshot;
|
||||||
|
}
|
||||||
|
if (bufline_length < STRLEN(bufline))
|
||||||
|
{
|
||||||
|
char_u *shortened = vim_strnsave(bufline, bufline_length);
|
||||||
|
ml_replace(curbuf->b_ml.ml_line_count, shortened, FALSE);
|
||||||
}
|
}
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
if (curbuf == term->tl_buffer)
|
if (curbuf == term->tl_buffer)
|
||||||
@ -1999,6 +2141,7 @@ cleanup_scrollback(term_T *term)
|
|||||||
update_snapshot(term_T *term)
|
update_snapshot(term_T *term)
|
||||||
{
|
{
|
||||||
VTermScreen *screen;
|
VTermScreen *screen;
|
||||||
|
VTermState *state;
|
||||||
int len;
|
int len;
|
||||||
int lines_skipped = 0;
|
int lines_skipped = 0;
|
||||||
VTermPos pos;
|
VTermPos pos;
|
||||||
@ -2014,6 +2157,7 @@ update_snapshot(term_T *term)
|
|||||||
cleanup_scrollback(term);
|
cleanup_scrollback(term);
|
||||||
|
|
||||||
screen = vterm_obtain_screen(term->tl_vterm);
|
screen = vterm_obtain_screen(term->tl_vterm);
|
||||||
|
state = vterm_obtain_state(term->tl_vterm);
|
||||||
fill_attr = new_fill_attr = term->tl_default_color;
|
fill_attr = new_fill_attr = term->tl_default_color;
|
||||||
for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
|
for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
|
||||||
{
|
{
|
||||||
@ -2038,7 +2182,10 @@ update_snapshot(term_T *term)
|
|||||||
// Line was skipped, add an empty line.
|
// Line was skipped, add an empty line.
|
||||||
--lines_skipped;
|
--lines_skipped;
|
||||||
if (add_empty_scrollback(term, &fill_attr, 0) == OK)
|
if (add_empty_scrollback(term, &fill_attr, 0) == OK)
|
||||||
add_scrollback_line_to_buffer(term, (char_u *)"", 0);
|
{
|
||||||
|
add_scrollback_line_to_buffer(term, (char_u *)"", 0, 0);
|
||||||
|
++term->tl_scrollback_snapshot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@ -2050,9 +2197,12 @@ update_snapshot(term_T *term)
|
|||||||
{
|
{
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
int width;
|
int width;
|
||||||
|
const VTermLineInfo *lineinfo;
|
||||||
sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
|
sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
|
||||||
+ term->tl_scrollback.ga_len;
|
+ term->tl_scrollback.ga_len;
|
||||||
|
|
||||||
|
lineinfo = vterm_state_get_lineinfo(state, pos.row);
|
||||||
|
|
||||||
ga_init2(&ga, 1, 100);
|
ga_init2(&ga, 1, 100);
|
||||||
for (pos.col = 0; pos.col < len; pos.col += width)
|
for (pos.col = 0; pos.col < len; pos.col += width)
|
||||||
{
|
{
|
||||||
@ -2087,17 +2237,21 @@ update_snapshot(term_T *term)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
line->sb_cols = len;
|
line->sb_cols = len;
|
||||||
|
line->sb_bytes = ga.ga_len;
|
||||||
line->sb_cells = p;
|
line->sb_cells = p;
|
||||||
line->sb_fill_attr = new_fill_attr;
|
line->sb_fill_attr = new_fill_attr;
|
||||||
|
line->continuation = lineinfo->continuation;
|
||||||
fill_attr = new_fill_attr;
|
fill_attr = new_fill_attr;
|
||||||
++term->tl_scrollback.ga_len;
|
++term->tl_scrollback.ga_len;
|
||||||
|
++term->tl_scrollback_snapshot;
|
||||||
|
|
||||||
if (ga_grow(&ga, 1) == FAIL)
|
if (ga_grow(&ga, 1) == FAIL)
|
||||||
add_scrollback_line_to_buffer(term, (char_u *)"", 0);
|
add_scrollback_line_to_buffer(term, (char_u *)"", 0, 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*((char_u *)ga.ga_data + ga.ga_len) = NUL;
|
*((char_u *)ga.ga_data + ga.ga_len) = NUL;
|
||||||
add_scrollback_line_to_buffer(term, ga.ga_data, ga.ga_len);
|
add_scrollback_line_to_buffer(term, ga.ga_data, ga.ga_len,
|
||||||
|
lineinfo->continuation);
|
||||||
}
|
}
|
||||||
ga_clear(&ga);
|
ga_clear(&ga);
|
||||||
}
|
}
|
||||||
@ -2112,7 +2266,10 @@ update_snapshot(term_T *term)
|
|||||||
++pos.row)
|
++pos.row)
|
||||||
{
|
{
|
||||||
if (add_empty_scrollback(term, &fill_attr, 0) == OK)
|
if (add_empty_scrollback(term, &fill_attr, 0) == OK)
|
||||||
add_scrollback_line_to_buffer(term, (char_u *)"", 0);
|
{
|
||||||
|
add_scrollback_line_to_buffer(term, (char_u *)"", 0, 0);
|
||||||
|
++term->tl_scrollback_snapshot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
term->tl_dirty_snapshot = FALSE;
|
term->tl_dirty_snapshot = FALSE;
|
||||||
@ -2157,7 +2314,7 @@ may_move_terminal_to_buffer(term_T *term, int redraw)
|
|||||||
// Update the snapshot only if something changes or the buffer does not
|
// Update the snapshot only if something changes or the buffer does not
|
||||||
// have all the lines.
|
// have all the lines.
|
||||||
if (term->tl_dirty_snapshot || term->tl_buffer->b_ml.ml_line_count
|
if (term->tl_dirty_snapshot || term->tl_buffer->b_ml.ml_line_count
|
||||||
<= term->tl_scrollback_scrolled)
|
<= term->tl_buffer_scrolled)
|
||||||
update_snapshot(term);
|
update_snapshot(term);
|
||||||
|
|
||||||
// Obtain the current background color.
|
// Obtain the current background color.
|
||||||
@ -2257,7 +2414,9 @@ cleanup_vterm(term_T *term)
|
|||||||
static void
|
static void
|
||||||
term_enter_normal_mode(void)
|
term_enter_normal_mode(void)
|
||||||
{
|
{
|
||||||
term_T *term = curbuf->b_term;
|
term_T *term = curbuf->b_term;
|
||||||
|
linenr_T lnum;
|
||||||
|
int col;
|
||||||
|
|
||||||
set_terminal_mode(term, TRUE);
|
set_terminal_mode(term, TRUE);
|
||||||
|
|
||||||
@ -2266,15 +2425,16 @@ term_enter_normal_mode(void)
|
|||||||
|
|
||||||
// Move the window cursor to the position of the cursor in the
|
// Move the window cursor to the position of the cursor in the
|
||||||
// terminal.
|
// terminal.
|
||||||
curwin->w_cursor.lnum = term->tl_scrollback_scrolled
|
lnum = term->tl_buffer_scrolled + 1 + term->tl_cursor_pos.row;
|
||||||
+ term->tl_cursor_pos.row + 1;
|
col = term->tl_cursor_pos.col;
|
||||||
|
scrollbackline_pos_in_buf(term, term->tl_cursor_pos.row + term->tl_scrollback_scrolled, &lnum, &col, NULL);
|
||||||
|
|
||||||
|
curwin->w_cursor.lnum = lnum;
|
||||||
check_cursor();
|
check_cursor();
|
||||||
if (coladvance(term->tl_cursor_pos.col) == FAIL)
|
if (coladvance(col) == FAIL)
|
||||||
coladvance(MAXCOL);
|
coladvance(MAXCOL);
|
||||||
curwin->w_set_curswant = TRUE;
|
curwin->w_set_curswant = TRUE;
|
||||||
|
curwin->w_topline = term->tl_buffer_scrolled + 1;
|
||||||
// Display the same lines as in the terminal.
|
|
||||||
curwin->w_topline = term->tl_scrollback_scrolled + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3443,20 +3603,27 @@ limit_scrollback(term_T *term, garray_T *gap, int update_buffer)
|
|||||||
int todo = MAX(term->tl_buffer->b_p_twsl / 10,
|
int todo = MAX(term->tl_buffer->b_p_twsl / 10,
|
||||||
gap->ga_len - term->tl_buffer->b_p_twsl);
|
gap->ga_len - term->tl_buffer->b_p_twsl);
|
||||||
int i;
|
int i;
|
||||||
|
sb_line_T *sb_lines = (sb_line_T *)gap->ga_data;
|
||||||
|
|
||||||
curbuf = term->tl_buffer;
|
curbuf = term->tl_buffer;
|
||||||
for (i = 0; i < todo; ++i)
|
for (i = 0; i < todo; ++i)
|
||||||
{
|
{
|
||||||
vim_free(((sb_line_T *)gap->ga_data + i)->sb_cells);
|
if (update_buffer && (!sb_lines[i].continuation || !i))
|
||||||
if (update_buffer)
|
{
|
||||||
ml_delete(1);
|
ml_delete(1);
|
||||||
|
--term->tl_buffer_scrolled;
|
||||||
|
}
|
||||||
|
vim_free(sb_lines[i].sb_cells);
|
||||||
}
|
}
|
||||||
|
// Continue until end of wrapped line
|
||||||
|
for (; todo < gap->ga_len && sb_lines[todo].continuation; ++todo)
|
||||||
|
vim_free(sb_lines[todo].sb_cells);
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
|
|
||||||
gap->ga_len -= todo;
|
gap->ga_len -= todo;
|
||||||
mch_memmove(gap->ga_data,
|
mch_memmove(gap->ga_data,
|
||||||
(sb_line_T *)gap->ga_data + todo,
|
(sb_line_T *)gap->ga_data + todo,
|
||||||
sizeof(sb_line_T) * gap->ga_len);
|
sizeof(sb_line_T) * gap->ga_len);
|
||||||
if (update_buffer)
|
if (update_buffer)
|
||||||
{
|
{
|
||||||
win_T *curwin_save = curwin;
|
win_T *curwin_save = curwin;
|
||||||
@ -3481,7 +3648,7 @@ limit_scrollback(term_T *term, garray_T *gap, int update_buffer)
|
|||||||
* Handle a line that is pushed off the top of the screen.
|
* Handle a line that is pushed off the top of the screen.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
handle_pushline(int cols, const VTermScreenCell *cells, void *user)
|
handle_pushline(int cols, const VTermScreenCell *cells, const VTermLineInfo *info, void *user)
|
||||||
{
|
{
|
||||||
term_T *term = (term_T *)user;
|
term_T *term = (term_T *)user;
|
||||||
garray_T *gap;
|
garray_T *gap;
|
||||||
@ -3559,16 +3726,20 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
|
|||||||
*(text + text_len) = NUL;
|
*(text + text_len) = NUL;
|
||||||
}
|
}
|
||||||
if (update_buffer)
|
if (update_buffer)
|
||||||
add_scrollback_line_to_buffer(term, text, text_len);
|
add_scrollback_line_to_buffer(term, text, text_len, info->continuation);
|
||||||
|
|
||||||
line = (sb_line_T *)gap->ga_data + gap->ga_len;
|
line = (sb_line_T *)gap->ga_data + gap->ga_len;
|
||||||
line->sb_cols = len;
|
line->sb_cols = len;
|
||||||
|
line->sb_bytes = text_len;
|
||||||
line->sb_cells = p;
|
line->sb_cells = p;
|
||||||
line->sb_fill_attr = fill_attr;
|
line->sb_fill_attr = fill_attr;
|
||||||
|
line->continuation = info->continuation;
|
||||||
if (update_buffer)
|
if (update_buffer)
|
||||||
{
|
{
|
||||||
line->sb_text = NULL;
|
line->sb_text = NULL;
|
||||||
++term->tl_scrollback_scrolled;
|
++term->tl_scrollback_scrolled;
|
||||||
|
if (!info->continuation)
|
||||||
|
++term->tl_buffer_scrolled;
|
||||||
ga_clear(&ga); // free the text
|
ga_clear(&ga); // free the text
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3610,17 +3781,20 @@ handle_postponed_scrollback(term_T *term)
|
|||||||
text = pp_line->sb_text;
|
text = pp_line->sb_text;
|
||||||
if (text == NULL)
|
if (text == NULL)
|
||||||
text = (char_u *)"";
|
text = (char_u *)"";
|
||||||
add_scrollback_line_to_buffer(term, text, (int)STRLEN(text));
|
add_scrollback_line_to_buffer(term, text, (int)STRLEN(text), pp_line->continuation);
|
||||||
vim_free(pp_line->sb_text);
|
vim_free(pp_line->sb_text);
|
||||||
|
|
||||||
line = (sb_line_T *)term->tl_scrollback.ga_data
|
line = (sb_line_T *)term->tl_scrollback.ga_data
|
||||||
+ term->tl_scrollback.ga_len;
|
+ term->tl_scrollback.ga_len;
|
||||||
line->sb_cols = pp_line->sb_cols;
|
line->sb_cols = pp_line->sb_cols;
|
||||||
|
line->sb_bytes = pp_line->sb_bytes;
|
||||||
line->sb_cells = pp_line->sb_cells;
|
line->sb_cells = pp_line->sb_cells;
|
||||||
line->sb_fill_attr = pp_line->sb_fill_attr;
|
line->sb_fill_attr = pp_line->sb_fill_attr;
|
||||||
line->sb_text = NULL;
|
line->sb_text = NULL;
|
||||||
++term->tl_scrollback_scrolled;
|
++term->tl_scrollback_scrolled;
|
||||||
++term->tl_scrollback.ga_len;
|
++term->tl_scrollback.ga_len;
|
||||||
|
if (!pp_line->continuation)
|
||||||
|
++term->tl_buffer_scrolled;
|
||||||
}
|
}
|
||||||
|
|
||||||
ga_clear(&term->tl_scrollback_postponed);
|
ga_clear(&term->tl_scrollback_postponed);
|
||||||
@ -4197,16 +4371,21 @@ term_get_attr(win_T *wp, linenr_T lnum, int col)
|
|||||||
term_T *term = buf->b_term;
|
term_T *term = buf->b_term;
|
||||||
sb_line_T *line;
|
sb_line_T *line;
|
||||||
cellattr_T *cellattr;
|
cellattr_T *cellattr;
|
||||||
|
int sb_line = -1;
|
||||||
|
int sb_col;
|
||||||
|
|
||||||
if (lnum > term->tl_scrollback.ga_len)
|
if (term->tl_scrollback.ga_len)
|
||||||
|
bufline_pos_in_scrollback(term, lnum, col, &sb_line, &sb_col);
|
||||||
|
|
||||||
|
if (sb_line < 0)
|
||||||
cellattr = &term->tl_default_color;
|
cellattr = &term->tl_default_color;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
line = (sb_line_T *)term->tl_scrollback.ga_data + lnum - 1;
|
line = (sb_line_T *)term->tl_scrollback.ga_data + sb_line;
|
||||||
if (col < 0 || col >= line->sb_cols)
|
if (sb_col < 0 || sb_col >= line->sb_cols)
|
||||||
cellattr = &line->sb_fill_attr;
|
cellattr = &line->sb_fill_attr;
|
||||||
else
|
else
|
||||||
cellattr = line->sb_cells + col;
|
cellattr = line->sb_cells + sb_col;
|
||||||
}
|
}
|
||||||
return cell2attr(term, wp, &cellattr->attrs, &cellattr->fg, &cellattr->bg);
|
return cell2attr(term, wp, &cellattr->attrs, &cellattr->fg, &cellattr->bg);
|
||||||
}
|
}
|
||||||
@ -5433,6 +5612,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
|
|||||||
if (max_cells < ga_cell.ga_len)
|
if (max_cells < ga_cell.ga_len)
|
||||||
max_cells = ga_cell.ga_len;
|
max_cells = ga_cell.ga_len;
|
||||||
line->sb_cols = ga_cell.ga_len;
|
line->sb_cols = ga_cell.ga_len;
|
||||||
|
line->sb_bytes = ga_text.ga_len;
|
||||||
line->sb_cells = ga_cell.ga_data;
|
line->sb_cells = ga_cell.ga_data;
|
||||||
line->sb_fill_attr = term->tl_default_color;
|
line->sb_fill_attr = term->tl_default_color;
|
||||||
++term->tl_scrollback.ga_len;
|
++term->tl_scrollback.ga_len;
|
||||||
@ -6249,11 +6429,19 @@ f_term_getline(typval_T *argvars, typval_T *rettv)
|
|||||||
|
|
||||||
if (term->tl_vterm == NULL)
|
if (term->tl_vterm == NULL)
|
||||||
{
|
{
|
||||||
linenr_T lnum = row + term->tl_scrollback_scrolled + 1;
|
linenr_T lnum = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data + term->tl_scrollback_scrolled + row;
|
||||||
|
|
||||||
|
scrollbackline_pos_in_buf(term, row + term->tl_scrollback_scrolled, &lnum, NULL, &offset);
|
||||||
|
|
||||||
// vterm is finished, get the text from the buffer
|
// vterm is finished, get the text from the buffer
|
||||||
if (lnum > 0 && lnum <= buf->b_ml.ml_line_count)
|
if (lnum > 0 && lnum <= buf->b_ml.ml_line_count)
|
||||||
rettv->vval.v_string = vim_strsave(ml_get_buf(buf, lnum, FALSE));
|
{
|
||||||
|
char_u *p = ml_get_buf(buf, lnum, FALSE);
|
||||||
|
if (STRLEN(p) >= offset + line->sb_bytes)
|
||||||
|
rettv->vval.v_string = vim_strnsave(p + offset, line->sb_bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6292,7 +6480,7 @@ f_term_getscrolled(typval_T *argvars, typval_T *rettv)
|
|||||||
buf = term_get_buf(argvars, "term_getscrolled()");
|
buf = term_get_buf(argvars, "term_getscrolled()");
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return;
|
return;
|
||||||
rettv->vval.v_number = buf->b_term->tl_scrollback_scrolled;
|
rettv->vval.v_number = buf->b_term->tl_buffer_scrolled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6506,12 +6694,22 @@ f_term_scrape(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
linenr_T lnum = pos.row + term->tl_scrollback_scrolled;
|
int sb_row = term->tl_scrollback_scrolled + pos.row;
|
||||||
|
linenr_T lnum = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
|
||||||
if (lnum < 0 || lnum >= term->tl_scrollback.ga_len)
|
scrollbackline_pos_in_buf(term, sb_row, &lnum, NULL, &offset);
|
||||||
|
|
||||||
|
if (sb_row >= term->tl_scrollback.ga_len || lnum <= 0 || lnum > buf->b_ml.ml_line_count)
|
||||||
return;
|
return;
|
||||||
p = ml_get_buf(buf, lnum + 1, FALSE);
|
|
||||||
line = (sb_line_T *)term->tl_scrollback.ga_data + lnum;
|
line = (sb_line_T *)term->tl_scrollback.ga_data + sb_row;
|
||||||
|
p = ml_get_buf(buf, lnum, FALSE);
|
||||||
|
|
||||||
|
if (STRLEN(p) < offset + line->sb_bytes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pos.col = 0; pos.col < term->tl_cols; )
|
for (pos.col = 0; pos.col < term->tl_cols; )
|
||||||
|
@ -2422,4 +2422,26 @@ func Test_term_TextChangedT_close()
|
|||||||
augroup END
|
augroup END
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_terminal_unwraps()
|
||||||
|
30vnew
|
||||||
|
|
||||||
|
redraw
|
||||||
|
let buf = term_start("echo 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15")
|
||||||
|
call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
|
||||||
|
|
||||||
|
" A long wrapped line appears as 2 lines in libvterm
|
||||||
|
let l = term_getline(buf, 1)
|
||||||
|
call assert_equal('1+2+3+4+5+6+7+8+9+10+11+12+13+', l)
|
||||||
|
|
||||||
|
let l = term_getline(buf, 2)
|
||||||
|
call assert_equal('14+15', l)
|
||||||
|
|
||||||
|
call TermWait(buf)
|
||||||
|
" It should appear as a single buffer line in vim
|
||||||
|
let lastline = getline('$')
|
||||||
|
call assert_equal('1+2+3+4+5+6+7+8+9+10+11+12+13+14+15', lastline)
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Loading…
x
Reference in New Issue
Block a user