|
@@ -3,6 +3,7 @@ import 'dart:math' show max, min;
|
|
|
import 'package:xterm/buffer/buffer_line.dart';
|
|
import 'package:xterm/buffer/buffer_line.dart';
|
|
|
import 'package:xterm/terminal/charset.dart';
|
|
import 'package:xterm/terminal/charset.dart';
|
|
|
import 'package:xterm/terminal/terminal.dart';
|
|
import 'package:xterm/terminal/terminal.dart';
|
|
|
|
|
+import 'package:xterm/utli/circular_list.dart';
|
|
|
import 'package:xterm/utli/scroll_range.dart';
|
|
import 'package:xterm/utli/scroll_range.dart';
|
|
|
import 'package:xterm/utli/unicode_v11.dart';
|
|
import 'package:xterm/utli/unicode_v11.dart';
|
|
|
|
|
|
|
@@ -10,10 +11,12 @@ class Buffer {
|
|
|
Buffer(this.terminal) {
|
|
Buffer(this.terminal) {
|
|
|
resetVerticalMargins();
|
|
resetVerticalMargins();
|
|
|
|
|
|
|
|
- lines = List.generate(
|
|
|
|
|
- terminal.viewHeight,
|
|
|
|
|
- (_) => _newEmptyLine(),
|
|
|
|
|
|
|
+ lines = CircularList(
|
|
|
|
|
+ terminal.maxLines,
|
|
|
);
|
|
);
|
|
|
|
|
+ for (int i = 0; i < terminal.viewHeight; i++) {
|
|
|
|
|
+ lines.push(_newEmptyLine());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
final Terminal terminal;
|
|
final Terminal terminal;
|
|
@@ -21,7 +24,7 @@ class Buffer {
|
|
|
|
|
|
|
|
/// lines of the buffer. the length of [lines] should always be equal or
|
|
/// lines of the buffer. the length of [lines] should always be equal or
|
|
|
/// greater than [Terminal.viewHeight].
|
|
/// greater than [Terminal.viewHeight].
|
|
|
- late final List<BufferLine> lines;
|
|
|
|
|
|
|
+ late final CircularList<BufferLine> lines;
|
|
|
|
|
|
|
|
int? _savedCursorX;
|
|
int? _savedCursorX;
|
|
|
int? _savedCursorY;
|
|
int? _savedCursorY;
|
|
@@ -269,18 +272,12 @@ class Buffer {
|
|
|
// the cursor is not in the scrollable region
|
|
// the cursor is not in the scrollable region
|
|
|
if (_cursorY >= terminal.viewHeight - 1) {
|
|
if (_cursorY >= terminal.viewHeight - 1) {
|
|
|
// we are at the bottom so a new line is created.
|
|
// we are at the bottom so a new line is created.
|
|
|
- lines.add(_newEmptyLine());
|
|
|
|
|
|
|
+ lines.push(_newEmptyLine());
|
|
|
|
|
|
|
|
// keep viewport from moving if user is scrolling.
|
|
// keep viewport from moving if user is scrolling.
|
|
|
if (isUserScrolling) {
|
|
if (isUserScrolling) {
|
|
|
_scrollOffsetFromBottom++;
|
|
_scrollOffsetFromBottom++;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // clean extra lines if needed.
|
|
|
|
|
- final maxLines = terminal.maxLines;
|
|
|
|
|
- if (maxLines != null && lines.length > maxLines) {
|
|
|
|
|
- lines.removeRange(0, lines.length - maxLines);
|
|
|
|
|
- }
|
|
|
|
|
} else {
|
|
} else {
|
|
|
// there're still lines so we simply move cursor down.
|
|
// there're still lines so we simply move cursor down.
|
|
|
moveCursorY(1);
|
|
moveCursorY(1);
|
|
@@ -419,16 +416,14 @@ class Buffer {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- lines.removeRange(0, lines.length - terminal.viewHeight);
|
|
|
|
|
|
|
+ lines.trimStart(lines.length - terminal.viewHeight);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void clear() {
|
|
void clear() {
|
|
|
lines.clear();
|
|
lines.clear();
|
|
|
-
|
|
|
|
|
- lines.addAll(List.generate(
|
|
|
|
|
- terminal.viewHeight,
|
|
|
|
|
- (_) => _newEmptyLine(),
|
|
|
|
|
- ));
|
|
|
|
|
|
|
+ for (int i = 0; i < terminal.viewHeight; i++) {
|
|
|
|
|
+ lines.push(_newEmptyLine());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void insertBlankCharacters(int count) {
|
|
void insertBlankCharacters(int count) {
|
|
@@ -455,19 +450,9 @@ class Buffer {
|
|
|
final index = convertViewLineToRawLine(_cursorX);
|
|
final index = convertViewLineToRawLine(_cursorX);
|
|
|
final newLine = _newEmptyLine();
|
|
final newLine = _newEmptyLine();
|
|
|
lines.insert(index, newLine);
|
|
lines.insert(index, newLine);
|
|
|
-
|
|
|
|
|
- final maxLines = terminal.maxLines;
|
|
|
|
|
- if (maxLines != null && lines.length > maxLines) {
|
|
|
|
|
- lines.removeRange(0, lines.length - maxLines);
|
|
|
|
|
- }
|
|
|
|
|
} else {
|
|
} else {
|
|
|
- final bottom = convertViewLineToRawLine(marginBottom);
|
|
|
|
|
-
|
|
|
|
|
- final movedLines = lines.getRange(_cursorY, bottom - 1);
|
|
|
|
|
- lines.setRange(_cursorY + 1, bottom, movedLines);
|
|
|
|
|
-
|
|
|
|
|
final newLine = _newEmptyLine();
|
|
final newLine = _newEmptyLine();
|
|
|
- lines[_cursorY] = newLine;
|
|
|
|
|
|
|
+ lines.insert(_cursorY, newLine);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -490,21 +475,21 @@ class Buffer {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- lines.removeAt(index);
|
|
|
|
|
|
|
+ lines.remove(index);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void resize(int newWidth, int newHeight) {
|
|
void resize(int newWidth, int newHeight) {
|
|
|
if (newWidth > terminal.viewWidth) {
|
|
if (newWidth > terminal.viewWidth) {
|
|
|
- for (var line in lines) {
|
|
|
|
|
|
|
+ lines.forEach((line) {
|
|
|
line.ensure(newWidth);
|
|
line.ensure(newWidth);
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (newHeight > terminal.viewHeight) {
|
|
if (newHeight > terminal.viewHeight) {
|
|
|
// Grow larger
|
|
// Grow larger
|
|
|
for (var i = 0; i < newHeight - terminal.viewHeight; i++) {
|
|
for (var i = 0; i < newHeight - terminal.viewHeight; i++) {
|
|
|
if (_cursorY < terminal.viewHeight - 1) {
|
|
if (_cursorY < terminal.viewHeight - 1) {
|
|
|
- lines.add(_newEmptyLine());
|
|
|
|
|
|
|
+ lines.push(_newEmptyLine());
|
|
|
} else {
|
|
} else {
|
|
|
_cursorY++;
|
|
_cursorY++;
|
|
|
}
|
|
}
|
|
@@ -513,7 +498,7 @@ class Buffer {
|
|
|
// Shrink smaller
|
|
// Shrink smaller
|
|
|
for (var i = 0; i < terminal.viewHeight - newHeight; i++) {
|
|
for (var i = 0; i < terminal.viewHeight - newHeight; i++) {
|
|
|
if (_cursorY < terminal.viewHeight - 1) {
|
|
if (_cursorY < terminal.viewHeight - 1) {
|
|
|
- lines.removeLast();
|
|
|
|
|
|
|
+ lines.pop();
|
|
|
} else {
|
|
} else {
|
|
|
_cursorY++;
|
|
_cursorY++;
|
|
|
}
|
|
}
|