WindowsDriver.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Threading.Tasks;
  4. using Mono.Terminal;
  5. using NStack;
  6. namespace Terminal.Gui {
  7. internal class WindowsConsole {
  8. public const int STD_OUTPUT_HANDLE = -11;
  9. public const int STD_INPUT_HANDLE = -10;
  10. public const int STD_ERROR_HANDLE = -12;
  11. public IntPtr InputHandle, OutputHandle;
  12. public IntPtr ScreenBuffer;
  13. public WindowsConsole ()
  14. {
  15. InputHandle = GetStdHandle (STD_INPUT_HANDLE);
  16. OutputHandle = GetStdHandle (STD_OUTPUT_HANDLE);
  17. }
  18. public CharInfo[] OriginalStdOutChars;
  19. public bool WriteToConsole(CharInfo[] charInfoBuffer, Coord coords, SmallRect window)
  20. {
  21. if (ScreenBuffer == IntPtr.Zero)
  22. {
  23. ScreenBuffer = CreateConsoleScreenBuffer(
  24. DesiredAccess.GenericRead | DesiredAccess.GenericWrite,
  25. ShareMode.FileShareRead | ShareMode.FileShareWrite,
  26. IntPtr.Zero,
  27. 1,
  28. IntPtr.Zero
  29. );
  30. var err = Marshal.GetLastWin32Error();
  31. if (err != 0)
  32. {
  33. Console.WriteLine("Error: {0}", err);
  34. throw new System.ComponentModel.Win32Exception(err);
  35. }
  36. if (!SetConsoleActiveScreenBuffer(ScreenBuffer))
  37. {
  38. err = Marshal.GetLastWin32Error();
  39. Console.WriteLine("Error: {0}", err);
  40. }
  41. OriginalStdOutChars = new CharInfo[Console.WindowHeight * Console.WindowWidth];
  42. ReadConsoleOutput(
  43. OutputHandle,
  44. OriginalStdOutChars,
  45. coords,
  46. new Coord() { X = 0, Y = 0 },
  47. ref window
  48. );
  49. }
  50. return WriteConsoleOutput(
  51. ScreenBuffer,
  52. charInfoBuffer,
  53. coords,
  54. new Coord() { X = 0, Y = 0 },
  55. ref window
  56. );
  57. }
  58. [Flags]
  59. public enum ConsoleModes : uint
  60. {
  61. EnableMouseInput = 16,
  62. EnableQuickEditMode = 64,
  63. EnableExtendedFlags = 128,
  64. }
  65. [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
  66. public struct KeyEventRecord {
  67. [FieldOffset (0), MarshalAs (UnmanagedType.Bool)]
  68. public bool bKeyDown;
  69. [FieldOffset (4), MarshalAs (UnmanagedType.U2)]
  70. public ushort wRepeatCount;
  71. [FieldOffset (6), MarshalAs (UnmanagedType.U2)]
  72. public ushort wVirtualKeyCode;
  73. [FieldOffset (8), MarshalAs (UnmanagedType.U2)]
  74. public ushort wVirtualScanCode;
  75. [FieldOffset (10)]
  76. public char UnicodeChar;
  77. [FieldOffset (12), MarshalAs (UnmanagedType.U4)]
  78. public ControlKeyState dwControlKeyState;
  79. }
  80. [Flags]
  81. public enum ButtonState {
  82. Button1Pressed = 1,
  83. Button2Pressed = 4,
  84. Button3Pressed = 8,
  85. Button4Pressed = 16,
  86. RightmostButtonPressed = 2,
  87. }
  88. [Flags]
  89. public enum ControlKeyState {
  90. RightAltPressed = 1,
  91. LeftAltPressed = 2,
  92. RightControlPressed = 4,
  93. LeftControlPressed = 8,
  94. ShiftPressed = 16,
  95. NumlockOn = 32,
  96. ScrolllockOn = 64,
  97. CapslockOn = 128,
  98. EnhancedKey = 256
  99. }
  100. [Flags]
  101. public enum EventFlags {
  102. MouseMoved = 1,
  103. DoubleClick = 2,
  104. MouseWheeled = 4,
  105. MouseHorizontalWheeled = 8
  106. }
  107. [StructLayout (LayoutKind.Explicit)]
  108. public struct MouseEventRecord {
  109. [FieldOffset (0)]
  110. public Coordinate MousePosition;
  111. [FieldOffset (4)]
  112. public ButtonState ButtonState;
  113. [FieldOffset (8)]
  114. public ControlKeyState ControlKeyState;
  115. [FieldOffset (12)]
  116. public EventFlags EventFlags;
  117. public override string ToString ()
  118. {
  119. return $"[Mouse({MousePosition},{ButtonState},{ControlKeyState},{EventFlags}";
  120. }
  121. }
  122. [StructLayout (LayoutKind.Sequential)]
  123. public struct Coordinate {
  124. public short X;
  125. public short Y;
  126. public Coordinate (short X, short Y)
  127. {
  128. this.X = X;
  129. this.Y = Y;
  130. }
  131. public override string ToString () => $"({X},{Y})";
  132. };
  133. internal struct WindowBufferSizeRecord {
  134. public Coordinate size;
  135. public WindowBufferSizeRecord (short x, short y)
  136. {
  137. this.size = new Coordinate (x, y);
  138. }
  139. public override string ToString () => $"[WindowBufferSize{size}";
  140. }
  141. [StructLayout (LayoutKind.Sequential)]
  142. public struct MenuEventRecord {
  143. public uint dwCommandId;
  144. }
  145. [StructLayout (LayoutKind.Sequential)]
  146. public struct FocusEventRecord {
  147. public uint bSetFocus;
  148. }
  149. public enum EventType {
  150. Focus = 0x10,
  151. Key = 0x1,
  152. Menu = 0x8,
  153. Mouse = 2,
  154. WindowBufferSize = 4
  155. }
  156. [StructLayout (LayoutKind.Explicit)]
  157. public struct InputRecord {
  158. [FieldOffset (0)]
  159. public EventType EventType;
  160. [FieldOffset (4)]
  161. public KeyEventRecord KeyEvent;
  162. [FieldOffset (4)]
  163. public MouseEventRecord MouseEvent;
  164. [FieldOffset (4)]
  165. public WindowBufferSizeRecord WindowBufferSizeEvent;
  166. [FieldOffset (4)]
  167. public MenuEventRecord MenuEvent;
  168. [FieldOffset (4)]
  169. public FocusEventRecord FocusEvent;
  170. public override string ToString ()
  171. {
  172. switch (EventType) {
  173. case EventType.Focus:
  174. return FocusEvent.ToString ();
  175. case EventType.Key:
  176. return KeyEvent.ToString ();
  177. case EventType.Menu:
  178. return MenuEvent.ToString ();
  179. case EventType.Mouse:
  180. return MouseEvent.ToString ();
  181. case EventType.WindowBufferSize:
  182. return WindowBufferSizeEvent.ToString ();
  183. default:
  184. return "Unknown event type: " + EventType;
  185. }
  186. }
  187. };
  188. public void PollEvents(Action<InputRecord> inputEventHandler)
  189. {
  190. if (OriginalConsoleMode != 0)
  191. return;
  192. OriginalConsoleMode = ConsoleMode;
  193. ConsoleMode |= (uint)ConsoleModes.EnableMouseInput;
  194. ConsoleMode &= ~(uint)ConsoleModes.EnableQuickEditMode;
  195. ConsoleMode |= (uint)ConsoleModes.EnableExtendedFlags;
  196. Task.Run(() =>
  197. {
  198. uint numberEventsRead = 0;
  199. uint length = 1;
  200. InputRecord[] records = new InputRecord[length];
  201. while (
  202. ContinueListeningForConsoleEvents &&
  203. ReadConsoleInput(InputHandle, records, length, out numberEventsRead) &&
  204. numberEventsRead > 0
  205. )
  206. {
  207. inputEventHandler(records[0]);
  208. }
  209. });
  210. }
  211. public void Cleanup()
  212. {
  213. ContinueListeningForConsoleEvents = false;
  214. ConsoleMode = OriginalConsoleMode;
  215. OriginalConsoleMode = 0;
  216. if (!SetConsoleActiveScreenBuffer(OutputHandle))
  217. {
  218. var err = Marshal.GetLastWin32Error();
  219. Console.WriteLine("Error: {0}", err);
  220. }
  221. }
  222. private bool ContinueListeningForConsoleEvents = true;
  223. private uint OriginalConsoleMode = 0;
  224. public uint ConsoleMode {
  225. get {
  226. uint v;
  227. GetConsoleMode (InputHandle, out v);
  228. return v;
  229. }
  230. set {
  231. SetConsoleMode (InputHandle, value);
  232. }
  233. }
  234. [Flags]
  235. enum ShareMode : uint
  236. {
  237. FileShareRead = 1,
  238. FileShareWrite = 2,
  239. }
  240. [Flags]
  241. enum DesiredAccess : uint
  242. {
  243. GenericRead = 2147483648,
  244. GenericWrite = 1073741824,
  245. }
  246. [StructLayout(LayoutKind.Sequential)]
  247. public struct ConsoleScreenBufferInfo
  248. {
  249. public Coord dwSize;
  250. public Coord dwCursorPosition;
  251. public ushort wAttributes;
  252. public SmallRect srWindow;
  253. public Coord dwMaximumWindowSize;
  254. }
  255. [StructLayout(LayoutKind.Sequential)]
  256. public struct Coord
  257. {
  258. public short X;
  259. public short Y;
  260. public Coord(short X, short Y)
  261. {
  262. this.X = X;
  263. this.Y = Y;
  264. }
  265. };
  266. [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
  267. public struct CharUnion
  268. {
  269. [FieldOffset(0)] public char UnicodeChar;
  270. [FieldOffset(0)] public byte AsciiChar;
  271. }
  272. [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
  273. public struct CharInfo
  274. {
  275. [FieldOffset(0)] public CharUnion Char;
  276. [FieldOffset(2)] public ushort Attributes;
  277. }
  278. [StructLayout(LayoutKind.Sequential)]
  279. public struct SmallRect
  280. {
  281. public short Left;
  282. public short Top;
  283. public short Right;
  284. public short Bottom;
  285. }
  286. [DllImport ("kernel32.dll", SetLastError = true)]
  287. static extern IntPtr GetStdHandle (int nStdHandle);
  288. [DllImport ("kernel32.dll", EntryPoint = "ReadConsoleInputW", CharSet = CharSet.Unicode)]
  289. public static extern bool ReadConsoleInput (
  290. IntPtr hConsoleInput,
  291. [Out] InputRecord [] lpBuffer,
  292. uint nLength,
  293. out uint lpNumberOfEventsRead);
  294. [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
  295. static extern bool ReadConsoleOutput(
  296. IntPtr hConsoleOutput,
  297. [Out] CharInfo[] lpBuffer,
  298. Coord dwBufferSize,
  299. Coord dwBufferCoord,
  300. ref SmallRect lpReadRegion
  301. );
  302. [DllImport("kernel32.dll", EntryPoint="WriteConsoleOutput", SetLastError=true, CharSet=CharSet.Unicode)]
  303. static extern bool WriteConsoleOutput(
  304. IntPtr hConsoleOutput,
  305. CharInfo[] lpBuffer,
  306. Coord dwBufferSize,
  307. Coord dwBufferCoord,
  308. ref SmallRect lpWriteRegion
  309. );
  310. [DllImport ("kernel32.dll")]
  311. static extern bool GetConsoleMode (IntPtr hConsoleHandle, out uint lpMode);
  312. [DllImport ("kernel32.dll")]
  313. static extern bool SetConsoleMode (IntPtr hConsoleHandle, uint dwMode);
  314. [DllImport("kernel32.dll", SetLastError = true)]
  315. static extern IntPtr CreateConsoleScreenBuffer(
  316. DesiredAccess dwDesiredAccess,
  317. ShareMode dwShareMode,
  318. IntPtr secutiryAttributes,
  319. UInt32 flags,
  320. IntPtr screenBufferData
  321. );
  322. [DllImport("kernel32.dll", SetLastError = true)]
  323. static extern bool SetConsoleActiveScreenBuffer(IntPtr Handle);
  324. }
  325. internal class WindowsDriver : ConsoleDriver {
  326. Action TerminalResized;
  327. WindowsConsole WinConsole;
  328. WindowsConsole.CharInfo[] OutputBuffer;
  329. int cols, rows;
  330. public override int Cols => cols;
  331. public override int Rows => rows;
  332. static bool sync;
  333. public WindowsDriver ()
  334. {
  335. WinConsole = new WindowsConsole();
  336. cols = Console.WindowWidth;
  337. rows = Console.WindowHeight - 1;
  338. ResizeScreen ();
  339. UpdateOffScreen ();
  340. }
  341. private MouseEvent ToDriverMouse(WindowsConsole.MouseEventRecord mouseEvent)
  342. {
  343. MouseFlags mouseFlag = MouseFlags.AllEvents;
  344. if (mouseEvent.EventFlags == 0)
  345. {
  346. switch (mouseEvent.ButtonState)
  347. {
  348. case WindowsConsole.ButtonState.Button1Pressed:
  349. mouseFlag = MouseFlags.Button1Clicked;
  350. break;
  351. case WindowsConsole.ButtonState.Button2Pressed:
  352. mouseFlag = MouseFlags.Button2Clicked;
  353. break;
  354. case WindowsConsole.ButtonState.Button3Pressed:
  355. mouseFlag = MouseFlags.Button3Clicked;
  356. break;
  357. }
  358. }
  359. else if(mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved)
  360. {
  361. mouseFlag = MouseFlags.ReportMousePosition;
  362. }
  363. return new MouseEvent () {
  364. X = mouseEvent.MousePosition.X,
  365. Y = mouseEvent.MousePosition.Y,
  366. Flags = mouseFlag
  367. };
  368. }
  369. private ConsoleKeyInfo ToConsoleKeyInfo (WindowsConsole.KeyEventRecord keyEvent)
  370. {
  371. var state = keyEvent.dwControlKeyState;
  372. bool shift = (state & WindowsConsole.ControlKeyState.ShiftPressed) != 0;
  373. bool alt = (state & (WindowsConsole.ControlKeyState.LeftAltPressed | WindowsConsole.ControlKeyState.RightAltPressed)) != 0;
  374. bool control = (state & (WindowsConsole.ControlKeyState.LeftControlPressed | WindowsConsole.ControlKeyState.RightControlPressed)) != 0;
  375. return new ConsoleKeyInfo(keyEvent.UnicodeChar, (ConsoleKey)keyEvent.wVirtualKeyCode, shift, alt, control);
  376. }
  377. public Key MapKey (ConsoleKeyInfo keyInfo)
  378. {
  379. switch (keyInfo.Key) {
  380. case ConsoleKey.Escape:
  381. return Key.Esc;
  382. case ConsoleKey.Tab:
  383. return Key.Tab;
  384. case ConsoleKey.Home:
  385. return Key.Home;
  386. case ConsoleKey.End:
  387. return Key.End;
  388. case ConsoleKey.LeftArrow:
  389. return Key.CursorLeft;
  390. case ConsoleKey.RightArrow:
  391. return Key.CursorRight;
  392. case ConsoleKey.UpArrow:
  393. return Key.CursorUp;
  394. case ConsoleKey.DownArrow:
  395. return Key.CursorDown;
  396. case ConsoleKey.PageUp:
  397. return Key.PageUp;
  398. case ConsoleKey.PageDown:
  399. return Key.PageDown;
  400. case ConsoleKey.Enter:
  401. return Key.Enter;
  402. case ConsoleKey.Spacebar:
  403. return Key.Space;
  404. case ConsoleKey.Backspace:
  405. return Key.Backspace;
  406. case ConsoleKey.Delete:
  407. return Key.Delete;
  408. case ConsoleKey.Oem1:
  409. case ConsoleKey.Oem2:
  410. case ConsoleKey.Oem3:
  411. case ConsoleKey.Oem4:
  412. case ConsoleKey.Oem5:
  413. case ConsoleKey.Oem6:
  414. case ConsoleKey.Oem7:
  415. case ConsoleKey.Oem8:
  416. case ConsoleKey.Oem102:
  417. case ConsoleKey.OemPeriod:
  418. case ConsoleKey.OemComma:
  419. case ConsoleKey.OemPlus:
  420. case ConsoleKey.OemMinus:
  421. return (Key)((uint)keyInfo.KeyChar);
  422. }
  423. var key = keyInfo.Key;
  424. if (key >= ConsoleKey.A && key <= ConsoleKey.Z) {
  425. var delta = key - ConsoleKey.A;
  426. if (keyInfo.Modifiers == ConsoleModifiers.Control)
  427. return (Key)((uint)Key.ControlA + delta);
  428. if (keyInfo.Modifiers == ConsoleModifiers.Alt)
  429. return (Key)(((uint)Key.AltMask) | ((uint)'A' + delta));
  430. if (keyInfo.Modifiers == ConsoleModifiers.Shift)
  431. return (Key)((uint)'A' + delta);
  432. else
  433. return (Key)((uint)'a' + delta);
  434. }
  435. if (key >= ConsoleKey.D0 && key <= ConsoleKey.D9) {
  436. var delta = key - ConsoleKey.D0;
  437. if (keyInfo.Modifiers == ConsoleModifiers.Alt)
  438. return (Key)(((uint)Key.AltMask) | ((uint)'0' + delta));
  439. if (keyInfo.Modifiers == ConsoleModifiers.Shift)
  440. return (Key)((uint)keyInfo.KeyChar);
  441. return (Key)((uint)'0' + delta);
  442. }
  443. if (key >= ConsoleKey.F1 && key <= ConsoleKey.F10) {
  444. var delta = key - ConsoleKey.F1;
  445. return (Key)((int)Key.F1 + delta);
  446. }
  447. return (Key)(0xffffffff);
  448. }
  449. public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<MouseEvent> mouseHandler)
  450. {
  451. WinConsole.PollEvents (inputEvent =>
  452. {
  453. switch(inputEvent.EventType)
  454. {
  455. case WindowsConsole.EventType.Key:
  456. if (inputEvent.KeyEvent.bKeyDown == false)
  457. return;
  458. var map = MapKey (ToConsoleKeyInfo (inputEvent.KeyEvent));
  459. if (map == (Key) 0xffffffff)
  460. return;
  461. keyHandler (new KeyEvent (map));
  462. break;
  463. case WindowsConsole.EventType.Mouse:
  464. mouseHandler (ToDriverMouse (inputEvent.MouseEvent));
  465. break;
  466. case WindowsConsole.EventType.WindowBufferSize:
  467. cols = inputEvent.WindowBufferSizeEvent.size.X;
  468. rows = inputEvent.WindowBufferSizeEvent.size.Y - 1;
  469. ResizeScreen ();
  470. UpdateOffScreen ();
  471. TerminalResized ();
  472. break;
  473. }
  474. });
  475. }
  476. public override void Init (Action terminalResized)
  477. {
  478. TerminalResized = terminalResized;
  479. Colors.Base = new ColorScheme ();
  480. Colors.Dialog = new ColorScheme ();
  481. Colors.Menu = new ColorScheme ();
  482. Colors.Error = new ColorScheme ();
  483. HLine = '\u2500';
  484. VLine = '\u2502';
  485. Stipple = '\u2592';
  486. Diamond = '\u25c6';
  487. ULCorner = '\u250C';
  488. LLCorner = '\u2514';
  489. URCorner = '\u2510';
  490. LRCorner = '\u2518';
  491. LeftTee = '\u251c';
  492. RightTee = '\u2524';
  493. TopTee = '\u22a4';
  494. BottomTee = '\u22a5';
  495. Colors.Base.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Blue);
  496. Colors.Base.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
  497. Colors.Base.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Blue);
  498. Colors.Base.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
  499. Colors.Menu.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Black);
  500. Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
  501. Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
  502. Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
  503. Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
  504. Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
  505. Colors.Dialog.HotNormal = MakeColor (ConsoleColor.Blue, ConsoleColor.Gray);
  506. Colors.Dialog.HotFocus = MakeColor (ConsoleColor.Blue, ConsoleColor.Cyan);
  507. Colors.Error.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Red);
  508. Colors.Error.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
  509. Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
  510. Colors.Error.HotFocus = Colors.Error.HotNormal;
  511. Console.Clear ();
  512. }
  513. void ResizeScreen ()
  514. {
  515. OutputBuffer = new WindowsConsole.CharInfo[Rows * Cols];
  516. Clip = new Rect (0, 0, Cols, Rows);
  517. }
  518. void UpdateOffScreen ()
  519. {
  520. for (int row = 0; row < rows; row++)
  521. for (int col = 0; col < cols; col++)
  522. {
  523. int position = row * cols + col;
  524. OutputBuffer[position].Attributes = (ushort)MakeColor(ConsoleColor.White, ConsoleColor.Blue);
  525. OutputBuffer[position].Char.UnicodeChar = ' ';
  526. }
  527. }
  528. int ccol, crow;
  529. public override void Move (int col, int row)
  530. {
  531. ccol = col;
  532. crow = row;
  533. }
  534. public override void AddRune (Rune rune)
  535. {
  536. var position = crow * Cols + ccol;
  537. if (Clip.Contains (ccol, crow))
  538. {
  539. OutputBuffer[position].Attributes = (ushort)currentAttribute;
  540. OutputBuffer[position].Char.UnicodeChar = (char)rune;
  541. }
  542. ccol++;
  543. if (ccol == Cols) {
  544. ccol = 0;
  545. if (crow + 1 < Rows)
  546. crow++;
  547. }
  548. if (sync)
  549. UpdateScreen ();
  550. }
  551. public override void AddStr (ustring str)
  552. {
  553. foreach (var rune in str)
  554. AddRune (rune);
  555. }
  556. int currentAttribute;
  557. public override void SetAttribute (Attribute c)
  558. {
  559. currentAttribute = c.value;
  560. }
  561. private Attribute MakeColor (ConsoleColor f, ConsoleColor b)
  562. {
  563. // Encode the colors into the int value.
  564. return new Attribute ()
  565. {
  566. value = ((int)f | (int)b << 4)
  567. };
  568. }
  569. public override void Refresh()
  570. {
  571. var bufferCoords = new WindowsConsole.Coord ()
  572. {
  573. X = (short)Clip.Width,
  574. Y = (short)Clip.Height
  575. };
  576. var window = new WindowsConsole.SmallRect ()
  577. {
  578. Top = 0,
  579. Left = 0,
  580. Right = (short)Clip.Right,
  581. Bottom = (short)Clip.Bottom
  582. };
  583. WinConsole.WriteToConsole (OutputBuffer, bufferCoords, window);
  584. }
  585. public override void UpdateScreen ()
  586. {
  587. var bufferCoords = new WindowsConsole.Coord ()
  588. {
  589. X = (short)Clip.Width,
  590. Y = (short)Clip.Height
  591. };
  592. var window = new WindowsConsole.SmallRect ()
  593. {
  594. Top = 0,
  595. Left = 0,
  596. Right = (short)Clip.Right,
  597. Bottom = (short)Clip.Bottom
  598. };
  599. WinConsole.WriteToConsole (OutputBuffer, bufferCoords, window);
  600. }
  601. public override void End ()
  602. {
  603. WinConsole.Cleanup();
  604. }
  605. #region Unused
  606. public override void SetColors (ConsoleColor foreground, ConsoleColor background)
  607. {
  608. }
  609. public override void UpdateCursor()
  610. {
  611. }
  612. public override void SetColors (short foregroundColorId, short backgroundColorId)
  613. {
  614. }
  615. public override void Suspend ()
  616. {
  617. }
  618. public override void StartReportingMouseMoves ()
  619. {
  620. }
  621. public override void StopReportingMouseMoves ()
  622. {
  623. }
  624. public override void UncookMouse ()
  625. {
  626. }
  627. public override void CookMouse ()
  628. {
  629. }
  630. #endregion
  631. }
  632. }