Skip to content

Commit

Permalink
Merge mirror
Browse files Browse the repository at this point in the history
  • Loading branch information
marvim committed Jul 16, 2024
2 parents 0a15c6e + c8a56cb commit 2ba6ea6
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 24 deletions.
8 changes: 8 additions & 0 deletions include/vterm.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ typedef struct {
int (*resize)(int rows, int cols, VTermStateFields *fields, void *user);
int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user);
int (*sb_clear)(void *user);
// ABI-compat only enabled if vterm_state_callbacks_has_premove() is invoked
int (*premove)(VTermRect dest, void *user);
} VTermStateCallbacks;

typedef struct {
Expand All @@ -459,6 +461,8 @@ VTermState *vterm_obtain_state(VTerm *vt);
void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user);
void *vterm_state_get_cbdata(VTermState *state);

void vterm_state_callbacks_has_premove(VTermState *state);

void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermStateFallbacks *fallbacks, void *user);
void *vterm_state_get_unrecognised_fbdata(VTermState *state);

Expand Down Expand Up @@ -541,13 +545,17 @@ typedef struct {
int (*sb_pushline)(int cols, const VTermScreenCell *cells, void *user);
int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
int (*sb_clear)(void* user);
/* ABI-compat this is only used if vterm_screen_callbacks_has_pushline4() is called */
int (*sb_pushline4)(int cols, const VTermScreenCell *cells, bool continuation, void *user);
} VTermScreenCallbacks;

VTermScreen *vterm_obtain_screen(VTerm *vt);

void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user);
void *vterm_screen_get_cbdata(VTermScreen *screen);

void vterm_screen_callbacks_has_pushline4(VTermScreen *screen);

void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user);
void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen);

Expand Down
47 changes: 36 additions & 11 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct VTermScreen

const VTermScreenCallbacks *callbacks;
void *cbdata;
bool callbacks_has_pushline4;

VTermDamageSize damage_merge;
/* start_row == -1 => no damage */
Expand Down Expand Up @@ -205,27 +206,40 @@ static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
return 1;
}

