Sample crossbuild makefile
[pforth] / csrc / win32_console / pf_io_win32_console.c
CommitLineData
bb6b2dcd 1/* $Id$ */\r
2/***************************************************************\r
3** I/O subsystem for PForth for WIN32 systems.\r
4**\r
5** Use Windows Console so we can add the ANSI console commands needed to support HISTORY\r
6**\r
7** Author: Phil Burk\r
8** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom\r
9**\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
18**\r
19***************************************************************/\r
20\r
21#include "../pf_all.h"\r
22\r
e2531e83 23#if defined(WIN32) || defined(__NT__)\r
bb6b2dcd 24\r
25#include <windows.h>\r
26\r
27#define ASCII_ESCAPE (0x1B)\r
28\r
29static HANDLE sConsoleHandle = INVALID_HANDLE_VALUE;\r
30static int sIsConsoleValid = FALSE;\r
31\r
32typedef enum ConsoleState_e\r
33{\r
34 SDCONSOLE_STATE_IDLE = 0,\r
35 SDCONSOLE_STATE_GOT_ESCAPE,\r
25962507 36 SDCONSOLE_STATE_GOT_BRACKET\r
bb6b2dcd 37\r
38} ConsoleState;\r
39\r
40static int sConsoleState = SDCONSOLE_STATE_IDLE;\r
41static int sParam1 = 0;\r
42static CONSOLE_SCREEN_BUFFER_INFO sScreenInfo;\r
43\r
44/******************************************************************/\r
45static void sdConsoleEmit( char c )\r
46{\r
25962507
HV
47 /* Write a WCHAR in case we have compiled with Unicode support.\r
48 * Otherwise we will see '?' printed.*/\r
bb6b2dcd 49 WCHAR wc = (WCHAR) c;\r
50 DWORD count;\r
51 if( sIsConsoleValid )\r
52 {\r
53 WriteConsoleW(sConsoleHandle, &wc, 1, &count, NULL );\r
54 }\r
55 else\r
56 {\r
25962507 57 /* This will get called if we are redirecting to a file.*/\r
bb6b2dcd 58 WriteFile(sConsoleHandle, &c, 1, &count, NULL );\r
59 }\r
60}\r
61\r
62/******************************************************************/\r
63static void sdClearScreen( void )\r
64{\r
65 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )\r
66 {\r
67 COORD XY;\r
68 int numNeeded;\r
69 DWORD count;\r
70 XY.X = 0;\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
76 }\r
77}\r
78\r
79/******************************************************************/\r
80static void sdEraseEOL( void )\r
81{\r
82 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )\r
83 {\r
84 COORD savedXY;\r
85 int numNeeded;\r
86 DWORD count;\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
92 }\r
93}\r
94\r
95/******************************************************************/\r
96static void sdCursorBack( int dx )\r
97{\r
98 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )\r
99 {\r
100 COORD XY;\r
101 XY.X = sScreenInfo.dwCursorPosition.X;\r
102 XY.Y = sScreenInfo.dwCursorPosition.Y;\r
103 XY.X -= dx;\r
104 if( XY.X < 0 ) XY.X = 0;\r
105 SetConsoleCursorPosition( sConsoleHandle, XY );\r
106 }\r
107}\r
108/******************************************************************/\r
109static void sdCursorForward( int dx )\r
110{\r
111 if( GetConsoleScreenBufferInfo( sConsoleHandle, &sScreenInfo ) )\r
112 {\r
113 COORD XY;\r
114 int width = sScreenInfo.dwSize.X;\r
115 XY.X = sScreenInfo.dwCursorPosition.X;\r
116 XY.Y = sScreenInfo.dwCursorPosition.Y;\r
117 XY.X += dx;\r
118 if( XY.X > width ) XY.X = width;\r
119 SetConsoleCursorPosition( sConsoleHandle, XY );\r
120 }\r
121}\r
122\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
127 */\r
128int sdTerminalOut( char c )\r
129{\r
130 switch( sConsoleState )\r
131 {\r
132 case SDCONSOLE_STATE_IDLE:\r
133 switch( c )\r
134 {\r
135 case ASCII_ESCAPE:\r
136 sConsoleState = SDCONSOLE_STATE_GOT_ESCAPE;\r
137 break;\r
138 default:\r
139 sdConsoleEmit( c );\r
140 }\r
141 break;\r
142\r
143 case SDCONSOLE_STATE_GOT_ESCAPE:\r
144 switch( c )\r
145 {\r
146 case '[':\r
147 sConsoleState = SDCONSOLE_STATE_GOT_BRACKET;\r
148 sParam1 = 0;\r
149 break;\r
150 default:\r
151 sConsoleState = SDCONSOLE_STATE_IDLE;\r
152 sdConsoleEmit( c );\r
153 }\r
154 break;\r
155\r
156 case SDCONSOLE_STATE_GOT_BRACKET:\r
157 if( (c >= '0') && (c <= '9') )\r
158 {\r
159 sParam1 = (sParam1 * 10) + (c - '0');\r
160 }\r
161 else\r
162 {\r
163 sConsoleState = SDCONSOLE_STATE_IDLE;\r
164 if( c == 'K')\r
165 {\r
166 sdEraseEOL();\r
167 }\r
168 else if( c == 'D' )\r
169 {\r
170 sdCursorBack( sParam1 );\r
171 }\r
172 else if( c == 'C' )\r
173 {\r
174 sdCursorForward( sParam1 );\r
175 }\r
176 else if( (c == 'J') && (sParam1 == 2) )\r
177 {\r
178 sdClearScreen();\r
179 }\r
180 }\r
181 break;\r
182 }\r
183 return 0;\r
184}\r
185\r
186/* Needed cuz _getch() does not echo. */\r
187int sdTerminalEcho( char c )\r
188{\r
189 sdConsoleEmit((char)(c));\r
190 return 0;\r
191}\r
192\r
193int sdTerminalIn( void )\r
194{\r
195 return _getch();\r
196}\r
197\r
198int sdQueryTerminal( void )\r
199{\r
200 return _kbhit();\r
201}\r
202\r
203int sdTerminalFlush( void )\r
204{\r
205#ifdef PF_NO_FILEIO\r
206 return -1;\r
207#else\r
208 return fflush(PF_STDOUT);\r
209#endif\r
210}\r
211\r
212void sdTerminalInit( void )\r
213{\r
214 DWORD mode = 0;\r
215 sConsoleHandle = GetStdHandle( STD_OUTPUT_HANDLE );\r
216 if( GetConsoleMode( sConsoleHandle, &mode ) )\r
217 {\r
25962507 218 /*printf("GetConsoleMode() mode is 0x%08X\n", mode );*/\r
bb6b2dcd 219 sIsConsoleValid = TRUE;\r
220 }\r
221 else\r
222 {\r
25962507 223 /*printf("GetConsoleMode() failed\n", mode );*/\r
bb6b2dcd 224 sIsConsoleValid = FALSE;\r
225 }\r
226}\r
227\r
228void sdTerminalTerm( void )\r
229{\r
230}\r
231#endif\r