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