~verzegnassi-stefano/+junk/ubuntu-terminal-app-uitk13

« back to all changes in this revision

Viewing changes to src/plugin/qmltermwidget/qtermwidget/lib/Vt102Emulation.cpp

  • Committer: Filippo Scognamiglio
  • Date: 2014-10-25 04:42:31 UTC
  • Revision ID: flscogna@gmail.com-20141025044231-javjhusbqa171127
Initial reboot commit.

Show diffs side-by-side

added added

removed removed

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