Sample crossbuild makefile
[debian/pforth] / csrc / win32_console / pf_io_win32_console.c
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
23 #if defined(WIN32) || defined(__NT__)\r
24 \r
25 #include <windows.h>\r
26 \r
27 #define ASCII_ESCAPE  (0x1B)\r
28 \r
29 static HANDLE sConsoleHandle = INVALID_HANDLE_VALUE;\r
30 static int sIsConsoleValid = FALSE;\r
31 \r
32 typedef enum ConsoleState_e\r
33 {\r
34         SDCONSOLE_STATE_IDLE = 0,\r
35         SDCONSOLE_STATE_GOT_ESCAPE,\r
36         SDCONSOLE_STATE_GOT_BRACKET\r
37 \r
38 } ConsoleState;\r
39 \r
40 static int sConsoleState = SDCONSOLE_STATE_IDLE;\r
41 static int sParam1 = 0;\r
42 static CONSOLE_SCREEN_BUFFER_INFO sScreenInfo;\r
43 \r
44 /******************************************************************/\r
45 static void sdConsoleEmit( char c )\r
46 {\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
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
57           /* This will get called if we are redirecting to a file.*/\r
58                 WriteFile(sConsoleHandle, &c, 1, &count, NULL );\r
59         }\r
60 }\r
61 \r
62 /******************************************************************/\r
63 static 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
80 static 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
96 static 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
109 static 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
128 int  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
187 int  sdTerminalEcho( char c )\r
188 {\r
189         sdConsoleEmit((char)(c));\r
190         return 0;\r
191 }\r
192 \r
193 int  sdTerminalIn( void )\r
194 {\r
195         return _getch();\r
196 }\r
197 \r
198 int  sdQueryTerminal( void )\r
199 {\r
200         return _kbhit();\r
201 }\r
202 \r
203 int  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
212 void 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
218           /*printf("GetConsoleMode() mode is 0x%08X\n", mode );*/\r
219                 sIsConsoleValid = TRUE;\r
220         }\r
221         else\r
222         {\r
223           /*printf("GetConsoleMode() failed\n", mode );*/\r
224                 sIsConsoleValid = FALSE;\r
225         }\r
226 }\r
227 \r
228 void sdTerminalTerm( void )\r
229 {\r
230 }\r
231 #endif\r