@@ -320,7 +320,37 @@ export class Buffer implements IBuffer {
320
320
if ( toRemove . length > 0 ) {
321
321
const newLayoutResult = reflowLargerCreateNewLayout ( this . lines , toRemove ) ;
322
322
reflowLargerApplyNewLayout ( this . lines , newLayoutResult . layout ) ;
323
+
324
+ // For conpty, it has its own copy of the buffer _without scrollback_ internally. Its behavior
325
+ // when reflowing larger is to insert empty lines at the bottom of the buffer as when lines
326
+ // unwrap conpty's view cannot pull scrollback down, so it adds empty lines at the end.
327
+ let removedInViewport = 0 ;
328
+ const isWindowsMode = this . _optionsService . rawOptions . windowsMode || this . _optionsService . rawOptions . windowsPty . backend !== undefined || this . _optionsService . rawOptions . windowsPty . buildNumber !== undefined ;
329
+ if ( isWindowsMode ) {
330
+ for ( let i = ( toRemove . length / 2 ) - 1 ; i >= 0 ; i -- ) {
331
+ if ( toRemove [ i * 2 + 0 ] > this . ybase + removedInViewport ) {
332
+ removedInViewport += toRemove [ i * 2 + 1 ] ;
333
+ }
334
+ }
335
+ }
336
+
323
337
this . _reflowLargerAdjustViewport ( newCols , newRows , newLayoutResult . countRemoved ) ;
338
+
339
+ // Apply empty lines for any removed in viewport for conpty.
340
+ if ( isWindowsMode ) {
341
+ if ( removedInViewport > 0 ) {
342
+ for ( let i = 0 ; i < removedInViewport ; i ++ ) {
343
+ // Just add the new missing rows on Windows as conpty reprints the screen with it's
344
+ // view of the world. Once a line enters scrollback for conpty it remains there
345
+ this . lines . push ( new BufferLine ( newCols , this . getNullCell ( DEFAULT_ATTR_DATA ) ) ) ;
346
+ }
347
+ if ( this . ybase === this . ydisp ) {
348
+ this . ydisp += removedInViewport ;
349
+ }
350
+ this . ybase += removedInViewport ;
351
+ this . y -= removedInViewport ;
352
+ }
353
+ }
324
354
}
325
355
}
326
356
@@ -352,7 +382,7 @@ export class Buffer implements IBuffer {
352
382
const nullCell = this . getNullCell ( DEFAULT_ATTR_DATA ) ;
353
383
// Gather all BufferLines that need to be inserted into the Buffer here so that they can be
354
384
// batched up and only committed once
355
- const toInsert = [ ] ;
385
+ const toInsert : { start : number , newLines : IBufferLine [ ] } [ ] = [ ] ;
356
386
let countToInsert = 0 ;
357
387
// Go backwards as many lines may be trimmed and this will avoid considering them
358
388
for ( let y = this . lines . length - 1 ; y >= 0 ; y -- ) {
@@ -467,6 +497,20 @@ export class Buffer implements IBuffer {
467
497
this . savedY = Math . min ( this . savedY + linesToAdd , this . ybase + newRows - 1 ) ;
468
498
}
469
499
500
+ // For conpty, it has its own copy of the buffer _without scrollback_ internally. Its behavior
501
+ // when reflowing smaller is to reflow all lines inside the viewport, and removing empty or
502
+ // whitespace only lines from the bottom, until non-whitespace is hit in order to prevent
503
+ // content from being pushed into the scrollback.
504
+ let addedInViewport = 0 ;
505
+ const isWindowsMode = this . _optionsService . rawOptions . windowsMode || this . _optionsService . rawOptions . windowsPty . backend !== undefined || this . _optionsService . rawOptions . windowsPty . buildNumber !== undefined ;
506
+ if ( isWindowsMode ) {
507
+ for ( let i = toInsert . length - 1 ; i >= 0 ; i -- ) {
508
+ if ( toInsert [ i ] . start > this . ybase + addedInViewport ) {
509
+ addedInViewport += toInsert [ i ] . newLines . length ;
510
+ }
511
+ }
512
+ }
513
+
470
514
// Rearrange lines in the buffer if there are any insertions, this is done at the end rather
471
515
// than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many
472
516
// costly calls to CircularList.splice.
@@ -520,6 +564,35 @@ export class Buffer implements IBuffer {
520
564
this . lines . onTrimEmitter . fire ( amountToTrim ) ;
521
565
}
522
566
}
567
+
568
+ // Apply empty lines to remove calculated earlier for conpty.
569
+ if ( isWindowsMode ) {
570
+ if ( addedInViewport > 0 ) {
571
+ let emptyLinesAtBottom = 0 ;
572
+ for ( let i = this . lines . length - 1 ; i >= this . ybase + this . y ; i -- ) {
573
+ const line = this . lines . get ( i ) as BufferLine ;
574
+ if ( line . isWrapped || line . getTrimmedLength ( ) > 0 ) {
575
+ break ;
576
+ }
577
+ emptyLinesAtBottom ++ ;
578
+ }
579
+ const emptyLinesToRemove = Math . min ( addedInViewport , emptyLinesAtBottom ) ;
580
+ if ( emptyLinesToRemove > 0 ) {
581
+ for ( let i = 0 ; i < emptyLinesToRemove ; i ++ ) {
582
+ this . lines . pop ( ) ;
583
+ }
584
+ if ( this . ybase === this . ydisp ) {
585
+ this . ydisp -= emptyLinesToRemove ;
586
+ }
587
+ this . ybase -= emptyLinesToRemove ;
588
+ this . y += emptyLinesToRemove ;
589
+ this . lines . onDeleteEmitter . fire ( {
590
+ index : this . lines . length - emptyLinesToRemove ,
591
+ amount : emptyLinesToRemove
592
+ } ) ;
593
+ }
594
+ }
595
+ }
523
596
}
524
597
525
598
/**
0 commit comments