terminal.dart 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. import 'dart:math' show max;
  2. import 'package:xterm/src/base/observable.dart';
  3. import 'package:xterm/src/core/buffer/buffer.dart';
  4. import 'package:xterm/src/core/buffer/cell_offset.dart';
  5. import 'package:xterm/src/core/buffer/line.dart';
  6. import 'package:xterm/src/core/cursor.dart';
  7. import 'package:xterm/src/core/escape/emitter.dart';
  8. import 'package:xterm/src/core/escape/handler.dart';
  9. import 'package:xterm/src/core/escape/parser.dart';
  10. import 'package:xterm/src/core/input/handler.dart';
  11. import 'package:xterm/src/core/input/keys.dart';
  12. import 'package:xterm/src/core/mouse/button.dart';
  13. import 'package:xterm/src/core/mouse/button_state.dart';
  14. import 'package:xterm/src/core/mouse/handler.dart';
  15. import 'package:xterm/src/core/mouse/mode.dart';
  16. import 'package:xterm/src/core/platform.dart';
  17. import 'package:xterm/src/core/state.dart';
  18. import 'package:xterm/src/core/tabs.dart';
  19. import 'package:xterm/src/utils/ascii.dart';
  20. import 'package:xterm/src/utils/circular_buffer.dart';
  21. /// [Terminal] is an interface to interact with command line applications. It
  22. /// translates escape sequences from the application into updates to the
  23. /// [buffer] and events such as [onTitleChange] or [onBell], as well as
  24. /// translating user input into escape sequences that the application can
  25. /// understand.
  26. class Terminal with Observable implements TerminalState, EscapeHandler {
  27. /// The number of lines that the scrollback buffer can hold. If the buffer
  28. /// exceeds this size, the lines at the top of the buffer will be removed.
  29. final int maxLines;
  30. /// Function that is called when the program requests the terminal to ring
  31. /// the bell. If not set, the terminal will do nothing.
  32. void Function()? onBell;
  33. /// Function that is called when the program requests the terminal to change
  34. /// the title of the window to [title].
  35. void Function(String title)? onTitleChange;
  36. /// Function that is called when the program requests the terminal to change
  37. /// the icon of the window. [icon] is the name of the icon.
  38. void Function(String icon)? onIconChange;
  39. /// Function that is called when the terminal emits data to the underlying
  40. /// program. This is typically caused by user inputs from [textInput],
  41. /// [keyInput], [mouseInput], or [paste].
  42. void Function(String data)? onOutput;
  43. /// Function that is called when the dimensions of the terminal change.
  44. void Function(int width, int height, int pixelWidth, int pixelHeight)?
  45. onResize;
  46. /// The [TerminalInputHandler] used by this terminal. [defaultInputHandler] is
  47. /// used when not specified. User of this class can provide their own
  48. /// implementation of [TerminalInputHandler] or extend [defaultInputHandler]
  49. /// with [CascadeInputHandler].
  50. TerminalInputHandler? inputHandler;
  51. TerminalMouseHandler? mouseHandler;
  52. /// The callback that is called when the terminal receives a unrecognized
  53. /// escape sequence.
  54. void Function(String code, List<String> args)? onPrivateOSC;
  55. /// Flag to toggle os specific behaviors.
  56. final TerminalTargetPlatform platform;
  57. /// Characters that break selection when double clicking. If not set, the
  58. /// [Buffer.defaultWordSeparators] will be used.
  59. final Set<int>? wordSeparators;
  60. Terminal({
  61. this.maxLines = 1000,
  62. this.onBell,
  63. this.onTitleChange,
  64. this.onIconChange,
  65. this.onOutput,
  66. this.onResize,
  67. this.platform = TerminalTargetPlatform.unknown,
  68. this.inputHandler = defaultInputHandler,
  69. this.mouseHandler = defaultMouseHandler,
  70. this.onPrivateOSC,
  71. this.reflowEnabled = true,
  72. this.wordSeparators,
  73. });
  74. late final _parser = EscapeParser(this);
  75. final _emitter = const EscapeEmitter();
  76. late var _buffer = _mainBuffer;
  77. late final _mainBuffer = Buffer(
  78. this,
  79. maxLines: maxLines,
  80. isAltBuffer: false,
  81. wordSeparators: wordSeparators,
  82. );
  83. late final _altBuffer = Buffer(
  84. this,
  85. maxLines: maxLines,
  86. isAltBuffer: true,
  87. wordSeparators: wordSeparators,
  88. );
  89. final _tabStops = TabStops();
  90. /// The last character written to the buffer. Used to implement some escape
  91. /// sequences that repeat the last character.
  92. var _precedingCodepoint = 0;
  93. /* TerminalState */
  94. int _viewWidth = 80;
  95. int _viewHeight = 24;
  96. final _cursorStyle = CursorStyle();
  97. bool _insertMode = false;
  98. bool _lineFeedMode = false;
  99. bool _cursorKeysMode = false;
  100. bool _reverseDisplayMode = false;
  101. bool _originMode = false;
  102. bool _autoWrapMode = true;
  103. MouseMode _mouseMode = MouseMode.none;
  104. MouseReportMode _mouseReportMode = MouseReportMode.normal;
  105. bool _cursorBlinkMode = false;
  106. bool _cursorVisibleMode = true;
  107. bool _appKeypadMode = false;
  108. bool _reportFocusMode = false;
  109. bool _altBufferMouseScrollMode = false;
  110. bool _bracketedPasteMode = false;
  111. /* State getters */
  112. /// Number of cells in a terminal row.
  113. @override
  114. int get viewWidth => _viewWidth;
  115. /// Number of rows in this terminal.
  116. @override
  117. int get viewHeight => _viewHeight;
  118. @override
  119. CursorStyle get cursor => _cursorStyle;
  120. @override
  121. bool get insertMode => _insertMode;
  122. @override
  123. bool get lineFeedMode => _lineFeedMode;
  124. @override
  125. bool get cursorKeysMode => _cursorKeysMode;
  126. @override
  127. bool get reverseDisplayMode => _reverseDisplayMode;
  128. @override
  129. bool get originMode => _originMode;
  130. @override
  131. bool get autoWrapMode => _autoWrapMode;
  132. @override
  133. MouseMode get mouseMode => _mouseMode;
  134. @override
  135. MouseReportMode get mouseReportMode => _mouseReportMode;
  136. @override
  137. bool get cursorBlinkMode => _cursorBlinkMode;
  138. @override
  139. bool get cursorVisibleMode => _cursorVisibleMode;
  140. @override
  141. bool get appKeypadMode => _appKeypadMode;
  142. @override
  143. bool get reportFocusMode => _reportFocusMode;
  144. @override
  145. bool get altBufferMouseScrollMode => _altBufferMouseScrollMode;
  146. @override
  147. bool get bracketedPasteMode => _bracketedPasteMode;
  148. /// Current active buffer of the terminal. This is initially [mainBuffer] and
  149. /// can be switched back and forth from [altBuffer] to [mainBuffer] when
  150. /// the underlying program requests it.
  151. Buffer get buffer => _buffer;
  152. Buffer get mainBuffer => _mainBuffer;
  153. Buffer get altBuffer => _altBuffer;
  154. bool get isUsingAltBuffer => _buffer == _altBuffer;
  155. /// Lines of the active buffer.
  156. IndexAwareCircularBuffer<BufferLine> get lines => _buffer.lines;
  157. /// Whether the terminal performs reflow when the viewport size changes or
  158. /// simply truncates lines. true by default.
  159. @override
  160. bool reflowEnabled;
  161. /// Writes the data from the underlying program to the terminal. Calling this
  162. /// updates the states of the terminal and emits events such as [onBell] or
  163. /// [onTitleChange] when the escape sequences in [data] request it.
  164. void write(String data) {
  165. _parser.write(data);
  166. notifyListeners();
  167. }
  168. /// Sends a key event to the underlying program.
  169. ///
  170. /// See also:
  171. /// - [charInput]
  172. /// - [textInput]
  173. /// - [paste]
  174. bool keyInput(
  175. TerminalKey key, {
  176. bool shift = false,
  177. bool alt = false,
  178. bool ctrl = false,
  179. }) {
  180. final output = inputHandler?.call(
  181. TerminalKeyboardEvent(
  182. key: key,
  183. shift: shift,
  184. alt: alt,
  185. ctrl: ctrl,
  186. state: this,
  187. altBuffer: isUsingAltBuffer,
  188. platform: platform,
  189. ),
  190. );
  191. if (output != null) {
  192. onOutput?.call(output);
  193. return true;
  194. }
  195. return false;
  196. }
  197. /// Similary to [keyInput], but takes a character as input instead of a
  198. /// [TerminalKey].
  199. ///
  200. /// See also:
  201. /// - [keyInput]
  202. /// - [textInput]
  203. /// - [paste]
  204. bool charInput(
  205. int charCode, {
  206. bool alt = false,
  207. bool ctrl = false,
  208. }) {
  209. if (ctrl) {
  210. // a(97) ~ z(122)
  211. if (charCode >= Ascii.a && charCode <= Ascii.z) {
  212. final output = charCode - Ascii.a + 1;
  213. onOutput?.call(String.fromCharCode(output));
  214. return true;
  215. }
  216. // [(91) ~ _(95)
  217. if (charCode >= Ascii.openBracket && charCode <= Ascii.underscore) {
  218. final output = charCode - Ascii.openBracket + 27;
  219. onOutput?.call(String.fromCharCode(output));
  220. return true;
  221. }
  222. }
  223. if (alt && platform != TerminalTargetPlatform.macos) {
  224. if (charCode >= Ascii.a && charCode <= Ascii.z) {
  225. final code = charCode - Ascii.a + 65;
  226. final input = [0x1b, code];
  227. onOutput?.call(String.fromCharCodes(input));
  228. return true;
  229. }
  230. }
  231. return false;
  232. }
  233. /// Sends regular text input to the underlying program.
  234. ///
  235. /// See also:
  236. /// - [keyInput]
  237. /// - [charInput]
  238. /// - [paste]
  239. void textInput(String text) {
  240. onOutput?.call(text);
  241. }
  242. /// Similar to [textInput], except that when the program tells the terminal
  243. /// that it supports [bracketedPasteMode], the text is wrapped in escape
  244. /// sequences to indicate that it is a paste operation. Prefer this method
  245. /// over [textInput] when pasting text.
  246. ///
  247. /// See also:
  248. /// - [textInput]
  249. void paste(String text) {
  250. if (_bracketedPasteMode) {
  251. onOutput?.call(_emitter.bracketedPaste(text));
  252. } else {
  253. textInput(text);
  254. }
  255. }
  256. // Handle a mouse event and return true if it was handled.
  257. bool mouseInput(
  258. TerminalMouseButton button,
  259. TerminalMouseButtonState buttonState,
  260. CellOffset position,
  261. ) {
  262. final output = mouseHandler?.call(TerminalMouseEvent(
  263. button: button,
  264. buttonState: buttonState,
  265. position: position,
  266. state: this,
  267. platform: platform,
  268. ));
  269. if (output != null) {
  270. onOutput?.call(output);
  271. return true;
  272. }
  273. return false;
  274. }
  275. /// Resize the terminal screen. [newWidth] and [newHeight] should be greater
  276. /// than 0. Text reflow is currently not implemented and will be avaliable in
  277. /// the future.
  278. @override
  279. void resize(
  280. int newWidth,
  281. int newHeight, [
  282. int? pixelWidth,
  283. int? pixelHeight,
  284. ]) {
  285. newWidth = max(newWidth, 1);
  286. newHeight = max(newHeight, 1);
  287. onResize?.call(newWidth, newHeight, pixelWidth ?? 0, pixelHeight ?? 0);
  288. //we need to resize both buffers so that they are ready when we switch between them
  289. _altBuffer.resize(_viewWidth, _viewHeight, newWidth, newHeight);
  290. _mainBuffer.resize(_viewWidth, _viewHeight, newWidth, newHeight);
  291. _viewWidth = newWidth;
  292. _viewHeight = newHeight;
  293. if (buffer == _altBuffer) {
  294. buffer.clearScrollback();
  295. }
  296. _altBuffer.resetVerticalMargins();
  297. _mainBuffer.resetVerticalMargins();
  298. }
  299. @override
  300. String toString() {
  301. return 'Terminal(#$hashCode, $_viewWidth x $_viewHeight, ${_buffer.height} lines)';
  302. }
  303. /* Handlers */
  304. @override
  305. void writeChar(int char) {
  306. _precedingCodepoint = char;
  307. _buffer.writeChar(char);
  308. }
  309. /* SBC */
  310. @override
  311. void bell() {
  312. onBell?.call();
  313. }
  314. @override
  315. void backspaceReturn() {
  316. _buffer.moveCursorX(-1);
  317. }
  318. @override
  319. void tab() {
  320. final nextStop = _tabStops.find(_buffer.cursorX + 1, _viewWidth);
  321. if (nextStop != null) {
  322. _buffer.setCursorX(nextStop);
  323. } else {
  324. _buffer.setCursorX(_viewWidth);
  325. _buffer.cursorGoForward(); // Enter pending-wrap state
  326. }
  327. }
  328. @override
  329. void lineFeed() {
  330. _buffer.lineFeed();
  331. }
  332. @override
  333. void carriageReturn() {
  334. _buffer.setCursorX(0);
  335. }
  336. @override
  337. void shiftOut() {
  338. _buffer.charset.use(1);
  339. }
  340. @override
  341. void shiftIn() {
  342. _buffer.charset.use(0);
  343. }
  344. @override
  345. void unknownSBC(int char) {
  346. // no-op
  347. }
  348. /* ANSI sequence */
  349. @override
  350. void saveCursor() {
  351. _buffer.saveCursor();
  352. }
  353. @override
  354. void restoreCursor() {
  355. _buffer.restoreCursor();
  356. }
  357. @override
  358. void index() {
  359. _buffer.index();
  360. }
  361. @override
  362. void nextLine() {
  363. _buffer.index();
  364. _buffer.setCursorX(0);
  365. }
  366. @override
  367. void setTapStop() {
  368. _tabStops.isSetAt(_buffer.cursorX);
  369. }
  370. @override
  371. void reverseIndex() {
  372. _buffer.reverseIndex();
  373. }
  374. @override
  375. void designateCharset(int charset, int name) {
  376. _buffer.charset.designate(charset, name);
  377. }
  378. @override
  379. void unkownEscape(int char) {
  380. // no-op
  381. }
  382. /* CSI */
  383. @override
  384. void repeatPreviousCharacter(int count) {
  385. if (_precedingCodepoint == 0) {
  386. return;
  387. }
  388. for (var i = 0; i < count; i++) {
  389. _buffer.writeChar(_precedingCodepoint);
  390. }
  391. }
  392. @override
  393. void setCursor(int x, int y) {
  394. _buffer.setCursor(x, y);
  395. }
  396. @override
  397. void setCursorX(int x) {
  398. _buffer.setCursorX(x);
  399. }
  400. @override
  401. void setCursorY(int y) {
  402. _buffer.setCursorY(y);
  403. }
  404. @override
  405. void moveCursorX(int offset) {
  406. _buffer.moveCursorX(offset);
  407. }
  408. @override
  409. void moveCursorY(int n) {
  410. _buffer.moveCursorY(n);
  411. }
  412. @override
  413. void clearTabStopUnderCursor() {
  414. _tabStops.clearAt(_buffer.cursorX);
  415. }
  416. @override
  417. void clearAllTabStops() {
  418. _tabStops.clearAll();
  419. }
  420. @override
  421. void sendPrimaryDeviceAttributes() {
  422. onOutput?.call(_emitter.primaryDeviceAttributes());
  423. }
  424. @override
  425. void sendSecondaryDeviceAttributes() {
  426. onOutput?.call(_emitter.secondaryDeviceAttributes());
  427. }
  428. @override
  429. void sendTertiaryDeviceAttributes() {
  430. onOutput?.call(_emitter.tertiaryDeviceAttributes());
  431. }
  432. @override
  433. void sendOperatingStatus() {
  434. onOutput?.call(_emitter.operatingStatus());
  435. }
  436. @override
  437. void sendCursorPosition() {
  438. onOutput?.call(_emitter.cursorPosition(_buffer.cursorX, _buffer.cursorY));
  439. }
  440. @override
  441. void setMargins(int top, [int? bottom]) {
  442. _buffer.setVerticalMargins(top, bottom ?? viewHeight - 1);
  443. }
  444. @override
  445. void cursorNextLine(int amount) {
  446. _buffer.moveCursorY(amount);
  447. _buffer.setCursorX(0);
  448. }
  449. @override
  450. void cursorPrecedingLine(int amount) {
  451. _buffer.moveCursorY(-amount);
  452. _buffer.setCursorX(0);
  453. }
  454. @override
  455. void eraseDisplayBelow() {
  456. _buffer.eraseDisplayFromCursor();
  457. }
  458. @override
  459. void eraseDisplayAbove() {
  460. _buffer.eraseDisplayToCursor();
  461. }
  462. @override
  463. void eraseDisplay() {
  464. _buffer.eraseDisplay();
  465. }
  466. @override
  467. void eraseScrollbackOnly() {
  468. _buffer.clearScrollback();
  469. }
  470. @override
  471. void eraseLineRight() {
  472. _buffer.eraseLineFromCursor();
  473. }
  474. @override
  475. void eraseLineLeft() {
  476. _buffer.eraseLineToCursor();
  477. }
  478. @override
  479. void eraseLine() {
  480. _buffer.eraseLine();
  481. }
  482. @override
  483. void insertLines(int amount) {
  484. _buffer.insertLines(amount);
  485. }
  486. @override
  487. void deleteLines(int amount) {
  488. _buffer.deleteLines(amount);
  489. }
  490. @override
  491. void deleteChars(int amount) {
  492. _buffer.deleteChars(amount);
  493. }
  494. @override
  495. void scrollUp(int amount) {
  496. _buffer.scrollUp(amount);
  497. }
  498. @override
  499. void scrollDown(int amount) {
  500. _buffer.scrollDown(amount);
  501. }
  502. @override
  503. void eraseChars(int amount) {
  504. _buffer.eraseChars(amount);
  505. }
  506. @override
  507. void insertBlankChars(int amount) {
  508. _buffer.insertBlankChars(amount);
  509. }
  510. @override
  511. void sendSize() {
  512. onOutput?.call(_emitter.size(viewHeight, viewWidth));
  513. }
  514. @override
  515. void unknownCSI(int finalByte) {
  516. // no-op
  517. }
  518. /* Modes */
  519. @override
  520. void setInsertMode(bool enabled) {
  521. _insertMode = enabled;
  522. }
  523. @override
  524. void setLineFeedMode(bool enabled) {
  525. _lineFeedMode = enabled;
  526. }
  527. @override
  528. void setUnknownMode(int mode, bool enabled) {
  529. // no-op
  530. }
  531. /* DEC Private modes */
  532. @override
  533. void setCursorKeysMode(bool enabled) {
  534. _cursorKeysMode = enabled;
  535. }
  536. @override
  537. void setReverseDisplayMode(bool enabled) {
  538. _reverseDisplayMode = enabled;
  539. }
  540. @override
  541. void setOriginMode(bool enabled) {
  542. _originMode = enabled;
  543. }
  544. @override
  545. void setColumnMode(bool enabled) {
  546. // no-op
  547. }
  548. @override
  549. void setAutoWrapMode(bool enabled) {
  550. _autoWrapMode = enabled;
  551. }
  552. @override
  553. void setMouseMode(MouseMode mode) {
  554. _mouseMode = mode;
  555. }
  556. @override
  557. void setCursorBlinkMode(bool enabled) {
  558. _cursorBlinkMode = enabled;
  559. }
  560. @override
  561. void setCursorVisibleMode(bool enabled) {
  562. _cursorVisibleMode = enabled;
  563. }
  564. @override
  565. void useAltBuffer() {
  566. _buffer = _altBuffer;
  567. }
  568. @override
  569. void useMainBuffer() {
  570. _buffer = _mainBuffer;
  571. }
  572. @override
  573. void clearAltBuffer() {
  574. _altBuffer.clear();
  575. }
  576. @override
  577. void setAppKeypadMode(bool enabled) {
  578. _appKeypadMode = enabled;
  579. }
  580. @override
  581. void setReportFocusMode(bool enabled) {
  582. _reportFocusMode = enabled;
  583. }
  584. @override
  585. void setMouseReportMode(MouseReportMode mode) {
  586. _mouseReportMode = mode;
  587. }
  588. @override
  589. void setAltBufferMouseScrollMode(bool enabled) {
  590. _altBufferMouseScrollMode = enabled;
  591. }
  592. @override
  593. void setBracketedPasteMode(bool enabled) {
  594. _bracketedPasteMode = enabled;
  595. }
  596. @override
  597. void setUnknownDecMode(int mode, bool enabled) {
  598. // no-op
  599. }
  600. /* Select Graphic Rendition (SGR) */
  601. @override
  602. void resetCursorStyle() {
  603. _cursorStyle.reset();
  604. }
  605. @override
  606. void setCursorBold() {
  607. _cursorStyle.setBold();
  608. }
  609. @override
  610. void setCursorFaint() {
  611. _cursorStyle.setFaint();
  612. }
  613. @override
  614. void setCursorItalic() {
  615. _cursorStyle.setItalic();
  616. }
  617. @override
  618. void setCursorUnderline() {
  619. _cursorStyle.setUnderline();
  620. }
  621. @override
  622. void setCursorBlink() {
  623. _cursorStyle.setBlink();
  624. }
  625. @override
  626. void setCursorInverse() {
  627. _cursorStyle.setInverse();
  628. }
  629. @override
  630. void setCursorInvisible() {
  631. _cursorStyle.setInvisible();
  632. }
  633. @override
  634. void setCursorStrikethrough() {
  635. _cursorStyle.setStrikethrough();
  636. }
  637. @override
  638. void unsetCursorBold() {
  639. _cursorStyle.unsetBold();
  640. }
  641. @override
  642. void unsetCursorFaint() {
  643. _cursorStyle.unsetFaint();
  644. }
  645. @override
  646. void unsetCursorItalic() {
  647. _cursorStyle.unsetItalic();
  648. }
  649. @override
  650. void unsetCursorUnderline() {
  651. _cursorStyle.unsetUnderline();
  652. }
  653. @override
  654. void unsetCursorBlink() {
  655. _cursorStyle.unsetBlink();
  656. }
  657. @override
  658. void unsetCursorInverse() {
  659. _cursorStyle.unsetInverse();
  660. }
  661. @override
  662. void unsetCursorInvisible() {
  663. _cursorStyle.unsetInvisible();
  664. }
  665. @override
  666. void unsetCursorStrikethrough() {
  667. _cursorStyle.unsetStrikethrough();
  668. }
  669. @override
  670. void setForegroundColor16(int color) {
  671. _cursorStyle.setForegroundColor16(color);
  672. }
  673. @override
  674. void setForegroundColor256(int index) {
  675. _cursorStyle.setForegroundColor256(index);
  676. }
  677. @override
  678. void setForegroundColorRgb(int r, int g, int b) {
  679. _cursorStyle.setForegroundColorRgb(r, g, b);
  680. }
  681. @override
  682. void resetForeground() {
  683. _cursorStyle.resetForegroundColor();
  684. }
  685. @override
  686. void setBackgroundColor16(int color) {
  687. _cursorStyle.setBackgroundColor16(color);
  688. }
  689. @override
  690. void setBackgroundColor256(int index) {
  691. _cursorStyle.setBackgroundColor256(index);
  692. }
  693. @override
  694. void setBackgroundColorRgb(int r, int g, int b) {
  695. _cursorStyle.setBackgroundColorRgb(r, g, b);
  696. }
  697. @override
  698. void resetBackground() {
  699. _cursorStyle.resetBackgroundColor();
  700. }
  701. @override
  702. void unsupportedStyle(int param) {
  703. // no-op
  704. }
  705. /* OSC */
  706. @override
  707. void setTitle(String name) {
  708. onTitleChange?.call(name);
  709. }
  710. @override
  711. void setIconName(String name) {
  712. onIconChange?.call(name);
  713. }
  714. @override
  715. void unknownOSC(String ps, List<String> pt) {
  716. onPrivateOSC?.call(ps, pt);
  717. }
  718. }