• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

Vt102Emulation.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of Konsole, an X terminal.
00003     
00004     Copyright 2007-2008 by Robert Knight <robert.knight@gmail.com>
00005     Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00020     02110-1301  USA.
00021 */
00022 
00023 // Own
00024 #include "Vt102Emulation.h"
00025 
00026 // XKB
00027 #include <config-konsole.h>
00028 #if defined(__osf__) || defined(__APPLE__)
00029     #define AVOID_XKB
00030 #endif
00031 
00032 // this allows konsole to be compiled without XKB and XTEST extensions
00033 // even though it might be available on a particular system.
00034 #if defined(AVOID_XKB)
00035     #undef HAVE_XKB
00036 #endif
00037 
00038 #if defined(HAVE_XKB)
00039     void scrolllock_set_off();
00040     void scrolllock_set_on();
00041 #endif
00042 
00043 // Standard 
00044 #include <stdio.h>
00045 #include <unistd.h>
00046 #include <assert.h>
00047 
00048 // Qt
00049 #include <QtCore/QEvent>
00050 #include <QtGui/QKeyEvent>
00051 #include <QtCore/QByteRef>
00052 
00053 // KDE
00054 #include <kdebug.h>
00055 #include <klocale.h>
00056 
00057 // Konsole
00058 #include "KeyboardTranslator.h"
00059 #include "Screen.h"
00060 
00061 
00062 using namespace Konsole;
00063 
00064 Vt102Emulation::Vt102Emulation() 
00065     : Emulation(),
00066      _titleUpdateTimer(new QTimer(this))
00067 {
00068   _titleUpdateTimer->setSingleShot(true);
00069   QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));
00070 
00071   initTokenizer();
00072   reset();
00073 }
00074 
00075 Vt102Emulation::~Vt102Emulation()
00076 {}
00077 
00078 void Vt102Emulation::clearEntireScreen()
00079 {
00080   _currentScreen->clearEntireScreen();
00081   bufferedUpdate(); 
00082 }
00083 
00084 void Vt102Emulation::reset()
00085 {
00086   resetTokenizer();
00087   resetModes();
00088   resetCharset(0);
00089   _screen[0]->reset();
00090   resetCharset(1);
00091   _screen[1]->reset();
00092   setCodec(LocaleCodec);
00093  
00094   bufferedUpdate();
00095 }
00096 
00097 /* ------------------------------------------------------------------------- */
00098 /*                                                                           */
00099 /*                     Processing the incoming byte stream                   */
00100 /*                                                                           */
00101 /* ------------------------------------------------------------------------- */
00102 
00103 /* Incoming Bytes Event pipeline
00104 
00105    This section deals with decoding the incoming character stream.
00106    Decoding means here, that the stream is first separated into `tokens'
00107    which are then mapped to a `meaning' provided as operations by the
00108    `Screen' class or by the emulation class itself.
00109 
00110    The pipeline proceeds as follows:
00111 
00112    - Tokenizing the ESC codes (onReceiveChar)
00113    - VT100 code page translation of plain characters (applyCharset)
00114    - Interpretation of ESC codes (processToken)
00115 
00116    The escape codes and their meaning are described in the
00117    technical reference of this program.
00118 */
00119 
00120 // Tokens ------------------------------------------------------------------ --
00121 
00122 /*
00123    Since the tokens are the central notion if this section, we've put them
00124    in front. They provide the syntactical elements used to represent the
00125    terminals operations as byte sequences.
00126 
00127    They are encodes here into a single machine word, so that we can later
00128    switch over them easily. Depending on the token itself, additional
00129    argument variables are filled with parameter values.
00130 
00131    The tokens are defined below:
00132 
00133    - CHR        - Printable characters     (32..255 but DEL (=127))
00134    - CTL        - Control characters       (0..31 but ESC (= 27), DEL)
00135    - ESC        - Escape codes of the form <ESC><CHR but `[]()+*#'>
00136    - ESC_DE     - Escape codes of the form <ESC><any of `()+*#%'> C
00137    - CSI_PN     - Escape codes of the form <ESC>'['     {Pn} ';' {Pn} C
00138    - CSI_PS     - Escape codes of the form <ESC>'['     {Pn} ';' ...  C
00139    - CSI_PR     - Escape codes of the form <ESC>'[' '?' {Pn} ';' ...  C
00140    - CSI_PE     - Escape codes of the form <ESC>'[' '!' {Pn} ';' ...  C
00141    - VT52       - VT52 escape codes
00142                   - <ESC><Chr>
00143                   - <ESC>'Y'{Pc}{Pc}
00144    - XTE_HA     - Xterm window/terminal attribute commands 
00145                   of the form <ESC>`]' {Pn} `;' {Text} <BEL>
00146                   (Note that these are handled differently to the other formats)
00147 
00148    The last two forms allow list of arguments. Since the elements of
00149    the lists are treated individually the same way, they are passed
00150    as individual tokens to the interpretation. Further, because the
00151    meaning of the parameters are names (althought represented as numbers),
00152    they are includes within the token ('N').
00153 
00154 */
00155 
00156 #define TY_CONSTRUCT(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
00157 
00158 #define TY_CHR(   )     TY_CONSTRUCT(0,0,0)
00159 #define TY_CTL(A  )     TY_CONSTRUCT(1,A,0)
00160 #define TY_ESC(A  )     TY_CONSTRUCT(2,A,0)
00161 #define TY_ESC_CS(A,B)  TY_CONSTRUCT(3,A,B)
00162 #define TY_ESC_DE(A  )  TY_CONSTRUCT(4,A,0)
00163 #define TY_CSI_PS(A,N)  TY_CONSTRUCT(5,A,N)
00164 #define TY_CSI_PN(A  )  TY_CONSTRUCT(6,A,0)
00165 #define TY_CSI_PR(A,N)  TY_CONSTRUCT(7,A,N)
00166 
00167 #define TY_VT52(A)    TY_CONSTRUCT(8,A,0)
00168 #define TY_CSI_PG(A)  TY_CONSTRUCT(9,A,0)
00169 #define TY_CSI_PE(A)  TY_CONSTRUCT(10,A,0)
00170 
00171 #define MAX_ARGUMENT 4096
00172 
00173 // Tokenizer --------------------------------------------------------------- --
00174 
00175 /* The tokenizer's state
00176 
00177    The state is represented by the buffer (tokenBuffer, tokenBufferPos),
00178    and accompanied by decoded arguments kept in (argv,argc).
00179    Note that they are kept internal in the tokenizer.
00180 */
00181 
00182 void Vt102Emulation::resetTokenizer()
00183 {
00184   tokenBufferPos = 0; 
00185   argc = 0; 
00186   argv[0] = 0; 
00187   argv[1] = 0;
00188 }
00189 
00190 void Vt102Emulation::addDigit(int digit)
00191 {
00192   if (argv[argc] < MAX_ARGUMENT)
00193       argv[argc] = 10*argv[argc] + digit;
00194 }
00195 
00196 void Vt102Emulation::addArgument()
00197 {
00198   argc = qMin(argc+1,MAXARGS-1);
00199   argv[argc] = 0;
00200 }
00201 
00202 void Vt102Emulation::addToCurrentToken(int cc)
00203 {
00204   tokenBuffer[tokenBufferPos] = cc;
00205   tokenBufferPos = qMin(tokenBufferPos+1,MAX_TOKEN_LENGTH-1);
00206 }
00207 
00208 // Character Class flags used while decoding
00209 
00210 #define CTL  1  // Control character
00211 #define CHR  2  // Printable character
00212 #define CPN  4  // TODO: Document me 
00213 #define DIG  8  // Digit
00214 #define SCS 16  // TODO: Document me  
00215 #define GRP 32  // TODO: Document me
00216 #define CPS 64  // Character which indicates end of window resize
00217                 // escape sequence '\e[8;<row>;<col>t'
00218 
00219 void Vt102Emulation::initTokenizer()
00220 { 
00221   int i; 
00222   quint8* s;
00223   for(i = 0;i < 256; ++i) 
00224     charClass[i] = 0;
00225   for(i = 0;i < 32; ++i) 
00226     charClass[i] |= CTL;
00227   for(i = 32;i < 256; ++i) 
00228     charClass[i] |= CHR;
00229   for(s = (quint8*)"@ABCDGHILMPSTXZcdfry"; *s; ++s) 
00230     charClass[*s] |= CPN;
00231   // resize = \e[8;<row>;<col>t
00232   for(s = (quint8*)"t"; *s; ++s) 
00233     charClass[*s] |= CPS;
00234   for(s = (quint8*)"0123456789"; *s; ++s) 
00235     charClass[*s] |= DIG;
00236   for(s = (quint8*)"()+*%"; *s; ++s) 
00237     charClass[*s] |= SCS;
00238   for(s = (quint8*)"()+*#[]%"; *s; ++s) 
00239     charClass[*s] |= GRP;
00240 
00241   resetTokenizer();
00242 }
00243 
00244 /* Ok, here comes the nasty part of the decoder.
00245 
00246    Instead of keeping an explicit state, we deduce it from the
00247    token scanned so far. It is then immediately combined with
00248    the current character to form a scanning decision.
00249 
00250    This is done by the following defines.
00251 
00252    - P is the length of the token scanned so far.
00253    - L (often P-1) is the position on which contents we base a decision.
00254    - C is a character or a group of characters (taken from 'charClass').
00255    
00256    - 'cc' is the current character
00257    - 's' is a pointer to the start of the token buffer
00258    - 'p' is the current position within the token buffer 
00259 
00260    Note that they need to applied in proper order.
00261 */
00262 
00263 #define lec(P,L,C) (p == (P) && s[(L)] == (C))
00264 #define lun(     ) (p ==  1  && cc >= 32 )
00265 #define les(P,L,C) (p == (P) && s[L] < 256 && (charClass[s[(L)]] & (C)) == (C))
00266 #define eec(C)     (p >=  3  && cc == (C))
00267 #define ees(C)     (p >=  3  && cc < 256 && (charClass[cc] & (C)) == (C))
00268 #define eps(C)     (p >=  3  && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (charClass[cc] & (C)) == (C))
00269 #define epp( )     (p >=  3  && s[2] == '?')
00270 #define epe( )     (p >=  3  && s[2] == '!')
00271 #define egt( )     (p >=  3  && s[2] == '>')
00272 #define Xpe        (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
00273 #define Xte        (Xpe      && cc ==  7 )
00274 #define ces(C)     (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
00275 
00276 #define ESC 27
00277 #define CNTL(c) ((c)-'@')
00278 
00279 // process an incoming unicode character
00280 void Vt102Emulation::receiveChar(int cc)
00281 { 
00282   if (cc == 127) 
00283     return; //VT100: ignore.
00284 
00285   if (ces(CTL))
00286   { 
00287     // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
00288     // This means, they do neither a resetTokenizer() nor a pushToToken(). Some of them, do
00289     // of course. Guess this originates from a weakly layered handling of the X-on
00290     // X-off protocol, which comes really below this level.
00291     if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) 
00292         resetTokenizer(); //VT100: CAN or SUB
00293     if (cc != ESC)    
00294     { 
00295         processToken(TY_CTL(cc+'@' ),0,0); 
00296         return; 
00297     }
00298   }
00299   // advance the state
00300   addToCurrentToken(cc); 
00301 
00302   int* s = tokenBuffer;
00303   int  p = tokenBufferPos;
00304 
00305   if (getMode(MODE_Ansi)) 
00306   {
00307     if (lec(1,0,ESC)) { return; }
00308     if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('['); return; }
00309     if (les(2,1,GRP)) { return; }
00310     if (Xte         ) { processWindowAttributeChange(); resetTokenizer(); return; }
00311     if (Xpe         ) { return; }
00312     if (lec(3,2,'?')) { return; }
00313     if (lec(3,2,'>')) { return; }
00314     if (lec(3,2,'!')) { return; }
00315     if (lun(       )) { processToken( TY_CHR(), applyCharset(cc), 0);   resetTokenizer(); return; }
00316     if (lec(2,0,ESC)) { processToken( TY_ESC(s[1]), 0, 0);              resetTokenizer(); return; }
00317     if (les(3,1,SCS)) { processToken( TY_ESC_CS(s[1],s[2]), 0, 0);      resetTokenizer(); return; }
00318     if (lec(3,1,'#')) { processToken( TY_ESC_DE(s[2]), 0, 0);           resetTokenizer(); return; }
00319     if (eps(    CPN)) { processToken( TY_CSI_PN(cc), argv[0],argv[1]);  resetTokenizer(); return; }
00320 
00321     // resize = \e[8;<row>;<col>t
00322     if (eps(CPS)) 
00323     { 
00324         processToken( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]);   
00325         resetTokenizer(); 
00326         return; 
00327     }
00328 
00329     if (epe(   )) { processToken( TY_CSI_PE(cc), 0, 0); resetTokenizer(); return; }
00330     if (ees(DIG)) { addDigit(cc-'0'); return; }
00331     if (eec(';')) { addArgument();    return; }
00332     for (int i=0;i<=argc;i++)
00333     {
00334         if (epp())  
00335             processToken( TY_CSI_PR(cc,argv[i]), 0, 0);
00336         else if (egt())   
00337             processToken( TY_CSI_PG(cc), 0, 0); // spec. case for ESC]>0c or ESC]>c
00338         else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
00339         { 
00340             // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
00341             i += 2;
00342             processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);
00343             i += 2;
00344         }
00345         else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)
00346         { 
00347             // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
00348             i += 2;
00349             processToken( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_256, argv[i]);
00350         }
00351         else
00352             processToken( TY_CSI_PS(cc,argv[i]), 0, 0);
00353     }
00354     resetTokenizer();
00355   }
00356   else 
00357   {
00358     // VT52 Mode
00359     if (lec(1,0,ESC))                                                      
00360         return;
00361     if (les(1,0,CHR)) 
00362     { 
00363         processToken( TY_CHR(), s[0], 0); 
00364         resetTokenizer(); 
00365         return; 
00366     }
00367     if (lec(2,1,'Y'))                                                      
00368         return;
00369     if (lec(3,1,'Y'))                                                      
00370         return;
00371     if (p < 4) 
00372     { 
00373         processToken( TY_VT52(s[1] ), 0, 0); 
00374         resetTokenizer(); 
00375         return; 
00376     }
00377     processToken( TY_VT52(s[1]), s[2], s[3]); 
00378     resetTokenizer(); 
00379     return;
00380   }
00381 }
00382 void Vt102Emulation::processWindowAttributeChange()
00383 {
00384   // Describes the window or terminal session attribute to change
00385   // See Session::UserTitleChange for possible values
00386   int attributeToChange = 0;
00387   int i;
00388   for (i = 2; i < tokenBufferPos     && 
00389               tokenBuffer[i] >= '0'  && 
00390               tokenBuffer[i] <= '9'; i++)
00391   {
00392     attributeToChange = 10 * attributeToChange + (tokenBuffer[i]-'0');
00393   }
00394 
00395   if (tokenBuffer[i] != ';') 
00396   { 
00397     reportDecodingError(); 
00398     return; 
00399   }
00400   
00401   QString newValue;
00402   newValue.reserve(tokenBufferPos-i-2);
00403   for (int j = 0; j < tokenBufferPos-i-2; j++)
00404     newValue[j] = tokenBuffer[i+1+j];
00405  
00406   _pendingTitleUpdates[attributeToChange] = newValue;
00407   _titleUpdateTimer->start(20);
00408 }
00409 
00410 void Vt102Emulation::updateTitle()
00411 {
00412     QListIterator<int> iter( _pendingTitleUpdates.keys() );
00413     while (iter.hasNext()) {
00414         int arg = iter.next();
00415         emit titleChanged( arg , _pendingTitleUpdates[arg] );    
00416     }
00417     _pendingTitleUpdates.clear();    
00418 }
00419 
00420 // Interpreting Codes ---------------------------------------------------------
00421 
00422 /*
00423    Now that the incoming character stream is properly tokenized,
00424    meaning is assigned to them. These are either operations of
00425    the current _screen, or of the emulation class itself.
00426 
00427    The token to be interpreteted comes in as a machine word
00428    possibly accompanied by two parameters.
00429 
00430    Likewise, the operations assigned to, come with up to two
00431    arguments. One could consider to make up a proper table
00432    from the function below.
00433 
00434    The technical reference manual provides more information
00435    about this mapping.
00436 */
00437 
00438 void Vt102Emulation::processToken(int token, int p, int q)
00439 {
00440   switch (token)
00441   {
00442 
00443     case TY_CHR(         ) : _currentScreen->displayCharacter     (p         ); break; //UTF16
00444 
00445     //             127 DEL    : ignored on input
00446 
00447     case TY_CTL('@'      ) : /* NUL: ignored                      */ break;
00448     case TY_CTL('A'      ) : /* SOH: ignored                      */ break;
00449     case TY_CTL('B'      ) : /* STX: ignored                      */ break;
00450     case TY_CTL('C'      ) : /* ETX: ignored                      */ break;
00451     case TY_CTL('D'      ) : /* EOT: ignored                      */ break;
00452     case TY_CTL('E'      ) :      reportAnswerBack     (          ); break; //VT100
00453     case TY_CTL('F'      ) : /* ACK: ignored                      */ break;
00454     case TY_CTL('G'      ) : emit stateSet(NOTIFYBELL);
00455                                 break; //VT100
00456     case TY_CTL('H'      ) : _currentScreen->backspace            (          ); break; //VT100
00457     case TY_CTL('I'      ) : _currentScreen->tab                  (          ); break; //VT100
00458     case TY_CTL('J'      ) : _currentScreen->newLine              (          ); break; //VT100
00459     case TY_CTL('K'      ) : _currentScreen->newLine              (          ); break; //VT100
00460     case TY_CTL('L'      ) : _currentScreen->newLine              (          ); break; //VT100
00461     case TY_CTL('M'      ) : _currentScreen->toStartOfLine        (          ); break; //VT100
00462 
00463     case TY_CTL('N'      ) :      useCharset           (         1); break; //VT100
00464     case TY_CTL('O'      ) :      useCharset           (         0); break; //VT100
00465 
00466     case TY_CTL('P'      ) : /* DLE: ignored                      */ break;
00467     case TY_CTL('Q'      ) : /* DC1: XON continue                 */ break; //VT100
00468     case TY_CTL('R'      ) : /* DC2: ignored                      */ break;
00469     case TY_CTL('S'      ) : /* DC3: XOFF halt                    */ break; //VT100
00470     case TY_CTL('T'      ) : /* DC4: ignored                      */ break;
00471     case TY_CTL('U'      ) : /* NAK: ignored                      */ break;
00472     case TY_CTL('V'      ) : /* SYN: ignored                      */ break;
00473     case TY_CTL('W'      ) : /* ETB: ignored                      */ break;
00474     case TY_CTL('X'      ) : _currentScreen->displayCharacter     (    0x2592); break; //VT100
00475     case TY_CTL('Y'      ) : /* EM : ignored                      */ break;
00476     case TY_CTL('Z'      ) : _currentScreen->displayCharacter     (    0x2592); break; //VT100
00477     case TY_CTL('['      ) : /* ESC: cannot be seen here.         */ break;
00478     case TY_CTL('\\'     ) : /* FS : ignored                      */ break;
00479     case TY_CTL(']'      ) : /* GS : ignored                      */ break;
00480     case TY_CTL('^'      ) : /* RS : ignored                      */ break;
00481     case TY_CTL('_'      ) : /* US : ignored                      */ break;
00482 
00483     case TY_ESC('D'      ) : _currentScreen->index                (          ); break; //VT100
00484     case TY_ESC('E'      ) : _currentScreen->nextLine             (          ); break; //VT100
00485     case TY_ESC('H'      ) : _currentScreen->changeTabStop        (true      ); break; //VT100
00486     case TY_ESC('M'      ) : _currentScreen->reverseIndex         (          ); break; //VT100
00487     case TY_ESC('Z'      ) :      reportTerminalType   (          ); break;
00488     case TY_ESC('c'      ) :      reset                (          ); break;
00489 
00490     case TY_ESC('n'      ) :      useCharset           (         2); break;
00491     case TY_ESC('o'      ) :      useCharset           (         3); break;
00492     case TY_ESC('7'      ) :      saveCursor           (          ); break;
00493     case TY_ESC('8'      ) :      restoreCursor        (          ); break;
00494 
00495     case TY_ESC('='      ) :          setMode      (MODE_AppKeyPad); break;
00496     case TY_ESC('>'      ) :        resetMode      (MODE_AppKeyPad); break;
00497     case TY_ESC('<'      ) :          setMode      (MODE_Ansi     ); break; //VT100
00498 
00499     case TY_ESC_CS('(', '0') :      setCharset           (0,    '0'); break; //VT100
00500     case TY_ESC_CS('(', 'A') :      setCharset           (0,    'A'); break; //VT100
00501     case TY_ESC_CS('(', 'B') :      setCharset           (0,    'B'); break; //VT100
00502 
00503     case TY_ESC_CS(')', '0') :      setCharset           (1,    '0'); break; //VT100
00504     case TY_ESC_CS(')', 'A') :      setCharset           (1,    'A'); break; //VT100
00505     case TY_ESC_CS(')', 'B') :      setCharset           (1,    'B'); break; //VT100
00506 
00507     case TY_ESC_CS('*', '0') :      setCharset           (2,    '0'); break; //VT100
00508     case TY_ESC_CS('*', 'A') :      setCharset           (2,    'A'); break; //VT100
00509     case TY_ESC_CS('*', 'B') :      setCharset           (2,    'B'); break; //VT100
00510 
00511     case TY_ESC_CS('+', '0') :      setCharset           (3,    '0'); break; //VT100
00512     case TY_ESC_CS('+', 'A') :      setCharset           (3,    'A'); break; //VT100
00513     case TY_ESC_CS('+', 'B') :      setCharset           (3,    'B'); break; //VT100
00514 
00515     case TY_ESC_CS('%', 'G') :      setCodec             (Utf8Codec   ); break; //LINUX
00516     case TY_ESC_CS('%', '@') :      setCodec             (LocaleCodec ); break; //LINUX
00517 
00518     case TY_ESC_DE('3'      ) : /* Double height line, top half    */ 
00519                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
00520                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
00521                                     break;
00522     case TY_ESC_DE('4'      ) : /* Double height line, bottom half */ 
00523                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
00524                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
00525                                     break;
00526     case TY_ESC_DE('5'      ) : /* Single width, single height line*/
00527                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
00528                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
00529                                 break;
00530     case TY_ESC_DE('6'      ) : /* Double width, single height line*/ 
00531                                 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);    
00532                                 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
00533                                 break;
00534     case TY_ESC_DE('8'      ) : _currentScreen->helpAlign            (          ); break;
00535 
00536 // resize = \e[8;<row>;<col>t
00537     case TY_CSI_PS('t',   8) : setImageSize( q /* colums */, p /* lines */ );    break;
00538 
00539 // change tab text color : \e[28;<color>t  color: 0-16,777,215
00540     case TY_CSI_PS('t',   28) : emit changeTabTextColorRequest      ( p        );          break;
00541 
00542     case TY_CSI_PS('K',   0) : _currentScreen->clearToEndOfLine     (          ); break;
00543     case TY_CSI_PS('K',   1) : _currentScreen->clearToBeginOfLine   (          ); break;
00544     case TY_CSI_PS('K',   2) : _currentScreen->clearEntireLine      (          ); break;
00545     case TY_CSI_PS('J',   0) : _currentScreen->clearToEndOfScreen   (          ); break;
00546     case TY_CSI_PS('J',   1) : _currentScreen->clearToBeginOfScreen (          ); break;
00547     case TY_CSI_PS('J',   2) : _currentScreen->clearEntireScreen    (          ); break;
00548     case TY_CSI_PS('J',      3) : clearHistory();                            break;
00549     case TY_CSI_PS('g',   0) : _currentScreen->changeTabStop        (false     ); break; //VT100
00550     case TY_CSI_PS('g',   3) : _currentScreen->clearTabStops        (          ); break; //VT100
00551     case TY_CSI_PS('h',   4) : _currentScreen->    setMode      (MODE_Insert   ); break;
00552     case TY_CSI_PS('h',  20) :          setMode      (MODE_NewLine  ); break;
00553     case TY_CSI_PS('i',   0) : /* IGNORE: attached printer          */ break; //VT100
00554     case TY_CSI_PS('l',   4) : _currentScreen->  resetMode      (MODE_Insert   ); break;
00555     case TY_CSI_PS('l',  20) :        resetMode      (MODE_NewLine  ); break;
00556     case TY_CSI_PS('s',   0) :      saveCursor           (          ); break;
00557     case TY_CSI_PS('u',   0) :      restoreCursor        (          ); break;
00558 
00559     case TY_CSI_PS('m',   0) : _currentScreen->setDefaultRendition  (          ); break;
00560     case TY_CSI_PS('m',   1) : _currentScreen->  setRendition     (RE_BOLD     ); break; //VT100
00561     case TY_CSI_PS('m',   4) : _currentScreen->  setRendition     (RE_UNDERLINE); break; //VT100
00562     case TY_CSI_PS('m',   5) : _currentScreen->  setRendition     (RE_BLINK    ); break; //VT100
00563     case TY_CSI_PS('m',   7) : _currentScreen->  setRendition     (RE_REVERSE  ); break;
00564     case TY_CSI_PS('m',  10) : /* IGNORED: mapping related          */ break; //LINUX
00565     case TY_CSI_PS('m',  11) : /* IGNORED: mapping related          */ break; //LINUX
00566     case TY_CSI_PS('m',  12) : /* IGNORED: mapping related          */ break; //LINUX
00567     case TY_CSI_PS('m',  22) : _currentScreen->resetRendition     (RE_BOLD     ); break;
00568     case TY_CSI_PS('m',  24) : _currentScreen->resetRendition     (RE_UNDERLINE); break;
00569     case TY_CSI_PS('m',  25) : _currentScreen->resetRendition     (RE_BLINK    ); break;
00570     case TY_CSI_PS('m',  27) : _currentScreen->resetRendition     (RE_REVERSE  ); break;
00571 
00572     case TY_CSI_PS('m',   30) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  0); break;
00573     case TY_CSI_PS('m',   31) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  1); break;
00574     case TY_CSI_PS('m',   32) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  2); break;
00575     case TY_CSI_PS('m',   33) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  3); break;
00576     case TY_CSI_PS('m',   34) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  4); break;
00577     case TY_CSI_PS('m',   35) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  5); break;
00578     case TY_CSI_PS('m',   36) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  6); break;
00579     case TY_CSI_PS('m',   37) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  7); break;
00580 
00581     case TY_CSI_PS('m',   38) : _currentScreen->setForeColor         (p,       q); break;
00582 
00583     case TY_CSI_PS('m',   39) : _currentScreen->setForeColor         (COLOR_SPACE_DEFAULT,  0); break;
00584 
00585     case TY_CSI_PS('m',   40) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  0); break;
00586     case TY_CSI_PS('m',   41) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  1); break;
00587     case TY_CSI_PS('m',   42) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  2); break;
00588     case TY_CSI_PS('m',   43) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  3); break;
00589     case TY_CSI_PS('m',   44) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  4); break;
00590     case TY_CSI_PS('m',   45) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  5); break;
00591     case TY_CSI_PS('m',   46) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  6); break;
00592     case TY_CSI_PS('m',   47) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  7); break;
00593 
00594     case TY_CSI_PS('m',   48) : _currentScreen->setBackColor         (p,       q); break;
00595 
00596     case TY_CSI_PS('m',   49) : _currentScreen->setBackColor         (COLOR_SPACE_DEFAULT,  1); break;
00597 
00598     case TY_CSI_PS('m',   90) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  8); break;
00599     case TY_CSI_PS('m',   91) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  9); break;
00600     case TY_CSI_PS('m',   92) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 10); break;
00601     case TY_CSI_PS('m',   93) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 11); break;
00602     case TY_CSI_PS('m',   94) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 12); break;
00603     case TY_CSI_PS('m',   95) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 13); break;
00604     case TY_CSI_PS('m',   96) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 14); break;
00605     case TY_CSI_PS('m',   97) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 15); break;
00606 
00607     case TY_CSI_PS('m',  100) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  8); break;
00608     case TY_CSI_PS('m',  101) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  9); break;
00609     case TY_CSI_PS('m',  102) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 10); break;
00610     case TY_CSI_PS('m',  103) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 11); break;
00611     case TY_CSI_PS('m',  104) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 12); break;
00612     case TY_CSI_PS('m',  105) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 13); break;
00613     case TY_CSI_PS('m',  106) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 14); break;
00614     case TY_CSI_PS('m',  107) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 15); break;
00615 
00616     case TY_CSI_PS('n',   5) :      reportStatus         (          ); break;
00617     case TY_CSI_PS('n',   6) :      reportCursorPosition (          ); break;
00618     case TY_CSI_PS('q',   0) : /* IGNORED: LEDs off                 */ break; //VT100
00619     case TY_CSI_PS('q',   1) : /* IGNORED: LED1 on                  */ break; //VT100
00620     case TY_CSI_PS('q',   2) : /* IGNORED: LED2 on                  */ break; //VT100
00621     case TY_CSI_PS('q',   3) : /* IGNORED: LED3 on                  */ break; //VT100
00622     case TY_CSI_PS('q',   4) : /* IGNORED: LED4 on                  */ break; //VT100
00623     case TY_CSI_PS('x',   0) :      reportTerminalParms  (         2); break; //VT100
00624     case TY_CSI_PS('x',   1) :      reportTerminalParms  (         3); break; //VT100
00625 
00626     case TY_CSI_PN('@'      ) : _currentScreen->insertChars          (p         ); break;
00627     case TY_CSI_PN('A'      ) : _currentScreen->cursorUp             (p         ); break; //VT100
00628     case TY_CSI_PN('B'      ) : _currentScreen->cursorDown           (p         ); break; //VT100
00629     case TY_CSI_PN('C'      ) : _currentScreen->cursorRight          (p         ); break; //VT100
00630     case TY_CSI_PN('D'      ) : _currentScreen->cursorLeft           (p         ); break; //VT100
00631     case TY_CSI_PN('G'      ) : _currentScreen->setCursorX           (p         ); break; //LINUX
00632     case TY_CSI_PN('H'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100
00633     case TY_CSI_PN('I'      ) : _currentScreen->tab                  (p         ); break;
00634     case TY_CSI_PN('L'      ) : _currentScreen->insertLines          (p         ); break;
00635     case TY_CSI_PN('M'      ) : _currentScreen->deleteLines          (p         ); break;
00636     case TY_CSI_PN('P'      ) : _currentScreen->deleteChars          (p         ); break;
00637     case TY_CSI_PN('S'      ) : _currentScreen->scrollUp             (p         ); break;
00638     case TY_CSI_PN('T'      ) : _currentScreen->scrollDown           (p         ); break;
00639     case TY_CSI_PN('X'      ) : _currentScreen->eraseChars           (p         ); break;
00640     case TY_CSI_PN('Z'      ) : _currentScreen->backtab              (p         ); break;
00641     case TY_CSI_PN('c'      ) :      reportTerminalType   (          ); break; //VT100
00642     case TY_CSI_PN('d'      ) : _currentScreen->setCursorY           (p         ); break; //LINUX
00643     case TY_CSI_PN('f'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100
00644     case TY_CSI_PN('r'      ) :      setMargins           (p,      q); break; //VT100
00645     case TY_CSI_PN('y'      ) : /* IGNORED: Confidence test          */ break; //VT100
00646 
00647     case TY_CSI_PR('h',   1) :          setMode      (MODE_AppCuKeys); break; //VT100
00648     case TY_CSI_PR('l',   1) :        resetMode      (MODE_AppCuKeys); break; //VT100
00649     case TY_CSI_PR('s',   1) :         saveMode      (MODE_AppCuKeys); break; //FIXME
00650     case TY_CSI_PR('r',   1) :      restoreMode      (MODE_AppCuKeys); break; //FIXME
00651 
00652     case TY_CSI_PR('l',   2) :        resetMode      (MODE_Ansi     ); break; //VT100
00653 
00654     case TY_CSI_PR('h',   3) :          setMode      (MODE_132Columns);break; //VT100
00655     case TY_CSI_PR('l',   3) :        resetMode      (MODE_132Columns);break; //VT100
00656 
00657     case TY_CSI_PR('h',   4) : /* IGNORED: soft scrolling           */ break; //VT100
00658     case TY_CSI_PR('l',   4) : /* IGNORED: soft scrolling           */ break; //VT100
00659 
00660     case TY_CSI_PR('h',   5) : _currentScreen->    setMode      (MODE_Screen   ); break; //VT100
00661     case TY_CSI_PR('l',   5) : _currentScreen->  resetMode      (MODE_Screen   ); break; //VT100
00662 
00663     case TY_CSI_PR('h',   6) : _currentScreen->    setMode      (MODE_Origin   ); break; //VT100
00664     case TY_CSI_PR('l',   6) : _currentScreen->  resetMode      (MODE_Origin   ); break; //VT100
00665     case TY_CSI_PR('s',   6) : _currentScreen->   saveMode      (MODE_Origin   ); break; //FIXME
00666     case TY_CSI_PR('r',   6) : _currentScreen->restoreMode      (MODE_Origin   ); break; //FIXME
00667 
00668     case TY_CSI_PR('h',   7) : _currentScreen->    setMode      (MODE_Wrap     ); break; //VT100
00669     case TY_CSI_PR('l',   7) : _currentScreen->  resetMode      (MODE_Wrap     ); break; //VT100
00670     case TY_CSI_PR('s',   7) : _currentScreen->   saveMode      (MODE_Wrap     ); break; //FIXME
00671     case TY_CSI_PR('r',   7) : _currentScreen->restoreMode      (MODE_Wrap     ); break; //FIXME
00672 
00673     case TY_CSI_PR('h',   8) : /* IGNORED: autorepeat on            */ break; //VT100
00674     case TY_CSI_PR('l',   8) : /* IGNORED: autorepeat off           */ break; //VT100
00675     case TY_CSI_PR('s',   8) : /* IGNORED: autorepeat on            */ break; //VT100
00676     case TY_CSI_PR('r',   8) : /* IGNORED: autorepeat off           */ break; //VT100
00677 
00678     case TY_CSI_PR('h',   9) : /* IGNORED: interlace                */ break; //VT100
00679     case TY_CSI_PR('l',   9) : /* IGNORED: interlace                */ break; //VT100
00680     case TY_CSI_PR('s',   9) : /* IGNORED: interlace                */ break; //VT100
00681     case TY_CSI_PR('r',   9) : /* IGNORED: interlace                */ break; //VT100
00682 
00683     case TY_CSI_PR('h',  12) : /* IGNORED: Cursor blink             */ break; //att610
00684     case TY_CSI_PR('l',  12) : /* IGNORED: Cursor blink             */ break; //att610
00685     case TY_CSI_PR('s',  12) : /* IGNORED: Cursor blink             */ break; //att610
00686     case TY_CSI_PR('r',  12) : /* IGNORED: Cursor blink             */ break; //att610
00687 
00688     case TY_CSI_PR('h',  25) :          setMode      (MODE_Cursor   ); break; //VT100
00689     case TY_CSI_PR('l',  25) :        resetMode      (MODE_Cursor   ); break; //VT100
00690     case TY_CSI_PR('s',  25) :         saveMode      (MODE_Cursor   ); break; //VT100
00691     case TY_CSI_PR('r',  25) :      restoreMode      (MODE_Cursor   ); break; //VT100
00692 
00693     case TY_CSI_PR('h',  40) :         setMode(MODE_Allow132Columns ); break; // XTERM
00694     case TY_CSI_PR('l',  40) :       resetMode(MODE_Allow132Columns ); break; // XTERM
00695 
00696     case TY_CSI_PR('h',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
00697     case TY_CSI_PR('l',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
00698     case TY_CSI_PR('s',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
00699     case TY_CSI_PR('r',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM
00700 
00701     case TY_CSI_PR('h',  47) :          setMode      (MODE_AppScreen); break; //VT100
00702     case TY_CSI_PR('l',  47) :        resetMode      (MODE_AppScreen); break; //VT100
00703     case TY_CSI_PR('s',  47) :         saveMode      (MODE_AppScreen); break; //XTERM
00704     case TY_CSI_PR('r',  47) :      restoreMode      (MODE_AppScreen); break; //XTERM
00705 
00706     case TY_CSI_PR('h',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
00707     case TY_CSI_PR('l',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
00708     case TY_CSI_PR('s',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
00709     case TY_CSI_PR('r',  67) : /* IGNORED: DECBKM                   */ break; //XTERM
00710 
00711     // XTerm defines the following modes:
00712     // SET_VT200_MOUSE             1000
00713     // SET_VT200_HIGHLIGHT_MOUSE   1001
00714     // SET_BTN_EVENT_MOUSE         1002
00715     // SET_ANY_EVENT_MOUSE         1003
00716     //
00717     
00718     //Note about mouse modes:
00719     //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003
00720     //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).
00721     //TODO:  Implementation of mouse modes 1001 (something called hilight tracking) and 
00722     //1003 (a slight variation on dragging the mouse)
00723     //
00724  
00725     case TY_CSI_PR('h', 1000) :          setMode      (MODE_Mouse1000); break; //XTERM
00726     case TY_CSI_PR('l', 1000) :        resetMode      (MODE_Mouse1000); break; //XTERM
00727     case TY_CSI_PR('s', 1000) :         saveMode      (MODE_Mouse1000); break; //XTERM
00728     case TY_CSI_PR('r', 1000) :      restoreMode      (MODE_Mouse1000); break; //XTERM
00729 
00730     case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
00731     case TY_CSI_PR('l', 1001) :        resetMode      (MODE_Mouse1001); break; //XTERM
00732     case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
00733     case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM
00734 
00735     case TY_CSI_PR('h', 1002) :          setMode      (MODE_Mouse1002); break; //XTERM
00736     case TY_CSI_PR('l', 1002) :        resetMode      (MODE_Mouse1002); break; //XTERM
00737     case TY_CSI_PR('s', 1002) :         saveMode      (MODE_Mouse1002); break; //XTERM
00738     case TY_CSI_PR('r', 1002) :      restoreMode      (MODE_Mouse1002); break; //XTERM
00739 
00740     case TY_CSI_PR('h', 1003) :          setMode      (MODE_Mouse1003); break; //XTERM
00741     case TY_CSI_PR('l', 1003) :        resetMode      (MODE_Mouse1003); break; //XTERM
00742     case TY_CSI_PR('s', 1003) :         saveMode      (MODE_Mouse1003); break; //XTERM
00743     case TY_CSI_PR('r', 1003) :      restoreMode      (MODE_Mouse1003); break; //XTERM
00744 
00745     case TY_CSI_PR('h', 1047) :          setMode      (MODE_AppScreen); break; //XTERM
00746     case TY_CSI_PR('l', 1047) : _screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break; //XTERM
00747     case TY_CSI_PR('s', 1047) :         saveMode      (MODE_AppScreen); break; //XTERM
00748     case TY_CSI_PR('r', 1047) :      restoreMode      (MODE_AppScreen); break; //XTERM
00749 
00750     //FIXME: Unitoken: save translations
00751     case TY_CSI_PR('h', 1048) :      saveCursor           (          ); break; //XTERM
00752     case TY_CSI_PR('l', 1048) :      restoreCursor        (          ); break; //XTERM
00753     case TY_CSI_PR('s', 1048) :      saveCursor           (          ); break; //XTERM
00754     case TY_CSI_PR('r', 1048) :      restoreCursor        (          ); break; //XTERM
00755 
00756     //FIXME: every once new sequences like this pop up in xterm.
00757     //       Here's a guess of what they could mean.
00758     case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM
00759     case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM
00760 
00761     //FIXME: weird DEC reset sequence
00762     case TY_CSI_PE('p'      ) : /* IGNORED: reset         (        ) */ break;
00763 
00764     //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
00765     case TY_VT52('A'      ) : _currentScreen->cursorUp             (         1); break; //VT52
00766     case TY_VT52('B'      ) : _currentScreen->cursorDown           (         1); break; //VT52
00767     case TY_VT52('C'      ) : _currentScreen->cursorRight          (         1); break; //VT52
00768     case TY_VT52('D'      ) : _currentScreen->cursorLeft           (         1); break; //VT52
00769 
00770     case TY_VT52('F'      ) :      setAndUseCharset     (0,    '0'); break; //VT52
00771     case TY_VT52('G'      ) :      setAndUseCharset     (0,    'B'); break; //VT52
00772 
00773     case TY_VT52('H'      ) : _currentScreen->setCursorYX          (1,1       ); break; //VT52
00774     case TY_VT52('I'      ) : _currentScreen->reverseIndex         (          ); break; //VT52
00775     case TY_VT52('J'      ) : _currentScreen->clearToEndOfScreen   (          ); break; //VT52
00776     case TY_VT52('K'      ) : _currentScreen->clearToEndOfLine     (          ); break; //VT52
00777     case TY_VT52('Y'      ) : _currentScreen->setCursorYX          (p-31,q-31 ); break; //VT52
00778     case TY_VT52('Z'      ) :      reportTerminalType   (           ); break; //VT52
00779     case TY_VT52('<'      ) :          setMode      (MODE_Ansi     ); break; //VT52
00780     case TY_VT52('='      ) :          setMode      (MODE_AppKeyPad); break; //VT52
00781     case TY_VT52('>'      ) :        resetMode      (MODE_AppKeyPad); break; //VT52
00782 
00783     case TY_CSI_PG('c'      ) :  reportSecondaryAttributes(          ); break; //VT100
00784 
00785     default: 
00786         reportDecodingError();    
00787         break;
00788   };
00789 }
00790 
00791 void Vt102Emulation::clearScreenAndSetColumns(int columnCount)
00792 {
00793     setImageSize(_currentScreen->getLines(),columnCount); 
00794     clearEntireScreen();
00795     setDefaultMargins(); 
00796     _currentScreen->setCursorYX(0,0);
00797 }
00798 
00799 void Vt102Emulation::sendString(const char* s , int length)
00800 {
00801   if ( length >= 0 )
00802     emit sendData(s,length);
00803   else
00804     emit sendData(s,strlen(s));
00805 }
00806 
00807 void Vt102Emulation::reportCursorPosition()
00808 { 
00809   char tmp[20];
00810   sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);
00811   sendString(tmp);
00812 }
00813 
00814 void Vt102Emulation::reportTerminalType()
00815 {
00816   // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
00817   // VT220:  ^[[?63;1;2;3;6;7;8c   (list deps on emul. capabilities)
00818   // VT100:  ^[[?1;2c
00819   // VT101:  ^[[?1;0c
00820   // VT102:  ^[[?6v
00821   if (getMode(MODE_Ansi))
00822     sendString("\033[?1;2c"); // I'm a VT100
00823   else
00824     sendString("\033/Z"); // I'm a VT52
00825 }
00826 
00827 void Vt102Emulation::reportSecondaryAttributes()
00828 {
00829   // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
00830   if (getMode(MODE_Ansi))
00831     sendString("\033[>0;115;0c"); // Why 115?  ;)
00832   else
00833     sendString("\033/Z");         // FIXME I don't think VT52 knows about it but kept for
00834                                   // konsoles backward compatibility.
00835 }
00836 
00837 void Vt102Emulation::reportTerminalParms(int p)
00838 // DECREPTPARM
00839 { 
00840   char tmp[100];
00841   sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
00842   sendString(tmp);
00843 }
00844 
00845 void Vt102Emulation::reportStatus()
00846 {
00847   sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
00848 }
00849 
00850 void Vt102Emulation::reportAnswerBack()
00851 {
00852   // FIXME - Test this with VTTEST
00853   // This is really obsolete VT100 stuff.
00854   const char* ANSWER_BACK = "";
00855   sendString(ANSWER_BACK);
00856 }
00857 
00868 void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
00869 { 
00870   if (cx < 1 || cy < 1) 
00871     return;
00872 
00873   // normal buttons are passed as 0x20 + button,
00874   // mouse wheel (buttons 4,5) as 0x5c + button
00875   if (cb >= 4) 
00876     cb += 0x3c;
00877 
00878   //Mouse motion handling
00879   if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
00880       cb += 0x20; //add 32 to signify motion event
00881 
00882   char command[20];
00883   sprintf(command,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20);
00884   sendString(command);
00885 }
00886 
00887 void Vt102Emulation::sendText( const QString& text )
00888 {
00889   if (!text.isEmpty()) 
00890   {
00891     QKeyEvent event(QEvent::KeyPress, 
00892                     0, 
00893                     Qt::NoModifier, 
00894                     text);
00895     sendKeyEvent(&event); // expose as a big fat keypress event
00896   }
00897 }
00898 void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
00899 {
00900     Qt::KeyboardModifiers modifiers = event->modifiers();
00901     KeyboardTranslator::States states = KeyboardTranslator::NoState;
00902 
00903     // get current states
00904     if (getMode(MODE_NewLine)  ) states |= KeyboardTranslator::NewLineState;
00905     if (getMode(MODE_Ansi)     ) states |= KeyboardTranslator::AnsiState;
00906     if (getMode(MODE_AppCuKeys)) states |= KeyboardTranslator::CursorKeysState;
00907     if (getMode(MODE_AppScreen)) states |= KeyboardTranslator::AlternateScreenState;
00908     if (getMode(MODE_AppKeyPad) && (modifiers & Qt::KeypadModifier)) 
00909         states |= KeyboardTranslator::ApplicationKeypadState;
00910 
00911     // check flow control state
00912     if (modifiers & Qt::ControlModifier)
00913     {
00914         if (event->key() == Qt::Key_S)
00915             emit flowControlKeyPressed(true);
00916         else if (event->key() == Qt::Key_Q)
00917             emit flowControlKeyPressed(false);
00918     }
00919 
00920     // lookup key binding
00921     if ( _keyTranslator )
00922     {
00923     KeyboardTranslator::Entry entry = _keyTranslator->findEntry( 
00924                                                 event->key() , 
00925                                                 modifiers,
00926                                                 states );
00927 
00928         // send result to terminal
00929         QByteArray textToSend;
00930 
00931         // special handling for the Alt (aka. Meta) modifier.  pressing
00932         // Alt+[Character] results in Esc+[Character] being sent
00933         // (unless there is an entry defined for this particular combination
00934         //  in the keyboard modifier)
00935         bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;
00936         bool wantsAnyModifier = entry.state() & 
00937                                 entry.stateMask() & KeyboardTranslator::AnyModifierState;
00938 
00939         if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier) 
00940              && !event->text().isEmpty() )
00941         {
00942             textToSend.prepend("\033");
00943         }
00944 
00945         if ( entry.command() != KeyboardTranslator::NoCommand )
00946         {
00947             if (entry.command() & KeyboardTranslator::EraseCommand)
00948                 textToSend += eraseChar();
00949 
00950             // TODO command handling
00951         }
00952         else if ( !entry.text().isEmpty() ) 
00953         {
00954             textToSend += _codec->fromUnicode(entry.text(true,modifiers));
00955         }
00956         else
00957             textToSend += _codec->fromUnicode(event->text());
00958 
00959         sendData( textToSend.constData() , textToSend.length() );
00960     }
00961     else
00962     {
00963         // print an error message to the terminal if no key translator has been
00964         // set
00965         QString translatorError =  i18n("No keyboard translator available.  "
00966                                          "The information needed to convert key presses "
00967                                          "into characters to send to the terminal " 
00968                                          "is missing.");
00969         reset();
00970         receiveData( translatorError.toAscii().constData() , translatorError.count() );
00971     }
00972 }
00973 
00974 /* ------------------------------------------------------------------------- */
00975 /*                                                                           */
00976 /*                                VT100 Charsets                             */
00977 /*                                                                           */
00978 /* ------------------------------------------------------------------------- */
00979 
00980 // Character Set Conversion ------------------------------------------------ --
00981 
00982 /* 
00983    The processing contains a VT100 specific code translation layer.
00984    It's still in use and mainly responsible for the line drawing graphics.
00985 
00986    These and some other glyphs are assigned to codes (0x5f-0xfe)
00987    normally occupied by the latin letters. Since this codes also
00988    appear within control sequences, the extra code conversion
00989    does not permute with the tokenizer and is placed behind it
00990    in the pipeline. It only applies to tokens, which represent
00991    plain characters.
00992 
00993    This conversion it eventually continued in TerminalDisplay.C, since 
00994    it might involve VT100 enhanced fonts, which have these
00995    particular glyphs allocated in (0x00-0x1f) in their code page.
00996 */
00997 
00998 #define CHARSET _charset[_currentScreen==_screen[1]]
00999 
01000 // Apply current character map.
01001 
01002 unsigned short Vt102Emulation::applyCharset(unsigned short c)
01003 {
01004   if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
01005   if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
01006   return c;
01007 }
01008 
01009 /*
01010    "Charset" related part of the emulation state.
01011    This configures the VT100 charset filter.
01012 
01013    While most operation work on the current _screen,
01014    the following two are different.
01015 */
01016 
01017 void Vt102Emulation::resetCharset(int scrno)
01018 {
01019   _charset[scrno].cu_cs = 0;
01020   strncpy(_charset[scrno].charset,"BBBB",4);
01021   _charset[scrno].sa_graphic = false;
01022   _charset[scrno].sa_pound = false;
01023   _charset[scrno].graphic = false;
01024   _charset[scrno].pound = false;
01025 }
01026 
01027 void Vt102Emulation::setCharset(int n, int cs) // on both screens.
01028 {
01029   _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);
01030   _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);
01031 }
01032 
01033 void Vt102Emulation::setAndUseCharset(int n, int cs)
01034 {
01035   CHARSET.charset[n&3] = cs;
01036   useCharset(n&3);
01037 }
01038 
01039 void Vt102Emulation::useCharset(int n)
01040 {
01041   CHARSET.cu_cs   = n&3;
01042   CHARSET.graphic = (CHARSET.charset[n&3] == '0');
01043   CHARSET.pound   = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
01044 }
01045 
01046 void Vt102Emulation::setDefaultMargins()
01047 {
01048     _screen[0]->setDefaultMargins();
01049     _screen[1]->setDefaultMargins();
01050 }
01051 
01052 void Vt102Emulation::setMargins(int t, int b)
01053 {
01054   _screen[0]->setMargins(t, b);
01055   _screen[1]->setMargins(t, b);
01056 }
01057 
01058 void Vt102Emulation::saveCursor()
01059 {
01060   CHARSET.sa_graphic = CHARSET.graphic;
01061   CHARSET.sa_pound   = CHARSET.pound; //This mode is obsolete
01062   // we are not clear about these
01063   //sa_charset = charsets[cScreen->_charset];
01064   //sa_charset_num = cScreen->_charset;
01065   _currentScreen->saveCursor();
01066 }
01067 
01068 void Vt102Emulation::restoreCursor()
01069 {
01070   CHARSET.graphic = CHARSET.sa_graphic;
01071   CHARSET.pound   = CHARSET.sa_pound; //This mode is obsolete
01072   _currentScreen->restoreCursor();
01073 }
01074 
01075 /* ------------------------------------------------------------------------- */
01076 /*                                                                           */
01077 /*                                Mode Operations                            */
01078 /*                                                                           */
01079 /* ------------------------------------------------------------------------- */
01080 
01081 /*
01082    Some of the emulations state is either added to the state of the screens.
01083 
01084    This causes some scoping problems, since different emulations choose to
01085    located the mode either to the current _screen or to both.
01086 
01087    For strange reasons, the extend of the rendition attributes ranges over
01088    all screens and not over the actual _screen.
01089 
01090    We decided on the precise precise extend, somehow.
01091 */
01092 
01093 // "Mode" related part of the state. These are all booleans.
01094 
01095 void Vt102Emulation::resetModes()
01096 {
01097   // MODE_Allow132Columns is not reset here
01098   // to match Xterm's behaviour (see Xterm's VTReset() function)
01099 
01100   resetMode(MODE_132Columns); saveMode(MODE_132Columns);
01101   resetMode(MODE_Mouse1000);  saveMode(MODE_Mouse1000);
01102   resetMode(MODE_Mouse1001);  saveMode(MODE_Mouse1001);
01103   resetMode(MODE_Mouse1002);  saveMode(MODE_Mouse1002);
01104   resetMode(MODE_Mouse1003);  saveMode(MODE_Mouse1003);
01105 
01106   resetMode(MODE_AppScreen);  saveMode(MODE_AppScreen);
01107   resetMode(MODE_AppCuKeys);  saveMode(MODE_AppCuKeys);
01108   resetMode(MODE_AppKeyPad);  saveMode(MODE_AppKeyPad);
01109   resetMode(MODE_NewLine);
01110   setMode(MODE_Ansi);
01111 }
01112 
01113 void Vt102Emulation::setMode(int m)
01114 {
01115   _currentModes.mode[m] = true;
01116   switch (m)
01117   {
01118     case MODE_132Columns:
01119         if (getMode(MODE_Allow132Columns))
01120             clearScreenAndSetColumns(132);
01121         else
01122             _currentModes.mode[m] = false;
01123         break;
01124     case MODE_Mouse1000:
01125     case MODE_Mouse1001:
01126     case MODE_Mouse1002:
01127     case MODE_Mouse1003:
01128          emit programUsesMouseChanged(false); 
01129     break;
01130 
01131     case MODE_AppScreen : _screen[1]->clearSelection();
01132                           setScreen(1);
01133     break;
01134   }
01135   if (m < MODES_SCREEN || m == MODE_NewLine)
01136   {
01137     _screen[0]->setMode(m);
01138     _screen[1]->setMode(m);
01139   }
01140 }
01141 
01142 void Vt102Emulation::resetMode(int m)
01143 {
01144   _currentModes.mode[m] = false;
01145   switch (m)
01146   {
01147     case MODE_132Columns:
01148         if (getMode(MODE_Allow132Columns))
01149             clearScreenAndSetColumns(80);
01150         break;
01151     case MODE_Mouse1000 : 
01152     case MODE_Mouse1001 :
01153     case MODE_Mouse1002 :
01154     case MODE_Mouse1003 :
01155         emit programUsesMouseChanged(true); 
01156     break;
01157 
01158     case MODE_AppScreen : 
01159         _screen[0]->clearSelection();
01160         setScreen(0);
01161     break;
01162   }
01163   if (m < MODES_SCREEN || m == MODE_NewLine)
01164   {
01165     _screen[0]->resetMode(m);
01166     _screen[1]->resetMode(m);
01167   }
01168 }
01169 
01170 void Vt102Emulation::saveMode(int m)
01171 {
01172   _savedModes.mode[m] = _currentModes.mode[m];
01173 }
01174 
01175 void Vt102Emulation::restoreMode(int m)
01176 {
01177   if (_savedModes.mode[m]) 
01178       setMode(m); 
01179   else 
01180       resetMode(m);
01181 }
01182 
01183 bool Vt102Emulation::getMode(int m)
01184 {
01185   return _currentModes.mode[m];
01186 }
01187 
01188 char Vt102Emulation::eraseChar() const
01189 {
01190   KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
01191                                             Qt::Key_Backspace,
01192                                             0,
01193                                             0);
01194   if ( entry.text().count() > 0 )
01195       return entry.text()[0];
01196   else
01197       return '\b';
01198 }
01199 
01200 // print contents of the scan buffer
01201 static void hexdump(int* s, int len)
01202 { int i;
01203   for (i = 0; i < len; i++)
01204   {
01205     if (s[i] == '\\')
01206       printf("\\\\");
01207     else
01208     if ((s[i]) > 32 && s[i] < 127)
01209       printf("%c",s[i]);
01210     else
01211       printf("\\%04x(hex)",s[i]);
01212   }
01213 }
01214 
01215 void Vt102Emulation::reportDecodingError()
01216 {
01217   if (tokenBufferPos == 0 || ( tokenBufferPos == 1 && (tokenBuffer[0] & 0xff) >= 32) ) 
01218     return;
01219   printf("Undecodable sequence: "); 
01220   hexdump(tokenBuffer,tokenBufferPos); 
01221   printf("\n");
01222 }
01223 
01224 #include "Vt102Emulation.moc"
01225 

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal