X-Git-Url: http://git.subgeniuskitty.com/pforth/.git/blobdiff_plain/c232a9379c2e4683bed211e845e4d85b7a7e2499..1f99f95d6a7eecc05cae8fb357f9b7bf564c2725:/csrc/win32_console/pf_io_win32_console.c diff --git a/csrc/win32_console/pf_io_win32_console.c b/csrc/win32_console/pf_io_win32_console.c index a081812..d8e5389 100644 --- a/csrc/win32_console/pf_io_win32_console.c +++ b/csrc/win32_console/pf_io_win32_console.c @@ -1,231 +1,234 @@ -/* $Id$ */ -/*************************************************************** -** I/O subsystem for PForth for WIN32 systems. -** -** Use Windows Console so we can add the ANSI console commands needed to support HISTORY -** -** Author: Phil Burk -** 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. -** -***************************************************************/ - -#include "../pf_all.h" - -#if defined(WIN32) || defined(__NT__) - -#include - -#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 - -} ConsoleState; - -static int sConsoleState = SDCONSOLE_STATE_IDLE; -static int sParam1 = 0; -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.*/ - WCHAR wc = (WCHAR) c; - DWORD count; - if( sIsConsoleValid ) - { - WriteConsoleW(sConsoleHandle, &wc, 1, &count, NULL ); - } - else - { - /* 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 ) ) - { - COORD XY; - int numNeeded; - DWORD count; - XY.X = 0; - 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 ) ) - { - COORD savedXY; - int numNeeded; - DWORD count; - 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 ) ) - { - COORD XY; - XY.X = sScreenInfo.dwCursorPosition.X; - XY.Y = sScreenInfo.dwCursorPosition.Y; - XY.X -= dx; - if( XY.X < 0 ) XY.X = 0; - SetConsoleCursorPosition( sConsoleHandle, XY ); - } -} -/******************************************************************/ -static void sdCursorForward( int dx ) -{ - if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) ) - { - COORD XY; - int width = sScreenInfo.dwSize.X; - XY.X = sScreenInfo.dwCursorPosition.X; - XY.Y = sScreenInfo.dwCursorPosition.Y; - XY.X += dx; - 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 - * control functions. - */ -int sdTerminalOut( char c ) -{ - switch( sConsoleState ) - { - case SDCONSOLE_STATE_IDLE: - switch( c ) - { - case ASCII_ESCAPE: - sConsoleState = SDCONSOLE_STATE_GOT_ESCAPE; - break; - default: - sdConsoleEmit( c ); - } - break; - - case SDCONSOLE_STATE_GOT_ESCAPE: - switch( c ) - { - case '[': - sConsoleState = SDCONSOLE_STATE_GOT_BRACKET; - sParam1 = 0; - break; - default: - sConsoleState = SDCONSOLE_STATE_IDLE; - sdConsoleEmit( c ); - } - break; - - case SDCONSOLE_STATE_GOT_BRACKET: - if( (c >= '0') && (c <= '9') ) - { - sParam1 = (sParam1 * 10) + (c - '0'); - } - else - { - sConsoleState = SDCONSOLE_STATE_IDLE; - if( c == 'K') - { - sdEraseEOL(); - } - else if( c == 'D' ) - { - sdCursorBack( sParam1 ); - } - else if( c == 'C' ) - { - sdCursorForward( sParam1 ); - } - else if( (c == 'J') && (sParam1 == 2) ) - { - sdClearScreen(); - } - } - break; - } - return 0; -} - -/* Needed cuz _getch() does not echo. */ -int sdTerminalEcho( char c ) -{ - sdConsoleEmit((char)(c)); - return 0; -} - -int sdTerminalIn( void ) -{ - return _getch(); -} - -int sdQueryTerminal( void ) -{ - return _kbhit(); -} - -int sdTerminalFlush( void ) -{ -#ifdef PF_NO_FILEIO - return -1; -#else - return fflush(PF_STDOUT); -#endif -} - -void sdTerminalInit( void ) -{ - DWORD mode = 0; - sConsoleHandle = GetStdHandle( STD_OUTPUT_HANDLE ); - if( GetConsoleMode( sConsoleHandle, &mode ) ) - { - /*printf("GetConsoleMode() mode is 0x%08X\n", mode );*/ - sIsConsoleValid = TRUE; - } - else - { - /*printf("GetConsoleMode() failed\n", mode );*/ - sIsConsoleValid = FALSE; - } -} - -void sdTerminalTerm( void ) -{ -} -#endif +/* $Id$ */ +/*************************************************************** +** I/O subsystem for PForth for WIN32 systems. +** +** Use Windows Console so we can add the ANSI console commands needed to support HISTORY +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#include "../pf_all.h" + +#if defined(WIN32) || defined(__NT__) + +#include + +#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 + +} ConsoleState; + +static int sConsoleState = SDCONSOLE_STATE_IDLE; +static int sParam1 = 0; +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.*/ + WCHAR wc = (WCHAR) c; + DWORD count; + if( sIsConsoleValid ) + { + WriteConsoleW(sConsoleHandle, &wc, 1, &count, NULL ); + } + else + { + /* 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 ) ) + { + COORD XY; + int numNeeded; + DWORD count; + XY.X = 0; + 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 ) ) + { + COORD savedXY; + int numNeeded; + DWORD count; + 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 ) ) + { + COORD XY; + XY.X = sScreenInfo.dwCursorPosition.X; + XY.Y = sScreenInfo.dwCursorPosition.Y; + XY.X -= dx; + if( XY.X < 0 ) XY.X = 0; + SetConsoleCursorPosition( sConsoleHandle, XY ); + } +} +/******************************************************************/ +static void sdCursorForward( int dx ) +{ + if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) ) + { + COORD XY; + int width = sScreenInfo.dwSize.X; + XY.X = sScreenInfo.dwCursorPosition.X; + XY.Y = sScreenInfo.dwCursorPosition.Y; + XY.X += dx; + 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 + * control functions. + */ +int sdTerminalOut( char c ) +{ + switch( sConsoleState ) + { + case SDCONSOLE_STATE_IDLE: + switch( c ) + { + case ASCII_ESCAPE: + sConsoleState = SDCONSOLE_STATE_GOT_ESCAPE; + break; + default: + sdConsoleEmit( c ); + } + break; + + case SDCONSOLE_STATE_GOT_ESCAPE: + switch( c ) + { + case '[': + sConsoleState = SDCONSOLE_STATE_GOT_BRACKET; + sParam1 = 0; + break; + default: + sConsoleState = SDCONSOLE_STATE_IDLE; + sdConsoleEmit( c ); + } + break; + + case SDCONSOLE_STATE_GOT_BRACKET: + if( (c >= '0') && (c <= '9') ) + { + sParam1 = (sParam1 * 10) + (c - '0'); + } + else + { + sConsoleState = SDCONSOLE_STATE_IDLE; + if( c == 'K') + { + sdEraseEOL(); + } + else if( c == 'D' ) + { + sdCursorBack( sParam1 ); + } + else if( c == 'C' ) + { + sdCursorForward( sParam1 ); + } + else if( (c == 'J') && (sParam1 == 2) ) + { + sdClearScreen(); + } + } + break; + } + return 0; +} + +/* Needed cuz _getch() does not echo. */ +int sdTerminalEcho( char c ) +{ + sdConsoleEmit((char)(c)); + return 0; +} + +int sdTerminalIn( void ) +{ + return _getch(); +} + +int sdQueryTerminal( void ) +{ + return _kbhit(); +} + +int sdTerminalFlush( void ) +{ +#ifdef PF_NO_FILEIO + return -1; +#else + return fflush(PF_STDOUT); +#endif +} + +void sdTerminalInit( void ) +{ + DWORD mode = 0; + sConsoleHandle = GetStdHandle( STD_OUTPUT_HANDLE ); + if( GetConsoleMode( sConsoleHandle, &mode ) ) + { + /*printf("GetConsoleMode() mode is 0x%08X\n", mode );*/ + sIsConsoleValid = TRUE; + } + else + { + /*printf("GetConsoleMode() failed\n", mode );*/ + sIsConsoleValid = FALSE; + } +} + +void sdTerminalTerm( void ) +{ +} +#endif