From 2f0a4fc5c02d52351d7ab80b5de0f1453a70057c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 10 Jun 2021 10:35:58 +0200 Subject: [PATCH 1/2] allow cursor to stick at cols in ED/EL --- src/browser/Terminal2.test.ts | 1 + src/common/InputHandler.test.ts | 86 +++++++++++++++++++++++++++++++++ src/common/InputHandler.ts | 4 +- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/browser/Terminal2.test.ts b/src/browser/Terminal2.test.ts index 44540c6e2..4965e8f36 100644 --- a/src/browser/Terminal2.test.ts +++ b/src/browser/Terminal2.test.ts @@ -17,6 +17,7 @@ const ROWS = 25; const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '../..')}); const SKIP_FILES = [ + 't0055-EL.in', // EL/ED handle cursor at cols differently (see #3362) 't0084-CBT.in', 't0101-NLM.in', 't0103-reverse_wrap.in', // not comparable, we deviate from xterm reverse wrap on purpose diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index 676b1e453..58b1c5b88 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -1913,6 +1913,92 @@ describe('InputHandler', () => { }); }); }); + + // issue #3362 and #2979 + describe.only('EL/ED cursor at buffer.cols', () => { + beforeEach(() => { + bufferService.resize(10, 5); + }); + describe('cursor should stay at cols / does not overflow', () => { + it('EL0', async () => { + await inputHandler.parseP('##########\x1b[0K'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']); + }); + it('EL1', async () => { + await inputHandler.parseP('##########\x1b[1K'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['', '', '', '', '']); + }); + it('EL2', async () => { + await inputHandler.parseP('##########\x1b[2K'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['', '', '', '', '']); + }); + it('ED0', async () => { + await inputHandler.parseP('##########\x1b[0J'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']); + }); + it('ED1', async () => { + await inputHandler.parseP('##########\x1b[1J'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['', '', '', '', '']); + }); + it('ED2', async () => { + await inputHandler.parseP('##########\x1b[2J'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['', '', '', '', '']); + }); + it('ED3', async () => { + await inputHandler.parseP('##########\x1b[3J'); + assert.equal(bufferService.buffer.x, 10); + assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']); + }); + }); + describe('following sequence keeps working', () => { + // sequences to test (cursor related ones) + const SEQ = [ + /* ICH */ '\x1b[10@', + /* SL */ '\x1b[10 @', + /* CUU */ '\x1b[10A', + /* SR */ '\x1b[10 A', + /* CUD */ '\x1b[10B', + /* CUF */ '\x1b[10C', + /* CUB */ '\x1b[10D', + /* CNL */ '\x1b[10E', + /* CPL */ '\x1b[10F', + /* CHA */ '\x1b[10G', + /* CUP */ '\x1b[10;10H', + /* CHT */ '\x1b[10I', + /* IL */ '\x1b[10L', + /* DL */ '\x1b[10M', + /* DCH */ '\x1b[10P', + /* SU */ '\x1b[10S', + /* SD */ '\x1b[10T', + /* ECH */ '\x1b[10X', + /* CBT */ '\x1b[10Z', + /* HPA */ '\x1b[10`', + /* HPR */ '\x1b[10a', + /* REP */ '\x1b[10b', + /* VPA */ '\x1b[10d', + /* VPR */ '\x1b[10e', + /* HVP */ '\x1b[10;10f', + /* TBC */ '\x1b[0g', + /* SCOSC */ '\x1b[s', + /* DECIC */ '\x1b[10\'}', + /* DECDC */ '\x1b[10\'~' + ]; + it('cursor never advances beyond cols', async () => { + for (const seq of SEQ) { + await inputHandler.parseP('##########\x1b[2J' + seq); + assert.equal(bufferService.buffer.x <= bufferService.cols, true); + inputHandler.reset(); + bufferService.reset(); + } + }); + }); + }); }); diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index a2b5a7829..d3b29a702 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -1247,7 +1247,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #P[Protection attributes are not supported.] CSI DECSED "Selective Erase In Display" "CSI ? Ps J" "Currently the same as ED." */ public eraseInDisplay(params: IParams): boolean { - this._restrictCursor(); + this._restrictCursor(this._bufferService.cols); let j; switch (params.params[0]) { case 0: @@ -1319,7 +1319,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #P[Protection attributes are not supported.] CSI DECSEL "Selective Erase In Line" "CSI ? Ps K" "Currently the same as EL." */ public eraseInLine(params: IParams): boolean { - this._restrictCursor(); + this._restrictCursor(this._bufferService.cols); switch (params.params[0]) { case 0: this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._bufferService.cols); From 55cd97ec68fd138c6ba11c200278d4e4bb65329e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 10 Jun 2021 10:42:27 +0200 Subject: [PATCH 2/2] remove left over only test clause --- src/common/InputHandler.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index 58b1c5b88..902640f90 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -1915,7 +1915,7 @@ describe('InputHandler', () => { }); // issue #3362 and #2979 - describe.only('EL/ED cursor at buffer.cols', () => { + describe('EL/ED cursor at buffer.cols', () => { beforeEach(() => { bufferService.resize(10, 5); });