diff --git a/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text b/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text index 92c10331..f89893ba 100644 --- a/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text +++ b/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text @@ -1,3 +1,4 @@ + 6 C 8 ^^^^ 9 vvvv DL on line 11, expected: ACD_ 10 A @@ -12,14 +13,14 @@ 19 vvvv IL on line 21, expected: A_ 20 A + 22 ^^^^ - -23 vvvv IL on line 24, expected: _A +24 A 25 B -26 ^^^^ -28 A +27 vvvv DL on line 28, expected: B_ +28 A 29 B 30 ^^^^ 31 -32 +32 \ No newline at end of file diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index c21ca5f9..6d4a3ca8 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -15,6 +15,13 @@ import { AttributeData } from 'common/buffer/AttributeData'; import { Params } from 'common/parser/Params'; import { MockCoreService } from 'common/TestUtils.test'; +function getCursor(term: TestTerminal): number[] { + return [ + term.buffer.x, + term.buffer.y + ]; +} + describe('InputHandler', () => { describe('save and restore cursor', () => { const terminal = new MockInputHandlingTerminal(); @@ -702,12 +709,6 @@ describe('InputHandler', () => { beforeEach(() => { term = new TestTerminal({cols: 10, rows: 10}); }); - function getCursor(term: TestTerminal): number[] { - return [ - term.buffer.x, - term.buffer.y - ]; - } it('cursor forward (CUF)', () => { term.writeSync('\x1b[C'); assert.deepEqual(getCursor(term), [1, 0]); @@ -1104,8 +1105,14 @@ describe('InputHandler', () => { assert.equal(term.buffer.scrollTop, 0); assert.equal(term.buffer.scrollBottom, 9); }); + it('should home cursor', () => { + term.buffer.x = 10000; + term.buffer.y = 10000; + term.writeSync('\x1b[2;7r'); + assert.deepEqual(getCursor(term), [0, 0]); + }); }); - describe('scrolling', () => { + describe('scroll margins', () => { let term: TestTerminal; beforeEach(() => { term = new TestTerminal({cols: 10, rows: 10}); @@ -1117,13 +1124,63 @@ describe('InputHandler', () => { } return res; } - it('scrollUp with margins', () => { + it('scrollUp', () => { term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Sm'); assert.deepEqual(getLines(term), ['m', '3', '', '', '4', '5', '6', '7', '8', '9']); }); - it('scrollDown with margins', () => { + it('scrollDown', () => { term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Tm'); assert.deepEqual(getLines(term), ['m', '', '', '1', '4', '5', '6', '7', '8', '9']); }); + it('insertLines - out of margins', () => { + term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(term.buffer.scrollTop, 2); + assert.equal(term.buffer.scrollBottom, 5); + term.writeSync('\x1b[2Lm'); + assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); + term.writeSync('\x1b[2H\x1b[2Ln'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); + // skip below scrollbottom + term.writeSync('\x1b[7H\x1b[2Lo'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); + term.writeSync('\x1b[8H\x1b[2Lp'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); + term.writeSync('\x1b[100H\x1b[2Lq'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); + }); + it('insertLines - within margins', () => { + term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(term.buffer.scrollTop, 2); + assert.equal(term.buffer.scrollBottom, 5); + term.writeSync('\x1b[3H\x1b[2Lm'); + assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', '3', '6', '7', '8', '9']); + term.writeSync('\x1b[6H\x1b[2Ln'); + assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', 'n', '6', '7', '8', '9']); + }); + it('deleteLines - out of margins', () => { + term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(term.buffer.scrollTop, 2); + assert.equal(term.buffer.scrollBottom, 5); + term.writeSync('\x1b[2Mm'); + assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); + term.writeSync('\x1b[2H\x1b[2Mn'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); + // skip below scrollbottom + term.writeSync('\x1b[7H\x1b[2Mo'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); + term.writeSync('\x1b[8H\x1b[2Mp'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); + term.writeSync('\x1b[100H\x1b[2Mq'); + assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); + }); + it('deleteLines - within margins', () => { + term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(term.buffer.scrollTop, 2); + assert.equal(term.buffer.scrollBottom, 5); + term.writeSync('\x1b[6H\x1b[2Mm'); + assert.deepEqual(getLines(term), ['0', '1', '2', '3', '4', 'm', '6', '7', '8', '9']); + term.writeSync('\x1b[3H\x1b[2Mn'); + assert.deepEqual(getLines(term), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']); + }); }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 7bdd5fe4..1f1dee2e 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -847,6 +847,10 @@ export class InputHandler extends Disposable implements IInputHandler { // make buffer local for faster access const buffer = this._terminal.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } + const row: number = buffer.y + buffer.ybase; const scrollBottomRowsOffset = this._terminal.rows - 1 - buffer.scrollBottom; @@ -875,6 +879,10 @@ export class InputHandler extends Disposable implements IInputHandler { // make buffer local for faster access const buffer = this._terminal.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } + const row: number = buffer.y + buffer.ybase; let j: number; diff --git a/src/Terminal2.test.ts b/src/Terminal2.test.ts index b65a2e59..0555368b 100644 --- a/src/Terminal2.test.ts +++ b/src/Terminal2.test.ts @@ -119,12 +119,12 @@ if (os.platform() !== 'win32') { // 't0056-ED.in', // 't0060-DECSC.in', // 't0061-CSI_s.in', - 't0070-DECSTBM_LF.in', + 't0070-DECSTBM_LF.in', // lineFeed not working correctly 't0071-DECSTBM_IND.in', 't0072-DECSTBM_NEL.in', // 't0074-DECSTBM_SU_SD.in', 't0075-DECSTBM_CUU_CUD.in', - 't0076-DECSTBM_IL_DL.in', + 't0076-DECSTBM_IL_DL.in', // not working due to lineFeed 't0077-DECSTBM_quirks.in', // 't0080-HT.in', // 't0082-HTS.in',