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