Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render using canvas #938

Merged
merged 108 commits into from
Sep 8, 2017
Merged
Show file tree
Hide file tree
Changes from 106 commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
c6d4c73
Initial prototype
Tyriar Aug 30, 2017
640cd18
Support bold, underline, fix colors
Tyriar Aug 31, 2017
e98794a
progress
Tyriar Aug 31, 2017
5ce39d3
GPU ascii rendering
Tyriar Aug 31, 2017
137847e
Linkify all rows at once to prevent multiple timeout restarts
Tyriar Aug 31, 2017
0db42e2
Pull bg rendering into an IRenderLayer
Tyriar Aug 31, 2017
5961bdb
[email protected] for ImageBitmap interface
Tyriar Aug 31, 2017
2cb6593
Move fg rendering into IRenderLayer
Tyriar Aug 31, 2017
18e1134
Tidy up
Tyriar Aug 31, 2017
129633a
Only draw background when needed
Tyriar Aug 31, 2017
d93a803
Draw unicode characters
Tyriar Aug 31, 2017
6a0b9bd
Only render fg cells if there are changes
Tyriar Aug 31, 2017
1291dc5
Support inverse
Tyriar Aug 31, 2017
a224ed7
Move canvas Renderer into folder
Tyriar Aug 31, 2017
7aff45c
Remove additional frame skipping as rendering is so fast now
Tyriar Aug 31, 2017
5953bba
Start SelectionRenderLayer
Tyriar Aug 31, 2017
3d1bb2c
Support selection
Tyriar Aug 31, 2017
d601f0a
Hang on to selection state to avoid redrawing
Tyriar Aug 31, 2017
dff3d16
Support 256 color
Tyriar Aug 31, 2017
d3650d9
Draw selection underneath foreground
Tyriar Aug 31, 2017
fd18f7c
Support basic cursor
Tyriar Sep 1, 2017
a91380a
Pull common parts into BaseRenderLayer
Tyriar Sep 1, 2017
fe7b424
Move char atlas into BaseRenderLayer
Tyriar Sep 1, 2017
1998675
Move char drawing to base and use in cursor layer
Tyriar Sep 1, 2017
c888241
Simplify color generation code
Tyriar Sep 1, 2017
15c73ef
Add fontSize and fontFamily options
Tyriar Sep 1, 2017
6588e9e
Fix cursor which cursor character is rendered
Tyriar Sep 1, 2017
9323833
Move scaledCharWidth/Height into base render layer
Tyriar Sep 1, 2017
5109403
Provide convenience draw methods that deal with cells
Tyriar Sep 1, 2017
42e5b34
Don't clear fg char if it's null or ' '
Tyriar Sep 1, 2017
81d93b8
Ensure CharMeasure exposes integers
Tyriar Sep 1, 2017
848c85c
Fix more cases where ' ' doesn't have code
Tyriar Sep 1, 2017
882d7e4
Add basic support for cursor blinking
Tyriar Sep 1, 2017
3fc500b
Pull cursor animation state management into a helper class
Tyriar Sep 1, 2017
076156b
Properly support blinking cursors
Tyriar Sep 1, 2017
62fea4d
Add theme support
Tyriar Sep 1, 2017
bc3bdac
Add a char atlas cache to allow different styles+reuse across terminals
Tyriar Sep 1, 2017
de4fcb9
Merge render layer interface types
Tyriar Sep 1, 2017
2c9dbc6
Add some jsdoc
Tyriar Sep 1, 2017
bf95333
Fix the fit addon
Tyriar Sep 2, 2017
1f444b1
Support invisible attr
Tyriar Sep 2, 2017
70764a7
Use the proper bg/fg colors for inverse attr
Tyriar Sep 2, 2017
b0653fe
Support underline
Tyriar Sep 2, 2017
5cd189e
Fix demo pty size
Tyriar Sep 2, 2017
6ee8e91
Remove some old dead code
Tyriar Sep 2, 2017
b57b94a
Improve focus/blur state, fire only once
Tyriar Sep 2, 2017
dc1e727
Support blurred cursor
Tyriar Sep 2, 2017
4919c40
Add cursor to ITheme
Tyriar Sep 2, 2017
f8ece10
Rerender cursor if state changes
Tyriar Sep 2, 2017
06b5458
Fix cursor render when after focusing underline/bar
Tyriar Sep 2, 2017
cf7237d
Fix remaining cursor animation state issues
Tyriar Sep 2, 2017
36a723c
Fix 256 FG chars
Tyriar Sep 2, 2017
6dd6d03
Add cell spacing to char atlas
Tyriar Sep 2, 2017
ae72e1c
Fix uncached chars bleeding into other cells
Tyriar Sep 2, 2017
32a3c98
Support wide character drawing and cursors
Tyriar Sep 2, 2017
b8732a2
Support Safari
Tyriar Sep 2, 2017
ee4b71c
Remove Terminal.options.colors
Tyriar Sep 2, 2017
9cabb93
Organize temporary color handling code
Tyriar Sep 2, 2017
c92a2f9
Support lineHeight
Tyriar Sep 2, 2017
66d41fe
Expose setTheme through .d.ts
Tyriar Sep 2, 2017
24a98f2
Remove rowContainer and children, disable Linkifier
Tyriar Sep 2, 2017
8039fd3
Remove unused CSS, selectionElement
Tyriar Sep 2, 2017
4f81cdf
Make the terminal background theme aware
Tyriar Sep 2, 2017
c5a6d96
Remove padding from terminal, not support atm
Tyriar Sep 2, 2017
7ccac09
Fix the composition element's position
Tyriar Sep 3, 2017
c94e874
Fix CharMeasure getting taller on successive calls
Tyriar Sep 3, 2017
7973b26
Include new options in ITerminalOptions
Tyriar Sep 3, 2017
8427f74
Clear state when resizing as canvases get cleared
Tyriar Sep 3, 2017
fd4e9d8
Fix graphical glitch wide chars would leave behind
Tyriar Sep 3, 2017
5a48516
Prevent updating of invalid terminal row ranges
Tyriar Sep 3, 2017
deb47e2
Fix canvas resizing with non-1 lineHeight
Tyriar Sep 3, 2017
a3297b0
Fix viewport/background size after char size changed
Tyriar Sep 3, 2017
bc3470c
Fix default bold text
Tyriar Sep 3, 2017
48b3745
Ensure char measure's line height isn't influenced by outside
Tyriar Sep 3, 2017
2d1a1bf
Fix inconsistency with lineHeight
Tyriar Sep 3, 2017
5619abe
Basic link support using mouse zone manager
Tyriar Sep 3, 2017
923ea72
Get links working on proper coords
Tyriar Sep 3, 2017
b30cb58
Support hover callback in links
Tyriar Sep 3, 2017
17731c3
Support multiple links in a line, fix Linkifier tests
Tyriar Sep 3, 2017
e518ea0
Get tests reporting failures again
Tyriar Sep 3, 2017
3677818
Fix tests
Tyriar Sep 3, 2017
e123dd1
Null check if clicking on scroll bar
Tyriar Sep 4, 2017
7934e05
jsdoc Linkifier
Tyriar Sep 4, 2017
e77f1a9
Use default colors if not defined in a theme
Tyriar Sep 4, 2017
29a7ee3
Fix lint
Tyriar Sep 4, 2017
0bfdff0
Theme unfocused cursor using cursor color
Tyriar Sep 4, 2017
ff31f34
Add selection to ITheme
Tyriar Sep 4, 2017
a179502
Support emoji
Tyriar Sep 4, 2017
1c3028c
Work around an emoji bug
Tyriar Sep 4, 2017
a35cf02
Add GridCache tests
Tyriar Sep 4, 2017
6f6f17f
Add tests for ColorManager
Tyriar Sep 4, 2017
1f38c2f
Remove unused file
Tyriar Sep 4, 2017
9506c01
Add tests for utils/Mouse
Tyriar Sep 4, 2017
da1e3b4
Don't use ImageBitmap on Firefox
Tyriar Sep 4, 2017
8e07af0
Drop support for IE/Opera and indicate latest
Tyriar Sep 4, 2017
0dc24cf
Move theme setting into setOption API
Tyriar Sep 4, 2017
46b0857
Resolve TODOs
Tyriar Sep 4, 2017
1e728d4
Add new API to typings test
Tyriar Sep 4, 2017
5c2d5dc
Document methods of BaseRenderLayer
Tyriar Sep 5, 2017
7b199ac
Some more documentation
Tyriar Sep 5, 2017
b69ff5d
Redraw terminal when devicePixelRatio changes
Tyriar Sep 6, 2017
fb90c98
Fix blurry text by supporting floating pt devicePixelRatios
Tyriar Sep 6, 2017
66c891d
Fix resize adding right padding on demo
Tyriar Sep 6, 2017
e960a0a
Add ILinkMatcherOptions.hoverEndCallback
Tyriar Sep 6, 2017
67962a5
[email protected]
Tyriar Sep 7, 2017
ea8dbbd
Underline links on hover
Tyriar Sep 7, 2017
75b91c6
Update license text
Tyriar Sep 8, 2017
0c19bc9
Fix tests
Tyriar Sep 8, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,10 @@ xterm.fit();

Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Here is a list of the versions we aim to support:

