GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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 <lars.doelle@on-line.de>
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  case TY_CSI_PR('h', 2004) : setMode (MODE_BracketedPaste); break; //XTERM
756  case TY_CSI_PR('l', 2004) : resetMode (MODE_BracketedPaste); break; //XTERM
757  case TY_CSI_PR('s', 2004) : saveMode (MODE_BracketedPaste); break; //XTERM
758  case TY_CSI_PR('r', 2004) : restoreMode (MODE_BracketedPaste); break; //XTERM
759 
760  //FIXME: weird DEC reset sequence
761  case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break;
762 
763  //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
764  case TY_VT52('A' ) : _currentScreen->cursorUp ( 1); break; //VT52
765  case TY_VT52('B' ) : _currentScreen->cursorDown ( 1); break; //VT52
766  case TY_VT52('C' ) : _currentScreen->cursorRight ( 1); break; //VT52
767  case TY_VT52('D' ) : _currentScreen->cursorLeft ( 1); break; //VT52
768 
769  case TY_VT52('F' ) : setAndUseCharset (0, '0'); break; //VT52
770  case TY_VT52('G' ) : setAndUseCharset (0, 'B'); break; //VT52
771 
772  case TY_VT52('H' ) : _currentScreen->setCursorYX (1,1 ); break; //VT52
773  case TY_VT52('I' ) : _currentScreen->reverseIndex ( ); break; //VT52
774  case TY_VT52('J' ) : _currentScreen->clearToEndOfScreen ( ); break; //VT52
775  case TY_VT52('K' ) : _currentScreen->clearToEndOfLine ( ); break; //VT52
776  case TY_VT52('Y' ) : _currentScreen->setCursorYX (p-31,q-31 ); break; //VT52
777  case TY_VT52('Z' ) : reportTerminalType ( ); break; //VT52
778  case TY_VT52('<' ) : setMode (MODE_Ansi ); break; //VT52
779  case TY_VT52('=' ) : setMode (MODE_AppKeyPad); break; //VT52
780  case TY_VT52('>' ) : resetMode (MODE_AppKeyPad); break; //VT52
781 
782  case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break; //VT100
783 
784  default : ReportErrorToken(); break;
785  };
786 }
787 
789 {
790  setImageSize(_currentScreen->getLines(),columnCount);
794 }
795 
796 /* ------------------------------------------------------------------------- */
797 /* */
798 /* Terminal to Host protocol */
799 /* */
800 /* ------------------------------------------------------------------------- */
801 
802 /*
803  Outgoing bytes originate from several sources:
804 
805  - Replies to Enquieries.
806  - Mouse Events
807  - Keyboard Events
808 */
809 
810 /*!
811 */
812 
813 void Vt102Emulation::sendString(const char* s , int length)
814 {
815  if ( length >= 0 )
816  emit sendData(s,length);
817  else
818  emit sendData(s,strlen(s));
819 }
820 
821 // Replies ----------------------------------------------------------------- --
822 
823 // This section copes with replies send as response to an enquiery control code.
824 
825 /*!
826 */
827 
829 { char tmp[20];
830  sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);
831  sendString(tmp);
832 }
833 
834 /*
835  What follows here is rather obsolete and faked stuff.
836  The correspondent enquieries are neverthenless issued.
837 */
838 
839 /*!
840 */
841 
843 {
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
853 }
854 
856 {
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.
863 }
864 
866 // DECREPTPARM
867 { char tmp[100];
868  sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
869  sendString(tmp);
870 }
871 
872 /*!
873 */
874 
876 {
877  sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
878 }
879 
880 /*!
881 */
882 
883 #define ANSWER_BACK "" // This is really obsolete VT100 stuff.
884 
886 {
888 }
889 
890 // Mouse Handling ---------------------------------------------------------- --
891 
892 /*!
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).
898 
899  `x',`y' are 1-based.
900  `ev' (event) indicates the button pressed (0-2)
901  or a general mouse release (3).
902 
903  eventType represents the kind of mouse action that occurred:
904  0 = Mouse button press or release
905  1 = Mouse drag
906 */
907 
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;
914 
915  //Mouse motion handling
916  if ( (getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1 )
917  cb += 0x20; //add 32 to signify motion event
918 
919  sprintf(tmp,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20);
920  sendString(tmp);
921 }
922 
923 // Keyboard Handling ------------------------------------------------------- --
924 
925 #define encodeMode(M,B) BITS(B,getMode(M))
926 #define encodeStat(M,B) BITS(B,((ev->modifiers() & (M)) == (M)))
927 
928 void Vt102Emulation::sendText( const QString& text )
929 {
930  if (!text.isEmpty()) {
931  QKeyEvent event(QEvent::KeyPress,
932  0,
933  Qt::NoModifier,
934  text);
935  sendKeyEvent(&event); // expose as a big fat keypress event
936  }
937 
938 }
939 
940 void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
941 {
942  Qt::KeyboardModifiers modifiers = event->modifiers();
943  KeyboardTranslator::States states = KeyboardTranslator::NoState;
944 
945  // get current states
950 
951  // lookup key binding
952  if ( _keyTranslator )
953  {
955  event->key() ,
956  modifiers,
957  states );
958 
959  // send result to terminal
960  QByteArray textToSend;
961 
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;
968 
969  if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier)
970  && !event->text().isEmpty() )
971  {
972 #if !defined(Q_OS_MAC)
973  textToSend.prepend("\033");
974 #endif
975  }
976 
977  if ( entry.command() != KeyboardTranslator::NoCommand )
978  {
980  textToSend += getErase();
981  // TODO command handling
982  }
983  else if ( !entry.text().isEmpty() )
984  {
985  textToSend += _codec->fromUnicode(entry.text(true,modifiers));
986  }
987  else if (event->key() == Qt::Key_PageUp)
988  {
989  textToSend += "\033[5~";
990  }
991  else if (event->key() == Qt::Key_PageDown)
992  {
993  textToSend += "\033[6~";
994  }
995  else
996  textToSend += _codec->fromUnicode(event->text());
997 
998  sendData( textToSend.constData() , textToSend.length() );
999  }
1000  else
1001  {
1002  // print an error message to the terminal if no key translator has been
1003  // set
1004  QString translatorError = ("No keyboard translator available. "
1005  "The information needed to convert key presses "
1006  "into characters to send to the terminal "
1007  "is missing.");
1008 
1009  reset();
1010  receiveData( translatorError.toLatin1().constData() , translatorError.count() );
1011  }
1012 }
1013 
1014 /* ------------------------------------------------------------------------- */
1015 /* */
1016 /* VT100 Charsets */
1017 /* */
1018 /* ------------------------------------------------------------------------- */
1019 
1020 // Character Set Conversion ------------------------------------------------ --
1021 
1022 /*
1023  The processing contains a VT100 specific code translation layer.
1024  It's still in use and mainly responsible for the line drawing graphics.
1025 
1026  These and some other glyphs are assigned to codes (0x5f-0xfe)
1027  normally occupied by the latin letters. Since this codes also
1028  appear within control sequences, the extra code conversion
1029  does not permute with the tokenizer and is placed behind it
1030  in the pipeline. It only applies to tokens, which represent
1031  plain characters.
1032 
1033  This conversion it eventually continued in TerminalDisplay.C, since
1034  it might involve VT100 enhanced fonts, which have these
1035  particular glyphs allocated in (0x00-0x1f) in their code page.
1036 */
1037 
1038 #define CHARSET _charset[_currentScreen==_screen[1]]
1039 
1040 // Apply current character map.
1041 
1042 unsigned short Vt102Emulation::applyCharset(unsigned short c)
1043 {
1044  if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
1045  if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
1046  return c;
1047 }
1048 
1049 /*
1050  "Charset" related part of the emulation state.
1051  This configures the VT100 _charset filter.
1052 
1053  While most operation work on the current _screen,
1054  the following two are different.
1055 */
1056 
1058 {
1059  _charset[scrno].cu_cs = 0;
1060  strncpy(_charset[scrno].charset,"BBBB",4);
1061  _charset[scrno].sa_graphic = false;
1062  _charset[scrno].sa_pound = false;
1063  _charset[scrno].graphic = false;
1064  _charset[scrno].pound = false;
1065 }
1066 
1067 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
1068 {
1069  _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);
1070  _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);
1071 }
1072 
1074 {
1075  CHARSET.charset[n&3] = cs;
1076  useCharset(n&3);
1077 }
1078 
1080 {
1081  CHARSET.cu_cs = n&3;
1082  CHARSET.graphic = (CHARSET.charset[n&3] == '0');
1083  CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
1084 }
1085 
1087 {
1088  _screen[0]->setDefaultMargins();
1089  _screen[1]->setDefaultMargins();
1090 }
1091 
1092 void Vt102Emulation::setMargins(int t, int b)
1093 {
1094  _screen[0]->setMargins(t, b);
1095  _screen[1]->setMargins(t, b);
1096 }
1097 
1098 /*! Save the cursor position and the rendition attribute settings. */
1099 
1101 {
1102  CHARSET.sa_graphic = CHARSET.graphic;
1103  CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
1104  // we are not clear about these
1105  //sa_charset = charsets[cScreen->_charset];
1106  //sa_charset_num = cScreen->_charset;
1108 }
1109 
1110 /*! Restore the cursor position and the rendition attribute settings. */
1111 
1113 {
1114  CHARSET.graphic = CHARSET.sa_graphic;
1115  CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
1117 }
1118 
1119 /* ------------------------------------------------------------------------- */
1120 /* */
1121 /* Mode Operations */
1122 /* */
1123 /* ------------------------------------------------------------------------- */
1124 
1125 /*
1126  Some of the emulations state is either added to the state of the screens.
1127 
1128  This causes some scoping problems, since different emulations choose to
1129  located the mode either to the current _screen or to both.
1130 
1131  For strange reasons, the extend of the rendition attributes ranges over
1132  all screens and not over the actual _screen.
1133 
1134  We decided on the precise precise extend, somehow.
1135 */
1136 
1137 // "Mode" related part of the state. These are all booleans.
1138 
1140 {
1146 
1148  // here come obsolete modes
1151  setMode(MODE_Ansi );
1152 }
1153 
1155 {
1156  _currParm.mode[m] = true;
1157  switch (m)
1158  {
1159  case MODE_Mouse1000:
1160  case MODE_Mouse1001:
1161  case MODE_Mouse1002:
1162  case MODE_Mouse1003:
1163  emit programUsesMouseChanged(false);
1164  break;
1165 
1166  case MODE_BracketedPaste:
1168  break;
1169 
1170  case MODE_AppScreen : _screen[1]->clearSelection();
1171  setScreen(1);
1172  break;
1173  }
1174  if (m < MODES_SCREEN || m == MODE_NewLine)
1175  {
1176  _screen[0]->setMode(m);
1177  _screen[1]->setMode(m);
1178  }
1179 }
1180 
1182 {
1183  _currParm.mode[m] = false;
1184  switch (m)
1185  {
1186  case MODE_Mouse1000 :
1187  case MODE_Mouse1001 :
1188  case MODE_Mouse1002 :
1189  case MODE_Mouse1003 :
1190  emit programUsesMouseChanged(true);
1191  break;
1192 
1193  case MODE_BracketedPaste:
1195  break;
1196 
1197  case MODE_AppScreen : _screen[0]->clearSelection();
1198  setScreen(0);
1199  break;
1200  }
1201  if (m < MODES_SCREEN || m == MODE_NewLine)
1202  {
1203  _screen[0]->resetMode(m);
1204  _screen[1]->resetMode(m);
1205  }
1206 }
1207 
1209 {
1211 }
1212 
1214 {
1215  if (_saveParm.mode[m])
1216  setMode(m);
1217  else
1218  resetMode(m);
1219 }
1220 
1222 {
1223  return _currParm.mode[m];
1224 }
1225 
1227 {
1229  Qt::Key_Backspace,
1230  Qt::NoModifier);
1231 
1232  if ( entry.text().count() > 0 )
1233  return entry.text()[0];
1234  else
1235  return '\b';
1236 }
1237 
1238 /* ------------------------------------------------------------------------- */
1239 /* */
1240 /* Diagnostic */
1241 /* */
1242 /* ------------------------------------------------------------------------- */
1243 
1244 /*! shows the contents of the scan buffer.
1245 
1246  This functions is used for diagnostics. It is called by @e ReportErrorToken
1247  to inform about strings that cannot be decoded or handled by the emulation.
1248 
1249  @sa ReportErrorToken
1250 */
1251 
1252 static void hexdump(int* s, int len)
1253 { int i;
1254  for (i = 0; i < len; i++)
1255  {
1256  if (s[i] == '\\')
1257  printf("\\\\");
1258  else
1259  if ((s[i]) > 32 && s[i] < 127)
1260  printf("%c",s[i]);
1261  else
1262  printf("\\%04x(hex)",s[i]);
1263  }
1264 }
1265 
1267  if (ppos == 0 || (ppos == 1 && (pbuf[0] & 0xff) >= 32)) {
1268  return;
1269  }
1270  printf("token: ");
1271  hexdump(pbuf,ppos);
1272  printf("\n");
1273 }
1274 
1275 /*!
1276 */
1277 
1279 {
1280  // #ifndef NDEBUG
1281  // printf("undecodable "); scan_buffer_report();
1282  // #endif
1283 }
#define COLOR_SPACE_SYSTEM
#define COLOR_SPACE_RGB
#define COLOR_SPACE_256
#define COLOR_SPACE_DEFAULT
static const int LINE_DOUBLEHEIGHT
Definition: Character.h:39
#define RE_REVERSE
Definition: Character.h:45
#define RE_UNDERLINE
Definition: Character.h:44
unsigned short vt100_graphics[32]
static const int LINE_DOUBLEWIDTH
Definition: Character.h:38
#define RE_BOLD
Definition: Character.h:42
#define RE_BLINK
Definition: Character.h:43
@ NOTIFYBELL
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
#define MODE_NewLine
Definition: Screen.h:42
#define MODE_Wrap
Definition: Screen.h:38
#define MODE_Insert
Definition: Screen.h:39
#define MODE_Screen
Definition: Screen.h:40
#define MODE_Origin
Definition: Screen.h:37
#define MODES_SCREEN
Definition: Screen.h:43
#define MODE_Cursor
Definition: Screen.h:41
#define TY_CSI_PE(A)
#define eps(C)
#define CHARSET
static void hexdump(int *s, int len)
#define Xte
#define TY_VT52(A)
#define TY_ESC_DE(A)
#define ANSWER_BACK
#define TY_CSI_PS(A, N)
#define TY_ESC(A)
#define ESC
#define ees(C)
#define SCS
#define epp()
#define les(P, L, C)
#define epe()
#define TY_CTL(A)
#define CNTL(c)
#define CPN
#define ces(C)
#define TY_CHR()
#define CPS
#define DIG
#define TY_CSI_PN(A)
#define TY_CSI_PG(A)
#define CTL
#define TY_CSI_PR(A, N)
#define Xpe
#define lun()
#define eec(C)
#define GRP
#define egt()
#define TY_ESC_CS(A, B)
#define lec(P, L, C)
#define CHR
#define MODE_BracketedPaste
#define MODE_Mouse1001
#define MODE_Mouse1002
#define MODE_Mouse1003
#define MODE_AppScreen
#define MAXARGS
#define MAXPBUF
#define MODE_Ansi
#define MODE_AppCuKeys
#define MODE_AppKeyPad
#define MODE_Mouse1000
Base class for terminal emulation back-ends.
Definition: Emulation.h:119
const QTextCodec * _codec
Definition: Emulation.h:431
Screen * _currentScreen
Definition: Emulation.h:420
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:262
void programUsesMouseChanged(bool usesMouse)
This is emitted when the program running in the shell indicates whether or not it is interested in mo...
void bufferedUpdate()
Schedules an update of attached views.
Definition: Emulation.cpp:310
const KeyboardTranslator * _keyTranslator
Definition: Emulation.h:434
void programBracketedPasteModeChanged(bool bracketedPasteMode)
void changeTabTextColorRequest(int color)
Requests that the color of the text used to represent the tabs associated with this emulation be chan...
void titleChanged(int title, const QString &newTitle)
Emitted when the program running in the terminal wishes to update the session's title.
@ LocaleCodec
Definition: Emulation.h:412
void sendData(const char *data, int len)
Emitted when a buffer of data is ready to send to the standard input of the terminal.
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:326
void setScreen(int index)
Sets the active screen.
Definition: Emulation.cpp:130
Screen * _screen[2]
Definition: Emulation.h:423
void stateSet(int state)
Emitted when the activity state of the emulation is set.
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:163
Represents an association between a key sequence pressed by the user and the character sequence and c...
QByteArray text(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns the character sequence associated with this entry, optionally replacing wildcard '*' characte...
States state() const
Returns a bitwise-OR of the enabled state flags associated with this entry.
Command command() const
Returns the commands associated with this entry.
Qt::KeyboardModifiers modifiers() const
Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry.
States stateMask() const
Returns the state flags which are valid in this entry.
Qt::KeyboardModifiers modifierMask() const
Returns the keyboard modifiers which are valid in this entry.
@ NewLineState
TODO More documentation.
@ NoState
Indicates that no special state is active.
@ AnyModifierState
Indicates that any of the modifier keys is active.
@ AnsiState
Indicates that the terminal is in 'Ansi' mode.
@ AlternateScreenState
Indicates that the alternate screen ( typically used by interactive programs such as screen or vim ) ...
@ CursorKeysState
TODO More documentation.
Entry findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state=NoState) const
Looks for an entry in this keyboard translator which matches the given key code, keyboard modifiers a...
@ EraseCommand
Echos the operating system specific erase character.
@ NoCommand
Indicates that no command is associated with this command sequence.
void backTabulate(int n)
Moves the cursor n tab-stops to the left.
Definition: Screen.cpp:690
void setCursorYX(int y, int x)
Position the cursor at line y, column x.
Definition: Screen.cpp:910
int getCursorY() const
Returns the line which the cursor is positioned on.
Definition: Screen.cpp:945
void clearToEndOfScreen()
Clear the area of the screen from the current cursor position to the end of the screen.
Definition: Screen.cpp:1103
void deleteChars(int n)
Delete n characters beginning from the current cursor position.
Definition: Screen.cpp:247
void setMargins(int topLine, int bottomLine)
Sets the margins for scrolling the screen.
Definition: Screen.cpp:180
void reset(bool clearScreen=true)
Resets the state of the screen.
Definition: Screen.cpp:639
void clearEntireScreen()
Clear the whole screen, moving the current screen contents into the history first.
Definition: Screen.cpp:1113
void saveCursor()
Saves the current position and appearence (text color and style) of the cursor.
Definition: Screen.cpp:341
void clearToBeginOfLine()
Clears from the current cursor position to the beginning of the line.
Definition: Screen.cpp:1138
void clearEntireLine()
Clears the whole of the line on which the cursor is currently positioned.
Definition: Screen.cpp:1143
void setCursorY(int y)
Position the cursor on line y.
Definition: Screen.cpp:922
void BackSpace()
Moves the cursor one column to the left and erases the character at the new cursor position.
Definition: Screen.cpp:667
void insertChars(int n)
Insert n blank characters beginning from the current cursor position.
Definition: Screen.cpp:268
void Return()
Moves the cursor to the beginning of the current line.
Definition: Screen.cpp:935
void changeTabStop(bool set)
Sets or removes a tab stop at the cursor's current column.
Definition: Screen.cpp:706
void cursorDown(int n)
Move the cursor down by n lines.
Definition: Screen.cpp:144
void setDefaultMargins()
Resets the scrolling margins back to the top and bottom lines of the screen.
Definition: Screen.cpp:422
void setCursorX(int x)
Position the cursor at column x.
Definition: Screen.cpp:915
void NewLine()
Moves the cursor down one line, if the MODE_NewLine mode flag is enabled then the cursor is returned ...
Definition: Screen.cpp:729
void clearTabStops()
Clears all the tab stops.
Definition: Screen.cpp:701
void clearToBeginOfScreen()
Clear the area of the screen from the current cursor position to the start of the screen.
Definition: Screen.cpp:1108
void eraseChars(int n)
Erase n characters beginning from the current cursor position.
Definition: Screen.cpp:240
void helpAlign()
Fills the entire screen with the letter 'E'.
Definition: Screen.cpp:1128
int getCursorX() const
Returns the column which the cursor is positioned at.
Definition: Screen.cpp:940
void Tabulate(int n=1)
Moves the cursor n tab-stops to the right.
Definition: Screen.cpp:679
void cursorUp(int n)
Move the cursor up by n lines.
Definition: Screen.cpp:129
void clearSelection()
Clears the current selection.
Definition: Screen.cpp:1194
void setLineProperty(LineProperty property, bool enable)
Sets or clears an attribute of the current line.
Definition: Screen.cpp:1551
void setMode(int mode)
Sets (enables) the specified screen mode.
Definition: Screen.cpp:302
void setDefaultRendition()
Resets the cursor's color back to the default and sets the character's rendition flags back to the de...
Definition: Screen.cpp:1160
void scrollDown(int n)
Scroll the scrolling region of the screen down by n lines.
Definition: Screen.cpp:884
void scrollUp(int n)
Scroll the scrolling region of the screen up by n lines.
Definition: Screen.cpp:855
void NextLine()
Moves the cursor down one line and positions it at the beginning of the line.
Definition: Screen.cpp:234
void cursorRight(int n)
Move the cursor to the right by n columns.
Definition: Screen.cpp:173
void restoreMode(int mode)
Restores the state of a screen mode saved by calling saveMode()
Definition: Screen.cpp:331
void resetRendition(int rendition)
Disables the given rendition flag.
Definition: Screen.cpp:1154
void restoreCursor()
Restores the position and appearence of the cursor.
Definition: Screen.cpp:350
void setBackColor(int space, int color)
Sets the cursor's background color.
Definition: Screen.cpp:1178
void ShowCharacter(unsigned short c)
Displays a new character at the current cursor position.
Definition: Screen.cpp:752
void deleteLines(int n)
Removes n lines beginning from the current cursor position.
Definition: Screen.cpp:281
void resetMode(int mode)
Resets (clears) the specified screen mode.
Definition: Screen.cpp:313
void index()
Move the cursor down one line.
Definition: Screen.cpp:207
void reverseIndex()
Move the cursor up one line.
Definition: Screen.cpp:218
void clearToEndOfLine()
Clears from the current cursor position to the end of the line.
Definition: Screen.cpp:1133
int getLines()
Return the number of lines.
Definition: Screen.h:377
void cursorLeft(int n)
Move the cursor to the left by n columns.
Definition: Screen.cpp:159
void setForeColor(int space, int color)
Sets the cursor's foreground color.
Definition: Screen.cpp:1168
void insertLines(int n)
Inserts lines beginning from the current cursor position.
Definition: Screen.cpp:292
QTimer * _titleUpdateTimer
void setAndUseCharset(int n, int cs)
virtual void setMode(int mode)
bool getMode(int mode)
void clearScreenAndSetColumns(int columnCount)
void setMargins(int top, int bottom)
virtual void reset()
Resets the state of the terminal.
void setCharset(int n, int cs)
virtual char getErase() const
TODO Document me.
void addDigit(int dig)
void reportSecondaryAttributes()
void restoreMode(int mode)
void useCharset(int n)
virtual void sendMouseEvent(int buttons, int column, int line, int eventType)
virtual void sendKeyEvent(QKeyEvent *)
virtual void receiveChar(int cc)
Processes an incoming character.
virtual void sendText(const QString &text)
void reportTerminalParms(int p)
unsigned short applyCharset(unsigned short c)
QHash< int, QString > _pendingTitleUpdates
virtual void clearEntireScreen()
Copies the current image into the history and clears the screen.
Vt102Emulation()
Constructs a new emulation.
void reportCursorPosition()
void saveMode(int mode)
void resetCharset(int scrno)
CharCodes _charset[2]
virtual void resetMode(int mode)
virtual void sendString(const char *, int length=-1)
void tau(int code, int p, int q)
void pushToToken(int cc)
F77_RET_T const F77_INT & N
F77_RET_T const F77_INT F77_CMPLX * A
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
char charset[4]
bool sa_graphic
bool mode[(MODES_SCREEN+9)]
F77_RET_T len
Definition: xerbla.cc:61