summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-console/vt102emulation.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-console/vt102emulation.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/vt102emulation.cpp1024
1 files changed, 0 insertions, 1024 deletions
diff --git a/noncore/apps/opie-console/vt102emulation.cpp b/noncore/apps/opie-console/vt102emulation.cpp
deleted file mode 100644
index 35b789c..0000000
--- a/noncore/apps/opie-console/vt102emulation.cpp
+++ b/dev/null
@@ -1,1024 +0,0 @@
1/* ------------------------------------------------------------------------- */
2/* */
3/* [vt102emulation.cpp] VT102 Terminal Emulation */
4/* */
5/* ------------------------------------------------------------------------- */
6/* */
7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
8/* */
9/* This file is part of Konsole - an X terminal for KDE */
10/* */
11/* ------------------------------------------------------------------------- */
12/* */
13/* Ported Konsole to Qt/Embedded */
14/* */
15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
16/* */
17/* -------------------------------------------------------------------------- */
18
19/*! \class Vt102Emulation
20
21 \brief Actual Emulation for Konsole
22
23 \sa Widget \sa Screen \sa EmulationLayer
24*/
25
26#include "vt102emulation.h"
27
28#include <stdio.h>
29#include <unistd.h>
30
31
32/* VT102 Terminal Emulation
33
34 This class puts together the screens, the pty and the widget to a
35 complete terminal emulation. Beside combining it's componentes, it
36 handles the emulations's protocol.
37
38 This module consists of the following sections:
39
40 - Constructor/Destructor
41 - Incoming Bytes Event pipeline
42 - Outgoing Bytes
43 - Mouse Events
44 - Keyboard Events
45 - Modes and Charset State
46 - Diagnostics
47*/
48
49
50/* ------------------------------------------------------------------------- */
51/* */
52/* Constructor / Destructor */
53/* */
54/* ------------------------------------------------------------------------- */
55
56/*
57 Nothing really intesting happens here.
58*/
59
60/*!
61*/
62
63Vt102Emulation::Vt102Emulation(WidgetLayer* gui) : EmulationLayer(gui)
64{
65 QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
66 this,SLOT(onMouse(int,int,int)));
67 initTokenizer();
68 reset();
69}
70
71/*!
72*/
73
74Vt102Emulation::~Vt102Emulation()
75{
76}
77
78/*!
79*/
80
81void Vt102Emulation::reset()
82{
83 resetToken();
84 resetModes();
85 resetCharset(0); screen[0]->reset();
86 resetCharset(1); screen[0]->reset();
87 setCodec(0);
88 setKeytrans("linux.keytab");
89}
90
91/* ------------------------------------------------------------------------- */
92/* */
93/* Processing the incoming byte stream */
94/* */
95/* ------------------------------------------------------------------------- */
96
97/* Incoming Bytes Event pipeline
98
99 This section deals with decoding the incoming character stream.
100 Decoding means here, that the stream is first seperated into `tokens'
101 which are then mapped to a `meaning' provided as operations by the
102 `TEScreen' class or by the emulation class itself.
103
104 The pipeline proceeds as follows:
105
106 - Tokenizing the ESC codes (onRcvChar)
107 - VT100 code page translation of plain characters (applyCharset)
108 - Interpretation of ESC codes (tau)
109
110 The escape codes and their meaning are described in the
111 technical reference of this program.
112*/
113
114// Tokens ------------------------------------------------------------------ --
115
116/*
117 Since the tokens are the central notion if this section, we've put them
118 in front. They provide the syntactical elements used to represent the
119 terminals operations as byte sequences.
120
121 They are encodes here into a single machine word, so that we can later
122 switch over them easily. Depending on the token itself, additional
123 argument variables are filled with parameter values.
124
125 The tokens are defined below:
126
127 - CHR - Printable characters (32..255 but DEL (=127))
128 - CTL - Control characters (0..31 but ESC (= 27), DEL)
129 - ESC - Escape codes of the form <ESC><CHR but `[]()+*#'>
130 - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
131 - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
132 - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
133 - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
134 - VT52 - VT52 escape codes
135 - <ESC><Chr>
136 - <ESC>'Y'{Pc}{Pc}
137 - XTE_HA - Xterm hacks <ESC>`]' {Pn} `;' {Text} <BEL>
138 note that this is handled differently
139
140 The last two forms allow list of arguments. Since the elements of
141 the lists are treated individually the same way, they are passed
142 as individual tokens to the interpretation. Further, because the
143 meaning of the parameters are names (althought represented as numbers),
144 they are includes within the token ('N').
145
146*/
147
148#define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
149
150#define TY_CHR___( ) TY_CONSTR(0,0,0)
151#define TY_CTL___(A ) TY_CONSTR(1,A,0)
152#define TY_ESC___(A ) TY_CONSTR(2,A,0)
153#define TY_ESC_CS(A,B) TY_CONSTR(3,A,B)
154#define TY_ESC_DE(A ) TY_CONSTR(4,A,0)
155#define TY_CSI_PS(A,N) TY_CONSTR(5,A,N)
156#define TY_CSI_PN(A ) TY_CONSTR(6,A,0)
157#define TY_CSI_PR(A,N) TY_CONSTR(7,A,N)
158
159#define TY_VT52__(A ) TY_CONSTR(8,A,0)
160
161// Tokenizer --------------------------------------------------------------- --
162
163/* The tokenizers state
164
165 The state is represented by the buffer (pbuf, ppos),
166 and accompanied by decoded arguments kept in (argv,argc).
167 Note that they are kept internal in the tokenizer.
168*/
169
170void Vt102Emulation::resetToken()
171{
172 ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
173}
174
175void Vt102Emulation::addDigit(int dig)
176{
177 argv[argc] = 10*argv[argc] + dig;
178}
179
180void Vt102Emulation::addArgument()
181{
182 argc = QMIN(argc+1,MAXARGS-1);
183 argv[argc] = 0;
184}
185
186void Vt102Emulation::pushToToken(int cc)
187{
188 pbuf[ppos] = cc;
189 ppos = QMIN(ppos+1,MAXPBUF-1);
190}
191
192// Character Classes used while decoding
193
194#define CTL 1
195#define CHR 2
196#define CPN 4
197#define DIG 8
198#define SCS 16
199#define GRP 32
200
201void Vt102Emulation::initTokenizer()
202{ int i; UINT8* s;
203 for(i = 0; i < 256; i++) tbl[ i] = 0;
204 for(i = 0; i < 32; i++) tbl[ i] |= CTL;
205 for(i = 32; i < 256; i++) tbl[ i] |= CHR;
206 for(s = (UINT8*)"@ABCDGHLMPXcdfry"; *s; s++) tbl[*s] |= CPN;
207 for(s = (UINT8*)"0123456789" ; *s; s++) tbl[*s] |= DIG;
208 for(s = (UINT8*)"()+*%" ; *s; s++) tbl[*s] |= SCS;
209 for(s = (UINT8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP;
210 resetToken();
211}
212
213/* Ok, here comes the nasty part of the decoder.
214
215 Instead of keeping an explicit state, we deduce it from the
216 token scanned so far. It is then immediately combined with
217 the current character to form a scanning decision.
218
219 This is done by the following defines.
220
221 - P is the length of the token scanned so far.
222 - L (often P-1) is the position on which contents we base a decision.
223 - C is a character or a group of characters (taken from 'tbl').
224
225 Note that they need to applied in proper order.
226*/
227
228#define lec(P,L,C) (p == (P) && s[(L)] == (C))
229#define lun( ) (p == 1 && cc >= 32 )
230#define les(P,L,C) (p == (P) && s[L] < 256 && (tbl[s[(L)]] & (C)) == (C))
231#define eec(C) (p >= 3 && cc == (C))
232#define ees(C) (p >= 3 && cc < 256 && (tbl[ cc ] & (C)) == (C))
233#define eps(C) (p >= 3 && s[2] != '?' && cc < 256 && (tbl[ cc ] & (C)) == (C))
234#define epp( ) (p >= 3 && s[2] == '?' )
235#define egt( ) (p == 3 && s[2] == '>' )
236#define Xpe (ppos>=2 && pbuf[1] == ']' )
237#define Xte (Xpe && cc == 7 )
238#define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte)
239
240#define ESC 27
241#define CNTL(c) ((c)-'@')
242
243// process an incoming unicode character
244
245void Vt102Emulation::onRcvChar(int cc)
246{ int i;
247
248 if (cc == 127) return; //VT100: ignore.
249
250 if (ces( CTL))
251 { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
252 // This means, they do neither a resetToken nor a pushToToken. Some of them, do
253 // of course. Guess this originates from a weakly layered handling of the X-on
254 // X-off protocol, which comes really below this level.
255 if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB
256 if (cc != ESC) { tau( TY_CTL___(cc+'@' ), 0, 0); return; }
257 }
258
259 pushToToken(cc); // advance the state
260
261 int* s = pbuf;
262 int p = ppos;
263
264 if (getMode(MODE_Ansi)) // decide on proper action
265 {
266 if (lec(1,0,ESC)) { return; }
267 if (les(2,1,GRP)) { return; }
268 if (Xte ) { XtermHack(); resetToken(); return; }
269 if (Xpe ) { return; }
270 if (lec(3,2,'?')) { return; }
271 if (lec(3,2,'>')) { return; }
272 if (lun( )) { tau( TY_CHR___(), applyCharset(cc), 0); resetToken(); return; }
273 if (lec(2,0,ESC)) { tau( TY_ESC___(s[1]), 0, 0); resetToken(); return; }
274 if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]), 0, 0); resetToken(); return; }
275 if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]), 0, 0); resetToken(); return; }
276// if (egt( )) { tau( TY_CSI_PG(cc ), '>', 0); resetToken(); return; }
277 if (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; }
278 if (ees( DIG)) { addDigit(cc-'0'); return; }
279 if (eec( ';')) { addArgument(); return; }
280 for (i=0;i<=argc;i++)
281 if (epp( )) tau( TY_CSI_PR(cc,argv[i]), 0, 0); else
282 tau( TY_CSI_PS(cc,argv[i]), 0, 0);
283 resetToken();
284 }
285 else // mode VT52
286 {
287 if (lec(1,0,ESC)) return;
288 if (les(1,0,CHR)) { tau( TY_CHR___( ), s[0], 0); resetToken(); return; }
289 if (lec(2,1,'Y')) return;
290 if (lec(3,1,'Y')) return;
291 if (p < 4) { tau( TY_VT52__(s[1] ), 0, 0); resetToken(); return; }
292 tau( TY_VT52__(s[1] ), s[2],s[3]); resetToken(); return;
293 }
294}
295
296void Vt102Emulation::XtermHack()
297{ int i,arg = 0;
298 for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)
299 arg = 10*arg + (pbuf[i]-'0');
300 if (pbuf[i] != ';') { ReportErrorToken(); return; }
301 QChar *str = new QChar[ppos-i-2];
302 for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
303 QString unistr(str,ppos-i-2);
304 // arg == 1 doesn't change the title. In XTerm it only changes the icon name
305 // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title
306 if (arg == 0 || arg == 2) emit changeTitle(arg,unistr);
307 delete [] str;
308}
309
310// Interpreting Codes ---------------------------------------------------------
311
312/*
313 Now that the incoming character stream is properly tokenized,
314 meaning is assigned to them. These are either operations of
315 the current screen, or of the emulation class itself.
316
317 The token to be interpreteted comes in as a machine word
318 possibly accompanied by two parameters.
319
320 Likewise, the operations assigned to, come with up to two
321 arguments. One could consider to make up a proper table
322 from the function below.
323
324 The technical reference manual provides more informations
325 about this mapping.
326*/
327
328void Vt102Emulation::tau( int token, int p, int q )
329{
330//scan_buffer_report();
331//if (token == TY_CHR___()) printf("%c",p); else
332//printf("tau(%d,%d,%d, %d,%d)\n",(token>>0)&0xff,(token>>8)&0xff,(token>>16)&0xffff,p,q);
333 switch (token)
334 {
335
336 case TY_CHR___( ) : scr->ShowCharacter (p ); break; //UTF16
337
338 // 127 DEL : ignored on input
339
340 case TY_CTL___('@' ) : /* NUL: ignored */ break;
341 case TY_CTL___('A' ) : /* SOH: ignored */ break;
342 case TY_CTL___('B' ) : /* STX: ignored */ break;
343 case TY_CTL___('C' ) : /* ETX: ignored */ break;
344 case TY_CTL___('D' ) : /* EOT: ignored */ break;
345 case TY_CTL___('E' ) : reportAnswerBack ( ); break; //VT100
346 case TY_CTL___('F' ) : /* ACK: ignored */ break;
347 case TY_CTL___('G' ) : gui->bell ( ); break; //VT100
348 case TY_CTL___('H' ) : scr->BackSpace ( ); break; //VT100
349 case TY_CTL___('I' ) : scr->Tabulate ( ); break; //VT100
350 case TY_CTL___('J' ) : scr->NewLine ( ); break; //VT100
351 case TY_CTL___('K' ) : scr->NewLine ( ); break; //VT100
352 case TY_CTL___('L' ) : scr->NewLine ( ); break; //VT100
353 case TY_CTL___('M' ) : scr->Return ( ); break; //VT100
354
355 case TY_CTL___('N' ) : useCharset ( 1); break; //VT100
356 case TY_CTL___('O' ) : useCharset ( 0); break; //VT100
357
358 case TY_CTL___('P' ) : /* DLE: ignored */ break;
359 case TY_CTL___('Q' ) : /* DC1: XON continue */ break; //VT100
360 case TY_CTL___('R' ) : /* DC2: ignored */ break;
361 case TY_CTL___('S' ) : /* DC3: XOFF halt */ break; //VT100
362 case TY_CTL___('T' ) : /* DC4: ignored */ break;
363 case TY_CTL___('U' ) : /* NAK: ignored */ break;
364 case TY_CTL___('V' ) : /* SYN: ignored */ break;
365 case TY_CTL___('W' ) : /* ETB: ignored */ break;
366 case TY_CTL___('X' ) : scr->ShowCharacter ( 0x2592); break; //VT100
367 case TY_CTL___('Y' ) : /* EM : ignored */ break;
368 case TY_CTL___('Z' ) : scr->ShowCharacter ( 0x2592); break; //VT100
369 case TY_CTL___('[' ) : /* ESC: cannot be seen here. */ break;
370 case TY_CTL___('\\' ) : /* FS : ignored */ break;
371 case TY_CTL___(']' ) : /* GS : ignored */ break;
372 case TY_CTL___('^' ) : /* RS : ignored */ break;
373 case TY_CTL___('_' ) : /* US : ignored */ break;
374
375 case TY_ESC___('D' ) : scr->index ( ); break; //VT100
376 case TY_ESC___('E' ) : scr->NextLine ( ); break; //VT100
377 case TY_ESC___('H' ) : scr->changeTabStop (TRUE ); break; //VT100
378 case TY_ESC___('M' ) : scr->reverseIndex ( ); break; //VT100
379 case TY_ESC___('Z' ) : reportTerminalType ( ); break;
380 case TY_ESC___('c' ) : reset ( ); break;
381
382 case TY_ESC___('n' ) : useCharset ( 2); break;
383 case TY_ESC___('o' ) : useCharset ( 3); break;
384 case TY_ESC___('7' ) : saveCursor ( ); break;
385 case TY_ESC___('8' ) : restoreCursor ( ); break;
386
387 case TY_ESC___('=' ) : setMode (MODE_AppKeyPad); break;
388 case TY_ESC___('>' ) : resetMode (MODE_AppKeyPad); break;
389 case TY_ESC___('<' ) : setMode (MODE_Ansi ); break; //VT100
390
391 case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100
392 case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100
393 case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100
394
395 case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100
396 case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100
397 case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100
398
399 case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100
400 case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100
401 case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100
402
403 case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100
404 case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100
405 case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100
406
407 case TY_ESC_CS('%', 'G') : setCodec (1 ); break; //LINUX
408 case TY_ESC_CS('%', '@') : setCodec (0 ); break; //LINUX
409
410 case TY_ESC_DE('3' ) : /* IGNORED: double high, top half */ break;
411 case TY_ESC_DE('4' ) : /* IGNORED: double high, bottom half */ break;
412 case TY_ESC_DE('5' ) : /* IGNORED: single width, single high*/ break;
413 case TY_ESC_DE('6' ) : /* IGNORED: double width, single high*/ break;
414 case TY_ESC_DE('8' ) : scr->helpAlign ( ); break;
415
416 case TY_CSI_PS('K', 0) : scr->clearToEndOfLine ( ); break;
417 case TY_CSI_PS('K', 1) : scr->clearToBeginOfLine ( ); break;
418 case TY_CSI_PS('K', 2) : scr->clearEntireLine ( ); break;
419 case TY_CSI_PS('J', 0) : scr->clearToEndOfScreen ( ); break;
420 case TY_CSI_PS('J', 1) : scr->clearToBeginOfScreen ( ); break;
421 case TY_CSI_PS('J', 2) : scr->clearEntireScreen ( ); break;
422 case TY_CSI_PS('g', 0) : scr->changeTabStop (FALSE ); break; //VT100
423 case TY_CSI_PS('g', 3) : scr->clearTabStops ( ); break; //VT100
424 case TY_CSI_PS('h', 4) : scr-> setMode (MODE_Insert ); break;
425 case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break;
426 case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100
427 case TY_CSI_PS('l', 4) : scr-> resetMode (MODE_Insert ); break;
428 case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break;
429
430 case TY_CSI_PS('m', 0) : scr->setDefaultRendition ( ); break;
431 case TY_CSI_PS('m', 1) : scr-> setRendition (RE_BOLD ); break; //VT100
432 case TY_CSI_PS('m', 4) : scr-> setRendition (RE_UNDERLINE); break; //VT100
433 case TY_CSI_PS('m', 5) : scr-> setRendition (RE_BLINK ); break; //VT100
434 case TY_CSI_PS('m', 7) : scr-> setRendition (RE_REVERSE ); break;
435 case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
436 case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
437 case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
438 case TY_CSI_PS('m', 22) : scr->resetRendition (RE_BOLD ); break;
439 case TY_CSI_PS('m', 24) : scr->resetRendition (RE_UNDERLINE); break;
440 case TY_CSI_PS('m', 25) : scr->resetRendition (RE_BLINK ); break;
441 case TY_CSI_PS('m', 27) : scr->resetRendition (RE_REVERSE ); break;
442
443 case TY_CSI_PS('m', 30) : scr->setForeColor ( 0); break;
444 case TY_CSI_PS('m', 31) : scr->setForeColor ( 1); break;
445 case TY_CSI_PS('m', 32) : scr->setForeColor ( 2); break;
446 case TY_CSI_PS('m', 33) : scr->setForeColor ( 3); break;
447 case TY_CSI_PS('m', 34) : scr->setForeColor ( 4); break;
448 case TY_CSI_PS('m', 35) : scr->setForeColor ( 5); break;
449 case TY_CSI_PS('m', 36) : scr->setForeColor ( 6); break;
450 case TY_CSI_PS('m', 37) : scr->setForeColor ( 7); break;
451 case TY_CSI_PS('m', 39) : scr->setForeColorToDefault( ); break;
452
453 case TY_CSI_PS('m', 40) : scr->setBackColor ( 0); break;
454 case TY_CSI_PS('m', 41) : scr->setBackColor ( 1); break;
455 case TY_CSI_PS('m', 42) : scr->setBackColor ( 2); break;
456 case TY_CSI_PS('m', 43) : scr->setBackColor ( 3); break;
457 case TY_CSI_PS('m', 44) : scr->setBackColor ( 4); break;
458 case TY_CSI_PS('m', 45) : scr->setBackColor ( 5); break;
459 case TY_CSI_PS('m', 46) : scr->setBackColor ( 6); break;
460 case TY_CSI_PS('m', 47) : scr->setBackColor ( 7); break;
461 case TY_CSI_PS('m', 49) : scr->setBackColorToDefault( ); break;
462
463 case TY_CSI_PS('m', 90) : scr->setForeColor ( 8); break;
464 case TY_CSI_PS('m', 91) : scr->setForeColor ( 9); break;
465 case TY_CSI_PS('m', 92) : scr->setForeColor ( 10); break;
466 case TY_CSI_PS('m', 93) : scr->setForeColor ( 11); break;
467 case TY_CSI_PS('m', 94) : scr->setForeColor ( 12); break;
468 case TY_CSI_PS('m', 95) : scr->setForeColor ( 13); break;
469 case TY_CSI_PS('m', 96) : scr->setForeColor ( 14); break;
470 case TY_CSI_PS('m', 97) : scr->setForeColor ( 15); break;
471
472 case TY_CSI_PS('m', 100) : scr->setBackColor ( 8); break;
473 case TY_CSI_PS('m', 101) : scr->setBackColor ( 9); break;
474 case TY_CSI_PS('m', 102) : scr->setBackColor ( 10); break;
475 case TY_CSI_PS('m', 103) : scr->setBackColor ( 11); break;
476 case TY_CSI_PS('m', 104) : scr->setBackColor ( 12); break;
477 case TY_CSI_PS('m', 105) : scr->setBackColor ( 13); break;
478 case TY_CSI_PS('m', 106) : scr->setBackColor ( 14); break;
479 case TY_CSI_PS('m', 107) : scr->setBackColor ( 15); break;
480
481 case TY_CSI_PS('n', 5) : reportStatus ( ); break;
482 case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break;
483 case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100
484 case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100
485 case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100
486 case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100
487 case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100
488 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
489 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
490
491 case TY_CSI_PN('@' ) : scr->insertChars (p ); break;
492 case TY_CSI_PN('A' ) : scr->cursorUp (p ); break; //VT100
493 case TY_CSI_PN('B' ) : scr->cursorDown (p ); break; //VT100
494 case TY_CSI_PN('C' ) : scr->cursorRight (p ); break; //VT100
495 case TY_CSI_PN('D' ) : scr->cursorLeft (p ); break; //VT100
496 case TY_CSI_PN('G' ) : scr->setCursorX (p ); break; //LINUX
497 case TY_CSI_PN('H' ) : scr->setCursorYX (p, q); break; //VT100
498 case TY_CSI_PN('L' ) : scr->insertLines (p ); break;
499 case TY_CSI_PN('M' ) : scr->deleteLines (p ); break;
500 case TY_CSI_PN('P' ) : scr->deleteChars (p ); break;
501 case TY_CSI_PN('X' ) : scr->eraseChars (p ); break;
502 case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
503 case TY_CSI_PN('d' ) : scr->setCursorY (p ); break; //LINUX
504 case TY_CSI_PN('f' ) : scr->setCursorYX (p, q); break; //VT100
505 case TY_CSI_PN('r' ) : scr->setMargins (p, q); break; //VT100
506 case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100
507
508 case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100
509 case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100
510 case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME
511 case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME
512
513 case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100
514
515 case TY_CSI_PR('h', 3) : setColumns ( 132); break; //VT100
516 case TY_CSI_PR('l', 3) : setColumns ( 80); break; //VT100
517
518 case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100
519 case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100
520
521 case TY_CSI_PR('h', 5) : scr-> setMode (MODE_Screen ); break; //VT100
522 case TY_CSI_PR('l', 5) : scr-> resetMode (MODE_Screen ); break; //VT100
523
524 case TY_CSI_PR('h', 6) : scr-> setMode (MODE_Origin ); break; //VT100
525 case TY_CSI_PR('l', 6) : scr-> resetMode (MODE_Origin ); break; //VT100
526 case TY_CSI_PR('s', 6) : scr-> saveMode (MODE_Origin ); break; //FIXME
527 case TY_CSI_PR('r', 6) : scr->restoreMode (MODE_Origin ); break; //FIXME
528
529 case TY_CSI_PR('h', 7) : scr-> setMode (MODE_Wrap ); break; //VT100
530 case TY_CSI_PR('l', 7) : scr-> resetMode (MODE_Wrap ); break; //VT100
531 case TY_CSI_PR('s', 7) : scr-> saveMode (MODE_Wrap ); break; //FIXME
532 case TY_CSI_PR('r', 7) : scr->restoreMode (MODE_Wrap ); break; //FIXME
533
534 case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100
535 case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100
536
537 case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100
538 case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100
539
540 case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100
541 case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100
542
543 case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
544 case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
545 case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
546 case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
547
548 case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100
549 case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100
550
551 case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM
552 case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM
553 case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM
554 case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM
555
556 case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
557 case TY_CSI_PR('l', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
558 case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
559 case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
560
561 case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM
562 case TY_CSI_PR('l', 1047) : resetMode (MODE_AppScreen); break; //XTERM
563
564 //FIXME: Unitoken: save translations
565 case TY_CSI_PR('h', 1048) : saveCursor ( ); break; //XTERM
566 case TY_CSI_PR('l', 1048) : restoreCursor ( ); break; //XTERM
567
568 //FIXME: every once new sequences like this pop up in xterm.
569 // Here's a guess of what they could mean.
570 case TY_CSI_PR('h', 1049) : setMode (MODE_AppScreen); break; //XTERM
571 case TY_CSI_PR('l', 1049) : resetMode (MODE_AppScreen); break; //XTERM
572
573 //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
574 case TY_VT52__('A' ) : scr->cursorUp ( 1); break; //VT52
575 case TY_VT52__('B' ) : scr->cursorDown ( 1); break; //VT52
576 case TY_VT52__('C' ) : scr->cursorRight ( 1); break; //VT52
577 case TY_VT52__('D' ) : scr->cursorLeft ( 1); break; //VT52
578
579 case TY_VT52__('F' ) : setAndUseCharset (0, '0'); break; //VT52
580 case TY_VT52__('G' ) : setAndUseCharset (0, 'B'); break; //VT52
581
582 case TY_VT52__('H' ) : scr->setCursorYX (1,1 ); break; //VT52
583 case TY_VT52__('I' ) : scr->reverseIndex ( ); break; //VT52
584 case TY_VT52__('J' ) : scr->clearToEndOfScreen ( ); break; //VT52
585 case TY_VT52__('K' ) : scr->clearToEndOfLine ( ); break; //VT52
586 case TY_VT52__('Y' ) : scr->setCursorYX (p-31,q-31 ); break; //VT52
587 case TY_VT52__('Z' ) : reportTerminalType ( ); break; //VT52
588 case TY_VT52__('<' ) : setMode (MODE_Ansi ); break; //VT52
589 case TY_VT52__('=' ) : setMode (MODE_AppKeyPad); break; //VT52
590 case TY_VT52__('>' ) : resetMode (MODE_AppKeyPad); break; //VT52
591
592 default : ReportErrorToken(); break;
593 };
594}
595
596/* ------------------------------------------------------------------------- */
597/* */
598/* Terminal to Host protocol */
599/* */
600/* ------------------------------------------------------------------------- */
601
602/*
603 Outgoing bytes originate from several sources:
604
605 - Replies to Enquieries.
606 - Mouse Events
607 - Keyboard Events
608*/
609
610/*!
611*/
612
613void Vt102Emulation::sendString(const char* s)
614{
615 QByteArray tmp;
616 tmp.setRawData( s, strlen( s ));
617 emit sndBlock( tmp);
618}
619
620void Vt102Emulation::sendString(const QByteArray& s)
621{
622 emit sndBlock( s );
623}
624
625// Replies ----------------------------------------------------------------- --
626
627// This section copes with replies send as response to an enquiery control code.
628
629/*!
630*/
631
632void Vt102Emulation::reportCursorPosition()
633{ char tmp[20];
634 sprintf(tmp,"\033[%d;%dR",scr->getCursorY()+1,scr->getCursorX()+1);
635 sendString(tmp);
636}
637
638/*
639 What follows here is rather obsolete and faked stuff.
640 The correspondent enquieries are neverthenless issued.
641*/
642
643/*!
644*/
645
646void Vt102Emulation::reportTerminalType()
647{
648//FIXME: should change?
649 if (getMode(MODE_Ansi))
650// sendString("\033[?1;2c"); // I'm a VT100 with AP0 //FIXME: send only in response to ^[[0c
651 sendString("\033[>0;115;0c"); // I'm a VT220 //FIXME: send only in response to ^[[>c
652 else
653 sendString("\033/Z"); // I'm a VT52
654}
655
656void Vt102Emulation::reportTerminalParms(int p)
657// DECREPTPARM
658{ char tmp[100];
659 sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
660 sendString(tmp);
661}
662
663/*!
664*/
665
666void Vt102Emulation::reportStatus()
667{
668 sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
669}
670
671/*!
672*/
673
674#define ANSWER_BACK "" // This is really obsolete VT100 stuff.
675
676void Vt102Emulation::reportAnswerBack()
677{
678 sendString(ANSWER_BACK);
679}
680
681// Mouse Handling ---------------------------------------------------------- --
682
683/*!
684 Mouse clicks are possibly reported to the client
685 application if it has issued interest in them.
686 They are normally consumed by the widget for copy
687 and paste, but may be propagated from the widget
688 when gui->setMouseMarks is set via setMode(MODE_Mouse1000).
689
690 `x',`y' are 1-based.
691 `ev' (event) indicates the button pressed (0-2)
692 or a general mouse release (3).
693*/
694
695void Vt102Emulation::onMouse( int cb, int cx, int cy )
696{ char tmp[20];
697 if (!connected) return;
698 sprintf(tmp,"\033[M%c%c%c",cb+040,cx+040,cy+040);
699 sendString(tmp);
700}
701
702// Keyboard Handling ------------------------------------------------------- --
703
704#define encodeMode(M,B) BITS(B,getMode(M))
705#define encodeStat(M,B) BITS(B,((ev->state() & (M)) == (M)))
706
707/*
708 Keyboard event handling has been simplified somewhat by pushing
709 the complications towards a configuration file [see KeyTrans class].
710*/
711
712void Vt102Emulation::onKeyPress( QKeyEvent* ev )
713{
714 if (!connected) return; // someone else gets the keys
715
716//printf("State/Key: 0x%04x 0x%04x (%d,%d)\n",ev->state(),ev->key(),ev->text().length(),ev->text().length()?ev->text().ascii()[0]:0);
717
718 // revert to non-history when typing
719 if (scr->getHistCursor() != scr->getHistLines());
720 scr->setHistCursor(scr->getHistLines());
721
722 // lookup in keyboard translation table ...
723 int cmd; const char* txt; int len;
724 if (keytrans->findEntry(ev->key(), encodeMode(MODE_NewLine , BITS_NewLine ) + // OLD,
725 encodeMode(MODE_Ansi , BITS_Ansi ) + // OBSOLETE,
726 encodeMode(MODE_AppCuKeys, BITS_AppCuKeys ) + // VT100 stuff
727 encodeStat(ControlButton , BITS_Control ) +
728 encodeStat(ShiftButton , BITS_Shift ) +
729 encodeStat(AltButton , BITS_Alt ),
730 &cmd, &txt, &len ))
731//printf("cmd: %d, %s, %d\n",cmd,txt,len);
732 {
733 switch(cmd) // ... and execute if found.
734 {
735 case CMD_emitSelection : gui->insertSelection(); return;
736 case CMD_scrollPageUp : gui->scroll(-gui->lines()/2); return;
737 case CMD_scrollPageDown : gui->scroll(+gui->lines()/2); return;
738 case CMD_scrollLineUp : gui->scroll(-1 ); return;
739 case CMD_scrollLineDown : gui->scroll(+1 ); return;
740 case CMD_send : sendString( txt ); return;
741 case CMD_prevSession : emit prevSession(); return;
742 case CMD_nextSession : emit nextSession(); return;
743 }
744 }
745 // fall back handling
746 if (!ev->text().isEmpty())
747 {
748 if (ev->state() & AltButton) sendString("\033"); // ESC, this is the ALT prefix
749 /// very hacky
750 if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='A')) sendString("\01");
751 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='B')) sendString("\02");
752 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='C')) sendString("\03");
753 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='D')) sendString("\04");
754 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='E')) sendString("\05");
755 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='F')) sendString("\06");
756 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='G')) sendString("\07");
757 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='H')) sendString("\010");
758 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='I')) sendString("\011");
759 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='J')) sendString("\012");
760 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='K')) sendString("\013");
761 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='L')) sendString("\014");
762 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='M')) sendString("\015");
763 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='N')) sendString("\016");
764 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='O')) sendString("\017");
765 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='P')) sendString("\020");
766 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Q')) sendString("\021");
767 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='R')) sendString("\022");
768 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='S')) sendString("\023");
769 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='T')) sendString("\024");
770 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='U')) sendString("\025");
771 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='V')) sendString("\026");
772 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='W')) sendString("\027");
773 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='X')) sendString("\030");
774 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Y')) sendString("\031");
775 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Z')) sendString("\032");
776 else
777 {
778 QCString s = codec->fromUnicode(ev->text()); // encode for application
779 sendString( s ); // we may well have s.length() > 1
780 }
781 return;
782 }
783}
784
785/* ------------------------------------------------------------------------- */
786/* */
787/* VT100 Charsets */
788/* */
789/* ------------------------------------------------------------------------- */
790
791// Character Set Conversion ------------------------------------------------ --
792
793/*
794 The processing contains a VT100 specific code translation layer.
795 It's still in use and mainly responsible for the line drawing graphics.
796
797 These and some other glyphs are assigned to codes (0x5f-0xfe)
798 normally occupied by the latin letters. Since this codes also
799 appear within control sequences, the extra code conversion
800 does not permute with the tokenizer and is placed behind it
801 in the pipeline. It only applies to tokens, which represent
802 plain characters.
803
804 This conversion it eventually continued in TEWidget.C, since
805 it might involve VT100 enhanced fonts, which have these
806 particular glyphs allocated in (0x00-0x1f) in their code page.
807*/
808
809#define CHARSET charset[scr==screen[1]]
810
811// Apply current character map.
812
813unsigned short Vt102Emulation::applyCharset(unsigned short c)
814{
815 if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
816 if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
817 return c;
818}
819
820/*
821 "Charset" related part of the emulation state.
822 This configures the VT100 charset filter.
823
824 While most operation work on the current screen,
825 the following two are different.
826*/
827
828void Vt102Emulation::resetCharset(int scrno)
829{
830 charset[scrno].cu_cs = 0;
831 strncpy(charset[scrno].charset,"BBBB",4);
832 charset[scrno].sa_graphic = FALSE;
833 charset[scrno].sa_pound = FALSE;
834 charset[scrno].graphic = FALSE;
835 charset[scrno].pound = FALSE;
836}
837
838/*!
839*/
840
841void Vt102Emulation::setCharset(int n, int cs) // on both screens.
842{
843 charset[0].charset[n&3] = cs; useCharset(charset[0].cu_cs);
844 charset[1].charset[n&3] = cs; useCharset(charset[1].cu_cs);
845}
846
847/*!
848*/
849
850void Vt102Emulation::setAndUseCharset(int n, int cs)
851{
852 CHARSET.charset[n&3] = cs;
853 useCharset(n&3);
854}
855
856/*!
857*/
858
859void Vt102Emulation::useCharset(int n)
860{
861 CHARSET.cu_cs = n&3;
862 CHARSET.graphic = (CHARSET.charset[n&3] == '0');
863 CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
864}
865
866/*! Save the cursor position and the rendition attribute settings. */
867
868void Vt102Emulation::saveCursor()
869{
870 CHARSET.sa_graphic = CHARSET.graphic;
871 CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
872 // we are not clear about these
873 //sa_charset = charsets[cScreen->charset];
874 //sa_charset_num = cScreen->charset;
875 scr->saveCursor();
876}
877
878/*! Restore the cursor position and the rendition attribute settings. */
879
880void Vt102Emulation::restoreCursor()
881{
882 CHARSET.graphic = CHARSET.sa_graphic;
883 CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
884 scr->restoreCursor();
885}
886
887/* ------------------------------------------------------------------------- */
888/* */
889/* Mode Operations */
890/* */
891/* ------------------------------------------------------------------------- */
892
893/*
894 Some of the emulations state is either added to the state of the screens.
895
896 This causes some scoping problems, since different emulations choose to
897 located the mode either to the current screen or to both.
898
899 For strange reasons, the extend of the rendition attributes ranges over
900 all screens and not over the actual screen.
901
902 We decided on the precise precise extend, somehow.
903*/
904
905// "Mode" related part of the state. These are all booleans.
906
907void Vt102Emulation::resetModes()
908{
909 resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
910 resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
911 // here come obsolete modes
912 resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
913 resetMode(MODE_NewLine );
914 setMode(MODE_Ansi );
915}
916
917void Vt102Emulation::setMode(int m)
918{
919 currParm.mode[m] = TRUE;
920 switch (m)
921 {
922 case MODE_Mouse1000 : //gui->setMouseMarks(FALSE);
923 break;
924 case MODE_AppScreen : screen[1]->clearSelection();
925 screen[1]->clearEntireScreen();
926 setScreen(1);
927 break;
928 }
929 if (m < MODES_SCREEN || m == MODE_NewLine)
930 {
931 screen[0]->setMode(m);
932 screen[1]->setMode(m);
933 }
934}
935
936void Vt102Emulation::resetMode(int m)
937{
938 currParm.mode[m] = FALSE;
939 switch (m)
940 {
941 case MODE_Mouse1000 : //gui->setMouseMarks(TRUE);
942 break;
943 case MODE_AppScreen : screen[0]->clearSelection();
944 setScreen(0);
945 break;
946 }
947 if (m < MODES_SCREEN || m == MODE_NewLine)
948 {
949 screen[0]->resetMode(m);
950 screen[1]->resetMode(m);
951 }
952}
953
954void Vt102Emulation::saveMode(int m)
955{
956 saveParm.mode[m] = currParm.mode[m];
957}
958
959void Vt102Emulation::restoreMode(int m)
960{
961 if(saveParm.mode[m]) setMode(m); else resetMode(m);
962}
963
964BOOL Vt102Emulation::getMode(int m)
965{
966 return currParm.mode[m];
967}
968
969void Vt102Emulation::setConnect(bool c)
970{
971 EmulationLayer::setConnect(c);
972 if (c)
973 { // refresh mouse mode
974 if (getMode(MODE_Mouse1000))
975 setMode(MODE_Mouse1000);
976 else
977 resetMode(MODE_Mouse1000);
978 }
979}
980
981/* ------------------------------------------------------------------------- */
982/* */
983/* Diagnostic */
984/* */
985/* ------------------------------------------------------------------------- */
986
987/*! shows the contents of the scan buffer.
988
989 This functions is used for diagnostics. It is called by \e ReportErrorToken
990 to inform about strings that cannot be decoded or handled by the emulation.
991
992 \sa ReportErrorToken
993*/
994
995/*!
996*/
997
998static void hexdump(int* s, int len)
999{ int i;
1000 for (i = 0; i < len; i++)
1001 {
1002 if (s[i] == '\\')
1003 printf("\\\\");
1004 else
1005 if ((s[i]) > 32 && s[i] < 127)
1006 printf("%c",s[i]);
1007 else
1008 printf("\\%04x(hex)",s[i]);
1009 }
1010}
1011
1012void Vt102Emulation::scan_buffer_report()
1013{
1014 if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
1015 printf("token: "); hexdump(pbuf,ppos); printf("\n");
1016}
1017
1018/*!
1019*/
1020
1021void Vt102Emulation::ReportErrorToken()
1022{
1023 printf("undecodable "); scan_buffer_report();
1024}