File indexing completed on 2025-01-19 04:23:33

0001 /*
0002     This file is part of Konsole, an X terminal.
0003 
0004     Copyright 2007-2008 by Robert Knight <robert.knight@gmail.com>
0005     Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
0006 
0007     This program is free software; you can redistribute it and/or modify
0008     it under the terms of the GNU General Public License as published by
0009     the Free Software Foundation; either version 2 of the License, or
0010     (at your option) any later version.
0011 
0012     This program is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015     GNU General Public License for more details.
0016 
0017     You should have received a copy of the GNU General Public License
0018     along with this program; if not, write to the Free Software
0019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0020     02110-1301  USA.
0021 */
0022 
0023 // Own
0024 #include "Vt102Emulation.h"
0025 #include "mac-vkcode.h"
0026 
0027 // XKB
0028 //#include <config-konsole.h>
0029 
0030 // this allows konsole to be compiled without XKB and XTEST extensions
0031 // even though it might be available on a particular system.
0032 #if defined(AVOID_XKB)
0033     #undef HAVE_XKB
0034 #endif
0035 
0036 #if defined(HAVE_XKB)
0037     void scrolllock_set_off();
0038     void scrolllock_set_on();
0039 #endif
0040 
0041 // Standard
0042 #include <stdio.h>
0043 #include <unistd.h>
0044 
0045 // Qt
0046 #include <QEvent>
0047 #include <QKeyEvent>
0048 #include <QByteRef>
0049 
0050 // KDE
0051 //#include <kdebug.h>
0052 //#include <klocale.h>
0053 
0054 // Konsole
0055 #include "KeyboardTranslator.h"
0056 #include "Screen.h"
0057 
0058 
0059 using namespace Konsole;
0060 
0061 Vt102Emulation::Vt102Emulation()
0062     : Emulation(),
0063      prevCC(0),
0064      _titleUpdateTimer(new QTimer(this)),
0065      _reportFocusEvents(false)
0066 {
0067   _titleUpdateTimer->setSingleShot(true);
0068   QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));
0069 
0070   initTokenizer();
0071   reset();
0072 }
0073 
0074 Vt102Emulation::~Vt102Emulation()
0075 {}
0076 
0077 void Vt102Emulation::clearEntireScreen()
0078 {
0079   _currentScreen->clearEntireScreen();
0080   bufferedUpdate();
0081 }
0082 
0083 void Vt102Emulation::reset()
0084 {
0085   resetTokenizer();
0086   resetModes();
0087   resetCharset(0);
0088   _screen[0]->reset();
0089   resetCharset(1);
0090   _screen[1]->reset();
0091   setCodec(LocaleCodec);
0092 
0093   bufferedUpdate();
0094 }
0095 
0096 /* ------------------------------------------------------------------------- */
0097 /*                                                                           */
0098 /*                     Processing the incoming byte stream                   */
0099 /*                                                                           */
0100 /* ------------------------------------------------------------------------- */
0101 
0102 /* Incoming Bytes Event pipeline
0103 
0104    This section deals with decoding the incoming character stream.
0105    Decoding means here, that the stream is first separated into `tokens'
0106    which are then mapped to a `meaning' provided as operations by the
0107    `Screen' class or by the emulation class itself.
0108 
0109    The pipeline proceeds as follows:
0110 
0111    - Tokenizing the ESC codes (onReceiveChar)
0112    - VT100 code page translation of plain characters (applyCharset)
0113    - Interpretation of ESC codes (processToken)
0114 
0115    The escape codes and their meaning are described in the
0116    technical reference of this program.
0117 */
0118 
0119 // Tokens ------------------------------------------------------------------ --
0120 
0121 /*
0122    Since the tokens are the central notion if this section, we've put them
0123    in front. They provide the syntactical elements used to represent the
0124    terminals operations as byte sequences.
0125 
0126    They are encodes here into a single machine word, so that we can later
0127    switch over them easily. Depending on the token itself, additional
0128    argument variables are filled with parameter values.
0129 
0130    The tokens are defined below:
0131 
0132    - CHR        - Printable characters     (32..255 but DEL (=127))
0133    - CTL        - Control characters       (0..31 but ESC (= 27), DEL)
0134    - ESC        - Escape codes of the form <ESC><CHR but `[]()+*#'>
0135    - ESC_DE     - Escape codes of the form <ESC><any of `()+*#%'> C
0136    - CSI_PN     - Escape codes of the form <ESC>'['     {Pn} ';' {Pn} C
0137    - CSI_PS     - Escape codes of the form <ESC>'['     {Pn} ';' ...  C
0138    - CSI_PS_SP  - Escape codes of the form <ESC>'['     {Pn} ';' ... {Space} C
0139    - CSI_PR     - Escape codes of the form <ESC>'[' '?' {Pn} ';' ...  C
0140    - CSI_PE     - Escape codes of the form <ESC>'[' '!' {Pn} ';' ...  C
0141    - VT52       - VT52 escape codes
0142                   - <ESC><Chr>
0143                   - <ESC>'Y'{Pc}{Pc}
0144    - XTE_HA     - Xterm window/terminal attribute commands
0145                   of the form <ESC>`]' {Pn} `;' {Text} <BEL>
0146                   (Note that these are handled differently to the other formats)
0147 
0148    The last two forms allow list of arguments. Since the elements of
0149    the lists are treated individually the same way, they are passed
0150    as individual tokens to the interpretation. Further, because the
0151    meaning of the parameters are names (althought represented as numbers),
0152    they are includes within the token ('N').
0153 
0154 */
0155 
0156 #define TY_CONSTRUCT(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
0157 
0158 #define TY_CHR(   )     TY_CONSTRUCT(0,0,0)
0159 #define TY_CTL(A  )     TY_CONSTRUCT(1,A,0)
0160 #define TY_ESC(A  )     TY_CONSTRUCT(2,A,0)
0161 #define TY_ESC_CS(A,B)  TY_CONSTRUCT(3,A,B)
0162 #define TY_ESC_DE(A  )  TY_CONSTRUCT(4,A,0)
0163 #define TY_CSI_PS(A,N)  TY_CONSTRUCT(5,A,N)
0164 #define TY_CSI_PN(A  )  TY_CONSTRUCT(6,A,0)
0165 #define TY_CSI_PR(A,N)  TY_CONSTRUCT(7,A,N)
0166 #define TY_CSI_PS_SP(A,N)  TY_CONSTRUCT(11,A,N)
0167 
0168 #define TY_VT52(A)    TY_CONSTRUCT(8,A,0)
0169 #define TY_CSI_PG(A)  TY_CONSTRUCT(9,A,0)
0170 #define TY_CSI_PE(A)  TY_CONSTRUCT(10,A,0)
0171 
0172 #define MAX_ARGUMENT 4096
0173 
0174 // Tokenizer --------------------------------------------------------------- --
0175 
0176 /* The tokenizer's state
0177 
0178    The state is represented by the buffer (tokenBuffer, tokenBufferPos),
0179    and accompanied by decoded arguments kept in (argv,argc).
0180    Note that they are kept internal in the tokenizer.
0181 */
0182 
0183 void Vt102Emulation::resetTokenizer()
0184 {
0185   tokenBufferPos = 0;
0186   argc = 0;
0187   argv[0] = 0;
0188   argv[1] = 0;
0189   prevCC = 0;
0190 }
0191 
0192 void Vt102Emulation::addDigit(int digit)
0193 {
0194   if (argv[argc] < MAX_ARGUMENT)
0195       argv[argc] = 10*argv[argc] + digit;
0196 }
0197 
0198 void Vt102Emulation::addArgument()
0199 {
0200   argc = qMin(argc+1,MAXARGS-1);
0201   argv[argc] = 0;
0202 }
0203 
0204 void Vt102Emulation::addToCurrentToken(wchar_t cc)
0205 {
0206   tokenBuffer[tokenBufferPos] = cc;
0207   tokenBufferPos = qMin(tokenBufferPos+1,MAX_TOKEN_LENGTH-1);
0208 }
0209 
0210 // Character Class flags used while decoding
0211 #define CTL  1  // Control character
0212 #define CHR  2  // Printable character
0213 #define CPN  4  // TODO: Document me
0214 #define DIG  8  // Digit
0215 #define SCS 16  // TODO: Document me
0216 #define GRP 32  // TODO: Document me
0217 #define CPS 64  // Character which indicates end of window resize
0218                 // escape sequence '\e[8;<row>;<col>t'
0219 
0220 void Vt102Emulation::initTokenizer()
0221 {
0222   int i;
0223   quint8* s;
0224   for(i = 0;i < 256; ++i)
0225     charClass[i] = 0;
0226   for(i = 0;i < 32; ++i)
0227     charClass[i] |= CTL;
0228   for(i = 32;i < 256; ++i)
0229     charClass[i] |= CHR;
0230   for(s = (quint8*)"@ABCDGHILMPSTXZbcdfry"; *s; ++s)
0231     charClass[*s] |= CPN;
0232   // resize = \e[8;<row>;<col>t
0233   for(s = (quint8*)"t"; *s; ++s)
0234     charClass[*s] |= CPS;
0235   for(s = (quint8*)"0123456789"; *s; ++s)
0236     charClass[*s] |= DIG;
0237   for(s = (quint8*)"()+*%"; *s; ++s)
0238     charClass[*s] |= SCS;
0239   for(s = (quint8*)"()+*#[]%"; *s; ++s)
0240     charClass[*s] |= GRP;
0241 
0242   resetTokenizer();
0243 }
0244 
0245 /* Ok, here comes the nasty part of the decoder.
0246 
0247    Instead of keeping an explicit state, we deduce it from the
0248    token scanned so far. It is then immediately combined with
0249    the current character to form a scanning decision.
0250 
0251    This is done by the following defines.
0252 
0253    - P is the length of the token scanned so far.
0254    - L (often P-1) is the position on which contents we base a decision.
0255    - C is a character or a group of characters (taken from 'charClass').
0256 
0257    - 'cc' is the current character
0258    - 's' is a pointer to the start of the token buffer
0259    - 'p' is the current position within the token buffer
0260 
0261    Note that they need to applied in proper order.
0262 */
0263 
0264 #define lec(P,L,C) (p == (P) && s[(L)] == (C))
0265 #define lun(     ) (p ==  1  && cc >= 32 )
0266 #define les(P,L,C) (p == (P) && s[L] < 256 && (charClass[s[(L)]] & (C)) == (C))
0267 #define eec(C)     (p >=  3  && cc == (C))
0268 #define ees(C)     (p >=  3  && cc < 256 && (charClass[cc] & (C)) == (C))
0269 #define eps(C)     (p >=  3  && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (charClass[cc] & (C)) == (C))
0270 #define epp( )     (p >=  3  && s[2] == '?')
0271 #define epe( )     (p >=  3  && s[2] == '!')
0272 #define egt( )     (p >=  3  && s[2] == '>')
0273 #define esp( )     (p ==  4  && s[3] == ' ')
0274 #define Xpe        (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
0275 #define Xte        (Xpe      && (cc ==  7 || (prevCC == 27 && cc == 92) )) // 27, 92 => "\e\\" (ST, String Terminator)
0276 #define ces(C)     (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
0277 
0278 #define CNTL(c) ((c)-'@')
0279 #define ESC 27
0280 #define DEL 127
0281 
0282 // process an incoming unicode character
0283 void Vt102Emulation::receiveChar(wchar_t cc)
0284 {
0285   if (cc == DEL)
0286     return; //VT100: ignore.
0287 
0288   if (ces(CTL))
0289   {
0290     // ignore control characters in the text part of Xpe (aka OSC) "ESC]"
0291     // escape sequences; this matches what XTERM docs say
0292     if (Xpe) {
0293         prevCC = cc;
0294         return;
0295     }
0296 
0297     // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
0298     // This means, they do neither a resetTokenizer() nor a pushToToken(). Some of them, do
0299     // of course. Guess this originates from a weakly layered handling of the X-on
0300     // X-off protocol, which comes really below this level.
0301     if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC)
0302         resetTokenizer(); //VT100: CAN or SUB
0303     if (cc != ESC)
0304     {
0305         processToken(TY_CTL(cc+'@' ),0,0);
0306         return;
0307     }
0308   }
0309   // advance the state
0310   addToCurrentToken(cc);
0311 
0312   wchar_t* s = tokenBuffer;
0313   int  p = tokenBufferPos;
0314 
0315   if (getMode(MODE_Ansi))
0316   {
0317     if (lec(1,0,ESC)) { return; }
0318     if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('['); return; }
0319     if (les(2,1,GRP)) { return; }
0320     if (Xte         ) { processWindowAttributeChange(); resetTokenizer(); return; }
0321     if (Xpe         ) { prevCC = cc; return; }
0322     if (lec(3,2,'?')) { return; }
0323     if (lec(3,2,'>')) { return; }
0324     if (lec(3,2,'!')) { return; }
0325     if (lun(       )) { processToken( TY_CHR(), applyCharset(cc), 0);   resetTokenizer(); return; }
0326     if (lec(2,0,ESC)) { processToken( TY_ESC(s[1]), 0, 0);              resetTokenizer(); return; }
0327     if (les(3,1,SCS)) { processToken( TY_ESC_CS(s[1],s[2]), 0, 0);      resetTokenizer(); return; }
0328     if (lec(3,1,'#')) { processToken( TY_ESC_DE(s[2]), 0, 0);           resetTokenizer(); return; }
0329     if (eps(    CPN)) { processToken( TY_CSI_PN(cc), argv[0],argv[1]);  resetTokenizer(); return; }
0330     if (esp(       )) { return; }
0331     if (lec(5, 4, 'q') && s[3] == ' ') {
0332       processToken( TY_CSI_PS_SP(cc, argv[0]), argv[0], 0);
0333       resetTokenizer();
0334       return;
0335     }
0336 
0337     // resize = \e[8;<row>;<col>t
0338     if (eps(CPS))
0339     {
0340         processToken( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]);
0341         resetTokenizer();
0342         return;
0343     }
0344 
0345     if (epe(   )) { processToken( TY_CSI_PE(cc), 0, 0); resetTokenizer(); return; }
0346     if (ees(DIG)) { addDigit(cc-'0'); return; }
0347     if (eec(';')) { addArgument();    return; }
0348     for (int i=0;i<=argc;i++)
0349     {
0350         if (epp())
0351             processToken( TY_CSI_PR(cc,argv[i]), 0, 0);
0352         else if (egt())
0353             processToken( TY_CSI_PG(cc), 0, 0); // spec. case for ESC]>0c or ESC]>c
0354         else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
0355         {
0356             // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
0357             i += 2;
0358             processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);
0359             i += 2;
0360         }
0361         else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)
0362         {
0363             // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
0364             i += 2;
0365             processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_256, argv[i]);
0366         }
0367         else
0368             processToken( TY_CSI_PS(cc,argv[i]), 0, 0);
0369     }
0370     resetTokenizer();
0371   }
0372   else
0373   {
0374     // VT52 Mode
0375     if (lec(1,0,ESC))
0376         return;
0377     if (les(1,0,CHR))
0378     {
0379         processToken( TY_CHR(), s[0], 0);
0380         resetTokenizer();
0381         return;
0382     }
0383     if (lec(2,1,'Y'))
0384         return;
0385 
0386     if (lec(3,1,'Y'))
0387         return;
0388 
0389     if (p < 4)
0390     {
0391         processToken( TY_VT52(s[1] ), 0, 0);
0392         resetTokenizer();
0393         return;
0394     }
0395     processToken( TY_VT52(s[1]), s[2], s[3]);
0396     resetTokenizer();
0397     return;
0398   }
0399 }
0400 void Vt102Emulation::processWindowAttributeChange()
0401 {
0402   // Describes the window or terminal session attribute to change
0403   // See Session::UserTitleChange for possible values
0404   int attributeToChange = 0;
0405   int i;
0406   for (i = 2; i < tokenBufferPos     &&
0407               tokenBuffer[i] >= '0'  &&
0408               tokenBuffer[i] <= '9'; i++)
0409   {
0410     attributeToChange = 10 * attributeToChange + (tokenBuffer[i]-'0');
0411   }
0412 
0413   if (tokenBuffer[i] != ';')
0414   {
0415     reportDecodingError();
0416     return;
0417   }
0418 
0419   QString newValue;
0420   newValue.reserve(tokenBufferPos-i-2);
0421   for (int j = 0; j < tokenBufferPos-i-2; j++)
0422     newValue[j] = tokenBuffer[i+1+j];
0423 
0424   _pendingTitleUpdates[attributeToChange] = newValue;
0425   _titleUpdateTimer->start(20);
0426 }
0427 
0428 void Vt102Emulation::updateTitle()
0429 {
0430     QListIterator<int> iter( _pendingTitleUpdates.keys() );
0431     while (iter.hasNext()) {
0432         int arg = iter.next();
0433         Q_EMIT titleChanged( arg , _pendingTitleUpdates[arg] );
0434     }
0435     _pendingTitleUpdates.clear();
0436 }
0437 
0438 // Interpreting Codes ---------------------------------------------------------
0439 
0440 /*
0441    Now that the incoming character stream is properly tokenized,
0442    meaning is assigned to them. These are either operations of
0443    the current _screen, or of the emulation class itself.
0444 
0445    The token to be interpreteted comes in as a machine word
0446    possibly accompanied by two parameters.
0447 
0448    Likewise, the operations assigned to, come with up to two
0449    arguments. One could consider to make up a proper table
0450    from the function below.
0451 
0452    The technical reference manual provides more information
0453    about this mapping.
0454 */
0455 
0456 void Vt102Emulation::processToken(int token, wchar_t p, int q)
0457 {
0458   switch (token)
0459   {
0460 
0461     case TY_CHR(         ) : _currentScreen->displayCharacter     (p         ); break; //UTF16
0462 
0463     //             127 DEL    : ignored on input
0464 
0465     case TY_CTL('@'      ) : /* NUL: ignored                      */ break;
0466     case TY_CTL('A'      ) : /* SOH: ignored                      */ break;
0467     case TY_CTL('B'      ) : /* STX: ignored                      */ break;
0468     case TY_CTL('C'      ) : /* ETX: ignored                      */ break;
0469     case TY_CTL('D'      ) : /* EOT: ignored                      */ break;
0470     case TY_CTL('E'      ) :      reportAnswerBack     (          ); break; //VT100
0471     case TY_CTL('F'      ) : /* ACK: ignored                      */ break;
0472     case TY_CTL('G'      ) : Q_EMIT stateSet(NOTIFYBELL);
0473                                 break; //VT100
0474     case TY_CTL('H'      ) : _currentScreen->backspace            (          ); break; //VT100
0475     case TY_CTL('I'      ) : _currentScreen->tab                  (          ); break; //VT100
0476     case TY_CTL('J'      ) : _currentScreen->newLine              (          ); break; //VT100
0477     case TY_CTL('K'      ) : _currentScreen->newLine              (          ); break; //VT100
0478     case TY_CTL('L'      ) : _currentScreen->newLine              (          ); break; //VT100
0479     case TY_CTL('M'      ) : _currentScreen->toStartOfLine        (          ); break; //VT100
0480 
0481     case TY_CTL('N'      ) :      useCharset           (         1); break; //VT100
0482     case TY_CTL('O'      ) :      useCharset           (         0); break; //VT100
0483 
0484     case TY_CTL('P'      ) : /* DLE: ignored                      */ break;
0485     case TY_CTL('Q'      ) : /* DC1: XON continue                 */ break; //VT100
0486     case TY_CTL('R'      ) : /* DC2: ignored                      */ break;
0487     case TY_CTL('S'      ) : /* DC3: XOFF halt                    */ break; //VT100
0488     case TY_CTL('T'      ) : /* DC4: ignored                      */ break;
0489     case TY_CTL('U'      ) : /* NAK: ignored                      */ break;
0490     case TY_CTL('V'      ) : /* SYN: ignored                      */ break;
0491     case TY_CTL('W'      ) : /* ETB: ignored                      */ break;
0492     case TY_CTL('X'      ) : _currentScreen->displayCharacter     (    0x2592); break; //VT100
0493     case TY_CTL('Y'      ) : /* EM : ignored                      */ break;
0494     case TY_CTL('Z'      ) : _currentScreen->displayCharacter     (    0x2592); break; //VT100
0495     case TY_CTL('['      ) : /* ESC: cannot be seen here.         */ break;
0496     case TY_CTL('\\'     ) : /* FS : ignored                      */ break;
0497     case TY_CTL(']'      ) : /* GS : ignored                      */ break;
0498     case TY_CTL('^'      ) : /* RS : ignored                      */ break;
0499     case TY_CTL('_'      ) : /* US : ignored                      */ break;
0500 
0501     case TY_ESC('D'      ) : _currentScreen->index                (          ); break; //VT100
0502     case TY_ESC('E'      ) : _currentScreen->nextLine             (          ); break; //VT100
0503     case TY_ESC('H'      ) : _currentScreen->changeTabStop        (true      ); break; //VT100
0504     case TY_ESC('M'      ) : _currentScreen->reverseIndex         (          ); break; //VT100
0505     case TY_ESC('Z'      ) :      reportTerminalType   (          ); break;
0506     case TY_ESC('c'      ) :      reset                (          ); break;
0507 
0508     case TY_ESC('n'      ) :      useCharset           (         2); break;
0509     case TY_ESC('o'      ) :      useCharset           (         3); break;
0510     case TY_ESC('7'      ) :      saveCursor           (          ); break;
0511     case TY_ESC('8'      ) :      restoreCursor        (          ); break;
0512 
0513     case TY_ESC('='      ) :          setMode      (MODE_AppKeyPad); break;
0514     case TY_ESC('>'      ) :        resetMode      (MODE_AppKeyPad); break;
0515     case TY_ESC('<'      ) :          setMode      (MODE_Ansi     ); break; //VT100
0516 
0517     case TY_ESC_CS('(', '0') :      setCharset           (0,    '0'); break; //VT100
0518     case TY_ESC_CS('(', 'A') :      setCharset           (0,    'A'); break; //VT100
0519     case TY_ESC_CS('(', 'B') :      setCharset           (0,    'B'); break; //VT100
0520 
0521     case TY_ESC_CS(')', '0') :      setCharset           (1,    '0'); break; //VT100
0522     case TY_ESC_CS(')', 'A') :      setCharset           (1,    'A'); break; //VT100
0523     case TY_ESC_CS(')', 'B') :      setCharset           (1,    'B'); break; //VT100
0524 
0525     case TY_ESC_CS('*', '0') :      setCharset           (2,    '0'); break; //VT100
0526     case TY_ESC_CS('*', 'A') :      setCharset           (2,    'A'); break; //VT100
0527     case TY_ESC_CS('*', 'B') :      setCharset           (2,    'B'); break; //VT100
0528 
0529     case TY_ESC_CS('+', '0') :      setCharset           (3,    '0'); break; //VT100
0530     case TY_ESC_CS('+', 'A') :      setCharset           (3,    'A'); break; //VT100
0531     case TY_ESC_CS('+', 'B') :      setCharset           (3,    'B'); break; //VT100
0532 
0533     case TY_ESC_CS('%', 'G') :      setCodec             (Utf8Codec   ); break; //LINUX
0534     case TY_ESC_CS('%', '@') :      setCodec             (LocaleCodec ); break; //LINUX
0535 
0536     case TY_ESC_DE('3'      ) : /* Double height line, top half    */
0537                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
0538                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
0539                                     break;
0540     case TY_ESC_DE('4'      ) : /* Double height line, bottom half */
0541                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
0542                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
0543                                     break;
0544     case TY_ESC_DE('5'      ) : /* Single width, single height line*/
0545                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
0546                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
0547                                 break;
0548     case TY_ESC_DE('6'      ) : /* Double width, single height line*/
0549                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);
0550                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
0551                                 break;
0552     case TY_ESC_DE('8'      ) : _currentScreen->helpAlign            (          ); break;
0553 
0554 // resize = \e[8;<row>;<col>t
0555     case TY_CSI_PS('t',   8) : setImageSize( p /*lines */, q /* columns */ );
0556                                Q_EMIT imageResizeRequest(QSize(q, p));
0557                                break;
0558 
0559 // change tab text color : \e[28;<color>t  color: 0-16,777,215
0560     case TY_CSI_PS('t',   28) : Q_EMIT changeTabTextColorRequest      ( p        );          break;
0561 
0562     case TY_CSI_PS('K',   0) : _currentScreen->clearToEndOfLine     (          ); break;
0563     case TY_CSI_PS('K',   1) : _currentScreen->clearToBeginOfLine   (          ); break;
0564     case TY_CSI_PS('K',   2) : _currentScreen->clearEntireLine      (          ); break;
0565     case TY_CSI_PS('J',   0) : _currentScreen->clearToEndOfScreen   (          ); break;
0566     case TY_CSI_PS('J',   1) : _currentScreen->clearToBeginOfScreen (          ); break;
0567     case TY_CSI_PS('J',   2) : _currentScreen->clearEntireScreen    (          ); break;
0568     case TY_CSI_PS('J',      3) : clearHistory();                            break;
0569     case TY_CSI_PS('g',   0) : _currentScreen->changeTabStop        (false     ); break; //VT100
0570     case TY_CSI_PS('g',   3) : _currentScreen->clearTabStops        (          ); break; //VT100
0571     case TY_CSI_PS('h',   4) : _currentScreen->    setMode      (MODE_Insert   ); break;
0572     case TY_CSI_PS('h',  20) :          setMode      (MODE_NewLine  ); break;
0573     case TY_CSI_PS('i',   0) : /* IGNORE: attached printer          */ break; //VT100
0574     case TY_CSI_PS('l',   4) : _currentScreen->  resetMode      (MODE_Insert   ); break;
0575     case TY_CSI_PS('l',  20) :        resetMode      (MODE_NewLine  ); break;
0576     case TY_CSI_PS('s',   0) :      saveCursor           (          ); break;
0577     case TY_CSI_PS('u',   0) :      restoreCursor        (          ); break;
0578 
0579     case TY_CSI_PS('m',   0) : _currentScreen->setDefaultRendition  (          ); break;
0580     case TY_CSI_PS('m',   1) : _currentScreen->  setRendition     (RE_BOLD     ); break; //VT100
0581     case TY_CSI_PS('m',   2) : _currentScreen->  setRendition     (RE_FAINT    ); break;
0582     case TY_CSI_PS('m',   3) : _currentScreen->  setRendition     (RE_ITALIC   ); break; //VT100
0583     case TY_CSI_PS('m',   4) : _currentScreen->  setRendition     (RE_UNDERLINE); break; //VT100
0584     case TY_CSI_PS('m',   5) : _currentScreen->  setRendition     (RE_BLINK    ); break; //VT100
0585     case TY_CSI_PS('m',   7) : _currentScreen->  setRendition     (RE_REVERSE  ); break;
0586     case TY_CSI_PS('m',   8) : _currentScreen->  setRendition     (RE_CONCEAL  ); break;
0587     case TY_CSI_PS('m',   9) : _currentScreen->  setRendition     (RE_STRIKEOUT); break;
0588     case TY_CSI_PS('m',  53) : _currentScreen->  setRendition     (RE_OVERLINE ); break;
0589     case TY_CSI_PS('m',  10) : /* IGNORED: mapping related          */ break; //LINUX
0590     case TY_CSI_PS('m',  11) : /* IGNORED: mapping related          */ break; //LINUX
0591     case TY_CSI_PS('m',  12) : /* IGNORED: mapping related          */ break; //LINUX
0592     case TY_CSI_PS('m',  21) : _currentScreen->resetRendition     (RE_BOLD     ); break;
0593     case TY_CSI_PS('m',  22) : _currentScreen->resetRendition     (RE_BOLD     );
0594                                _currentScreen->resetRendition     (RE_FAINT    ); break;
0595     case TY_CSI_PS('m',  23) : _currentScreen->resetRendition     (RE_ITALIC   ); break; //VT100
0596     case TY_CSI_PS('m',  24) : _currentScreen->resetRendition     (RE_UNDERLINE); break;
0597     case TY_CSI_PS('m',  25) : _currentScreen->resetRendition     (RE_BLINK    ); break;
0598     case TY_CSI_PS('m',  27) : _currentScreen->resetRendition     (RE_REVERSE  ); break;
0599     case TY_CSI_PS('m',  28) : _currentScreen->resetRendition     (RE_CONCEAL  ); break;
0600     case TY_CSI_PS('m',  29) : _currentScreen->resetRendition     (RE_STRIKEOUT); break;
0601     case TY_CSI_PS('m',  55) : _currentScreen->resetRendition     (RE_OVERLINE ); break;
0602 
0603     case TY_CSI_PS('m',   30) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  0); break;
0604     case TY_CSI_PS('m',   31) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  1); break;
0605     case TY_CSI_PS('m',   32) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  2); break;
0606     case TY_CSI_PS('m',   33) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  3); break;
0607     case TY_CSI_PS('m',   34) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  4); break;
0608     case TY_CSI_PS('m',   35) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  5); break;
0609     case TY_CSI_PS('m',   36) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  6); break;
0610     case TY_CSI_PS('m',   37) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  7); break;
0611 
0612     case TY_CSI_PS('m',   38) : _currentScreen->setForeColor         (p,       q); break;
0613 
0614     case TY_CSI_PS('m',   39) : _currentScreen->setForeColor         (COLOR_SPACE_DEFAULT,  0); break;
0615 
0616     case TY_CSI_PS('m',   40) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  0); break;
0617     case TY_CSI_PS('m',   41) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  1); break;
0618     case TY_CSI_PS('m',   42) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  2); break;
0619     case TY_CSI_PS('m',   43) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  3); break;
0620     case TY_CSI_PS('m',   44) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  4); break;
0621     case TY_CSI_PS('m',   45) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  5); break;
0622     case TY_CSI_PS('m',   46) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  6); break;
0623     case TY_CSI_PS('m',   47) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  7); break;
0624 
0625     case TY_CSI_PS('m',   48) : _currentScreen->setBackColor         (p,       q); break;
0626 
0627     case TY_CSI_PS('m',   49) : _currentScreen->setBackColor         (COLOR_SPACE_DEFAULT,  1); break;
0628 
0629     case TY_CSI_PS('m',   90) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  8); break;
0630     case TY_CSI_PS('m',   91) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  9); break;
0631     case TY_CSI_PS('m',   92) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 10); break;
0632     case TY_CSI_PS('m',   93) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 11); break;
0633     case TY_CSI_PS('m',   94) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 12); break;
0634     case TY_CSI_PS('m',   95) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 13); break;
0635     case TY_CSI_PS('m',   96) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 14); break;
0636     case TY_CSI_PS('m',   97) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 15); break;
0637 
0638     case TY_CSI_PS('m',  100) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  8); break;
0639     case TY_CSI_PS('m',  101) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  9); break;
0640     case TY_CSI_PS('m',  102) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 10); break;
0641     case TY_CSI_PS('m',  103) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 11); break;
0642     case TY_CSI_PS('m',  104) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 12); break;
0643     case TY_CSI_PS('m',  105) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 13); break;
0644     case TY_CSI_PS('m',  106) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 14); break;
0645     case TY_CSI_PS('m',  107) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 15); break;
0646 
0647     case TY_CSI_PS('n',   5) :      reportStatus         (          ); break;
0648     case TY_CSI_PS('n',   6) :      reportCursorPosition (          ); break;
0649     case TY_CSI_PS('q',   0) : /* IGNORED: LEDs off                 */ break; //VT100
0650     case TY_CSI_PS('q',   1) : /* IGNORED: LED1 on                  */ break; //VT100
0651     case TY_CSI_PS('q',   2) : /* IGNORED: LED2 on                  */ break; //VT100
0652     case TY_CSI_PS('q',   3) : /* IGNORED: LED3 on                  */ break; //VT100
0653     case TY_CSI_PS('q',   4) : /* IGNORED: LED4 on                  */ break; //VT100
0654     case TY_CSI_PS('x',   0) :      reportTerminalParms  (         2); break; //VT100
0655     case TY_CSI_PS('x',   1) :      reportTerminalParms  (         3); break; //VT100
0656 
0657     case TY_CSI_PS_SP('q',   0) : /* fall through */
0658     case TY_CSI_PS_SP('q',   1) : Q_EMIT cursorChanged(KeyboardCursorShape::BlockCursor,     true ); break;
0659     case TY_CSI_PS_SP('q',   2) : Q_EMIT cursorChanged(KeyboardCursorShape::BlockCursor,     false); break;
0660     case TY_CSI_PS_SP('q',   3) : Q_EMIT cursorChanged(KeyboardCursorShape::UnderlineCursor, true ); break;
0661     case TY_CSI_PS_SP('q',   4) : Q_EMIT cursorChanged(KeyboardCursorShape::UnderlineCursor, false); break;
0662     case TY_CSI_PS_SP('q',   5) : Q_EMIT cursorChanged(KeyboardCursorShape::IBeamCursor,     true ); break;
0663     case TY_CSI_PS_SP('q',   6) : Q_EMIT cursorChanged(KeyboardCursorShape::IBeamCursor,     false); break;
0664 
0665     case TY_CSI_PN('@'      ) : _currentScreen->insertChars          (p         ); break;
0666     case TY_CSI_PN('A'      ) : _currentScreen->cursorUp             (p         ); break; //VT100
0667     case TY_CSI_PN('B'      ) : _currentScreen->cursorDown           (p         ); break; //VT100
0668     case TY_CSI_PN('C'      ) : _currentScreen->cursorRight          (p         ); break; //VT100
0669     case TY_CSI_PN('D'      ) : _currentScreen->cursorLeft           (p         ); break; //VT100
0670     case TY_CSI_PN('E'      ) : /* Not implemented: cursor next p lines */         break; //VT100
0671     case TY_CSI_PN('F'      ) : /* Not implemented: cursor preceding p lines */    break; //VT100
0672     case TY_CSI_PN('G'      ) : _currentScreen->setCursorX           (p         ); break; //LINUX
0673     case TY_CSI_PN('H'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100
0674     case TY_CSI_PN('I'      ) : _currentScreen->tab                  (p         ); break;
0675     case TY_CSI_PN('L'      ) : _currentScreen->insertLines          (p         ); break;
0676     case TY_CSI_PN('M'      ) : _currentScreen->deleteLines          (p         ); break;
0677     case TY_CSI_PN('P'      ) : _currentScreen->deleteChars          (p         ); break;
0678     case TY_CSI_PN('S'      ) : _currentScreen->scrollUp             (p         ); break;
0679     case TY_CSI_PN('T'      ) : _currentScreen->scrollDown           (p         ); break;
0680     case TY_CSI_PN('X'      ) : _currentScreen->eraseChars           (p         ); break;
0681     case TY_CSI_PN('Z'      ) : _currentScreen->backtab              (p         ); break;
0682     case TY_CSI_PN('b'      ) : _currentScreen->repeatChars          (p         ); break;
0683     case TY_CSI_PN('c'      ) :      reportTerminalType   (          ); break; //VT100
0684     case TY_CSI_PN('d'      ) : _currentScreen->setCursorY           (p         ); break; //LINUX
0685     case TY_CSI_PN('f'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100
0686     case TY_CSI_PN('r'      ) :      setMargins           (p,      q); break; //VT100
0687     case TY_CSI_PN('y'      ) : /* IGNORED: Confidence test          */ break; //VT100
0688 
0689     case TY_CSI_PR('h',   1) :          setMode      (MODE_AppCuKeys); break; //VT100
0690     case TY_CSI_PR('l',   1) :        resetMode      (MODE_AppCuKeys); break; //VT100
0691     case TY_CSI_PR('s',   1) :         saveMode      (MODE_AppCuKeys); break; //FIXME
0692     case TY_CSI_PR('r',   1) :      restoreMode      (MODE_AppCuKeys); break; //FIXME
0693 
0694     case TY_CSI_PR('l',   2) :        resetMode      (MODE_Ansi     ); break; //VT100
0695 
0696     case TY_CSI_PR('h',   3) :          setMode      (MODE_132Columns);break; //VT100
0697     case TY_CSI_PR('l',   3) :        resetMode      (MODE_132Columns);break; //VT100
0698 
0699     case TY_CSI_PR('h',   4) : /* IGNORED: soft scrolling           */ break; //VT100
0700     case TY_CSI_PR('l',   4) : /* IGNORED: soft scrolling           */ break; //VT100
0701 
0702     case TY_CSI_PR('h',   5) : _currentScreen->    setMode      (MODE_Screen   ); break; //VT100
0703     case TY_CSI_PR('l',   5) : _currentScreen->  resetMode      (MODE_Screen   ); break; //VT100
0704 
0705     case TY_CSI_PR('h',   6) : _currentScreen->    setMode      (MODE_Origin   ); break; //VT100
0706     case TY_CSI_PR('l',   6) : _currentScreen->  resetMode      (MODE_Origin   ); break; //VT100
0707     case TY_CSI_PR('s',   6) : _currentScreen->   saveMode      (MODE_Origin   ); break; //FIXME
0708     case TY_CSI_PR('r',   6) : _currentScreen->restoreMode      (MODE_Origin   ); break; //FIXME
0709 
0710     case TY_CSI_PR('h',   7) : _currentScreen->    setMode      (MODE_Wrap     ); break; //VT100
0711     case TY_CSI_PR('l',   7) : _currentScreen->  resetMode      (MODE_Wrap     ); break; //VT100
0712     case TY_CSI_PR('s',   7) : _currentScreen->   saveMode      (MODE_Wrap     ); break; //FIXME
0713     case TY_CSI_PR('r',   7) : _currentScreen->restoreMode      (MODE_Wrap     ); break; //FIXME
0714 
0715     case TY_CSI_PR('h',   8) : /* IGNORED: autorepeat on            */ break; //VT100
0716     case TY_CSI_PR('l',   8) : /* IGNORED: autorepeat off           */ break; //VT100
0717     case TY_CSI_PR('s',   8) : /* IGNORED: autorepeat on            */ break; //VT100
0718     case TY_CSI_PR('r',   8) : /* IGNORED: autorepeat off           */ break; //VT100
0719 
0720     case TY_CSI_PR('h',   9) : /* IGNORED: interlace                */ break; //VT100
0721     case TY_CSI_PR('l',   9) : /* IGNORED: interlace                */ break; //VT100
0722     case TY_CSI_PR('s',   9) : /* IGNORED: interlace                */ break; //VT100
0723     case TY_CSI_PR('r',   9) : /* IGNORED: interlace                */ break; //VT100
0724 
0725     case TY_CSI_PR('h',  12) : /* IGNORED: Cursor blink             */ break; //att610
0726     case TY_CSI_PR('l',  12) : /* IGNORED: Cursor blink             */ break; //att610
0727     case TY_CSI_PR('s',  12) : /* IGNORED: Cursor blink             */ break; //att610
0728     case TY_CSI_PR('r',  12) : /* IGNORED: Cursor blink             */ break; //att610
0729 
0730     case TY_CSI_PR('h',  25) :          setMode      (MODE_Cursor   ); break; //VT100
0731     case TY_CSI_PR('l',  25) :        resetMode      (MODE_Cursor   ); break; //VT100
0732     case TY_CSI_PR('s',  25) :         saveMode      (MODE_Cursor   ); break; //VT100
0733     case TY_CSI_PR('r',  25) :      restoreMode      (MODE_Cursor   ); break; //VT100
0734 
0735     case TY_CSI_PR('h',  40) :         setMode(MODE_Allow132Columns ); break; // XTERM
0736     case TY_CSI_PR('l',  40) :       resetMode(MODE_Allow132Columns ); break; // XTERM
0737 
0738     case TY_CSI_PR('h',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
0739     case TY_CSI_PR('l',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
0740     case TY_CSI_PR('s',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
0741     case TY_CSI_PR('r',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
0742 
0743     case TY_CSI_PR('h',  47) :          setMode      (MODE_AppScreen); break; //VT100
0744     case TY_CSI_PR('l',  47) :        resetMode      (MODE_AppScreen); break; //VT100
0745     case TY_CSI_PR('s',  47) :         saveMode      (MODE_AppScreen); break; //XTERM
0746     case TY_CSI_PR('r',  47) :      restoreMode      (MODE_AppScreen); break; //XTERM
0747 
0748     case TY_CSI_PR('h',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
0749     case TY_CSI_PR('l',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
0750     case TY_CSI_PR('s',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
0751     case TY_CSI_PR('r',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
0752 
0753     // XTerm defines the following modes:
0754     // SET_VT200_MOUSE             1000
0755     // SET_VT200_HIGHLIGHT_MOUSE   1001
0756     // SET_BTN_EVENT_MOUSE         1002
0757     // SET_ANY_EVENT_MOUSE         1003
0758     //
0759 
0760     //Note about mouse modes:
0761     //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003
0762     //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).
0763     //TODO:  Implementation of mouse modes 1001 (something called hilight tracking) and
0764     //1003 (a slight variation on dragging the mouse)
0765     //
0766 
0767     case TY_CSI_PR('h', 1000) :          setMode      (MODE_Mouse1000); break; //XTERM
0768     case TY_CSI_PR('l', 1000) :        resetMode      (MODE_Mouse1000); break; //XTERM
0769     case TY_CSI_PR('s', 1000) :         saveMode      (MODE_Mouse1000); break; //XTERM
0770     case TY_CSI_PR('r', 1000) :      restoreMode      (MODE_Mouse1000); break; //XTERM
0771 
0772     case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
0773     case TY_CSI_PR('l', 1001) :        resetMode      (MODE_Mouse1001); break; //XTERM
0774     case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
0775     case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
0776 
0777     case TY_CSI_PR('h', 1002) :          setMode      (MODE_Mouse1002); break; //XTERM
0778     case TY_CSI_PR('l', 1002) :        resetMode      (MODE_Mouse1002); break; //XTERM
0779     case TY_CSI_PR('s', 1002) :         saveMode      (MODE_Mouse1002); break; //XTERM
0780     case TY_CSI_PR('r', 1002) :      restoreMode      (MODE_Mouse1002); break; //XTERM
0781 
0782     case TY_CSI_PR('h', 1003) :          setMode      (MODE_Mouse1003); break; //XTERM
0783     case TY_CSI_PR('l', 1003) :        resetMode      (MODE_Mouse1003); break; //XTERM
0784     case TY_CSI_PR('s', 1003) :         saveMode      (MODE_Mouse1003); break; //XTERM
0785     case TY_CSI_PR('r', 1003) :      restoreMode      (MODE_Mouse1003); break; //XTERM
0786 
0787     case TY_CSI_PR('h',  1004) : _reportFocusEvents = true; break;
0788     case TY_CSI_PR('l',  1004) : _reportFocusEvents = false; break;
0789 
0790     case TY_CSI_PR('h', 1005) :          setMode      (MODE_Mouse1005); break; //XTERM
0791     case TY_CSI_PR('l', 1005) :        resetMode      (MODE_Mouse1005); break; //XTERM
0792     case TY_CSI_PR('s', 1005) :         saveMode      (MODE_Mouse1005); break; //XTERM
0793     case TY_CSI_PR('r', 1005) :      restoreMode      (MODE_Mouse1005); break; //XTERM
0794 
0795     case TY_CSI_PR('h', 1006) :          setMode      (MODE_Mouse1006); break; //XTERM
0796     case TY_CSI_PR('l', 1006) :        resetMode      (MODE_Mouse1006); break; //XTERM
0797     case TY_CSI_PR('s', 1006) :         saveMode      (MODE_Mouse1006); break; //XTERM
0798     case TY_CSI_PR('r', 1006) :      restoreMode      (MODE_Mouse1006); break; //XTERM
0799 
0800     case TY_CSI_PR('h', 1015) :          setMode      (MODE_Mouse1015); break; //URXVT
0801     case TY_CSI_PR('l', 1015) :        resetMode      (MODE_Mouse1015); break; //URXVT
0802     case TY_CSI_PR('s', 1015) :         saveMode      (MODE_Mouse1015); break; //URXVT
0803     case TY_CSI_PR('r', 1015) :      restoreMode      (MODE_Mouse1015); break; //URXVT
0804 
0805     case TY_CSI_PR('h', 1034) : /* IGNORED: 8bitinput activation     */ break; //XTERM
0806 
0807     case TY_CSI_PR('h', 1047) :          setMode      (MODE_AppScreen); break; //XTERM
0808     case TY_CSI_PR('l', 1047) : _screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break; //XTERM
0809     case TY_CSI_PR('s', 1047) :         saveMode      (MODE_AppScreen); break; //XTERM
0810     case TY_CSI_PR('r', 1047) :      restoreMode      (MODE_AppScreen); break; //XTERM
0811 
0812     //FIXME: Unitoken: save translations
0813     case TY_CSI_PR('h', 1048) :      saveCursor           (          ); break; //XTERM
0814     case TY_CSI_PR('l', 1048) :      restoreCursor        (          ); break; //XTERM
0815     case TY_CSI_PR('s', 1048) :      saveCursor           (          ); break; //XTERM
0816     case TY_CSI_PR('r', 1048) :      restoreCursor        (          ); break; //XTERM
0817 
0818     //FIXME: every once new sequences like this pop up in xterm.
0819     //       Here's a guess of what they could mean.
0820     case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM
0821     case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM
0822 
0823     case TY_CSI_PR('h', 2004) :          setMode      (MODE_BracketedPaste); break; //XTERM
0824     case TY_CSI_PR('l', 2004) :        resetMode      (MODE_BracketedPaste); break; //XTERM
0825     case TY_CSI_PR('s', 2004) :         saveMode      (MODE_BracketedPaste); break; //XTERM
0826     case TY_CSI_PR('r', 2004) :      restoreMode      (MODE_BracketedPaste); break; //XTERM
0827 
0828     //FIXME: weird DEC reset sequence
0829     case TY_CSI_PE('p'      ) : /* IGNORED: reset         (        ) */ break;
0830 
0831     //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
0832     case TY_VT52('A'      ) : _currentScreen->cursorUp             (         1); break; //VT52
0833     case TY_VT52('B'      ) : _currentScreen->cursorDown           (         1); break; //VT52
0834     case TY_VT52('C'      ) : _currentScreen->cursorRight          (         1); break; //VT52
0835     case TY_VT52('D'      ) : _currentScreen->cursorLeft           (         1); break; //VT52
0836 
0837     case TY_VT52('F'      ) :      setAndUseCharset     (0,    '0'); break; //VT52
0838     case TY_VT52('G'      ) :      setAndUseCharset     (0,    'B'); break; //VT52
0839 
0840     case TY_VT52('H'      ) : _currentScreen->setCursorYX          (1,1       ); break; //VT52
0841     case TY_VT52('I'      ) : _currentScreen->reverseIndex         (          ); break; //VT52
0842     case TY_VT52('J'      ) : _currentScreen->clearToEndOfScreen   (          ); break; //VT52
0843     case TY_VT52('K'      ) : _currentScreen->clearToEndOfLine     (          ); break; //VT52
0844     case TY_VT52('Y'      ) : _currentScreen->setCursorYX          (p-31,q-31 ); break; //VT52
0845     case TY_VT52('Z'      ) :      reportTerminalType   (           ); break; //VT52
0846     case TY_VT52('<'      ) :          setMode      (MODE_Ansi     ); break; //VT52
0847     case TY_VT52('='      ) :          setMode      (MODE_AppKeyPad); break; //VT52
0848     case TY_VT52('>'      ) :        resetMode      (MODE_AppKeyPad); break; //VT52
0849 
0850     case TY_CSI_PG('c'      ) :  reportSecondaryAttributes(          ); break; //VT100
0851 
0852     default:
0853         reportDecodingError();
0854         break;
0855   };
0856 }
0857 
0858 void Vt102Emulation::clearScreenAndSetColumns(int columnCount)
0859 {
0860     setImageSize(_currentScreen->getLines(),columnCount);
0861     clearEntireScreen();
0862     setDefaultMargins();
0863     _currentScreen->setCursorYX(0,0);
0864 }
0865 
0866 void Vt102Emulation::sendString(const char* s , int length)
0867 {
0868   if ( length >= 0 )
0869     Q_EMIT sendData(s,length);
0870   else
0871     Q_EMIT sendData(s,strlen(s));
0872 }
0873 
0874 void Vt102Emulation::reportCursorPosition()
0875 {
0876   char tmp[20];
0877   sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);
0878   sendString(tmp);
0879 }
0880 
0881 void Vt102Emulation::reportTerminalType()
0882 {
0883   // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
0884   // VT220:  ^[[?63;1;2;3;6;7;8c   (list deps on emul. capabilities)
0885   // VT100:  ^[[?1;2c
0886   // VT101:  ^[[?1;0c
0887   // VT102:  ^[[?6v
0888   if (getMode(MODE_Ansi))
0889     sendString("\033[?1;2c"); // I'm a VT100
0890   else
0891     sendString("\033/Z"); // I'm a VT52
0892 }
0893 
0894 void Vt102Emulation::reportSecondaryAttributes()
0895 {
0896   // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
0897   if (getMode(MODE_Ansi))
0898     sendString("\033[>0;115;0c"); // Why 115?  ;)
0899   else
0900     sendString("\033/Z");         // FIXME I don't think VT52 knows about it but kept for
0901                                   // konsoles backward compatibility.
0902 }
0903 
0904 void Vt102Emulation::reportTerminalParms(int p)
0905 // DECREPTPARM
0906 {
0907   char tmp[100];
0908   sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
0909   sendString(tmp);
0910 }
0911 
0912 void Vt102Emulation::reportStatus()
0913 {
0914   sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
0915 }
0916 
0917 void Vt102Emulation::reportAnswerBack()
0918 {
0919   // FIXME - Test this with VTTEST
0920   // This is really obsolete VT100 stuff.
0921   const char* ANSWER_BACK = "";
0922   sendString(ANSWER_BACK);
0923 }
0924 
0925 /*!
0926     `cx',`cy' are 1-based.
0927     `cb' indicates the button pressed or released (0-2) or scroll event (4-5).
0928 
0929     eventType represents the kind of mouse action that occurred:
0930         0 = Mouse button press
0931         1 = Mouse drag
0932         2 = Mouse button release
0933 */
0934 
0935 void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
0936 {
0937     if (cx < 1 || cy < 1)
0938       return;
0939 
0940     // With the exception of the 1006 mode, button release is encoded in cb.
0941     // Note that if multiple extensions are enabled, the 1006 is used, so it's okay to check for only that.
0942     if (eventType == 2 && !getMode(MODE_Mouse1006))
0943         cb = 3;
0944 
0945     // normal buttons are passed as 0x20 + button,
0946     // mouse wheel (buttons 4,5) as 0x5c + button
0947     if (cb >= 4)
0948       cb += 0x3c;
0949 
0950     //Mouse motion handling
0951     if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
0952       cb += 0x20; //add 32 to signify motion event
0953 
0954     char command[32];
0955     command[0] = '\0';
0956     // Check the extensions in decreasing order of preference. Encoding the release event above assumes that 1006 comes first.
0957     if (getMode(MODE_Mouse1006)) {
0958         snprintf(command, sizeof(command), "\033[<%d;%d;%d%c", cb, cx, cy, eventType == 2 ? 'm' : 'M');
0959     } else if (getMode(MODE_Mouse1015)) {
0960         snprintf(command, sizeof(command), "\033[%d;%d;%dM", cb + 0x20, cx, cy);
0961     } else if (getMode(MODE_Mouse1005)) {
0962         if (cx <= 2015 && cy <= 2015) {
0963             // The xterm extension uses UTF-8 (up to 2 bytes) to encode
0964             // coordinate+32, no matter what the locale is. We could easily
0965             // convert manually, but QString can also do it for us.
0966             QChar coords[2];
0967             coords[0] = cx + 0x20;
0968             coords[1] = cy + 0x20;
0969             QString coordsStr = QString(coords, 2);
0970             QByteArray utf8 = coordsStr.toUtf8();
0971             snprintf(command, sizeof(command), "\033[M%c%s", cb + 0x20, utf8.constData());
0972         }
0973     } else if (cx <= 223 && cy <= 223) {
0974         snprintf(command, sizeof(command), "\033[M%c%c%c", cb + 0x20, cx + 0x20, cy + 0x20);
0975     }
0976 
0977   sendString(command);
0978 }
0979 
0980 /**
0981  * The focus lost event can be used by Vim (or other terminal applications)
0982  * to recognize that the konsole window has lost focus.
0983  * The escape sequence is also used by iTerm2.
0984  * Vim needs the following plugin to be installed to convert the escape
0985  * sequence into the FocusLost autocmd: https://github.com/sjl/vitality.vim
0986  */
0987 void Vt102Emulation::focusLost(void)
0988 {
0989     if (_reportFocusEvents)
0990         sendString("\033[O");
0991 }
0992 
0993 /**
0994  * The focus gained event can be used by Vim (or other terminal applications)
0995  * to recognize that the konsole window has gained focus again.
0996  * The escape sequence is also used by iTerm2.
0997  * Vim needs the following plugin to be installed to convert the escape
0998  * sequence into the FocusGained autocmd: https://github.com/sjl/vitality.vim
0999  */
1000 void Vt102Emulation::focusGained(void)
1001 {
1002     if (_reportFocusEvents)
1003         sendString("\033[I");
1004 }
1005 
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 
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 
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             Q_EMIT flowControlKeyPressed(true);
1185             break;
1186         case Qt::Key_Q:
1187         case Qt::Key_C: // cancel flow control
1188             Q_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 
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 
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 
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 
1325 void Vt102Emulation::setAndUseCharset(int n, int cs)
1326 {
1327   CHARSET.charset[n&3] = cs;
1328   useCharset(n&3);
1329 }
1330 
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 
1338 void Vt102Emulation::setDefaultMargins()
1339 {
1340     _screen[0]->setDefaultMargins();
1341     _screen[1]->setDefaultMargins();
1342 }
1343 
1344 void Vt102Emulation::setMargins(int t, int b)
1345 {
1346   _screen[0]->setMargins(t, b);
1347   _screen[1]->setMargins(t, b);
1348 }
1349 
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 
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 
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 
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         Q_EMIT programUsesMouseChanged(false);
1425     break;
1426 
1427     case MODE_BracketedPaste:
1428         Q_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 
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         Q_EMIT programUsesMouseChanged(true);
1457     break;
1458 
1459     case MODE_BracketedPaste:
1460         Q_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 
1475 void Vt102Emulation::saveMode(int m)
1476 {
1477   _savedModes.mode[m] = _currentModes.mode[m];
1478 }
1479 
1480 void Vt102Emulation::restoreMode(int m)
1481 {
1482   if (_savedModes.mode[m])
1483       setMode(m);
1484   else
1485       resetMode(m);
1486 }
1487 
1488 bool Vt102Emulation::getMode(int m)
1489 {
1490   return _currentModes.mode[m];
1491 }
1492 
1493 char Vt102Emulation::eraseChar() const
1494 {
1495   KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
1496                                             Qt::Key_Backspace,
1497                                             Qt::NoModifier,
1498                                             KeyboardTranslator::NoState);
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
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 
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