]> git.proxmox.com Git - mirror_xterm.js.git/blame - src/SelectionModel.ts
Merge pull request #926 from ficristo/search-fix
[mirror_xterm.js.git] / src / SelectionModel.ts
CommitLineData
f7d6ab5f
DI
1/**
2 * @license MIT
3 */
4
5import { ITerminal } from './Interfaces';
6
6075498c
DI
7/**
8 * Represents a selection within the buffer. This model only cares about column
9 * and row coordinates, not wide characters.
10 */
f7d6ab5f
DI
11export class SelectionModel {
12 /**
13 * Whether select all is currently active.
14 */
15 public isSelectAllActive: boolean;
16
17 /**
18 * The [x, y] position the selection starts at.
19 */
20 public selectionStart: [number, number];
21
22 /**
23 * The minimal length of the selection from the start position. When double
24 * clicking on a word, the word will be selected which makes the selection
25 * start at the start of the word and makes this variable the length.
26 */
27 public selectionStartLength: number;
28
29 /**
30 * The [x, y] position the selection ends at.
31 */
32 public selectionEnd: [number, number];
33
34 constructor(
35 private _terminal: ITerminal
36 ) {
a047359f 37 this.clearSelection();
f7d6ab5f
DI
38 }
39
4405f5e1
DI
40 /**
41 * Clears the current selection.
42 */
43 public clearSelection(): void {
44 this.selectionStart = null;
45 this.selectionEnd = null;
46 this.isSelectAllActive = false;
a047359f 47 this.selectionStartLength = 0;
4405f5e1
DI
48 }
49
f7d6ab5f
DI
50 /**
51 * The final selection start, taking into consideration select all.
52 */
53 public get finalSelectionStart(): [number, number] {
54 if (this.isSelectAllActive) {
55 return [0, 0];
56 }
57
a047359f 58 if (!this.selectionEnd || !this.selectionStart) {
f7d6ab5f
DI
59 return this.selectionStart;
60 }
61
4b170ca4 62 return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart;
f7d6ab5f
DI
63 }
64
65 /**
66 * The final selection end, taking into consideration select all, double click
67 * word selection and triple click line selection.
68 */
69 public get finalSelectionEnd(): [number, number] {
2b243182 70 if (this.isSelectAllActive) {
4626e19b 71 return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1];
24bed01f
DI
72 }
73
2b243182
DI
74 if (!this.selectionStart) {
75 return null;
f7d6ab5f
DI
76 }
77
78 // Use the selection start if the end doesn't exist or they're reversed
4b170ca4 79 if (!this.selectionEnd || this.areSelectionValuesReversed()) {
f7d6ab5f
DI
80 return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]];
81 }
82
83 // Ensure the the word/line is selected after a double/triple click
84 if (this.selectionStartLength) {
85 // Select the larger of the two when start and end are on the same line
86 if (this.selectionEnd[1] === this.selectionStart[1]) {
87 return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]];
88 }
89 }
90 return this.selectionEnd;
91 }
92
93 /**
94 * Returns whether the selection start and end are reversed.
95 */
4b170ca4 96 public areSelectionValuesReversed(): boolean {
f7d6ab5f
DI
97 const start = this.selectionStart;
98 const end = this.selectionEnd;
99 return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]);
100 }
101
102 /**
103 * Handle the buffer being trimmed, adjust the selection position.
104 * @param amount The amount the buffer is being trimmed.
105 * @return Whether a refresh is necessary.
106 */
107 public onTrim(amount: number): boolean {
108 // Adjust the selection position based on the trimmed amount.
109 if (this.selectionStart) {
b81c165b 110 this.selectionStart[1] -= amount;
f7d6ab5f
DI
111 }
112 if (this.selectionEnd) {
b81c165b 113 this.selectionEnd[1] -= amount;
f7d6ab5f
DI
114 }
115
116 // The selection has moved off the buffer, clear it.
b81c165b
DI
117 if (this.selectionEnd && this.selectionEnd[1] < 0) {
118 this.clearSelection();
f7d6ab5f
DI
119 return true;
120 }
121
122 // If the selection start is trimmed, ensure the start column is 0.
b81c165b 123 if (this.selectionStart && this.selectionStart[1] < 0) {
f7d6ab5f
DI
124 this.selectionStart[1] = 0;
125 }
126 return false;
127 }
128}