4130efcac1580e6c50f92c6449a5a26fc279d04a
[reactos.git] / reactos / apps / utils / net / telnet / ansi.cpp
1 /* $Id: ansi.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
2 *
3 * FILE : ansi.cpp
4 * AUTHOR : unknown (sources found on www.telnet.org)
5 * PROJECT : ReactOS Operating System
6 * DESCRIPTION: telnet client for the W32 subsystem
7 * DATE : 2001-01-21
8 * REVISIONS
9 * 2001-02-21 ea Modified to compile under 0.0.16 src tree
10 */
11 #include <winsock.h>
12 #include <windows.h>
13
14 #include "telnet.h"
15
16 // Need to implement a Keymapper.
17 // here are some example key maps
18
19 // vt100 f1 - \eOP
20 // vt100 f2 - \eOQ
21
22 // ansi f5 - \e[17~
23 // f6 - \e[18~
24 // f7 - \e[20~
25 // f10- \e[[V
26
27 enum _ansi_state
28 {
29 as_normal,
30 as_esc,
31 as_esc1
32 };
33
34 //SetConsoleMode
35
36 ///////////////////////////////////////////////////////////////////////////////
37 // SET SCREEN ATTRIBUTE
38 /*
39 ESC [ Ps..Ps m Ps refers to selective parameter. Multiple parameters are
40 separated by the semicolon character (073 octal). The param-
41 eters are executed in order and have the following meaning:
42
43 0 or none All attributes off
44 1 Bold on
45 4 Underscore on
46 5 Blink on
47 7 Reverse video on
48
49 3x set foreground color to x
50 nx set background color to x
51
52 Any other parameters are ignored.
53 */
54 static int sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
55
56 void ansi_set_screen_attribute(char* buffer)
57 {
58 while(*buffer)
59 {
60 switch(*buffer++)
61 {
62 case '0': //Normal
63 sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
64 break;
65 case '1': //Hign Intensity
66 sa |= FOREGROUND_INTENSITY;
67 break;
68 case '4': //Underscore
69 break;
70 case '5': //Blink.
71 sa |= BACKGROUND_INTENSITY;
72 break;
73 case '7':
74 sa = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
75 break;
76 case '8':
77 sa = 0;
78 break;
79 case '3':
80 sa = sa & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY) |
81 (*buffer & 1)?FOREGROUND_RED:0 |
82 (*buffer & 2)?FOREGROUND_GREEN:0 |
83 (*buffer & 4)?FOREGROUND_BLUE:0;
84 if(*buffer)
85 buffer++;
86 break;
87 case '6':
88 sa = sa & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY) |
89 (*buffer & 1)?BACKGROUND_RED:0 |
90 (*buffer & 2)?BACKGROUND_GREEN:0 |
91 (*buffer & 4)?BACKGROUND_BLUE:0;
92 if(*buffer)
93 buffer++;
94 break;
95 }
96 if(*buffer && *buffer == ';')
97 buffer++;
98 }
99 SetConsoleTextAttribute(StandardOutput,sa);
100 }
101
102 ///////////////////////////////////////////////////////////////////////////////
103 // ERASE LINE
104 /*
105 ESC [ 0K Same *default*
106 ESC [ 1K Erase from beginning of line to cursor
107 ESC [ 2K Erase line containing cursor
108 */
109
110 void ansi_erase_line(char* buffer)
111 {
112 int act = 0;
113 while(*buffer)
114 {
115 act = (*buffer++) - '0';
116 }
117
118 CONSOLE_SCREEN_BUFFER_INFO csbi;
119 GetConsoleScreenBufferInfo(StandardOutput,&csbi);
120
121 COORD pos;
122 DWORD n;
123
124 switch(act)
125 {
126 case 0: //erase to end of line
127 pos.X = csbi.dwCursorPosition.X;
128 pos.Y = csbi.dwCursorPosition.Y;
129 n = csbi.dwSize.X - csbi.dwCursorPosition.X;
130 break;
131 case 1: //erase from beginning
132 pos.X = 0;
133 pos.Y = csbi.dwCursorPosition.Y;
134 n = csbi.dwCursorPosition.X;
135 break;
136 case 2: // erase whole line
137 pos.X = 0;
138 pos.Y = csbi.dwCursorPosition.Y;
139 n = csbi.dwSize.X;
140 break;
141 }
142
143 DWORD w;
144 FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w);
145 }
146
147
148 ///////////////////////////////////////////////////////////////////////////////
149 // SET POSITION
150 // ESC [ Pl;PcH Direct cursor addressing, where Pl is line#, Pc is column#
151 // default = (1,1)
152
153 void ansi_set_position(char* buffer)
154 {
155 COORD pos = {0,0};
156
157 // Grab line
158 while(*buffer && *buffer != ';')
159 pos.Y = pos.Y*10 + *buffer++ - '0';
160
161 if(*buffer)
162 buffer++;
163
164 // Grab y
165 while(*buffer && *buffer != ';')
166 pos.X = pos.X*10 + *buffer++ - '0';
167
168 (pos.X)?pos.X--:0;
169 (pos.Y)?pos.Y--:0;
170
171 SetConsoleCursorPosition(StandardOutput,pos);
172
173 }
174
175 ///////////////////////////////////////////////////////////////////////////////
176 // ERASE SCREEN
177 /*
178 ESC [ 0J Same *default*
179 ESC [ 2J Erase entire screen
180 */
181
182 void ansi_erase_screen(char* buffer)
183 {
184 int act = 0;
185 while(*buffer)
186 {
187 act = (*buffer++) - '0';
188 }
189
190 CONSOLE_SCREEN_BUFFER_INFO csbi;
191 GetConsoleScreenBufferInfo(StandardOutput,&csbi);
192
193 COORD pos;
194 DWORD n;
195
196 switch(act)
197 {
198 case 0:
199 pos.X = csbi.dwCursorPosition.X;
200 pos.Y = csbi.dwCursorPosition.Y;
201 n = csbi.dwSize.X*csbi.dwSize.Y;
202 break;
203 case 2:
204 pos.X = 0;
205 pos.Y = 0;
206 n = csbi.dwSize.X*csbi.dwSize.Y;
207 break;
208 }
209
210 DWORD w;
211 FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w);
212 SetConsoleCursorPosition(StandardOutput,pos);
213 }
214
215 ///////////////////////////////////////////////////////////////////////////////
216 // MOVE UP
217 // ESC [ Pn A Cursor up Pn lines (Pn default=1)
218
219 void ansi_move_up(char* buffer)
220 {
221 int cnt = *buffer?0:1;
222 while(*buffer)
223 {
224 cnt = cnt*10 + (*buffer++) - '0';
225 }
226
227 COORD pos;
228
229 CONSOLE_SCREEN_BUFFER_INFO csbi;
230 GetConsoleScreenBufferInfo(StandardOutput,&csbi);
231
232 pos.X = csbi.dwCursorPosition.X;
233 pos.Y = ((csbi.dwCursorPosition.Y-cnt)>=0)?(csbi.dwCursorPosition.Y-cnt):0;
234
235 SetConsoleCursorPosition(StandardOutput,pos);
236 }
237
238 ///////////////////////////////////////////////////////////////////////////////
239 char codebuf[256];
240 unsigned char codeptr;
241
242 #define NUM_CODEC 6
243
244 typedef void (*LPCODEPROC)(char*);
245
246 struct
247 {
248 unsigned char cmd;
249 LPCODEPROC proc;
250 } codec[NUM_CODEC] = {
251 {'m',ansi_set_screen_attribute},
252 {'H',ansi_set_position},
253 {'K',ansi_erase_line},
254 {'J',ansi_erase_screen},
255 {'A',ansi_move_up},
256 {0,0}
257 };
258
259 void ansi(SOCKET server,unsigned char data)
260 {
261 static _ansi_state state = as_normal;
262 DWORD z;
263 switch( state)
264 {
265 case as_normal:
266 switch(data)
267 {
268 case 0: //eat null codes.
269 break;
270 case 27: //ANSI esc.
271 state = as_esc;
272 break;
273 default: //Send all else to the console.
274 WriteConsole(StandardOutput,&data,1,&z,NULL);
275 break;
276 }
277 break;
278 case as_esc:
279 state = as_esc1;
280 codeptr=0;
281 codebuf[codeptr] = 0;
282 break;
283 case as_esc1:
284 if(data > 64)
285 {
286 int i = 0;
287 codebuf[codeptr] = 0;
288 for(i=0; codec[i].cmd && codec[i].cmd != data; i++);
289 if(codec[i].proc)
290 codec[i].proc(codebuf);
291 #ifdef _DEBUG
292 else
293 {
294 char buf[256];
295 wsprintf(buf,"Unknown Ansi code:'%c' (%s)\n",data,codebuf);
296 OutputDebugString(buf);
297 }
298 #endif
299 state = as_normal;
300 }
301 else
302 codebuf[codeptr++] = data;
303 break;
304 }
305 }
306
307 /* EOF */