1 /*
2 This file is part of Konsole, an X terminal.
3
4 Copyright 2007-2008 by Robert Knight <robert.knight@gmail.com>
5 Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 */
22
23 // Own
24 #include "Vt102Emulation.h"
25 #include "mac-vkcode.h"
26
27 // XKB
28 //#include <config-konsole.h>
29
30 // this allows konsole to be compiled without XKB and XTEST extensions
31 // even though it might be available on a particular system.
32 #if defined(AVOID_XKB)
33 #undef HAVE_XKB
34 #endif
35
36 #if defined(HAVE_XKB)
37 void scrolllock_set_off();
38 void scrolllock_set_on();
39 #endif
40
41 // Standard
42 #include <stdio.h>
43 #include <unistd.h>
44
45 // Qt
46 #include <QEvent>
47 #include <QKeyEvent>
48 #include <QByteRef>
49
50 // KDE
51 //#include <kdebug.h>
52 //#include <klocale.h>
53
54 // Konsole
55 #include "KeyboardTranslator.h"
56 #include "Screen.h"
57
58
59 using namespace Konsole;
60
Vt102Emulation()61 Vt102Emulation::Vt102Emulation()
62 : Emulation(),
63 prevCC(0),
64 _titleUpdateTimer(new QTimer(this)),
65 _reportFocusEvents(false)
66 {
67 _titleUpdateTimer->setSingleShot(true);
68 QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));
69
70 initTokenizer();
71 reset();
72 }
73
~Vt102Emulation()74 Vt102Emulation::~Vt102Emulation()
75 {}
76
clearEntireScreen()77 void Vt102Emulation::clearEntireScreen()
78 {
79 _currentScreen->clearEntireScreen();
80 bufferedUpdate();
81 }
82
reset()83 void Vt102Emulation::reset()
84 {
85 resetTokenizer();
86 resetModes();
87 resetCharset(0);
88 _screen[0]->reset();
89 resetCharset(1);
90 _screen[1]->reset();
91 setCodec(LocaleCodec);
92
93 bufferedUpdate();
94 }
95
96 /* ------------------------------------------------------------------------- */
97 /* */
98 /* Processing the incoming byte stream */
99 /* */
100 /* ------------------------------------------------------------------------- */
101
102 /* Incoming Bytes Event pipeline
103
104 This section deals with decoding the incoming character stream.
105 Decoding means here, that the stream is first separated into `tokens'
106 which are then mapped to a `meaning' provided as operations by the
107 `Screen' class or by the emulation class itself.
108
109 The pipeline proceeds as follows:
110
111 - Tokenizing the ESC codes (onReceiveChar)
112 - VT100 code page translation of plain characters (applyCharset)
113 - Interpretation of ESC codes (processToken)
114
115 The escape codes and their meaning are described in the
116 technical reference of this program.
117 */
118
119 // Tokens ------------------------------------------------------------------ --
120
121 /*
122 Since the tokens are the central notion if this section, we've put them
123 in front. They provide the syntactical elements used to represent the
124 terminals operations as byte sequences.
125
126 They are encodes here into a single machine word, so that we can later
127 switch over them easily. Depending on the token itself, additional
128 argument variables are filled with parameter values.
129
130 The tokens are defined below:
131
132 - CHR - Printable characters (32..255 but DEL (=127))
133 - CTL - Control characters (0..31 but ESC (= 27), DEL)
134 - ESC - Escape codes of the form <ESC><CHR but `[]()+*#'>
135 - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
136 - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
137 - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
138 - CSI_PS_SP - Escape codes of the form <ESC>'[' {Pn} ';' ... {Space} C
139 - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
140 - CSI_PE - Escape codes of the form <ESC>'[' '!' {Pn} ';' ... C
141 - VT52 - VT52 escape codes
142 - <ESC><Chr>
143 - <ESC>'Y'{Pc}{Pc}
144 - XTE_HA - Xterm window/terminal attribute commands
145 of the form <ESC>`]' {Pn} `;' {Text} <BEL>
146 (Note that these are handled differently to the other formats)
147
148 The last two forms allow list of arguments. Since the elements of
149 the lists are treated individually the same way, they are passed
150 as individual tokens to the interpretation. Further, because the
151 meaning of the parameters are names (althought represented as numbers),
152 they are includes within the token ('N').
153
154 */
155
156 #define TY_CONSTRUCT(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
157
158 #define TY_CHR( ) TY_CONSTRUCT(0,0,0)
159 #define TY_CTL(A ) TY_CONSTRUCT(1,A,0)
160 #define TY_ESC(A ) TY_CONSTRUCT(2,A,0)
161 #define TY_ESC_CS(A,B) TY_CONSTRUCT(3,A,B)
162 #define TY_ESC_DE(A ) TY_CONSTRUCT(4,A,0)
163 #define TY_CSI_PS(A,N) TY_CONSTRUCT(5,A,N)
164 #define TY_CSI_PN(A ) TY_CONSTRUCT(6,A,0)
165 #define TY_CSI_PR(A,N) TY_CONSTRUCT(7,A,N)
166 #define TY_CSI_PS_SP(A,N) TY_CONSTRUCT(11,A,N)
167
168 #define TY_VT52(A) TY_CONSTRUCT(8,A,0)
169 #define TY_CSI_PG(A) TY_CONSTRUCT(9,A,0)
170 #define TY_CSI_PE(A) TY_CONSTRUCT(10,A,0)
171
172 #define MAX_ARGUMENT 4096
173
174 // Tokenizer --------------------------------------------------------------- --
175
176 /* The tokenizer's state
177
178 The state is represented by the buffer (tokenBuffer, tokenBufferPos),
179 and accompanied by decoded arguments kept in (argv,argc).
180 Note that they are kept internal in the tokenizer.
181 */
182
resetTokenizer()183 void Vt102Emulation::resetTokenizer()
184 {
185 tokenBufferPos = 0;
186 argc = 0;
187 argv[0] = 0;
188 argv[1] = 0;
189 prevCC = 0;
190 }
191
addDigit(int digit)192 void Vt102Emulation::addDigit(int digit)
193 {
194 if (argv[argc] < MAX_ARGUMENT)
195 argv[argc] = 10*argv[argc] + digit;
196 }
197
addArgument()198 void Vt102Emulation::addArgument()
199 {
200 argc = qMin(argc+1,MAXARGS-1);
201 argv[argc] = 0;
202 }
203
addToCurrentToken(wchar_t cc)204 void Vt102Emulation::addToCurrentToken(wchar_t cc)
205 {
206 tokenBuffer[tokenBufferPos] = cc;
207 tokenBufferPos = qMin(tokenBufferPos+1,MAX_TOKEN_LENGTH-1);
208 }
209
210 // Character Class flags used while decoding
211 #define CTL 1 // Control character
212 #define CHR 2 // Printable character
213 #define CPN 4 // TODO: Document me
214 #define DIG 8 // Digit
215 #define SCS 16 // TODO: Document me
216 #define GRP 32 // TODO: Document me
217 #define CPS 64 // Character which indicates end of window resize
218 // escape sequence '\e[8;<row>;<col>t'
219
initTokenizer()220 void Vt102Emulation::initTokenizer()
221 {
222 int i;
223 quint8* s;
224 for(i = 0;i < 256; ++i)
225 charClass[i] = 0;
226 for(i = 0;i < 32; ++i)
227 charClass[i] |= CTL;
228 for(i = 32;i < 256; ++i)
229 charClass[i] |= CHR;
230 for(s = (quint8*)"@ABCDGHILMPSTXZbcdfry"; *s; ++s)
231 charClass[*s] |= CPN;
232 // resize = \e[8;<row>;<col>t
233 for(s = (quint8*)"t"; *s; ++s)
234 charClass[*s] |= CPS;
235 for(s = (quint8*)"0123456789"; *s; ++s)
236 charClass[*s] |= DIG;
237 for(s = (quint8*)"()+*%"; *s; ++s)
238 charClass[*s] |= SCS;
239 for(s = (quint8*)"()+*#[]%"; *s; ++s)
240 charClass[*s] |= GRP;
241
242 resetTokenizer();
243 }
244
245 /* Ok, here comes the nasty part of the decoder.
246
247 Instead of keeping an explicit state, we deduce it from the
248 token scanned so far. It is then immediately combined with
249 the current character to form a scanning decision.
250
251 This is done by the following defines.
252
253 - P is the length of the token scanned so far.
254 - L (often P-1) is the position on which contents we base a decision.
255 - C is a character or a group of characters (taken from 'charClass').
256
257 - 'cc' is the current character
258 - 's' is a pointer to the start of the token buffer
259 - 'p' is the current position within the token buffer
260
261 Note that they need to applied in proper order.
262 */
263
264 #define lec(P,L,C) (p == (P) && s[(L)] == (C))
265 #define lun( ) (p == 1 && cc >= 32 )
266 #define les(P,L,C) (p == (P) && s[L] < 256 && (charClass[s[(L)]] & (C)) == (C))
267 #define eec(C) (p >= 3 && cc == (C))
268 #define ees(C) (p >= 3 && cc < 256 && (charClass[cc] & (C)) == (C))
269 #define eps(C) (p >= 3 && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (charClass[cc] & (C)) == (C))
270 #define epp( ) (p >= 3 && s[2] == '?')
271 #define epe( ) (p >= 3 && s[2] == '!')
272 #define egt( ) (p >= 3 && s[2] == '>')
273 #define esp( ) (p == 4 && s[3] == ' ')
274 #define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
275 #define Xte (Xpe && (cc == 7 || (prevCC == 27 && cc == 92) )) // 27, 92 => "\e\\" (ST, String Terminator)
276 #define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
277
278 #define CNTL(c) ((c)-'@')
279 #define ESC 27
280 #define DEL 127
281
282 // process an incoming unicode character
receiveChar(wchar_t cc)283 void Vt102Emulation::receiveChar(wchar_t cc)
284 {
285 if (cc == DEL)
286 return; //VT100: ignore.
287
288 if (ces(CTL))
289 {
290 // ignore control characters in the text part of Xpe (aka OSC) "ESC]"
291 // escape sequences; this matches what XTERM docs say
292 if (Xpe) {
293 prevCC = cc;
294 return;
295 }
296
297 // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
298 // This means, they do neither a resetTokenizer() nor a pushToToken(). Some of them, do
299 // of course. Guess this originates from a weakly layered handling of the X-on
300 // X-off protocol, which comes really below this level.
301 if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC)
302 resetTokenizer(); //VT100: CAN or SUB
303 if (cc != ESC)
304 {
305 processToken(TY_CTL(cc+'@' ),0,0);
306 return;
307 }
308 }
309 // advance the state
310 addToCurrentToken(cc);
311
312 wchar_t* s = tokenBuffer;
313 int p = tokenBufferPos;
314
315 if (getMode(MODE_Ansi))
316 {
317 if (lec(1,0,ESC)) { return; }
318 if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('['); return; }
319 if (les(2,1,GRP)) { return; }
320 if (Xte ) { processWindowAttributeChange(); resetTokenizer(); return; }
321 if (Xpe ) { prevCC = cc; return; }
322 if (lec(3,2,'?')) { return; }
323 if (lec(3,2,'>')) { return; }
324 if (lec(3,2,'!')) { return; }
325 if (lun( )) { processToken( TY_CHR(), applyCharset(cc), 0); resetTokenizer(); return; }
326 if (lec(2,0,ESC)) { processToken( TY_ESC(s[1]), 0, 0); resetTokenizer(); return; }
327 if (les(3,1,SCS)) { processToken( TY_ESC_CS(s[1],s[2]), 0, 0); resetTokenizer(); return; }
328 if (lec(3,1,'#')) { processToken( TY_ESC_DE(s[2]), 0, 0); resetTokenizer(); return; }
329 if (eps( CPN)) { processToken( TY_CSI_PN(cc), argv[0],argv[1]); resetTokenizer(); return; }
330 if (esp( )) { return; }
331 if (lec(5, 4, 'q') && s[3] == ' ') {
332 processToken( TY_CSI_PS_SP(cc, argv[0]), argv[0], 0);
333 resetTokenizer();
334 return;
335 }
336
337 // resize = \e[8;<row>;<col>t
338 if (eps(CPS))
339 {
340 processToken( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]);
341 resetTokenizer();
342 return;
343 }
344
345 if (epe( )) { processToken( TY_CSI_PE(cc), 0, 0); resetTokenizer(); return; }
346 if (ees(DIG)) { addDigit(cc-'0'); return; }
347 if (eec(';')) { addArgument(); return; }
348 for (int i=0;i<=argc;i++)
349 {
350 if (epp())
351 processToken( TY_CSI_PR(cc,argv[i]), 0, 0);
352 else if (egt())
353 processToken( TY_CSI_PG(cc), 0, 0); // spec. case for ESC]>0c or ESC]>c
354 else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
355 {
356 // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
357 i += 2;
358 processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);
359 i += 2;
360 }
361 else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)
362 {
363 // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
364 i += 2;
365 processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_256, argv[i]);
366 }
367 else
368 processToken( TY_CSI_PS(cc,argv[i]), 0, 0);
369 }
370 resetTokenizer();
371 }
372 else
373 {
374 // VT52 Mode
375 if (lec(1,0,ESC))
376 return;
377 if (les(1,0,CHR))
378 {
379 processToken( TY_CHR(), s[0], 0);
380 resetTokenizer();
381 return;
382 }
383 if (lec(2,1,'Y'))
384 return;
385
386 if (lec(3,1,'Y'))
387 return;
388
389 if (p < 4)
390 {
391 processToken( TY_VT52(s[1] ), 0, 0);
392 resetTokenizer();
393 return;
394 }
395 processToken( TY_VT52(s[1]), s[2], s[3]);
396 resetTokenizer();
397 return;
398 }
399 }
processWindowAttributeChange()400 void Vt102Emulation::processWindowAttributeChange()
401 {
402 // Describes the window or terminal session attribute to change
403 // See Session::UserTitleChange for possible values
404 int attributeToChange = 0;
405 int i;
406 for (i = 2; i < tokenBufferPos &&
407 tokenBuffer[i] >= '0' &&
408 tokenBuffer[i] <= '9'; i++)
409 {
410 attributeToChange = 10 * attributeToChange + (tokenBuffer[i]-'0');
411 }
412
413 if (tokenBuffer[i] != ';')
414 {
415 reportDecodingError();
416 return;
417 }
418
419 QString newValue;
420 newValue.reserve(tokenBufferPos-i-2);
421 for (int j = 0; j < tokenBufferPos-i-2; j++)
422 newValue[j] = tokenBuffer[i+1+j];
423
424 _pendingTitleUpdates[attributeToChange] = newValue;
425 _titleUpdateTimer->start(20);
426 }
427
updateTitle()428 void Vt102Emulation::updateTitle()
429 {
430 QListIterator<int> iter( _pendingTitleUpdates.keys() );
431 while (iter.hasNext()) {
432 int arg = iter.next();
433 emit titleChanged( arg , _pendingTitleUpdates[arg] );
434 }
435 _pendingTitleUpdates.clear();
436 }
437
438 // Interpreting Codes ---------------------------------------------------------
439
440 /*
441 Now that the incoming character stream is properly tokenized,
442 meaning is assigned to them. These are either operations of
443 the current _screen, or of the emulation class itself.
444
445 The token to be interpreteted comes in as a machine word
446 possibly accompanied by two parameters.
447
448 Likewise, the operations assigned to, come with up to two
449 arguments. One could consider to make up a proper table
450 from the function below.
451
452 The technical reference manual provides more information
453 about this mapping.
454 */
455
processToken(int token,wchar_t p,int q)456 void Vt102Emulation::processToken(int token, wchar_t p, int q)
457 {
458 switch (token)
459 {
460
461 case TY_CHR( ) : _currentScreen->displayCharacter (p ); break; //UTF16
462
463 // 127 DEL : ignored on input
464
465 case TY_CTL('@' ) : /* NUL: ignored */ break;
466 case TY_CTL('A' ) : /* SOH: ignored */ break;
467 case TY_CTL('B' ) : /* STX: ignored */ break;
468 case TY_CTL('C' ) : /* ETX: ignored */ break;
469 case TY_CTL('D' ) : /* EOT: ignored */ break;
470 case TY_CTL('E' ) : reportAnswerBack ( ); break; //VT100
471 case TY_CTL('F' ) : /* ACK: ignored */ break;
472 case TY_CTL('G' ) : emit stateSet(NOTIFYBELL);
473 break; //VT100
474 case TY_CTL('H' ) : _currentScreen->backspace ( ); break; //VT100
475 case TY_CTL('I' ) : _currentScreen->tab ( ); break; //VT100
476 case TY_CTL('J' ) : _currentScreen->newLine ( ); break; //VT100
477 case TY_CTL('K' ) : _currentScreen->newLine ( ); break; //VT100
478 case TY_CTL('L' ) : _currentScreen->newLine ( ); break; //VT100
479 case TY_CTL('M' ) : _currentScreen->toStartOfLine ( ); break; //VT100
480
481 case TY_CTL('N' ) : useCharset ( 1); break; //VT100
482 case TY_CTL('O' ) : useCharset ( 0); break; //VT100
483
484 case TY_CTL('P' ) : /* DLE: ignored */ break;
485 case TY_CTL('Q' ) : /* DC1: XON continue */ break; //VT100
486 case TY_CTL('R' ) : /* DC2: ignored */ break;
487 case TY_CTL('S' ) : /* DC3: XOFF halt */ break; //VT100
488 case TY_CTL('T' ) : /* DC4: ignored */ break;
489 case TY_CTL('U' ) : /* NAK: ignored */ break;
490 case TY_CTL('V' ) : /* SYN: ignored */ break;
491 case TY_CTL('W' ) : /* ETB: ignored */ break;
492 case TY_CTL('X' ) : _currentScreen->displayCharacter ( 0x2592); break; //VT100
493 case TY_CTL('Y' ) : /* EM : ignored */ break;
494 case TY_CTL('Z' ) : _currentScreen->displayCharacter ( 0x2592); break; //VT100
495 case TY_CTL('[' ) : /* ESC: cannot be seen here. */ break;
496 case TY_CTL('\\' ) : /* FS : ignored */ break;
497 case TY_CTL(']' ) : /* GS : ignored */ break;
498 case TY_CTL('^' ) : /* RS : ignored */ break;
499 case TY_CTL('_' ) : /* US : ignored */ break;
500
501 case TY_ESC('D' ) : _currentScreen->index ( ); break; //VT100
502 case TY_ESC('E' ) : _currentScreen->nextLine ( ); break; //VT100
503 case TY_ESC('H' ) : _currentScreen->changeTabStop (true ); break; //VT100
504 case TY_ESC('M' ) : _currentScreen->reverseIndex ( ); break; //VT100
505 case TY_ESC('Z' ) : reportTerminalType ( ); break;
506 case TY_ESC('c' ) : reset ( ); break;
507
508 case TY_ESC('n' ) : useCharset ( 2); break;
509 case TY_ESC('o' ) : useCharset ( 3); break;
510 case TY_ESC('7' ) : saveCursor ( ); break;
511 case TY_ESC('8' ) : restoreCursor ( ); break;
512
513 case TY_ESC('=' ) : setMode (MODE_AppKeyPad); break;
514 case TY_ESC('>' ) : resetMode (MODE_AppKeyPad); break;
515 case TY_ESC('<' ) : setMode (MODE_Ansi ); break; //VT100
516
517 case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100
518 case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100
519 case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100
520
521 case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100
522 case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100
523 case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100
524
525 case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100
526 case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100
527 case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100
528
529 case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100
530 case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100
531 case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100
532
533 case TY_ESC_CS('%', 'G') : setCodec (Utf8Codec ); break; //LINUX
534 case TY_ESC_CS('%', '@') : setCodec (LocaleCodec ); break; //LINUX
535
536 case TY_ESC_DE('3' ) : /* Double height line, top half */
537 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
538 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
539 break;
540 case TY_ESC_DE('4' ) : /* Double height line, bottom half */
541 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
542 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
543 break;
544 case TY_ESC_DE('5' ) : /* Single width, single height line*/
545 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
546 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
547 break;
548 case TY_ESC_DE('6' ) : /* Double width, single height line*/
549 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);
550 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
551 break;
552 case TY_ESC_DE('8' ) : _currentScreen->helpAlign ( ); break;
553
554 // resize = \e[8;<row>;<col>t
555 case TY_CSI_PS('t', 8) : setImageSize( p /*lines */, q /* columns */ );
556 emit imageResizeRequest(QSize(q, p));
557 break;
558
559 // change tab text color : \e[28;<color>t color: 0-16,777,215
560 case TY_CSI_PS('t', 28) : emit changeTabTextColorRequest ( p ); break;
561
562 case TY_CSI_PS('K', 0) : _currentScreen->clearToEndOfLine ( ); break;
563 case TY_CSI_PS('K', 1) : _currentScreen->clearToBeginOfLine ( ); break;
564 case TY_CSI_PS('K', 2) : _currentScreen->clearEntireLine ( ); break;
565 case TY_CSI_PS('J', 0) : _currentScreen->clearToEndOfScreen ( ); break;
566 case TY_CSI_PS('J', 1) : _currentScreen->clearToBeginOfScreen ( ); break;
567 case TY_CSI_PS('J', 2) : _currentScreen->clearEntireScreen ( ); break;
568 case TY_CSI_PS('J', 3) : clearHistory(); break;
569 case TY_CSI_PS('g', 0) : _currentScreen->changeTabStop (false ); break; //VT100
570 case TY_CSI_PS('g', 3) : _currentScreen->clearTabStops ( ); break; //VT100
571 case TY_CSI_PS('h', 4) : _currentScreen-> setMode (MODE_Insert ); break;
572 case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break;
573 case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100
574 case TY_CSI_PS('l', 4) : _currentScreen-> resetMode (MODE_Insert ); break;
575 case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break;
576 case TY_CSI_PS('s', 0) : saveCursor ( ); break;
577 case TY_CSI_PS('u', 0) : restoreCursor ( ); break;
578
579 case TY_CSI_PS('m', 0) : _currentScreen->setDefaultRendition ( ); break;
580 case TY_CSI_PS('m', 1) : _currentScreen-> setRendition (RE_BOLD ); break; //VT100
581 case TY_CSI_PS('m', 2) : _currentScreen-> setRendition (RE_FAINT ); break;
582 case TY_CSI_PS('m', 3) : _currentScreen-> setRendition (RE_ITALIC ); break; //VT100
583 case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break; //VT100
584 case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break; //VT100
585 case TY_CSI_PS('m', 7) : _currentScreen-> setRendition (RE_REVERSE ); break;
586 case TY_CSI_PS('m', 8) : _currentScreen-> setRendition (RE_CONCEAL ); break;
587 case TY_CSI_PS('m', 9) : _currentScreen-> setRendition (RE_STRIKEOUT); break;
588 case TY_CSI_PS('m', 53) : _currentScreen-> setRendition (RE_OVERLINE ); break;
589 case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
590 case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
591 case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
592 case TY_CSI_PS('m', 21) : _currentScreen->resetRendition (RE_BOLD ); break;
593 case TY_CSI_PS('m', 22) : _currentScreen->resetRendition (RE_BOLD );
594 _currentScreen->resetRendition (RE_FAINT ); break;
595 case TY_CSI_PS('m', 23) : _currentScreen->resetRendition (RE_ITALIC ); break; //VT100
596 case TY_CSI_PS('m', 24) : _currentScreen->resetRendition (RE_UNDERLINE); break;
597 case TY_CSI_PS('m', 25) : _currentScreen->resetRendition (RE_BLINK ); break;
598 case TY_CSI_PS('m', 27) : _currentScreen->resetRendition (RE_REVERSE ); break;
599 case TY_CSI_PS('m', 28) : _currentScreen->resetRendition (RE_CONCEAL ); break;
600 case TY_CSI_PS('m', 29) : _currentScreen->resetRendition (RE_STRIKEOUT); break;
601 case TY_CSI_PS('m', 55) : _currentScreen->resetRendition (RE_OVERLINE ); break;
602
603 case TY_CSI_PS('m', 30) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); break;
604 case TY_CSI_PS('m', 31) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); break;
605 case TY_CSI_PS('m', 32) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 2); break;
606 case TY_CSI_PS('m', 33) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 3); break;
607 case TY_CSI_PS('m', 34) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 4); break;
608 case TY_CSI_PS('m', 35) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 5); break;
609 case TY_CSI_PS('m', 36) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 6); break;
610 case TY_CSI_PS('m', 37) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 7); break;
611
612 case TY_CSI_PS('m', 38) : _currentScreen->setForeColor (p, q); break;
613
614 case TY_CSI_PS('m', 39) : _currentScreen->setForeColor (COLOR_SPACE_DEFAULT, 0); break;
615
616 case TY_CSI_PS('m', 40) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 0); break;
617 case TY_CSI_PS('m', 41) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 1); break;
618 case TY_CSI_PS('m', 42) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 2); break;
619 case TY_CSI_PS('m', 43) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 3); break;
620 case TY_CSI_PS('m', 44) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 4); break;
621 case TY_CSI_PS('m', 45) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 5); break;
622 case TY_CSI_PS('m', 46) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 6); break;
623 case TY_CSI_PS('m', 47) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 7); break;
624
625 case TY_CSI_PS('m', 48) : _currentScreen->setBackColor (p, q); break;
626
627 case TY_CSI_PS('m', 49) : _currentScreen->setBackColor (COLOR_SPACE_DEFAULT, 1); break;
628
629 case TY_CSI_PS('m', 90) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 8); break;
630 case TY_CSI_PS('m', 91) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 9); break;
631 case TY_CSI_PS('m', 92) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 10); break;
632 case TY_CSI_PS('m', 93) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 11); break;
633 case TY_CSI_PS('m', 94) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 12); break;
634 case TY_CSI_PS('m', 95) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 13); break;
635 case TY_CSI_PS('m', 96) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 14); break;
636 case TY_CSI_PS('m', 97) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 15); break;
637
638 case TY_CSI_PS('m', 100) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 8); break;
639 case TY_CSI_PS('m', 101) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 9); break;
640 case TY_CSI_PS('m', 102) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 10); break;
641 case TY_CSI_PS('m', 103) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 11); break;
642 case TY_CSI_PS('m', 104) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 12); break;
643 case TY_CSI_PS('m', 105) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 13); break;
644 case TY_CSI_PS('m', 106) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 14); break;
645 case TY_CSI_PS('m', 107) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 15); break;
646
647 case TY_CSI_PS('n', 5) : reportStatus ( ); break;
648 case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break;
649 case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100
650 case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100
651 case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100
652 case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100
653 case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100
654 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
655 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
656
657 case TY_CSI_PS_SP('q', 0) : /* fall through */
658 case TY_CSI_PS_SP('q', 1) : emit cursorChanged(KeyboardCursorShape::BlockCursor, true ); break;
659 case TY_CSI_PS_SP('q', 2) : emit cursorChanged(KeyboardCursorShape::BlockCursor, false); break;
660 case TY_CSI_PS_SP('q', 3) : emit cursorChanged(KeyboardCursorShape::UnderlineCursor, true ); break;
661 case TY_CSI_PS_SP('q', 4) : emit cursorChanged(KeyboardCursorShape::UnderlineCursor, false); break;
662 case TY_CSI_PS_SP('q', 5) : emit cursorChanged(KeyboardCursorShape::IBeamCursor, true ); break;
663 case TY_CSI_PS_SP('q', 6) : emit cursorChanged(KeyboardCursorShape::IBeamCursor, false); break;
664
665 case TY_CSI_PN('@' ) : _currentScreen->insertChars (p ); break;
666 case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break; //VT100
667 case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break; //VT100
668 case TY_CSI_PN('C' ) : _currentScreen->cursorRight (p ); break; //VT100
669 case TY_CSI_PN('D' ) : _currentScreen->cursorLeft (p ); break; //VT100
670 case TY_CSI_PN('E' ) : /* Not implemented: cursor next p lines */ break; //VT100
671 case TY_CSI_PN('F' ) : /* Not implemented: cursor preceding p lines */ break; //VT100
672 case TY_CSI_PN('G' ) : _currentScreen->setCursorX (p ); break; //LINUX
673 case TY_CSI_PN('H' ) : _currentScreen->setCursorYX (p, q); break; //VT100
674 case TY_CSI_PN('I' ) : _currentScreen->tab (p ); break;
675 case TY_CSI_PN('L' ) : _currentScreen->insertLines (p ); break;
676 case TY_CSI_PN('M' ) : _currentScreen->deleteLines (p ); break;
677 case TY_CSI_PN('P' ) : _currentScreen->deleteChars (p ); break;
678 case TY_CSI_PN('S' ) : _currentScreen->scrollUp (p ); break;
679 case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break;
680 case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break;
681 case TY_CSI_PN('Z' ) : _currentScreen->backtab (p ); break;
682 case TY_CSI_PN('b' ) : _currentScreen->repeatChars (p ); break;
683 case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
684 case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX
685 case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break; //VT100
686 case TY_CSI_PN('r' ) : setMargins (p, q); break; //VT100
687 case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100
688
689 case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100
690 case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100
691 case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME
692 case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME
693
694 case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100
695
696 case TY_CSI_PR('h', 3) : setMode (MODE_132Columns);break; //VT100
697 case TY_CSI_PR('l', 3) : resetMode (MODE_132Columns);break; //VT100
698
699 case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100
700 case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100
701
702 case TY_CSI_PR('h', 5) : _currentScreen-> setMode (MODE_Screen ); break; //VT100
703 case TY_CSI_PR('l', 5) : _currentScreen-> resetMode (MODE_Screen ); break; //VT100
704
705 case TY_CSI_PR('h', 6) : _currentScreen-> setMode (MODE_Origin ); break; //VT100
706 case TY_CSI_PR('l', 6) : _currentScreen-> resetMode (MODE_Origin ); break; //VT100
707 case TY_CSI_PR('s', 6) : _currentScreen-> saveMode (MODE_Origin ); break; //FIXME
708 case TY_CSI_PR('r', 6) : _currentScreen->restoreMode (MODE_Origin ); break; //FIXME
709
710 case TY_CSI_PR('h', 7) : _currentScreen-> setMode (MODE_Wrap ); break; //VT100
711 case TY_CSI_PR('l', 7) : _currentScreen-> resetMode (MODE_Wrap ); break; //VT100
712 case TY_CSI_PR('s', 7) : _currentScreen-> saveMode (MODE_Wrap ); break; //FIXME
713 case TY_CSI_PR('r', 7) : _currentScreen->restoreMode (MODE_Wrap ); break; //FIXME
714
715 case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100
716 case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100
717 case TY_CSI_PR('s', 8) : /* IGNORED: autorepeat on */ break; //VT100
718 case TY_CSI_PR('r', 8) : /* IGNORED: autorepeat off */ break; //VT100
719
720 case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100
721 case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100
722 case TY_CSI_PR('s', 9) : /* IGNORED: interlace */ break; //VT100
723 case TY_CSI_PR('r', 9) : /* IGNORED: interlace */ break; //VT100
724
725 case TY_CSI_PR('h', 12) : /* IGNORED: Cursor blink */ break; //att610
726 case TY_CSI_PR('l', 12) : /* IGNORED: Cursor blink */ break; //att610
727 case TY_CSI_PR('s', 12) : /* IGNORED: Cursor blink */ break; //att610
728 case TY_CSI_PR('r', 12) : /* IGNORED: Cursor blink */ break; //att610
729
730 case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100
731 case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100
732 case TY_CSI_PR('s', 25) : saveMode (MODE_Cursor ); break; //VT100
733 case TY_CSI_PR('r', 25) : restoreMode (MODE_Cursor ); break; //VT100
734
735 case TY_CSI_PR('h', 40) : setMode(MODE_Allow132Columns ); break; // XTERM
736 case TY_CSI_PR('l', 40) : resetMode(MODE_Allow132Columns ); break; // XTERM
737
738 case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
739 case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
740 case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
741 case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
742
743 case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100
744 case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100
745 case TY_CSI_PR('s', 47) : saveMode (MODE_AppScreen); break; //XTERM
746 case TY_CSI_PR('r', 47) : restoreMode (MODE_AppScreen); break; //XTERM
747
748 case TY_CSI_PR('h', 67) : /* IGNORED: DECBKM */ break; //XTERM
749 case TY_CSI_PR('l', 67) : /* IGNORED: DECBKM */ break; //XTERM
750 case TY_CSI_PR('s', 67) : /* IGNORED: DECBKM */ break; //XTERM
751 case TY_CSI_PR('r', 67) : /* IGNORED: DECBKM */ break; //XTERM
752
753 // XTerm defines the following modes:
754 // SET_VT200_MOUSE 1000
755 // SET_VT200_HIGHLIGHT_MOUSE 1001
756 // SET_BTN_EVENT_MOUSE 1002
757 // SET_ANY_EVENT_MOUSE 1003
758 //
759
760 //Note about mouse modes:
761 //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003
762 //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).
763 //TODO: Implementation of mouse modes 1001 (something called hilight tracking) and
764 //1003 (a slight variation on dragging the mouse)
765 //
766
767 case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM
768 case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM
769 case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM
770 case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM
771
772 case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
773 case TY_CSI_PR('l', 1001) : resetMode (MODE_Mouse1001); break; //XTERM
774 case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
775 case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
776
777 case TY_CSI_PR('h', 1002) : setMode (MODE_Mouse1002); break; //XTERM
778 case TY_CSI_PR('l', 1002) : resetMode (MODE_Mouse1002); break; //XTERM
779 case TY_CSI_PR('s', 1002) : saveMode (MODE_Mouse1002); break; //XTERM
780 case TY_CSI_PR('r', 1002) : restoreMode (MODE_Mouse1002); break; //XTERM
781
782 case TY_CSI_PR('h', 1003) : setMode (MODE_Mouse1003); break; //XTERM
783 case TY_CSI_PR('l', 1003) : resetMode (MODE_Mouse1003); break; //XTERM
784 case TY_CSI_PR('s', 1003) : saveMode (MODE_Mouse1003); break; //XTERM
785 case TY_CSI_PR('r', 1003) : restoreMode (MODE_Mouse1003); break; //XTERM
786
787 case TY_CSI_PR('h', 1004) : _reportFocusEvents = true; break;
788 case TY_CSI_PR('l', 1004) : _reportFocusEvents = false; break;
789
790 case TY_CSI_PR('h', 1005) : setMode (MODE_Mouse1005); break; //XTERM
791 case TY_CSI_PR('l', 1005) : resetMode (MODE_Mouse1005); break; //XTERM
792 case TY_CSI_PR('s', 1005) : saveMode (MODE_Mouse1005); break; //XTERM
793 case TY_CSI_PR('r', 1005) : restoreMode (MODE_Mouse1005); break; //XTERM
794
795 case TY_CSI_PR('h', 1006) : setMode (MODE_Mouse1006); break; //XTERM
796 case TY_CSI_PR('l', 1006) : resetMode (MODE_Mouse1006); break; //XTERM
797 case TY_CSI_PR('s', 1006) : saveMode (MODE_Mouse1006); break; //XTERM
798 case TY_CSI_PR('r', 1006) : restoreMode (MODE_Mouse1006); break; //XTERM
799
800 case TY_CSI_PR('h', 1015) : setMode (MODE_Mouse1015); break; //URXVT
801 case TY_CSI_PR('l', 1015) : resetMode (MODE_Mouse1015); break; //URXVT
802 case TY_CSI_PR('s', 1015) : saveMode (MODE_Mouse1015); break; //URXVT
803 case TY_CSI_PR('r', 1015) : restoreMode (MODE_Mouse1015); break; //URXVT
804
805 case TY_CSI_PR('h', 1034) : /* IGNORED: 8bitinput activation */ break; //XTERM
806
807 case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM
808 case TY_CSI_PR('l', 1047) : _screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break; //XTERM
809 case TY_CSI_PR('s', 1047) : saveMode (MODE_AppScreen); break; //XTERM
810 case TY_CSI_PR('r', 1047) : restoreMode (MODE_AppScreen); break; //XTERM
811
812 //FIXME: Unitoken: save translations
813 case TY_CSI_PR('h', 1048) : saveCursor ( ); break; //XTERM
814 case TY_CSI_PR('l', 1048) : restoreCursor ( ); break; //XTERM
815 case TY_CSI_PR('s', 1048) : saveCursor ( ); break; //XTERM
816 case TY_CSI_PR('r', 1048) : restoreCursor ( ); break; //XTERM
817
818 //FIXME: every once new sequences like this pop up in xterm.
819 // Here's a guess of what they could mean.
820 case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM
821 case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM
822
823 case TY_CSI_PR('h', 2004) : setMode (MODE_BracketedPaste); break; //XTERM
824 case TY_CSI_PR('l', 2004) : resetMode (MODE_BracketedPaste); break; //XTERM
825 case TY_CSI_PR('s', 2004) : saveMode (MODE_BracketedPaste); break; //XTERM
826 case TY_CSI_PR('r', 2004) : restoreMode (MODE_BracketedPaste); break; //XTERM
827
828 //FIXME: weird DEC reset sequence
829 case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break;
830
831 //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
832 case TY_VT52('A' ) : _currentScreen->cursorUp ( 1); break; //VT52
833 case TY_VT52('B' ) : _currentScreen->cursorDown ( 1); break; //VT52
834 case TY_VT52('C' ) : _currentScreen->cursorRight ( 1); break; //VT52
835 case TY_VT52('D' ) : _currentScreen->cursorLeft ( 1); break; //VT52
836
837 case TY_VT52('F' ) : setAndUseCharset (0, '0'); break; //VT52
838 case TY_VT52('G' ) : setAndUseCharset (0, 'B'); break; //VT52
839
840 case TY_VT52('H' ) : _currentScreen->setCursorYX (1,1 ); break; //VT52
841 case TY_VT52('I' ) : _currentScreen->reverseIndex ( ); break; //VT52
842 case TY_VT52('J' ) : _currentScreen->clearToEndOfScreen ( ); break; //VT52
843 case TY_VT52('K' ) : _currentScreen->clearToEndOfLine ( ); break; //VT52
844 case TY_VT52('Y' ) : _currentScreen->setCursorYX (p-31,q-31 ); break; //VT52
845 case TY_VT52('Z' ) : reportTerminalType ( ); break; //VT52
846 case TY_VT52('<' ) : setMode (MODE_Ansi ); break; //VT52
847 case TY_VT52('=' ) : setMode (MODE_AppKeyPad); break; //VT52
848 case TY_VT52('>' ) : resetMode (MODE_AppKeyPad); break; //VT52
849
850 case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break; //VT100
851
852 default:
853 reportDecodingError();
854 break;
855 };
856 }
857
clearScreenAndSetColumns(int columnCount)858 void Vt102Emulation::clearScreenAndSetColumns(int columnCount)
859 {
860 setImageSize(_currentScreen->getLines(),columnCount);
861 clearEntireScreen();
862 setDefaultMargins();
863 _currentScreen->setCursorYX(0,0);
864 }
865
sendString(const char * s,int length)866 void Vt102Emulation::sendString(const char* s , int length)
867 {
868 if ( length >= 0 )
869 emit sendData(s,length);
870 else
871 emit sendData(s,strlen(s));
872 }
873
reportCursorPosition()874 void Vt102Emulation::reportCursorPosition()
875 {
876 char tmp[20];
877 sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);
878 sendString(tmp);
879 }
880
reportTerminalType()881 void Vt102Emulation::reportTerminalType()
882 {
883 // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
884 // VT220: ^[[?63;1;2;3;6;7;8c (list deps on emul. capabilities)
885 // VT100: ^[[?1;2c
886 // VT101: ^[[?1;0c
887 // VT102: ^[[?6v
888 if (getMode(MODE_Ansi))
889 sendString("\033[?1;2c"); // I'm a VT100
890 else
891 sendString("\033/Z"); // I'm a VT52
892 }
893
reportSecondaryAttributes()894 void Vt102Emulation::reportSecondaryAttributes()
895 {
896 // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
897 if (getMode(MODE_Ansi))
898 sendString("\033[>0;115;0c"); // Why 115? ;)
899 else
900 sendString("\033/Z"); // FIXME I don't think VT52 knows about it but kept for
901 // konsoles backward compatibility.
902 }
903
reportTerminalParms(int p)904 void Vt102Emulation::reportTerminalParms(int p)
905 // DECREPTPARM
906 {
907 char tmp[100];
908 sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
909 sendString(tmp);
910 }
911
reportStatus()912 void Vt102Emulation::reportStatus()
913 {
914 sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
915 }
916
reportAnswerBack()917 void Vt102Emulation::reportAnswerBack()
918 {
919 // FIXME - Test this with VTTEST
920 // This is really obsolete VT100 stuff.
921 const char* ANSWER_BACK = "";
922 sendString(ANSWER_BACK);
923 }
924
925 /*!
926 `cx',`cy' are 1-based.
927 `cb' indicates the button pressed or released (0-2) or scroll event (4-5).
928
929 eventType represents the kind of mouse action that occurred:
930 0 = Mouse button press
931 1 = Mouse drag
932 2 = Mouse button release
933 */
934
sendMouseEvent(int cb,int cx,int cy,int eventType)935 void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
936 {
937 if (cx < 1 || cy < 1)
938 return;
939
940 // With the exception of the 1006 mode, button release is encoded in cb.
941 // Note that if multiple extensions are enabled, the 1006 is used, so it's okay to check for only that.
942 if (eventType == 2 && !getMode(MODE_Mouse1006))
943 cb = 3;
944
945 // normal buttons are passed as 0x20 + button,
946 // mouse wheel (buttons 4,5) as 0x5c + button
947 if (cb >= 4)
948 cb += 0x3c;
949
950 //Mouse motion handling
951 if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
952 cb += 0x20; //add 32 to signify motion event
953
954 char command[32];
955 command[0] = '\0';
956 // Check the extensions in decreasing order of preference. Encoding the release event above assumes that 1006 comes first.
957 if (getMode(MODE_Mouse1006)) {
958 snprintf(command, sizeof(command), "\033[<%d;%d;%d%c", cb, cx, cy, eventType == 2 ? 'm' : 'M');
959 } else if (getMode(MODE_Mouse1015)) {
960 snprintf(command, sizeof(command), "\033[%d;%d;%dM", cb + 0x20, cx, cy);
961 } else if (getMode(MODE_Mouse1005)) {
962 if (cx <= 2015 && cy <= 2015) {
963 // The xterm extension uses UTF-8 (up to 2 bytes) to encode
964 // coordinate+32, no matter what the locale is. We could easily
965 // convert manually, but QString can also do it for us.
966 QChar coords[2];
967 coords[0] = cx + 0x20;
968 coords[1] = cy + 0x20;
969 QString coordsStr = QString(coords, 2);
970 QByteArray utf8 = coordsStr.toUtf8();
971 snprintf(command, sizeof(command), "\033[M%c%s", cb + 0x20, utf8.constData());
972 }
973 } else if (cx <= 223 && cy <= 223) {
974 snprintf(command, sizeof(command), "\033[M%c%c%c", cb + 0x20, cx + 0x20, cy + 0x20);
975 }
976
977 sendString(command);
978 }
979
980 /**
981 * The focus lost event can be used by Vim (or other terminal applications)
982 * to recognize that the konsole window has lost focus.
983 * The escape sequence is also used by iTerm2.
984 * Vim needs the following plugin to be installed to convert the escape
985 * sequence into the FocusLost autocmd: https://github.com/sjl/vitality.vim
986 */
focusLost(void)987 void Vt102Emulation::focusLost(void)
988 {
989 if (_reportFocusEvents)
990 sendString("\033[O");
991 }
992
993 /**
994 * The focus gained event can be used by Vim (or other terminal applications)
995 * to recognize that the konsole window has gained focus again.
996 * The escape sequence is also used by iTerm2.
997 * Vim needs the following plugin to be installed to convert the escape
998 * sequence into the FocusGained autocmd: https://github.com/sjl/vitality.vim
999 */
focusGained(void)1000 void Vt102Emulation::focusGained(void)
1001 {
1002 if (_reportFocusEvents)
1003 sendString("\033[I");
1004 }
1005
sendText(const QString & text)1006 void Vt102Emulation::sendText( const QString& text )
1007 {
1008 if (!text.isEmpty())
1009 {
1010 QKeyEvent event(QEvent::KeyPress,
1011 0,
1012 Qt::NoModifier,
1013 text);
1014 sendKeyEvent(&event); // expose as a big fat keypress event
1015 }
1016 }
1017
remapKeyModifiersForMac(QKeyEvent * event)1018 QKeyEvent * Vt102Emulation::remapKeyModifiersForMac(QKeyEvent *event) {
1019 Qt::KeyboardModifiers modifiers = event->modifiers();
1020
1021 QFlags<Qt::KeyboardModifier> isTheLabeledKeyCommandPressed = modifiers & Qt::ControlModifier;
1022 QFlags<Qt::KeyboardModifier> isTheLabeledKeyControlPressed = modifiers & Qt::MetaModifier;
1023 if (isTheLabeledKeyCommandPressed){
1024 qDebug("Command is pressed.");
1025 modifiers &= ~Qt::ControlModifier;
1026 modifiers |= Qt::MetaModifier;
1027 } else {
1028 modifiers &= ~Qt::MetaModifier;
1029 }
1030
1031 if (isTheLabeledKeyControlPressed) {
1032 qDebug("Control is pressed.");
1033 modifiers &= ~Qt::MetaModifier;
1034 modifiers |= Qt::ControlModifier;
1035 } else {
1036 modifiers &= ~Qt::ControlModifier;
1037 }
1038
1039 QString eventText = event->text();
1040 int eventKey = event->key();
1041 // disable dead key
1042 bool isAscii = true;
1043 switch (event->nativeVirtualKey()) {
1044 case kVK_ANSI_B:
1045 eventText = "b";
1046 eventKey = Qt::Key_B;
1047 break;
1048 case kVK_ANSI_C:
1049 eventText = "c";
1050 eventKey = Qt::Key_C;
1051 break;
1052 case kVK_ANSI_D:
1053 eventText = "d";
1054 eventKey = Qt::Key_D;
1055 break;
1056 case kVK_ANSI_E:
1057 eventText = "e";
1058 eventKey = Qt::Key_E;
1059 break;
1060 case kVK_ANSI_F:
1061 eventText = "f";
1062 eventKey = Qt::Key_F;
1063 break;
1064 case kVK_ANSI_G:
1065 eventText = "g";
1066 eventKey = Qt::Key_G;
1067 break;
1068 case kVK_ANSI_H:
1069 eventText = "h";
1070 eventKey = Qt::Key_H;
1071 break;
1072 case kVK_ANSI_I:
1073 eventText = "i";
1074 eventKey = Qt::Key_I;
1075 break;
1076 case kVK_ANSI_J:
1077 eventText = "j";
1078 eventKey = Qt::Key_J;
1079 break;
1080 case kVK_ANSI_K:
1081 eventText = "k";
1082 eventKey = Qt::Key_K;
1083 break;
1084 case kVK_ANSI_L:
1085 eventText = "l";
1086 eventKey = Qt::Key_L;
1087 break;
1088 case kVK_ANSI_M:
1089 eventText = "m";
1090 eventKey = Qt::Key_M;
1091 break;
1092 case kVK_ANSI_N:
1093 eventText = "n";
1094 eventKey = Qt::Key_N;
1095 break;
1096 case kVK_ANSI_O:
1097 eventText = "o";
1098 eventKey = Qt::Key_O;
1099 break;
1100 case kVK_ANSI_P:
1101 eventText = "p";
1102 eventKey = Qt::Key_P;
1103 break;
1104 case kVK_ANSI_Q:
1105 eventText = "q";
1106 eventKey = Qt::Key_Q;
1107 break;
1108 case kVK_ANSI_R:
1109 eventText = "r";
1110 eventKey = Qt::Key_R;
1111 break;
1112 case kVK_ANSI_S:
1113 eventText = "s";
1114 eventKey = Qt::Key_S;
1115 break;
1116 case kVK_ANSI_T:
1117 eventText = "t";
1118 eventKey = Qt::Key_T;
1119 break;
1120 case kVK_ANSI_U:
1121 eventText = "u";
1122 eventKey = Qt::Key_U;
1123 break;
1124 case kVK_ANSI_V:
1125 eventText = "v";
1126 eventKey = Qt::Key_V;
1127 break;
1128 case kVK_ANSI_W:
1129 eventText = "w";
1130 eventKey = Qt::Key_W;
1131 break;
1132 case kVK_ANSI_X:
1133 eventText = "x";
1134 eventKey = Qt::Key_X;
1135 break;
1136 case kVK_ANSI_Y:
1137 eventText = "y";
1138 eventKey = Qt::Key_Y;
1139 break;
1140 case kVK_ANSI_Z:
1141 eventText = "z";
1142 eventKey = Qt::Key_Z;
1143 break;
1144 default:
1145 isAscii = false;
1146 }
1147 // a's vk code is 0, a special case
1148 if (event->nativeVirtualKey() == kVK_ANSI_A && event->key() == Qt::Key_A) {
1149 eventText = "a";
1150 eventKey = Qt::Key_A;
1151 isAscii = true;
1152 }
1153 if (modifiers & Qt::ShiftModifier && isAscii) {
1154 eventText = eventText.toUpper();
1155 }
1156 return new QKeyEvent(QEvent::None, eventKey, modifiers,
1157 event->nativeScanCode(), event->nativeVirtualKey(), event->nativeModifiers(),
1158 eventText, event->isAutoRepeat(), event->count());
1159 }
1160
sendKeyEvent(QKeyEvent * origEvent)1161 void Vt102Emulation::sendKeyEvent( QKeyEvent* origEvent )
1162 {
1163 #if defined(Q_OS_MAC)
1164 QScopedPointer<QKeyEvent> event(remapKeyModifiersForMac(origEvent));
1165 #else
1166 QKeyEvent *event = origEvent;
1167 #endif
1168 Qt::KeyboardModifiers modifiers = event->modifiers();
1169 KeyboardTranslator::States states = KeyboardTranslator::NoState;
1170
1171 // get current states
1172 if (getMode(MODE_NewLine) ) states |= KeyboardTranslator::NewLineState;
1173 if (getMode(MODE_Ansi) ) states |= KeyboardTranslator::AnsiState;
1174 if (getMode(MODE_AppCuKeys)) states |= KeyboardTranslator::CursorKeysState;
1175 if (getMode(MODE_AppScreen)) states |= KeyboardTranslator::AlternateScreenState;
1176 if (getMode(MODE_AppKeyPad) && (modifiers & Qt::KeypadModifier))
1177 states |= KeyboardTranslator::ApplicationKeypadState;
1178
1179 // check flow control state
1180 if (modifiers & Qt::ControlModifier)
1181 {
1182 switch (event->key()) {
1183 case Qt::Key_S:
1184 emit flowControlKeyPressed(true);
1185 break;
1186 case Qt::Key_Q:
1187 case Qt::Key_C: // cancel flow control
1188 emit flowControlKeyPressed(false);
1189 break;
1190 }
1191 }
1192
1193 // lookup key binding
1194 if ( _keyTranslator )
1195 {
1196 KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
1197 event->key() ,
1198 modifiers,
1199 states );
1200 // send result to terminal
1201 QByteArray textToSend;
1202
1203 // special handling for the Alt (aka. Meta) modifier. pressing
1204 // Alt+[Character] results in Esc+[Character] being sent
1205 // (unless there is an entry defined for this particular combination
1206 // in the keyboard modifier)
1207
1208 bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;
1209 bool wantsMetaModifier = entry.modifiers() & entry.modifierMask() & Qt::MetaModifier;
1210 bool wantsAnyModifier = entry.state() &
1211 entry.stateMask() & KeyboardTranslator::AnyModifierState;
1212
1213 if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier)
1214 && !event->text().isEmpty() )
1215 {
1216 textToSend.prepend("\033");
1217 }
1218 if ( modifiers & Qt::MetaModifier && !(wantsMetaModifier || wantsAnyModifier)
1219 && !event->text().isEmpty() )
1220 {
1221 textToSend.prepend("\030@s");
1222 }
1223
1224 if ( entry.command() != KeyboardTranslator::NoCommand )
1225 {
1226 if (entry.command() & KeyboardTranslator::EraseCommand)
1227 textToSend += eraseChar();
1228
1229 // TODO command handling
1230 }
1231 else if ( !entry.text().isEmpty() )
1232 {
1233 textToSend += entry.text(true,modifiers);
1234 }
1235 else if((modifiers & Qt::ControlModifier) && event->key() >= 0x40 && event->key() < 0x5f) {
1236 textToSend += (event->key() & 0x1f);
1237 }
1238 else if(event->key() == Qt::Key_Tab) {
1239 textToSend += 0x09;
1240 }
1241 else if (event->key() == Qt::Key_PageUp) {
1242 textToSend += "\033[5~";
1243 }
1244 else if (event->key() == Qt::Key_PageDown) {
1245 textToSend += "\033[6~";
1246 }
1247 else {
1248 textToSend += _codec->fromUnicode(event->text());
1249 }
1250
1251 sendData( textToSend.constData() , textToSend.length() );
1252 }
1253 else
1254 {
1255 // print an error message to the terminal if no key translator has been
1256 // set
1257 QString translatorError = tr("No keyboard translator available. "
1258 "The information needed to convert key presses "
1259 "into characters to send to the terminal "
1260 "is missing.");
1261 reset();
1262 receiveData( translatorError.toUtf8().constData() , translatorError.count() );
1263 }
1264 }
1265
1266 /* ------------------------------------------------------------------------- */
1267 /* */
1268 /* VT100 Charsets */
1269 /* */
1270 /* ------------------------------------------------------------------------- */
1271
1272 // Character Set Conversion ------------------------------------------------ --
1273
1274 /*
1275 The processing contains a VT100 specific code translation layer.
1276 It's still in use and mainly responsible for the line drawing graphics.
1277
1278 These and some other glyphs are assigned to codes (0x5f-0xfe)
1279 normally occupied by the latin letters. Since this codes also
1280 appear within control sequences, the extra code conversion
1281 does not permute with the tokenizer and is placed behind it
1282 in the pipeline. It only applies to tokens, which represent
1283 plain characters.
1284
1285 This conversion it eventually continued in TerminalDisplay.C, since
1286 it might involve VT100 enhanced fonts, which have these
1287 particular glyphs allocated in (0x00-0x1f) in their code page.
1288 */
1289
1290 #define CHARSET _charset[_currentScreen==_screen[1]]
1291
1292 // Apply current character map.
1293
applyCharset(wchar_t c)1294 wchar_t Vt102Emulation::applyCharset(wchar_t c)
1295 {
1296 if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
1297 if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
1298 return c;
1299 }
1300
1301 /*
1302 "Charset" related part of the emulation state.
1303 This configures the VT100 charset filter.
1304
1305 While most operation work on the current _screen,
1306 the following two are different.
1307 */
1308
resetCharset(int scrno)1309 void Vt102Emulation::resetCharset(int scrno)
1310 {
1311 _charset[scrno].cu_cs = 0;
1312 qstrncpy(_charset[scrno].charset,"BBBB",4);
1313 _charset[scrno].sa_graphic = false;
1314 _charset[scrno].sa_pound = false;
1315 _charset[scrno].graphic = false;
1316 _charset[scrno].pound = false;
1317 }
1318
setCharset(int n,int cs)1319 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
1320 {
1321 _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);
1322 _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);
1323 }
1324
setAndUseCharset(int n,int cs)1325 void Vt102Emulation::setAndUseCharset(int n, int cs)
1326 {
1327 CHARSET.charset[n&3] = cs;
1328 useCharset(n&3);
1329 }
1330
useCharset(int n)1331 void Vt102Emulation::useCharset(int n)
1332 {
1333 CHARSET.cu_cs = n&3;
1334 CHARSET.graphic = (CHARSET.charset[n&3] == '0');
1335 CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
1336 }
1337
setDefaultMargins()1338 void Vt102Emulation::setDefaultMargins()
1339 {
1340 _screen[0]->setDefaultMargins();
1341 _screen[1]->setDefaultMargins();
1342 }
1343
setMargins(int t,int b)1344 void Vt102Emulation::setMargins(int t, int b)
1345 {
1346 _screen[0]->setMargins(t, b);
1347 _screen[1]->setMargins(t, b);
1348 }
1349
saveCursor()1350 void Vt102Emulation::saveCursor()
1351 {
1352 CHARSET.sa_graphic = CHARSET.graphic;
1353 CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
1354 // we are not clear about these
1355 //sa_charset = charsets[cScreen->_charset];
1356 //sa_charset_num = cScreen->_charset;
1357 _currentScreen->saveCursor();
1358 }
1359
restoreCursor()1360 void Vt102Emulation::restoreCursor()
1361 {
1362 CHARSET.graphic = CHARSET.sa_graphic;
1363 CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
1364 _currentScreen->restoreCursor();
1365 }
1366
1367 /* ------------------------------------------------------------------------- */
1368 /* */
1369 /* Mode Operations */
1370 /* */
1371 /* ------------------------------------------------------------------------- */
1372
1373 /*
1374 Some of the emulations state is either added to the state of the screens.
1375
1376 This causes some scoping problems, since different emulations choose to
1377 located the mode either to the current _screen or to both.
1378
1379 For strange reasons, the extend of the rendition attributes ranges over
1380 all screens and not over the actual _screen.
1381
1382 We decided on the precise precise extend, somehow.
1383 */
1384
1385 // "Mode" related part of the state. These are all booleans.
1386
resetModes()1387 void Vt102Emulation::resetModes()
1388 {
1389 // MODE_Allow132Columns is not reset here
1390 // to match Xterm's behaviour (see Xterm's VTReset() function)
1391
1392 resetMode(MODE_132Columns); saveMode(MODE_132Columns);
1393 resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
1394 resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001);
1395 resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002);
1396 resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003);
1397 resetMode(MODE_Mouse1005); saveMode(MODE_Mouse1005);
1398 resetMode(MODE_Mouse1006); saveMode(MODE_Mouse1006);
1399 resetMode(MODE_Mouse1015); saveMode(MODE_Mouse1015);
1400 resetMode(MODE_BracketedPaste); saveMode(MODE_BracketedPaste);
1401
1402 resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
1403 resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
1404 resetMode(MODE_AppKeyPad); saveMode(MODE_AppKeyPad);
1405 resetMode(MODE_NewLine);
1406 setMode(MODE_Ansi);
1407 }
1408
setMode(int m)1409 void Vt102Emulation::setMode(int m)
1410 {
1411 _currentModes.mode[m] = true;
1412 switch (m)
1413 {
1414 case MODE_132Columns:
1415 if (getMode(MODE_Allow132Columns))
1416 clearScreenAndSetColumns(132);
1417 else
1418 _currentModes.mode[m] = false;
1419 break;
1420 case MODE_Mouse1000:
1421 case MODE_Mouse1001:
1422 case MODE_Mouse1002:
1423 case MODE_Mouse1003:
1424 emit programUsesMouseChanged(false);
1425 break;
1426
1427 case MODE_BracketedPaste:
1428 emit programBracketedPasteModeChanged(true);
1429
1430 break;
1431
1432 case MODE_AppScreen : _screen[1]->clearSelection();
1433 setScreen(1);
1434 break;
1435 }
1436 if (m < MODES_SCREEN || m == MODE_NewLine)
1437 {
1438 _screen[0]->setMode(m);
1439 _screen[1]->setMode(m);
1440 }
1441 }
1442
resetMode(int m)1443 void Vt102Emulation::resetMode(int m)
1444 {
1445 _currentModes.mode[m] = false;
1446 switch (m)
1447 {
1448 case MODE_132Columns:
1449 if (getMode(MODE_Allow132Columns))
1450 clearScreenAndSetColumns(80);
1451 break;
1452 case MODE_Mouse1000 :
1453 case MODE_Mouse1001 :
1454 case MODE_Mouse1002 :
1455 case MODE_Mouse1003 :
1456 emit programUsesMouseChanged(true);
1457 break;
1458
1459 case MODE_BracketedPaste:
1460 emit programBracketedPasteModeChanged(false);
1461 break;
1462
1463 case MODE_AppScreen :
1464 _screen[0]->clearSelection();
1465 setScreen(0);
1466 break;
1467 }
1468 if (m < MODES_SCREEN || m == MODE_NewLine)
1469 {
1470 _screen[0]->resetMode(m);
1471 _screen[1]->resetMode(m);
1472 }
1473 }
1474
saveMode(int m)1475 void Vt102Emulation::saveMode(int m)
1476 {
1477 _savedModes.mode[m] = _currentModes.mode[m];
1478 }
1479
restoreMode(int m)1480 void Vt102Emulation::restoreMode(int m)
1481 {
1482 if (_savedModes.mode[m])
1483 setMode(m);
1484 else
1485 resetMode(m);
1486 }
1487
getMode(int m)1488 bool Vt102Emulation::getMode(int m)
1489 {
1490 return _currentModes.mode[m];
1491 }
1492
eraseChar() const1493 char Vt102Emulation::eraseChar() const
1494 {
1495 KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
1496 Qt::Key_Backspace,
1497 0,
1498 0);
1499 if ( entry.text().count() > 0 )
1500 return entry.text().at(0);
1501 else
1502 return '\b';
1503 }
1504
1505 // print contents of the scan buffer
hexdump(wchar_t * s,int len)1506 static void hexdump(wchar_t* s, int len)
1507 { int i;
1508 for (i = 0; i < len; i++)
1509 {
1510 if (s[i] == '\\')
1511 printf("\\\\");
1512 else
1513 if ((s[i]) > 32 && s[i] < 127)
1514 printf("%c",s[i]);
1515 else
1516 printf("\\%04x(hex)",s[i]);
1517 }
1518 }
1519
reportDecodingError()1520 void Vt102Emulation::reportDecodingError()
1521 {
1522 if (tokenBufferPos == 0 || ( tokenBufferPos == 1 && (tokenBuffer[0] & 0xff) >= 32) )
1523 return;
1524 printf("Undecodable sequence: ");
1525 hexdump(tokenBuffer,tokenBufferPos);
1526 printf("\n");
1527 }
1528
1529 //#include "Vt102Emulation.moc"
1530
1531