Skip to content

Commit 2ba6ea6

Browse files
committed
Merge mirror
2 parents 0a15c6e + c8a56cb commit 2ba6ea6

10 files changed

+134
-24
lines changed

include/vterm.h

+8
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ typedef struct {
437437
int (*resize)(int rows, int cols, VTermStateFields *fields, void *user);
438438
int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user);
439439
int (*sb_clear)(void *user);
440+
// ABI-compat only enabled if vterm_state_callbacks_has_premove() is invoked
441+
int (*premove)(VTermRect dest, void *user);
440442
} VTermStateCallbacks;
441443

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

464+
void vterm_state_callbacks_has_premove(VTermState *state);
465+
462466
void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermStateFallbacks *fallbacks, void *user);
463467
void *vterm_state_get_unrecognised_fbdata(VTermState *state);
464468

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

546552
VTermScreen *vterm_obtain_screen(VTerm *vt);
547553

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

557+
void vterm_screen_callbacks_has_pushline4(VTermScreen *screen);
558+
551559
void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user);
552560
void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen);
553561

src/screen.c

+36-11
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct VTermScreen
4848

4949
const VTermScreenCallbacks *callbacks;
5050
void *cbdata;
51+
bool callbacks_has_pushline4;
5152

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

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

214-
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
215+
if(screen->callbacks_has_pushline4 && screen->callbacks->sb_pushline4)
216+
(screen->callbacks->sb_pushline4)(screen->cols, screen->sb_buffer, continuation, screen->cbdata);
217+
else
218+
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
215219
}
216220

217-
static int moverect_internal(VTermRect dest, VTermRect src, void *user)
221+
static int premove(VTermRect rect, void *user)
218222
{
219223
VTermScreen *screen = user;
220224

221-
if(screen->callbacks && screen->callbacks->sb_pushline &&
222-
dest.start_row == 0 && dest.start_col == 0 && // starts top-left corner
223-
dest.end_col == screen->cols && // full width
225+
if(((screen->callbacks && screen->callbacks->sb_pushline) ||
226+
(screen->callbacks_has_pushline4 && screen->callbacks && screen->callbacks->sb_pushline4)) &&
227+
rect.start_row == 0 && rect.start_col == 0 && // starts top-left corner
228+
rect.end_col == screen->cols && // full width
224229
screen->buffer == screen->buffers[BUFIDX_PRIMARY]) { // not altscreen
225-
for(int row = 0; row < src.start_row; row++)
226-
sb_pushline_from_row(screen, row);
230+
for(int row = 0; row < rect.end_row; row++) {
231+
const VTermLineInfo *lineinfo = vterm_state_get_lineinfo(screen->state, row);
232+
sb_pushline_from_row(screen, row, lineinfo->continuation);
233+
}
227234
}
228235

236+
return 1;
237+
}
238+
239+
static int moverect_internal(VTermRect dest, VTermRect src, void *user)
240+
{
241+
VTermScreen *screen = user;
242+
229243
int cols = src.end_col - src.start_col;
230244
int downward = src.start_row - dest.start_row;
231245

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

668682
if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) {
669683
/* Push spare lines to scrollback buffer */
670-
if(screen->callbacks && screen->callbacks->sb_pushline)
671-
for(int row = 0; row <= old_row; row++)
672-
sb_pushline_from_row(screen, row);
684+
if((screen->callbacks && screen->callbacks->sb_pushline) ||
685+
(screen->callbacks_has_pushline4 && screen->callbacks && screen->callbacks->sb_pushline4))
686+
for(int row = 0; row <= old_row; row++) {
687+
const VTermLineInfo *lineinfo = old_lineinfo + row;
688+
sb_pushline_from_row(screen, row, lineinfo->continuation);
689+
}
673690
if(active)
674691
statefields->pos.row -= (old_row + 1);
675692
}
@@ -840,6 +857,7 @@ static int sb_clear(void *user) {
840857
static VTermStateCallbacks state_cbs = {
841858
.putglyph = &putglyph,
842859
.movecursor = &movecursor,
860+
.premove = &premove,
843861
.scrollrect = &scrollrect,
844862
.erase = &erase,
845863
.setpenattr = &setpenattr,
@@ -876,6 +894,7 @@ static VTermScreen *screen_new(VTerm *vt)
876894

877895
screen->callbacks = NULL;
878896
screen->cbdata = NULL;
897+
screen->callbacks_has_pushline4 = false;
879898

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

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

886905
vterm_state_set_callbacks(screen->state, &state_cbs, screen);
906+
vterm_state_callbacks_has_premove(screen->state);
887907

888908
return screen;
889909
}
@@ -1061,6 +1081,11 @@ void *vterm_screen_get_cbdata(VTermScreen *screen)
10611081
return screen->cbdata;
10621082
}
10631083

1084+
void vterm_screen_callbacks_has_pushline4(VTermScreen *screen)
1085+
{
1086+
screen->callbacks_has_pushline4 = true;
1087+
}
1088+
10641089
void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user)
10651090
{
10661091
vterm_state_set_unrecognised_fallbacks(screen->state, fallbacks, user);

src/state.c

+33
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static VTermState *vterm_state_new(VTerm *vt)
7373

7474
state->callbacks = NULL;
7575
state->cbdata = NULL;
76+
state->callbacks_has_premove = false;
7677

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

130+
if(state->callbacks_has_premove && state->callbacks && state->callbacks->premove) {
131+
// TODO: technically this logic is wrong if both downward != 0 and rightward != 0
132+
133+
/* Work out what subsection of the destination area is about to be destroyed */
134+
if(downward > 0)
135+
/* about to destroy the top */
136+
(*state->callbacks->premove)((VTermRect){
137+
.start_row = rect.start_row, .end_row = rect.start_row + downward,
138+
.start_col = rect.start_col, .end_col = rect.end_col}, state->cbdata);
139+
else if(downward < 0)
140+
/* about to destroy the bottom */
141+
(*state->callbacks->premove)((VTermRect){
142+
.start_row = rect.end_row + downward, .end_row = rect.end_row,
143+
.start_col = rect.start_col, .end_col = rect.end_col}, state->cbdata);
144+
145+
if(rightward > 0)
146+
/* about to destroy the left */
147+
(*state->callbacks->premove)((VTermRect){
148+
.start_row = rect.start_row, .end_row = rect.end_row,
149+
.start_col = rect.start_col, .end_col = rect.start_col + rightward}, state->cbdata);
150+
else if(rightward < 0)
151+
/* about to destroy the right */
152+
(*state->callbacks->premove)((VTermRect){
153+
.start_row = rect.start_row, .end_row = rect.end_row,
154+
.start_col = rect.end_col + rightward, .end_col = rect.end_col}, state->cbdata);
155+
}
156+
129157
// Update lineinfo if full line
130158
if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
131159
int height = rect.end_row - rect.start_row - abs(downward);
@@ -2156,6 +2184,11 @@ void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *cal
21562184
}
21572185
}
21582186

