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