Merge branch 'master' into 1990_layering_libs
This commit is contained in:
+36
-34
@@ -3,15 +3,15 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminal, ISelectionManager, IBuffer, CharData, IBufferLine } from './Types';
|
||||
import { ITerminal, ISelectionManager, IBuffer, IBufferLine } from './Types';
|
||||
import { XtermListener } from './common/Types';
|
||||
import { MouseHelper } from './ui/MouseHelper';
|
||||
import * as Browser from './common/Platform';
|
||||
import { CharMeasure } from './ui/CharMeasure';
|
||||
import { EventEmitter } from './common/EventEmitter';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';
|
||||
import { AltClickHandler } from './handlers/AltClickHandler';
|
||||
import { CellData } from './BufferLine';
|
||||
|
||||
/**
|
||||
* The number of pixels the mouse needs to be above or below the viewport in
|
||||
@@ -103,6 +103,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
private _mouseMoveListener: EventListener;
|
||||
private _mouseUpListener: EventListener;
|
||||
private _trimListener: XtermListener;
|
||||
private _workCell: CellData = new CellData();
|
||||
|
||||
private _mouseDownTimeStamp: number;
|
||||
|
||||
@@ -506,8 +507,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
|
||||
// If the mouse is over the second half of a wide character, adjust the
|
||||
// selection to cover the whole character
|
||||
const char = line.get(this._model.selectionStart[0]);
|
||||
if (char[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
if (line.hasWidth(this._model.selectionStart[0]) === 0) {
|
||||
this._model.selectionStart[0]++;
|
||||
}
|
||||
}
|
||||
@@ -596,8 +596,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
// selection. Note that selections at the very end of the line will never
|
||||
// have a character.
|
||||
if (this._model.selectionEnd[1] < this._buffer.lines.length) {
|
||||
const char = this._buffer.lines.get(this._model.selectionEnd[1]).get(this._model.selectionEnd[0]);
|
||||
if (char && char[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
if (this._buffer.lines.get(this._model.selectionEnd[1]).hasWidth(this._model.selectionEnd[0]) === 0) {
|
||||
this._model.selectionEnd[0]++;
|
||||
}
|
||||
}
|
||||
@@ -670,16 +669,16 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
private _convertViewportColToCharacterIndex(bufferLine: IBufferLine, coords: [number, number]): number {
|
||||
let charIndex = coords[0];
|
||||
for (let i = 0; coords[0] >= i; i++) {
|
||||
const char = bufferLine.get(i);
|
||||
if (char[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
const length = bufferLine.loadCell(i, this._workCell).getChars().length;
|
||||
if (this._workCell.getWidth() === 0) {
|
||||
// Wide characters aren't included in the line string so decrement the
|
||||
// index so the index is back on the wide character.
|
||||
charIndex--;
|
||||
} else if (char[CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) {
|
||||
} else if (length > 1 && coords[0] !== i) {
|
||||
// Emojis take up multiple characters, so adjust accordingly. For these
|
||||
// we don't want ot include the character at the column as we're
|
||||
// returning the start index in the string, not the end index.
|
||||
charIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
charIndex += length - 1;
|
||||
}
|
||||
}
|
||||
return charIndex;
|
||||
@@ -739,48 +738,51 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
|
||||
// Consider the initial position, skip it and increment the wide char
|
||||
// variable
|
||||
if (bufferLine.get(startCol)[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
if (bufferLine.getWidth(startCol) === 0) {
|
||||
leftWideCharCount++;
|
||||
startCol--;
|
||||
}
|
||||
if (bufferLine.get(endCol)[CHAR_DATA_WIDTH_INDEX] === 2) {
|
||||
if (bufferLine.getWidth(endCol) === 2) {
|
||||
rightWideCharCount++;
|
||||
endCol++;
|
||||
}
|
||||
|
||||
// Adjust the end index for characters whose length are > 1 (emojis)
|
||||
if (bufferLine.get(endCol)[CHAR_DATA_CHAR_INDEX].length > 1) {
|
||||
rightLongCharOffset += bufferLine.get(endCol)[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
endIndex += bufferLine.get(endCol)[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
const length = bufferLine.getString(endCol).length;
|
||||
if (length > 1) {
|
||||
rightLongCharOffset += length - 1;
|
||||
endIndex += length - 1;
|
||||
}
|
||||
|
||||
// Expand the string in both directions until a space is hit
|
||||
while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine.get(startCol - 1))) {
|
||||
const char = bufferLine.get(startCol - 1);
|
||||
if (char[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine.loadCell(startCol - 1, this._workCell))) {
|
||||
bufferLine.loadCell(startCol - 1, this._workCell);
|
||||
const length = this._workCell.getChars().length;
|
||||
if (this._workCell.getWidth() === 0) {
|
||||
// If the next character is a wide char, record it and skip the column
|
||||
leftWideCharCount++;
|
||||
startCol--;
|
||||
} else if (char[CHAR_DATA_CHAR_INDEX].length > 1) {
|
||||
} else if (length > 1) {
|
||||
// If the next character's string is longer than 1 char (eg. emoji),
|
||||
// adjust the index
|
||||
leftLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
startIndex -= char[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
leftLongCharOffset += length - 1;
|
||||
startIndex -= length - 1;
|
||||
}
|
||||
startIndex--;
|
||||
startCol--;
|
||||
}
|
||||
while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine.get(endCol + 1))) {
|
||||
const char = bufferLine.get(endCol + 1);
|
||||
if (char[CHAR_DATA_WIDTH_INDEX] === 2) {
|
||||
while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine.loadCell(endCol + 1, this._workCell))) {
|
||||
bufferLine.loadCell(endCol + 1, this._workCell);
|
||||
const length = this._workCell.getChars().length;
|
||||
if (this._workCell.getWidth() === 2) {
|
||||
// If the next character is a wide char, record it and skip the column
|
||||
rightWideCharCount++;
|
||||
endCol++;
|
||||
} else if (char[CHAR_DATA_CHAR_INDEX].length > 1) {
|
||||
} else if (length > 1) {
|
||||
// If the next character's string is longer than 1 char (eg. emoji),
|
||||
// adjust the index
|
||||
rightLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
|
||||
rightLongCharOffset += length - 1;
|
||||
endIndex += length - 1;
|
||||
}
|
||||
endIndex++;
|
||||
endCol++;
|
||||
@@ -814,9 +816,9 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
|
||||
// Recurse upwards if the line is wrapped and the word wraps to the above line
|
||||
if (followWrappedLinesAbove) {
|
||||
if (start === 0 && bufferLine.get(0)[CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {
|
||||
if (start === 0 && bufferLine.getCodePoint(0) !== 32 /*' '*/) {
|
||||
const previousBufferLine = this._buffer.lines.get(coords[1] - 1);
|
||||
if (previousBufferLine && bufferLine.isWrapped && previousBufferLine.get(this._terminal.cols - 1)[CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {
|
||||
if (previousBufferLine && bufferLine.isWrapped && previousBufferLine.getCodePoint(this._terminal.cols - 1) !== 32 /*' '*/) {
|
||||
const previousLineWordPosition = this._getWordAt([this._terminal.cols - 1, coords[1] - 1], false, true, false);
|
||||
if (previousLineWordPosition) {
|
||||
const offset = this._terminal.cols - previousLineWordPosition.start;
|
||||
@@ -829,9 +831,9 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
|
||||
// Recurse downwards if the line is wrapped and the word wraps to the next line
|
||||
if (followWrappedLinesBelow) {
|
||||
if (start + length === this._terminal.cols && bufferLine.get(this._terminal.cols - 1)[CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {
|
||||
if (start + length === this._terminal.cols && bufferLine.getCodePoint(this._terminal.cols - 1) !== 32 /*' '*/) {
|
||||
const nextBufferLine = this._buffer.lines.get(coords[1] + 1);
|
||||
if (nextBufferLine && nextBufferLine.isWrapped && nextBufferLine.get(0)[CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {
|
||||
if (nextBufferLine && nextBufferLine.isWrapped && nextBufferLine.getCodePoint(0) !== 32 /*' '*/) {
|
||||
const nextLineWordPosition = this._getWordAt([0, coords[1] + 1], false, false, true);
|
||||
if (nextLineWordPosition) {
|
||||
length += nextLineWordPosition.length;
|
||||
@@ -894,13 +896,13 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
* word logic.
|
||||
* @param char The character to check.
|
||||
*/
|
||||
private _isCharWordSeparator(charData: CharData): boolean {
|
||||
private _isCharWordSeparator(cell: CellData): boolean {
|
||||
// Zero width characters are never separators as they are always to the
|
||||
// right of wide characters
|
||||
if (charData[CHAR_DATA_WIDTH_INDEX] === 0) {
|
||||
if (cell.getWidth() === 0) {
|
||||
return false;
|
||||
}
|
||||
return WORD_SEPARATORS.indexOf(charData[CHAR_DATA_CHAR_INDEX]) >= 0;
|
||||
return WORD_SEPARATORS.indexOf(cell.getChars()) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user