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