| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- import 'package:async/async.dart';
- import 'package:xterm/terminal/modes.dart';
- import 'package:xterm/terminal/sgr.dart';
- import 'package:xterm/terminal/terminal.dart';
- typedef CsiSequenceHandler = void Function(CSI, Terminal);
- final _csiHandlers = <String, CsiSequenceHandler>{
- 'c': csiSendDeviceAttributesHandler,
- 'd': csiLinePositionAbsolute,
- 'f': csiCursorPositionHandler,
- 'g': csiTabClearHandler,
- 'h': csiModeHandler,
- 'l': csiModeHandler,
- 'm': sgrHandler,
- 'n': csiDeviceStatusReportHandler,
- 'r': csiSetMarginsHandler,
- 't': csiWindowManipulation,
- 'A': csiCursorUpHandler,
- 'B': csiCursorDownHandler,
- 'C': csiCursorForwardHandler,
- 'D': csiCursorBackwardHandler,
- 'E': csiCursorNextLineHandler,
- 'F': csiCursorPrecedingLineHandler,
- 'G': csiCursorHorizontalAbsoluteHandler,
- 'H': csiCursorPositionHandler,
- 'J': csiEraseInDisplayHandler,
- 'K': csiEraseInLineHandler,
- 'L': csiInsertLinesHandler,
- 'M': csiDeleteLinesHandler,
- 'P': csiDeleteHandler,
- 'S': csiScrollUpHandler,
- 'T': csiScrollDownHandler,
- 'X': csiEraseCharactersHandler,
- '@': csiInsertBlankCharactersHandler,
- };
- class CSI {
- CSI({
- this.params,
- this.finalByte,
- this.intermediates,
- });
- final List<String> params;
- final int finalByte;
- final List<int> intermediates;
- @override
- String toString() {
- return params.join(';') + String.fromCharCode(finalByte);
- }
- }
- Future<CSI> _parseCsi(StreamQueue<int> queue) async {
- final paramBuffer = StringBuffer();
- final intermediates = <int>[];
- while (true) {
- final char = await queue.next;
- if (char >= 0x30 && char <= 0x3F) {
- paramBuffer.writeCharCode(char);
- continue;
- }
- if (char > 0 && char <= 0x2F) {
- intermediates.add(char);
- continue;
- }
- const csiMin = 0x40;
- const csiMax = 0x7e;
- if (char >= csiMin && char <= csiMax) {
- final params = paramBuffer.toString().split(';');
- return CSI(
- params: params,
- finalByte: char,
- intermediates: intermediates,
- );
- }
- }
- }
- Future<void> csiHandler(StreamQueue<int> queue, Terminal terminal) async {
- final csi = await _parseCsi(queue);
- terminal.debug.onCsi(csi);
- final handler = _csiHandlers[String.fromCharCode(csi.finalByte)];
- if (handler != null) {
- handler(csi, terminal);
- return;
- }
- terminal.debug.onError('unknown: $csi');
- }
- void csiEraseInDisplayHandler(CSI csi, Terminal terminal) {
- var ps = '0';
- if (csi.params.isNotEmpty) {
- ps = csi.params.first;
- }
- switch (ps) {
- case '':
- case '0':
- terminal.buffer.eraseDisplayFromCursor();
- break;
- case '1':
- terminal.buffer.eraseDisplayToCursor();
- break;
- case '2':
- case '3':
- terminal.buffer.eraseDisplay();
- break;
- default:
- terminal.debug.onError("Unsupported ED: CSI $ps J");
- }
- }
- void csiEraseInLineHandler(CSI csi, Terminal terminal) {
- var ps = '0';
- if (csi.params.isNotEmpty) {
- ps = csi.params.first;
- }
- switch (ps) {
- case '':
- case '0':
- terminal.buffer.eraseLineFromCursor();
- break;
- case '1':
- terminal.buffer.eraseLineToCursor();
- break;
- case '2':
- terminal.buffer.eraseLine();
- break;
- default:
- terminal.debug.onError("Unsupported EL: CSI $ps K");
- }
- }
- void csiCursorPositionHandler(CSI csi, Terminal terminal) {
- var x = 1;
- var y = 1;
- if (csi.params.length == 2) {
- y = int.tryParse(csi.params[0]) ?? x;
- x = int.tryParse(csi.params[1]) ?? y;
- }
- terminal.buffer.setPosition(x - 1, y - 1);
- }
- void csiLinePositionAbsolute(CSI csi, Terminal terminal) {
- var row = 1;
- if (csi.params.isNotEmpty) {
- row = int.tryParse(csi.params.first) ?? row;
- }
- terminal.buffer.setCursorY(row - 1);
- }
- void csiCursorHorizontalAbsoluteHandler(CSI csi, Terminal terminal) {
- var x = 1;
- if (csi.params.isNotEmpty) {
- x = int.tryParse(csi.params.first) ?? x;
- }
- terminal.buffer.setCursorX(x - 1);
- }
- void csiCursorForwardHandler(CSI csi, Terminal terminal) {
- var offset = 1;
- if (csi.params.isNotEmpty) {
- offset = int.tryParse(csi.params.first) ?? offset;
- }
- terminal.buffer.movePosition(offset, 0);
- }
- void csiCursorBackwardHandler(CSI csi, Terminal terminal) {
- var offset = 1;
- if (csi.params.isNotEmpty) {
- offset = int.tryParse(csi.params.first) ?? offset;
- }
- terminal.buffer.movePosition(-offset, 0);
- }
- void csiEraseCharactersHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- terminal.buffer.eraseCharacters(count);
- }
- void csiModeHandler(CSI csi, Terminal terminal) {
- // terminal.ActiveBuffer().ClearSelection()
- return csiSetModes(csi, terminal);
- }
- void csiDeviceStatusReportHandler(CSI csi, Terminal terminal) {
- if (csi.params.isEmpty) return;
- switch (csi.params[0]) {
- case "5":
- terminal.onInput("\x1b[0n");
- break;
- case "6": // report cursor position
- terminal.onInput("\x1b[${terminal.cursorX + 1};${terminal.cursorY + 1}R");
- break;
- default:
- terminal.debug.onError('Unknown Device Status Report identifier: ${csi.params[0]}');
- return;
- }
- }
- void csiSendDeviceAttributesHandler(CSI csi, Terminal terminal) {
- var response = '?1;2';
- if (csi.params.isNotEmpty && csi.params.first.startsWith('>')) {
- response = '>0;0;0';
- }
- terminal.onInput('\x1b[${response}c');
- }
- void csiCursorUpHandler(CSI csi, Terminal terminal) {
- var distance = 1;
- if (csi.params.isNotEmpty) {
- distance = int.tryParse(csi.params.first) ?? distance;
- }
- terminal.buffer.movePosition(0, -distance);
- }
- void csiCursorDownHandler(CSI csi, Terminal terminal) {
- var distance = 1;
- if (csi.params.isNotEmpty) {
- distance = int.tryParse(csi.params.first) ?? distance;
- }
- terminal.buffer.movePosition(0, distance);
- }
- void csiSetMarginsHandler(CSI csi, Terminal terminal) {
- var top = 1;
- var bottom = terminal.viewHeight;
- if (csi.params.length > 2) {
- return;
- }
- if (csi.params.isNotEmpty) {
- top = int.tryParse(csi.params[0]) ?? top;
- if (csi.params.length > 1) {
- bottom = int.tryParse(csi.params[1]) ?? bottom;
- }
- }
- terminal.buffer.setVerticalMargins(top - 1, bottom - 1);
- terminal.buffer.setPosition(0, 0);
- }
- void csiDeleteHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.deleteChars(count);
- }
- void csiTabClearHandler(CSI csi, Terminal terminal) {
- // TODO
- }
- void csiWindowManipulation(CSI csi, Terminal terminal) {
- // not supported
- }
- void csiCursorNextLineHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.moveCursorY(count);
- terminal.buffer.setCursorX(0);
- }
- void csiCursorPrecedingLineHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.moveCursorY(-count);
- terminal.buffer.setCursorX(0);
- }
- void csiInsertLinesHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.insertLines(count);
- }
- void csiDeleteLinesHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.deleteLines(count);
- }
- void csiScrollUpHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.areaScrollUp(count);
- }
- void csiScrollDownHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.areaScrollDown(count);
- }
- void csiInsertBlankCharactersHandler(CSI csi, Terminal terminal) {
- var count = 1;
- if (csi.params.isNotEmpty) {
- count = int.tryParse(csi.params.first) ?? count;
- }
- if (count < 1) {
- count = 1;
- }
- terminal.buffer.insertBlankCharacters(count);
- }
|