- Chrome 48+
- Edge 13+
- Firefox 44+
- Internet Explorer 11+
- Opera 35+
- Safari 8+
- Chrome latest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we be a little bit more precise here? Latest is a moving frame, and in some terms even inaccurate because we cannot always guarantee that xterm.js will work after an API change on one of those engines?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breakages from going up versions are not likely to happen on browsers and they deprecate and change behavior very slowly. The main point this is trying to get across is that this is for developers which should be on updated browsers. I certainly don't go back and check my features on Chrome 48, I do make sure they work on Blink, Gecko, etc. though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But does that also imply that we can start using a browser feature (like IntersectionObserver, ResizeObserver, async / await etc.) once that feature is supported by the aforementioned list of supported browsers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and we absolutely should imo. window.createImageBitmap for example is implemented using progressive enhancement, falling back to a HTMLElement because Firefox and Safari are lacking here. It provides a 2x speed up when I measured it on Chrome though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things like async/await have the potential to break an awful lot of older browsers so we should be mindful of that, we're not trying to kill old browser support but rather guarantee it works on the latest (unless it becomes a nuisance).

- Edge latest
- Firefox latest
- Safari latest

Xterm.js works seamlessly in Electron apps and may even work on earlier versions of the browsers but these are the browsers we strive to keep working.