2187+
void vterm_state_callbacks_has_premove(VTermState *state)
2188+
{
2189+
state->callbacks_has_premove = true;
2190+
}
2191+
21592192
void *vterm_state_get_cbdata(VTermState *state)
21602193
{
21612194
return state->cbdata;

src/vterm_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct VTermState
5858

5959
const VTermStateCallbacks *callbacks;
6060
void *cbdata;
61+
bool callbacks_has_premove;
6162

6263
const VTermStateFallbacks *fallbacks;
6364
void *fbdata;

t/12state_scroll.test

+5-1
Original file line numberDiff line numberDiff line change
@@ -127,24 +127,28 @@ PUSH "\e[100;105r\eD"
127127
PUSH "\e[5;2r\eD"
128128

129129
RESET
130-
WANTSTATE -s+me
130+
WANTSTATE -s+Pme
131131

132132
!Scroll Down move+erase emulation
133133
PUSH "\e[S"
134+
premove 0..1,0..80
134135
moverect 1..25,0..80 -> 0..24,0..80
135136
erase 24..25,0..80
136137
?cursor = 0,0
137138
PUSH "\e[2S"
139+
premove 0..2,0..80
138140
moverect 2..25,0..80 -> 0..23,0..80
139141
erase 23..25,0..80
140142
?cursor = 0,0
141143

142144
!Scroll Up move+erase emulation
143145
PUSH "\e[T"
146+
premove 24..25,0..80
144147
moverect 0..24,0..80 -> 1..25,0..80
145148
erase 0..1,0..80
146149
?cursor = 0,0
147150
PUSH "\e[2T"
151+
premove 23..25,0..80
148152
moverect 0..23,0..80 -> 2..25,0..80
149153
erase 0..2,0..80
150154
?cursor = 0,0

t/13state_edit.test

+5-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ PUSH "\e[2\"q"
268268
PUSH "\eP\$q\"q\e\\"
269269
output "\eP1\$r2\"q\e\\"
270270

271-
WANTSTATE -s+m
271+
WANTSTATE -s+Pm
272272

273273
!ICH move+erase emuation
274274
RESET
@@ -278,12 +278,14 @@ PUSH "ACD"
278278
PUSH "\e[2D"
279279
?cursor = 0,1
280280
PUSH "\e[@"
281+
premove 0..1,79..80
281282
moverect 0..1,1..79 -> 0..1,2..80
282283
erase 0..1,1..2
283284
?cursor = 0,1
284285
PUSH "B"
285286
?cursor = 0,2
286287
PUSH "\e[3@"
288+
premove 0..1,77..80
287289
moverect 0..1,2..77 -> 0..1,5..80
288290
erase 0..1,2..5
289291

@@ -295,10 +297,12 @@ PUSH "ABBC"
295297
PUSH "\e[3D"
296298
?cursor = 0,1
297299
PUSH "\e[P"
300+
premove 0..1,1..2
298301
moverect 0..1,2..80 -> 0..1,1..79
299302
erase 0..1,79..80
300303
?cursor = 0,1
301304
PUSH "\e[3P"
305+
premove 0..1,1..4
302306
moverect 0..1,4..80 -> 0..1,1..77
303307
erase 0..1,77..80
304308
?cursor = 0,1

t/62screen_damage.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ PUSH "\e[25H\r\nABCDE\b\b\b\e[2P\r\n"
146146
sb_pushline 80 =
147147
moverect 1..25,0..80 -> 0..24,0..80
148148
damage 24..25,0..80 = 24<41 42 43 44 45>
149+
sb_pushline 80 =
149150
moverect 24..25,4..80 -> 24..25,2..78
150151
damage 24..25,78..80
151-
sb_pushline 80 =
152152
DAMAGEFLUSH
153153
moverect 1..25,0..80 -> 0..24,0..80
154154
damage 24..25,0..80

t/69screen_pushline.test

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
INIT
2+
WANTSTATE
3+
WANTSCREEN b
4+
5+
RESET
6+
7+
!Spillover text marks continuation on second line
8+
PUSH "A"x85
9+
PUSH "\r\n"
10+
?lineinfo 0 =
11+
?lineinfo 1 = cont
12+
13+
!Continuation mark sent to sb_pushline
14+
PUSH "\n"x23
15+
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
16+
PUSH "\n"
17+
sb_pushline 80 cont = 41 41 41 41 41

t/harness.c

+27-9
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,18 @@ static int movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
318318
return 1;
319319
}
320320

