Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / apps / konsole / src / Vt102Emulation.cpp
blob8dd2de6f592a4e4d9b740e26c2818eaf7de06572
1 /*
2 This file is part of Konsole, an X terminal.
3 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301 USA.
21 // Own
22 #include "Vt102Emulation.h"
24 #include <config-konsole.h>
27 #if defined(__osf__) || defined(__APPLE__)
28 #define AVOID_XKB
29 #endif
31 // this allows konsole to be compiled without XKB and XTEST extensions
32 // even though it might be available on a particular system.
33 #if defined(AVOID_XKB)
34 #undef HAVE_XKB
35 #endif
37 // Standard
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <assert.h>
42 // Qt
43 #include <QtCore/QEvent>
44 #include <QtGui/QKeyEvent>
45 #include <QtCore/QByteRef>
47 // KDE
48 #include <kdebug.h>
49 #include <klocale.h>
51 // Konsole
52 #include "KeyboardTranslator.h"
53 #include "Screen.h"
55 #if defined(HAVE_XKB)
56 void scrolllock_set_off();
57 void scrolllock_set_on();
58 #endif
60 using namespace Konsole;
62 /* VT102 Terminal Emulation
64 This class puts together the screens, the pty and the widget to a
65 complete terminal emulation. Beside combining it's componentes, it
66 handles the emulations's protocol.
68 This module consists of the following sections:
70 - Constructor/Destructor
71 - Incoming Bytes Event pipeline
72 - Outgoing Bytes
73 - Mouse Events
74 - Keyboard Events
75 - Modes and Charset State
76 - Diagnostics
79 /* ------------------------------------------------------------------------- */
80 /* */
81 /* Constructor / Destructor */
82 /* */
83 /* ------------------------------------------------------------------------- */
86 Vt102Emulation::Vt102Emulation()
87 : Emulation(),
88 _titleUpdateTimer(new QTimer(this))
90 _titleUpdateTimer->setSingleShot(true);
92 QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));
94 initTokenizer();
95 reset();
98 Vt102Emulation::~Vt102Emulation()
102 void Vt102Emulation::clearEntireScreen()
104 _currentScreen->clearEntireScreen();
106 bufferedUpdate();
109 void Vt102Emulation::reset()
111 //kDebug(1211)<<"Vt102Emulation::reset() resetToken()";
112 resetToken();
113 //kDebug(1211)<<"Vt102Emulation::reset() resetModes()";
114 resetModes();
115 //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()";
116 resetCharset(0);
117 //kDebug(1211)<<"Vt102Emulation::reset() reset screen0()";
118 _screen[0]->reset();
119 //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()";
120 resetCharset(1);
121 //kDebug(1211)<<"Vt102Emulation::reset() reset _screen 1";
122 _screen[1]->reset();
123 //kDebug(1211)<<"Vt102Emulation::reset() setCodec()";
124 setCodec(LocaleCodec);
125 //kDebug(1211)<<"Vt102Emulation::reset() done";
127 bufferedUpdate();
130 /* ------------------------------------------------------------------------- */
131 /* */
132 /* Processing the incoming byte stream */
133 /* */
134 /* ------------------------------------------------------------------------- */
136 /* Incoming Bytes Event pipeline
138 This section deals with decoding the incoming character stream.
139 Decoding means here, that the stream is first separated into `tokens'
140 which are then mapped to a `meaning' provided as operations by the
141 `Screen' class or by the emulation class itself.
143 The pipeline proceeds as follows:
145 - Tokenizing the ESC codes (onReceiveChar)
146 - VT100 code page translation of plain characters (applyCharset)
147 - Interpretation of ESC codes (tau)
149 The escape codes and their meaning are described in the
150 technical reference of this program.
153 // Tokens ------------------------------------------------------------------ --
156 Since the tokens are the central notion if this section, we've put them
157 in front. They provide the syntactical elements used to represent the
158 terminals operations as byte sequences.
160 They are encodes here into a single machine word, so that we can later
161 switch over them easily. Depending on the token itself, additional
162 argument variables are filled with parameter values.
164 The tokens are defined below:
166 - CHR - Printable characters (32..255 but DEL (=127))
167 - CTL - Control characters (0..31 but ESC (= 27), DEL)
168 - ESC - Escape codes of the form <ESC><CHR but `[]()+*#'>
169 - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
170 - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
171 - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
172 - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
173 - CSI_PE - Escape codes of the form <ESC>'[' '!' {Pn} ';' ... C
174 - VT52 - VT52 escape codes
175 - <ESC><Chr>
176 - <ESC>'Y'{Pc}{Pc}
177 - XTE_HA - Xterm hacks <ESC>`]' {Pn} `;' {Text} <BEL>
178 note that this is handled differently
180 The last two forms allow list of arguments. Since the elements of
181 the lists are treated individually the same way, they are passed
182 as individual tokens to the interpretation. Further, because the
183 meaning of the parameters are names (althought represented as numbers),
184 they are includes within the token ('N').
188 #define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
190 #define TY_CHR( ) TY_CONSTR(0,0,0)
191 #define TY_CTL(A ) TY_CONSTR(1,A,0)
192 #define TY_ESC(A ) TY_CONSTR(2,A,0)
193 #define TY_ESC_CS(A,B) TY_CONSTR(3,A,B)
194 #define TY_ESC_DE(A ) TY_CONSTR(4,A,0)
195 #define TY_CSI_PS(A,N) TY_CONSTR(5,A,N)
196 #define TY_CSI_PN(A ) TY_CONSTR(6,A,0)
197 #define TY_CSI_PR(A,N) TY_CONSTR(7,A,N)
199 #define TY_VT52(A ) TY_CONSTR(8,A,0)
201 #define TY_CSI_PG(A ) TY_CONSTR(9,A,0)
203 #define TY_CSI_PE(A ) TY_CONSTR(10,A,0)
205 // Tokenizer --------------------------------------------------------------- --
207 /* The tokenizers state
209 The state is represented by the buffer (pbuf, ppos),
210 and accompanied by decoded arguments kept in (argv,argc).
211 Note that they are kept internal in the tokenizer.
214 void Vt102Emulation::resetToken()
216 ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
219 void Vt102Emulation::addDigit(int dig)
221 argv[argc] = 10*argv[argc] + dig;
224 void Vt102Emulation::addArgument()
226 argc = qMin(argc+1,MAXARGS-1);
227 argv[argc] = 0;
230 void Vt102Emulation::pushToToken(int cc)
232 pbuf[ppos] = cc;
233 ppos = qMin(ppos+1,MAXPBUF-1);
236 // Character Classes used while decoding
238 #define CTL 1
239 #define CHR 2
240 #define CPN 4
241 #define DIG 8
242 #define SCS 16
243 #define GRP 32
244 #define CPS 64
246 void Vt102Emulation::initTokenizer()
247 { int i; quint8* s;
248 for(i = 0; i < 256; i++) tbl[ i] = 0;
249 for(i = 0; i < 32; i++) tbl[ i] |= CTL;
250 for(i = 32; i < 256; i++) tbl[ i] |= CHR;
251 for(s = (quint8*)"@ABCDGHILMPSTXZcdfry"; *s; s++) tbl[*s] |= CPN;
252 // resize = \e[8;<row>;<col>t
253 for(s = (quint8*)"t"; *s; s++) tbl[*s] |= CPS;
254 for(s = (quint8*)"0123456789" ; *s; s++) tbl[*s] |= DIG;
255 for(s = (quint8*)"()+*%" ; *s; s++) tbl[*s] |= SCS;
256 for(s = (quint8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP;
257 resetToken();
260 /* Ok, here comes the nasty part of the decoder.
262 Instead of keeping an explicit state, we deduce it from the
263 token scanned so far. It is then immediately combined with
264 the current character to form a scanning decision.
266 This is done by the following defines.
268 - P is the length of the token scanned so far.
269 - L (often P-1) is the position on which contents we base a decision.
270 - C is a character or a group of characters (taken from 'tbl').
272 Note that they need to applied in proper order.
275 #define lec(P,L,C) (p == (P) && s[(L)] == (C))
276 #define lun( ) (p == 1 && cc >= 32 )
277 #define les(P,L,C) (p == (P) && s[L] < 256 && (tbl[s[(L)]] & (C)) == (C))
278 #define eec(C) (p >= 3 && cc == (C))
279 #define ees(C) (p >= 3 && cc < 256 && (tbl[ cc ] & (C)) == (C))
280 #define eps(C) (p >= 3 && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (tbl[ cc ] & (C)) == (C))
281 #define epp( ) (p >= 3 && s[2] == '?' )
282 #define epe( ) (p >= 3 && s[2] == '!' )
283 #define egt( ) (p >= 3 && s[2] == '>' )
284 #define Xpe (ppos>=2 && pbuf[1] == ']' )
285 #define Xte (Xpe && cc == 7 )
286 #define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte)
288 #define ESC 27
289 #define CNTL(c) ((c)-'@')
291 // process an incoming unicode character
293 void Vt102Emulation::receiveChar(int cc)
295 int i;
296 if (cc == 127) return; //VT100: ignore.
298 if (ces( CTL))
299 { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
300 // This means, they do neither a resetToken nor a pushToToken. Some of them, do
301 // of course. Guess this originates from a weakly layered handling of the X-on
302 // X-off protocol, which comes really below this level.
303 if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB
304 if (cc != ESC) { tau( TY_CTL(cc+'@' ), 0, 0); return; }
307 pushToToken(cc); // advance the state
309 int* s = pbuf;
310 int p = ppos;
312 if (getMode(MODE_Ansi)) // decide on proper action
314 if (lec(1,0,ESC)) { return; }
315 if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('['); return; }
316 if (les(2,1,GRP)) { return; }
317 if (Xte ) { XtermHack(); resetToken(); return; }
318 if (Xpe ) { return; }
319 if (lec(3,2,'?')) { return; }
320 if (lec(3,2,'>')) { return; }
321 if (lec(3,2,'!')) { return; }
322 if (lun( )) { tau( TY_CHR(), applyCharset(cc), 0); resetToken(); return; }
323 if (lec(2,0,ESC)) { tau( TY_ESC(s[1]), 0, 0); resetToken(); return; }
324 if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]), 0, 0); resetToken(); return; }
325 if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]), 0, 0); resetToken(); return; }
326 if (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; }
328 // resize = \e[8;<row>;<col>t
329 if (eps( CPS)) { tau( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]); resetToken(); return; }
331 if (epe( )) { tau( TY_CSI_PE(cc), 0, 0); resetToken(); return; }
332 if (ees( DIG)) { addDigit(cc-'0'); return; }
333 if (eec( ';')) { addArgument(); return; }
334 for (i=0;i<=argc;i++)
335 if ( epp( )) { tau( TY_CSI_PR(cc,argv[i]), 0, 0); }
336 else if(egt( )) { tau( TY_CSI_PG(cc ), 0, 0); } // spec. case for ESC]>0c or ESC]>c
337 else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
338 { // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
339 i += 2;
340 tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);
341 i += 2;
343 else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)
344 { // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
345 i += 2;
346 tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_256, argv[i]);
348 else { tau( TY_CSI_PS(cc,argv[i]), 0, 0); }
349 resetToken();
351 else // mode VT52
353 if (lec(1,0,ESC)) return;
354 if (les(1,0,CHR)) { tau( TY_CHR( ), s[0], 0); resetToken(); return; }
355 if (lec(2,1,'Y')) return;
356 if (lec(3,1,'Y')) return;
357 if (p < 4) { tau( TY_VT52(s[1] ), 0, 0); resetToken(); return; }
358 tau( TY_VT52(s[1] ), s[2],s[3]); resetToken(); return;
362 void Vt102Emulation::XtermHack()
363 { int i,arg = 0;
364 for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)
365 arg = 10*arg + (pbuf[i]-'0');
366 if (pbuf[i] != ';') { ReportErrorToken(); return; }
367 QChar *str = new QChar[ppos-i-2];
368 for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
369 QString unistr(str,ppos-i-2);
371 // arg == 1 doesn't change the title. In XTerm it only changes the icon name
372 // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title
373 // emit changeTitle(arg,unistr);
374 _pendingTitleUpdates[arg] = unistr;
375 _titleUpdateTimer->start(20);
377 delete [] str;
380 void Vt102Emulation::updateTitle()
382 QListIterator<int> iter( _pendingTitleUpdates.keys() );
383 while (iter.hasNext()) {
384 int arg = iter.next();
385 emit titleChanged( arg , _pendingTitleUpdates[arg] );
388 _pendingTitleUpdates.clear();
391 // Interpreting Codes ---------------------------------------------------------
394 Now that the incoming character stream is properly tokenized,
395 meaning is assigned to them. These are either operations of
396 the current _screen, or of the emulation class itself.
398 The token to be interpreteted comes in as a machine word
399 possibly accompanied by two parameters.
401 Likewise, the operations assigned to, come with up to two
402 arguments. One could consider to make up a proper table
403 from the function below.
405 The technical reference manual provides more information
406 about this mapping.
409 void Vt102Emulation::tau( int token, int p, int q )
411 #if 0
412 int N = (token>>0)&0xff;
413 int A = (token>>8)&0xff;
414 switch( N )
416 case 0: printf("%c", (p < 128) ? p : '?');
417 break;
418 case 1: if (A == 'J') printf("\r");
419 else if (A == 'M') printf("\n");
420 else printf("CTL-%c ", (token>>8)&0xff);
421 break;
422 case 2: printf("ESC-%c ", (token>>8)&0xff);
423 break;
424 case 3: printf("ESC_CS-%c-%c ", (token>>8)&0xff, (token>>16)&0xff);
425 break;
426 case 4: printf("ESC_DE-%c ", (token>>8)&0xff);
427 break;
428 case 5: printf("CSI-PS-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
429 break;
430 case 6: printf("CSI-PN-%c [%d]", (token>>8)&0xff, p);
431 break;
432 case 7: printf("CSI-PR-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
433 break;
434 case 8: printf("VT52-%c", (token>>8)&0xff);
435 break;
436 case 9: printf("CSI-PG-%c", (token>>8)&0xff);
437 break;
438 case 10: printf("CSI-PE-%c", (token>>8)&0xff);
439 break;
441 #endif
443 switch (token)
446 case TY_CHR( ) : _currentScreen->ShowCharacter (p ); break; //UTF16
448 // 127 DEL : ignored on input
450 case TY_CTL('@' ) : /* NUL: ignored */ break;
451 case TY_CTL('A' ) : /* SOH: ignored */ break;
452 case TY_CTL('B' ) : /* STX: ignored */ break;
453 case TY_CTL('C' ) : /* ETX: ignored */ break;
454 case TY_CTL('D' ) : /* EOT: ignored */ break;
455 case TY_CTL('E' ) : reportAnswerBack ( ); break; //VT100
456 case TY_CTL('F' ) : /* ACK: ignored */ break;
457 case TY_CTL('G' ) : emit stateSet(NOTIFYBELL);
458 break; //VT100
459 case TY_CTL('H' ) : _currentScreen->BackSpace ( ); break; //VT100
460 case TY_CTL('I' ) : _currentScreen->Tabulate ( ); break; //VT100
461 case TY_CTL('J' ) : _currentScreen->NewLine ( ); break; //VT100
462 case TY_CTL('K' ) : _currentScreen->NewLine ( ); break; //VT100
463 case TY_CTL('L' ) : _currentScreen->NewLine ( ); break; //VT100
464 case TY_CTL('M' ) : _currentScreen->Return ( ); break; //VT100
466 case TY_CTL('N' ) : useCharset ( 1); break; //VT100
467 case TY_CTL('O' ) : useCharset ( 0); break; //VT100
469 case TY_CTL('P' ) : /* DLE: ignored */ break;
470 case TY_CTL('Q' ) : /* DC1: XON continue */ break; //VT100
471 case TY_CTL('R' ) : /* DC2: ignored */ break;
472 case TY_CTL('S' ) : /* DC3: XOFF halt */ break; //VT100
473 case TY_CTL('T' ) : /* DC4: ignored */ break;
474 case TY_CTL('U' ) : /* NAK: ignored */ break;
475 case TY_CTL('V' ) : /* SYN: ignored */ break;
476 case TY_CTL('W' ) : /* ETB: ignored */ break;
477 case TY_CTL('X' ) : _currentScreen->ShowCharacter ( 0x2592); break; //VT100
478 case TY_CTL('Y' ) : /* EM : ignored */ break;
479 case TY_CTL('Z' ) : _currentScreen->ShowCharacter ( 0x2592); break; //VT100
480 case TY_CTL('[' ) : /* ESC: cannot be seen here. */ break;
481 case TY_CTL('\\' ) : /* FS : ignored */ break;
482 case TY_CTL(']' ) : /* GS : ignored */ break;
483 case TY_CTL('^' ) : /* RS : ignored */ break;
484 case TY_CTL('_' ) : /* US : ignored */ break;
486 case TY_ESC('D' ) : _currentScreen->index ( ); break; //VT100
487 case TY_ESC('E' ) : _currentScreen->NextLine ( ); break; //VT100
488 case TY_ESC('H' ) : _currentScreen->changeTabStop (true ); break; //VT100
489 case TY_ESC('M' ) : _currentScreen->reverseIndex ( ); break; //VT100
490 case TY_ESC('Z' ) : reportTerminalType ( ); break;
491 case TY_ESC('c' ) : reset ( ); break;
493 case TY_ESC('n' ) : useCharset ( 2); break;
494 case TY_ESC('o' ) : useCharset ( 3); break;
495 case TY_ESC('7' ) : saveCursor ( ); break;
496 case TY_ESC('8' ) : restoreCursor ( ); break;
498 case TY_ESC('=' ) : setMode (MODE_AppKeyPad); break;
499 case TY_ESC('>' ) : resetMode (MODE_AppKeyPad); break;
500 case TY_ESC('<' ) : setMode (MODE_Ansi ); break; //VT100
502 case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100
503 case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100
504 case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100
506 case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100
507 case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100
508 case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100
510 case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100
511 case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100
512 case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100
514 case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100
515 case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100
516 case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100
518 case TY_ESC_CS('%', 'G') : setCodec (Utf8Codec ); break; //LINUX
519 case TY_ESC_CS('%', '@') : setCodec (LocaleCodec ); break; //LINUX
521 case TY_ESC_DE('3' ) : /* Double height line, top half */
522 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
523 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
524 break;
525 case TY_ESC_DE('4' ) : /* Double height line, bottom half */
526 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
527 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
528 break;
529 case TY_ESC_DE('5' ) : /* Single width, single height line*/
530 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
531 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
532 break;
533 case TY_ESC_DE('6' ) : /* Double width, single height line*/
534 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);
535 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
536 break;
537 case TY_ESC_DE('8' ) : _currentScreen->helpAlign ( ); break;
539 // resize = \e[8;<row>;<col>t
540 case TY_CSI_PS('t', 8) : setImageSize( q /* colums */, p /* lines */ ); break;
542 // change tab text color : \e[28;<color>t color: 0-16,777,215
543 case TY_CSI_PS('t', 28) : emit changeTabTextColorRequest ( p ); break;
545 case TY_CSI_PS('K', 0) : _currentScreen->clearToEndOfLine ( ); break;
546 case TY_CSI_PS('K', 1) : _currentScreen->clearToBeginOfLine ( ); break;
547 case TY_CSI_PS('K', 2) : _currentScreen->clearEntireLine ( ); break;
548 case TY_CSI_PS('J', 0) : _currentScreen->clearToEndOfScreen ( ); break;
549 case TY_CSI_PS('J', 1) : _currentScreen->clearToBeginOfScreen ( ); break;
550 case TY_CSI_PS('J', 2) : _currentScreen->clearEntireScreen ( ); break;
551 case TY_CSI_PS('g', 0) : _currentScreen->changeTabStop (false ); break; //VT100
552 case TY_CSI_PS('g', 3) : _currentScreen->clearTabStops ( ); break; //VT100
553 case TY_CSI_PS('h', 4) : _currentScreen-> setMode (MODE_Insert ); break;
554 case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break;
555 case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100
556 case TY_CSI_PS('l', 4) : _currentScreen-> resetMode (MODE_Insert ); break;
557 case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break;
558 case TY_CSI_PS('s', 0) : saveCursor ( ); break;
559 case TY_CSI_PS('u', 0) : restoreCursor ( ); break;
561 case TY_CSI_PS('m', 0) : _currentScreen->setDefaultRendition ( ); break;
562 case TY_CSI_PS('m', 1) : _currentScreen-> setRendition (RE_BOLD ); break; //VT100
563 case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break; //VT100
564 case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break; //VT100
565 case TY_CSI_PS('m', 7) : _currentScreen-> setRendition (RE_REVERSE ); break;
566 case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
567 case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
568 case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
569 case TY_CSI_PS('m', 22) : _currentScreen->resetRendition (RE_BOLD ); break;
570 case TY_CSI_PS('m', 24) : _currentScreen->resetRendition (RE_UNDERLINE); break;
571 case TY_CSI_PS('m', 25) : _currentScreen->resetRendition (RE_BLINK ); break;
572 case TY_CSI_PS('m', 27) : _currentScreen->resetRendition (RE_REVERSE ); break;
574 case TY_CSI_PS('m', 30) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); break;
575 case TY_CSI_PS('m', 31) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); break;
576 case TY_CSI_PS('m', 32) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 2); break;
577 case TY_CSI_PS('m', 33) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 3); break;
578 case TY_CSI_PS('m', 34) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 4); break;
579 case TY_CSI_PS('m', 35) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 5); break;
580 case TY_CSI_PS('m', 36) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 6); break;
581 case TY_CSI_PS('m', 37) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 7); break;
583 case TY_CSI_PS('m', 38) : _currentScreen->setForeColor (p, q); break;
585 case TY_CSI_PS('m', 39) : _currentScreen->setForeColor (COLOR_SPACE_DEFAULT, 0); break;
587 case TY_CSI_PS('m', 40) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 0); break;
588 case TY_CSI_PS('m', 41) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 1); break;
589 case TY_CSI_PS('m', 42) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 2); break;
590 case TY_CSI_PS('m', 43) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 3); break;
591 case TY_CSI_PS('m', 44) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 4); break;
592 case TY_CSI_PS('m', 45) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 5); break;
593 case TY_CSI_PS('m', 46) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 6); break;
594 case TY_CSI_PS('m', 47) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 7); break;
596 case TY_CSI_PS('m', 48) : _currentScreen->setBackColor (p, q); break;
598 case TY_CSI_PS('m', 49) : _currentScreen->setBackColor (COLOR_SPACE_DEFAULT, 1); break;
600 case TY_CSI_PS('m', 90) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 8); break;
601 case TY_CSI_PS('m', 91) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 9); break;
602 case TY_CSI_PS('m', 92) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 10); break;
603 case TY_CSI_PS('m', 93) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 11); break;
604 case TY_CSI_PS('m', 94) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 12); break;
605 case TY_CSI_PS('m', 95) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 13); break;
606 case TY_CSI_PS('m', 96) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 14); break;
607 case TY_CSI_PS('m', 97) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 15); break;
609 case TY_CSI_PS('m', 100) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 8); break;
610 case TY_CSI_PS('m', 101) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 9); break;
611 case TY_CSI_PS('m', 102) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 10); break;
612 case TY_CSI_PS('m', 103) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 11); break;
613 case TY_CSI_PS('m', 104) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 12); break;
614 case TY_CSI_PS('m', 105) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 13); break;
615 case TY_CSI_PS('m', 106) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 14); break;
616 case TY_CSI_PS('m', 107) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 15); break;
618 case TY_CSI_PS('n', 5) : reportStatus ( ); break;
619 case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break;
620 case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100
621 case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100
622 case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100
623 case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100
624 case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100
625 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
626 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
628 case TY_CSI_PN('@' ) : _currentScreen->insertChars (p ); break;
629 case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break; //VT100
630 case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break; //VT100
631 case TY_CSI_PN('C' ) : _currentScreen->cursorRight (p ); break; //VT100
632 case TY_CSI_PN('D' ) : _currentScreen->cursorLeft (p ); break; //VT100
633 case TY_CSI_PN('G' ) : _currentScreen->setCursorX (p ); break; //LINUX
634 case TY_CSI_PN('H' ) : _currentScreen->setCursorYX (p, q); break; //VT100
635 case TY_CSI_PN('I' ) : _currentScreen->Tabulate (p ); break;
636 case TY_CSI_PN('L' ) : _currentScreen->insertLines (p ); break;
637 case TY_CSI_PN('M' ) : _currentScreen->deleteLines (p ); break;
638 case TY_CSI_PN('P' ) : _currentScreen->deleteChars (p ); break;
639 case TY_CSI_PN('S' ) : _currentScreen->scrollUp (p ); break;
640 case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break;
641 case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break;
642 case TY_CSI_PN('Z' ) : _currentScreen->backTabulate (p ); break;
643 case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
644 case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX
645 case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break; //VT100
646 case TY_CSI_PN('r' ) : setMargins (p, q); break; //VT100
647 case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100
649 case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100
650 case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100
651 case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME
652 case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME
654 case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100
656 case TY_CSI_PR('h', 3) : clearScreenAndSetColumns(132); break; //VT100
657 case TY_CSI_PR('l', 3) : clearScreenAndSetColumns(80); break; //VT100
659 case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100
660 case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100
662 case TY_CSI_PR('h', 5) : _currentScreen-> setMode (MODE_Screen ); break; //VT100
663 case TY_CSI_PR('l', 5) : _currentScreen-> resetMode (MODE_Screen ); break; //VT100
665 case TY_CSI_PR('h', 6) : _currentScreen-> setMode (MODE_Origin ); break; //VT100
666 case TY_CSI_PR('l', 6) : _currentScreen-> resetMode (MODE_Origin ); break; //VT100
667 case TY_CSI_PR('s', 6) : _currentScreen-> saveMode (MODE_Origin ); break; //FIXME
668 case TY_CSI_PR('r', 6) : _currentScreen->restoreMode (MODE_Origin ); break; //FIXME
670 case TY_CSI_PR('h', 7) : _currentScreen-> setMode (MODE_Wrap ); break; //VT100
671 case TY_CSI_PR('l', 7) : _currentScreen-> resetMode (MODE_Wrap ); break; //VT100
672 case TY_CSI_PR('s', 7) : _currentScreen-> saveMode (MODE_Wrap ); break; //FIXME
673 case TY_CSI_PR('r', 7) : _currentScreen->restoreMode (MODE_Wrap ); break; //FIXME
675 case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100
676 case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100
677 case TY_CSI_PR('s', 8) : /* IGNORED: autorepeat on */ break; //VT100
678 case TY_CSI_PR('r', 8) : /* IGNORED: autorepeat off */ break; //VT100
680 case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100
681 case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100
682 case TY_CSI_PR('s', 9) : /* IGNORED: interlace */ break; //VT100
683 case TY_CSI_PR('r', 9) : /* IGNORED: interlace */ break; //VT100
685 case TY_CSI_PR('h', 12) : /* IGNORED: Cursor blink */ break; //att610
686 case TY_CSI_PR('l', 12) : /* IGNORED: Cursor blink */ break; //att610
687 case TY_CSI_PR('s', 12) : /* IGNORED: Cursor blink */ break; //att610
688 case TY_CSI_PR('r', 12) : /* IGNORED: Cursor blink */ break; //att610
690 case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100
691 case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100
692 case TY_CSI_PR('s', 25) : saveMode (MODE_Cursor ); break; //VT100
693 case TY_CSI_PR('r', 25) : restoreMode (MODE_Cursor ); break; //VT100
695 case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
696 case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
697 case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
698 case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
700 case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100
701 case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100
702 case TY_CSI_PR('s', 47) : saveMode (MODE_AppScreen); break; //XTERM
703 case TY_CSI_PR('r', 47) : restoreMode (MODE_AppScreen); break; //XTERM
705 case TY_CSI_PR('h', 67) : /* IGNORED: DECBKM */ break; //XTERM
706 case TY_CSI_PR('l', 67) : /* IGNORED: DECBKM */ break; //XTERM
707 case TY_CSI_PR('s', 67) : /* IGNORED: DECBKM */ break; //XTERM
708 case TY_CSI_PR('r', 67) : /* IGNORED: DECBKM */ break; //XTERM
710 // XTerm defines the following modes:
711 // SET_VT200_MOUSE 1000
712 // SET_VT200_HIGHLIGHT_MOUSE 1001
713 // SET_BTN_EVENT_MOUSE 1002
714 // SET_ANY_EVENT_MOUSE 1003
717 //Note about mouse modes:
718 //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003
719 //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).
720 //TODO: Implementation of mouse modes 1001 (something called hilight tracking) and
721 //1003 (a slight variation on dragging the mouse)
724 case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM
725 case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM
726 case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM
727 case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM
729 case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
730 case TY_CSI_PR('l', 1001) : resetMode (MODE_Mouse1001); break; //XTERM
731 case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
732 case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
734 case TY_CSI_PR('h', 1002) : setMode (MODE_Mouse1002); break; //XTERM
735 case TY_CSI_PR('l', 1002) : resetMode (MODE_Mouse1002); break; //XTERM
736 case TY_CSI_PR('s', 1002) : saveMode (MODE_Mouse1002); break; //XTERM
737 case TY_CSI_PR('r', 1002) : restoreMode (MODE_Mouse1002); break; //XTERM
739 case TY_CSI_PR('h', 1003) : setMode (MODE_Mouse1003); break; //XTERM
740 case TY_CSI_PR('l', 1003) : resetMode (MODE_Mouse1003); break; //XTERM
741 case TY_CSI_PR('s', 1003) : saveMode (MODE_Mouse1003); break; //XTERM
742 case TY_CSI_PR('r', 1003) : restoreMode (MODE_Mouse1003); break; //XTERM
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
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
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
760 //FIXME: weird DEC reset sequence
761 case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break;
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
769 case TY_VT52('F' ) : setAndUseCharset (0, '0'); break; //VT52
770 case TY_VT52('G' ) : setAndUseCharset (0, 'B'); break; //VT52
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
782 case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break; //VT100
784 default : ReportErrorToken(); break;
788 void Vt102Emulation::clearScreenAndSetColumns(int columnCount)
790 setImageSize(_currentScreen->getLines(),columnCount);
791 clearEntireScreen();
792 setDefaultMargins();
793 _currentScreen->setCursorYX(0,0);
796 /* ------------------------------------------------------------------------- */
797 /* */
798 /* Terminal to Host protocol */
799 /* */
800 /* ------------------------------------------------------------------------- */
803 Outgoing bytes originate from several sources:
805 - Replies to Enquieries.
806 - Mouse Events
807 - Keyboard Events
813 void Vt102Emulation::sendString(const char* s , int length)
815 if ( length >= 0 )
816 emit sendData(s,length);
817 else
818 emit sendData(s,strlen(s));
821 // Replies ----------------------------------------------------------------- --
823 // This section copes with replies send as response to an enquiery control code.
828 void Vt102Emulation::reportCursorPosition()
829 { char tmp[20];
830 sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);
831 sendString(tmp);
835 What follows here is rather obsolete and faked stuff.
836 The correspondent enquieries are neverthenless issued.
842 void Vt102Emulation::reportTerminalType()
844 // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
845 // VT220: ^[[?63;1;2;3;6;7;8c (list deps on emul. capabilities)
846 // VT100: ^[[?1;2c
847 // VT101: ^[[?1;0c
848 // VT102: ^[[?6v
849 if (getMode(MODE_Ansi))
850 sendString("\033[?1;2c"); // I'm a VT100
851 else
852 sendString("\033/Z"); // I'm a VT52
855 void Vt102Emulation::reportSecondaryAttributes()
857 // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
858 if (getMode(MODE_Ansi))
859 sendString("\033[>0;115;0c"); // Why 115? ;)
860 else
861 sendString("\033/Z"); // FIXME I don't think VT52 knows about it but kept for
862 // konsoles backward compatibility.
865 void Vt102Emulation::reportTerminalParms(int p)
866 // DECREPTPARM
867 { char tmp[100];
868 sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
869 sendString(tmp);
875 void Vt102Emulation::reportStatus()
877 sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
883 #define ANSWER_BACK "" // This is really obsolete VT100 stuff.
885 void Vt102Emulation::reportAnswerBack()
887 sendString(ANSWER_BACK);
890 // Mouse Handling ---------------------------------------------------------- --
893 Mouse clicks are possibly reported to the client
894 application if it has issued interest in them.
895 They are normally consumed by the widget for copy
896 and paste, but may be propagated from the widget
897 when gui->setMouseMarks is set via setMode(MODE_Mouse1000).
899 `x',`y' are 1-based.
900 `ev' (event) indicates the button pressed (0-2)
901 or a general mouse release (3).
903 eventType represents the kind of mouse action that occurred:
904 0 = Mouse button press or release
905 1 = Mouse drag
908 void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
909 { char tmp[20];
910 if ( cx<1 || cy<1 ) return;
911 // normal buttons are passed as 0x20 + button,
912 // mouse wheel (buttons 4,5) as 0x5c + button
913 if (cb >= 4) cb += 0x3c;
915 //Mouse motion handling
916 if ( (getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1 )
917 cb += 0x20; //add 32 to signify motion event
919 sprintf(tmp,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20);
920 sendString(tmp);
923 // Keyboard Handling ------------------------------------------------------- --
925 #define encodeMode(M,B) BITS(B,getMode(M))
926 #define encodeStat(M,B) BITS(B,((ev->modifiers() & (M)) == (M)))
928 void Vt102Emulation::sendText( const QString& text )
930 if (!text.isEmpty()) {
931 QKeyEvent event(QEvent::KeyPress,
933 Qt::NoModifier,
934 text);
935 sendKeyEvent(&event); // expose as a big fat keypress event
940 void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
942 Qt::KeyboardModifiers modifiers = event->modifiers();
943 KeyboardTranslator::States states = KeyboardTranslator::NoState;
945 // get current states
946 if ( getMode(MODE_NewLine) ) states |= KeyboardTranslator::NewLineState;
947 if ( getMode(MODE_Ansi) ) states |= KeyboardTranslator::AnsiState;
948 if ( getMode(MODE_AppCuKeys)) states |= KeyboardTranslator::CursorKeysState;
949 if ( getMode(MODE_AppScreen)) states |= KeyboardTranslator::AlternateScreenState;
951 // lookup key binding
952 if ( _keyTranslator )
954 KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
955 event->key() ,
956 modifiers,
957 states );
959 // send result to terminal
960 QByteArray textToSend;
962 // special handling for the Alt (aka. Meta) modifier. pressing
963 // Alt+[Character] results in Esc+[Character] being sent
964 // (unless there is an entry defined for this particular combination
965 // in the keyboard modifier)
966 bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;
967 bool wantsAnyModifier = entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState;
969 if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier)
970 && !event->text().isEmpty() )
972 textToSend.prepend("\033");
975 if ( entry.command() != KeyboardTranslator::NoCommand )
977 if (entry.command() & KeyboardTranslator::EraseCommand)
978 textToSend += getErase();
980 // TODO command handling
982 else if ( !entry.text().isEmpty() )
984 textToSend += _codec->fromUnicode(entry.text(true,modifiers));
986 else
987 textToSend += _codec->fromUnicode(event->text());
989 sendData( textToSend.constData() , textToSend.length() );
991 else
993 // print an error message to the terminal if no key translator has been
994 // set
995 QString translatorError = i18n("No keyboard translator available. "
996 "The information needed to convert key presses "
997 "into characters to send to the terminal "
998 "is missing.");
1000 reset();
1001 receiveData( translatorError.toAscii().constData() , translatorError.count() );
1005 /* ------------------------------------------------------------------------- */
1006 /* */
1007 /* VT100 Charsets */
1008 /* */
1009 /* ------------------------------------------------------------------------- */
1011 // Character Set Conversion ------------------------------------------------ --
1014 The processing contains a VT100 specific code translation layer.
1015 It's still in use and mainly responsible for the line drawing graphics.
1017 These and some other glyphs are assigned to codes (0x5f-0xfe)
1018 normally occupied by the latin letters. Since this codes also
1019 appear within control sequences, the extra code conversion
1020 does not permute with the tokenizer and is placed behind it
1021 in the pipeline. It only applies to tokens, which represent
1022 plain characters.
1024 This conversion it eventually continued in TerminalDisplay.C, since
1025 it might involve VT100 enhanced fonts, which have these
1026 particular glyphs allocated in (0x00-0x1f) in their code page.
1029 #define CHARSET _charset[_currentScreen==_screen[1]]
1031 // Apply current character map.
1033 unsigned short Vt102Emulation::applyCharset(unsigned short c)
1035 if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
1036 if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
1037 return c;
1041 "Charset" related part of the emulation state.
1042 This configures the VT100 _charset filter.
1044 While most operation work on the current _screen,
1045 the following two are different.
1048 void Vt102Emulation::resetCharset(int scrno)
1050 _charset[scrno].cu_cs = 0;
1051 strncpy(_charset[scrno].charset,"BBBB",4);
1052 _charset[scrno].sa_graphic = false;
1053 _charset[scrno].sa_pound = false;
1054 _charset[scrno].graphic = false;
1055 _charset[scrno].pound = false;
1058 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
1060 _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);
1061 _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);
1064 void Vt102Emulation::setAndUseCharset(int n, int cs)
1066 CHARSET.charset[n&3] = cs;
1067 useCharset(n&3);
1070 void Vt102Emulation::useCharset(int n)
1072 CHARSET.cu_cs = n&3;
1073 CHARSET.graphic = (CHARSET.charset[n&3] == '0');
1074 CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
1077 void Vt102Emulation::setDefaultMargins()
1079 _screen[0]->setDefaultMargins();
1080 _screen[1]->setDefaultMargins();
1083 void Vt102Emulation::setMargins(int t, int b)
1085 _screen[0]->setMargins(t, b);
1086 _screen[1]->setMargins(t, b);
1089 /*! Save the cursor position and the rendition attribute settings. */
1091 void Vt102Emulation::saveCursor()
1093 CHARSET.sa_graphic = CHARSET.graphic;
1094 CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
1095 // we are not clear about these
1096 //sa_charset = charsets[cScreen->_charset];
1097 //sa_charset_num = cScreen->_charset;
1098 _currentScreen->saveCursor();
1101 /*! Restore the cursor position and the rendition attribute settings. */
1103 void Vt102Emulation::restoreCursor()
1105 CHARSET.graphic = CHARSET.sa_graphic;
1106 CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
1107 _currentScreen->restoreCursor();
1110 /* ------------------------------------------------------------------------- */
1111 /* */
1112 /* Mode Operations */
1113 /* */
1114 /* ------------------------------------------------------------------------- */
1117 Some of the emulations state is either added to the state of the screens.
1119 This causes some scoping problems, since different emulations choose to
1120 located the mode either to the current _screen or to both.
1122 For strange reasons, the extend of the rendition attributes ranges over
1123 all screens and not over the actual _screen.
1125 We decided on the precise precise extend, somehow.
1128 // "Mode" related part of the state. These are all booleans.
1130 void Vt102Emulation::resetModes()
1132 resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
1133 resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001);
1134 resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002);
1135 resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003);
1137 resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
1138 // here come obsolete modes
1139 resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
1140 resetMode(MODE_NewLine );
1141 setMode(MODE_Ansi );
1144 void Vt102Emulation::setMode(int m)
1146 _currParm.mode[m] = true;
1147 switch (m)
1149 case MODE_Mouse1000:
1150 case MODE_Mouse1001:
1151 case MODE_Mouse1002:
1152 case MODE_Mouse1003:
1153 emit programUsesMouseChanged(false);
1154 break;
1156 case MODE_AppScreen : _screen[1]->clearSelection();
1157 setScreen(1);
1158 break;
1160 if (m < MODES_SCREEN || m == MODE_NewLine)
1162 _screen[0]->setMode(m);
1163 _screen[1]->setMode(m);
1167 void Vt102Emulation::resetMode(int m)
1169 _currParm.mode[m] = false;
1170 switch (m)
1172 case MODE_Mouse1000 :
1173 case MODE_Mouse1001 :
1174 case MODE_Mouse1002 :
1175 case MODE_Mouse1003 :
1176 emit programUsesMouseChanged(true);
1177 break;
1179 case MODE_AppScreen : _screen[0]->clearSelection();
1180 setScreen(0);
1181 break;
1183 if (m < MODES_SCREEN || m == MODE_NewLine)
1185 _screen[0]->resetMode(m);
1186 _screen[1]->resetMode(m);
1190 void Vt102Emulation::saveMode(int m)
1192 _saveParm.mode[m] = _currParm.mode[m];
1195 void Vt102Emulation::restoreMode(int m)
1197 if (_saveParm.mode[m])
1198 setMode(m);
1199 else
1200 resetMode(m);
1203 bool Vt102Emulation::getMode(int m)
1205 return _currParm.mode[m];
1208 char Vt102Emulation::getErase() const
1210 KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
1211 Qt::Key_Backspace,
1214 if ( entry.text().count() > 0 )
1215 return entry.text()[0];
1216 else
1217 return '\b';
1220 /* ------------------------------------------------------------------------- */
1221 /* */
1222 /* Diagnostic */
1223 /* */
1224 /* ------------------------------------------------------------------------- */
1226 /*! shows the contents of the scan buffer.
1228 This functions is used for diagnostics. It is called by \e ReportErrorToken
1229 to inform about strings that cannot be decoded or handled by the emulation.
1231 \sa ReportErrorToken
1234 static void hexdump(int* s, int len)
1235 { int i;
1236 for (i = 0; i < len; i++)
1238 if (s[i] == '\\')
1239 printf("\\\\");
1240 else
1241 if ((s[i]) > 32 && s[i] < 127)
1242 printf("%c",s[i]);
1243 else
1244 printf("\\%04x(hex)",s[i]);
1248 void Vt102Emulation::scan_buffer_report()
1250 if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
1251 printf("token: "); hexdump(pbuf,ppos); printf("\n");
1257 void Vt102Emulation::ReportErrorToken()
1259 #ifndef NDEBUG
1260 printf("undecodable "); scan_buffer_report();
1261 #endif
1264 #include "Vt102Emulation.moc"