1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . ComponentModel ;
4+ using System . Runtime . InteropServices ;
5+ using System . Text ;
6+
7+ namespace Org . Edgerunner . ANTLR4 . Tools . Testing . Grun . SyntaxHighlighting
8+ {
9+ public class ConsoleReader
10+ {
11+ public static IEnumerable < string > ReadFromBuffer ( short x , short y , short width , short height )
12+ {
13+ IntPtr buffer = Marshal . AllocHGlobal ( width * height * Marshal . SizeOf ( typeof ( CHAR_INFO ) ) ) ;
14+ if ( buffer == null )
15+ throw new OutOfMemoryException ( ) ;
16+
17+ try
18+ {
19+ COORD coord = new COORD ( ) ;
20+ SMALL_RECT rc = new SMALL_RECT ( ) ;
21+ rc . Left = x ;
22+ rc . Top = y ;
23+ rc . Right = ( short ) ( x + width - 1 ) ;
24+ rc . Bottom = ( short ) ( y + height - 1 ) ;
25+
26+ COORD size = new COORD ( ) ;
27+ size . X = width ;
28+ size . Y = height ;
29+
30+ const int STD_OUTPUT_HANDLE = - 11 ;
31+ if ( ! ReadConsoleOutput ( GetStdHandle ( STD_OUTPUT_HANDLE ) , buffer , size , coord , ref rc ) )
32+ {
33+ // 'Not enough storage is available to process this command' may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
34+ throw new Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
35+ }
36+
37+ IntPtr ptr = buffer ;
38+ for ( int h = 0 ; h < height ; h ++ )
39+ {
40+ StringBuilder sb = new StringBuilder ( ) ;
41+ for ( int w = 0 ; w < width ; w ++ )
42+ {
43+ CHAR_INFO ci = ( CHAR_INFO ) Marshal . PtrToStructure ( ptr , typeof ( CHAR_INFO ) ) ;
44+ char [ ] chars = Console . OutputEncoding . GetChars ( ci . charData ) ;
45+ sb . Append ( chars [ 0 ] ) ;
46+ ptr += Marshal . SizeOf ( typeof ( CHAR_INFO ) ) ;
47+ }
48+ yield return sb . ToString ( ) ;
49+ }
50+ }
51+ finally
52+ {
53+ Marshal . FreeHGlobal ( buffer ) ;
54+ }
55+ }
56+
57+ [ StructLayout ( LayoutKind . Sequential ) ]
58+ private struct CHAR_INFO
59+ {
60+ [ MarshalAs ( UnmanagedType . ByValArray , SizeConst = 2 ) ]
61+ public byte [ ] charData ;
62+ public short attributes ;
63+ }
64+
65+ [ StructLayout ( LayoutKind . Sequential ) ]
66+ private struct COORD
67+ {
68+ public short X ;
69+ public short Y ;
70+ }
71+
72+ [ StructLayout ( LayoutKind . Sequential ) ]
73+ private struct SMALL_RECT
74+ {
75+ public short Left ;
76+ public short Top ;
77+ public short Right ;
78+ public short Bottom ;
79+ }
80+
81+ [ StructLayout ( LayoutKind . Sequential ) ]
82+ private struct CONSOLE_SCREEN_BUFFER_INFO
83+ {
84+ public COORD dwSize ;
85+ public COORD dwCursorPosition ;
86+ public short wAttributes ;
87+ public SMALL_RECT srWindow ;
88+ public COORD dwMaximumWindowSize ;
89+ }
90+
91+ [ DllImport ( "kernel32.dll" , SetLastError = true ) ]
92+ private static extern bool ReadConsoleOutput ( IntPtr hConsoleOutput , IntPtr lpBuffer , COORD dwBufferSize , COORD dwBufferCoord , ref SMALL_RECT lpReadRegion ) ;
93+
94+ [ DllImport ( "kernel32.dll" , SetLastError = true ) ]
95+ private static extern IntPtr GetStdHandle ( int nStdHandle ) ;
96+ }
97+ }
0 commit comments