diff options
author | Toby Vincent <tobyv13@gmail.com> | 2022-03-23 14:04:55 -0500 |
---|---|---|
committer | Toby Vincent <tobyv13@gmail.com> | 2022-03-23 14:15:18 -0500 |
commit | 8e36499326e969c7c34ecc537e589bd5ef5598a0 (patch) | |
tree | 7943cda837324847875d472d2ad68922c5019a50 /node_modules/xterm/src/browser/input | |
parent | 337fa04fe3686e0f0d236eef5df89179ee68f673 (diff) |
chore: removed node_modules from git
Diffstat (limited to 'node_modules/xterm/src/browser/input')
-rw-r--r-- | node_modules/xterm/src/browser/input/CompositionHelper.ts | 237 | ||||
-rw-r--r-- | node_modules/xterm/src/browser/input/Mouse.ts | 58 | ||||
-rw-r--r-- | node_modules/xterm/src/browser/input/MoveToCell.ts | 249 |
3 files changed, 0 insertions, 544 deletions
diff --git a/node_modules/xterm/src/browser/input/CompositionHelper.ts b/node_modules/xterm/src/browser/input/CompositionHelper.ts deleted file mode 100644 index 61051b5..0000000 --- a/node_modules/xterm/src/browser/input/CompositionHelper.ts +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2016 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IRenderService } from 'browser/services/Services'; -import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services'; - -interface IPosition { - start: number; - end: number; -} - -/** - * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend - * events, displaying the in-progress composition to the UI and forwarding the final composition - * to the handler. - */ -export class CompositionHelper { - /** - * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or - * IME. This variable determines whether the compositionText should be displayed on the UI. - */ - private _isComposing: boolean; - public get isComposing(): boolean { return this._isComposing; } - - /** - * The position within the input textarea's value of the current composition. - */ - private _compositionPosition: IPosition; - - /** - * Whether a composition is in the process of being sent, setting this to false will cancel any - * in-progress composition. - */ - private _isSendingComposition: boolean; - - /** - * Data already sent due to keydown event. - */ - private _dataAlreadySent: string; - - constructor( - private readonly _textarea: HTMLTextAreaElement, - private readonly _compositionView: HTMLElement, - @IBufferService private readonly _bufferService: IBufferService, - @IOptionsService private readonly _optionsService: IOptionsService, - @ICoreService private readonly _coreService: ICoreService, - @IRenderService private readonly _renderService: IRenderService - ) { - this._isComposing = false; - this._isSendingComposition = false; - this._compositionPosition = { start: 0, end: 0 }; - this._dataAlreadySent = ''; - } - - /** - * Handles the compositionstart event, activating the composition view. - */ - public compositionstart(): void { - this._isComposing = true; - this._compositionPosition.start = this._textarea.value.length; - this._compositionView.textContent = ''; - this._dataAlreadySent = ''; - this._compositionView.classList.add('active'); - } - - /** - * Handles the compositionupdate event, updating the composition view. - * @param ev The event. - */ - public compositionupdate(ev: Pick<CompositionEvent, 'data'>): void { - this._compositionView.textContent = ev.data; - this.updateCompositionElements(); - setTimeout(() => { - this._compositionPosition.end = this._textarea.value.length; - }, 0); - } - - /** - * Handles the compositionend event, hiding the composition view and sending the composition to - * the handler. - */ - public compositionend(): void { - this._finalizeComposition(true); - } - - /** - * Handles the keydown event, routing any necessary events to the CompositionHelper functions. - * @param ev The keydown event. - * @return Whether the Terminal should continue processing the keydown event. - */ - public keydown(ev: KeyboardEvent): boolean { - if (this._isComposing || this._isSendingComposition) { - if (ev.keyCode === 229) { - // Continue composing if the keyCode is the "composition character" - return false; - } - if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { - // Continue composing if the keyCode is a modifier key - return false; - } - // Finish composition immediately. This is mainly here for the case where enter is - // pressed and the handler needs to be triggered before the command is executed. - this._finalizeComposition(false); - } - - if (ev.keyCode === 229) { - // If the "composition character" is used but gets to this point it means a non-composition - // character (eg. numbers and punctuation) was pressed when the IME was active. - this._handleAnyTextareaChanges(); - return false; - } - - return true; - } - - /** - * Finalizes the composition, resuming regular input actions. This is called when a composition - * is ending. - * @param waitForPropagation Whether to wait for events to propagate before sending - * the input. This should be false if a non-composition keystroke is entered before the - * compositionend event is triggered, such as enter, so that the composition is sent before - * the command is executed. - */ - private _finalizeComposition(waitForPropagation: boolean): void { - this._compositionView.classList.remove('active'); - this._isComposing = false; - - if (!waitForPropagation) { - // Cancel any delayed composition send requests and send the input immediately. - this._isSendingComposition = false; - const input = this._textarea.value.substring(this._compositionPosition.start, this._compositionPosition.end); - this._coreService.triggerDataEvent(input, true); - } else { - // Make a deep copy of the composition position here as a new compositionstart event may - // fire before the setTimeout executes. - const currentCompositionPosition = { - start: this._compositionPosition.start, - end: this._compositionPosition.end - }; - - // Since composition* events happen before the changes take place in the textarea on most - // browsers, use a setTimeout with 0ms time to allow the native compositionend event to - // complete. This ensures the correct character is retrieved. - // This solution was used because: - // - The compositionend event's data property is unreliable, at least on Chromium - // - The last compositionupdate event's data property does not always accurately describe - // the character, a counter example being Korean where an ending consonsant can move to - // the following character if the following input is a vowel. - this._isSendingComposition = true; - setTimeout(() => { - // Ensure that the input has not already been sent - if (this._isSendingComposition) { - this._isSendingComposition = false; - let input; - // Add length of data already sent due to keydown event, - // otherwise input characters can be duplicated. (Issue #3191) - currentCompositionPosition.start += this._dataAlreadySent.length; - if (this._isComposing) { - // Use the end position to get the string if a new composition has started. - input = this._textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end); - } else { - // Don't use the end position here in order to pick up any characters after the - // composition has finished, for example when typing a non-composition character - // (eg. 2) after a composition character. - input = this._textarea.value.substring(currentCompositionPosition.start); - } - if (input.length > 0) { - this._coreService.triggerDataEvent(input, true); - } - } - }, 0); - } - } - - /** - * Apply any changes made to the textarea after the current event chain is allowed to complete. - * This should be called when not currently composing but a keydown event with the "composition - * character" (229) is triggered, in order to allow non-composition text to be entered when an - * IME is active. - */ - private _handleAnyTextareaChanges(): void { - const oldValue = this._textarea.value; - setTimeout(() => { - // Ignore if a composition has started since the timeout - if (!this._isComposing) { - const newValue = this._textarea.value; - const diff = newValue.replace(oldValue, ''); - if (diff.length > 0) { - this._dataAlreadySent = diff; - this._coreService.triggerDataEvent(diff, true); - } - } - }, 0); - } - - /** - * Positions the composition view on top of the cursor and the textarea just below it (so the - * IME helper dialog is positioned correctly). - * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is - * necessary as the IME events across browsers are not consistently triggered. - */ - public updateCompositionElements(dontRecurse?: boolean): void { - if (!this._isComposing) { - return; - } - - if (this._bufferService.buffer.isCursorInViewport) { - const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1); - - const cellHeight = this._renderService.dimensions.actualCellHeight; - const cursorTop = this._bufferService.buffer.y * this._renderService.dimensions.actualCellHeight; - const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; - - this._compositionView.style.left = cursorLeft + 'px'; - this._compositionView.style.top = cursorTop + 'px'; - this._compositionView.style.height = cellHeight + 'px'; - this._compositionView.style.lineHeight = cellHeight + 'px'; - this._compositionView.style.fontFamily = this._optionsService.rawOptions.fontFamily; - this._compositionView.style.fontSize = this._optionsService.rawOptions.fontSize + '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 = cursorLeft + 'px'; - this._textarea.style.top = cursorTop + 'px'; - // Ensure the text area is at least 1x1, otherwise certain IMEs may break - this._textarea.style.width = Math.max(compositionViewBounds.width, 1) + 'px'; - this._textarea.style.height = Math.max(compositionViewBounds.height, 1) + 'px'; - this._textarea.style.lineHeight = compositionViewBounds.height + 'px'; - } - - if (!dontRecurse) { - setTimeout(() => this.updateCompositionElements(true), 0); - } - } -} diff --git a/node_modules/xterm/src/browser/input/Mouse.ts b/node_modules/xterm/src/browser/input/Mouse.ts deleted file mode 100644 index 2986fb3..0000000 --- a/node_modules/xterm/src/browser/input/Mouse.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -export function getCoordsRelativeToElement(event: {clientX: number, clientY: number}, element: HTMLElement): [number, number] { - const rect = element.getBoundingClientRect(); - return [event.clientX - rect.left, event.clientY - rect.top]; -} - -/** - * Gets coordinates within the terminal for a particular mouse event. The result - * is returned as an array in the form [x, y] instead of an object as it's a - * little faster and this function is used in some low level code. - * @param event The mouse event. - * @param element The terminal's container element. - * @param colCount The number of columns in the terminal. - * @param rowCount The number of rows n the terminal. - * @param isSelection Whether the request is for the selection or not. This will - * apply an offset to the x value such that the left half of the cell will - * select that cell and the right half will select the next cell. - */ -export function getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, hasValidCharSize: boolean, actualCellWidth: number, actualCellHeight: number, isSelection?: boolean): [number, number] | undefined { - // Coordinates cannot be measured if there are no valid - if (!hasValidCharSize) { - return undefined; - } - - const coords = getCoordsRelativeToElement(event, element); - if (!coords) { - return undefined; - } - - coords[0] = Math.ceil((coords[0] + (isSelection ? actualCellWidth / 2 : 0)) / actualCellWidth); - coords[1] = Math.ceil(coords[1] / actualCellHeight); - - // Ensure coordinates are within the terminal viewport. Note that selections - // need an addition point of precision to cover the end point (as characters - // cover half of one char and half of the next). - coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0)); - coords[1] = Math.min(Math.max(coords[1], 1), rowCount); - - return coords; -} - -/** - * Gets coordinates within the terminal for a particular mouse event, wrapping - * them to the bounds of the terminal and adding 32 to both the x and y values - * as expected by xterm. - */ -export function getRawByteCoords(coords: [number, number] | undefined): { x: number, y: number } | undefined { - if (!coords) { - return undefined; - } - - // xterm sends raw bytes and starts at 32 (SP) for each. - return { x: coords[0] + 32, y: coords[1] + 32 }; -} diff --git a/node_modules/xterm/src/browser/input/MoveToCell.ts b/node_modules/xterm/src/browser/input/MoveToCell.ts deleted file mode 100644 index 82e767c..0000000 --- a/node_modules/xterm/src/browser/input/MoveToCell.ts +++ /dev/null @@ -1,249 +0,0 @@ -/** - * Copyright (c) 2018 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { C0 } from 'common/data/EscapeSequences'; -import { IBufferService } from 'common/services/Services'; - -const enum Direction { - UP = 'A', - DOWN = 'B', - RIGHT = 'C', - LEFT = 'D' -} - -/** - * Concatenates all the arrow sequences together. - * Resets the starting row to an unwrapped row, moves to the requested row, - * then moves to requested col. - */ -export function moveToCellSequence(targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - const startX = bufferService.buffer.x; - const startY = bufferService.buffer.y; - - // The alt buffer should try to navigate between rows - if (!bufferService.buffer.hasScrollback) { - return resetStartingRow(startX, startY, targetX, targetY, bufferService, applicationCursor) + - moveToRequestedRow(startY, targetY, bufferService, applicationCursor) + - moveToRequestedCol(startX, startY, targetX, targetY, bufferService, applicationCursor); - } - - // Only move horizontally for the normal buffer - let direction; - if (startY === targetY) { - direction = startX > targetX ? Direction.LEFT : Direction.RIGHT; - return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor)); - } - direction = startY > targetY ? Direction.LEFT : Direction.RIGHT; - const rowDifference = Math.abs(startY - targetY); - const cellsToMove = colsFromRowEnd(startY > targetY ? targetX : startX, bufferService) + - (rowDifference - 1) * bufferService.cols + 1 /* wrap around 1 row */ + - colsFromRowBeginning(startY > targetY ? startX : targetX, bufferService); - return repeat(cellsToMove, sequence(direction, applicationCursor)); -} - -/** - * Find the number of cols from a row beginning to a col. - */ -function colsFromRowBeginning(currX: number, bufferService: IBufferService): number { - return currX - 1; -} - -/** - * Find the number of cols from a col to row end. - */ -function colsFromRowEnd(currX: number, bufferService: IBufferService): number { - return bufferService.cols - currX; -} - -/** - * If the initial position of the cursor is on a row that is wrapped, move the - * cursor up to the first row that is not wrapped to have accurate vertical - * positioning. - */ -function resetStartingRow(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length === 0) { - return ''; - } - return repeat(bufferLine( - startX, startY, startX, - startY - wrappedRowsForRow(bufferService, startY), false, bufferService - ).length, sequence(Direction.LEFT, applicationCursor)); -} - -/** - * Using the reset starting and ending row, move to the requested row, - * ignoring wrapped rows - */ -function moveToRequestedRow(startY: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - const startRow = startY - wrappedRowsForRow(bufferService, startY); - const endRow = targetY - wrappedRowsForRow(bufferService, targetY); - - const rowsToMove = Math.abs(startRow - endRow) - wrappedRowsCount(startY, targetY, bufferService); - - return repeat(rowsToMove, sequence(verticalDirection(startY, targetY), applicationCursor)); -} - -/** - * Move to the requested col on the ending row - */ -function moveToRequestedCol(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - let startRow; - if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length > 0) { - startRow = targetY - wrappedRowsForRow(bufferService, targetY); - } else { - startRow = startY; - } - - const endRow = targetY; - const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor); - - return repeat(bufferLine( - startX, startRow, targetX, endRow, - direction === Direction.RIGHT, bufferService - ).length, sequence(direction, applicationCursor)); -} - -/** - * Utility functions - */ - -/** - * Calculates the number of wrapped rows between the unwrapped starting and - * ending rows. These rows need to ignored since the cursor skips over them. - */ -function wrappedRowsCount(startY: number, targetY: number, bufferService: IBufferService): number { - let wrappedRows = 0; - const startRow = startY - wrappedRowsForRow(bufferService, startY); - const endRow = targetY - wrappedRowsForRow(bufferService, targetY); - - for (let i = 0; i < Math.abs(startRow - endRow); i++) { - const direction = verticalDirection(startY, targetY) === Direction.UP ? -1 : 1; - const line = bufferService.buffer.lines.get(startRow + (direction * i)); - if (line?.isWrapped) { - wrappedRows++; - } - } - - return wrappedRows; -} - -/** - * Calculates the number of wrapped rows that make up a given row. - * @param currentRow The row to determine how many wrapped rows make it up - */ -function wrappedRowsForRow(bufferService: IBufferService, currentRow: number): number { - let rowCount = 0; - let line = bufferService.buffer.lines.get(currentRow); - let lineWraps = line?.isWrapped; - - while (lineWraps && currentRow >= 0 && currentRow < bufferService.rows) { - rowCount++; - line = bufferService.buffer.lines.get(--currentRow); - lineWraps = line?.isWrapped; - } - - return rowCount; -} - -/** - * Direction determiners - */ - -/** - * Determines if the right or left arrow is needed - */ -function horizontalDirection(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): Direction { - let startRow; - if (moveToRequestedRow(targetX, targetY, bufferService, applicationCursor).length > 0) { - startRow = targetY - wrappedRowsForRow(bufferService, targetY); - } else { - startRow = startY; - } - - if ((startX < targetX && - startRow <= targetY) || // down/right or same y/right - (startX >= targetX && - startRow < targetY)) { // down/left or same y/left - return Direction.RIGHT; - } - return Direction.LEFT; -} - -/** - * Determines if the up or down arrow is needed - */ -function verticalDirection(startY: number, targetY: number): Direction { - return startY > targetY ? Direction.UP : Direction.DOWN; -} - -/** - * Constructs the string of chars in the buffer from a starting row and col - * to an ending row and col - * @param startCol The starting column position - * @param startRow The starting row position - * @param endCol The ending column position - * @param endRow The ending row position - * @param forward Direction to move - */ -function bufferLine( - startCol: number, - startRow: number, - endCol: number, - endRow: number, - forward: boolean, - bufferService: IBufferService -): string { - let currentCol = startCol; - let currentRow = startRow; - let bufferStr = ''; - - while (currentCol !== endCol || currentRow !== endRow) { - currentCol += forward ? 1 : -1; - - if (forward && currentCol > bufferService.cols - 1) { - bufferStr += bufferService.buffer.translateBufferLineToString( - currentRow, false, startCol, currentCol - ); - currentCol = 0; - startCol = 0; - currentRow++; - } else if (!forward && currentCol < 0) { - bufferStr += bufferService.buffer.translateBufferLineToString( - currentRow, false, 0, startCol + 1 - ); - currentCol = bufferService.cols - 1; - startCol = currentCol; - currentRow--; - } - } - - return bufferStr + bufferService.buffer.translateBufferLineToString( - currentRow, false, startCol, currentCol - ); -} - -/** - * Constructs the escape sequence for clicking an arrow - * @param direction The direction to move - */ -function sequence(direction: Direction, applicationCursor: boolean): string { - const mod = applicationCursor ? 'O' : '['; - return C0.ESC + mod + direction; -} - -/** - * Returns a string repeated a given number of times - * Polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat - * @param count The number of times to repeat the string - * @param string The string that is to be repeated - */ -function repeat(count: number, str: string): string { - count = Math.floor(count); - let rpt = ''; - for (let i = 0; i < count; i++) { - rpt += str; - } - return rpt; -} |