2 /***************************************************************
\r
3 ** I/O subsystem for PForth for WIN32 systems.
\r
5 ** Use Windows Console so we can add the ANSI console commands needed to support HISTORY
\r
8 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
\r
10 ** The pForth software code is dedicated to the public domain,
\r
11 ** and any third party may reproduce, distribute and modify
\r
12 ** the pForth software code or any derivative works thereof
\r
13 ** without any compensation or license. The pForth software
\r
14 ** code is provided on an "as is" basis without any warranty
\r
15 ** of any kind, including, without limitation, the implied
\r
16 ** warranties of merchantability and fitness for a particular
\r
17 ** purpose and their equivalents under the laws of any jurisdiction.
\r
19 ***************************************************************/
\r
21 #include "../pf_all.h"
\r
25 #include <windows.h>
\r
27 #define ASCII_ESCAPE (0x1B)
\r
29 static HANDLE sConsoleHandle = INVALID_HANDLE_VALUE;
\r
30 static int sIsConsoleValid = FALSE;
\r
32 typedef enum ConsoleState_e
\r
34 SDCONSOLE_STATE_IDLE = 0,
\r
35 SDCONSOLE_STATE_GOT_ESCAPE,
\r
36 SDCONSOLE_STATE_GOT_BRACKET,
\r
40 static int sConsoleState = SDCONSOLE_STATE_IDLE;
\r
41 static int sParam1 = 0;
\r
42 static CONSOLE_SCREEN_BUFFER_INFO sScreenInfo;
\r
44 /******************************************************************/
\r
45 static void sdConsoleEmit( char c )
\r
47 // Write a WCHAR in case we have compiled with Unicode support.
\r
48 // Otherwise we will see '?' printed.
\r
49 WCHAR wc = (WCHAR) c;
\r
51 if( sIsConsoleValid )
\r
53 WriteConsoleW(sConsoleHandle, &wc, 1, &count, NULL );
\r
57 // This will get called if we are redirecting to a file.
\r
58 WriteFile(sConsoleHandle, &c, 1, &count, NULL );
\r
62 /******************************************************************/
\r
63 static void sdClearScreen( void )
\r
65 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )
\r
71 XY.Y = sScreenInfo.srWindow.Top;
\r
72 numNeeded = sScreenInfo.dwSize.X * (sScreenInfo.srWindow.Bottom - sScreenInfo.srWindow.Top + 1);
\r
73 FillConsoleOutputCharacter(
\r
74 sConsoleHandle, ' ', numNeeded, XY, &count );
\r
75 SetConsoleCursorPosition( sConsoleHandle, XY );
\r
79 /******************************************************************/
\r
80 static void sdEraseEOL( void )
\r
82 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )
\r
87 savedXY.X = sScreenInfo.dwCursorPosition.X;
\r
88 savedXY.Y = sScreenInfo.dwCursorPosition.Y;
\r
89 numNeeded = sScreenInfo.dwSize.X - savedXY.X;
\r
90 FillConsoleOutputCharacter(
\r
91 sConsoleHandle, ' ', numNeeded, savedXY, &count );
\r
95 /******************************************************************/
\r
96 static void sdCursorBack( int dx )
\r
98 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )
\r
101 XY.X = sScreenInfo.dwCursorPosition.X;
\r
102 XY.Y = sScreenInfo.dwCursorPosition.Y;
\r
104 if( XY.X < 0 ) XY.X = 0;
\r
105 SetConsoleCursorPosition( sConsoleHandle, XY );
\r
108 /******************************************************************/
\r
109 static void sdCursorForward( int dx )
\r
111 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )
\r
114 int width = sScreenInfo.dwSize.X;
\r
115 XY.X = sScreenInfo.dwCursorPosition.X;
\r
116 XY.Y = sScreenInfo.dwCursorPosition.Y;
\r
118 if( XY.X > width ) XY.X = width;
\r
119 SetConsoleCursorPosition( sConsoleHandle, XY );
\r
123 /******************************************************************/
\r
124 /* Use console mode I/O so that KEY and ?TERMINAL will work.
\r
125 * Parse ANSI escape sequences and call the appropriate cursor
\r
126 * control functions.
\r
128 int sdTerminalOut( char c )
\r
130 switch( sConsoleState )
\r
132 case SDCONSOLE_STATE_IDLE:
\r
136 sConsoleState = SDCONSOLE_STATE_GOT_ESCAPE;
\r
139 sdConsoleEmit( c );
\r
143 case SDCONSOLE_STATE_GOT_ESCAPE:
\r
147 sConsoleState = SDCONSOLE_STATE_GOT_BRACKET;
\r
151 sConsoleState = SDCONSOLE_STATE_IDLE;
\r
152 sdConsoleEmit( c );
\r
156 case SDCONSOLE_STATE_GOT_BRACKET:
\r
157 if( (c >= '0') && (c <= '9') )
\r
159 sParam1 = (sParam1 * 10) + (c - '0');
\r
163 sConsoleState = SDCONSOLE_STATE_IDLE;
\r
168 else if( c == 'D' )
\r
170 sdCursorBack( sParam1 );
\r
172 else if( c == 'C' )
\r
174 sdCursorForward( sParam1 );
\r
176 else if( (c == 'J') && (sParam1 == 2) )
\r
186 /* Needed cuz _getch() does not echo. */
\r
187 int sdTerminalEcho( char c )
\r
189 sdConsoleEmit((char)(c));
\r
193 int sdTerminalIn( void )
\r
198 int sdQueryTerminal( void )
\r
203 int sdTerminalFlush( void )
\r
205 #ifdef PF_NO_FILEIO
\r
208 return fflush(PF_STDOUT);
\r
212 void sdTerminalInit( void )
\r
215 sConsoleHandle = GetStdHandle( STD_OUTPUT_HANDLE );
\r
216 if( GetConsoleMode( sConsoleHandle, &mode ) )
\r
218 //printf("GetConsoleMode() mode is 0x%08X\n", mode );
\r
219 sIsConsoleValid = TRUE;
\r
223 //printf("GetConsoleMode() failed\n", mode );
\r
224 sIsConsoleValid = FALSE;
\r
228 void sdTerminalTerm( void )
\r