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