Expand Down
49 changes: 24 additions & 25 deletions demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ var term,
protocol,
socketURL,
socket,
pid,
charWidth,
charHeight;
pid;

var terminalContainer = document.getElementById('terminal-container'),
actionElements = {
Expand All @@ -21,11 +19,13 @@ var terminalContainer = document.getElementById('terminal-container'),
colsElement = document.getElementById('cols'),
rowsElement = document.getElementById('rows');

function setTerminalSize () {
var cols = parseInt(colsElement.value, 10),
rows = parseInt(rowsElement.value, 10),
width = (cols * charWidth).toString() + 'px',
height = (rows * charHeight).toString() + 'px';
function setTerminalSize() {
var cols = parseInt(colsElement.value, 10);
var rows = parseInt(rowsElement.value, 10);
var viewportElement = document.querySelector('.xterm-viewport');
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px';
var height = (rows * term.charMeasure.height).toString() + 'px';

terminalContainer.style.width = width;
terminalContainer.style.height = height;
Expand Down Expand Up @@ -92,27 +92,26 @@ function createTerminal() {
term.open(terminalContainer);
term.fit();

var initialGeometry = term.proposeGeometry(),
cols = initialGeometry.cols,
rows = initialGeometry.rows;
// fit is called within a setTimeout, cols and rows need this.
setTimeout(() => {
colsElement.value = term.cols;
rowsElement.value = term.rows;

colsElement.value = cols;
rowsElement.value = rows;
// Set terminal size again to set the specific dimensions on the demo
setTerminalSize();

fetch('/terminals?cols=' + cols + '&rows=' + rows, {method: 'POST'}).then(function (res) {
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {

charWidth = Math.ceil(term.element.offsetWidth / cols);
charHeight = Math.ceil(term.element.offsetHeight / rows);

res.text().then(function (pid) {
window.pid = pid;
socketURL += pid;
socket = new WebSocket(socketURL);
socket.onopen = runRealTerminal;
socket.onclose = runFakeTerminal;
socket.onerror = runFakeTerminal;
res.text().then(function (pid) {
window.pid = pid;
socketURL += pid;
socket = new WebSocket(socketURL);
socket.onopen = runRealTerminal;
socket.onclose = runFakeTerminal;
socket.onerror = runFakeTerminal;
});
});
});
}, 0);
}

function runRealTerminal() {
Expand Down
6 changes: 0 additions & 6 deletions demo/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,3 @@ h1 {
margin: 0 auto;
padding: 2px;
}

#terminal-container .terminal {
background-color: #111;
color: #fafafa;
padding: 2px;
}
11 changes: 9 additions & 2 deletions fixtures/typings-test/typings-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ namespace methods_core {
t.setOption('bellStyle', 'visual');
t.setOption('bellStyle', 'sound');
t.setOption('bellStyle', 'both');
t.setOption('fontSize', 1);
t.setOption('lineHeight', 1);
t.setOption('fontFamily', 'foo');
t.setOption('theme', {background: '#ff0000'});
}
}
namespace scrolling {
Expand Down Expand Up @@ -210,8 +214,11 @@ namespace methods_experimental {
t.registerLinkMatcher(/foo/, () => true, {
matchIndex: 1,
priority: 1,
validationCallback: (uri: string, element: HTMLElement, callback: (isValid: boolean) => void) => {
console.log(uri, element, callback);
validationCallback: (uri: string, callback: (isValid: boolean) => void) => {
console.log(uri, callback);
},
hoverCallback: (e: MouseEvent, uri: string) => {
console.log(e, uri);
}
});
t.deregisterLinkMatcher(1);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"nodemon": "1.10.2",
"sorcery": "^0.10.0",
"tslint": "^4.0.2",
"typescript": "~2.2.0",
"typescript": "~2.4.0",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
},
Expand Down
14 changes: 11 additions & 3 deletions src/Buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { ITerminal, IBuffer } from './Interfaces';
import { CircularList } from './utils/CircularList';
import { LineData, CharData } from './Types';

export const CHAR_DATA_ATTR_INDEX = 0;
export const CHAR_DATA_CHAR_INDEX = 1;
export const CHAR_DATA_WIDTH_INDEX = 2;
export const CHAR_DATA_CODE_INDEX = 3;

/**
* This class represents a terminal buffer (an internal state of the terminal), where the
Expand All @@ -32,8 +34,8 @@ export class Buffer implements IBuffer {
/**
* Create a new Buffer.
* @param _terminal The terminal the Buffer will belong to.
* @param _hasScrollback Whether the buffer should respecr the scrollback of
* the terminal..
* @param _hasScrollback Whether the buffer should respect the scrollback of
* the terminal.
*/
constructor(
private _terminal: ITerminal,
Expand All @@ -50,6 +52,12 @@ export class Buffer implements IBuffer {
return this._hasScrollback && this.lines.maxLength > this._terminal.rows;
}

public get isCursorInViewport(): boolean {
const absoluteY = this.ybase + this.y;
const relativeY = absoluteY - this.ydisp;
return (relativeY >= 0 && relativeY < this._terminal.rows);
}

/**
* Gets the correct buffer length based on the rows provided, the terminal's
* scrollback and whether this buffer is flagged to have scrollback or not.
Expand Down Expand Up @@ -106,7 +114,7 @@ export class Buffer implements IBuffer {
if (this._lines.length > 0) {
// Deal with columns increasing (we don't do anything when columns reduce)
if (this._terminal.cols < newCols) {
const ch: CharData = [this._terminal.defAttr, ' ', 1]; // does xterm use the default attr?
const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr?
for (let i = 0; i < this._lines.length; i++) {
// TODO: This should be removed, with tests setup for the case that was
// causing the underlying bug, see https://github.com/sourcelair/xterm.js/issues/824
Expand Down
10 changes: 10 additions & 0 deletions src/CompositionHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ describe('CompositionHelper', () => {
},
handler: (text: string) => {
handledText += text;
},
buffer: {
isCursorInViewport: true
},
charMeasure: {
height: 10,
width: 10
},
options: {
lineHeight: 1
}
};
handledText = '';
Expand Down
23 changes: 12 additions & 11 deletions src/CompositionHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export class CompositionHelper {
* @param {CompositionEvent} ev The event.
*/
public compositionupdate(ev: CompositionEvent): void {
console.log('compositionupdate');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a logger here I think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch 😅 #983

this.compositionView.textContent = ev.data;
this.updateCompositionElements();
setTimeout(() => {
Expand Down Expand Up @@ -193,26 +194,26 @@ export class CompositionHelper {
if (!this.isComposing) {
return;
}
const cursor = <HTMLElement>this.terminal.element.querySelector('.terminal-cursor');
if (cursor) {
// Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within
// the .xterm element.
const xtermRows = <HTMLElement>this.terminal.element.querySelector('.xterm-rows');
const cursorTop = xtermRows.offsetTop + cursor.offsetTop;

this.compositionView.style.left = cursor.offsetLeft + 'px';

if (this.terminal.buffer.isCursorInViewport) {
const cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight);
const cursorTop = this.terminal.buffer.y * cellHeight;
const cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width;

this.compositionView.style.left = cursorLeft + 'px';
this.compositionView.style.top = cursorTop + 'px';
this.compositionView.style.height = cursor.offsetHeight + 'px';
this.compositionView.style.lineHeight = cursor.offsetHeight + 'px';
this.compositionView.style.height = cellHeight + 'px';
this.compositionView.style.lineHeight = cellHeight + 'px';
// Sync the textarea to the exact position of the composition view so the IME knows where the
// text is.
const compositionViewBounds = this.compositionView.getBoundingClientRect();
this.textarea.style.left = cursor.offsetLeft + 'px';
this.textarea.style.left = cursorLeft + 'px';
this.textarea.style.top = cursorTop + 'px';
this.textarea.style.width = compositionViewBounds.width + 'px';
this.textarea.style.height = compositionViewBounds.height + 'px';
this.textarea.style.lineHeight = compositionViewBounds.height + 'px';
}

if (!dontRecurse) {
setTimeout(() => this.updateCompositionElements(true), 0);
}
Expand Down
23 changes: 12 additions & 11 deletions src/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ export class InputHandler implements IInputHandler {
// dont overflow left
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {
if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) {

// found empty cell after fullwidth, need to go 2 cells back
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2])
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) {
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][CHAR_DATA_CHAR_INDEX] += char;

this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0);
}
} else {
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_CHAR_INDEX] += char;
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0);
}
this._terminal.updateRange(this._terminal.buffer.y);
}
Expand Down Expand Up @@ -81,21 +82,21 @@ export class InputHandler implements IInputHandler {
if (removed[CHAR_DATA_WIDTH_INDEX] === 0
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2]
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][CHAR_DATA_WIDTH_INDEX] === 2) {
this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)];
}

