Skip to content

Commit

Permalink
Add a 'premove' state-layer callback to inform the higher layer befor…
Browse files Browse the repository at this point in the history
…e scroll-based moves happen
  • Loading branch information
leonerd committed Jul 16, 2024
1 parent 9d6d211 commit 3cb1c9c
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 3 deletions.
4 changes: 4 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
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
17 changes: 17 additions & 0 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 @@ -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 Down
2 changes: 1 addition & 1 deletion t/run-test.pl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ sub do_line
elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) {
$line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . " $2";
}
elsif( $line =~ m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|sb_clear|settermprop|setmousefunc|selection-query) ?/ ) {
elsif( $line =~ m/^(?:movecursor|scrollrect|premove|moverect|erase|damage|sb_pushline|sb_popline|sb_clear|settermprop|setmousefunc|selection-query) ?/ ) {
# no conversion
}
elsif( $line =~ m/^(selection-set) (.*?) (\[?)(.*?)(\]?)$/ ) {
Expand Down

0 comments on commit 3cb1c9c

Please sign in to comment.