00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Vt102Emulation.h"
00025
00026
00027 #include <config-konsole.h>
00028 #if defined(__osf__) || defined(__APPLE__)
00029 #define AVOID_XKB
00030 #endif
00031
00032
00033
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
00044 #include <stdio.h>
00045 #include <unistd.h>
00046 #include <assert.h>
00047
00048
00049 #include <QtCore/QEvent>
00050 #include <QtGui/QKeyEvent>
00051 #include <QtCore/QByteRef>
00052
00053
00054 #include <kdebug.h>
00055 #include <klocale.h>
00056
00057
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
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
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
00174
00175
00176
00177
00178
00179
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
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
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
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
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
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
00280 void Vt102Emulation::receiveChar(int cc)
00281 {
00282 if (cc == 127)
00283 return;
00284
00285 if (ces(CTL))
00286 {
00287
00288
00289
00290
00291 if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC)
00292 resetTokenizer();
00293 if (cc != ESC)
00294 {
00295 processToken(TY_CTL(cc+'@' ),0,0);
00296 return;
00297 }
00298 }
00299
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
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);
00338 else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
00339 {
00340
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
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
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
00385
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
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
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;
00444
00445
00446
00447 case TY_CTL('@' ) : break;
00448 case TY_CTL('A' ) : break;
00449 case TY_CTL('B' ) : break;
00450 case TY_CTL('C' ) : break;
00451 case TY_CTL('D' ) : break;
00452 case TY_CTL('E' ) : reportAnswerBack ( ); break;
00453 case TY_CTL('F' ) : break;
00454 case TY_CTL('G' ) : emit stateSet(NOTIFYBELL);
00455 break;
00456 case TY_CTL('H' ) : _currentScreen->backspace ( ); break;
00457 case TY_CTL('I' ) : _currentScreen->tab ( ); break;
00458 case TY_CTL('J' ) : _currentScreen->newLine ( ); break;
00459 case TY_CTL('K' ) : _currentScreen->newLine ( ); break;
00460 case TY_CTL('L' ) : _currentScreen->newLine ( ); break;
00461 case TY_CTL('M' ) : _currentScreen->toStartOfLine ( ); break;
00462
00463 case TY_CTL('N' ) : useCharset ( 1); break;
00464 case TY_CTL('O' ) : useCharset ( 0); break;
00465
00466 case TY_CTL('P' ) : break;
00467 case TY_CTL('Q' ) : break;
00468 case TY_CTL('R' ) : break;
00469 case TY_CTL('S' ) : break;
00470 case TY_CTL('T' ) : break;
00471 case TY_CTL('U' ) : break;
00472 case TY_CTL('V' ) : break;
00473 case TY_CTL('W' ) : break;
00474 case TY_CTL('X' ) : _currentScreen->displayCharacter ( 0x2592); break;
00475 case TY_CTL('Y' ) : break;
00476 case TY_CTL('Z' ) : _currentScreen->displayCharacter ( 0x2592); break;
00477 case TY_CTL('[' ) : break;
00478 case TY_CTL('\\' ) : break;
00479 case TY_CTL(']' ) : break;
00480 case TY_CTL('^' ) : break;
00481 case TY_CTL('_' ) : break;
00482
00483 case TY_ESC('D' ) : _currentScreen->index ( ); break;
00484 case TY_ESC('E' ) : _currentScreen->nextLine ( ); break;
00485 case TY_ESC('H' ) : _currentScreen->changeTabStop (true ); break;
00486 case TY_ESC('M' ) : _currentScreen->reverseIndex ( ); break;
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;
00498
00499 case TY_ESC_CS('(', '0') : setCharset (0, '0'); break;
00500 case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break;
00501 case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break;
00502
00503 case TY_ESC_CS(')', '0') : setCharset (1, '0'); break;
00504 case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break;
00505 case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break;
00506
00507 case TY_ESC_CS('*', '0') : setCharset (2, '0'); break;
00508 case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break;
00509 case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break;
00510
00511 case TY_ESC_CS('+', '0') : setCharset (3, '0'); break;
00512 case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break;
00513 case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break;
00514
00515 case TY_ESC_CS('%', 'G') : setCodec (Utf8Codec ); break;
00516 case TY_ESC_CS('%', '@') : setCodec (LocaleCodec ); break;
00517
00518 case TY_ESC_DE('3' ) :
00519 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
00520 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
00521 break;
00522 case TY_ESC_DE('4' ) :
00523 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
00524 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
00525 break;
00526 case TY_ESC_DE('5' ) :
00527 _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
00528 _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
00529 break;
00530 case TY_ESC_DE('6' ) :
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
00537 case TY_CSI_PS('t', 8) : setImageSize( q , p ); break;
00538
00539
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;
00550 case TY_CSI_PS('g', 3) : _currentScreen->clearTabStops ( ); break;
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) : break;
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;
00561 case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break;
00562 case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break;
00563 case TY_CSI_PS('m', 7) : _currentScreen-> setRendition (RE_REVERSE ); break;
00564 case TY_CSI_PS('m', 10) : break;
00565 case TY_CSI_PS('m', 11) : break;
00566 case TY_CSI_PS('m', 12) : break;
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) : break;
00619 case TY_CSI_PS('q', 1) : break;
00620 case TY_CSI_PS('q', 2) : break;
00621 case TY_CSI_PS('q', 3) : break;
00622 case TY_CSI_PS('q', 4) : break;
00623 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break;
00624 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break;
00625
00626 case TY_CSI_PN('@' ) : _currentScreen->insertChars (p ); break;
00627 case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break;
00628 case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break;
00629 case TY_CSI_PN('C' ) : _currentScreen->cursorRight (p ); break;
00630 case TY_CSI_PN('D' ) : _currentScreen->cursorLeft (p ); break;
00631 case TY_CSI_PN('G' ) : _currentScreen->setCursorX (p ); break;
00632 case TY_CSI_PN('H' ) : _currentScreen->setCursorYX (p, q); break;
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;
00642 case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break;
00643 case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break;
00644 case TY_CSI_PN('r' ) : setMargins (p, q); break;
00645 case TY_CSI_PN('y' ) : break;
00646
00647 case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break;
00648 case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break;
00649 case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break;
00650 case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break;
00651
00652 case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break;
00653
00654 case TY_CSI_PR('h', 3) : setMode (MODE_132Columns);break;
00655 case TY_CSI_PR('l', 3) : resetMode (MODE_132Columns);break;
00656
00657 case TY_CSI_PR('h', 4) : break;
00658 case TY_CSI_PR('l', 4) : break;
00659
00660 case TY_CSI_PR('h', 5) : _currentScreen-> setMode (MODE_Screen ); break;
00661 case TY_CSI_PR('l', 5) : _currentScreen-> resetMode (MODE_Screen ); break;
00662
00663 case TY_CSI_PR('h', 6) : _currentScreen-> setMode (MODE_Origin ); break;
00664 case TY_CSI_PR('l', 6) : _currentScreen-> resetMode (MODE_Origin ); break;
00665 case TY_CSI_PR('s', 6) : _currentScreen-> saveMode (MODE_Origin ); break;
00666 case TY_CSI_PR('r', 6) : _currentScreen->restoreMode (MODE_Origin ); break;
00667
00668 case TY_CSI_PR('h', 7) : _currentScreen-> setMode (MODE_Wrap ); break;
00669 case TY_CSI_PR('l', 7) : _currentScreen-> resetMode (MODE_Wrap ); break;
00670 case TY_CSI_PR('s', 7) : _currentScreen-> saveMode (MODE_Wrap ); break;
00671 case TY_CSI_PR('r', 7) : _currentScreen->restoreMode (MODE_Wrap ); break;
00672
00673 case TY_CSI_PR('h', 8) : break;
00674 case TY_CSI_PR('l', 8) : break;
00675 case TY_CSI_PR('s', 8) : break;
00676 case TY_CSI_PR('r', 8) : break;
00677
00678 case TY_CSI_PR('h', 9) : break;
00679 case TY_CSI_PR('l', 9) : break;
00680 case TY_CSI_PR('s', 9) : break;
00681 case TY_CSI_PR('r', 9) : break;
00682
00683 case TY_CSI_PR('h', 12) : break;
00684 case TY_CSI_PR('l', 12) : break;
00685 case TY_CSI_PR('s', 12) : break;
00686 case TY_CSI_PR('r', 12) : break;
00687
00688 case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break;
00689 case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break;
00690 case TY_CSI_PR('s', 25) : saveMode (MODE_Cursor ); break;
00691 case TY_CSI_PR('r', 25) : restoreMode (MODE_Cursor ); break;
00692
00693 case TY_CSI_PR('h', 40) : setMode(MODE_Allow132Columns ); break;
00694 case TY_CSI_PR('l', 40) : resetMode(MODE_Allow132Columns ); break;
00695
00696 case TY_CSI_PR('h', 41) : break;
00697 case TY_CSI_PR('l', 41) : break;
00698 case TY_CSI_PR('s', 41) : break;
00699 case TY_CSI_PR('r', 41) : break;
00700
00701 case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break;
00702 case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break;
00703 case TY_CSI_PR('s', 47) : saveMode (MODE_AppScreen); break;
00704 case TY_CSI_PR('r', 47) : restoreMode (MODE_AppScreen); break;
00705
00706 case TY_CSI_PR('h', 67) : break;
00707 case TY_CSI_PR('l', 67) : break;
00708 case TY_CSI_PR('s', 67) : break;
00709 case TY_CSI_PR('r', 67) : break;
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break;
00726 case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break;
00727 case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break;
00728 case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break;
00729
00730 case TY_CSI_PR('h', 1001) : break;
00731 case TY_CSI_PR('l', 1001) : resetMode (MODE_Mouse1001); break;
00732 case TY_CSI_PR('s', 1001) : break;
00733 case TY_CSI_PR('r', 1001) : break;
00734
00735 case TY_CSI_PR('h', 1002) : setMode (MODE_Mouse1002); break;
00736 case TY_CSI_PR('l', 1002) : resetMode (MODE_Mouse1002); break;
00737 case TY_CSI_PR('s', 1002) : saveMode (MODE_Mouse1002); break;
00738 case TY_CSI_PR('r', 1002) : restoreMode (MODE_Mouse1002); break;
00739
00740 case TY_CSI_PR('h', 1003) : setMode (MODE_Mouse1003); break;
00741 case TY_CSI_PR('l', 1003) : resetMode (MODE_Mouse1003); break;
00742 case TY_CSI_PR('s', 1003) : saveMode (MODE_Mouse1003); break;
00743 case TY_CSI_PR('r', 1003) : restoreMode (MODE_Mouse1003); break;
00744
00745 case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break;
00746 case TY_CSI_PR('l', 1047) : _screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break;
00747 case TY_CSI_PR('s', 1047) : saveMode (MODE_AppScreen); break;
00748 case TY_CSI_PR('r', 1047) : restoreMode (MODE_AppScreen); break;
00749
00750
00751 case TY_CSI_PR('h', 1048) : saveCursor ( ); break;
00752 case TY_CSI_PR('l', 1048) : restoreCursor ( ); break;
00753 case TY_CSI_PR('s', 1048) : saveCursor ( ); break;
00754 case TY_CSI_PR('r', 1048) : restoreCursor ( ); break;
00755
00756
00757
00758 case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break;
00759 case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break;
00760
00761
00762 case TY_CSI_PE('p' ) : break;
00763
00764
00765 case TY_VT52('A' ) : _currentScreen->cursorUp ( 1); break;
00766 case TY_VT52('B' ) : _currentScreen->cursorDown ( 1); break;
00767 case TY_VT52('C' ) : _currentScreen->cursorRight ( 1); break;
00768 case TY_VT52('D' ) : _currentScreen->cursorLeft ( 1); break;
00769
00770 case TY_VT52('F' ) : setAndUseCharset (0, '0'); break;
00771 case TY_VT52('G' ) : setAndUseCharset (0, 'B'); break;
00772
00773 case TY_VT52('H' ) : _currentScreen->setCursorYX (1,1 ); break;
00774 case TY_VT52('I' ) : _currentScreen->reverseIndex ( ); break;
00775 case TY_VT52('J' ) : _currentScreen->clearToEndOfScreen ( ); break;
00776 case TY_VT52('K' ) : _currentScreen->clearToEndOfLine ( ); break;
00777 case TY_VT52('Y' ) : _currentScreen->setCursorYX (p-31,q-31 ); break;
00778 case TY_VT52('Z' ) : reportTerminalType ( ); break;
00779 case TY_VT52('<' ) : setMode (MODE_Ansi ); break;
00780 case TY_VT52('=' ) : setMode (MODE_AppKeyPad); break;
00781 case TY_VT52('>' ) : resetMode (MODE_AppKeyPad); break;
00782
00783 case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break;
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
00817
00818
00819
00820
00821 if (getMode(MODE_Ansi))
00822 sendString("\033[?1;2c");
00823 else
00824 sendString("\033/Z");
00825 }
00826
00827 void Vt102Emulation::reportSecondaryAttributes()
00828 {
00829
00830 if (getMode(MODE_Ansi))
00831 sendString("\033[>0;115;0c");
00832 else
00833 sendString("\033/Z");
00834
00835 }
00836
00837 void Vt102Emulation::reportTerminalParms(int p)
00838
00839 {
00840 char tmp[100];
00841 sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p);
00842 sendString(tmp);
00843 }
00844
00845 void Vt102Emulation::reportStatus()
00846 {
00847 sendString("\033[0n");
00848 }
00849
00850 void Vt102Emulation::reportAnswerBack()
00851 {
00852
00853
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
00874
00875 if (cb >= 4)
00876 cb += 0x3c;
00877
00878
00879 if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
00880 cb += 0x20;
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);
00896 }
00897 }
00898 void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
00899 {
00900 Qt::KeyboardModifiers modifiers = event->modifiers();
00901 KeyboardTranslator::States states = KeyboardTranslator::NoState;
00902
00903
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
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
00921 if ( _keyTranslator )
00922 {
00923 KeyboardTranslator::Entry entry = _keyTranslator->findEntry(
00924 event->key() ,
00925 modifiers,
00926 states );
00927
00928
00929 QByteArray textToSend;
00930
00931
00932
00933
00934
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
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
00964
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
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 #define CHARSET _charset[_currentScreen==_screen[1]]
00999
01000
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;
01006 return c;
01007 }
01008
01009
01010
01011
01012
01013
01014
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)
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');
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;
01062
01063
01064
01065 _currentScreen->saveCursor();
01066 }
01067
01068 void Vt102Emulation::restoreCursor()
01069 {
01070 CHARSET.graphic = CHARSET.sa_graphic;
01071 CHARSET.pound = CHARSET.sa_pound;
01072 _currentScreen->restoreCursor();
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095 void Vt102Emulation::resetModes()
01096 {
01097
01098
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
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