// insert empty cell at cursor
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1]);
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]);
}
}

this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width];
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)];
this._terminal.buffer.x++;
this._terminal.updateRange(this._terminal.buffer.y);

// fullwidth char - set next cell width to zero and advance cursor
if (ch_width === 2) {
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0];
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined];
this._terminal.buffer.x++;
}
}
Expand Down Expand Up @@ -188,7 +189,7 @@ export class InputHandler implements IInputHandler {

const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
let j = this._terminal.buffer.x;
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm

while (param-- && j < this._terminal.cols) {
this._terminal.buffer.lines.get(row).splice(j++, 0, ch);
Expand Down Expand Up @@ -487,7 +488,7 @@ export class InputHandler implements IInputHandler {
}

const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm

while (param--) {
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1);
Expand Down Expand Up @@ -535,7 +536,7 @@ export class InputHandler implements IInputHandler {

const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
let j = this._terminal.buffer.x;
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm

while (param-- && j < this._terminal.cols) {
this._terminal.buffer.lines.get(row)[j++] = ch;
Expand Down Expand Up @@ -589,7 +590,7 @@ export class InputHandler implements IInputHandler {
public repeatPrecedingCharacter(params: number[]): void {
let param = params[0] || 1;
const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y);
const ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1];
const ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32];

while (param--) {
line[this._terminal.buffer.x++] = ch;
Expand Down
Loading