/***************************************************************
** I/O subsystem for PForth for WIN32 systems.
** Use Windows Console so we can add the ANSI console commands needed to support HISTORY
** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
** The pForth software code is dedicated to the public domain,
** and any third party may reproduce, distribute and modify
** the pForth software code or any derivative works thereof
** without any compensation or license. The pForth software
** code is provided on an "as is" basis without any warranty
** of any kind, including, without limitation, the implied
** warranties of merchantability and fitness for a particular
** purpose and their equivalents under the laws of any jurisdiction.
***************************************************************/
#if defined(WIN32) || defined(__NT__)
#define ASCII_ESCAPE (0x1B)
static HANDLE sConsoleHandle
= INVALID_HANDLE_VALUE
;
static int sIsConsoleValid
= FALSE
;
typedef enum ConsoleState_e
SDCONSOLE_STATE_IDLE
= 0,
SDCONSOLE_STATE_GOT_ESCAPE
,
SDCONSOLE_STATE_GOT_BRACKET
static int sConsoleState
= SDCONSOLE_STATE_IDLE
;
static CONSOLE_SCREEN_BUFFER_INFO sScreenInfo
;
/******************************************************************/
static void sdConsoleEmit( char c
)
/* Write a WCHAR in case we have compiled with Unicode support.
* Otherwise we will see '?' printed.*/
WriteConsoleW(sConsoleHandle
, &wc
, 1, &count
, NULL
);
/* This will get called if we are redirecting to a file.*/
WriteFile(sConsoleHandle
, &c
, 1, &count
, NULL
);
/******************************************************************/
static void sdClearScreen( void )
if( GetConsoleScreenBufferInfo( sConsoleHandle
, &sScreenInfo
) )
XY
.Y
= sScreenInfo
.srWindow
.Top
;
numNeeded
= sScreenInfo
.dwSize
.X
* (sScreenInfo
.srWindow
.Bottom
- sScreenInfo
.srWindow
.Top
+ 1);
FillConsoleOutputCharacter(
sConsoleHandle
, ' ', numNeeded
, XY
, &count
);
SetConsoleCursorPosition( sConsoleHandle
, XY
);
/******************************************************************/
static void sdEraseEOL( void )
if( GetConsoleScreenBufferInfo( sConsoleHandle
, &sScreenInfo
) )
savedXY
.X
= sScreenInfo
.dwCursorPosition
.X
;
savedXY
.Y
= sScreenInfo
.dwCursorPosition
.Y
;
numNeeded
= sScreenInfo
.dwSize
.X
- savedXY
.X
;
FillConsoleOutputCharacter(
sConsoleHandle
, ' ', numNeeded
, savedXY
, &count
);
/******************************************************************/
static void sdCursorBack( int dx
)
if( GetConsoleScreenBufferInfo( sConsoleHandle
, &sScreenInfo
) )
XY
.X
= sScreenInfo
.dwCursorPosition
.X
;
XY
.Y
= sScreenInfo
.dwCursorPosition
.Y
;
SetConsoleCursorPosition( sConsoleHandle
, XY
);
/******************************************************************/
static void sdCursorForward( int dx
)
if( GetConsoleScreenBufferInfo( sConsoleHandle
, &sScreenInfo
) )
int width
= sScreenInfo
.dwSize
.X
;
XY
.X
= sScreenInfo
.dwCursorPosition
.X
;
XY
.Y
= sScreenInfo
.dwCursorPosition
.Y
;
if( XY
.X
> width
) XY
.X
= width
;
SetConsoleCursorPosition( sConsoleHandle
, XY
);
/******************************************************************/
/* Use console mode I/O so that KEY and ?TERMINAL will work.
* Parse ANSI escape sequences and call the appropriate cursor
int sdTerminalOut( char c
)
case SDCONSOLE_STATE_IDLE
:
sConsoleState
= SDCONSOLE_STATE_GOT_ESCAPE
;
case SDCONSOLE_STATE_GOT_ESCAPE
:
sConsoleState
= SDCONSOLE_STATE_GOT_BRACKET
;
sConsoleState
= SDCONSOLE_STATE_IDLE
;
case SDCONSOLE_STATE_GOT_BRACKET
:
if( (c
>= '0') && (c
<= '9') )
sParam1
= (sParam1
* 10) + (c
- '0');
sConsoleState
= SDCONSOLE_STATE_IDLE
;
sdCursorForward( sParam1
);
else if( (c
== 'J') && (sParam1
== 2) )
/* Needed cuz _getch() does not echo. */
int sdTerminalEcho( char c
)
sdConsoleEmit((char)(c
));
int sdQueryTerminal( void )
int sdTerminalFlush( void )
return fflush(PF_STDOUT
);
void sdTerminalInit( void )
sConsoleHandle
= GetStdHandle( STD_OUTPUT_HANDLE
);
if( GetConsoleMode( sConsoleHandle
, &mode
) )
/*printf("GetConsoleMode() mode is 0x%08X\n", mode );*/
/*printf("GetConsoleMode() failed\n", mode );*/
void sdTerminalTerm( void )