File indexing completed on 2024-05-19 05:28:22

0001 /*
0002     This file is part of Konsole, an X terminal.
0003 
0004     SPDX-FileCopyrightText: 2007-2008 Robert Knight <robert.knight@gmail.com>
0005     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 
0009     This program is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012     GNU General Public License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program; if not, write to the Free Software
0016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301  USA.
0018 */
0019 
0020 // Own
0021 #include "Vt102Emulation.h"
0022 #include "tools.h"
0023 
0024 // XKB
0025 // #include <config-konsole.h>
0026 
0027 // this allows konsole to be compiled without XKB and XTEST extensions
0028 // even though it might be available on a particular system.
0029 #if defined(AVOID_XKB)
0030 #undef HAVE_XKB
0031 #endif
0032 
0033 #if defined(HAVE_XKB)
0034 void scrolllock_set_off();
0035 void scrolllock_set_on();
0036 #endif
0037 
0038 // Standard
0039 #include <cstdio>
0040 #include <unistd.h>
0041 
0042 // Qt
0043 #include <QDebug>
0044 #include <QEvent>
0045 #include <QKeyEvent>
0046 
0047 // KDE
0048 // #include <kdebug.h>
0049 // #include <klocale.h>
0050 
0051 // Konsole
0052 #include "KeyboardTranslator.h"
0053 #include "Screen.h"
0054 
0055 using namespace Konsole;
0056 
0057 Vt102Emulation::Vt102Emulation()
0058     : Emulation()
0059     , prevCC(0)
0060     , _titleUpdateTimer(new QTimer(this))
0061     , _reportFocusEvents(false)
0062 {
0063     _titleUpdateTimer->setSingleShot(true);
0064     QObject::connect(_titleUpdateTimer, &QTimer::timeout, this, &Vt102Emulation::updateTitle);
0065 
0066     initTokenizer();
0067     reset();
0068 }
0069 
0070 Vt102Emulation::~Vt102Emulation()
0071 {
0072 }
0073 
0074 void Vt102Emulation::clearEntireScreen()
0075 {
0076     _currentScreen->clearEntireScreen();
0077     bufferedUpdate();
0078 }
0079 
0080 void Vt102Emulation::reset()
0081 {
0082     resetTokenizer();
0083     resetModes();
0084     resetCharset(0);
0085     _primaryScreen->reset();
0086     resetCharset(1);
0087     _alternateScreen->reset();
0088     setCodec(LocaleCodec);
0089 
0090     bufferedUpdate();
0091 }
0092 
0093 /* ------------------------------------------------------------------------- */
0094 /*                                                                           */
0095 /*                     Processing the incoming byte stream                   */
0096 /*                                                                           */
0097 /* ------------------------------------------------------------------------- */
0098 
0099 /* Incoming Bytes Event pipeline
0100 
0101    This section deals with decoding the incoming character stream.
0102    Decoding means here, that the stream is first separated into `tokens'
0103    which are then mapped to a `meaning' provided as operations by the
0104    `Screen' class or by the emulation class itself.
0105 
0106    The pipeline proceeds as follows:
0107 
0108    - Tokenizing the ESC codes (onReceiveChar)
0109    - VT100 code page translation of plain characters (applyCharset)
0110    - Interpretation of ESC codes (processToken)
0111 
0112    The escape codes and their meaning are described in the
0113    technical reference of this program.
0114 */
0115 
0116 // Tokens ------------------------------------------------------------------ --
0117 
0118 /*
0119    Since the tokens are the central notion if this section, we've put them
0120    in front. They provide the syntactical elements used to represent the
0121    terminals operations as byte sequences.
0122 
0123    They are encodes here into a single machine word, so that we can later
0124    switch over them easily. Depending on the token itself, additional
0125    argument variables are filled with parameter values.
0126 
0127    The tokens are defined below:
0128 
0129    - CHR        - Printable characters     (32..255 but DEL (=127))
0130    - CTL        - Control characters       (0..31 but ESC (= 27), DEL)
0131    - ESC        - Escape codes of the form <ESC><CHR but `[]()+*#'>
0132    - ESC_DE     - Escape codes of the form <ESC><any of `()+*#%'> C
0133    - CSI_PN     - Escape codes of the form <ESC>'['     {Pn} ';' {Pn} C
0134    - CSI_PS     - Escape codes of the form <ESC>'['     {Pn} ';' ...  C
0135    - CSI_PS_SP  - Escape codes of the form <ESC>'['     {Pn} ';' ... {Space} C
0136    - CSI_PR     - Escape codes of the form <ESC>'[' '?' {Pn} ';' ...  C
0137    - CSI_PE     - Escape codes of the form <ESC>'[' '!' {Pn} ';' ...  C
0138    - VT52       - VT52 escape codes
0139                   - <ESC><Chr>
0140                   - <ESC>'Y'{Pc}{Pc}
0141    - XTE_HA     - Xterm window/terminal attribute commands
0142                   of the form <ESC>`]' {Pn} `;' {Text} <BEL>
0143                   (Note that these are handled differently to the other formats)
0144 
0145    The last two forms allow list of arguments. Since the elements of
0146    the lists are treated individually the same way, they are passed
0147    as individual tokens to the interpretation. Further, because the
0148    meaning of the parameters are names (althought represented as numbers),
0149    they are includes within the token ('N').
0150 
0151 */
0152 
0153 #define TY_CONSTRUCT(T, A, N) (((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff))
0154 
0155 #define TY_CHR() TY_CONSTRUCT(0, 0, 0)
0156 #define TY_CTL(A) TY_CONSTRUCT(1, A, 0)
0157 #define TY_ESC(A) TY_CONSTRUCT(2, A, 0)
0158 #define TY_ESC_CS(A, B) TY_CONSTRUCT(3, A, B)
0159 #define TY_ESC_DE(A) TY_CONSTRUCT(4, A, 0)
0160 #define TY_CSI_PS(A, N) TY_CONSTRUCT(5, A, N)
0161 #define TY_CSI_PN(A) TY_CONSTRUCT(6, A, 0)
0162 #define TY_CSI_PR(A, N) TY_CONSTRUCT(7, A, N)
0163 #define TY_CSI_PS_SP(A, N) TY_CONSTRUCT(11, A, N)
0164 
0165 #define TY_VT52(A) TY_CONSTRUCT(8, A, 0)
0166 #define TY_CSI_PG(A) TY_CONSTRUCT(9, A, 0)
0167 #define TY_CSI_PE(A) TY_CONSTRUCT(10, A, 0)
0168 
0169 #define MAX_ARGUMENT 4096
0170 
0171 // Tokenizer --------------------------------------------------------------- --
0172 
0173 /* The tokenizer's state
0174 
0175    The state is represented by the buffer (tokenBuffer, tokenBufferPos),
0176    and accompanied by decoded arguments kept in (argv,argc).
0177    Note that they are kept internal in the tokenizer.
0178 */
0179 
0180 void Vt102Emulation::resetTokenizer()
0181 {
0182     tokenBufferPos = 0;
0183     argc = 0;
0184     argv[0] = 0;
0185     argv[1] = 0;
0186     prevCC = 0;
0187 }
0188 
0189 void Vt102Emulation::addDigit(int digit)
0190 {
0191     if (argv[argc] < MAX_ARGUMENT)
0192         argv[argc] = 10 * argv[argc] + digit;
0193 }
0194 
0195 void Vt102Emulation::addArgument()
0196 {
0197     argc = qMin(argc + 1, MAXARGS - 1);
0198     argv[argc] = 0;
0199 }
0200 
0201 void Vt102Emulation::addToCurrentToken(char16_t cc)
0202 {
0203     tokenBuffer[tokenBufferPos] = cc;
0204     tokenBufferPos = qMin(tokenBufferPos + 1, MAX_TOKEN_LENGTH - 1);
0205 }
0206 
0207 // Character Class flags used while decoding
0208 #define CTL 1 // Control character
0209 #define CHR 2 // Printable character
0210 #define CPN 4 // TODO: Document me
0211 #define DIG 8 // Digit
0212 #define SCS 16 // TODO: Document me
0213 #define GRP 32 // TODO: Document me
0214 #define CPS                                                                                                                                                    \
0215     64 // Character which indicates end of window resize
0216        // escape sequence '\e[8;<row>;<col>t'
0217 
0218 void Vt102Emulation::initTokenizer()
0219 {
0220     int i;
0221     quint8 *s;
0222     for (i = 0; i < 256; ++i)
0223         charClass[i] = 0;
0224     for (i = 0; i < 32; ++i)
0225         charClass[i] |= CTL;
0226     for (i = 32; i < 256; ++i)
0227         charClass[i] |= CHR;
0228     for (s = (quint8 *)"@ABCDGHILMPSTXZbcdfry"; *s; ++s)
0229         charClass[*s] |= CPN;
0230     // resize = \e[8;<row>;<col>t
0231     for (s = (quint8 *)"t"; *s; ++s)
0232         charClass[*s] |= CPS;
0233     for (s = (quint8 *)"0123456789"; *s; ++s)
0234         charClass[*s] |= DIG;
0235     for (s = (quint8 *)"()+*%"; *s; ++s)
0236         charClass[*s] |= SCS;
0237     for (s = (quint8 *)"()+*#[]%"; *s; ++s)
0238         charClass[*s] |= GRP;
0239 
0240     resetTokenizer();
0241 }
0242 
0243 /* Ok, here comes the nasty part of the decoder.
0244 
0245    Instead of keeping an explicit state, we deduce it from the
0246    token scanned so far. It is then immediately combined with
0247    the current character to form a scanning decision.
0248 
0249    This is done by the following defines.
0250 
0251    - P is the length of the token scanned so far.
0252    - L (often P-1) is the position on which contents we base a decision.
0253    - C is a character or a group of characters (taken from 'charClass').
0254 
0255    - 'cc' is the current character
0256    - 's' is a pointer to the start of the token buffer
0257    - 'p' is the current position within the token buffer
0258 
0259    Note that they need to applied in proper order.
0260 */
0261 
0262 #define lec(P, L, C) (p == (P) && s[(L)] == (C))
0263 #define lun() (p == 1 && cc >= 32)
0264 #define les(P, L, C) (p == (P) && s[L] < 256 && (charClass[s[(L)]] & (C)) == (C))
0265 #define eec(C) (p >= 3 && cc == (C))
0266 #define ees(C) (p >= 3 && cc < 256 && (charClass[cc] & (C)) == (C))
0267 #define eps(C) (p >= 3 && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (charClass[cc] & (C)) == (C))
0268 #define epp() (p >= 3 && s[2] == '?')
0269 #define epe() (p >= 3 && s[2] == '!')
0270 #define egt() (p >= 3 && s[2] == '>')
0271 #define esp() (p == 4 && s[3] == ' ')
0272 #define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
0273 #define Xte (Xpe && (cc == 7 || (prevCC == 27 && cc == 92))) // 27, 92 => "\e\\" (ST, String Terminator)
0274 #define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
0275 
0276 #define CNTL(c) ((c) - '@')
0277 #define ESC 27
0278 #define DEL 127
0279 
0280 // process an incoming unicode character
0281 void Vt102Emulation::receiveChar(QChar character)
0282 {
0283     char16_t cc = character.unicode();
0284 
0285     if (cc == DEL)
0286         return; // VT100: ignore.
0287 
0288     if (ces(CTL)) {
0289         // ignore control characters in the text part of Xpe (aka OSC) "ESC]"
0290         // escape sequences; this matches what XTERM docs say
0291         if (Xpe) {
0292             prevCC = cc;
0293             return;
0294         }
0295 
0296         // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
0297         // This means, they do neither a resetTokenizer() nor a pushToToken(). Some of them, do
0298         // of course. Guess this originates from a weakly layered handling of the X-on
0299         // X-off protocol, which comes really below this level.
0300         if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC)
0301             resetTokenizer(); // VT100: CAN or SUB
0302         if (cc != ESC) {
0303             processToken(TY_CTL(cc + '@'), 0, 0);
0304             return;
0305         }
0306     }
0307     // advance the state
0308     addToCurrentToken(cc);
0309 
0310     char16_t *s = tokenBuffer;
0311     int p = tokenBufferPos;
0312 
0313     if (getMode(MODE_Ansi)) {
0314         if (lec(1, 0, ESC)) {
0315             return;
0316         }
0317         if (lec(1, 0, ESC + 128)) {
0318             s[0] = ESC;
0319             receiveChar(u'[');
0320             return;
0321         }
0322         if (les(2, 1, GRP)) {
0323             return;
0324         }
0325         if (Xte) {
0326             processWindowAttributeChange();
0327             resetTokenizer();
0328             return;
0329         }
0330         if (Xpe) {
0331             prevCC = cc;
0332             return;
0333         }
0334         if (lec(3, 2, '?')) {
0335             return;
0336         }
0337         if (lec(3, 2, '>')) {
0338             return;
0339         }
0340         if (lec(3, 2, '!')) {
0341             return;
0342         }
0343         if (lun()) {
0344             processToken(TY_CHR(), applyCharset(cc), 0);
0345             resetTokenizer();
0346             return;
0347         }
0348         if (lec(2, 0, ESC)) {
0349             processToken(TY_ESC(s[1]), 0, 0);
0350             resetTokenizer();
0351             return;
0352         }
0353         if (les(3, 1, SCS)) {
0354             processToken(TY_ESC_CS(s[1], s[2]), 0, 0);
0355             resetTokenizer();
0356             return;
0357         }
0358         if (lec(3, 1, '#')) {
0359             processToken(TY_ESC_DE(s[2]), 0, 0);
0360             resetTokenizer();
0361             return;
0362         }
0363         if (eps(CPN)) {
0364             processToken(TY_CSI_PN(cc), argv[0], argv[1]);
0365             resetTokenizer();
0366             return;
0367         }
0368         if (esp()) {
0369             return;
0370         }
0371         if (lec(5, 4, 'q') && s[3] == ' ') {
0372             processToken(TY_CSI_PS_SP(cc, argv[0]), argv[0], 0);
0373             resetTokenizer();
0374             return;
0375         }
0376 
0377         // resize = \e[8;<row>;<col>t
0378         if (eps(CPS)) {
0379             processToken(TY_CSI_PS(cc, argv[0]), argv[1], argv[2]);
0380             resetTokenizer();
0381             return;
0382         }
0383 
0384         if (epe()) {
0385             processToken(TY_CSI_PE(cc), 0, 0);
0386             resetTokenizer();
0387             return;
0388         }
0389         if (ees(DIG)) {
0390             addDigit(cc - '0');
0391             return;
0392         }
0393         if (eec(';') || eec(':')) {
0394             addArgument();
0395             return;
0396         }
0397         for (int i = 0; i <= argc; i++) {
0398             if (epp())
0399                 processToken(TY_CSI_PR(cc, argv[i]), 0, 0);
0400             else if (egt())
0401                 processToken(TY_CSI_PG(cc), 0, 0); // spec. case for ESC]>0c or ESC]>c
0402             else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i + 1] == 2) {
0403                 // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
0404                 i += 2;
0405                 processToken(TY_CSI_PS(cc, argv[i - 2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i + 1] << 8) | argv[i + 2]);
0406                 i += 2;
0407             } else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i + 1] == 5) {
0408                 // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
0409                 i += 2;
0410                 processToken(TY_CSI_PS(cc, argv[i - 2]), COLOR_SPACE_256, argv[i]);
0411             } else
0412                 processToken(TY_CSI_PS(cc, argv[i]), 0, 0);
0413         }
0414         resetTokenizer();
0415     } else {
0416         // VT52 Mode
0417         if (lec(1, 0, ESC))
0418             return;
0419         if (les(1, 0, CHR)) {
0420             processToken(TY_CHR(), s[0], 0);
0421             resetTokenizer();
0422             return;
0423         }
0424         if (lec(2, 1, 'Y'))
0425             return;
0426 
0427         if (lec(3, 1, 'Y'))
0428             return;
0429 
0430         if (p < 4) {
0431             processToken(TY_VT52(s[1]), 0, 0);
0432             resetTokenizer();
0433             return;
0434         }
0435         processToken(TY_VT52(s[1]), s[2], s[3]);
0436         resetTokenizer();
0437         return;
0438     }
0439 }
0440 void Vt102Emulation::processWindowAttributeChange()
0441 {
0442     // Describes the window or terminal session attribute to change
0443     // See Session::UserTitleChange for possible values
0444     int attributeToChange = 0;
0445     int i;
0446     for (i = 2; i < tokenBufferPos && tokenBuffer[i] >= '0' && tokenBuffer[i] <= '9'; i++) {
0447         attributeToChange = 10 * attributeToChange + (tokenBuffer[i] - '0');
0448     }
0449 
0450     if (tokenBuffer[i] != ';') {
0451         reportDecodingError();
0452         return;
0453     }
0454 
0455     // copy from the first char after ';', and skipping the ending delimiter
0456     // 0x07 or 0x92. Note that as control characters in OSC text parts are
0457     // ignored, only the second char in ST ("\e\\") is appended to tokenBuffer.
0458     QString newValue = QString::fromUtf16(tokenBuffer + i + 1, tokenBufferPos - i - 2);
0459 
0460     _pendingTitleUpdates[attributeToChange] = newValue;
0461     _titleUpdateTimer->start(20);
0462 }
0463 
0464 void Vt102Emulation::updateTitle()
0465 {
0466     QListIterator<int> iter(_pendingTitleUpdates.keys());
0467     while (iter.hasNext()) {
0468         int arg = iter.next();
0469         Q_EMIT titleChanged(arg, _pendingTitleUpdates[arg]);
0470     }
0471     _pendingTitleUpdates.clear();
0472 }
0473 
0474 // Interpreting Codes ---------------------------------------------------------
0475 
0476 /*
0477    Now that the incoming character stream is properly tokenized,
0478    meaning is assigned to them. These are either operations of
0479    the current _screen, or of the emulation class itself.
0480 
0481    The token to be interpreteted comes in as a machine word
0482    possibly accompanied by two parameters.
0483 
0484    Likewise, the operations assigned to, come with up to two
0485    arguments. One could consider to make up a proper table
0486    from the function below.
0487 
0488    The technical reference manual provides more information
0489    about this mapping.
0490 */
0491 
0492 void Vt102Emulation::processToken(int token, char16_t p, int q)
0493 {
0494     switch (token) {
0495     case TY_CHR():
0496         _currentScreen->displayCharacter(p);
0497         break; // UTF16
0498 
0499         //             127 DEL    : ignored on input
0500 
0501     case TY_CTL('@'): /* NUL: ignored                      */
0502         break;
0503     case TY_CTL('A'): /* SOH: ignored                      */
0504         break;
0505     case TY_CTL('B'): /* STX: ignored                      */
0506         break;
0507     case TY_CTL('C'): /* ETX: ignored                      */
0508         break;
0509     case TY_CTL('D'): /* EOT: ignored                      */
0510         break;
0511     case TY_CTL('E'):
0512         reportAnswerBack();
0513         break; // VT100
0514     case TY_CTL('F'): /* ACK: ignored                      */
0515         break;
0516     case TY_CTL('G'):
0517         Q_EMIT stateSet(NOTIFYBELL);
0518         break; // VT100
0519     case TY_CTL('H'):
0520         _currentScreen->backspace();
0521         break; // VT100
0522     case TY_CTL('I'):
0523         _currentScreen->tab();
0524         break; // VT100
0525     case TY_CTL('J'):
0526         _currentScreen->newLine();
0527         break; // VT100
0528     case TY_CTL('K'):
0529         _currentScreen->newLine();
0530         break; // VT100
0531     case TY_CTL('L'):
0532         _currentScreen->newLine();
0533         break; // VT100
0534     case TY_CTL('M'):
0535         _currentScreen->toStartOfLine();
0536         break; // VT100
0537 
0538     case TY_CTL('N'):
0539         useCharset(1);
0540         break; // VT100
0541     case TY_CTL('O'):
0542         useCharset(0);
0543         break; // VT100
0544 
0545     case TY_CTL('P'): /* DLE: ignored                      */
0546         break;
0547     case TY_CTL('Q'): /* DC1: XON continue                 */
0548         break; // VT100
0549     case TY_CTL('R'): /* DC2: ignored                      */
0550         break;
0551     case TY_CTL('S'): /* DC3: XOFF halt                    */
0552         break; // VT100
0553     case TY_CTL('T'): /* DC4: ignored                      */
0554         break;
0555     case TY_CTL('U'): /* NAK: ignored                      */
0556         break;
0557     case TY_CTL('V'): /* SYN: ignored                      */
0558         break;
0559     case TY_CTL('W'): /* ETB: ignored                      */
0560         break;
0561     case TY_CTL('X'):
0562         _currentScreen->displayCharacter(QChar(0x2592));
0563         break; // VT100
0564     case TY_CTL('Y'): /* EM : ignored                      */
0565         break;
0566     case TY_CTL('Z'):
0567         _currentScreen->displayCharacter(QChar(0x2592));
0568         break; // VT100
0569     case TY_CTL('['): /* ESC: cannot be seen here.         */
0570         break;
0571     case TY_CTL('\\'): /* FS : ignored                      */
0572         break;
0573     case TY_CTL(']'): /* GS : ignored                      */
0574         break;
0575     case TY_CTL('^'): /* RS : ignored                      */
0576         break;
0577     case TY_CTL('_'): /* US : ignored                      */
0578         break;
0579 
0580     case TY_ESC('D'):
0581         _currentScreen->index();
0582         break; // VT100
0583     case TY_ESC('E'):
0584         _currentScreen->nextLine();
0585         break; // VT100
0586     case TY_ESC('H'):
0587         _currentScreen->changeTabStop(true);
0588         break; // VT100
0589     case TY_ESC('M'):
0590         _currentScreen->reverseIndex();
0591         break; // VT100
0592     case TY_ESC('Z'):
0593         reportTerminalType();
0594         break;
0595     case TY_ESC('c'):
0596         reset();
0597         break;
0598 
0599     case TY_ESC('n'):
0600         useCharset(2);
0601         break;
0602     case TY_ESC('o'):
0603         useCharset(3);
0604         break;
0605     case TY_ESC('7'):
0606         saveCursor();
0607         break;
0608     case TY_ESC('8'):
0609         restoreCursor();
0610         break;
0611 
0612     case TY_ESC('='):
0613         setMode(MODE_AppKeyPad);
0614         break;
0615     case TY_ESC('>'):
0616         resetMode(MODE_AppKeyPad);
0617         break;
0618     case TY_ESC('<'):
0619         setMode(MODE_Ansi);
0620         break; // VT100
0621 
0622     case TY_ESC_CS('(', '0'):
0623         setCharset(0, '0');
0624         break; // VT100
0625     case TY_ESC_CS('(', 'A'):
0626         setCharset(0, 'A');
0627         break; // VT100
0628     case TY_ESC_CS('(', 'B'):
0629         setCharset(0, 'B');
0630         break; // VT100
0631 
0632     case TY_ESC_CS(')', '0'):
0633         setCharset(1, '0');
0634         break; // VT100
0635     case TY_ESC_CS(')', 'A'):
0636         setCharset(1, 'A');
0637         break; // VT100
0638     case TY_ESC_CS(')', 'B'):
0639         setCharset(1, 'B');
0640         break; // VT100
0641 
0642     case TY_ESC_CS('*', '0'):
0643         setCharset(2, '0');
0644         break; // VT100
0645     case TY_ESC_CS('*', 'A'):
0646         setCharset(2, 'A');
0647         break; // VT100
0648     case TY_ESC_CS('*', 'B'):
0649         setCharset(2, 'B');
0650         break; // VT100
0651 
0652     case TY_ESC_CS('+', '0'):
0653         setCharset(3, '0');
0654         break; // VT100
0655     case TY_ESC_CS('+', 'A'):
0656         setCharset(3, 'A');
0657         break; // VT100
0658     case TY_ESC_CS('+', 'B'):
0659         setCharset(3, 'B');
0660         break; // VT100
0661 
0662     case TY_ESC_CS('%', 'G'):
0663         setCodec(Utf8Codec);
0664         break; // LINUX
0665     case TY_ESC_CS('%', '@'):
0666         setCodec(LocaleCodec);
0667         break; // LINUX
0668 
0669     case TY_ESC_DE('3'): /* Double height line, top half    */
0670         _currentScreen->setLineProperty(LINE_DOUBLEWIDTH, true);
0671         _currentScreen->setLineProperty(LINE_DOUBLEHEIGHT, true);
0672         break;
0673     case TY_ESC_DE('4'): /* Double height line, bottom half */
0674         _currentScreen->setLineProperty(LINE_DOUBLEWIDTH, true);
0675         _currentScreen->setLineProperty(LINE_DOUBLEHEIGHT, true);
0676         break;
0677     case TY_ESC_DE('5'): /* Single width, single height line*/
0678         _currentScreen->setLineProperty(LINE_DOUBLEWIDTH, false);
0679         _currentScreen->setLineProperty(LINE_DOUBLEHEIGHT, false);
0680         break;
0681     case TY_ESC_DE('6'): /* Double width, single height line*/
0682         _currentScreen->setLineProperty(LINE_DOUBLEWIDTH, true);
0683         _currentScreen->setLineProperty(LINE_DOUBLEHEIGHT, false);
0684         break;
0685     case TY_ESC_DE('8'):
0686         _currentScreen->helpAlign();
0687         break;
0688 
0689         // resize = \e[8;<row>;<col>t
0690     case TY_CSI_PS('t', 8):
0691         setImageSize(p /*lines */, q /* columns */);
0692         Q_EMIT imageResizeRequest(QSize(q, p));
0693         break;
0694 
0695         // change tab text color : \e[28;<color>t  color: 0-16,777,215
0696     case TY_CSI_PS('t', 28):
0697         Q_EMIT changeTabTextColorRequest(p);
0698         break;
0699 
0700     case TY_CSI_PS('K', 0):
0701         _currentScreen->clearToEndOfLine();
0702         break;
0703     case TY_CSI_PS('K', 1):
0704         _currentScreen->clearToBeginOfLine();
0705         break;
0706     case TY_CSI_PS('K', 2):
0707         _currentScreen->clearEntireLine();
0708         break;
0709     case TY_CSI_PS('J', 0):
0710         _currentScreen->clearToEndOfScreen();
0711         break;
0712     case TY_CSI_PS('J', 1):
0713         _currentScreen->clearToBeginOfScreen();
0714         break;
0715     case TY_CSI_PS('J', 2):
0716         _currentScreen->clearEntireScreen();
0717         break;
0718     case TY_CSI_PS('J', 3):
0719         clearHistory();
0720         break;
0721     case TY_CSI_PS('g', 0):
0722         _currentScreen->changeTabStop(false);
0723         break; // VT100
0724     case TY_CSI_PS('g', 3):
0725         _currentScreen->clearTabStops();
0726         break; // VT100
0727     case TY_CSI_PS('h', 4):
0728         _currentScreen->setMode(MODE_Insert);
0729         break;
0730     case TY_CSI_PS('h', 20):
0731         setMode(MODE_NewLine);
0732         break;
0733     case TY_CSI_PS('i', 0): /* IGNORE: attached printer          */
0734         break; // VT100
0735     case TY_CSI_PS('l', 4):
0736         _currentScreen->resetMode(MODE_Insert);
0737         break;
0738     case TY_CSI_PS('l', 20):
0739         resetMode(MODE_NewLine);
0740         break;
0741     case TY_CSI_PS('s', 0):
0742         saveCursor();
0743         break;
0744     case TY_CSI_PS('u', 0):
0745         restoreCursor();
0746         break;
0747 
0748     case TY_CSI_PS('m', 0):
0749         _currentScreen->setDefaultRendition();
0750         break;
0751     case TY_CSI_PS('m', 1):
0752         _currentScreen->setRendition(RE_BOLD);
0753         break; // VT100
0754     case TY_CSI_PS('m', 2):
0755         _currentScreen->setRendition(RE_FAINT);
0756         break;
0757     case TY_CSI_PS('m', 3):
0758         _currentScreen->setRendition(RE_ITALIC);
0759         break; // VT100
0760     case TY_CSI_PS('m', 4):
0761         _currentScreen->setRendition(RE_UNDERLINE);
0762         break; // VT100
0763     case TY_CSI_PS('m', 5):
0764         _currentScreen->setRendition(RE_BLINK);
0765         break; // VT100
0766     case TY_CSI_PS('m', 7):
0767         _currentScreen->setRendition(RE_REVERSE);
0768         break;
0769     case TY_CSI_PS('m', 8):
0770         _currentScreen->setRendition(RE_CONCEAL);
0771         break;
0772     case TY_CSI_PS('m', 9):
0773         _currentScreen->setRendition(RE_STRIKEOUT);
0774         break;
0775     case TY_CSI_PS('m', 53):
0776         _currentScreen->setRendition(RE_OVERLINE);
0777         break;
0778     case TY_CSI_PS('m', 10): /* IGNORED: mapping related          */
0779         break; // LINUX
0780     case TY_CSI_PS('m', 11): /* IGNORED: mapping related          */
0781         break; // LINUX
0782     case TY_CSI_PS('m', 12): /* IGNORED: mapping related          */
0783         break; // LINUX
0784     case TY_CSI_PS('m', 21):
0785         _currentScreen->resetRendition(RE_BOLD);
0786         break;
0787     case TY_CSI_PS('m', 22):
0788         _currentScreen->resetRendition(RE_BOLD);
0789         _currentScreen->resetRendition(RE_FAINT);
0790         break;
0791     case TY_CSI_PS('m', 23):
0792         _currentScreen->resetRendition(RE_ITALIC);
0793         break; // VT100
0794     case TY_CSI_PS('m', 24):
0795         _currentScreen->resetRendition(RE_UNDERLINE);
0796         break;
0797     case TY_CSI_PS('m', 25):
0798         _currentScreen->resetRendition(RE_BLINK);
0799         break;
0800     case TY_CSI_PS('m', 27):
0801         _currentScreen->resetRendition(RE_REVERSE);
0802         break;
0803     case TY_CSI_PS('m', 28):
0804         _currentScreen->resetRendition(RE_CONCEAL);
0805         break;
0806     case TY_CSI_PS('m', 29):
0807         _currentScreen->resetRendition(RE_STRIKEOUT);
0808         break;
0809     case TY_CSI_PS('m', 55):
0810         _currentScreen->resetRendition(RE_OVERLINE);
0811         break;
0812 
0813     case TY_CSI_PS('m', 30):
0814         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 0);
0815         break;
0816     case TY_CSI_PS('m', 31):
0817         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 1);
0818         break;
0819     case TY_CSI_PS('m', 32):
0820         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 2);
0821         break;
0822     case TY_CSI_PS('m', 33):
0823         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 3);
0824         break;
0825     case TY_CSI_PS('m', 34):
0826         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 4);
0827         break;
0828     case TY_CSI_PS('m', 35):
0829         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 5);
0830         break;
0831     case TY_CSI_PS('m', 36):
0832         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 6);
0833         break;
0834     case TY_CSI_PS('m', 37):
0835         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 7);
0836         break;
0837 
0838     case TY_CSI_PS('m', 38):
0839         _currentScreen->setForeColor(p, q);
0840         break;
0841 
0842     case TY_CSI_PS('m', 39):
0843         _currentScreen->setForeColor(COLOR_SPACE_DEFAULT, 0);
0844         break;
0845 
0846     case TY_CSI_PS('m', 40):
0847         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 0);
0848         break;
0849     case TY_CSI_PS('m', 41):
0850         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 1);
0851         break;
0852     case TY_CSI_PS('m', 42):
0853         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 2);
0854         break;
0855     case TY_CSI_PS('m', 43):
0856         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 3);
0857         break;
0858     case TY_CSI_PS('m', 44):
0859         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 4);
0860         break;
0861     case TY_CSI_PS('m', 45):
0862         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 5);
0863         break;
0864     case TY_CSI_PS('m', 46):
0865         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 6);
0866         break;
0867     case TY_CSI_PS('m', 47):
0868         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 7);
0869         break;
0870 
0871     case TY_CSI_PS('m', 48):
0872         _currentScreen->setBackColor(p, q);
0873         break;
0874 
0875     case TY_CSI_PS('m', 49):
0876         _currentScreen->setBackColor(COLOR_SPACE_DEFAULT, 1);
0877         break;
0878 
0879     case TY_CSI_PS('m', 90):
0880         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 8);
0881         break;
0882     case TY_CSI_PS('m', 91):
0883         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 9);
0884         break;
0885     case TY_CSI_PS('m', 92):
0886         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 10);
0887         break;
0888     case TY_CSI_PS('m', 93):
0889         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 11);
0890         break;
0891     case TY_CSI_PS('m', 94):
0892         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 12);
0893         break;
0894     case TY_CSI_PS('m', 95):
0895         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 13);
0896         break;
0897     case TY_CSI_PS('m', 96):
0898         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 14);
0899         break;
0900     case TY_CSI_PS('m', 97):
0901         _currentScreen->setForeColor(COLOR_SPACE_SYSTEM, 15);
0902         break;
0903 
0904     case TY_CSI_PS('m', 100):
0905         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 8);
0906         break;
0907     case TY_CSI_PS('m', 101):
0908         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 9);
0909         break;
0910     case TY_CSI_PS('m', 102):
0911         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 10);
0912         break;
0913     case TY_CSI_PS('m', 103):
0914         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 11);
0915         break;
0916     case TY_CSI_PS('m', 104):
0917         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 12);
0918         break;
0919     case TY_CSI_PS('m', 105):
0920         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 13);
0921         break;
0922     case TY_CSI_PS('m', 106):
0923         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 14);
0924         break;
0925     case TY_CSI_PS('m', 107):
0926         _currentScreen->setBackColor(COLOR_SPACE_SYSTEM, 15);
0927         break;
0928 
0929     case TY_CSI_PS('n', 5):
0930         reportStatus();
0931         break;
0932     case TY_CSI_PS('n', 6):
0933         reportCursorPosition();
0934         break;
0935     case TY_CSI_PS('q', 0): /* IGNORED: LEDs off                 */
0936         break; // VT100
0937     case TY_CSI_PS('q', 1): /* IGNORED: LED1 on                  */
0938         break; // VT100
0939     case TY_CSI_PS('q', 2): /* IGNORED: LED2 on                  */
0940         break; // VT100
0941     case TY_CSI_PS('q', 3): /* IGNORED: LED3 on                  */
0942         break; // VT100
0943     case TY_CSI_PS('q', 4): /* IGNORED: LED4 on                  */
0944         break; // VT100
0945     case TY_CSI_PS('x', 0):
0946         reportTerminalParms(2);
0947         break; // VT100
0948     case TY_CSI_PS('x', 1):
0949         reportTerminalParms(3);
0950         break; // VT100
0951 
0952     case TY_CSI_PS_SP('q', 0): /* fall through */
0953     case TY_CSI_PS_SP('q', 1):
0954         Q_EMIT cursorChanged(KeyboardCursorShape::BlockCursor, true);
0955         break;
0956     case TY_CSI_PS_SP('q', 2):
0957         Q_EMIT cursorChanged(KeyboardCursorShape::BlockCursor, false);
0958         break;
0959     case TY_CSI_PS_SP('q', 3):
0960         Q_EMIT cursorChanged(KeyboardCursorShape::UnderlineCursor, true);
0961         break;
0962     case TY_CSI_PS_SP('q', 4):
0963         Q_EMIT cursorChanged(KeyboardCursorShape::UnderlineCursor, false);
0964         break;
0965     case TY_CSI_PS_SP('q', 5):
0966         Q_EMIT cursorChanged(KeyboardCursorShape::IBeamCursor, true);
0967         break;
0968     case TY_CSI_PS_SP('q', 6):
0969         Q_EMIT cursorChanged(KeyboardCursorShape::IBeamCursor, false);
0970         break;
0971 
0972     case TY_CSI_PN('@'):
0973         _currentScreen->insertChars(p);
0974         break;
0975     case TY_CSI_PN('A'):
0976         _currentScreen->cursorUp(p);
0977         break; // VT100
0978     case TY_CSI_PN('B'):
0979         _currentScreen->cursorDown(p);
0980         break; // VT100
0981     case TY_CSI_PN('C'):
0982         _currentScreen->cursorRight(p);
0983         break; // VT100
0984     case TY_CSI_PN('D'):
0985         _currentScreen->cursorLeft(p);
0986         break; // VT100
0987     case TY_CSI_PN('E'): /* Not implemented: cursor next p lines */
0988         break; // VT100
0989     case TY_CSI_PN('F'): /* Not implemented: cursor preceding p lines */
0990         break; // VT100
0991     case TY_CSI_PN('G'):
0992         _currentScreen->setCursorX(p);
0993         break; // LINUX
0994     case TY_CSI_PN('H'):
0995         _currentScreen->setCursorYX(p, q);
0996         break; // VT100
0997     case TY_CSI_PN('I'):
0998         _currentScreen->tab(p);
0999         break;
1000     case TY_CSI_PN('L'):
1001         _currentScreen->insertLines(p);
1002         break;
1003     case TY_CSI_PN('M'):
1004         _currentScreen->deleteLines(p);
1005         break;
1006     case TY_CSI_PN('P'):
1007         _currentScreen->deleteChars(p);
1008         break;
1009     case TY_CSI_PN('S'):
1010         _currentScreen->scrollUp(p);
1011         break;
1012     case TY_CSI_PN('T'):
1013         _currentScreen->scrollDown(p);
1014         break;
1015     case TY_CSI_PN('X'):
1016         _currentScreen->eraseChars(p);
1017         break;
1018     case TY_CSI_PN('Z'):
1019         _currentScreen->backtab(p);
1020         break;
1021     case TY_CSI_PN('b'):
1022         _currentScreen->repeatChars(p);
1023         break;
1024     case TY_CSI_PN('c'):
1025         reportTerminalType();
1026         break; // VT100
1027     case TY_CSI_PN('d'):
1028         _currentScreen->setCursorY(p);
1029         break; // LINUX
1030     case TY_CSI_PN('f'):
1031         _currentScreen->setCursorYX(p, q);
1032         break; // VT100
1033     case TY_CSI_PN('r'):
1034         setMargins(p, q);
1035         break; // VT100
1036     case TY_CSI_PN('y'): /* IGNORED: Confidence test          */
1037         break; // VT100
1038 
1039     case TY_CSI_PR('h', 1):
1040         setMode(MODE_AppCuKeys);
1041         break; // VT100
1042     case TY_CSI_PR('l', 1):
1043         resetMode(MODE_AppCuKeys);
1044         break; // VT100
1045     case TY_CSI_PR('s', 1):
1046         saveMode(MODE_AppCuKeys);
1047         break; // FIXME
1048     case TY_CSI_PR('r', 1):
1049         restoreMode(MODE_AppCuKeys);
1050         break; // FIXME
1051 
1052     case TY_CSI_PR('l', 2):
1053         resetMode(MODE_Ansi);
1054         break; // VT100
1055 
1056     case TY_CSI_PR('h', 3):
1057         setMode(MODE_132Columns);
1058         break; // VT100
1059     case TY_CSI_PR('l', 3):
1060         resetMode(MODE_132Columns);
1061         break; // VT100
1062 
1063     case TY_CSI_PR('h', 4): /* IGNORED: soft scrolling           */
1064         break; // VT100
1065     case TY_CSI_PR('l', 4): /* IGNORED: soft scrolling           */
1066         break; // VT100
1067 
1068     case TY_CSI_PR('h', 5):
1069         _currentScreen->setMode(MODE_Screen);
1070         break; // VT100
1071     case TY_CSI_PR('l', 5):
1072         _currentScreen->resetMode(MODE_Screen);
1073         break; // VT100
1074 
1075     case TY_CSI_PR('h', 6):
1076         _currentScreen->setMode(MODE_Origin);
1077         break; // VT100
1078     case TY_CSI_PR('l', 6):
1079         _currentScreen->resetMode(MODE_Origin);
1080         break; // VT100
1081     case TY_CSI_PR('s', 6):
1082         _currentScreen->saveMode(MODE_Origin);
1083         break; // FIXME
1084     case TY_CSI_PR('r', 6):
1085         _currentScreen->restoreMode(MODE_Origin);
1086         break; // FIXME
1087 
1088     case TY_CSI_PR('h', 7):
1089         _currentScreen->setMode(MODE_Wrap);
1090         break; // VT100
1091     case TY_CSI_PR('l', 7):
1092         _currentScreen->resetMode(MODE_Wrap);
1093         break; // VT100
1094     case TY_CSI_PR('s', 7):
1095         _currentScreen->saveMode(MODE_Wrap);
1096         break; // FIXME
1097     case TY_CSI_PR('r', 7):
1098         _currentScreen->restoreMode(MODE_Wrap);
1099         break; // FIXME
1100 
1101     case TY_CSI_PR('h', 8): /* IGNORED: autorepeat on            */
1102         break; // VT100
1103     case TY_CSI_PR('l', 8): /* IGNORED: autorepeat off           */
1104         break; // VT100
1105     case TY_CSI_PR('s', 8): /* IGNORED: autorepeat on            */
1106         break; // VT100
1107     case TY_CSI_PR('r', 8): /* IGNORED: autorepeat off           */
1108         break; // VT100
1109 
1110     case TY_CSI_PR('h', 9): /* IGNORED: interlace                */
1111         break; // VT100
1112     case TY_CSI_PR('l', 9): /* IGNORED: interlace                */
1113         break; // VT100
1114     case TY_CSI_PR('s', 9): /* IGNORED: interlace                */
1115         break; // VT100
1116     case TY_CSI_PR('r', 9): /* IGNORED: interlace                */
1117         break; // VT100
1118 
1119     case TY_CSI_PR('h', 12): /* IGNORED: Cursor blink             */
1120         break; // att610
1121     case TY_CSI_PR('l', 12): /* IGNORED: Cursor blink             */
1122         break; // att610
1123     case TY_CSI_PR('s', 12): /* IGNORED: Cursor blink             */
1124         break; // att610
1125     case TY_CSI_PR('r', 12): /* IGNORED: Cursor blink             */
1126         break; // att610
1127 
1128     case TY_CSI_PR('h', 25):
1129         setMode(MODE_Cursor);
1130         break; // VT100
1131     case TY_CSI_PR('l', 25):
1132         resetMode(MODE_Cursor);
1133         break; // VT100
1134     case TY_CSI_PR('s', 25):
1135         saveMode(MODE_Cursor);
1136         break; // VT100
1137     case TY_CSI_PR('r', 25):
1138         restoreMode(MODE_Cursor);
1139         break; // VT100
1140 
1141     case TY_CSI_PR('h', 40):
1142         setMode(MODE_Allow132Columns);
1143         break; // XTERM
1144     case TY_CSI_PR('l', 40):
1145         resetMode(MODE_Allow132Columns);
1146         break; // XTERM
1147 
1148     case TY_CSI_PR('h', 41): /* IGNORED: obsolete more(1) fix     */
1149         break; // XTERM
1150     case TY_CSI_PR('l', 41): /* IGNORED: obsolete more(1) fix     */
1151         break; // XTERM
1152     case TY_CSI_PR('s', 41): /* IGNORED: obsolete more(1) fix     */
1153         break; // XTERM
1154     case TY_CSI_PR('r', 41): /* IGNORED: obsolete more(1) fix     */
1155         break; // XTERM
1156 
1157     case TY_CSI_PR('h', 47):
1158         setMode(MODE_AppScreen);
1159         break; // VT100
1160     case TY_CSI_PR('l', 47):
1161         resetMode(MODE_AppScreen);
1162         break; // VT100
1163     case TY_CSI_PR('s', 47):
1164         saveMode(MODE_AppScreen);
1165         break; // XTERM
1166     case TY_CSI_PR('r', 47):
1167         restoreMode(MODE_AppScreen);
1168         break; // XTERM
1169 
1170     case TY_CSI_PR('h', 67): /* IGNORED: DECBKM                   */
1171         break; // XTERM
1172     case TY_CSI_PR('l', 67): /* IGNORED: DECBKM                   */
1173         break; // XTERM
1174     case TY_CSI_PR('s', 67): /* IGNORED: DECBKM                   */
1175         break; // XTERM
1176     case TY_CSI_PR('r', 67): /* IGNORED: DECBKM                   */
1177         break; // XTERM
1178 
1179         // XTerm defines the following modes:
1180         // SET_VT200_MOUSE             1000
1181         // SET_VT200_HIGHLIGHT_MOUSE   1001
1182         // SET_BTN_EVENT_MOUSE         1002
1183         // SET_ANY_EVENT_MOUSE         1003
1184         //
1185 
1186         // Note about mouse modes:
1187         // There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003
1188         // Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).
1189         // TODO:  Implementation of mouse modes 1001 (something called hilight tracking) and
1190         // 1003 (a slight variation on dragging the mouse)
1191         //
1192 
1193     case TY_CSI_PR('h', 1000):
1194         setMode(MODE_Mouse1000);
1195         break; // XTERM
1196     case TY_CSI_PR('l', 1000):
1197         resetMode(MODE_Mouse1000);
1198         break; // XTERM
1199     case TY_CSI_PR('s', 1000):
1200         saveMode(MODE_Mouse1000);
1201         break; // XTERM
1202     case TY_CSI_PR('r', 1000):
1203         restoreMode(MODE_Mouse1000);
1204         break; // XTERM
1205 
1206     case TY_CSI_PR('h', 1001): /* IGNORED: hilite mouse tracking    */
1207         break; // XTERM
1208     case TY_CSI_PR('l', 1001):
1209         resetMode(MODE_Mouse1001);
1210         break; // XTERM
1211     case TY_CSI_PR('s', 1001): /* IGNORED: hilite mouse tracking    */
1212         break; // XTERM
1213     case TY_CSI_PR('r', 1001): /* IGNORED: hilite mouse tracking    */
1214         break; // XTERM
1215 
1216     case TY_CSI_PR('h', 1002):
1217         setMode(MODE_Mouse1002);
1218         break; // XTERM
1219     case TY_CSI_PR('l', 1002):
1220         resetMode(MODE_Mouse1002);
1221         break; // XTERM
1222     case TY_CSI_PR('s', 1002):
1223         saveMode(MODE_Mouse1002);
1224         break; // XTERM
1225     case TY_CSI_PR('r', 1002):
1226         restoreMode(MODE_Mouse1002);
1227         break; // XTERM
1228 
1229     case TY_CSI_PR('h', 1003):
1230         setMode(MODE_Mouse1003);
1231         break; // XTERM
1232     case TY_CSI_PR('l', 1003):
1233         resetMode(MODE_Mouse1003);
1234         break; // XTERM
1235     case TY_CSI_PR('s', 1003):
1236         saveMode(MODE_Mouse1003);
1237         break; // XTERM
1238     case TY_CSI_PR('r', 1003):
1239         restoreMode(MODE_Mouse1003);
1240         break; // XTERM
1241 
1242     case TY_CSI_PR('h', 1004):
1243         _reportFocusEvents = true;
1244         break;
1245     case TY_CSI_PR('l', 1004):
1246         _reportFocusEvents = false;
1247         break;
1248 
1249     case TY_CSI_PR('h', 1005):
1250         setMode(MODE_Mouse1005);
1251         break; // XTERM
1252     case TY_CSI_PR('l', 1005):
1253         resetMode(MODE_Mouse1005);
1254         break; // XTERM
1255     case TY_CSI_PR('s', 1005):
1256         saveMode(MODE_Mouse1005);
1257         break; // XTERM
1258     case TY_CSI_PR('r', 1005):
1259         restoreMode(MODE_Mouse1005);
1260         break; // XTERM
1261 
1262     case TY_CSI_PR('h', 1006):
1263         setMode(MODE_Mouse1006);
1264         break; // XTERM
1265     case TY_CSI_PR('l', 1006):
1266         resetMode(MODE_Mouse1006);
1267         break; // XTERM
1268     case TY_CSI_PR('s', 1006):
1269         saveMode(MODE_Mouse1006);
1270         break; // XTERM
1271     case TY_CSI_PR('r', 1006):
1272         restoreMode(MODE_Mouse1006);
1273         break; // XTERM
1274 
1275     case TY_CSI_PR('h', 1015):
1276         setMode(MODE_Mouse1015);
1277         break; // URXVT
1278     case TY_CSI_PR('l', 1015):
1279         resetMode(MODE_Mouse1015);
1280         break; // URXVT
1281     case TY_CSI_PR('s', 1015):
1282         saveMode(MODE_Mouse1015);
1283         break; // URXVT
1284     case TY_CSI_PR('r', 1015):
1285         restoreMode(MODE_Mouse1015);
1286         break; // URXVT
1287 
1288     case TY_CSI_PR('h', 1034): /* IGNORED: 8bitinput activation     */
1289         break; // XTERM
1290 
1291     case TY_CSI_PR('h', 1047):
1292         setMode(MODE_AppScreen);
1293         break; // XTERM
1294     case TY_CSI_PR('l', 1047):
1295         _alternateScreen->clearEntireScreen();
1296         resetMode(MODE_AppScreen);
1297         break; // XTERM
1298     case TY_CSI_PR('s', 1047):
1299         saveMode(MODE_AppScreen);
1300         break; // XTERM
1301     case TY_CSI_PR('r', 1047):
1302         restoreMode(MODE_AppScreen);
1303         break; // XTERM
1304 
1305     // FIXME: Unitoken: save translations
1306     case TY_CSI_PR('h', 1048):
1307         saveCursor();
1308         break; // XTERM
1309     case TY_CSI_PR('l', 1048):
1310         restoreCursor();
1311         break; // XTERM
1312     case TY_CSI_PR('s', 1048):
1313         saveCursor();
1314         break; // XTERM
1315     case TY_CSI_PR('r', 1048):
1316         restoreCursor();
1317         break; // XTERM
1318 
1319     // FIXME: every once new sequences like this pop up in xterm.
1320     //        Here's a guess of what they could mean.
1321     case TY_CSI_PR('h', 1049):
1322         saveCursor();
1323         _alternateScreen->clearEntireScreen();
1324         setMode(MODE_AppScreen);
1325         break; // XTERM
1326     case TY_CSI_PR('l', 1049):
1327         resetMode(MODE_AppScreen);
1328         restoreCursor();
1329         break; // XTERM
1330 
1331     case TY_CSI_PR('h', 2004):
1332         setMode(MODE_BracketedPaste);
1333         break; // XTERM
1334     case TY_CSI_PR('l', 2004):
1335         resetMode(MODE_BracketedPaste);
1336         break; // XTERM
1337     case TY_CSI_PR('s', 2004):
1338         saveMode(MODE_BracketedPaste);
1339         break; // XTERM
1340     case TY_CSI_PR('r', 2004):
1341         restoreMode(MODE_BracketedPaste);
1342         break; // XTERM
1343 
1344     // FIXME: weird DEC reset sequence
1345     case TY_CSI_PE('p'): /* IGNORED: reset         (        ) */
1346         break;
1347 
1348     // FIXME: when changing between vt52 and ansi mode evtl do some resetting.
1349     case TY_VT52('A'):
1350         _currentScreen->cursorUp(1);
1351         break; // VT52
1352     case TY_VT52('B'):
1353         _currentScreen->cursorDown(1);
1354         break; // VT52
1355     case TY_VT52('C'):
1356         _currentScreen->cursorRight(1);
1357         break; // VT52
1358     case TY_VT52('D'):
1359         _currentScreen->cursorLeft(1);
1360         break; // VT52
1361 
1362     case TY_VT52('F'):
1363         setAndUseCharset(0, '0');
1364         break; // VT52
1365     case TY_VT52('G'):
1366         setAndUseCharset(0, 'B');
1367         break; // VT52
1368 
1369     case TY_VT52('H'):
1370         _currentScreen->setCursorYX(1, 1);
1371         break; // VT52
1372     case TY_VT52('I'):
1373         _currentScreen->reverseIndex();
1374         break; // VT52
1375     case TY_VT52('J'):
1376         _currentScreen->clearToEndOfScreen();
1377         break; // VT52
1378     case TY_VT52('K'):
1379         _currentScreen->clearToEndOfLine();
1380         break; // VT52
1381     case TY_VT52('Y'):
1382         _currentScreen->setCursorYX(p - 31, q - 31);
1383         break; // VT52
1384     case TY_VT52('Z'):
1385         reportTerminalType();
1386         break; // VT52
1387     case TY_VT52('<'):
1388         setMode(MODE_Ansi);
1389         break; // VT52
1390     case TY_VT52('='):
1391         setMode(MODE_AppKeyPad);
1392         break; // VT52
1393     case TY_VT52('>'):
1394         resetMode(MODE_AppKeyPad);
1395         break; // VT52
1396 
1397     case TY_CSI_PG('c'):
1398         reportSecondaryAttributes();
1399         break; // VT100
1400 
1401     default:
1402         reportDecodingError();
1403         break;
1404     };
1405 }
1406 
1407 void Vt102Emulation::clearScreenAndSetColumns(int columnCount)
1408 {
1409     setImageSize(_currentScreen->getLines(), columnCount);
1410     clearEntireScreen();
1411     setDefaultMargins();
1412     _currentScreen->setCursorYX(0, 0);
1413 }
1414 
1415 void Vt102Emulation::sendString(const char *s, int length)
1416 {
1417     if (length >= 0)
1418         Q_EMIT sendData(s, length);
1419     else
1420         Q_EMIT sendData(s, strlen(s));
1421 }
1422 
1423 void Vt102Emulation::reportCursorPosition()
1424 {
1425     const size_t sz = 20;
1426     char tmp[sz];
1427     const size_t r = snprintf(tmp, sz, "\033[%d;%dR", _currentScreen->getCursorY() + 1, _currentScreen->getCursorX() + 1);
1428     if (sz <= r) {
1429         qWarning("Vt102Emulation::reportCursorPosition: Buffer too small\n");
1430     }
1431     sendString(tmp);
1432 }
1433 
1434 void Vt102Emulation::reportTerminalType()
1435 {
1436     // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
1437     // VT220:  ^[[?63;1;2;3;6;7;8c   (list deps on emul. capabilities)
1438     // VT100:  ^[[?1;2c
1439     // VT101:  ^[[?1;0c
1440     // VT102:  ^[[?6v
1441     if (getMode(MODE_Ansi))
1442         sendString("\033[?1;2c"); // I'm a VT100
1443     else
1444         sendString("\033/Z"); // I'm a VT52
1445 }
1446 
1447 void Vt102Emulation::reportSecondaryAttributes()
1448 {
1449     // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
1450     if (getMode(MODE_Ansi))
1451         sendString("\033[>0;115;0c"); // Why 115?  ;)
1452     else
1453         sendString("\033/Z"); // FIXME I don't think VT52 knows about it but kept for
1454                               // konsoles backward compatibility.
1455 }
1456 
1457 void Vt102Emulation::reportTerminalParms(int p)
1458 // DECREPTPARM
1459 {
1460     const size_t sz = 100;
1461     char tmp[sz];
1462     const size_t r = snprintf(tmp, sz, "\033[%d;1;1;112;112;1;0x", p); // not really true.
1463     if (sz <= r) {
1464         qWarning("Vt102Emulation::reportTerminalParms: Buffer too small\n");
1465     }
1466     sendString(tmp);
1467 }
1468 
1469 void Vt102Emulation::reportStatus()
1470 {
1471     sendString("\033[0n"); // VT100. Device status report. 0 = Ready.
1472 }
1473 
1474 void Vt102Emulation::reportAnswerBack()
1475 {
1476     // FIXME - Test this with VTTEST
1477     // This is really obsolete VT100 stuff.
1478     const char *ANSWER_BACK = "";
1479     sendString(ANSWER_BACK);
1480 }
1481 
1482 /*!
1483     `cx',`cy' are 1-based.
1484     `cb' indicates the button pressed or released (0-2) or scroll event (4-5).
1485 
1486     eventType represents the kind of mouse action that occurred:
1487         0 = Mouse button press
1488         1 = Mouse drag
1489         2 = Mouse button release
1490 */
1491 
1492 void Vt102Emulation::sendMouseEvent(int cb, int cx, int cy, int eventType)
1493 {
1494     if (cx < 1 || cy < 1)
1495         return;
1496 
1497     // With the exception of the 1006 mode, button release is encoded in cb.
1498     // Note that if multiple extensions are enabled, the 1006 is used, so it's okay to check for only that.
1499     if (eventType == 2 && !getMode(MODE_Mouse1006))
1500         cb = 3;
1501 
1502     // normal buttons are passed as 0x20 + button,
1503     // mouse wheel (buttons 4,5) as 0x5c + button
1504     if (cb >= 4)
1505         cb += 0x3c;
1506 
1507     // Mouse motion handling
1508     if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
1509         cb += 0x20; // add 32 to signify motion event
1510 
1511     char command[32];
1512     command[0] = '\0';
1513     // Check the extensions in decreasing order of preference. Encoding the release event above assumes that 1006 comes first.
1514     if (getMode(MODE_Mouse1006)) {
1515         snprintf(command, sizeof(command), "\033[<%d;%d;%d%c", cb, cx, cy, eventType == 2 ? 'm' : 'M');
1516     } else if (getMode(MODE_Mouse1015)) {
1517         snprintf(command, sizeof(command), "\033[%d;%d;%dM", cb + 0x20, cx, cy);
1518     } else if (getMode(MODE_Mouse1005)) {
1519         if (cx <= 2015 && cy <= 2015) {
1520             // The xterm extension uses UTF-8 (up to 2 bytes) to encode
1521             // coordinate+32, no matter what the locale is. We could easily
1522             // convert manually, but QString can also do it for us.
1523             QChar coords[2];
1524             coords[0] = QChar(cx + 0x20);
1525             coords[1] = QChar(cy + 0x20);
1526             QString coordsStr = QString(coords, 2);
1527             QByteArray utf8 = coordsStr.toUtf8();
1528             snprintf(command, sizeof(command), "\033[M%c%s", cb + 0x20, utf8.constData());
1529         }
1530     } else if (cx <= 223 && cy <= 223) {
1531         snprintf(command, sizeof(command), "\033[M%c%c%c", cb + 0x20, cx + 0x20, cy + 0x20);
1532     }
1533 
1534     sendString(command);
1535 }
1536 
1537 /**
1538  * The focus lost event can be used by Vim (or other terminal applications)
1539  * to recognize that the konsole window has lost focus.
1540  * The escape sequence is also used by iTerm2.
1541  * Vim needs the following plugin to be installed to convert the escape
1542  * sequence into the FocusLost autocmd: https://github.com/sjl/vitality.vim
1543  */
1544 void Vt102Emulation::focusLost(void)
1545 {
1546     if (_reportFocusEvents)
1547         sendString("\033[O");
1548 }
1549 
1550 /**
1551  * The focus gained event can be used by Vim (or other terminal applications)
1552  * to recognize that the konsole window has gained focus again.
1553  * The escape sequence is also used by iTerm2.
1554  * Vim needs the following plugin to be installed to convert the escape
1555  * sequence into the FocusGained autocmd: https://github.com/sjl/vitality.vim
1556  */
1557 void Vt102Emulation::focusGained(void)
1558 {
1559     if (_reportFocusEvents)
1560         sendString("\033[I");
1561 }
1562 
1563 void Vt102Emulation::sendText(const QString &text)
1564 {
1565     if (!text.isEmpty()) {
1566         QKeyEvent event(QEvent::KeyPress, 0, Qt::NoModifier, text);
1567         sendKeyEvent(&event, false); // expose as a big fat keypress event
1568     }
1569 }
1570 //<<<<<<< HEAD
1571 
1572 QKeyEvent *Vt102Emulation::remapKeyModifiersForMac(QKeyEvent *event)
1573 {
1574     Qt::KeyboardModifiers modifiers = event->modifiers();
1575 
1576     QFlags<Qt::KeyboardModifier> isTheLabeledKeyCommandPressed = modifiers & Qt::ControlModifier;
1577     QFlags<Qt::KeyboardModifier> isTheLabeledKeyControlPressed = modifiers & Qt::MetaModifier;
1578     if (isTheLabeledKeyCommandPressed) {
1579         qDebug("Command is pressed.");
1580         modifiers &= ~Qt::ControlModifier;
1581         modifiers |= Qt::MetaModifier;
1582     } else {
1583         modifiers &= ~Qt::MetaModifier;
1584     }
1585 
1586     if (isTheLabeledKeyControlPressed) {
1587         qDebug("Control is pressed.");
1588         modifiers &= ~Qt::MetaModifier;
1589         modifiers |= Qt::ControlModifier;
1590     } else {
1591         modifiers &= ~Qt::ControlModifier;
1592     }
1593 
1594     return new QKeyEvent(QEvent::None,
1595                          event->key(),
1596                          modifiers,
1597                          event->nativeScanCode(),
1598                          event->nativeVirtualKey(),
1599                          event->nativeModifiers(),
1600                          event->text(),
1601                          event->isAutoRepeat(),
1602                          event->count());
1603 }
1604 
1605 void Vt102Emulation::sendKeyEvent(QKeyEvent *origEvent, bool fromPaste)
1606 {
1607 #if defined(Q_OS_MAC)
1608     QScopedPointer<QKeyEvent> event(remapKeyModifiersForMac(origEvent));
1609 #else
1610     QKeyEvent *event = origEvent;
1611 #endif
1612     Qt::KeyboardModifiers modifiers = event->modifiers();
1613     KeyboardTranslator::States states = KeyboardTranslator::NoState;
1614 
1615     // get current states
1616     if (getMode(MODE_NewLine))
1617         states |= KeyboardTranslator::NewLineState;
1618     if (getMode(MODE_Ansi))
1619         states |= KeyboardTranslator::AnsiState;
1620     if (getMode(MODE_AppCuKeys))
1621         states |= KeyboardTranslator::CursorKeysState;
1622     if (getMode(MODE_AppScreen))
1623         states |= KeyboardTranslator::AlternateScreenState;
1624     if (getMode(MODE_AppKeyPad) && (modifiers & Qt::KeypadModifier))
1625         states |= KeyboardTranslator::ApplicationKeypadState;
1626 
1627     // check flow control state
1628     if (modifiers & KeyboardTranslator::CTRL_MOD) {
1629         switch (event->key()) {
1630         case Qt::Key_S:
1631             Q_EMIT flowControlKeyPressed(true);
1632             break;
1633         case Qt::Key_Q:
1634         case Qt::Key_C: // cancel flow control
1635             Q_EMIT flowControlKeyPressed(false);
1636             break;
1637         }
1638     }
1639 
1640     // lookup key binding
1641     if (_keyTranslator) {
1642         KeyboardTranslator::Entry entry = _keyTranslator->findEntry(event->key(), modifiers, states);
1643         // send result to terminal
1644         QByteArray textToSend;
1645 
1646         // special handling for the Alt (aka. Meta) modifier.  pressing
1647         // Alt+[Character] results in Esc+[Character] being sent
1648         // (unless there is an entry defined for this particular combination
1649         //  in the keyboard modifier)
1650 
1651         bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;
1652         bool wantsMetaModifier = entry.modifiers() & entry.modifierMask() & Qt::MetaModifier;
1653         bool wantsAnyModifier = entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState;
1654 
1655         if (modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier) && !event->text().isEmpty()) {
1656             textToSend.prepend("\033");
1657         }
1658         if (modifiers & Qt::MetaModifier && !(wantsMetaModifier || wantsAnyModifier) && !event->text().isEmpty()) {
1659             textToSend.prepend("\030@s");
1660         }
1661 
1662         if (entry.command() != KeyboardTranslator::NoCommand) {
1663             if (entry.command() & KeyboardTranslator::EraseCommand) {
1664                 textToSend += eraseChar();
1665             } else {
1666                 Q_EMIT handleCommandFromKeyboard(entry.command());
1667             }
1668 
1669             // TODO command handling
1670         } else if (!entry.text().isEmpty()) {
1671             textToSend += entry.text(true, modifiers);
1672         } else if ((modifiers & KeyboardTranslator::CTRL_MOD) && event->key() >= 0x40 && event->key() < 0x5f) {
1673             textToSend += (event->key() & 0x1f);
1674         } else if (event->key() == Qt::Key_Tab) {
1675             textToSend += 0x09;
1676         } else if (event->key() == Qt::Key_PageUp) {
1677             textToSend += "\033[5~";
1678         } else if (event->key() == Qt::Key_PageDown) {
1679             textToSend += "\033[6~";
1680         } else {
1681             textToSend += _codec->fromUnicode(event->text());
1682         }
1683 
1684         if (!fromPaste && textToSend.length()) {
1685             Q_EMIT outputFromKeypressEvent();
1686         }
1687         Q_EMIT sendData(textToSend.constData(), textToSend.length());
1688     } else {
1689         // print an error message to the terminal if no key translator has been
1690         // set
1691         QString translatorError =
1692             tr("No keyboard translator available.  "
1693                "The information needed to convert key presses "
1694                "into characters to send to the terminal "
1695                "is missing.");
1696         reset();
1697         receiveData(translatorError.toUtf8().constData(), translatorError.size());
1698     }
1699 }
1700 
1701 /* ------------------------------------------------------------------------- */
1702 /*                                                                           */
1703 /*                                VT100 Charsets                             */
1704 /*                                                                           */
1705 /* ------------------------------------------------------------------------- */
1706 
1707 // Character Set Conversion ------------------------------------------------ --
1708 
1709 /*
1710    The processing contains a VT100 specific code translation layer.
1711    It's still in use and mainly responsible for the line drawing graphics.
1712 
1713    These and some other glyphs are assigned to codes (0x5f-0xfe)
1714    normally occupied by the latin letters. Since this codes also
1715    appear within control sequences, the extra code conversion
1716    does not permute with the tokenizer and is placed behind it
1717    in the pipeline. It only applies to tokens, which represent
1718    plain characters.
1719 
1720    This conversion it eventually continued in TerminalDisplay.C, since
1721    it might involve VT100 enhanced fonts, which have these
1722    particular glyphs allocated in (0x00-0x1f) in their code page.
1723 */
1724 
1725 #define CHARSET _charset[_currentScreen == _alternateScreen.get()]
1726 
1727 // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
1728 
1729 constexpr std::array<unsigned short, 32> vt100_graphics = { // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15
1730     0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
1731     0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7};
1732 
1733 // Apply current character map.
1734 
1735 wchar_t Vt102Emulation::applyCharset(char16_t c)
1736 {
1737     if (CHARSET.graphic && 0x5f <= c && c <= 0x7e)
1738         return vt100_graphics[c - 0x5f];
1739     if (CHARSET.pound && c == '#')
1740         return 0xa3; // This mode is obsolete
1741     return c;
1742 }
1743 
1744 /*
1745    "Charset" related part of the emulation state.
1746    This configures the VT100 charset filter.
1747 
1748    While most operation work on the current _screen,
1749    the following two are different.
1750 */
1751 
1752 void Vt102Emulation::resetCharset(int scrno)
1753 {
1754     _charset[scrno].cu_cs = 0;
1755     qstrncpy(_charset[scrno].charset, "BBBB", 4);
1756     _charset[scrno].sa_graphic = false;
1757     _charset[scrno].sa_pound = false;
1758     _charset[scrno].graphic = false;
1759     _charset[scrno].pound = false;
1760 }
1761 
1762 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
1763 {
1764     _charset[0].charset[n & 3] = cs;
1765     useCharset(_charset[0].cu_cs);
1766     _charset[1].charset[n & 3] = cs;
1767     useCharset(_charset[1].cu_cs);
1768 }
1769 
1770 void Vt102Emulation::setAndUseCharset(int n, int cs)
1771 {
1772     CHARSET.charset[n & 3] = cs;
1773     useCharset(n & 3);
1774 }
1775 
1776 void Vt102Emulation::useCharset(int n)
1777 {
1778     CHARSET.cu_cs = n & 3;
1779     CHARSET.graphic = (CHARSET.charset[n & 3] == '0');
1780     CHARSET.pound = (CHARSET.charset[n & 3] == 'A'); // This mode is obsolete
1781 }
1782 
1783 void Vt102Emulation::setDefaultMargins()
1784 {
1785     _primaryScreen->setDefaultMargins();
1786     _alternateScreen->setDefaultMargins();
1787 }
1788 
1789 void Vt102Emulation::setMargins(int t, int b)
1790 {
1791     _primaryScreen->setMargins(t, b);
1792     _alternateScreen->setMargins(t, b);
1793 }
1794 
1795 void Vt102Emulation::saveCursor()
1796 {
1797     CHARSET.sa_graphic = CHARSET.graphic;
1798     CHARSET.sa_pound = CHARSET.pound; // This mode is obsolete
1799     // we are not clear about these
1800     // sa_charset = charsets[cScreen->_charset];
1801     // sa_charset_num = cScreen->_charset;
1802     _currentScreen->saveCursor();
1803 }
1804 
1805 void Vt102Emulation::restoreCursor()
1806 {
1807     CHARSET.graphic = CHARSET.sa_graphic;
1808     CHARSET.pound = CHARSET.sa_pound; // This mode is obsolete
1809     _currentScreen->restoreCursor();
1810 }
1811 
1812 /* ------------------------------------------------------------------------- */
1813 /*                                                                           */
1814 /*                                Mode Operations                            */
1815 /*                                                                           */
1816 /* ------------------------------------------------------------------------- */
1817 
1818 /*
1819    Some of the emulations state is either added to the state of the screens.
1820 
1821    This causes some scoping problems, since different emulations choose to
1822    located the mode either to the current _screen or to both.
1823 
1824    For strange reasons, the extend of the rendition attributes ranges over
1825    all screens and not over the actual _screen.
1826 
1827    We decided on the precise precise extend, somehow.
1828 */
1829 
1830 // "Mode" related part of the state. These are all booleans.
1831 
1832 void Vt102Emulation::resetModes()
1833 {
1834     // MODE_Allow132Columns is not reset here
1835     // to match Xterm's behaviour (see Xterm's VTReset() function)
1836 
1837     resetMode(MODE_132Columns);
1838     saveMode(MODE_132Columns);
1839     resetMode(MODE_Mouse1000);
1840     saveMode(MODE_Mouse1000);
1841     resetMode(MODE_Mouse1001);
1842     saveMode(MODE_Mouse1001);
1843     resetMode(MODE_Mouse1002);
1844     saveMode(MODE_Mouse1002);
1845     resetMode(MODE_Mouse1003);
1846     saveMode(MODE_Mouse1003);
1847     resetMode(MODE_Mouse1005);
1848     saveMode(MODE_Mouse1005);
1849     resetMode(MODE_Mouse1006);
1850     saveMode(MODE_Mouse1006);
1851     resetMode(MODE_Mouse1015);
1852     saveMode(MODE_Mouse1015);
1853     resetMode(MODE_BracketedPaste);
1854     saveMode(MODE_BracketedPaste);
1855 
1856     resetMode(MODE_AppScreen);
1857     saveMode(MODE_AppScreen);
1858     resetMode(MODE_AppCuKeys);
1859     saveMode(MODE_AppCuKeys);
1860     resetMode(MODE_AppKeyPad);
1861     saveMode(MODE_AppKeyPad);
1862     resetMode(MODE_NewLine);
1863     setMode(MODE_Ansi);
1864 }
1865 
1866 void Vt102Emulation::setMode(int m)
1867 {
1868     _currentModes.mode[m] = true;
1869     switch (m) {
1870     case MODE_132Columns:
1871         if (getMode(MODE_Allow132Columns))
1872             clearScreenAndSetColumns(132);
1873         else
1874             _currentModes.mode[m] = false;
1875         break;
1876     case MODE_Mouse1000:
1877     case MODE_Mouse1001:
1878     case MODE_Mouse1002:
1879     case MODE_Mouse1003:
1880         Q_EMIT programUsesMouseChanged(false);
1881         break;
1882 
1883     case MODE_BracketedPaste:
1884         Q_EMIT programBracketedPasteModeChanged(true);
1885 
1886         break;
1887 
1888     case MODE_AppScreen:
1889         _alternateScreen->clearSelection();
1890         setScreen(1);
1891         break;
1892     }
1893     if (m < MODES_SCREEN || m == MODE_NewLine) {
1894         _primaryScreen->setMode(m);
1895         _alternateScreen->setMode(m);
1896     }
1897 }
1898 
1899 void Vt102Emulation::resetMode(int m)
1900 {
1901     _currentModes.mode[m] = false;
1902     switch (m) {
1903     case MODE_132Columns:
1904         if (getMode(MODE_Allow132Columns))
1905             clearScreenAndSetColumns(80);
1906         break;
1907     case MODE_Mouse1000:
1908     case MODE_Mouse1001:
1909     case MODE_Mouse1002:
1910     case MODE_Mouse1003:
1911         Q_EMIT programUsesMouseChanged(true);
1912         break;
1913 
1914     case MODE_BracketedPaste:
1915         Q_EMIT programBracketedPasteModeChanged(false);
1916         break;
1917 
1918     case MODE_AppScreen:
1919         _primaryScreen->clearSelection();
1920         setScreen(0);
1921         break;
1922     }
1923     if (m < MODES_SCREEN || m == MODE_NewLine) {
1924         _primaryScreen->resetMode(m);
1925         _alternateScreen->resetMode(m);
1926     }
1927 }
1928 
1929 void Vt102Emulation::saveMode(int m)
1930 {
1931     _savedModes.mode[m] = _currentModes.mode[m];
1932 }
1933 
1934 void Vt102Emulation::restoreMode(int m)
1935 {
1936     if (_savedModes.mode[m])
1937         setMode(m);
1938     else
1939         resetMode(m);
1940 }
1941 
1942 bool Vt102Emulation::getMode(int m)
1943 {
1944     return _currentModes.mode[m];
1945 }
1946 
1947 char Vt102Emulation::eraseChar() const
1948 {
1949     KeyboardTranslator::Entry entry = _keyTranslator->findEntry(Qt::Key_Backspace, Qt::NoModifier, KeyboardTranslator::NoState);
1950     if (entry.text().size() > 0)
1951         return entry.text().at(0);
1952     else
1953         return '\b';
1954 }
1955 
1956 void Vt102Emulation::reportDecodingError()
1957 {
1958     if (tokenBufferPos == 0 || (tokenBufferPos == 1 && (tokenBuffer[0] & 0xff) >= 32))
1959         return;
1960     qCDebug(qtermwidgetLogger) << "Undecodable sequence:" << QString::fromUtf16(tokenBuffer, tokenBufferPos);
1961 }
1962 
1963 // #include "Vt102Emulation.moc"