-rw-r--r-- | VT100.cpp | 1478 |
1 files changed, 1478 insertions, 0 deletions
diff --git a/VT100.cpp b/VT100.cpp new file mode 100644 index 0000000..ea626a9 --- a/dev/null +++ b/VT100.cpp | |||
@@ -0,0 +1,1478 @@ | |||
1 | class CVT100 : public CTTY{ | ||
2 | static DWORDdummyWritten; | ||
3 | static CHARm_ctGraphs[256]; | ||
4 | CHARsfCrap[256]; | ||
5 | public: | ||
6 | BYTE m_Sequence[1024]; // Buffered ESC[ sequence | ||
7 | UINT m_Sequenced; | ||
8 | CHAR_INFO m_Buffer[132*2];// Deferred output buffer | ||
9 | UINT m_Buffered; | ||
10 | UINT m_Parms[16]; // ESC[ Parameters | ||
11 | UINT m_nParms; | ||
12 | UINT m_ParmPtrs[16]; | ||
13 | INT m_TABs[132]; // Tabulations | ||
14 | CHAR* m_CT; // Codes table for various charsets | ||
15 | CHAR* m_ctG0; | ||
16 | CHAR* m_ctG1; | ||
17 | int m_ctG; | ||
18 | CHAR* m_savedCTG0; // Saved for ESC#7/ESC#8 | ||
19 | CHAR* m_savedCTG1; | ||
20 | CHAR* m_savedCT; | ||
21 | COORD m_savedCP; | ||
22 | int m_savedCTG; | ||
23 | int m_savedAttrs; | ||
24 | BOOL m_bRight; // At right margin | ||
25 | BOOL m_bKPN; // Keypad is in numeric mode | ||
26 | BOOL m_bCKM; // Cursor Keys Mode (DECCKM) | ||
27 | BOOL m_bAWM; // Autowrap mode | ||
28 | BOOL m_bOM; // Origin Mode | ||
29 | BOOL m_bLNM; // New Line Mode | ||
30 | BOOL m_bIM; // Insert Mode | ||
31 | BOOL m_bVT52; // VT52 Mode (as opposed to ANSI which is default) | ||
32 | BOOL m_bTR; // Total Reverse of the whole screen background/foreground | ||
33 | BOOL m_bEBFailure; // ESC[ Failure flag | ||
34 | int m_vt52Y1, m_vt52Y2; // ESCY in VT52 mode parameters | ||
35 | |||
36 | CHAR_INFO* m_tmpScrollBuffer;// Buffer used for temporary storage when doing scrolling. | ||
37 | UINT m_tmpScrollBufferSize; | ||
38 | |||
39 | void AllocateTmpBuffer() { | ||
40 | UINT newSize = m_CSBI.dwSize.X*m_CSBI.dwSize.Y; | ||
41 | if(newSize>m_tmpScrollBufferSize || !m_tmpScrollBuffer){ | ||
42 | if(m_tmpScrollBuffer) delete m_tmpScrollBuffer; | ||
43 | VERIFY(m_tmpScrollBuffer=new CHAR_INFO[newSize]); | ||
44 | m_tmpScrollBufferSize=newSize; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | CVT100() : m_tmpScrollBuffer(NULL) { } | ||
49 | virtual ~CVT100() { if(m_tmpScrollBuffer) delete m_tmpScrollBuffer; } | ||
50 | |||
51 | enum _state { | ||
52 | stateNone,stateESeq,stateEBSeq, stateEPOSeq, stateEPCSeq, stateEPSSeq, | ||
53 | stateEY52Seq1, stateEY52Seq2 | ||
54 | }state; | ||
55 | |||
56 | enum _attrs { | ||
57 | attrNone = 0, attrBold = 1, attrUnderline = 2, attrBlink = 4, attrReverse = 8 | ||
58 | }; | ||
59 | int attrs; // Screen attributes from _attrs enumeration | ||
60 | int sr0,sr1; // Scroll Region | ||
61 | int m_Attrs; // Screen attributes in console terms | ||
62 | int m_bgAttr; // Background color | ||
63 | int m_fgAttr; // Foreground color | ||
64 | |||
65 | CONSOLE_SCREEN_BUFFER_INFO | ||
66 | m_CSBI; // Tracking of SB information | ||
67 | |||
68 | void FillScreen(int x,int y,int n,TCHAR c,WORD a) { | ||
69 | COORD tmp = {x,y}; | ||
70 | VERIFY(FillConsoleOutputCharacter(hConsoleOutput,c,n,tmp,&dummyWritten)); | ||
71 | VERIFY(FillConsoleOutputAttribute(hConsoleOutput,a,n,tmp,&dummyWritten)); | ||
72 | } | ||
73 | void HScroll(int x,int y,int n,int x1=-1) { | ||
74 | if(!n) | ||
75 | return; | ||
76 | if(x1<0) | ||
77 | x1=m_CSBI.dwSize.X-1; | ||
78 | else | ||
79 | x1=max(x,min(x1,m_CSBI.dwSize.X-1)); | ||
80 | static | ||
81 | COORD zero = {0,0}; | ||
82 | if(n>0){ | ||
83 | int r = max(0,min(n,x1-x+1)); | ||
84 | if(!r) | ||
85 | return; | ||
86 | if((x+r)<=x1){ | ||
87 | ASSERT(m_tmpScrollBuffer); | ||
88 | SMALL_RECT sr = { x,y,x1-r,y }; | ||
89 | VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
90 | sr.Left+=r; | ||
91 | sr.Right+=r; | ||
92 | VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
93 | } | ||
94 | FillScreen(x,y,r,' ',m_Attrs); | ||
95 | }else{ | ||
96 | int r = max(0,min(-n,x1-x+1)); | ||
97 | if(!r) | ||
98 | return; | ||
99 | if((x+r)<=x1){ | ||
100 | ASSERT(m_tmpScrollBuffer); | ||
101 | SMALL_RECT sr = {x+r,y,x1,y }; | ||
102 | VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
103 | sr.Left-=r; | ||
104 | sr.Right-=r; | ||
105 | VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
106 | } | ||
107 | FillScreen(x1-r+1,y,r,' ',m_Attrs); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void VScroll(int y,int n,int y1=-1) { | ||
112 | static | ||
113 | COORD zero = {0,0}; | ||
114 | if(!n) | ||
115 | return; | ||
116 | if(y1<0) | ||
117 | y1 = m_CSBI.dwSize.Y; | ||
118 | else | ||
119 | y1 = max(y,min(y1,m_CSBI.dwSize.Y-1)); | ||
120 | if(n>0){ | ||
121 | int r = max(0,min(n,y1-y+1)); | ||
122 | if(!r) | ||
123 | return; | ||
124 | if((y+r)<=y1){ | ||
125 | ASSERT(m_tmpScrollBuffer); | ||
126 | SMALL_RECT sr = { 0,y,m_CSBI.dwSize.X-1,y1-r }; | ||
127 | VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
128 | sr.Top+=r; | ||
129 | sr.Bottom+=r; | ||
130 | VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
131 | } | ||
132 | FillScreen(0,y,r*m_CSBI.dwSize.X,' ',m_Attrs); | ||
133 | }else{ | ||
134 | int r = max(0,min(-n,y1-y+1)); | ||
135 | if(!r) | ||
136 | return; | ||
137 | if((y+r)<=y1){ | ||
138 | ASSERT(m_tmpScrollBuffer); | ||
139 | SMALL_RECT sr = {0,y+r,m_CSBI.dwSize.X-1,y1 }; | ||
140 | VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
141 | sr.Top-=r; | ||
142 | sr.Bottom-=r; | ||
143 | VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr)); | ||
144 | } | ||
145 | FillScreen(0,y1-r+1,r*m_CSBI.dwSize.X,' ',m_Attrs); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | BOOL DoNAWS() { | ||
150 | VERIFY(GetConsoleScreenBufferInfo(hConsoleOutput,&m_CSBI)); | ||
151 | AllocateTmpBuffer(); | ||
152 | VERIFY(TerminalUpdateTitle()); | ||
153 | if(Options[toNAWS].m_StateU==TOption::stateYes) | ||
154 | SendNAWS(); | ||
155 | else | ||
156 | AskWill(toNAWS); | ||
157 | return TRUE; | ||
158 | } | ||
159 | |||
160 | BOOL ResizeWindow(COORD ns) { | ||
161 | if(m_CSBI.dwCursorPosition.X>=ns.X) | ||
162 | m_CSBI.dwCursorPosition.X=0; | ||
163 | if(m_CSBI.dwCursorPosition.Y>=ns.Y){ | ||
164 | VScroll(0,-(m_CSBI.dwCursorPosition.Y-ns.Y+1),m_CSBI.dwCursorPosition.Y); | ||
165 | m_CSBI.dwCursorPosition.Y=ns.Y-1; | ||
166 | } | ||
167 | if(!SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition)) | ||
168 | return FALSE; | ||
169 | if(ns.X<m_CSBI.dwSize.X || ns.Y<m_CSBI.dwSize.Y){ | ||
170 | SMALL_RECT wi = { 0,0,min(ns.X-1,m_CSBI.dwMaximumWindowSize.X-1), | ||
171 | min(ns.Y-1,m_CSBI.dwMaximumWindowSize.Y-1) | ||
172 | }; | ||
173 | if(!SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi)) | ||
174 | return FALSE; | ||
175 | } | ||
176 | if(!SetConsoleScreenBufferSize(hConsoleOutput,ns)) | ||
177 | TRACE2("Failed to set buffer size to %dx%d\n",ns.X,ns.Y); | ||
178 | else{ | ||
179 | DoNAWS(); | ||
180 | if(sr0>=m_CSBI.dwSize.Y){ | ||
181 | sr0=0; sr1=m_CSBI.dwSize.Y-1; | ||
182 | }else if(sr1>=m_CSBI.dwSize.Y){ | ||
183 | sr1=m_CSBI.dwSize.Y-1; | ||
184 | if(sr0>=sr1) | ||
185 | sr0=0; | ||
186 | } | ||
187 | } | ||
188 | return TRUE; | ||
189 | } | ||
190 | |||
191 | WORD ReverseAttribute(WORD a) { | ||
192 | WORD rv = 0; | ||
193 | if(a&FOREGROUND_RED) | ||
194 | rv|=BACKGROUND_RED; | ||
195 | if(a&FOREGROUND_GREEN) | ||
196 | rv|=BACKGROUND_GREEN; | ||
197 | if(a&FOREGROUND_BLUE) | ||
198 | rv|=BACKGROUND_BLUE; | ||
199 | if(a&FOREGROUND_INTENSITY) | ||
200 | rv|=BACKGROUND_INTENSITY; | ||
201 | if(a&BACKGROUND_RED) | ||
202 | rv|=FOREGROUND_RED; | ||
203 | if(a&BACKGROUND_GREEN) | ||
204 | rv|=FOREGROUND_GREEN; | ||
205 | if(a&BACKGROUND_BLUE) | ||
206 | rv|=FOREGROUND_BLUE; | ||
207 | if(a&BACKGROUND_INTENSITY) | ||
208 | rv|=FOREGROUND_INTENSITY; | ||
209 | return rv; | ||
210 | } | ||
211 | |||
212 | void ReverseScreen() { | ||
213 | static | ||
214 | COORD zero = {0,0}; | ||
215 | SMALL_RECT whole = {0,0,m_CSBI.dwSize.X-1,m_CSBI.dwSize.Y-1}; | ||
216 | ASSERT(m_tmpScrollBuffer); | ||
217 | VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&whole)); | ||
218 | for(int tmp=0;tmp<(m_CSBI.dwSize.X*m_CSBI.dwSize.Y);tmp++) | ||
219 | m_tmpScrollBuffer[tmp].Attributes = ReverseAttribute(m_tmpScrollBuffer[tmp].Attributes); | ||
220 | VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&whole)); | ||
221 | } | ||
222 | |||
223 | BOOL SetAttrs() { | ||
224 | WORD a = (attrs&attrReverse)?BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE: | ||
225 | FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; | ||
226 | if(m_fgAttr>=0){ | ||
227 | a&=~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); | ||
228 | a|=m_fgAttr|FOREGROUND_INTENSITY; | ||
229 | } | ||
230 | if(m_bgAttr>=0){ | ||
231 | a&=~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE); | ||
232 | a|=m_bgAttr; | ||
233 | } | ||
234 | if(attrs&attrBold) | ||
235 | a|=FOREGROUND_INTENSITY; | ||
236 | if((attrs&attrUnderline) && (m_fgAttr<0)){ | ||
237 | if(attrs&attrReverse)// Is it right way to underline? - we make foreground blue. | ||
238 | a|=FOREGROUND_BLUE; | ||
239 | else | ||
240 | a&=~(FOREGROUND_RED|FOREGROUND_GREEN); | ||
241 | } | ||
242 | if(attrs&attrBlink) | ||
243 | a|=BACKGROUND_INTENSITY; | ||
244 | if(m_bTR) | ||
245 | m_Attrs=ReverseAttribute(a); | ||
246 | else | ||
247 | m_Attrs = a; | ||
248 | return TRUE; | ||
249 | } | ||
250 | |||
251 | virtual BOOL Input(UINT c) { | ||
252 | VERIFY(SendLiteral(c)); | ||
253 | if(c=='\r' && m_bLNM) | ||
254 | VERIFY(SendLiteral('\n')); | ||
255 | if( | ||
256 | ( | ||
257 | Options[toEcho].m_StateU==TOption::stateYes | ||
258 | || Options[toEcho].m_StateU==TOption::stateNone | ||
259 | ) && ( | ||
260 | Options[toEcho].m_StateH!=TOption::stateYes | ||
261 | || Options[toEcho].m_StateH==TOption::stateNone | ||
262 | ) | ||
263 | ){ | ||
264 | PreOutput(); | ||
265 | Output(c); | ||
266 | if(c=='\r' && m_bLNM) | ||
267 | Output('\n'); | ||
268 | PostOutput(); | ||
269 | } | ||
270 | return TRUE; | ||
271 | } | ||
272 | virtual BOOL VInput(WORD vk,DWORD cks) { | ||
273 | #define AROKEY(c,n)( \ | ||
274 | m_bVT52 \ | ||
275 | ? "\33" c \ | ||
276 | :( \ | ||
277 | (cks&ENHANCED_KEY) \ | ||
278 | ? (m_bCKM?"\33O" c:"\33[" c) \ | ||
279 | : (m_bKPN \ | ||
280 | ?"\33O" n \ | ||
281 | :(m_bCKM?"\33O" c:"\33[" c) \ | ||
282 | ) \ | ||
283 | ) \ | ||
284 | ) | ||
285 | #define FUNKEY(c,s) ( \ | ||
286 | (cks&SHIFT_PRESSED) \ | ||
287 | ?( \ | ||
288 | m_bVT52 \ | ||
289 | ? NULL \ | ||
290 | : "\33" s \ | ||
291 | ) \ | ||
292 | :( \ | ||
293 | m_bVT52 \ | ||
294 | ? "\33" c \ | ||
295 | : "\33O" c \ | ||
296 | ) \ | ||
297 | ) | ||
298 | if(cks&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)){ | ||
299 | COORD ns = {m_CSBI.dwSize.X,m_CSBI.dwSize.Y}; | ||
300 | switch(vk){ | ||
301 | case VK_UP: | ||
302 | if(ns.Y<2) | ||
303 | return TRUE; | ||
304 | ns.Y--; | ||
305 | break; | ||
306 | case VK_DOWN: | ||
307 | ns.Y++; | ||
308 | break; | ||
309 | case VK_LEFT: | ||
310 | if(ns.X<2) | ||
311 | return TRUE; | ||
312 | ns.X--; | ||
313 | break; | ||
314 | case VK_RIGHT: | ||
315 | ns.X++; | ||
316 | break; | ||
317 | default: | ||
318 | return TRUE; | ||
319 | } | ||
320 | ResizeWindow(ns); | ||
321 | return TRUE; | ||
322 | } | ||
323 | switch(vk){ | ||
324 | case VK_F1: return VIn(FUNKEY("P","[23~")); | ||
325 | case VK_F2: return VIn(FUNKEY("Q","[24~")); | ||
326 | case VK_F3: return VIn(FUNKEY("R","[25~")); | ||
327 | case VK_F4: return VIn(FUNKEY("S","[26~")); | ||
328 | case VK_F5: return VIn(FUNKEY("t","[28~")); | ||
329 | case VK_F6: return VIn(FUNKEY("u","[29~")); | ||
330 | case VK_F7: return VIn(FUNKEY("v","[31~")); | ||
331 | case VK_F8: return VIn(FUNKEY("l","[32~")); | ||
332 | case VK_F9: return VIn(FUNKEY("w","[33~")); | ||
333 | case VK_F10:return VIn(FUNKEY("x","[34~")); // terminfo says kf10 "y" | ||
334 | case VK_F11:return VIn("\33[23~"); | ||
335 | case VK_F12:return VIn("\33[24~"); | ||
336 | case VK_UP: | ||
337 | case VK_NUMPAD8:return VIn(AROKEY("A","x")); | ||
338 | case VK_DOWN: | ||
339 | case VK_NUMPAD2:return VIn(AROKEY("B","r")); | ||
340 | case VK_LEFT: | ||
341 | case VK_NUMPAD4:return VIn(AROKEY("D","t")); | ||
342 | case VK_RIGHT: | ||
343 | case VK_NUMPAD6:return VIn(AROKEY("C","v")); | ||
344 | case VK_HOME: | ||
345 | case VK_NUMPAD7:return VIn((cks&ENHANCED_KEY) | ||
346 | ? (NULL) | ||
347 | : (m_bKPN?"\33Ow":"\33[1~") | ||
348 | ); | ||
349 | case VK_END: | ||
350 | case VK_NUMPAD1:return VIn((cks&ENHANCED_KEY) | ||
351 | ? (NULL) | ||
352 | : (m_bKPN?"\33Oq":"\33[4~") | ||
353 | ); | ||
354 | case VK_PRIOR: | ||
355 | case VK_NUMPAD9:return VIn((cks&ENHANCED_KEY) | ||
356 | ? (NULL) | ||
357 | : (m_bKPN?"\33Oy":"\33[5~") | ||
358 | ); | ||
359 | case VK_INSERT: | ||
360 | case VK_NUMPAD0:return VIn((cks&ENHANCED_KEY) | ||
361 | ? ("\33Op") | ||
362 | : (m_bKPN?"\33[3~":"\33Op") | ||
363 | ); | ||
364 | case VK_DELETE: | ||
365 | case VK_DECIMAL:return VIn((cks&ENHANCED_KEY) | ||
366 | ? ("\33On") | ||
367 | : (m_bKPN?"\33[3~":"\33On") | ||
368 | ); | ||
369 | } | ||
370 | |||
371 | return FALSE; | ||
372 | #undefFUNKEY | ||
373 | #undefAROKEY | ||
374 | } | ||
375 | BOOL VIn(LPCTSTR str) { | ||
376 | if(!str) | ||
377 | return TRUE; | ||
378 | int l = strlen(str); | ||
379 | VERIFY(SendLiteral(str,l)); | ||
380 | if( | ||
381 | ( | ||
382 | Options[toEcho].m_StateU==TOption::stateYes | ||
383 | || Options[toEcho].m_StateU==TOption::stateNone | ||
384 | ) && ( | ||
385 | Options[toEcho].m_StateH!=TOption::stateYes | ||
386 | || Options[toEcho].m_StateH==TOption::stateNone | ||
387 | ) | ||
388 | ){ | ||
389 | PreOutput(); | ||
390 | for(;l>0;l--) | ||
391 | Output(*(str++)); | ||
392 | PostOutput(); | ||
393 | } | ||
394 | return TRUE; | ||
395 | } | ||
396 | |||
397 | UINT ParseParms() { | ||
398 | ASSERT(m_Sequenced>2); | ||
399 | m_Parms[m_nParms=0]=0; | ||
400 | m_ParmPtrs[m_nParms]=2; | ||
401 | BOOL bWas = FALSE; | ||
402 | for(UINT tmp=2;tmp<(m_Sequenced-1);tmp++){ | ||
403 | if(isdigit(m_Sequence[tmp])){ | ||
404 | m_Parms[m_nParms]*=10; | ||
405 | m_Parms[m_nParms]+=m_Sequence[tmp]-'0'; | ||
406 | bWas = TRUE; | ||
407 | }else{ | ||
408 | if((m_nParms+1)>=(sizeof(m_Parms)/sizeof(*m_Parms))){ | ||
409 | TRACE0("Way too many parameters in ESC[ sequence\n"); | ||
410 | return m_nParms=0; | ||
411 | } | ||
412 | m_Parms[++m_nParms]=0; | ||
413 | m_ParmPtrs[m_nParms]=tmp+1; | ||
414 | bWas = FALSE; | ||
415 | } | ||
416 | } | ||
417 | if(bWas) | ||
418 | m_nParms++; | ||
419 | return m_nParms; | ||
420 | } | ||
421 | |||
422 | void DoIL(int y,int n) { | ||
423 | VScroll(y,n,(y<=sr1)?sr1:-1); | ||
424 | } | ||
425 | void DoDL(int y,int n) { | ||
426 | VScroll(y,-n,(y<=sr1)?sr1:-1); | ||
427 | } | ||
428 | |||
429 | |||
430 | BOOL DoRI() { | ||
431 | m_CSBI.dwCursorPosition.Y--; | ||
432 | if(m_CSBI.dwCursorPosition.Y==(sr0-1)){ | ||
433 | m_CSBI.dwCursorPosition.Y++; | ||
434 | DoIL(m_CSBI.dwCursorPosition.Y,1); | ||
435 | } | ||
436 | return TRUE; | ||
437 | } | ||
438 | BOOL DoIND(BOOL bCR=FALSE) { | ||
439 | m_CSBI.dwCursorPosition.Y++; | ||
440 | if(m_CSBI.dwCursorPosition.Y==sr1+1){ | ||
441 | m_CSBI.dwCursorPosition.Y--; | ||
442 | DoDL(sr0,1); | ||
443 | } | ||
444 | if(bCR) | ||
445 | m_CSBI.dwCursorPosition.X=0; | ||
446 | return TRUE; | ||
447 | } | ||
448 | BOOL DoNEL() { | ||
449 | return DoIND(TRUE); | ||
450 | } | ||
451 | |||
452 | BOOL DoEBS() { | ||
453 | ASSERT(m_Sequenced>2); | ||
454 | ParseParms(); | ||
455 | CHAR c = m_Sequence[m_Sequenced-1]; | ||
456 | switch(c){ | ||
457 | UINT tmp; | ||
458 | case '@':// ICH Insert blank characters (default:1) | ||
459 | // VT102 Feature | ||
460 | if(m_nParms==0 || m_nParms==1){ | ||
461 | Flush(); | ||
462 | HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1); | ||
463 | }else | ||
464 | TRACE0("Invalid number of blanks for ESC[@\n"); | ||
465 | break; | ||
466 | case 'A': | ||
467 | case 'F': // With horizontal homing at the end?? VT102? rxvt? | ||
468 | Flush(); | ||
469 | if(m_nParms==0) | ||
470 | m_CSBI.dwCursorPosition.Y--; | ||
471 | else | ||
472 | m_CSBI.dwCursorPosition.Y-=max(1,m_Parms[0]); | ||
473 | if(m_CSBI.dwCursorPosition.Y<(m_bOM?sr0:0)) | ||
474 | m_CSBI.dwCursorPosition.Y=m_bOM?sr0:0; | ||
475 | if(c=='F') | ||
476 | m_CSBI.dwCursorPosition.X=0; | ||
477 | break; | ||
478 | case 'B': | ||
479 | case 'E': // With horizontal homing at the end?? VT102? rxvt? | ||
480 | Flush(); | ||
481 | if(m_nParms==0) | ||
482 | m_CSBI.dwCursorPosition.Y++; | ||
483 | else | ||
484 | m_CSBI.dwCursorPosition.Y+=max(1,m_Parms[0]); | ||
485 | if(m_CSBI.dwCursorPosition.Y>(m_bOM?sr1:(m_CSBI.dwSize.Y-1))) | ||
486 | m_CSBI.dwCursorPosition.Y=m_bOM?sr1:(m_CSBI.dwSize.Y-1); | ||
487 | if(c=='E') | ||
488 | m_CSBI.dwCursorPosition.X=0; | ||
489 | break; | ||
490 | case 'C': | ||
491 | Flush(); | ||
492 | if(m_nParms==0) | ||
493 | m_CSBI.dwCursorPosition.X++; | ||
494 | else | ||
495 | m_CSBI.dwCursorPosition.X+=max(1,m_Parms[0]); | ||
496 | if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X) | ||
497 | m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1; | ||
498 | break; | ||
499 | case 'D': | ||
500 | Flush(); | ||
501 | if(m_nParms==0) | ||
502 | m_CSBI.dwCursorPosition.X--; | ||
503 | else | ||
504 | m_CSBI.dwCursorPosition.X-=max(1,m_Parms[0]); | ||
505 | if(m_CSBI.dwCursorPosition.X<0) | ||
506 | m_CSBI.dwCursorPosition.X=0; | ||
507 | break; | ||
508 | case 'G':// HPA | ||
509 | if(m_nParms<2){ | ||
510 | Flush(); | ||
511 | m_CSBI.dwCursorPosition.X=min(m_CSBI.dwSize.X-1,m_nParms?max(0,(int)m_Parms[0]-1):0); | ||
512 | }else | ||
513 | TRACE0("Invalid args for ESC[G\n"); | ||
514 | break; | ||
515 | case 'H':// CUP | ||
516 | case 'f':// HVP | ||
517 | { | ||
518 | Flush(); | ||
519 | if(m_nParms==0){ | ||
520 | m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0; | ||
521 | }else if(m_nParms==1){ | ||
522 | m_CSBI.dwCursorPosition.Y = max( | ||
523 | m_bOM?sr0:0, | ||
524 | min( | ||
525 | (m_bOM?sr0:0)+(int)m_Parms[0]-1, | ||
526 | m_CSBI.dwSize.Y-1 | ||
527 | ) | ||
528 | ); | ||
529 | }else if(m_nParms==2){ | ||
530 | m_CSBI.dwCursorPosition.Y = max( | ||
531 | m_bOM?sr0:0, | ||
532 | min( | ||
533 | (m_bOM?sr0:0)+(int)m_Parms[0]-1, | ||
534 | m_CSBI.dwSize.Y-1 | ||
535 | ) | ||
536 | ); | ||
537 | m_CSBI.dwCursorPosition.X = max( | ||
538 | 0, | ||
539 | min( | ||
540 | (int)m_Parms[1]-1, | ||
541 | m_CSBI.dwSize.X-1 | ||
542 | ) | ||
543 | ); | ||
544 | }else{ | ||
545 | TRACE0("Invalid arguments for ESC[H\n"); | ||
546 | break; | ||
547 | } | ||
548 | } | ||
549 | break; | ||
550 | case 'J': | ||
551 | Flush(); | ||
552 | if(m_nParms==0 || m_Parms[0]==0){ | ||
553 | // Erase from cursor to the end of the screen. | ||
554 | FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y, | ||
555 | (m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X) + | ||
556 | (m_CSBI.dwSize.Y-m_CSBI.dwCursorPosition.Y-1)*m_CSBI.dwSize.X, | ||
557 | ' ',m_Attrs); | ||
558 | }else if(m_Parms[0]==1){ | ||
559 | // Erase from the beggining of the screen up to cursor. | ||
560 | FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwCursorPosition.Y+m_CSBI.dwCursorPosition.X+1, | ||
561 | ' ',m_Attrs); | ||
562 | }else if(m_Parms[0]==2){ | ||
563 | // Erase entire screen area | ||
564 | FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs); | ||
565 | }else | ||
566 | TRACE0("Invalid argument for ESC[J\n"); | ||
567 | break; | ||
568 | case 'K': | ||
569 | Flush(); | ||
570 | if(m_nParms==0 || m_Parms[0]==0){ | ||
571 | // From cursor to the end of line | ||
572 | FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y, | ||
573 | m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X,' ',m_Attrs); | ||
574 | }else if(m_Parms[0]==1){ | ||
575 | // From beginning to cursor | ||
576 | FillScreen(0,m_CSBI.dwCursorPosition.Y,m_CSBI.dwCursorPosition.X+1,' ',m_Attrs); | ||
577 | }else if(m_Parms[0]==2){ | ||
578 | // Entire line | ||
579 | FillScreen(0,m_CSBI.dwCursorPosition.Y,m_CSBI.dwSize.X,' ',m_Attrs); | ||
580 | }else | ||
581 | TRACE0("Invalid argument for ESC[K\n"); | ||
582 | break; | ||
583 | case 'L':// IL - Insert Line(s) - VT102 | ||
584 | if(m_nParms<2){ | ||
585 | Flush(); | ||
586 | DoIL(m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1); | ||
587 | }else | ||
588 | TRACE0("Invalid args for ESC[L\n"); | ||
589 | break; | ||
590 | case 'M':// DL - Delete Line(s) - VT102 | ||
591 | if(m_nParms<2){ | ||
592 | Flush(); | ||
593 | DoDL(m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1); | ||
594 | }else | ||
595 | TRACE0("Invalid args for ESC[M\n"); | ||
596 | break; | ||
597 | case 'P':// DCH - Delete Character(s) - VT102 | ||
598 | if(m_nParms<2){ | ||
599 | Flush(); | ||
600 | int dlc = m_nParms?m_Parms[0]:1; | ||
601 | HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,-dlc); | ||
602 | }else | ||
603 | TRACE0("Invalid args for ESC[P\n"); | ||
604 | break; | ||
605 | case 'X':// ECH - Erase characters VT102 | ||
606 | if(m_nParms<2){ | ||
607 | Flush(); | ||
608 | int ec = m_nParms?m_Parms[0]:1; | ||
609 | if((m_CSBI.dwCursorPosition.X+ec)>m_CSBI.dwSize.X) | ||
610 | ec = m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X; | ||
611 | FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,ec,' ',m_Attrs); | ||
612 | }else | ||
613 | TRACE0("Invalid args for ESC[X\n"); | ||
614 | break; | ||
615 | case 'c':// DA - Device attribute | ||
616 | if(m_nParms==0 || m_Parms[0]==0){ | ||
617 | SendLiteral("\33[?1;3c");// This is supposed to mean | ||
618 | // STP & AVO - not sure what | ||
619 | // is STP, though.. | ||
620 | }else | ||
621 | TRACE0("Invalid argument for ESC[c\n"); | ||
622 | break; | ||
623 | case 'd':// VPA | ||
624 | if(m_nParms<2){ | ||
625 | Flush(); | ||
626 | m_CSBI.dwCursorPosition.Y=min(m_CSBI.dwSize.Y-1,m_nParms?max(0,(int)m_Parms[0]-1):0); | ||
627 | }else | ||
628 | TRACE0("Invalid args for ESC[d\n"); | ||
629 | break; | ||
630 | case 'g':// TBC - Tabulation clear | ||
631 | if(m_nParms==0 || m_Parms[0]==0){ | ||
632 | Flush(); | ||
633 | ClearTAB(m_CSBI.dwCursorPosition.X); | ||
634 | }else if(m_Parms[0]==3){ | ||
635 | m_TABs[0]=-1; | ||
636 | }else | ||
637 | TRACE1("Invalid argument for ESC[g - %d\n",m_nParms?m_Parms[0]:-1); | ||
638 | break; | ||
639 | case 'h':// SM - Set Mode | ||
640 | { | ||
641 | BOOL bQ = FALSE; | ||
642 | for(tmp=0;tmp<m_nParms;tmp++){ | ||
643 | switch(m_Parms[tmp]){ | ||
644 | case 0:// This may be caused by '?' only | ||
645 | if(m_Sequence[m_ParmPtrs[tmp]]=='?'){ | ||
646 | bQ=TRUE; | ||
647 | continue; | ||
648 | } | ||
649 | TRACE0("Wrong zeromode in SM/RM command\n"); | ||
650 | break; | ||
651 | case 1: | ||
652 | if(bQ){ | ||
653 | m_bCKM=TRUE; | ||
654 | } | ||
655 | break; | ||
656 | case 2: | ||
657 | m_ctG0=m_ctG1=NULL;// Designate USASCII for G0-G3? | ||
658 | break; | ||
659 | case 3: | ||
660 | if(bQ){ | ||
661 | Flush(); | ||
662 | COORD ns = { 132,m_CSBI.dwSize.Y }; | ||
663 | ResizeWindow(ns); | ||
664 | } | ||
665 | break; | ||
666 | case 4: | ||
667 | if(bQ){ | ||
668 | TRACE0("Set smooth scrolling\n"); | ||
669 | }else{ | ||
670 | Flush(); | ||
671 | TRACE0("Insert Mode\n"); | ||
672 | m_bIM = TRUE; | ||
673 | } | ||
674 | break; | ||
675 | case 5: | ||
676 | if(bQ){ | ||
677 | Flush(); | ||
678 | if(!m_bTR) | ||
679 | ReverseScreen(); | ||
680 | m_bTR = TRUE; | ||
681 | SetAttrs(); | ||
682 | TRACE0("Set black on white\n"); | ||
683 | } | ||
684 | break; | ||
685 | case 6: | ||
686 | if(bQ){ | ||
687 | Flush(); | ||
688 | m_bOM = TRUE; | ||
689 | m_CSBI.dwCursorPosition.X=0; | ||
690 | m_CSBI.dwCursorPosition.Y=sr0;// ??? It was +1 ? | ||
691 | } | ||
692 | break; | ||
693 | case 7: | ||
694 | if(bQ){ | ||
695 | Flush(); | ||
696 | m_bAWM=TRUE; | ||
697 | } | ||
698 | break; | ||
699 | case 8: | ||
700 | if(bQ){ | ||
701 | TRACE0("Autorepeat On\n"); | ||
702 | } | ||
703 | break; | ||
704 | case 20: | ||
705 | if(!bQ){ | ||
706 | // LNM - New Line Mode | ||
707 | m_bLNM = TRUE; | ||
708 | } | ||
709 | break; | ||
710 | case 40: | ||
711 | if(bQ){ | ||
712 | TRACE0("Enable 80/132 switch\n");// ??? | ||
713 | } | ||
714 | break; | ||
715 | case 66: | ||
716 | if(bQ){ | ||
717 | TRACE0("KP - CS\n"); | ||
718 | m_bKPN = FALSE; | ||
719 | } | ||
720 | break; | ||
721 | default: | ||
722 | TRACE1("Unsupported mode in SM command: %d\n",m_Parms[tmp]); | ||
723 | break; | ||
724 | } | ||
725 | bQ=FALSE; | ||
726 | } | ||
727 | } | ||
728 | break; | ||
729 | case 'l':// RM - Reset Mode | ||
730 | { | ||
731 | BOOL bQ = FALSE; | ||
732 | for(tmp=0;tmp<m_nParms;tmp++){ | ||
733 | switch(m_Parms[tmp]){ | ||
734 | case 0:// This may be caused by '?' only | ||
735 | if(m_Sequence[m_ParmPtrs[tmp]]=='?'){ | ||
736 | bQ=TRUE; | ||
737 | continue; | ||
738 | } | ||
739 | TRACE0("Wrong zeromode in SM/RM command\n"); | ||
740 | break; | ||
741 | case 1: | ||
742 | if(bQ){ | ||
743 | m_bCKM=FALSE; | ||
744 | } | ||
745 | break; | ||
746 | case 2: | ||
747 | if(bQ){ | ||
748 | m_bVT52=TRUE; | ||
749 | } | ||
750 | break; | ||
751 | case 3: | ||
752 | if(bQ){ | ||
753 | Flush(); | ||
754 | COORD ns = { 80,m_CSBI.dwSize.Y }; | ||
755 | ResizeWindow(ns); | ||
756 | } | ||
757 | break; | ||
758 | case 4: | ||
759 | if(bQ){ | ||
760 | TRACE0("Set jump scrolling\n"); | ||
761 | }else{ | ||
762 | Flush(); | ||
763 | TRACE0("Overtype Mode\n"); | ||
764 | m_bIM = FALSE; | ||
765 | } | ||
766 | break; | ||
767 | case 5: | ||
768 | if(bQ){ | ||
769 | Flush(); | ||
770 | if(m_bTR) | ||
771 | ReverseScreen(); | ||
772 | m_bTR = FALSE; | ||
773 | SetAttrs(); | ||
774 | TRACE0("Set white on black\n"); | ||
775 | } | ||
776 | break; | ||
777 | case 6: | ||
778 | if(bQ){ | ||
779 | Flush(); | ||
780 | m_bOM = FALSE; | ||
781 | m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0; | ||
782 | } | ||
783 | break; | ||
784 | case 7: | ||
785 | if(bQ){ | ||
786 | Flush(); | ||
787 | m_bAWM=FALSE; | ||
788 | } | ||
789 | break; | ||
790 | case 8: | ||
791 | if(bQ){ | ||
792 | TRACE0("Autorepeat Off\n"); | ||
793 | } | ||
794 | break; | ||
795 | case 20: | ||
796 | if(!bQ){ | ||
797 | // LNM - New Line Mode | ||
798 | m_bLNM = FALSE; | ||
799 | } | ||
800 | break; | ||
801 | case 40: | ||
802 | if(bQ){ | ||
803 | TRACE0("Disable 80/132 switch\n");// ??? | ||
804 | } | ||
805 | break; | ||
806 | case 66: | ||
807 | if(bQ){ | ||
808 | TRACE0("KP - Numeric\n"); | ||
809 | m_bKPN = TRUE; | ||
810 | } | ||
811 | break; | ||
812 | default: | ||
813 | TRACE1("Unsupported mode in RM command: %d\n",m_Parms[tmp]); | ||
814 | break; | ||
815 | } | ||
816 | bQ=FALSE; | ||
817 | } | ||
818 | } | ||
819 | break; | ||
820 | case 'm': | ||
821 | if(m_nParms==0){ | ||
822 | attrs=0; | ||
823 | m_fgAttr=m_bgAttr=-1; | ||
824 | }else | ||
825 | for(tmp=0;tmp<m_nParms;tmp++){ | ||
826 | switch(m_Parms[tmp]){ | ||
827 | case 0: | ||
828 | attrs=0; m_fgAttr=m_bgAttr=-1; break; | ||
829 | case 1: | ||
830 | attrs|=attrBold; break; | ||
831 | case 21: | ||
832 | attrs&=~attrBold; break; | ||
833 | case 2: | ||
834 | case 22: | ||
835 | break;// *** LIGHT (as opposed to bold) | ||
836 | case 4: | ||
837 | attrs|=attrUnderline; break; | ||
838 | case 24: | ||
839 | attrs&=~attrUnderline; break; | ||
840 | case 5: | ||
841 | attrs|=attrBlink; break; | ||
842 | case 25: | ||
843 | attrs&=~attrBlink; break; | ||
844 | case 7: | ||
845 | attrs|=attrReverse; break; | ||
846 | case 27: | ||
847 | attrs&=~attrReverse; break; | ||
848 | case 30: | ||
849 | m_fgAttr=0; break; | ||
850 | case 40: | ||
851 | m_bgAttr=0; break; | ||
852 | case 31: | ||
853 | m_fgAttr=FOREGROUND_RED; break; | ||
854 | case 41: | ||
855 | m_bgAttr=BACKGROUND_RED; break; | ||
856 | case 32: | ||
857 | m_fgAttr=FOREGROUND_GREEN; break; | ||
858 | case 42: | ||
859 | m_bgAttr=BACKGROUND_GREEN; break; | ||
860 | case 33: | ||
861 | m_fgAttr=FOREGROUND_GREEN|FOREGROUND_RED; break; | ||
862 | case 43: | ||
863 | m_bgAttr=BACKGROUND_GREEN|BACKGROUND_RED; break; | ||
864 | case 34: | ||
865 | m_fgAttr=FOREGROUND_BLUE; break; | ||
866 | case 44: | ||
867 | m_bgAttr=BACKGROUND_BLUE; break; | ||
868 | case 35: | ||
869 | m_fgAttr=FOREGROUND_RED|FOREGROUND_BLUE; break; | ||
870 | case 45: | ||
871 | m_bgAttr=BACKGROUND_RED|BACKGROUND_BLUE; break; | ||
872 | case 36: | ||
873 | m_fgAttr=FOREGROUND_GREEN|FOREGROUND_BLUE; break; | ||
874 | case 46: | ||
875 | m_bgAttr=BACKGROUND_GREEN|BACKGROUND_BLUE; break; | ||
876 | case 37: | ||
877 | m_fgAttr=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; break; | ||
878 | case 47: | ||
879 | m_bgAttr=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE; break; | ||
880 | case 39: | ||
881 | m_fgAttr=-1; break; | ||
882 | case 49: | ||
883 | m_bgAttr=-1; break; | ||
884 | default: | ||
885 | TRACE1("Invalid attribute for ESC[m sequence - %u\n",m_Parms[tmp]); | ||
886 | break; | ||
887 | } | ||
888 | } | ||
889 | SetAttrs(); | ||
890 | break; | ||
891 | case 'n':// DSR - Device Status Report | ||
892 | if(m_nParms==1){ | ||
893 | switch(m_Parms[0]){ | ||
894 | case 5:// Report Status | ||
895 | SendLiteral("\33[0n"); | ||
896 | break; | ||
897 | case 6:// Report Cursor Position | ||
898 | Flush(); | ||
899 | sprintf(sfCrap,"\33[%d;%dR", | ||
900 | (m_bOM?(m_CSBI.dwCursorPosition.Y-sr0):m_CSBI.dwCursorPosition.Y)+1, | ||
901 | m_CSBI.dwCursorPosition.X+1 | ||
902 | ); | ||
903 | SendLiteral(sfCrap); | ||
904 | break; | ||
905 | } | ||
906 | }else | ||
907 | TRACE0("Invalid DSR request\n"); | ||
908 | break; | ||
909 | case 'r': | ||
910 | Flush(); | ||
911 | if(m_nParms==2){ | ||
912 | sr0=max(0,m_Parms[0]-1); | ||
913 | if(sr0>=m_CSBI.dwSize.Y) | ||
914 | sr0=m_CSBI.dwSize.Y-1; | ||
915 | sr1=max((UINT)sr0,m_Parms[1]-1); | ||
916 | if(sr1>=m_CSBI.dwSize.Y) | ||
917 | sr1=m_CSBI.dwSize.Y-1; | ||
918 | TRACE2("SCROLL{%d,%d}\n",(int)sr0,(int)sr1); | ||
919 | }else{ | ||
920 | sr0=0; sr1 = m_CSBI.dwSize.Y-1; | ||
921 | } | ||
922 | m_CSBI.dwCursorPosition.X=0; | ||
923 | m_CSBI.dwCursorPosition.Y=sr0; | ||
924 | break; | ||
925 | case 'x': // DECREQTPARM- Request Terminal Parameters | ||
926 | // if parameter is zero - we'll send unsolicited reports when we exit SET-UP. | ||
927 | // if not - we won't. Actually, we won't, anyway. | ||
928 | // Actually, first value is not made up according to any standard that I know of | ||
929 | // It's to make vttest happy. | ||
930 | SendLiteral((m_nParms==0 || m_Parms[0]==0)?"\33[2;1;1;112;112;1;0x":"\33[3;1;1;112;112;1;0x"); | ||
931 | break; | ||
932 | case 'y':// Invoke Confidence Test | ||
933 | if(m_nParms==2 && m_Parms[0]==2){ | ||
934 | if(m_Parms[1]==0){ | ||
935 | Flush(); | ||
936 | Init(); | ||
937 | FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs); | ||
938 | m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0; | ||
939 | }else | ||
940 | TRACE1("Terminal is now invoking tests - %d\n",m_Parms[0]); | ||
941 | }else | ||
942 | TRACE0("Invalid args for ESC[y\n"); | ||
943 | break; | ||
944 | default: | ||
945 | TRACE2("ESC[ SEQUENCE ENDING WITH '%c' AND %d PARS ",(CHAR)c,(INT)m_nParms); | ||
946 | for(tmp=0;tmp<m_nParms;tmp++) | ||
947 | TRACE1("[%d]",m_Parms[tmp]); | ||
948 | TRACE0("\n"); | ||
949 | break; | ||
950 | } | ||
951 | m_Sequenced=0; | ||
952 | state=stateNone; | ||
953 | return TRUE; | ||
954 | } | ||
955 | |||
956 | BOOL DoPrintable(CHAR c){ | ||
957 | if(m_Buffered>=(sizeof(m_Buffer)/sizeof(*m_Buffer))) | ||
958 | Flush(); | ||
959 | if(m_CT && m_CT[(BYTE)c]) | ||
960 | c = m_CT[(BYTE)c]; | ||
961 | m_Buffer[m_Buffered].Char.AsciiChar=c; | ||
962 | m_Buffer[m_Buffered].Attributes=m_Attrs; | ||
963 | m_Buffered++; | ||
964 | return TRUE; | ||
965 | } | ||
966 | BOOL Flush() { | ||
967 | for(UINT tmp=0;tmp<m_Buffered;){ | ||
968 | if(m_bRight){ | ||
969 | if(!m_bAWM) | ||
970 | break; | ||
971 | DoNEL(); | ||
972 | m_bRight=FALSE; | ||
973 | continue; | ||
974 | } | ||
975 | UINT chars = min(m_Buffered-tmp,(UINT)m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X); | ||
976 | COORD bs = {chars,1}; | ||
977 | static | ||
978 | COORD bc = {0,0}; | ||
979 | SMALL_RECT wr = {m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y, | ||
980 | m_CSBI.dwSize.X-1,m_CSBI.dwCursorPosition.Y}; | ||
981 | if(m_bIM && ((m_CSBI.dwCursorPosition.X+(int)chars)<m_CSBI.dwSize.X)) | ||
982 | // Scroll to make place in insert mode | ||
983 | HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,chars); | ||
984 | VERIFY(::WriteConsoleOutput(hConsoleOutput,&m_Buffer[tmp],bs,bc,&wr)); | ||
985 | m_CSBI.dwCursorPosition.X+=chars; | ||
986 | tmp+=chars; | ||
987 | if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X){ | ||
988 | ASSERT(m_CSBI.dwCursorPosition.X==m_CSBI.dwSize.X); | ||
989 | m_bRight=TRUE; | ||
990 | m_CSBI.dwCursorPosition.X--; | ||
991 | }else{ | ||
992 | m_bRight=FALSE; | ||
993 | } | ||
994 | } | ||
995 | m_Buffered=0; | ||
996 | //PulseOutput(); | ||
997 | return TRUE; | ||
998 | } | ||
999 | |||
1000 | BOOL ProcessSingleChar(CHAR c) { | ||
1001 | switch(c){ | ||
1002 | case 0: | ||
1003 | break;// Ignore NULLs | ||
1004 | case '\t': | ||
1005 | { | ||
1006 | Flush(); | ||
1007 | for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs)) && m_TABs[tmp]>=0;tmp++){ | ||
1008 | if(m_TABs[tmp]>m_CSBI.dwCursorPosition.X){ | ||
1009 | m_CSBI.dwCursorPosition.X=m_TABs[tmp]; | ||
1010 | break; | ||
1011 | } | ||
1012 | } | ||
1013 | if(tmp==(sizeof(m_TABs)/sizeof(*m_TABs)) || m_TABs[tmp]<0) | ||
1014 | m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1; | ||
1015 | if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X) | ||
1016 | m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1; | ||
1017 | } | ||
1018 | break; | ||
1019 | case '\n':// Handle this manually because of the glitch in windows handling.. | ||
1020 | case '\13':// VT | ||
1021 | case '\14':// FF | ||
1022 | Flush(); | ||
1023 | DoIND(); | ||
1024 | break; | ||
1025 | case '\a':// bell | ||
1026 | Flush(); | ||
1027 | MessageBeep(0xFFFFFFFF); | ||
1028 | break; | ||
1029 | case '\b':// back | ||
1030 | Flush(); | ||
1031 | m_CSBI.dwCursorPosition.X--; | ||
1032 | if(m_CSBI.dwCursorPosition.X<0) | ||
1033 | m_CSBI.dwCursorPosition.X=0; | ||
1034 | break; | ||
1035 | case '\r': | ||
1036 | Flush(); | ||
1037 | if(m_bLNM) | ||
1038 | DoIND(); | ||
1039 | else | ||
1040 | m_CSBI.dwCursorPosition.X=0; | ||
1041 | break; | ||
1042 | case '\16':// SO - Select G1 | ||
1043 | m_CT = m_ctG1; | ||
1044 | m_ctG = 1; | ||
1045 | break; | ||
1046 | case '\17':// SI - Select G0 | ||
1047 | m_CT = m_ctG0; | ||
1048 | m_ctG = 0; | ||
1049 | break; | ||
1050 | case '\5':// ENQ - Transmit ANSWERBACK message | ||
1051 | return VIn( | ||
1052 | "From kintucky to kinecticut,\n" | ||
1053 | "Kinky kinglet kindly rules,\n" | ||
1054 | "Makin' KINs that're most kinetic, but,\n" | ||
1055 | "Please, admit, they're kinda kool!\n\n" | ||
1056 | ); | ||
1057 | default: | ||
1058 | return FALSE; | ||
1059 | } | ||
1060 | return TRUE; | ||
1061 | } | ||
1062 | |||
1063 | |||
1064 | virtual BOOL Output(UINT c) { | ||
1065 | static | ||
1066 | COORDzero = {0,0}; | ||
1067 | switch(state) { | ||
1068 | case stateEY52Seq1: | ||
1069 | m_vt52Y1=c-037-1; | ||
1070 | state=stateEY52Seq2; | ||
1071 | break; | ||
1072 | case stateEY52Seq2: | ||
1073 | m_vt52Y2=c-037-1; | ||
1074 | Flush(); | ||
1075 | m_CSBI.dwCursorPosition.Y = max( | ||
1076 | m_bOM?sr0:0, | ||
1077 | min( | ||
1078 | (m_bOM?sr0:0)+(int)m_vt52Y1, | ||
1079 | m_CSBI.dwSize.Y-1 | ||
1080 | ) | ||
1081 | ); | ||
1082 | m_CSBI.dwCursorPosition.X = max( | ||
1083 | 0, | ||
1084 | min( | ||
1085 | m_vt52Y2, | ||
1086 | m_CSBI.dwSize.X-1 | ||
1087 | ) | ||
1088 | ); | ||
1089 | state=stateNone; | ||
1090 | break; | ||
1091 | case stateEPSSeq:// Pound Sign | ||
1092 | switch(c){ | ||
1093 | case '8':// DECALN - Screen Alignment Display | ||
1094 | Flush(); | ||
1095 | FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,'E',FOREGROUND_RED|FOREGROUND_GREEN| | ||
1096 | FOREGROUND_BLUE); | ||
1097 | break; | ||
1098 | default: | ||
1099 | TRACE1("ESC# %c\n",c); | ||
1100 | break; | ||
1101 | } | ||
1102 | state = stateNone; | ||
1103 | break; | ||
1104 | case stateEPOSeq:// Parenthesis Opening | ||
1105 | switch(c){ | ||
1106 | case 'A': | ||
1107 | case 'B': | ||
1108 | case '1': | ||
1109 | m_ctG0 =NULL; | ||
1110 | break; | ||
1111 | case '0': | ||
1112 | case '2': | ||
1113 | m_ctG0 = m_ctGraphs; | ||
1114 | break; | ||
1115 | default: | ||
1116 | TRACE1("Invalide ESC( %c\n",c); | ||
1117 | break; | ||
1118 | } | ||
1119 | if(m_ctG==0) | ||
1120 | m_CT = m_ctG0; | ||
1121 | state = stateNone; | ||
1122 | break; | ||
1123 | case stateEPCSeq:// Parenthesis Closing | ||
1124 | switch(c){ | ||
1125 | case 'A': | ||
1126 | case 'B': | ||
1127 | case '1': | ||
1128 | m_ctG1 =NULL; | ||
1129 | break; | ||
1130 | case '0': | ||
1131 | case '2': | ||
1132 | m_ctG1 = m_ctGraphs; | ||
1133 | break; | ||
1134 | default: | ||
1135 | TRACE1("Invalide ESC( %c\n",c); | ||
1136 | break; | ||
1137 | } | ||
1138 | if(m_ctG) | ||
1139 | m_CT = m_ctG1; | ||
1140 | state = stateNone; | ||
1141 | break; | ||
1142 | case stateEBSeq:// Bracket | ||
1143 | if(ProcessSingleChar(c)) | ||
1144 | break; | ||
1145 | if(m_Sequenced>=sizeof(m_Sequence)){ | ||
1146 | m_bEBFailure=TRUE; | ||
1147 | m_Sequenced=2; | ||
1148 | } | ||
1149 | m_Sequence[m_Sequenced++]=c; | ||
1150 | if(isalpha(c) || c=='~' || c=='@'){// *** Maybe we should reconsider these critera | ||
1151 | if(m_bEBFailure){ | ||
1152 | m_Sequenced=0; | ||
1153 | state = stateNone; | ||
1154 | }else | ||
1155 | DoEBS(); | ||
1156 | }else if(c==030){ // CAN | ||
1157 | m_Sequenced=0; | ||
1158 | state = stateNone; | ||
1159 | // *** DO WE PUT OUT the checkerboard (error character?) | ||
1160 | } | ||
1161 | break; | ||
1162 | case stateESeq:// Escape | ||
1163 | if(m_bVT52){ | ||
1164 | state=stateNone; | ||
1165 | switch(c){ | ||
1166 | case 'A': | ||
1167 | Flush(); | ||
1168 | if(m_nParms==0) | ||
1169 | m_CSBI.dwCursorPosition.Y--; | ||
1170 | else | ||
1171 | m_CSBI.dwCursorPosition.Y-=max(1,m_Parms[0]); | ||
1172 | if(m_CSBI.dwCursorPosition.Y<(m_bOM?sr0:0)) | ||
1173 | m_CSBI.dwCursorPosition.Y=m_bOM?sr0:0; | ||
1174 | if(c=='F') | ||
1175 | m_CSBI.dwCursorPosition.X=0; | ||
1176 | break; | ||
1177 | case 'B': | ||
1178 | Flush(); | ||
1179 | if(m_nParms==0) | ||
1180 | m_CSBI.dwCursorPosition.Y++; | ||
1181 | else | ||
1182 | m_CSBI.dwCursorPosition.Y+=max(1,m_Parms[0]); | ||
1183 | if(m_CSBI.dwCursorPosition.Y>(m_bOM?sr1:(m_CSBI.dwSize.Y-1))) | ||
1184 | m_CSBI.dwCursorPosition.Y=m_bOM?sr1:(m_CSBI.dwSize.Y-1); | ||
1185 | if(c=='E') | ||
1186 | m_CSBI.dwCursorPosition.X=0; | ||
1187 | break; | ||
1188 | case 'C': | ||
1189 | Flush(); | ||
1190 | if(m_nParms==0) | ||
1191 | m_CSBI.dwCursorPosition.X++; | ||
1192 | else | ||
1193 | m_CSBI.dwCursorPosition.X+=max(1,m_Parms[0]); | ||
1194 | if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X) | ||
1195 | m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1; | ||
1196 | break; | ||
1197 | case 'D': | ||
1198 | Flush(); | ||
1199 | if(m_nParms==0) | ||
1200 | m_CSBI.dwCursorPosition.X--; | ||
1201 | else | ||
1202 | m_CSBI.dwCursorPosition.X-=max(1,m_Parms[0]); | ||
1203 | if(m_CSBI.dwCursorPosition.X<0) | ||
1204 | m_CSBI.dwCursorPosition.X=0; | ||
1205 | break; | ||
1206 | case 'F': | ||
1207 | m_CT=m_ctG1; | ||
1208 | m_ctG=1; | ||
1209 | break; | ||
1210 | case 'G': | ||
1211 | m_CT=m_ctG0; | ||
1212 | m_ctG=0; | ||
1213 | break; | ||
1214 | case 'H': | ||
1215 | Flush(); | ||
1216 | m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0; | ||
1217 | break; | ||
1218 | case 'I': | ||
1219 | Flush(); | ||
1220 | DoRI(); | ||
1221 | break; | ||
1222 | case 'J': | ||
1223 | Flush(); | ||
1224 | // Erase from cursor to the end of the screen. | ||
1225 | FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y, | ||
1226 | (m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X) + | ||
1227 | (m_CSBI.dwSize.Y-m_CSBI.dwCursorPosition.Y-1)*m_CSBI.dwSize.X, | ||
1228 | ' ',m_Attrs); | ||
1229 | break; | ||
1230 | case 'K': | ||
1231 | Flush(); | ||
1232 | FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y, | ||
1233 | m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X,' ',m_Attrs); | ||
1234 | break; | ||
1235 | case 'Y': | ||
1236 | state=stateEY52Seq1; | ||
1237 | break; | ||
1238 | case 'Z': | ||
1239 | VIn("\33/Z"); | ||
1240 | break; | ||
1241 | case '<': | ||
1242 | m_bVT52=FALSE; | ||
1243 | break; | ||
1244 | default: | ||
1245 | TRACE0("Invalid ESC sequence in VT52 mode\n"); | ||
1246 | break; | ||
1247 | } | ||
1248 | }else{ | ||
1249 | switch(c){ | ||
1250 | case '[': | ||
1251 | ASSERT(m_Sequenced==1); | ||
1252 | m_Sequence[m_Sequenced++]=c; | ||
1253 | state = stateEBSeq; | ||
1254 | break; | ||
1255 | case 'H':// Set TAB at cursor | ||
1256 | InsertTAB(m_CSBI.dwCursorPosition.X); | ||
1257 | state = stateNone; | ||
1258 | break; | ||
1259 | case 'M':// Arrow Up and scroll if needed. | ||
1260 | Flush(); | ||
1261 | DoRI(); | ||
1262 | state = stateNone; | ||
1263 | break; | ||
1264 | case 'D':// Arrow Dn and scroll if needed. | ||
1265 | Flush(); | ||
1266 | DoIND(); | ||
1267 | state = stateNone; | ||
1268 | break; | ||
1269 | case 'E':// Next Line - about identical to \r\n | ||
1270 | Flush(); | ||
1271 | DoNEL(); | ||
1272 | state = stateNone; | ||
1273 | break; | ||
1274 | case 'c':// RIS - Reset to Initial State | ||
1275 | { | ||
1276 | Flush(); | ||
1277 | Init(); | ||
1278 | FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs); | ||
1279 | m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0; | ||
1280 | } | ||
1281 | break; | ||
1282 | case '(': | ||
1283 | state = stateEPOSeq; | ||
1284 | break; | ||
1285 | case ')': | ||
1286 | state = stateEPCSeq; | ||
1287 | break; | ||
1288 | case '#': | ||
1289 | state = stateEPSSeq; | ||
1290 | break; | ||
1291 | case '=': // DECKPAM- Keypad sends sequences | ||
1292 | TRACE0("KP - CS\n"); | ||
1293 | m_bKPN = FALSE; | ||
1294 | state = stateNone; | ||
1295 | break; | ||
1296 | case '>': // DECKPNM- Keypad sends numerics | ||
1297 | TRACE0("KP - Numeric\n"); | ||
1298 | m_bKPN = TRUE; | ||
1299 | state = stateNone; | ||
1300 | break; | ||
1301 | case '7':// Save Cursor and charsets | ||
1302 | m_savedCTG0 = m_ctG0; m_savedCTG1 = m_ctG1; m_savedCT = m_CT; | ||
1303 | m_savedCTG=m_ctG; | ||
1304 | memmove(&m_savedCP,&m_CSBI.dwCursorPosition,sizeof(m_savedCP)); | ||
1305 | m_savedAttrs = attrs; | ||
1306 | state = stateNone; | ||
1307 | break; | ||
1308 | case '8':// Restore cursor and charsets | ||
1309 | Flush(); | ||
1310 | m_ctG0 = m_savedCTG0; m_ctG1 = m_savedCTG1; m_CT = m_savedCT; | ||
1311 | m_ctG=m_savedCTG; | ||
1312 | memmove(&m_CSBI.dwCursorPosition,&m_savedCP,sizeof(m_CSBI.dwCursorPosition)); | ||
1313 | state = stateNone; | ||
1314 | attrs = m_savedAttrs; | ||
1315 | SetAttrs(); | ||
1316 | break; | ||
1317 | default: | ||
1318 | TRACE1("ESCNON[ SEQ - '%c'\n",c); | ||
1319 | state = stateNone; | ||
1320 | break; | ||
1321 | } | ||
1322 | } | ||
1323 | break; | ||
1324 | default: | ||
1325 | case stateNone: | ||
1326 | ASSERT(state==stateNone); | ||
1327 | if(isprint(c&0x7F) || (c&0x7F)==0x7F){ | ||
1328 | DoPrintable(c); | ||
1329 | }else{ | ||
1330 | switch(c){ | ||
1331 | case '\33': | ||
1332 | m_Sequenced=0;m_Sequence[m_Sequenced++]=c; | ||
1333 | state = stateESeq; | ||
1334 | break; | ||
1335 | default: | ||
1336 | if(!ProcessSingleChar(c)) | ||
1337 | TRACE1("Unrecognized character 0x%02X\n",(WORD)c); | ||
1338 | break; | ||
1339 | } | ||
1340 | } | ||
1341 | m_bRight=FALSE; | ||
1342 | break; | ||
1343 | } | ||
1344 | return TRUE; | ||
1345 | } | ||
1346 | |||
1347 | virtual BOOL PreOutput() { | ||
1348 | return TRUE; | ||
1349 | } | ||
1350 | virtual BOOL PostOutput() { | ||
1351 | Flush(); | ||
1352 | VERIFY(SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition)); | ||
1353 | return TRUE; | ||
1354 | } | ||
1355 | BOOL PulseOutput() { | ||
1356 | Flush(); | ||
1357 | VERIFY(SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition)); | ||
1358 | return TRUE; | ||
1359 | } | ||
1360 | |||
1361 | virtual BOOL Init() { | ||
1362 | m_Sequenced=0; | ||
1363 | state = stateNone; | ||
1364 | attrs=0; | ||
1365 | DoNAWS(); | ||
1366 | sr0 = 0; sr1 = m_CSBI.dwSize.Y-1; | ||
1367 | m_bRight = FALSE; | ||
1368 | m_Buffered=0; | ||
1369 | m_savedCT = m_CT = NULL; | ||
1370 | m_savedCTG0 = m_ctG0 = NULL; | ||
1371 | m_savedCTG1 = m_ctG1 = m_ctGraphs; | ||
1372 | m_savedCTG = m_ctG; | ||
1373 | m_savedCP.X=m_savedCP.Y=0; | ||
1374 | m_bKPN = TRUE; | ||
1375 | m_bCKM = FALSE; | ||
1376 | m_bAWM = TRUE; | ||
1377 | m_bOM = FALSE; | ||
1378 | m_bLNM = FALSE; | ||
1379 | m_bIM = FALSE; | ||
1380 | m_bVT52 = FALSE; | ||
1381 | m_bTR = FALSE; | ||
1382 | m_bgAttr=-1; | ||
1383 | m_fgAttr=-1; | ||
1384 | SetAttrs(); | ||
1385 | InitCT(); | ||
1386 | InitTAB(); | ||
1387 | SizeWindowToAll(); | ||
1388 | return TRUE; | ||
1389 | } | ||
1390 | |||
1391 | virtual LPCTSTR GetTitle() { | ||
1392 | static | ||
1393 | CHAR consoleTitle[1024]; | ||
1394 | if(TTTermType<0) | ||
1395 | return "WEIRDO"; | ||
1396 | sprintf(consoleTitle,"%s [%dx%d]",TTypes[TTTermType].m_Name,m_CSBI.dwSize.X,m_CSBI.dwSize.Y); | ||
1397 | return consoleTitle; | ||
1398 | } | ||
1399 | |||
1400 | BOOL SizeWindowToAll() { | ||
1401 | SMALL_RECT wi = {0,0, | ||
1402 | min(m_CSBI.dwSize.X-2,m_CSBI.dwMaximumWindowSize.X-1), | ||
1403 | min(m_CSBI.dwSize.Y-1,m_CSBI.dwMaximumWindowSize.Y-1) | ||
1404 | }; | ||
1405 | SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi); | ||
1406 | wi.Right++; | ||
1407 | return SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi); | ||
1408 | } | ||
1409 | |||
1410 | BOOL ClearTAB(INT tab) { | ||
1411 | for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs)) && m_TABs[tmp]>=0;tmp++) | ||
1412 | if(tab==m_TABs[tmp]){ | ||
1413 | memmove(&m_TABs[tmp],&m_TABs[tmp+1],sizeof(m_TABs)-sizeof(*m_TABs)*(tmp+1)); | ||
1414 | m_TABs[(sizeof(m_TABs)/sizeof(*m_TABs))-1]=-1; | ||
1415 | return TRUE; | ||
1416 | } | ||
1417 | return FALSE; | ||
1418 | } | ||
1419 | BOOL InsertTAB(INT tab) { | ||
1420 | for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs));tmp++){ | ||
1421 | if(tab==m_TABs[tmp]) | ||
1422 | return TRUE; | ||
1423 | else if(m_TABs[tmp]>tab || m_TABs[tmp]<0){ | ||
1424 | if(tmp!=((sizeof(m_TABs)/sizeof(*m_TABs))-1)) | ||
1425 | memmove(&m_TABs[tmp+1],&m_TABs[tmp],sizeof(m_TABs)-sizeof(*m_TABs)*(tmp+1)); | ||
1426 | m_TABs[tmp]=tab; | ||
1427 | return TRUE; | ||
1428 | } | ||
1429 | } | ||
1430 | return FALSE; | ||
1431 | } | ||
1432 | void InitTAB() { | ||
1433 | ASSERT(m_CSBI.dwSize.X<=(sizeof(m_TABs)/sizeof(*m_TABs))); | ||
1434 | for(int tmp=0,tab=0;tmp<m_CSBI.dwSize.X;tmp+=8) | ||
1435 | m_TABs[tab++]=tmp; | ||
1436 | m_TABs[tab++]=-1; | ||
1437 | } | ||
1438 | void InitCT() { | ||
1439 | memset(m_ctGraphs,0,sizeof(m_ctGraphs)); | ||
1440 | m_ctGraphs['_'] = ' ';// Blank | ||
1441 | m_ctGraphs['`'] = 4;//Diamond | ||
1442 | m_ctGraphs['a'] = (CHAR)0xB0;// Checkerboard | ||
1443 | m_ctGraphs['b'] = (CHAR)0x1D;// Digigraph: HT | ||
1444 | m_ctGraphs['c'] = (CHAR)0x1F;// Digigtaph: FF | ||
1445 | m_ctGraphs['d'] = (CHAR)0x11;// Digigraph: CR | ||
1446 | m_ctGraphs['e'] = (CHAR)0x19; // Digigraph: LF | ||
1447 | m_ctGraphs['f'] = (CHAR)0xF8;// Degree Symbol | ||
1448 | m_ctGraphs['g'] = (CHAR)0xF1;// +/i Symbol | ||
1449 | m_ctGraphs['h'] = (CHAR)0x1C;// Digigraph: NL | ||
1450 | m_ctGraphs['i'] = (CHAR)0x17;// Digigraph: VT | ||
1451 | m_ctGraphs['j'] = (CHAR)0xD9;// Lower-Right Corner | ||
1452 | m_ctGraphs['k'] = (CHAR)0xBF;// Upper-Right Corner | ||
1453 | m_ctGraphs['l'] = (CHAR)0xDA; // Upper-Left Corner | ||
1454 | m_ctGraphs['m'] = (CHAR)0xC0;// Lower-Left Corner | ||
1455 | m_ctGraphs['n'] = (CHAR)0xC5;// Crossing Lines | ||
1456 | m_ctGraphs['o'] = (CHAR)0xC4;// Horiz Line - scan 1 | ||
1457 | m_ctGraphs['p'] = (CHAR)0xC4;// Horiz Line - scan 3 | ||
1458 | m_ctGraphs['q'] = (CHAR)0xC4;// Horiz Line - scan 5 | ||
1459 | m_ctGraphs['r'] = (CHAR)0xC4;// Horiz Line - scan 7 | ||
1460 | m_ctGraphs['s'] = (CHAR)0xC4;// Horiz Line - scan 9 | ||
1461 | m_ctGraphs['t'] = (CHAR)0xC3;// Left 'T' - |- | ||
1462 | m_ctGraphs['u'] = (CHAR)0xB4;// Right 'T' - -| | ||
1463 | m_ctGraphs['v'] = (CHAR)0xC1;// Bottom 'T' - _|_ | ||
1464 | m_ctGraphs['w'] = (CHAR)0xC2;// Top 'T' - -,- | ||
1465 | m_ctGraphs['x'] = (CHAR)0xB3;// Vertical Bar - | | ||
1466 | m_ctGraphs['y'] = (CHAR)0xF3;// Less or equal <= | ||
1467 | m_ctGraphs['z'] = (CHAR)0xF2; // Greater or equal >= | ||
1468 | m_ctGraphs['{'] = (CHAR)0xE3;// Pi symbol | ||
1469 | m_ctGraphs['|'] = (CHAR)0xD8;// Not equal != | ||
1470 | m_ctGraphs['}'] = (CHAR)0xE0;// UK pound symbol | ||
1471 | m_ctGraphs['~'] = (CHAR)0xF9;// Centered dot | ||
1472 | } | ||
1473 | } | ||
1474 | TT_VT100; | ||
1475 | |||
1476 | DWORD CVT100::dummyWritten = 0; | ||
1477 | CHAR CVT100::m_ctGraphs[256]; | ||
1478 | // ?? CHAR CVT100::sfCrap[256]; | ||