Pull more parts out of reflow larger

This commit is contained in:
Daniel Imms
2019-01-23 23:58:38 -08:00
parent dfff04cf3d
commit d4bd8ae2be
2 changed files with 60 additions and 53 deletions
+18 -52
View File
@@ -9,7 +9,7 @@ import { EventEmitter } from './common/EventEmitter';
import { IMarker } from 'xterm';
import { BufferLine } from './BufferLine';
import { DEFAULT_COLOR } from './renderer/atlas/Types';
import { reflowSmallerGetNewLineLengths, reflowLargerGetLinesToRemove } from './BufferReflow';
import { reflowSmallerGetNewLineLengths, reflowLargerGetLinesToRemove, reflowLargerCreateNewLayout, reflowLargerApplyNewLayout } from './BufferReflow';
export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);
export const CHAR_DATA_ATTR_INDEX = 0;
@@ -240,62 +240,28 @@ export class Buffer implements IBuffer {
}
private _reflowLarger(newCols: number): void {
// TODO: Can toRemove be pulled out into BufferReflow?
// Gather all BufferLines that need to be removed from the Buffer here so that they can be
// batched up and only committed once
const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, newCols);
if (toRemove.length > 0) {
// First iterate through the list and get the actual indexes to use for rows
const newLayout: number[] = [];
const countRemoved = reflowLargerCreateNewLayout(this.lines, toRemove, newLayout);
reflowLargerApplyNewLayout(this.lines, newLayout);
this._reflowLargerAdjustViewport(newCols, countRemoved);
}
}
let nextToRemoveIndex = 0;
let nextToRemoveStart = toRemove[nextToRemoveIndex];
let countRemovedSoFar = 0;
for (let i = 0; i < this.lines.length; i++) {
if (nextToRemoveStart === i) {
const countToRemove = toRemove[++nextToRemoveIndex];
// Tell markers that there was a deletion
this.lines.emit('delete', {
index: i - countRemovedSoFar,
amount: countToRemove
} as IDeleteEvent);
i += countToRemove - 1;
countRemovedSoFar += countToRemove;
nextToRemoveStart = toRemove[++nextToRemoveIndex];
} else {
newLayout.push(i);
}
}
// Record original lines so they don't get overridden when we rearrange the list
const newLayoutLines: BufferLine[] = [];
for (let i = 0; i < newLayout.length; i++) {
newLayoutLines.push(this.lines.get(newLayout[i]) as BufferLine);
}
// Rearrange the list
for (let i = 0; i < newLayoutLines.length; i++) {
this.lines.set(i, newLayoutLines[i]);
}
this.lines.length = newLayout.length;
// Adjust viewport based on number of items removed
let viewportAdjustments = countRemovedSoFar;
while (viewportAdjustments-- > 0) {
if (this.ybase === 0) {
this.y--;
// Add an extra row at the bottom of the viewport
this.lines.push(new BufferLine(newCols, FILL_CHAR_DATA));
} else {
if (this.ydisp === this.ybase) {
this.ydisp--;
}
this.ybase--;
private _reflowLargerAdjustViewport(newCols: number, countRemoved: number): void {
// Adjust viewport based on number of items removed
let viewportAdjustments = countRemoved;
while (viewportAdjustments-- > 0) {
if (this.ybase === 0) {
this.y--;
// Add an extra row at the bottom of the viewport
this.lines.push(new BufferLine(newCols, FILL_CHAR_DATA));
} else {
if (this.ydisp === this.ybase) {
this.ydisp--;
}
this.ybase--;
}
}
}
+42 -1
View File
@@ -4,11 +4,13 @@
*/
import { BufferLine } from './BufferLine';
import { CircularList } from './common/CircularList';
import { CircularList, IDeleteEvent } from './common/CircularList';
import { IBufferLine } from './Types';
import { FILL_CHAR_DATA } from './Buffer';
export function reflowLargerGetLinesToRemove(lines: CircularList<IBufferLine>, newCols: number): number[] {
// Gather all BufferLines that need to be removed from the Buffer here so that they can be
// batched up and only committed once
const toRemove: number[] = [];
for (let y = 0; y < lines.length - 1; y++) {
@@ -83,6 +85,45 @@ export function reflowLargerGetLinesToRemove(lines: CircularList<IBufferLine>, n
return toRemove;
}
export function reflowLargerCreateNewLayout(lines: CircularList<IBufferLine>, toRemove: number[], newLayout: number[]): number {
// First iterate through the list and get the actual indexes to use for rows
let nextToRemoveIndex = 0;
let nextToRemoveStart = toRemove[nextToRemoveIndex];
let countRemovedSoFar = 0;
for (let i = 0; i < lines.length; i++) {
if (nextToRemoveStart === i) {
const countToRemove = toRemove[++nextToRemoveIndex];
// Tell markers that there was a deletion
lines.emit('delete', {
index: i - countRemovedSoFar,
amount: countToRemove
} as IDeleteEvent);
i += countToRemove - 1;
countRemovedSoFar += countToRemove;
nextToRemoveStart = toRemove[++nextToRemoveIndex];
} else {
newLayout.push(i);
}
}
return countRemovedSoFar;
}
export function reflowLargerApplyNewLayout(lines: CircularList<IBufferLine>, newLayout: number[]): void {
// Record original lines so they don't get overridden when we rearrange the list
const newLayoutLines: BufferLine[] = [];
for (let i = 0; i < newLayout.length; i++) {
newLayoutLines.push(lines.get(newLayout[i]) as BufferLine);
}
// Rearrange the list
for (let i = 0; i < newLayoutLines.length; i++) {
lines.set(i, newLayoutLines[i]);
}
lines.length = newLayout.length;
}
/**
* Gets the new line lengths for a given wrapped line. The purpose of this function it to pre-
* compute the wrapping points since wide characters may need to be wrapped onto the following line.