321+
static int want_premove = 0;
322+
static int premove(VTermRect rect, void *user)
323+
{
324+
if(!want_premove)
325+
return 0;
326+
327+
printf("premove %d..%d,%d..%d\n",
328+
rect.start_row, rect.end_row, rect.start_col, rect.end_col);
329+
330+
return 1;
331+
}
332+
321333
static int want_scrollrect = 0;
322334
static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
323335
{
@@ -489,6 +501,7 @@ static int state_sb_clear(void *user) {
489501
VTermStateCallbacks state_cbs = {
490502
.putglyph = state_putglyph,
491503
.movecursor = movecursor,
504+
.premove = premove,
492505
.scrollrect = scrollrect,
493506
.moverect = moverect,
494507
.erase = state_erase,
@@ -569,7 +582,7 @@ static int screen_damage(VTermRect rect, void *user)
569582
}
570583

571584
static int want_screen_scrollback = 0;
572-
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
585+
static int screen_sb_pushline4(int cols, const VTermScreenCell *cells, bool continuation, void *user)
573586
{
574587
if(!want_screen_scrollback)
575588
return 1;
@@ -578,7 +591,7 @@ static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user
578591
while(eol && !cells[eol-1].chars[0])
579592
eol--;
580593

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

617630
VTermScreenCallbacks screen_cbs = {
618-
.damage = screen_damage,
619-
.moverect = moverect,
620-
.movecursor = movecursor,
621-
.settermprop = settermprop,
622-
.sb_pushline = screen_sb_pushline,
623-
.sb_popline = screen_sb_popline,
624-
.sb_clear = screen_sb_clear,
631+
.damage = screen_damage,
632+
.moverect = moverect,
633+
.movecursor = movecursor,
634+
.settermprop = settermprop,
635+
.sb_popline = screen_sb_popline,
636+
.sb_clear = screen_sb_clear,
637+
.sb_pushline4 = screen_sb_pushline4,
625638
};
626639

627640
int main(int argc, char **argv)
@@ -657,6 +670,7 @@ int main(int argc, char **argv)
657670
if(!state) {
658671
state = vterm_obtain_state(vt);
659672
vterm_state_set_callbacks(state, &state_cbs, NULL);
673+
vterm_state_callbacks_has_premove(state);
660674
/* In some tests we want to check the behaviour of overflowing the
661675
* buffer, so make it nicely small
662676
*/
@@ -683,6 +697,9 @@ int main(int argc, char **argv)
683697
case 's':
684698
want_scrollrect = sense;
685699
break;
700+
case 'P':
701+
want_premove = sense;
702+
break;
686703
case 'm':
687704
want_moverect = sense;
688705
break;
@@ -708,6 +725,7 @@ int main(int argc, char **argv)
708725
if(!screen)
709726
screen = vterm_obtain_screen(vt);
710727
vterm_screen_set_callbacks(screen, &screen_cbs, NULL);
728+
vterm_screen_callbacks_has_pushline4(screen);
711729

712730
int i = 10;
713731
int sense = 1;

0 commit comments

Comments
 (0)