@@ -317,7 +317,7 @@ public struct CHAR_INFO
317317 public CHAR_INFO ( char c , ConsoleColor foreground , ConsoleColor background )
318318 {
319319 UnicodeChar = c ;
320- Attributes = ( ushort ) ( ( ( int ) background << 4 ) | ( int ) foreground ) ;
320+ Attributes = ( ushort ) ( ( ( ( int ) background << 4 ) & 0xf ) | ( ( int ) foreground & 0xf ) ) ;
321321 }
322322
323323 [ ExcludeFromCodeCoverage ]
@@ -330,7 +330,7 @@ public ConsoleColor ForegroundColor
330330 [ ExcludeFromCodeCoverage ]
331331 public ConsoleColor BackgroundColor
332332 {
333- get { return ( ConsoleColor ) ( ( Attributes & 0xf0 ) >> 4 ) ; }
333+ get { return ( ConsoleColor ) ( ( Attributes & 0x00f0 ) >> 4 ) ; }
334334 set { Attributes = ( ushort ) ( ( Attributes & 0xff0f ) | ( ( ( int ) value & 0xf ) << 4 ) ) ; }
335335 }
336336
@@ -426,6 +426,7 @@ public static string ToGestureString(this ConsoleKeyInfo key)
426426 }
427427 }
428428
429+ #if ! LINUX
429430 internal class ConhostConsole : IConsole
430431 {
431432 [ SuppressMessage ( "Microsoft.Reliability" , "CA2006:UseSafeHandleToEncapsulateNativeResources" ) ]
@@ -482,18 +483,42 @@ internal class ConhostConsole : IConsole
482483 return new SafeFileHandle ( handle , true ) ;
483484 } ) ;
484485
485- public uint GetConsoleInputMode ( )
486+ public object GetConsoleInputMode ( )
486487 {
488+ uint mode ;
487489 var handle = _inputHandle . Value . DangerousGetHandle ( ) ;
488- uint result ;
489- NativeMethods . GetConsoleMode ( handle , out result ) ;
490- return result ;
490+ NativeMethods . GetConsoleMode ( handle , out mode ) ;
491+ return mode ;
491492 }
492493
493- public void SetConsoleInputMode ( uint mode )
494+ public void SetConsoleInputMode ( object modeObj )
494495 {
495- var handle = _inputHandle . Value . DangerousGetHandle ( ) ;
496- NativeMethods . SetConsoleMode ( handle , mode ) ;
496+ if ( modeObj is uint )
497+ {
498+ // Clear a couple flags so we can actually receive certain keys:
499+ // ENABLE_PROCESSED_INPUT - enables Ctrl+C
500+ // ENABLE_LINE_INPUT - enables Ctrl+S
501+ // Also clear a couple flags so we don't mask the input that we ignore:
502+ // ENABLE_MOUSE_INPUT - mouse events
503+ // ENABLE_WINDOW_INPUT - window resize events
504+ var mode = ( uint ) modeObj &
505+ ~ ( NativeMethods . ENABLE_PROCESSED_INPUT |
506+ NativeMethods . ENABLE_LINE_INPUT |
507+ NativeMethods . ENABLE_WINDOW_INPUT |
508+ NativeMethods . ENABLE_MOUSE_INPUT ) ;
509+
510+ var handle = _inputHandle . Value . DangerousGetHandle ( ) ;
511+ NativeMethods . SetConsoleMode ( handle , mode ) ;
512+ }
513+ }
514+
515+ public void RestoreConsoleInputMode ( object modeObj )
516+ {
517+ if ( modeObj is uint )
518+ {
519+ var handle = _inputHandle . Value . DangerousGetHandle ( ) ;
520+ NativeMethods . SetConsoleMode ( handle , ( uint ) modeObj ) ;
521+ }
497522 }
498523
499524 public ConsoleKeyInfo ReadKey ( )
@@ -601,24 +626,7 @@ public void WriteBufferLines(CHAR_INFO[] buffer, ref int top, bool ensureBottomL
601626 ScrollBuffer ( scrollCount ) ;
602627 top -= scrollCount ;
603628 }
604- #if LINUX
605- ConsoleColor foregroundColor = Console . ForegroundColor ;
606- ConsoleColor backgroundColor = Console . BackgroundColor ;
607-
608- Console . SetCursorPosition ( 0 , ( top >= 0 ) ? top : 0 ) ;
609-
610- for ( int i = 0 ; i < buffer . Length ; ++ i )
611- {
612- // TODO: use escape sequences for better perf
613- Console . ForegroundColor = buffer [ i ] . ForegroundColor ;
614- Console . BackgroundColor = buffer [ i ] . BackgroundColor ;
615-
616- Console . Write ( ( char ) buffer [ i ] . UnicodeChar ) ;
617- }
618629
619- Console . BackgroundColor = backgroundColor ;
620- Console . ForegroundColor = foregroundColor ;
621- #else
622630 var handle = NativeMethods . GetStdHandle ( ( uint ) StandardHandleId . Output ) ;
623631 var bufferSize = new COORD
624632 {
@@ -643,18 +651,10 @@ public void WriteBufferLines(CHAR_INFO[] buffer, ref int top, bool ensureBottomL
643651 {
644652 Console . CursorTop = bottom ;
645653 }
646- #endif
647654 }
648655
649656 public void ScrollBuffer ( int lines )
650657 {
651- #if LINUX
652- for ( int i = 0 ; i < lines ; ++ i )
653- {
654- Console . SetCursorPosition ( Console . BufferWidth , Console . BufferHeight - 1 ) ;
655- Console . WriteLine ( ) ;
656- }
657- #else
658658 var handle = NativeMethods . GetStdHandle ( ( uint ) StandardHandleId . Output ) ;
659659
660660 var scrollRectangle = new SMALL_RECT
@@ -667,20 +667,11 @@ public void ScrollBuffer(int lines)
667667 var destinationOrigin = new COORD { X = 0 , Y = 0 } ;
668668 var fillChar = new CHAR_INFO ( ' ' , Console . ForegroundColor , Console . BackgroundColor ) ;
669669 NativeMethods . ScrollConsoleScreenBuffer ( handle , ref scrollRectangle , IntPtr . Zero , destinationOrigin , ref fillChar ) ;
670- #endif
671670 }
672671
673672 public CHAR_INFO [ ] ReadBufferLines ( int top , int count )
674673 {
675674 var result = new CHAR_INFO [ BufferWidth * count ] ;
676- #if LINUX
677- for ( int i = 0 ; i < BufferWidth * count ; ++ i )
678- {
679- result [ i ] . UnicodeChar = ' ' ;
680- result [ i ] . ForegroundColor = Console . ForegroundColor ;
681- result [ i ] . BackgroundColor = Console . BackgroundColor ;
682- }
683- #else
684675 var handle = NativeMethods . GetStdHandle ( ( uint ) StandardHandleId . Output ) ;
685676
686677 var readBufferSize = new COORD {
@@ -696,7 +687,7 @@ public CHAR_INFO[] ReadBufferLines(int top, int count)
696687 } ;
697688 NativeMethods . ReadConsoleOutput ( handle , result ,
698689 readBufferSize , readBufferCoord , ref readRegion ) ;
699- #endif
690+
700691 return result ;
701692 }
702693
@@ -891,14 +882,196 @@ public void EndRender()
891882 NativeMethods . ReleaseDC ( _hwnd , _hDC ) ;
892883 }
893884 }
885+ }
886+
887+ #else
888+
889+ internal class TTYConsole : IConsole
890+ {
891+ public object GetConsoleInputMode ( )
892+ {
893+ return Console . TreatControlCAsInput ;
894+ }
894895
895- #if LINUX // TODO: this is not correct, PSReadline never clears the screen, it should only scroll
896+ public void SetConsoleInputMode ( object modeObj )
897+ {
898+ Console . TreatControlCAsInput = true ;
899+ }
900+
901+ public void RestoreConsoleInputMode ( object modeObj )
902+ {
903+ if ( modeObj is bool )
904+ {
905+ Console . TreatControlCAsInput = ( bool ) modeObj ;
906+ }
907+ }
908+
909+ public ConsoleKeyInfo ReadKey ( )
910+ {
911+ return Console . ReadKey ( true ) ;
912+ }
913+
914+ public bool KeyAvailable
915+ {
916+ get { return Console . KeyAvailable ; }
917+ }
918+
919+ public int CursorLeft
920+ {
921+ get { return Console . CursorLeft ; }
922+ set { Console . CursorLeft = value ; }
923+ }
924+
925+ public int CursorTop
926+ {
927+ get { return Console . CursorTop ; }
928+ set { Console . CursorTop = value ; }
929+ }
930+
931+ public int CursorSize
932+ {
933+ get { return Console . CursorSize ; }
934+ set { Console . CursorSize = value ; }
935+ }
936+
937+ public int BufferWidth
938+ {
939+ get { return Console . BufferWidth ; }
940+ set { Console . BufferWidth = value ; }
941+ }
942+
943+ public int BufferHeight
944+ {
945+ get { return Console . BufferHeight ; }
946+ set { Console . BufferHeight = value ; }
947+ }
948+
949+ public int WindowWidth
950+ {
951+ get { return Console . WindowWidth ; }
952+ set { Console . WindowWidth = value ; }
953+ }
954+
955+ public int WindowHeight
956+ {
957+ get { return Console . WindowHeight ; }
958+ set { Console . WindowHeight = value ; }
959+ }
960+
961+ public int WindowTop
962+ {
963+ get { return Console . WindowTop ; }
964+ set { Console . WindowTop = value ; }
965+ }
966+
967+ public ConsoleColor BackgroundColor
968+ {
969+ get { return Console . BackgroundColor ; }
970+ set { Console . BackgroundColor = value ; }
971+ }
972+
973+ public ConsoleColor ForegroundColor
974+ {
975+ get { return Console . ForegroundColor ; }
976+ set { Console . ForegroundColor = value ; }
977+ }
978+
979+ public void SetWindowPosition ( int left , int top )
980+ {
981+ Console . SetWindowPosition ( left , top ) ;
982+ }
983+
984+ public void SetCursorPosition ( int left , int top )
985+ {
986+ Console . SetCursorPosition ( left , top ) ;
987+ }
988+
989+ public void Write ( string value )
990+ {
991+ Console . Write ( value ) ;
992+ }
993+
994+ public void WriteLine ( string value )
995+ {
996+ Console . WriteLine ( value ) ;
997+ }
998+
999+ public void WriteBufferLines ( CHAR_INFO [ ] buffer , ref int top )
1000+ {
1001+ WriteBufferLines ( buffer , ref top , true ) ;
1002+ }
1003+
1004+ public void WriteBufferLines ( CHAR_INFO [ ] buffer , ref int top , bool ensureBottomLineVisible )
1005+ {
1006+ int bufferWidth = Console . BufferWidth ;
1007+ int bufferLineCount = buffer . Length / bufferWidth ;
1008+ if ( ( top + bufferLineCount ) > Console . BufferHeight )
1009+ {
1010+ var scrollCount = ( top + bufferLineCount ) - Console . BufferHeight ;
1011+ ScrollBuffer ( scrollCount ) ;
1012+ top -= scrollCount ;
1013+ }
1014+
1015+ ConsoleColor foregroundColor = Console . ForegroundColor ;
1016+ ConsoleColor backgroundColor = Console . BackgroundColor ;
1017+
1018+ Console . SetCursorPosition ( 0 , ( top >= 0 ) ? top : 0 ) ;
1019+
1020+ for ( int i = 0 ; i < buffer . Length ; ++ i )
1021+ {
1022+ // TODO: use escape sequences for better perf
1023+ Console . ForegroundColor = buffer [ i ] . ForegroundColor ;
1024+ Console . BackgroundColor = buffer [ i ] . BackgroundColor ;
1025+
1026+ Console . Write ( ( char ) buffer [ i ] . UnicodeChar ) ;
1027+ }
1028+
1029+ Console . BackgroundColor = backgroundColor ;
1030+ Console . ForegroundColor = foregroundColor ;
1031+ }
1032+
1033+ public void ScrollBuffer ( int lines )
1034+ {
1035+ for ( int i = 0 ; i < lines ; ++ i )
1036+ {
1037+ Console . SetCursorPosition ( Console . BufferWidth , Console . BufferHeight - 1 ) ;
1038+ Console . WriteLine ( ) ;
1039+ }
1040+ }
1041+
1042+ public CHAR_INFO [ ] ReadBufferLines ( int top , int count )
1043+ {
1044+ var result = new CHAR_INFO [ BufferWidth * count ] ;
1045+ for ( int i = 0 ; i < BufferWidth * count ; ++ i )
1046+ {
1047+ result [ i ] . UnicodeChar = ' ' ;
1048+ result [ i ] . ForegroundColor = Console . ForegroundColor ;
1049+ result [ i ] . BackgroundColor = Console . BackgroundColor ;
1050+ }
1051+ return result ;
1052+ }
1053+
1054+ public int LengthInBufferCells ( char c )
1055+ {
1056+ return 1 ;
1057+ }
1058+
1059+
1060+ public void StartRender ( )
1061+ {
1062+ }
1063+
1064+ public void EndRender ( )
1065+ {
1066+ }
1067+
1068+ // TODO: this is not correct, PSReadline never clears the screen, it should only scroll
8961069 public void Clear ( )
8971070 {
8981071 Console . Clear ( ) ;
8991072 }
900- #endif
9011073 }
1074+ #endif
9021075
9031076#if CORECLR // TODO: remove if CORECLR adds this attribute back
9041077 [ AttributeUsage ( AttributeTargets . Class | AttributeTargets . Struct | AttributeTargets . Constructor | AttributeTargets . Method | AttributeTargets . Property | AttributeTargets . Event ) ]
0 commit comments