summaryrefslogtreecommitdiffabout
path: root/VT100.cpp
Unidiff
Diffstat (limited to 'VT100.cpp') (more/less context) (show whitespace changes)
-rw-r--r--VT100.cpp1478
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];
5public:
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
1476DWORD CVT100::dummyWritten = 0;
1477CHAR CVT100::m_ctGraphs[256];
1478// ?? CHAR CVT100::sfCrap[256];