static void sb_pushline_from_row(VTermScreen *screen, int row)
static void sb_pushline_from_row(VTermScreen *screen, int row, bool continuation)
{
VTermPos pos = { .row = row };
for(pos.col = 0; pos.col < screen->cols; pos.col++)
vterm_screen_get_cell(screen, pos, screen->sb_buffer + pos.col);

(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
if(screen->callbacks_has_pushline4 && screen->callbacks->sb_pushline4)
(screen->callbacks->sb_pushline4)(screen->cols, screen->sb_buffer, continuation, screen->cbdata);
else
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
}

static int moverect_internal(VTermRect dest, VTermRect src, void *user)
static int premove(VTermRect rect, void *user)
{
VTermScreen *screen = user;

if(screen->callbacks && screen->callbacks->sb_pushline &&
dest.start_row == 0 && dest.start_col == 0 && // starts top-left corner
dest.end_col == screen->cols && // full width
if(((screen->callbacks && screen->callbacks->sb_pushline) ||
(screen->callbacks_has_pushline4 && screen->callbacks && screen->callbacks->sb_pushline4)) &&
rect.start_row == 0 && rect.start_col == 0 && // starts top-left corner
rect.end_col == screen->cols && // full width
screen->buffer == screen->buffers[BUFIDX_PRIMARY]) { // not altscreen
for(int row = 0; row < src.start_row; row++)
sb_pushline_from_row(screen, row);
for(int row = 0; row < rect.end_row; row++) {
const VTermLineInfo *lineinfo = vterm_state_get_lineinfo(screen->state, row);
sb_pushline_from_row(screen, row, lineinfo->continuation);
}
}

return 1;
}

static int moverect_internal(VTermRect dest, VTermRect src, void *user)
{
VTermScreen *screen = user;

int cols = src.end_col - src.start_col;
int downward = src.start_row - dest.start_row;

Expand Down Expand Up @@ -667,9 +681,12 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new

if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) {
/* Push spare lines to scrollback buffer */
if(screen->callbacks && screen->callbacks->sb_pushline)
for(int row = 0; row <= old_row; row++)
sb_pushline_from_row(screen, row);
if((screen->callbacks && screen->callbacks->sb_pushline) ||
(screen->callbacks_has_pushline4 && screen->callbacks && screen->callbacks->sb_pushline4))
for(int row = 0; row <= old_row; row++) {
const VTermLineInfo *lineinfo = old_lineinfo + row;
sb_pushline_from_row(screen, row, lineinfo->continuation);
}
if(active)
statefields->pos.row -= (old_row + 1);
}
Expand Down Expand Up @@ -840,6 +857,7 @@ static int sb_clear(void *user) {
static VTermStateCallbacks state_cbs = {
.putglyph = &putglyph,
.movecursor = &movecursor,
.premove = &premove,
.scrollrect = &scrollrect,
.erase = &erase,
.setpenattr = &setpenattr,
Expand Down Expand Up @@ -876,6 +894,7 @@ static VTermScreen *screen_new(VTerm *vt)

screen->callbacks = NULL;
screen->cbdata = NULL;
screen->callbacks_has_pushline4 = false;

screen->buffers[BUFIDX_PRIMARY] = alloc_buffer(screen, rows, cols);

Expand All @@ -884,6 +903,7 @@ static VTermScreen *screen_new(VTerm *vt)
screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * cols);

vterm_state_set_callbacks(screen->state, &state_cbs, screen);
vterm_state_callbacks_has_premove(screen->state);

return screen;
}
Expand Down Expand Up @@ -1061,6 +1081,11 @@ void *vterm_screen_get_cbdata(VTermScreen *screen)
return screen->cbdata;
}

void vterm_screen_callbacks_has_pushline4(VTermScreen *screen)
{
screen->callbacks_has_pushline4 = true;
}

void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user)
{
vterm_state_set_unrecognised_fallbacks(screen->state, fallbacks, user);
Expand Down
33 changes: 33 additions & 0 deletions src/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static VTermState *vterm_state_new(VTerm *vt)

state->callbacks = NULL;
state->cbdata = NULL;
state->callbacks_has_premove = false;

state->selection.callbacks = NULL;
state->selection.user = NULL;
Expand Down Expand Up @@ -126,6 +127,33 @@ static void scroll(VTermState *state, VTermRect rect, int downward, int rightwar
else if(rightward < -cols)
rightward = -cols;

if(state->callbacks_has_premove && state->callbacks && state->callbacks->premove) {
// TODO: technically this logic is wrong if both downward != 0 and rightward != 0

/* Work out what subsection of the destination area is about to be destroyed */
if(downward > 0)
/* about to destroy the top */
(*state->callbacks->premove)((VTermRect){
.start_row = rect.start_row, .end_row = rect.start_row + downward,
.start_col = rect.start_col, .end_col = rect.end_col}, state->cbdata);
else if(downward < 0)
/* about to destroy the bottom */
(*state->callbacks->premove)((VTermRect){
.start_row = rect.end_row + downward, .end_row = rect.end_row,
.start_col = rect.start_col, .end_col = rect.end_col}, state->cbdata);

if(rightward > 0)
/* about to destroy the left */
(*state->callbacks->premove)((VTermRect){
.start_row = rect.start_row, .end_row = rect.end_row,
.start_col = rect.start_col, .end_col = rect.start_col + rightward}, state->cbdata);
else if(rightward < 0)
/* about to destroy the right */
(*state->callbacks->premove)((VTermRect){
.start_row = rect.start_row, .end_row = rect.end_row,
.start_col = rect.end_col + rightward, .end_col = rect.end_col}, state->cbdata);
}

// Update lineinfo if full line
if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
int height = rect.end_row - rect.start_row - abs(downward);
Expand Down Expand Up @@ -2156,6 +2184,11 @@ void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *cal
}
}

void vterm_state_callbacks_has_premove(VTermState *state)
{
state->callbacks_has_premove = true;
}

