source: ogBrowser-Git/qtermwidget/lib/Vt102Emulation.cpp

jenkins
Last change on this file was fedf2a2, checked in by Vadim Troshchinskiy Shmelev <vtroshchinskiy@…>, 18 months ago

Update Qtermwidget to Qt6 version
Remove build files

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