GNU Octave  4.0.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 <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  //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 #if !defined(Q_OS_MAC)
968  textToSend.prepend("\033");
969 #endif
970  }
971 
972  if ( entry.command() != KeyboardTranslator::NoCommand )
973  {
975  textToSend += getErase();
976  // TODO command handling
977  }
978  else if ( !entry.text().isEmpty() )
979  {
980  textToSend += _codec->fromUnicode(entry.text(true,modifiers));
981  }
982  else
983  textToSend += _codec->fromUnicode(event->text());
984 
985  sendData( textToSend.constData() , textToSend.length() );
986  }
987  else
988  {
989  // print an error message to the terminal if no key translator has been
990  // set
991  QString translatorError = ("No keyboard translator available. "
992  "The information needed to convert key presses "
993  "into characters to send to the terminal "
994  "is missing.");
995 
996  reset();
997  receiveData( translatorError.toAscii().constData() , translatorError.count() );
998  }
999 }
1000 
1001 /* ------------------------------------------------------------------------- */
1002 /* */
1003 /* VT100 Charsets */
1004 /* */
1005 /* ------------------------------------------------------------------------- */
1006 
1007 // Character Set Conversion ------------------------------------------------ --
1008 
1009 /*
1010  The processing contains a VT100 specific code translation layer.
1011  It's still in use and mainly responsible for the line drawing graphics.
1012 
1013  These and some other glyphs are assigned to codes (0x5f-0xfe)
1014  normally occupied by the latin letters. Since this codes also
1015  appear within control sequences, the extra code conversion
1016  does not permute with the tokenizer and is placed behind it
1017  in the pipeline. It only applies to tokens, which represent
1018  plain characters.
1019 
1020  This conversion it eventually continued in TerminalDisplay.C, since
1021  it might involve VT100 enhanced fonts, which have these
1022  particular glyphs allocated in (0x00-0x1f) in their code page.
1023 */
1024 
1025 #define CHARSET _charset[_currentScreen==_screen[1]]
1026 
1027 // Apply current character map.
1028 
1029 unsigned short Vt102Emulation::applyCharset(unsigned short c)
1030 {
1031  if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
1032  if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
1033  return c;
1034 }
1035 
1036 /*
1037  "Charset" related part of the emulation state.
1038  This configures the VT100 _charset filter.
1039 
1040  While most operation work on the current _screen,
1041  the following two are different.
1042 */
1043 
1045 {
1046  _charset[scrno].cu_cs = 0;
1047  strncpy(_charset[scrno].charset,"BBBB",4);
1048  _charset[scrno].sa_graphic = false;
1049  _charset[scrno].sa_pound = false;
1050  _charset[scrno].graphic = false;
1051  _charset[scrno].pound = false;
1052 }
1053 
1054 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
1055 {
1056  _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);
1057  _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);
1058 }
1059 
1061 {
1062  CHARSET.charset[n&3] = cs;
1063  useCharset(n&3);
1064 }
1065 
1067 {
1068  CHARSET.cu_cs = n&3;
1069  CHARSET.graphic = (CHARSET.charset[n&3] == '0');
1070  CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
1071 }
1072 
1074 {
1075  _screen[0]->setDefaultMargins();
1076  _screen[1]->setDefaultMargins();
1077 }
1078 
1079 void Vt102Emulation::setMargins(int t, int b)
1080 {
1081  _screen[0]->setMargins(t, b);
1082  _screen[1]->setMargins(t, b);
1083 }
1084 
1085 /*! Save the cursor position and the rendition attribute settings. */
1086 
1088 {
1089  CHARSET.sa_graphic = CHARSET.graphic;
1090  CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
1091  // we are not clear about these
1092  //sa_charset = charsets[cScreen->_charset];
1093  //sa_charset_num = cScreen->_charset;
1095 }
1096 
1097 /*! Restore the cursor position and the rendition attribute settings. */
1098 
1100 {
1101  CHARSET.graphic = CHARSET.sa_graphic;
1102  CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
1104 }
1105 
1106 /* ------------------------------------------------------------------------- */
1107 /* */
1108 /* Mode Operations */
1109 /* */
1110 /* ------------------------------------------------------------------------- */
1111 
1112 /*
1113  Some of the emulations state is either added to the state of the screens.
1114 
1115  This causes some scoping problems, since different emulations choose to
1116  located the mode either to the current _screen or to both.
1117 
1118  For strange reasons, the extend of the rendition attributes ranges over
1119  all screens and not over the actual _screen.
1120 
1121  We decided on the precise precise extend, somehow.
1122 */
1123 
1124 // "Mode" related part of the state. These are all booleans.
1125 
1127 {
1132 
1134  // here come obsolete modes
1137  setMode(MODE_Ansi );
1138 }
1139 
1141 {
1142  _currParm.mode[m] = true;
1143  switch (m)
1144  {
1145  case MODE_Mouse1000:
1146  case MODE_Mouse1001:
1147  case MODE_Mouse1002:
1148  case MODE_Mouse1003:
1149  emit programUsesMouseChanged(false);
1150  break;
1151 
1152  case MODE_AppScreen : _screen[1]->clearSelection();
1153  setScreen(1);
1154  break;
1155  }
1156  if (m < MODES_SCREEN || m == MODE_NewLine)
1157  {
1158  _screen[0]->setMode(m);
1159  _screen[1]->setMode(m);
1160  }
1161 }
1162 
1164 {
1165  _currParm.mode[m] = false;
1166  switch (m)
1167  {
1168  case MODE_Mouse1000 :
1169  case MODE_Mouse1001 :
1170  case MODE_Mouse1002 :
1171  case MODE_Mouse1003 :
1172  emit programUsesMouseChanged(true);
1173  break;
1174 
1175  case MODE_AppScreen : _screen[0]->clearSelection();
1176  setScreen(0);
1177  break;
1178  }
1179  if (m < MODES_SCREEN || m == MODE_NewLine)
1180  {
1181  _screen[0]->resetMode(m);
1182  _screen[1]->resetMode(m);
1183  }
1184 }
1185 
1187 {
1188  _saveParm.mode[m] = _currParm.mode[m];
1189 }
1190 
1192 {
1193  if (_saveParm.mode[m])
1194  setMode(m);
1195  else
1196  resetMode(m);
1197 }
1198 
1200 {
1201  return _currParm.mode[m];
1202 }
1203 
1205 {
1207  Qt::Key_Backspace,
1208  0,
1209  0);
1210  if ( entry.text().count() > 0 )
1211  return entry.text()[0];
1212  else
1213  return '\b';
1214 }
1215 
1216 /* ------------------------------------------------------------------------- */
1217 /* */
1218 /* Diagnostic */
1219 /* */
1220 /* ------------------------------------------------------------------------- */
1221 
1222 /*! shows the contents of the scan buffer.
1223 
1224  This functions is used for diagnostics. It is called by @e ReportErrorToken
1225  to inform about strings that cannot be decoded or handled by the emulation.
1226 
1227  @sa ReportErrorToken
1228 */
1229 
1230 static void hexdump(int* s, int len)
1231 { int i;
1232  for (i = 0; i < len; i++)
1233  {
1234  if (s[i] == '\\')
1235  printf("\\\\");
1236  else
1237  if ((s[i]) > 32 && s[i] < 127)
1238  printf("%c",s[i]);
1239  else
1240  printf("\\%04x(hex)",s[i]);
1241  }
1242 }
1243 
1245  if (ppos == 0 || (ppos == 1 && (pbuf[0] & 0xff) >= 32)) {
1246  return;
1247  }
1248  printf("token: ");
1249  hexdump(pbuf,ppos);
1250  printf("\n");
1251 }
1252 
1253 /*!
1254 */
1255 
1257 {
1258 #ifndef NDEBUG
1259  printf("undecodable "); scan_buffer_report();
1260 #endif
1261 }
1262 
1263 
void changeTabStop(bool set)
Sets or removes a tab stop at the cursor's current column.
Definition: Screen.cpp:706
void clearToEndOfLine()
Clears from the current cursor position to the end of the line.
Definition: Screen.cpp:1133
void setForeColor(int space, int color)
Sets the cursor's foreground color.
Definition: Screen.cpp:1168
void setAndUseCharset(int n, int cs)
void setCursorY(int y)
Position the cursor on line y.
Definition: Screen.cpp:922
char charset[4]
void clearSelection()
Clears the current selection.
Definition: Screen.cpp:1194
#define TY_CSI_PG(A)
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
Qt::KeyboardModifiers modifierMask() const
Returns the keyboard modifiers which are valid in this entry.
void setBackColor(int space, int color)
Sets the cursor's background color.
Definition: Screen.cpp:1178
virtual char getErase() const
TODO Document me.
#define MODE_AppKeyPad
#define ANSWER_BACK
#define GRP
static void hexdump(int *s, int len)
virtual void resetMode(int mode)
void reset(bool clearScreen=true)
Resets the state of the screen.
Definition: Screen.cpp:639
void setDefaultMargins()
Resets the scrolling margins back to the top and bottom lines of the screen.
Definition: Screen.cpp:422
virtual void clearEntireScreen()
Copies the current image into the history and clears the screen.
static const int LINE_DOUBLEWIDTH
Definition: Character.h:38
Echos the operating system specific erase character.
void setScreen(int index)
Sets the active screen.
Definition: Emulation.cpp:117
Command command() const
Returns the commands associated with this entry.
virtual void receiveChar(int cc)
Processes an incoming character.
#define ces(C)
#define COLOR_SPACE_RGB
Vt102Emulation()
Constructs a new emulation.
void Tabulate(int n=1)
Moves the cursor n tab-stops to the right.
Definition: Screen.cpp:679
void bufferedUpdate()
Schedules an update of attached views.
Definition: Emulation.cpp:297
#define TY_VT52(A)
int getCursorY() const
Returns the line which the cursor is positioned on.
Definition: Screen.cpp:945
#define RE_UNDERLINE
Definition: Character.h:44
void setCursorYX(int y, int x)
Position the cursor at line y, column x.
Definition: Screen.cpp:910
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...
void eraseChars(int n)
Erase n characters beginning from the current cursor position.
Definition: Screen.cpp:240
#define ees(C)
#define RE_REVERSE
Definition: Character.h:45
int getLines()
Return the number of lines.
Definition: Screen.h:377
void reportSecondaryAttributes()
void cursorRight(int n)
Move the cursor to the right by n columns.
Definition: Screen.cpp:173
F77_RET_T const octave_idx_type Complex * A
Definition: CmplxGEPBAL.cc:39
void helpAlign()
Fills the entire screen with the letter 'E'.
Definition: Screen.cpp:1128
Base class for terminal emulation back-ends.
Definition: Emulation.h:118
#define COLOR_SPACE_DEFAULT
#define CPN
void reportTerminalParms(int p)
QHash< int, QString > _pendingTitleUpdates
void resetCharset(int scrno)
void addDigit(int dig)
#define MODE_Mouse1000
#define MAXPBUF
void clearToEndOfScreen()
Clear the area of the screen from the current cursor position to the end of the screen.
Definition: Screen.cpp:1103
void setMargins(int top, int bottom)
void resetMode(int mode)
Resets (clears) the specified screen mode.
Definition: Screen.cpp:313
void backTabulate(int n)
Moves the cursor n tab-stops to the left.
Definition: Screen.cpp:690
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:313
#define ESC
void sendData(const char *data, int len)
Emitted when a buffer of data is ready to send to the standard input of the terminal.
#define epp()
void BackSpace()
Moves the cursor one column to the left and erases the character at the new cursor position...
Definition: Screen.cpp:667
void reportCursorPosition()
Indicates that no special state is active.
#define MODE_Origin
Definition: Screen.h:37
#define MODE_Insert
Definition: Screen.h:39
void Return()
Moves the cursor to the beginning of the current line.
Definition: Screen.cpp:935
#define MODES_SCREEN
Definition: Screen.h:43
#define MODE_Mouse1002
void setMargins(int topLine, int bottomLine)
Sets the margins for scrolling the screen.
Definition: Screen.cpp:180
QByteArray text(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns the character sequence associated with this entry, optionally replacing wildcard '*' characte...
#define CHR
unsigned short vt100_graphics[32]
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
#define COLOR_SPACE_256
#define DIG
void clearEntireScreen()
Clear the whole screen, moving the current screen contents into the history first.
Definition: Screen.cpp:1113
#define TY_ESC_DE(A)
#define MAXARGS
#define MODE_Screen
Definition: Screen.h:40
void programUsesMouseChanged(bool usesMouse)
This is emitted when the program running in the shell indicates whether or not it is interested in mo...
void clearToBeginOfScreen()
Clear the area of the screen from the current cursor position to the start of the screen...
Definition: Screen.cpp:1108
void tau(int code, int p, int q)
void clearScreenAndSetColumns(int columnCount)
#define egt()
void useCharset(int n)
virtual void sendString(const char *, int length=-1)
CharCodes _charset[2]
#define eec(C)
#define MODE_Cursor
Definition: Screen.h:41
#define TY_CSI_PS(A, N)
void stateSet(int state)
Emitted when the activity state of the emulation is set.
#define TY_CSI_PR(A, N)
virtual void setMode(int mode)
Screen * _currentScreen
Definition: Emulation.h:416
unsigned short applyCharset(unsigned short c)
bool mode[(MODES_SCREEN+8)]
const QTextCodec * _codec
Definition: Emulation.h:427
States state() const
Returns a bitwise-OR of the enabled state flags associated with this entry.
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 clearToBeginOfLine()
Clears from the current cursor position to the beginning of the line.
Definition: Screen.cpp:1138
#define epe()
#define les(P, L, C)
void deleteLines(int n)
Removes n lines beginning from the current cursor position.
Definition: Screen.cpp:281
States stateMask() const
Returns the state flags which are valid in this entry.
#define MODE_Ansi
#define TY_ESC(A)
void reverseIndex()
Move the cursor up one line.
Definition: Screen.cpp:218
virtual void sendKeyEvent(QKeyEvent *)
Indicates that the alternate screen ( typically used by interactive programs such as screen or vim ) ...
Indicates that the terminal is in 'Ansi' mode.
#define TY_ESC_CS(A, B)
void insertChars(int n)
Insert n blank characters beginning from the current cursor position.
Definition: Screen.cpp:268
virtual void sendText(const QString &text)
#define TY_CHR()
void pushToToken(int cc)
#define MODE_Wrap
Definition: Screen.h:38
#define lec(P, L, C)
int getCursorX() const
Returns the column which the cursor is positioned at.
Definition: Screen.cpp:940
Indicates that no command is associated with this command sequence.
void titleChanged(int title, const QString &newTitle)
Emitted when the program running in the terminal wishes to update the session's title.
#define eps(C)
void index()
Move the cursor down one line.
Definition: Screen.cpp:207
#define MODE_AppScreen
void changeTabTextColorRequest(int color)
Requests that the color of the text used to represent the tabs associated with this emulation be chan...
double arg(double x)
Definition: lo-mappers.h:37
const KeyboardTranslator * _keyTranslator
Definition: Emulation.h:430
void restoreMode(int mode)
void setLineProperty(LineProperty property, bool enable)
Sets or clears an attribute of the current line.
Definition: Screen.cpp:1551
void resetRendition(int rendition)
Disables the given rendition flag.
Definition: Screen.cpp:1154
#define CPS
Qt::KeyboardModifiers modifiers() const
Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry.
#define SCS
void clearEntireLine()
Clears the whole of the line on which the cursor is currently positioned.
Definition: Screen.cpp:1143
void NextLine()
Moves the cursor down one line and positions it at the beginning of the line.
Definition: Screen.cpp:234
virtual void sendMouseEvent(int buttons, int column, int line, int eventType)
void insertLines(int n)
Inserts lines beginning from the current cursor position.
Definition: Screen.cpp:292
F77_RET_T const octave_idx_type & N
Definition: CmplxGEPBAL.cc:39
Represents an association between a key sequence pressed by the user and the character sequence and c...
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:150
virtual void reset()
Resets the state of the terminal.
#define MODE_Mouse1001
#define MODE_AppCuKeys
void deleteChars(int n)
Delete n characters beginning from the current cursor position.
Definition: Screen.cpp:247
#define Xpe
#define CHARSET
#define MODE_Mouse1003
#define TY_CTL(A)
#define RE_BLINK
Definition: Character.h:43
void setCharset(int n, int cs)
void setMode(int mode)
Sets (enables) the specified screen mode.
Definition: Screen.cpp:302
void clearTabStops()
Clears all the tab stops.
Definition: Screen.cpp:701
void restoreCursor()
Restores the position and appearence of the cursor.
Definition: Screen.cpp:350
void restoreMode(int mode)
Restores the state of a screen mode saved by calling saveMode()
Definition: Screen.cpp:331
void scrollUp(int n)
Scroll the scrolling region of the screen up by n lines.
Definition: Screen.cpp:855
#define CTL
Indicates that any of the modifier keys is active.
Screen * _screen[2]
Definition: Emulation.h:419
void saveCursor()
Saves the current position and appearence (text color and style) of the cursor.
Definition: Screen.cpp:341
void cursorUp(int n)
Move the cursor up by n lines.
Definition: Screen.cpp:129
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:249
#define MODE_NewLine
Definition: Screen.h:42
bool sa_graphic
void cursorDown(int n)
Move the cursor down by n lines.
Definition: Screen.cpp:144
#define Xte
bool getMode(int mode)
void saveMode(int mode)
void ShowCharacter(unsigned short c)
Displays a new character at the current cursor position.
Definition: Screen.cpp:752
void cursorLeft(int n)
Move the cursor to the left by n columns.
Definition: Screen.cpp:159
void scrollDown(int n)
Scroll the scrolling region of the screen down by n lines.
Definition: Screen.cpp:884
#define CNTL(c)
#define COLOR_SPACE_SYSTEM
#define TY_CSI_PE(A)
#define RE_BOLD
Definition: Character.h:42
void setCursorX(int x)
Position the cursor at column x.
Definition: Screen.cpp:915
#define TY_CSI_PN(A)
static const int LINE_DOUBLEHEIGHT
Definition: Character.h:39
#define lun()
QTimer * _titleUpdateTimer
Definition: token.h:30