void *vterm_state_get_cbdata(VTermState *state)
{
return state->cbdata;
Expand Down
1 change: 1 addition & 0 deletions src/vterm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct VTermState

const VTermStateCallbacks *callbacks;
void *cbdata;
bool callbacks_has_premove;

const VTermStateFallbacks *fallbacks;
void *fbdata;
Expand Down
6 changes: 5 additions & 1 deletion t/12state_scroll.test
Original file line number Diff line number Diff line change
Expand Up @@ -127,24 +127,28 @@ PUSH "\e[100;105r\eD"
PUSH "\e[5;2r\eD"

RESET
WANTSTATE -s+me
WANTSTATE -s+Pme

!Scroll Down move+erase emulation
PUSH "\e[S"
premove 0..1,0..80
moverect 1..25,0..80 -> 0..24,0..80
erase 24..25,0..80
?cursor = 0,0
PUSH "\e[2S"
premove 0..2,0..80
moverect 2..25,0..80 -> 0..23,0..80
erase 23..25,0..80
?cursor = 0,0

!Scroll Up move+erase emulation
PUSH "\e[T"
premove 24..25,0..80
moverect 0..24,0..80 -> 1..25,0..80
erase 0..1,0..80
?cursor = 0,0
PUSH "\e[2T"
premove 23..25,0..80
moverect 0..23,0..80 -> 2..25,0..80
erase 0..2,0..80
?cursor = 0,0
Expand Down
6 changes: 5 additions & 1 deletion t/13state_edit.test
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ PUSH "\e[2\"q"
PUSH "\eP\$q\"q\e\\"
output "\eP1\$r2\"q\e\\"

WANTSTATE -s+m
WANTSTATE -s+Pm

!ICH move+erase emuation
RESET
Expand All @@ -278,12 +278,14 @@ PUSH "ACD"
PUSH "\e[2D"
?cursor = 0,1
PUSH "\e[@"
premove 0..1,79..80
moverect 0..1,1..79 -> 0..1,2..80
erase 0..1,1..2
?cursor = 0,1
PUSH "B"
?cursor = 0,2
PUSH "\e[3@"
premove 0..1,77..80
moverect 0..1,2..77 -> 0..1,5..80
erase 0..1,2..5

Expand All @@ -295,10 +297,12 @@ PUSH "ABBC"
PUSH "\e[3D"
?cursor = 0,1
PUSH "\e[P"
premove 0..1,1..2
moverect 0..1,2..80 -> 0..1,1..79
erase 0..1,79..80
?cursor = 0,1
PUSH "\e[3P"
premove 0..1,1..4
moverect 0..1,4..80 -> 0..1,1..77
erase 0..1,77..80
?cursor = 0,1
2 changes: 1 addition & 1 deletion t/62screen_damage.test
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ PUSH "\e[25H\r\nABCDE\b\b\b\e[2P\r\n"
sb_pushline 80 =
moverect 1..25,0..80 -> 0..24,0..80
damage 24..25,0..80 = 24<41 42 43 44 45>
sb_pushline 80 =
moverect 24..25,4..80 -> 24..25,2..78
damage 24..25,78..80
sb_pushline 80 =
DAMAGEFLUSH
moverect 1..25,0..80 -> 0..24,0..80
damage 24..25,0..80
Expand Down
17 changes: 17 additions & 0 deletions t/69screen_pushline.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
INIT
WANTSTATE
WANTSCREEN b

RESET

!Spillover text marks continuation on second line
PUSH "A"x85
PUSH "\r\n"
?lineinfo 0 =
?lineinfo 1 = cont

!Continuation mark sent to sb_pushline
PUSH "\n"x23
sb_pushline 80 = 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
PUSH "\n"
sb_pushline 80 cont = 41 41 41 41 41
36 changes: 27 additions & 9 deletions t/harness.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ static int movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
return 1;
}

static int want_premove = 0;
static int premove(VTermRect rect, void *user)
{
if(!want_premove)
return 0;

printf("premove %d..%d,%d..%d\n",
rect.start_row, rect.end_row, rect.start_col, rect.end_col);

return 1;
}

static int want_scrollrect = 0;
static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
{
Expand Down Expand Up @@ -489,6 +501,7 @@ static int state_sb_clear(void *user) {
VTermStateCallbacks state_cbs = {
.putglyph = state_putglyph,
.movecursor = movecursor,
.premove = premove,
.scrollrect = scrollrect,
.moverect = moverect,
.erase = state_erase,
Expand Down Expand Up @@ -569,7 +582,7 @@ static int screen_damage(VTermRect rect, void *user)
}

static int want_screen_scrollback = 0;
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
static int screen_sb_pushline4(int cols, const VTermScreenCell *cells, bool continuation, void *user)
{
if(!want_screen_scrollback)
return 1;
Expand All @@ -578,7 +591,7 @@ static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user
while(eol && !cells[eol-1].chars[0])
eol--;

printf("sb_pushline %d =", cols);
printf("sb_pushline %d%s =", cols, continuation ? " cont" : "");
for(int c = 0; c < eol; c++)
printf(" %02X", cells[c].chars[0]);
printf("\n");
Expand Down Expand Up @@ -615,13 +628,13 @@ static int screen_sb_clear(void *user)
}

VTermScreenCallbacks screen_cbs = {
.damage = screen_damage,
.moverect = moverect,
.movecursor = movecursor,
.settermprop = settermprop,
.sb_pushline = screen_sb_pushline,
.sb_popline = screen_sb_popline,
.sb_clear = screen_sb_clear,
.damage = screen_damage,
.moverect = moverect,
.movecursor = movecursor,
.settermprop = settermprop,
.sb_popline = screen_sb_popline,
.sb_clear = screen_sb_clear,
.sb_pushline4 = screen_sb_pushline4,
};

int main(int argc, char **argv)
Expand Down Expand Up @@ -657,6 +670,7 @@ int main(int argc, char **argv)
if(!state) {
state = vterm_obtain_state(vt);
vterm_state_set_callbacks(state, &state_cbs, NULL);
vterm_state_callbacks_has_premove(state);
/* In some tests we want to check the behaviour of overflowing the
* buffer, so make it nicely small
*/
Expand All @@ -683,6 +697,9 @@ int main(int argc, char **argv)
case 's':
want_scrollrect = sense;
break;
case 'P':
want_premove = sense;
break;
case 'm':
want_moverect = sense;
break;
Expand All @@ -708,6 +725,7 @@ int main(int argc, char **argv)
if(!screen)
screen = vterm_obtain_screen(vt);
vterm_screen_set_callbacks(screen, &screen_cbs, NULL);
vterm_screen_callbacks_has_pushline4(screen);

int i = 10;
int sense = 1;
Expand Down
Loading

0 comments on commit 2ba6ea6

Please sign in to comment.