summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-console
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
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') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/emulation_layer.cpp372
-rw-r--r--noncore/apps/opie-console/emulation_layer.cpp~373
-rw-r--r--noncore/apps/opie-console/emulation_layer.h146
-rw-r--r--noncore/apps/opie-console/emulation_layer.obin0 -> 13224 bytes
-rw-r--r--noncore/apps/opie-console/history.cpp218
-rw-r--r--noncore/apps/opie-console/history.h82
-rw-r--r--noncore/apps/opie-console/history.obin0 -> 6468 bytes
-rw-r--r--noncore/apps/opie-console/keytrans.cpp706
-rw-r--r--noncore/apps/opie-console/keytrans.h93
-rw-r--r--noncore/apps/opie-console/keytrans.obin0 -> 34264 bytes
-rw-r--r--noncore/apps/opie-console/screen.cpp1197
-rw-r--r--noncore/apps/opie-console/screen.h259
-rw-r--r--noncore/apps/opie-console/screen.obin0 -> 15864 bytes
-rw-r--r--noncore/apps/opie-console/vt102emulation.cpp1029
-rw-r--r--noncore/apps/opie-console/vt102emulation.h153
-rw-r--r--noncore/apps/opie-console/vt102emulation.obin0 -> 33320 bytes
16 files changed, 4628 insertions, 0 deletions
diff --git a/noncore/apps/opie-console/emulation_layer.cpp b/noncore/apps/opie-console/emulation_layer.cpp
new file mode 100644
index 0000000..6c420e0
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.cpp
@@ -0,0 +1,372 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [emulation_layer.cpp] Terminal Emulation Decoder */
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/* Modified to suit opie-console */
20 /* */
21/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
22 /* */
23/* -------------------------------------------------------------------------- */
24
25/*! \class EmulationLayer
26
27 \brief Mediator between Widget and Screen.
28
29 This class is responsible to scan the escapes sequences of the terminal
30 emulation and to map it to their corresponding semantic complements.
31 Thus this module knows mainly about decoding escapes sequences and
32 is a stateless device w.r.t. the semantics.
33
34 It is also responsible to refresh the Widget by certain rules.
35
36 \sa Widget \sa Screen
37
38 \par A note on refreshing
39
40 Although the modifications to the current screen image could immediately
41 be propagated via `Widget' to the graphical surface, we have chosen
42 another way here.
43
44 The reason for doing so is twofold.
45
46 First, experiments show that directly displaying the operation results
47 in slowing down the overall performance of emulations. Displaying
48 individual characters using X11 creates a lot of overhead.
49
50 Second, by using the following refreshing method, the screen operations
51 can be completely separated from the displaying. This greatly simplifies
52 the programmer's task of coding and maintaining the screen operations,
53 since one need not worry about differential modifications on the
54 display affecting the operation of concern.
55
56 We use a refreshing algorithm here that has been adoped from rxvt/kvt.
57
58 By this, refreshing is driven by a timer, which is (re)started whenever
59 a new bunch of data to be interpreted by the emulation arives at `onRcvBlock'.
60 As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger
61 refresh. This rule suits both bulk display operation as done by curses as
62 well as individual characters typed.
63 (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
64
65 Additionally, we trigger refreshing by newlines comming in to make visual
66 snapshots of lists as produced by `cat', `ls' and likely programs, thereby
67 producing the illusion of a permanent and immediate display operation.
68
69 As a sort of catch-all needed for cases where none of the above
70 conditions catch, the screen refresh is also triggered by a count
71 of incoming bulks (`bulk_incnt').
72*/
73
74/* FIXME
75 - evtl. the bulk operations could be made more transparent.
76*/
77
78#include "emulation_layer.h"
79#include "widget.h"
80#include "screen.h"
81#include <stdio.h>
82#include <stdlib.h>
83#include <unistd.h>
84#include <qkeycode.h>
85
86
87/* ------------------------------------------------------------------------- */
88/* */
89/* EmulationLayer */
90/* */
91/* ------------------------------------------------------------------------- */
92
93#define CNTL(c) ((c)-'@')
94
95/*!
96*/
97
98EmulationLayer::EmulationLayer(Widget* gui)
99: decoder((QTextDecoder*)NULL)
100{
101 this->gui = gui;
102
103 screen[0] = new Screen(gui->Lines(),gui->Columns());
104 screen[1] = new Screen(gui->Lines(),gui->Columns());
105 scr = screen[0];
106
107 bulk_nlcnt = 0; // reset bulk newline counter
108 bulk_incnt = 0; // reset bulk counter
109 connected = FALSE;
110
111 QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
112 QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)),
113 this,SLOT(onImageSizeChange(int,int)));
114 QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
115 this,SLOT(onHistoryCursorChange(int)));
116 QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
117 this,SLOT(onKeyPress(QKeyEvent*)));
118 QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)),
119 this,SLOT(onSelectionBegin(const int,const int)) );
120 QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
121 this,SLOT(onSelectionExtend(const int,const int)) );
122 QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)),
123 this,SLOT(setSelection(const BOOL)) );
124 QObject::connect(gui,SIGNAL(clearSelectionSignal()),
125 this,SLOT(clearSelection()) );
126}
127
128/*!
129*/
130
131EmulationLayer::~EmulationLayer()
132{
133 delete screen[0];
134 delete screen[1];
135 bulk_timer.stop();
136}
137
138/*! change between primary and alternate screen
139*/
140
141void EmulationLayer::setScreen(int n)
142{
143 scr = screen[n&1];
144}
145
146void EmulationLayer::setHistory(bool on)
147{
148 screen[0]->setScroll(on);
149 if (!connected) return;
150 showBulk();
151}
152
153bool EmulationLayer::history()
154{
155 return screen[0]->hasScroll();
156}
157
158void EmulationLayer::setCodec(int c)
159{
160 //FIXME: check whether we have to free codec
161 codec = c ? QTextCodec::codecForName("utf8")
162 : QTextCodec::codecForLocale();
163 if (decoder) delete decoder;
164 decoder = codec->makeDecoder();
165}
166
167void EmulationLayer::setKeytrans(int no)
168{
169 keytrans = KeyTrans::find(no);
170}
171
172void EmulationLayer::setKeytrans(const char * no)
173{
174 keytrans = KeyTrans::find(no);
175}
176
177// Interpreting Codes ---------------------------------------------------------
178
179/*
180 This section deals with decoding the incoming character stream.
181 Decoding means here, that the stream is first seperated into `tokens'
182 which are then mapped to a `meaning' provided as operations by the
183 `Screen' class.
184*/
185
186/*!
187*/
188
189void EmulationLayer::onRcvChar(int c)
190// process application unicode input to terminal
191// this is a trivial scanner
192{
193 c &= 0xff;
194 switch (c)
195 {
196 case '\b' : scr->BackSpace(); break;
197 case '\t' : scr->Tabulate(); break;
198 case '\n' : scr->NewLine(); break;
199 case '\r' : scr->Return(); break;
200 case 0x07 : gui->Bell(); break;
201 default : scr->ShowCharacter(c); break;
202 };
203}
204
205/* ------------------------------------------------------------------------- */
206/* */
207/* Keyboard Handling */
208/* */
209/* ------------------------------------------------------------------------- */
210
211/*!
212*/
213
214void EmulationLayer::onKeyPress( QKeyEvent* ev )
215{
216 if (!connected) return; // someone else gets the keys
217 if (scr->getHistCursor() != scr->getHistLines());
218 scr->setHistCursor(scr->getHistLines());
219 if (!ev->text().isEmpty())
220 { // A block of text
221 // Note that the text is proper unicode.
222 // We should do a conversion here, but since this
223 // routine will never be used, we simply emit plain ascii.
224 sendString( ev->text().ascii() ); //,ev->text().length());
225 }
226 else if (ev->ascii()>0)
227 {
228 QByteArray c = QByteArray( 1 );
229 c.at( 0 ) = ev->ascii();
230 // ibot: qbytearray is emited not char*
231 emit sndBlock( (QByteArray) c );
232 }
233}
234
235// Unblocking, Byte to Unicode translation --------------------------------- --
236
237/*
238 We are doing code conversion from locale to unicode first.
239*/
240
241void EmulationLayer::onRcvBlock(const QByteArray &s )
242{
243 bulkStart();
244 bulk_incnt += 1;
245 for (int i = 0; i < s.size(); i++)
246 {
247 //TODO: ibot: maybe decoding qbytearray to unicode in io_layer?
248 QString result = decoder->toUnicode(&s[i],1);
249 int reslen = result.length();
250 for (int j = 0; j < reslen; j++)
251 onRcvChar(result[j].unicode());
252 if (s[i] == '\n') bulkNewline();
253 }
254 bulkEnd();
255}
256
257// Selection --------------------------------------------------------------- --
258
259void EmulationLayer::onSelectionBegin(const int x, const int y) {
260 if (!connected) return;
261 scr->setSelBeginXY(x,y);
262 showBulk();
263}
264
265void EmulationLayer::onSelectionExtend(const int x, const int y) {
266 if (!connected) return;
267 scr->setSelExtentXY(x,y);
268 showBulk();
269}
270
271void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
272 if (!connected) return;
273 QString t = scr->getSelText(preserve_line_breaks);
274 if (!t.isNull()) gui->setSelection(t);
275}
276
277void EmulationLayer::clearSelection() {
278 if (!connected) return;
279 scr->clearSelection();
280 showBulk();
281}
282
283// Refreshing -------------------------------------------------------------- --
284
285#define BULK_TIMEOUT 20
286
287/*!
288 called when \n comes in. Evtl. triggers showBulk at endBulk
289*/
290
291void EmulationLayer::bulkNewline()
292{
293 bulk_nlcnt += 1;
294 bulk_incnt = 0; // reset bulk counter since `nl' rule applies
295}
296
297/*!
298*/
299
300void EmulationLayer::showBulk()
301{
302 bulk_nlcnt = 0; // reset bulk newline counter
303 bulk_incnt = 0; // reset bulk counter
304 if (connected)
305 {
306 Character* image = scr->getCookedImage(); // get the image
307 gui->setImage(image,
308 scr->getLines(),
309 scr->getColumns()); // actual refresh
310 free(image);
311 //FIXME: check that we do not trigger other draw event here.
312 gui->setScroll(scr->getHistCursor(),scr->getHistLines());
313 }
314}
315
316void EmulationLayer::bulkStart()
317{
318 if (bulk_timer.isActive()) bulk_timer.stop();
319}
320
321void EmulationLayer::bulkEnd()
322{
323 if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
324 showBulk(); // resets bulk_??cnt to 0, too.
325 else
326 bulk_timer.start(BULK_TIMEOUT,TRUE);
327}
328
329void EmulationLayer::setConnect(bool c)
330{
331 connected = c;
332 if ( connected)
333 {
334 onImageSizeChange(gui->Lines(), gui->Columns());
335 showBulk();
336 }
337 else
338 {
339 scr->clearSelection();
340 }
341}
342
343// ---------------------------------------------------------------------------
344
345/*! triggered by image size change of the Widget `gui'.
346
347 This event is simply propagated to the attached screens
348 and to the related serial line.
349*/
350
351void EmulationLayer::onImageSizeChange(int lines, int columns)
352{
353 if (!connected) return;
354 screen[0]->resizeImage(lines,columns);
355 screen[1]->resizeImage(lines,columns);
356 showBulk();
357 emit ImageSizeChanged(lines,columns); // propagate event to serial line
358}
359
360void EmulationLayer::onHistoryCursorChange(int cursor)
361{
362 if (!connected) return;
363 scr->setHistCursor(cursor);
364 showBulk();
365}
366
367void EmulationLayer::setColumns(int columns)
368{
369 //FIXME: this goes strange ways.
370 // Can we put this straight or explain it at least?
371 emit changeColumns(columns);
372}
diff --git a/noncore/apps/opie-console/emulation_layer.cpp~ b/noncore/apps/opie-console/emulation_layer.cpp~
new file mode 100644
index 0000000..e65fd4b
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.cpp~
@@ -0,0 +1,373 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEmulation.cpp] Terminal Emulation Decoder */
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 /* */
20/* Modified to suit opie-console */
21 /* */
22/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
23 /* */
24/* ------------------------------------------------------------------------- */
25
26/*! \class TEmulation
27
28 \brief Mediator between TEWidget and TEScreen.
29
30 This class is responsible to scan the escapes sequences of the terminal
31 emulation and to map it to their corresponding semantic complements.
32 Thus this module knows mainly about decoding escapes sequences and
33 is a stateless device w.r.t. the semantics.
34
35 It is also responsible to refresh the TEWidget by certain rules.
36
37 \sa TEWidget \sa TEScreen
38
39 \par A note on refreshing
40
41 Although the modifications to the current screen image could immediately
42 be propagated via `TEWidget' to the graphical surface, we have chosen
43 another way here.
44
45 The reason for doing so is twofold.
46
47 First, experiments show that directly displaying the operation results
48 in slowing down the overall performance of emulations. Displaying
49 individual characters using X11 creates a lot of overhead.
50
51 Second, by using the following refreshing method, the screen operations
52 can be completely separated from the displaying. This greatly simplifies
53 the programmer's task of coding and maintaining the screen operations,
54 since one need not worry about differential modifications on the
55 display affecting the operation of concern.
56
57 We use a refreshing algorithm here that has been adoped from rxvt/kvt.
58
59 By this, refreshing is driven by a timer, which is (re)started whenever
60 a new bunch of data to be interpreted by the emulation arives at `onRcvBlock'.
61 As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger
62 refresh. This rule suits both bulk display operation as done by curses as
63 well as individual characters typed.
64 (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
65
66 Additionally, we trigger refreshing by newlines comming in to make visual
67 snapshots of lists as produced by `cat', `ls' and likely programs, thereby
68 producing the illusion of a permanent and immediate display operation.
69
70 As a sort of catch-all needed for cases where none of the above
71 conditions catch, the screen refresh is also triggered by a count
72 of incoming bulks (`bulk_incnt').
73*/
74
75/* FIXME
76 - evtl. the bulk operations could be made more transparent.
77*/
78
79#include "emulation_layer.h"
80#include "widget.h"
81#include "TEScreen.h"
82#include <stdio.h>
83#include <stdlib.h>
84#include <unistd.h>
85#include <qkeycode.h>
86
87
88/* ------------------------------------------------------------------------- */
89/* */
90/* EmulationLayer */
91/* */
92/* ------------------------------------------------------------------------- */
93
94#define CNTL(c) ((c)-'@')
95
96/*!
97*/
98
99EmulationLayer::EmulationLayer(TEWidget* gui)
100: decoder((QTextDecoder*)NULL)
101{
102 this->gui = gui;
103
104 screen[0] = new TEScreen(gui->Lines(),gui->Columns());
105 screen[1] = new TEScreen(gui->Lines(),gui->Columns());
106 scr = screen[0];
107
108 bulk_nlcnt = 0; // reset bulk newline counter
109 bulk_incnt = 0; // reset bulk counter
110 connected = FALSE;
111
112 QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
113 QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)),
114 this,SLOT(onImageSizeChange(int,int)));
115 QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
116 this,SLOT(onHistoryCursorChange(int)));
117 QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
118 this,SLOT(onKeyPress(QKeyEvent*)));
119 QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)),
120 this,SLOT(onSelectionBegin(const int,const int)) );
121 QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
122 this,SLOT(onSelectionExtend(const int,const int)) );
123 QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)),
124 this,SLOT(setSelection(const BOOL)) );
125 QObject::connect(gui,SIGNAL(clearSelectionSignal()),
126 this,SLOT(clearSelection()) );
127}
128
129/*!
130*/
131
132EmulationLayer::~EmulationLayer()
133{
134 delete screen[0];
135 delete screen[1];
136 bulk_timer.stop();
137}
138
139/*! change between primary and alternate screen
140*/
141
142void EmulationLayer::setScreen(int n)
143{
144 scr = screen[n&1];
145}
146
147void EmulationLayer::setHistory(bool on)
148{
149 screen[0]->setScroll(on);
150 if (!connected) return;
151 showBulk();
152}
153
154bool EmulationLayer::history()
155{
156 return screen[0]->hasScroll();
157}
158
159void EmulationLayer::setCodec(int c)
160{
161 //FIXME: check whether we have to free codec
162 codec = c ? QTextCodec::codecForName("utf8")
163 : QTextCodec::codecForLocale();
164 if (decoder) delete decoder;
165 decoder = codec->makeDecoder();
166}
167
168void EmulationLayer::setKeytrans(int no)
169{
170 keytrans = KeyTrans::find(no);
171}
172
173void EmulationLayer::setKeytrans(const char * no)
174{
175 keytrans = KeyTrans::find(no);
176}
177
178// Interpreting Codes ---------------------------------------------------------
179
180/*
181 This section deals with decoding the incoming character stream.
182 Decoding means here, that the stream is first seperated into `tokens'
183 which are then mapped to a `meaning' provided as operations by the
184 `Screen' class.
185*/
186
187/*!
188*/
189
190void EmulationLayer::onRcvChar(int c)
191// process application unicode input to terminal
192// this is a trivial scanner
193{
194 c &= 0xff;
195 switch (c)
196 {
197 case '\b' : scr->BackSpace(); break;
198 case '\t' : scr->Tabulate(); break;
199 case '\n' : scr->NewLine(); break;
200 case '\r' : scr->Return(); break;
201 case 0x07 : gui->Bell(); break;
202 default : scr->ShowCharacter(c); break;
203 };
204}
205
206/* ------------------------------------------------------------------------- */
207/* */
208/* Keyboard Handling */
209/* */
210/* ------------------------------------------------------------------------- */
211
212/*!
213*/
214
215void EmulationLayer::onKeyPress( QKeyEvent* ev )
216{
217 if (!connected) return; // someone else gets the keys
218 if (scr->getHistCursor() != scr->getHistLines());
219 scr->setHistCursor(scr->getHistLines());
220 if (!ev->text().isEmpty())
221 { // A block of text
222 // Note that the text is proper unicode.
223 // We should do a conversion here, but since this
224 // routine will never be used, we simply emit plain ascii.
225 sendString( ev->text().ascii() ); //,ev->text().length());
226 }
227 else if (ev->ascii()>0)
228 {
229 QByteArray c = QByteArray( 1 );
230 c.at( 0 ) = ev->ascii();
231 // ibot: qbytearray is emited not char*
232 emit sndBlock( (QByteArray) c );
233 }
234}
235
236// Unblocking, Byte to Unicode translation --------------------------------- --
237
238/*
239 We are doing code conversion from locale to unicode first.
240*/
241
242void EmulationLayer::onRcvBlock(const QByteArray &s )
243{
244 bulkStart();
245 bulk_incnt += 1;
246 for (int i = 0; i < s.size(); i++)
247 {
248 //TODO: ibot: maybe decoding qbytearray to unicode in io_layer?
249 QString result = decoder->toUnicode(&s[i],1);
250 int reslen = result.length();
251 for (int j = 0; j < reslen; j++)
252 onRcvChar(result[j].unicode());
253 if (s[i] == '\n') bulkNewline();
254 }
255 bulkEnd();
256}
257
258// Selection --------------------------------------------------------------- --
259
260void EmulationLayer::onSelectionBegin(const int x, const int y) {
261 if (!connected) return;
262 scr->setSelBeginXY(x,y);
263 showBulk();
264}
265
266void EmulationLayer::onSelectionExtend(const int x, const int y) {
267 if (!connected) return;
268 scr->setSelExtentXY(x,y);
269 showBulk();
270}
271
272void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
273 if (!connected) return;
274 QString t = scr->getSelText(preserve_line_breaks);
275 if (!t.isNull()) gui->setSelection(t);
276}
277
278void EmulationLayer::clearSelection() {
279 if (!connected) return;
280 scr->clearSelection();
281 showBulk();
282}
283
284// Refreshing -------------------------------------------------------------- --
285
286#define BULK_TIMEOUT 20
287
288/*!
289 called when \n comes in. Evtl. triggers showBulk at endBulk
290*/
291
292void EmulationLayer::bulkNewline()
293{
294 bulk_nlcnt += 1;
295 bulk_incnt = 0; // reset bulk counter since `nl' rule applies
296}
297
298/*!
299*/
300
301void EmulationLayer::showBulk()
302{
303 bulk_nlcnt = 0; // reset bulk newline counter
304 bulk_incnt = 0; // reset bulk counter
305 if (connected)
306 {
307 ca* image = scr->getCookedImage(); // get the image
308 gui->setImage(image,
309 scr->getLines(),
310 scr->getColumns()); // actual refresh
311 free(image);
312 //FIXME: check that we do not trigger other draw event here.
313 gui->setScroll(scr->getHistCursor(),scr->getHistLines());
314 }
315}
316
317void EmulationLayer::bulkStart()
318{
319 if (bulk_timer.isActive()) bulk_timer.stop();
320}
321
322void EmulationLayer::bulkEnd()
323{
324 if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
325 showBulk(); // resets bulk_??cnt to 0, too.
326 else
327 bulk_timer.start(BULK_TIMEOUT,TRUE);
328}
329
330void EmulationLayer::setConnect(bool c)
331{
332 connected = c;
333 if ( connected)
334 {
335 onImageSizeChange(gui->Lines(), gui->Columns());
336 showBulk();
337 }
338 else
339 {
340 scr->clearSelection();
341 }
342}
343
344// ---------------------------------------------------------------------------
345
346/*! triggered by image size change of the TEWidget `gui'.
347
348 This event is simply propagated to the attached screens
349 and to the related serial line.
350*/
351
352void EmulationLayer::onImageSizeChange(int lines, int columns)
353{
354 if (!connected) return;
355 screen[0]->resizeImage(lines,columns);
356 screen[1]->resizeImage(lines,columns);
357 showBulk();
358 emit ImageSizeChanged(lines,columns); // propagate event to serial line
359}
360
361void EmulationLayer::onHistoryCursorChange(int cursor)
362{
363 if (!connected) return;
364 scr->setHistCursor(cursor);
365 showBulk();
366}
367
368void EmulationLayer::setColumns(int columns)
369{
370 //FIXME: this goes strange ways.
371 // Can we put this straight or explain it at least?
372 emit changeColumns(columns);
373}
diff --git a/noncore/apps/opie-console/emulation_layer.h b/noncore/apps/opie-console/emulation_layer.h
new file mode 100644
index 0000000..0f54331
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.h
@@ -0,0 +1,146 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [emulation.h] Fundamental 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 /* */
20/* made to a layer between io_layer and widget */
21 /* */
22/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
23 /* */
24/* -------------------------------------------------------------------------- */
25
26#ifndef EMULATION_LAYER_H
27#define EMULATION_LAYER_H
28
29#include "widget.h"
30#include "screen.h"
31#include <qtimer.h>
32#include <stdio.h>
33#include <qtextcodec.h>
34#include "keytrans.h"
35
36class EmulationLayer : public QObject
37{ Q_OBJECT
38
39public:
40
41 EmulationLayer(Widget* gui);
42 ~EmulationLayer();
43
44public:
45 virtual void setHistory(bool on);
46 virtual bool history();
47
48public slots: // signals incoming from Widget
49
50 virtual void onImageSizeChange(int lines, int columns);
51 virtual void onHistoryCursorChange(int cursor);
52 virtual void onKeyPress(QKeyEvent*);
53
54 virtual void clearSelection();
55 virtual void onSelectionBegin(const int x, const int y);
56 virtual void onSelectionExtend(const int x, const int y);
57 virtual void setSelection(const BOOL preserve_line_breaks);
58
59public slots: // signals incoming from data source
60
61 /**
62 * to be called, when new data arrives
63 */
64 void onRcvBlock(const QByteArray&);
65
66signals:
67
68 /**
69 * will send data, encoded to suit emulation
70 */
71 void sndBlock(const QByteArray&);
72
73 void ImageSizeChanged(int lines, int columns);
74
75 void changeColumns(int columns);
76
77 void changeTitle(int arg, const char* str);
78
79
80public:
81
82 /**
83 * process single char (decode)
84 */
85 virtual void onRcvChar(int);
86
87 virtual void setMode (int) = 0;
88 virtual void resetMode(int) = 0;
89
90 /**
91 * @deprecated use qbytearray instead
92 */
93 virtual void sendString(const char*) = 0;
94
95 /**
96 * sends a string to IOLayer
97 * encodes to suit emulation before
98 */
99 virtual void sendString(const QByteArray&) = 0;
100
101 virtual void setConnect(bool r);
102 void setColumns(int columns);
103
104 void setKeytrans(int no);
105 void setKeytrans(const char * no);
106
107protected:
108
109 Widget* gui;
110 Screen* scr; // referes to one `screen'
111 Screen* screen[2]; // 0 = primary, 1 = alternate
112 void setScreen(int n); // set `scr' to `screen[n]'
113
114 bool connected; // communicate with widget
115
116 void setCodec(int c); // codec number, 0 = locale, 1=utf8
117
118 QTextCodec* codec;
119 QTextCodec* localeCodec;
120 QTextDecoder* decoder;
121
122 KeyTrans* keytrans;
123
124// refreshing related material.
125// this is localized in the class.
126private slots: // triggered by timer
127
128 void showBulk();
129
130private:
131
132 void bulkNewline();
133 void bulkStart();
134 void bulkEnd();
135
136private:
137
138 QTimer bulk_timer;
139 int bulk_nlcnt; // bulk newline counter
140 char* SelectedText;
141 int bulk_incnt; // bulk counter
142
143
144};
145
146#endif // ifndef EMULATION_H
diff --git a/noncore/apps/opie-console/emulation_layer.o b/noncore/apps/opie-console/emulation_layer.o
new file mode 100644
index 0000000..fe80bcb
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.o
Binary files differ
diff --git a/noncore/apps/opie-console/history.cpp b/noncore/apps/opie-console/history.cpp
new file mode 100644
index 0000000..3b82d16
--- a/dev/null
+++ b/noncore/apps/opie-console/history.cpp
@@ -0,0 +1,218 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [history.c] History Buffer */
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/* Ported embedded-Konsole to opie-console */
20 /* */
21/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
22 /* */
23/* -------------------------------------------------------------------------- */
24
25#include "history.h"
26#include <stdlib.h>
27#include <assert.h>
28#include <stdio.h>
29#include <sys/types.h>
30#include <unistd.h>
31#include <errno.h>
32
33#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
34
35/*
36 An arbitrary long scroll.
37
38 One can modify the scroll only by adding either cells
39 or newlines, but access it randomly.
40
41 The model is that of an arbitrary wide typewriter scroll
42 in that the scroll is a serie of lines and each line is
43 a serie of cells with no overwriting permitted.
44
45 The implementation provides arbitrary length and numbers
46 of cells and line/column indexed read access to the scroll
47 at constant costs.
48
49FIXME: some complain about the history buffer comsuming the
50 memory of their machines. This problem is critical
51 since the history does not behave gracefully in cases
52 where the memory is used up completely.
53
54 I put in a workaround that should handle it problem
55 now gracefully. I'm not satisfied with the solution.
56
57FIXME: Terminating the history is not properly indicated
58 in the menu. We should throw a signal.
59
60FIXME: There is noticable decrease in speed, also. Perhaps,
61 there whole feature needs to be revisited therefore.
62 Disadvantage of a more elaborated, say block-oriented
63 scheme with wrap around would be it's complexity.
64*/
65
66//FIXME: tempory replacement for tmpfile
67// this is here one for debugging purpose.
68
69//#define tmpfile xTmpFile
70
71FILE* xTmpFile()
72{
73 static int fid = 0;
74 char fname[80];
75 sprintf(fname,"TmpFile.%d",fid++);
76 return fopen(fname,"w");
77}
78
79
80// History Buffer ///////////////////////////////////////////
81
82/*
83 A Row(X) data type which allows adding elements to the end.
84*/
85
86HistoryBuffer::HistoryBuffer()
87{
88 ion = -1;
89 length = 0;
90}
91
92HistoryBuffer::~HistoryBuffer()
93{
94 setScroll(FALSE);
95}
96
97void HistoryBuffer::setScroll(bool on)
98{
99 if (on == hasScroll()) return;
100
101 if (on)
102 {
103 assert( ion < 0 );
104 assert( length == 0);
105 FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; }
106 ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n");
107 fclose(tmp);
108 }
109 else
110 {
111 assert( ion >= 0 );
112 close(ion);
113 ion = -1;
114 length = 0;
115 }
116}
117
118bool HistoryBuffer::hasScroll()
119{
120 return ion >= 0;
121}
122
123void HistoryBuffer::add(const unsigned char* bytes, int len)
124{ int rc;
125 assert(hasScroll());
126 rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; }
127 rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; }
128 length += rc;
129}
130
131void HistoryBuffer::get(unsigned char* bytes, int len, int loc)
132{ int rc;
133 assert(hasScroll());
134 if (loc < 0 || len < 0 || loc + len > length)
135 fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
136 rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; }
137 rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; }
138}
139
140int HistoryBuffer::len()
141{
142 return length;
143}
144
145// History Scroll //////////////////////////////////////
146
147/*
148 The history scroll makes a Row(Row(Cell)) from
149 two history buffers. The index buffer contains
150 start of line positions which refere to the cells
151 buffer.
152
153 Note that index[0] addresses the second line
154 (line #1), while the first line (line #0) starts
155 at 0 in cells.
156*/
157
158HistoryScroll::HistoryScroll()
159{
160}
161
162HistoryScroll::~HistoryScroll()
163{
164}
165
166void HistoryScroll::setScroll(bool on)
167{
168 index.setScroll(on);
169 cells.setScroll(on);
170}
171
172bool HistoryScroll::hasScroll()
173{
174 return index.hasScroll() && cells.hasScroll();
175}
176
177int HistoryScroll::getLines()
178{
179 if (!hasScroll()) return 0;
180 return index.len() / sizeof(int);
181}
182
183int HistoryScroll::getLineLen(int lineno)
184{
185 if (!hasScroll()) return 0;
186 return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character);
187}
188
189int HistoryScroll::startOfLine(int lineno)
190{
191 if (lineno <= 0) return 0;
192 if (!hasScroll()) return 0;
193 if (lineno <= getLines())
194 { int res;
195 index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
196 return res;
197 }
198 return cells.len();
199}
200
201void HistoryScroll::getCells(int lineno, int colno, int count, Character res[])
202{
203 assert(hasScroll());
204 cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character));
205}
206
207void HistoryScroll::addCells(Character text[], int count)
208{
209 if (!hasScroll()) return;
210 cells.add((unsigned char*)text,count*sizeof(Character));
211}
212
213void HistoryScroll::addLine()
214{
215 if (!hasScroll()) return;
216 int locn = cells.len();
217 index.add((unsigned char*)&locn,sizeof(int));
218}
diff --git a/noncore/apps/opie-console/history.h b/noncore/apps/opie-console/history.h
new file mode 100644
index 0000000..aa77ebb
--- a/dev/null
+++ b/noncore/apps/opie-console/history.h
@@ -0,0 +1,82 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [history.h] History Buffer */
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 /* */
14/* Ported Konsole to Qt/Embedded */
15 /* */
16/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
17 /* */
18/* -------------------------------------------------------------------------- */
19 /* */
20/* ported embedded_konsole to opie-console */
21 /* */
22/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
23 /* */
24/* -------------------------------------------------------------------------- */
25
26#ifndef HISTORY_H
27#define HISTORY_H
28
29#include "common.h"
30
31/*
32 An extendable tmpfile(1) based buffer.
33*/
34class HistoryBuffer
35{
36public:
37 HistoryBuffer();
38 ~HistoryBuffer();
39
40public:
41 void setScroll(bool on);
42 bool hasScroll();
43
44public:
45 void add(const unsigned char* bytes, int len);
46 void get(unsigned char* bytes, int len, int loc);
47 int len();
48
49private:
50 int ion;
51 int length;
52};
53
54class HistoryScroll
55{
56public:
57 HistoryScroll();
58 ~HistoryScroll();
59
60public:
61 void setScroll(bool on);
62 bool hasScroll();
63
64public: // access to history
65 int getLines();
66 int getLineLen(int lineno);
67 void getCells(int lineno, int colno, int count, Character res[]);
68
69public: // backward compatibility (obsolete)
70 Character getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
71
72public: // adding lines.
73 void addCells(Character a[], int count);
74 void addLine();
75
76private:
77 int startOfLine(int lineno);
78 HistoryBuffer index; // lines Row(int)
79 HistoryBuffer cells; // text Row(Character)
80};
81
82#endif // HISTORY_H
diff --git a/noncore/apps/opie-console/history.o b/noncore/apps/opie-console/history.o
new file mode 100644
index 0000000..256d3a5
--- a/dev/null
+++ b/noncore/apps/opie-console/history.o
Binary files differ
diff --git a/noncore/apps/opie-console/keytrans.cpp b/noncore/apps/opie-console/keytrans.cpp
new file mode 100644
index 0000000..d569ae0
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.cpp
@@ -0,0 +1,706 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [keytrans.C] Keyboard Translation */
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/*
20 The keyboard translation table allows to configure konsoles behavior
21 on key strokes.
22
23 FIXME: some bug crept in, disallowing '\0' to be emitted.
24*/
25
26#include "keytrans.h"
27
28#include <qpe/qpeapplication.h>
29
30#include <qnamespace.h>
31#include <qbuffer.h>
32#include <qobject.h>
33#include <qdict.h>
34#include <qintdict.h>
35#include <qfile.h>
36#include <qglobal.h>
37#include <qdir.h>
38
39//#include <kstddirs.h>
40//nclude <klocale.h>
41
42#include <stdio.h>
43
44
45#undef USE_APPDATA_DIR
46
47
48#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
49
50/* KeyEntry
51
52 instances represent the individual assignments
53*/
54
55KeyTrans::KeyEntry::KeyEntry(int _ref, int _key, int _bits, int _mask, int _cmd, QString _txt)
56: ref(_ref), key(_key), bits(_bits), mask(_mask), cmd(_cmd), txt(_txt)
57{
58}
59
60KeyTrans::KeyEntry::~KeyEntry()
61{
62}
63
64bool KeyTrans::KeyEntry::matches(int _key, int _bits, int _mask)
65{ int m = mask & _mask;
66 return _key == key && (bits & m) == (_bits & m);
67}
68
69QString KeyTrans::KeyEntry::text()
70{
71 return txt;
72}
73
74/* KeyTrans
75
76 combines the individual assignments to a proper map
77 Takes part in a collection themself.
78*/
79
80KeyTrans::KeyTrans()
81{
82 path = "";
83 numb = 0;
84}
85
86KeyTrans::~KeyTrans()
87{
88}
89
90KeyTrans::KeyEntry* KeyTrans::addEntry(int ref, int key, int bits, int mask, int cmd, QString txt)
91// returns conflicting entry
92{
93 for (QListIterator<KeyEntry> it(table); it.current(); ++it)
94 {
95 if (it.current()->matches(key,bits,mask))
96 {
97 return it.current();
98 }
99 }
100 table.append(new KeyEntry(ref,key,bits,mask,cmd,txt));
101 return (KeyEntry*)NULL;
102}
103
104bool KeyTrans::findEntry(int key, int bits, int* cmd, const char** txt, int* len)
105{
106 for (QListIterator<KeyEntry> it(table); it.current(); ++it)
107 if (it.current()->matches(key,bits,0xffff))
108 {
109 *cmd = it.current()->cmd;
110 *txt = it.current()->txt.ascii();
111 *len = it.current()->txt.length();
112 return TRUE;
113 }
114 return FALSE;
115}
116
117/* ------------------------------------------------------------------------- */
118/* */
119/* Scanner for keyboard configuration */
120/* */
121/* ------------------------------------------------------------------------- */
122
123// regular tokenizer
124/* Tokens
125 - Spaces
126 - Name (A-Za-z0-9)+
127 - String
128 - Opr on of +-:
129*/
130
131#define SYMName 0
132#define SYMString 1
133#define SYMEol 2
134#define SYMEof 3
135#define SYMOpr 4
136#define SYMError 5
137
138#define inRange(L,X,H) ((L <= X) && (X <= H))
139#define isNibble(X) (inRange('A',X,'F')||inRange('a',X,'f')||inRange('0',X,'9'))
140#define convNibble(X) (inRange('0',X,'9')?X-'0':X+10-(inRange('A',X,'F')?'A':'a'))
141
142class KeytabReader
143{
144public:
145 KeytabReader(QString p, QIODevice &d);
146public:
147 void getCc();
148 void getSymbol();
149 void parseTo(KeyTrans* kt);
150 void ReportError(const char* msg);
151 void ReportToken(); // diagnostic
152private:
153 int sym;
154 QString res;
155 int len;
156 int slinno;
157 int scolno;
158private:
159 int cc;
160 int linno;
161 int colno;
162 QIODevice* buf;
163 QString path;
164};
165
166
167KeytabReader::KeytabReader(QString p, QIODevice &d)
168{
169 path = p;
170 buf = &d;
171 cc = 0;
172}
173
174void KeytabReader::getCc()
175{
176 if (cc == '\n') { linno += 1; colno = 0; }
177 if (cc < 0) return;
178 cc = buf->getch();
179 colno += 1;
180}
181
182void KeytabReader::getSymbol()
183{
184 res = ""; len = 0; sym = SYMError;
185 while (cc == ' ') getCc(); // skip spaces
186 if (cc == '#') // skip comment
187 {
188 while (cc != '\n' && cc > 0) getCc();
189 }
190 slinno = linno;
191 scolno = colno;
192 if (cc <= 0)
193 {
194 sym = SYMEof; return; // eos
195 }
196 if (cc == '\n')
197 {
198 getCc();
199 sym = SYMEol; return; // eol
200 }
201 if (inRange('A',cc,'Z')||inRange('a',cc,'z')||inRange('0',cc,'9'))
202 {
203 while (inRange('A',cc,'Z') || inRange('a',cc,'z') || inRange('0',cc,'9'))
204 {
205 res = res + (char)cc;
206 getCc();
207 }
208 sym = SYMName;
209 return;
210 }
211 if (strchr("+-:",cc))
212 {
213 res = "";
214 res = res + (char)cc;
215 getCc();
216 sym = SYMOpr; return;
217 }
218 if (cc == '"')
219 {
220 getCc();
221 while (cc >= ' ' && cc != '"')
222 { int sc;
223 if (cc == '\\') // handle quotation
224 {
225 getCc();
226 switch (cc)
227 {
228 case 'E' : sc = 27; getCc(); break;
229 case 'b' : sc = 8; getCc(); break;
230 case 'f' : sc = 12; getCc(); break;
231 case 't' : sc = 9; getCc(); break;
232 case 'r' : sc = 13; getCc(); break;
233 case 'n' : sc = 10; getCc(); break;
234 case '\\' : // fall thru
235 case '"' : sc = cc; getCc(); break;
236 case 'x' : getCc();
237 sc = 0;
238 if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
239 if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
240 break;
241 default : return;
242 }
243 }
244 else
245 {
246 // regular char
247 sc = cc; getCc();
248 }
249 res = res + (char)sc;
250 len = len + 1;
251 }
252 if (cc != '"') return;
253 getCc();
254 sym = SYMString; return;
255 }
256}
257
258void KeytabReader::ReportToken() // diagnostic
259{
260 printf("sym(%d): ",slinno);
261 switch(sym)
262 {
263 case SYMEol : printf("End of line"); break;
264 case SYMEof : printf("End of file"); break;
265 case SYMName : printf("Name: %s",res.latin1()); break;
266 case SYMOpr : printf("Opr : %s",res.latin1()); break;
267 case SYMString : printf("String len %d,%d ",res.length(),len);
268 for (unsigned i = 0; i < res.length(); i++)
269 printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?');
270 break;
271 }
272 printf("\n");
273}
274
275void KeytabReader::ReportError(const char* msg) // diagnostic
276{
277 fprintf(stderr,"%s(%d,%d):error: %s.\n",path.ascii(),slinno,scolno,msg);
278}
279
280// local symbol tables ---------------------------------------------------------------------
281
282class KeyTransSymbols
283{
284public:
285 KeyTransSymbols();
286protected:
287 void defOprSyms();
288 void defModSyms();
289 void defKeySyms();
290 void defKeySym(const char* key, int val);
291 void defOprSym(const char* key, int val);
292 void defModSym(const char* key, int val);
293public:
294 QDict<QObject> keysyms;
295 QDict<QObject> modsyms;
296 QDict<QObject> oprsyms;
297};
298
299static KeyTransSymbols * syms = 0L;
300
301// parser ----------------------------------------------------------------------------------
302/* Syntax
303 - Line :: [KeyName { ("+" | "-") ModeName } ":" (String|CommandName)] "\n"
304 - Comment :: '#' (any but \n)*
305*/
306
307KeyTrans* KeyTrans::fromDevice(QString path, QIODevice &buf)
308{
309 KeyTrans* kt = new KeyTrans;
310 kt->path = path;
311 KeytabReader ktr(path,buf); ktr.parseTo(kt);
312 return kt;
313}
314
315
316#define assertSyntax(Cond,Message) if (!(Cond)) { ReportError(Message); goto ERROR; }
317
318void KeytabReader::parseTo(KeyTrans* kt)
319{
320 // Opening sequence
321
322 buf->open(IO_ReadOnly);
323 getCc();
324 linno = 1;
325 colno = 1;
326 getSymbol();
327
328Loop:
329 // syntax: ["key" KeyName { ("+" | "-") ModeName } ":" String/CommandName] ["#" Comment]
330 if (sym == SYMName && !strcmp(res.latin1(),"keyboard"))
331 {
332 getSymbol(); assertSyntax(sym == SYMString, "Header expected")
333 kt->hdr = res.latin1();
334 getSymbol(); assertSyntax(sym == SYMEol, "Text unexpected")
335 getSymbol(); // eoln
336 goto Loop;
337 }
338 if (sym == SYMName && !strcmp(res.latin1(),"key"))
339 {
340//printf("line %3d: ",startofsym);
341 getSymbol(); assertSyntax(sym == SYMName, "Name expected")
342 assertSyntax(syms->keysyms[res], "Unknown key name")
343 int key = (int)syms->keysyms[res]-1;
344//printf(" key %s (%04x)",res.latin1(),(int)syms->keysyms[res]-1);
345 getSymbol(); // + - :
346 int mode = 0;
347 int mask = 0;
348 while (sym == SYMOpr && (!strcmp(res.latin1(),"+") || !strcmp(res.latin1(),"-")))
349 {
350 bool on = !strcmp(res.latin1(),"+");
351 getSymbol();
352 // mode name
353 assertSyntax(sym == SYMName, "Name expected")
354 assertSyntax(syms->modsyms[res], "Unknown mode name")
355 int bits = (int)syms->modsyms[res]-1;
356 if (mask & (1 << bits))
357 {
358 fprintf(stderr,"%s(%d,%d): mode name used multible times.\n",path.ascii(),slinno,scolno);
359 }
360 else
361 {
362 mode |= (on << bits);
363 mask |= (1 << bits);
364 }
365//printf(", mode %s(%d) %s",res.latin1(),(int)syms->modsyms[res]-1,on?"on":"off");
366 getSymbol();
367 }
368 assertSyntax(sym == SYMOpr && !strcmp(res.latin1(),":"), "':' expected")
369 getSymbol();
370 // string or command
371 assertSyntax(sym == SYMName || sym == SYMString,"Command or string expected")
372 int cmd = 0;
373 if (sym == SYMName)
374 {
375 assertSyntax(syms->oprsyms[res], "Unknown operator name")
376 cmd = (int)syms->oprsyms[res]-1;
377//printf(": do %s(%d)",res.latin1(),(int)syms->oprsyms[res]-1);
378 }
379 if (sym == SYMString)
380 {
381 cmd = CMD_send;
382//printf(": send");
383//for (unsigned i = 0; i < res.length(); i++)
384//printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?');
385 }
386//printf(". summary %04x,%02x,%02x,%d\n",key,mode,mask,cmd);
387 KeyTrans::KeyEntry* ke = kt->addEntry(slinno,key,mode,mask,cmd,res);
388 if (ke)
389 {
390 fprintf(stderr,"%s(%d): keystroke already assigned in line %d.\n",path.ascii(),slinno,ke->ref);
391 }
392 getSymbol();
393 assertSyntax(sym == SYMEol, "Unexpected text")
394 goto Loop;
395 }
396 if (sym == SYMEol)
397 {
398 getSymbol();
399 goto Loop;
400 }
401
402 assertSyntax(sym == SYMEof, "Undecodable Line")
403
404 buf->close();
405 return;
406
407ERROR:
408 while (sym != SYMEol && sym != SYMEof) getSymbol(); // eoln
409 goto Loop;
410}
411
412
413KeyTrans* KeyTrans::defaultKeyTrans()
414{
415 QCString txt =
416#include "default.keytab.h"
417 ;
418 QBuffer buf(txt);
419 return fromDevice("[buildin]",buf);
420}
421
422KeyTrans* KeyTrans::fromFile(const char* path)
423{
424 QFile file(path);
425 return fromDevice(path,file);
426}
427
428// local symbol tables ---------------------------------------------------------------------
429// material needed for parsing the config file.
430// This is incomplete work.
431
432void KeyTransSymbols::defKeySym(const char* key, int val)
433{
434 keysyms.insert(key,(QObject*)(val+1));
435}
436
437void KeyTransSymbols::defOprSym(const char* key, int val)
438{
439 oprsyms.insert(key,(QObject*)(val+1));
440}
441
442void KeyTransSymbols::defModSym(const char* key, int val)
443{
444 modsyms.insert(key,(QObject*)(val+1));
445}
446
447void KeyTransSymbols::defOprSyms()
448{
449 // Modifier
450 defOprSym("scrollLineUp", CMD_scrollLineUp );
451 defOprSym("scrollLineDown",CMD_scrollLineDown);
452 defOprSym("scrollPageUp", CMD_scrollPageUp );
453 defOprSym("scrollPageDown",CMD_scrollPageDown);
454 defOprSym("emitSelection", CMD_emitSelection );
455 defOprSym("prevSession", CMD_prevSession );
456 defOprSym("nextSession", CMD_nextSession );
457}
458
459void KeyTransSymbols::defModSyms()
460{
461 // Modifier
462 defModSym("Shift", BITS_Shift );
463 defModSym("Control", BITS_Control );
464 defModSym("Alt", BITS_Alt );
465 // Modes
466 defModSym("BsHack", BITS_BsHack ); // deprecated
467 defModSym("Ansi", BITS_Ansi );
468 defModSym("NewLine", BITS_NewLine );
469 defModSym("AppCuKeys", BITS_AppCuKeys );
470}
471
472void KeyTransSymbols::defKeySyms()
473{
474 // Grey keys
475 defKeySym("Escape", Qt::Key_Escape );
476 defKeySym("Tab", Qt::Key_Tab );
477 defKeySym("Backtab", Qt::Key_Backtab );
478 defKeySym("Backspace", Qt::Key_Backspace );
479 defKeySym("Return", Qt::Key_Return );
480 defKeySym("Enter", Qt::Key_Enter );
481 defKeySym("Insert", Qt::Key_Insert );
482 defKeySym("Delete", Qt::Key_Delete );
483 defKeySym("Pause", Qt::Key_Pause );
484 defKeySym("Print", Qt::Key_Print );
485 defKeySym("SysReq", Qt::Key_SysReq );
486 defKeySym("Home", Qt::Key_Home );
487 defKeySym("End", Qt::Key_End );
488 defKeySym("Left", Qt::Key_Left );
489 defKeySym("Up", Qt::Key_Up );
490 defKeySym("Right", Qt::Key_Right );
491 defKeySym("Down", Qt::Key_Down );
492 defKeySym("Prior", Qt::Key_Prior );
493 defKeySym("Next", Qt::Key_Next );
494 defKeySym("Shift", Qt::Key_Shift );
495 defKeySym("Control", Qt::Key_Control );
496 defKeySym("Meta", Qt::Key_Meta );
497 defKeySym("Alt", Qt::Key_Alt );
498 defKeySym("CapsLock", Qt::Key_CapsLock );
499 defKeySym("NumLock", Qt::Key_NumLock );
500 defKeySym("ScrollLock", Qt::Key_ScrollLock );
501 defKeySym("F1", Qt::Key_F1 );
502 defKeySym("F2", Qt::Key_F2 );
503 defKeySym("F3", Qt::Key_F3 );
504 defKeySym("F4", Qt::Key_F4 );
505 defKeySym("F5", Qt::Key_F5 );
506 defKeySym("F6", Qt::Key_F6 );
507 defKeySym("F7", Qt::Key_F7 );
508 defKeySym("F8", Qt::Key_F8 );
509 defKeySym("F9", Qt::Key_F9 );
510 defKeySym("F10", Qt::Key_F10 );
511 defKeySym("F11", Qt::Key_F11 );
512 defKeySym("F12", Qt::Key_F12 );
513 defKeySym("F13", Qt::Key_F13 );
514 defKeySym("F14", Qt::Key_F14 );
515 defKeySym("F15", Qt::Key_F15 );
516 defKeySym("F16", Qt::Key_F16 );
517 defKeySym("F17", Qt::Key_F17 );
518 defKeySym("F18", Qt::Key_F18 );
519 defKeySym("F19", Qt::Key_F19 );
520 defKeySym("F20", Qt::Key_F20 );
521 defKeySym("F21", Qt::Key_F21 );
522 defKeySym("F22", Qt::Key_F22 );
523 defKeySym("F23", Qt::Key_F23 );
524 defKeySym("F24", Qt::Key_F24 );
525 defKeySym("F25", Qt::Key_F25 );
526 defKeySym("F26", Qt::Key_F26 );
527 defKeySym("F27", Qt::Key_F27 );
528 defKeySym("F28", Qt::Key_F28 );
529 defKeySym("F29", Qt::Key_F29 );
530 defKeySym("F30", Qt::Key_F30 );
531 defKeySym("F31", Qt::Key_F31 );
532 defKeySym("F32", Qt::Key_F32 );
533 defKeySym("F33", Qt::Key_F33 );
534 defKeySym("F34", Qt::Key_F34 );
535 defKeySym("F35", Qt::Key_F35 );
536 defKeySym("Super_L", Qt::Key_Super_L );
537 defKeySym("Super_R", Qt::Key_Super_R );
538 defKeySym("Menu", Qt::Key_Menu );
539 defKeySym("Hyper_L", Qt::Key_Hyper_L );
540 defKeySym("Hyper_R", Qt::Key_Hyper_R );
541
542 // Regular keys
543 defKeySym("Space", Qt::Key_Space );
544 defKeySym("Exclam", Qt::Key_Exclam );
545 defKeySym("QuoteDbl", Qt::Key_QuoteDbl );
546 defKeySym("NumberSign", Qt::Key_NumberSign );
547 defKeySym("Dollar", Qt::Key_Dollar );
548 defKeySym("Percent", Qt::Key_Percent );
549 defKeySym("Ampersand", Qt::Key_Ampersand );
550 defKeySym("Apostrophe", Qt::Key_Apostrophe );
551 defKeySym("ParenLeft", Qt::Key_ParenLeft );
552 defKeySym("ParenRight", Qt::Key_ParenRight );
553 defKeySym("Asterisk", Qt::Key_Asterisk );
554 defKeySym("Plus", Qt::Key_Plus );
555 defKeySym("Comma", Qt::Key_Comma );
556 defKeySym("Minus", Qt::Key_Minus );
557 defKeySym("Period", Qt::Key_Period );
558 defKeySym("Slash", Qt::Key_Slash );
559 defKeySym("0", Qt::Key_0 );
560 defKeySym("1", Qt::Key_1 );
561 defKeySym("2", Qt::Key_2 );
562 defKeySym("3", Qt::Key_3 );
563 defKeySym("4", Qt::Key_4 );
564 defKeySym("5", Qt::Key_5 );
565 defKeySym("6", Qt::Key_6 );
566 defKeySym("7", Qt::Key_7 );
567 defKeySym("8", Qt::Key_8 );
568 defKeySym("9", Qt::Key_9 );
569 defKeySym("Colon", Qt::Key_Colon );
570 defKeySym("Semicolon", Qt::Key_Semicolon );
571 defKeySym("Less", Qt::Key_Less );
572 defKeySym("Equal", Qt::Key_Equal );
573 defKeySym("Greater", Qt::Key_Greater );
574 defKeySym("Question", Qt::Key_Question );
575 defKeySym("At", Qt::Key_At );
576 defKeySym("A", Qt::Key_A );
577 defKeySym("B", Qt::Key_B );
578 defKeySym("C", Qt::Key_C );
579 defKeySym("D", Qt::Key_D );
580 defKeySym("E", Qt::Key_E );
581 defKeySym("F", Qt::Key_F );
582 defKeySym("G", Qt::Key_G );
583 defKeySym("H", Qt::Key_H );
584 defKeySym("I", Qt::Key_I );
585 defKeySym("J", Qt::Key_J );
586 defKeySym("K", Qt::Key_K );
587 defKeySym("L", Qt::Key_L );
588 defKeySym("M", Qt::Key_M );
589 defKeySym("N", Qt::Key_N );
590 defKeySym("O", Qt::Key_O );
591 defKeySym("P", Qt::Key_P );
592 defKeySym("Q", Qt::Key_Q );
593 defKeySym("R", Qt::Key_R );
594 defKeySym("S", Qt::Key_S );
595 defKeySym("T", Qt::Key_T );
596 defKeySym("U", Qt::Key_U );
597 defKeySym("V", Qt::Key_V );
598 defKeySym("W", Qt::Key_W );
599 defKeySym("X", Qt::Key_X );
600 defKeySym("Y", Qt::Key_Y );
601 defKeySym("Z", Qt::Key_Z );
602 defKeySym("BracketLeft", Qt::Key_BracketLeft );
603 defKeySym("Backslash", Qt::Key_Backslash );
604 defKeySym("BracketRight", Qt::Key_BracketRight);
605 defKeySym("AsciiCircum", Qt::Key_AsciiCircum );
606 defKeySym("Underscore", Qt::Key_Underscore );
607 defKeySym("QuoteLeft", Qt::Key_QuoteLeft );
608 defKeySym("BraceLeft", Qt::Key_BraceLeft );
609 defKeySym("Bar", Qt::Key_Bar );
610 defKeySym("BraceRight", Qt::Key_BraceRight );
611 defKeySym("AsciiTilde", Qt::Key_AsciiTilde );
612}
613
614KeyTransSymbols::KeyTransSymbols()
615{
616 defModSyms();
617 defOprSyms();
618 defKeySyms();
619}
620
621// Global material -----------------------------------------------------------
622
623static int keytab_serial = 0; //FIXME: remove,localize
624
625static QIntDict<KeyTrans> * numb2keymap = 0L;
626static QDict<KeyTrans> * path2keymap = 0L;
627
628KeyTrans* KeyTrans::find(int numb)
629{
630 KeyTrans* res = numb2keymap->find(numb);
631 return res ? res : numb2keymap->find(0);
632}
633
634KeyTrans* KeyTrans::find(const char* path)
635{
636 KeyTrans* res = path2keymap->find(path);
637 return res ? res : numb2keymap->find(0);
638}
639
640int KeyTrans::count()
641{
642 return numb2keymap->count();
643}
644
645void KeyTrans::addKeyTrans()
646{
647 this->numb = keytab_serial ++;
648 numb2keymap->insert(numb,this);
649 path2keymap->insert(path,this);
650}
651
652void KeyTrans::loadAll()
653{
654 if (!numb2keymap)
655 numb2keymap = new QIntDict<KeyTrans>;
656 if (!path2keymap)
657 path2keymap = new QDict<KeyTrans>;
658 if (!syms)
659 syms = new KeyTransSymbols;
660
661 defaultKeyTrans()->addKeyTrans();
662
663
664 QString path = QPEApplication::qpeDir() + "etc/keytabs";
665 QDir dir(path);
666 QStringList lst = dir.entryList("*.keytab");
667
668 for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
669 QFile file(path + "/" + *it);
670 KeyTrans* sc = KeyTrans::fromDevice(*it, file);
671 if (sc) {
672 sc->addKeyTrans();
673 }
674 }
675
676}
677
678// Debugging material -----------------------------------------------------------
679/*
680void TestTokenizer(QBuffer &buf)
681{
682 // opening sequence
683
684 buf.open(IO_ReadOnly);
685 cc = buf.getch();
686 lineno = 1;
687
688 // Test tokenizer
689
690 while (getSymbol(buf)) ReportToken();
691
692 buf.close();
693}
694
695void test()
696{
697 // Opening sequence
698
699 QCString txt =
700#include "default.keytab.h"
701 ;
702 QBuffer buf(txt);
703 if (0) TestTokenizer(buf);
704 if (1) { KeyTrans kt; kt.scanTable(buf); }
705}
706*/
diff --git a/noncore/apps/opie-console/keytrans.h b/noncore/apps/opie-console/keytrans.h
new file mode 100644
index 0000000..ef6ed15
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.h
@@ -0,0 +1,93 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [keytrans.h] X 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#ifndef KEYTRANS_H
20#define KEYTRANS_H
21
22#include <qstring.h>
23#include <qlist.h>
24#include <qiodevice.h>
25
26#define BITS_NewLine 0
27#define BITS_BsHack 1
28#define BITS_Ansi 2
29#define BITS_AppCuKeys 3
30#define BITS_Control 4
31#define BITS_Shift 5
32#define BITS_Alt 6
33#define BITS_COUNT 7
34
35#define CMD_send 0
36#define CMD_emitSelection 1
37#define CMD_scrollPageUp 2
38#define CMD_scrollPageDown 3
39#define CMD_scrollLineUp 4
40#define CMD_scrollLineDown 5
41#define CMD_prevSession 6
42#define CMD_nextSession 7
43
44#define BITS(x,v) ((((v)!=0)<<(x)))
45
46
47class KeyTrans
48{
49public:
50 KeyTrans();
51 ~KeyTrans();
52 static KeyTrans* defaultKeyTrans();
53 static KeyTrans* fromFile(const char* path);
54 static KeyTrans* find(int numb);
55 static KeyTrans* find(const char* path);
56public:
57 static int count();
58 static void loadAll();
59public:
60 bool findEntry(int key, int bits, int* cmd, const char** txt, int* len);
61private:
62 void addKeyTrans();
63 static KeyTrans* fromDevice(QString path, QIODevice &buf);
64public:
65 class KeyEntry
66 {
67 public:
68 KeyEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
69 ~KeyEntry();
70 public:
71 bool matches(int key, int bits, int mask);
72 QString text();
73 public:
74 int ref;
75 private:
76 int key;
77 int bits;
78 int mask;
79 public:
80 int cmd;
81 QString txt;
82 };
83public:
84 KeyEntry* addEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
85private:
86 QList<KeyEntry> table;
87public: //FIXME: we'd do better
88 QString hdr;
89 int numb;
90 QString path;
91};
92
93#endif
diff --git a/noncore/apps/opie-console/keytrans.o b/noncore/apps/opie-console/keytrans.o
new file mode 100644
index 0000000..2557f8a
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.o
Binary files differ
diff --git a/noncore/apps/opie-console/screen.cpp b/noncore/apps/opie-console/screen.cpp
new file mode 100644
index 0000000..8ebc47d
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.cpp
@@ -0,0 +1,1197 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [screen.C] Screen Data Type */
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/*! \file
20*/
21
22/*! \class Screen
23
24 \brief The image manipulated by the emulation.
25
26 This class implements the operations of the terminal emulation framework.
27 It is a complete passive device, driven by the emulation decoder
28 (TEmuVT102). By this it forms in fact an ADT, that defines operations
29 on a rectangular image.
30
31 It does neither know how to display its image nor about escape sequences.
32 It is further independent of the underlying toolkit. By this, one can even
33 use this module for an ordinary text surface.
34
35 Since the operations are called by a specific emulation decoder, one may
36 collect their different operations here.
37
38 The state manipulated by the operations is mainly kept in `image', though
39 it is a little more complex bejond this. See the header file of the class.
40
41 \sa TEWidget \sa VT102Emulation
42*/
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <unistd.h>
47// #include <kdebug.h>
48
49#include <assert.h>
50#include <string.h>
51#include <ctype.h>
52
53#include "screen.h"
54
55#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
56
57//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
58//FIXME: see if we can get this from terminfo.
59#define BS_CLEARS FALSE
60
61#define loc(X,Y) ((Y)*columns+(X))
62
63/*! creates a `Screen' of `lines' lines and `columns' columns.
64*/
65
66Screen::Screen(int lines, int columns)
67{
68 this->lines = lines;
69 this->columns = columns;
70
71 image = (Character*) malloc(lines*columns*sizeof(Character));
72 tabstops = NULL; initTabStops();
73
74 histCursor = 0;
75
76 clearSelection();
77 reset();
78}
79
80/*! Destructor
81*/
82
83Screen::~Screen()
84{
85 free(image);
86 if (tabstops) free(tabstops);
87}
88
89/* ------------------------------------------------------------------------- */
90/* */
91/* Normalized Screen Operations */
92/* */
93/* ------------------------------------------------------------------------- */
94
95// Cursor Setting --------------------------------------------------------------
96
97/*! \section Cursor
98
99 The `cursor' is a location within the screen that is implicitely used in
100 many operations. The operations within this section allow to manipulate
101 the cursor explicitly and to obtain it's value.
102
103 The position of the cursor is guarantied to be between (including) 0 and
104 `columns-1' and `lines-1'.
105*/
106
107/*!
108 Move the cursor up.
109
110 The cursor will not be moved beyond the top margin.
111*/
112
113void Screen::cursorUp(int n)
114//=CUU
115{
116 if (n == 0) n = 1; // Default
117 int stop = cuY < tmargin ? 0 : tmargin;
118 cuX = QMIN(columns-1,cuX); // nowrap!
119 cuY = QMAX(stop,cuY-n);
120}
121
122/*!
123 Move the cursor down.
124
125 The cursor will not be moved beyond the bottom margin.
126*/
127
128void Screen::cursorDown(int n)
129//=CUD
130{
131 if (n == 0) n = 1; // Default
132 int stop = cuY > bmargin ? lines-1 : bmargin;
133 cuX = QMIN(columns-1,cuX); // nowrap!
134 cuY = QMIN(stop,cuY+n);
135}
136
137/*!
138 Move the cursor left.
139
140 The cursor will not move beyond the first column.
141*/
142
143void Screen::cursorLeft(int n)
144//=CUB
145{
146 if (n == 0) n = 1; // Default
147 cuX = QMIN(columns-1,cuX); // nowrap!
148 cuX = QMAX(0,cuX-n);
149}
150
151/*!
152 Move the cursor left.
153
154 The cursor will not move beyond the rightmost column.
155*/
156
157void Screen::cursorRight(int n)
158//=CUF
159{
160 if (n == 0) n = 1; // Default
161 cuX = QMIN(columns-1,cuX+n);
162}
163
164/*!
165 Set top and bottom margin.
166*/
167
168void Screen::setMargins(int top, int bot)
169//=STBM
170{
171 if (top == 0) top = 1; // Default
172 if (bot == 0) bot = lines; // Default
173 top = top - 1; // Adjust to internal lineno
174 bot = bot - 1; // Adjust to internal lineno
175 if ( !( 0 <= top && top < bot && bot < lines ) )
176 { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
177 __FILE__,__LINE__,top,bot);
178 return; // Default error action: ignore
179 }
180 tmargin = top;
181 bmargin = bot;
182 cuX = 0;
183 cuY = getMode(MODE_Origin) ? top : 0;
184}
185
186/*!
187 Move the cursor down one line.
188
189 If cursor is on bottom margin, the region between the
190 actual top and bottom margin is scrolled up instead.
191*/
192
193void Screen::index()
194//=IND
195{
196 if (cuY == bmargin)
197 {
198 if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
199 scrollUp(tmargin,1);
200 }
201 else if (cuY < lines-1)
202 cuY += 1;
203}
204
205/*!
206 Move the cursor up one line.
207
208 If cursor is on the top margin, the region between the
209 actual top and bottom margin is scrolled down instead.
210*/
211
212void Screen::reverseIndex()
213//=RI
214{
215 if (cuY == tmargin)
216 scrollDown(tmargin,1);
217 else if (cuY > 0)
218 cuY -= 1;
219}
220
221/*!
222 Move the cursor to the begin of the next line.
223
224 If cursor is on bottom margin, the region between the
225 actual top and bottom margin is scrolled up.
226*/
227
228void Screen::NextLine()
229//=NEL
230{
231 Return(); index();
232}
233
234// Line Editing ----------------------------------------------------------------
235
236/*! \section inserting / deleting characters
237*/
238
239/*! erase `n' characters starting from (including) the cursor position.
240
241 The line is filled in from the right with spaces.
242*/
243
244void Screen::eraseChars(int n)
245{
246 if (n == 0) n = 1; // Default
247 int p = QMAX(0,QMIN(cuX+n-1,columns-1));
248 clearImage(loc(cuX,cuY),loc(p,cuY),' ');
249}
250
251/*! delete `n' characters starting from (including) the cursor position.
252
253 The line is filled in from the right with spaces.
254*/
255
256void Screen::deleteChars(int n)
257{
258 if (n == 0) n = 1; // Default
259 int p = QMAX(0,QMIN(cuX+n,columns-1));
260 moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
261 clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
262}
263
264/*! insert `n' spaces at the cursor position.
265
266 The cursor is not moved by the operation.
267*/
268
269void Screen::insertChars(int n)
270{
271 if (n == 0) n = 1; // Default
272 int p = QMAX(0,QMIN(columns-1-n,columns-1));
273 int q = QMAX(0,QMIN(cuX+n,columns-1));
274 moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
275 clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
276}
277
278/*! delete `n' lines starting from (including) the cursor position.
279
280 The cursor is not moved by the operation.
281*/
282
283void Screen::deleteLines(int n)
284{
285 if (n == 0) n = 1; // Default
286 scrollUp(cuY,n);
287}
288
289/*! insert `n' lines at the cursor position.
290
291 The cursor is not moved by the operation.
292*/
293
294void Screen::insertLines(int n)
295{
296 if (n == 0) n = 1; // Default
297 scrollDown(cuY,n);
298}
299
300// Mode Operations -----------------------------------------------------------
301
302/*! Set a specific mode. */
303
304void Screen::setMode(int m)
305{
306 currParm.mode[m] = TRUE;
307 switch(m)
308 {
309 case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
310 }
311}
312
313/*! Reset a specific mode. */
314
315void Screen::resetMode(int m)
316{
317 currParm.mode[m] = FALSE;
318 switch(m)
319 {
320 case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
321 }
322}
323
324/*! Save a specific mode. */
325
326void Screen::saveMode(int m)
327{
328 saveParm.mode[m] = currParm.mode[m];
329}
330
331/*! Restore a specific mode. */
332
333void Screen::restoreMode(int m)
334{
335 currParm.mode[m] = saveParm.mode[m];
336}
337
338//NOTE: this is a helper function
339/*! Return the setting a specific mode. */
340BOOL Screen::getMode(int m)
341{
342 return currParm.mode[m];
343}
344
345/*! Save the cursor position and the rendition attribute settings. */
346
347void Screen::saveCursor()
348{
349 sa_cuX = cuX;
350 sa_cuY = cuY;
351 sa_cu_re = cu_re;
352 sa_cu_fg = cu_fg;
353 sa_cu_bg = cu_bg;
354}
355
356/*! Restore the cursor position and the rendition attribute settings. */
357
358void Screen::restoreCursor()
359{
360 cuX = QMIN(sa_cuX,columns-1);
361 cuY = QMIN(sa_cuY,lines-1);
362 cu_re = sa_cu_re;
363 cu_fg = sa_cu_fg;
364 cu_bg = sa_cu_bg;
365 effectiveRendition();
366}
367
368/* ------------------------------------------------------------------------- */
369/* */
370/* Screen Operations */
371/* */
372/* ------------------------------------------------------------------------- */
373
374/*! Assing a new size to the screen.
375
376 The topmost left position is maintained, while lower lines
377 or right hand side columns might be removed or filled with
378 spaces to fit the new size.
379
380 The region setting is reset to the whole screen and the
381 tab positions reinitialized.
382*/
383
384void Screen::resizeImage(int new_lines, int new_columns)
385{
386
387 if (cuY > new_lines-1)
388 { // attempt to preserve focus and lines
389 bmargin = lines-1; //FIXME: margin lost
390 for (int i = 0; i < cuY-(new_lines-1); i++)
391 {
392 addHistLine(); scrollUp(0,1);
393 }
394 }
395
396 // make new image
397 Character* newimg = (Character*) malloc(new_lines*new_columns*sizeof(Character));
398
399 clearSelection();
400
401 // clear new image
402 for (int y = 0; y < new_lines; y++)
403 for (int x = 0; x < new_columns; x++)
404 {
405 newimg[y*new_columns+x].c = ' ';
406 newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
407 newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
408 newimg[y*new_columns+x].r = DEFAULT_RENDITION;
409 }
410 int cpy_lines = QMIN(new_lines, lines);
411 int cpy_columns = QMIN(new_columns,columns);
412 // copy to new image
413 for (int y = 0; y < cpy_lines; y++)
414 for (int x = 0; x < cpy_columns; x++)
415 {
416 newimg[y*new_columns+x].c = image[loc(x,y)].c;
417 newimg[y*new_columns+x].f = image[loc(x,y)].f;
418 newimg[y*new_columns+x].b = image[loc(x,y)].b;
419 newimg[y*new_columns+x].r = image[loc(x,y)].r;
420 }
421 free(image);
422 image = newimg;
423 lines = new_lines;
424 columns = new_columns;
425 cuX = QMIN(cuX,columns-1);
426 cuY = QMIN(cuY,lines-1);
427
428 // FIXME: try to keep values, evtl.
429 tmargin=0;
430 bmargin=lines-1;
431 initTabStops();
432 clearSelection();
433}
434
435/*
436 Clarifying rendition here and in TEWidget.
437
438 currently, TEWidget's color table is
439 0 1 2 .. 9 10 .. 17
440 dft_fg, dft_bg, dim 0..7, intensive 0..7
441
442 cu_fg, cu_bg contain values 0..8;
443 - 0 = default color
444 - 1..8 = ansi specified color
445
446 re_fg, re_bg contain values 0..17
447 due to the TEWidget's color table
448
449 rendition attributes are
450
451 attr widget screen
452 -------------- ------ ------
453 RE_UNDERLINE XX XX affects foreground only
454 RE_BLINK XX XX affects foreground only
455 RE_BOLD XX XX affects foreground only
456 RE_REVERSE -- XX
457 RE_TRANSPARENT XX -- affects background only
458 RE_INTENSIVE XX -- affects foreground only
459
460 Note that RE_BOLD is used in both widget
461 and screen rendition. Since xterm/vt102
462 is to poor to distinguish between bold
463 (which is a font attribute) and intensive
464 (which is a color attribute), we translate
465 this and RE_BOLD in falls eventually appart
466 into RE_BOLD and RE_INTENSIVE.
467*/
468
469void Screen::reverseRendition(Character* p)
470{ UINT8 f = p->f; UINT8 b = p->b;
471 p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
472}
473
474void Screen::effectiveRendition()
475// calculate rendition
476{
477 ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
478 if (cu_re & RE_REVERSE)
479 {
480 ef_fg = cu_bg;
481 ef_bg = cu_fg;
482 }
483 else
484 {
485 ef_fg = cu_fg;
486 ef_bg = cu_bg;
487 }
488 if (cu_re & RE_BOLD)
489 {
490 if (ef_fg < BASE_COLORS)
491 ef_fg += BASE_COLORS;
492 else
493 ef_fg -= BASE_COLORS;
494 }
495}
496
497/*!
498 returns the image.
499
500 Get the size of the image by \sa getLines and \sa getColumns.
501
502 NOTE that the image returned by this function must later be
503 freed.
504
505*/
506
507Character* Screen::getCookedImage()
508{ int x,y;
509 Character* merged = (Character*) malloc(lines*columns*sizeof(Character));
510 Character dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
511
512 for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
513 {
514 int len = QMIN(columns,hist.getLineLen(y+histCursor));
515 int yp = y*columns;
516 int yq = (y+histCursor)*columns;
517
518 hist.getCells(y+histCursor,0,len,merged+yp);
519 for (x = len; x < columns; x++) merged[yp+x] = dft;
520 for (x = 0; x < columns; x++)
521 { int p=x + yp; int q=x + yq;
522 if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
523 reverseRendition(&merged[p]); // for selection
524 }
525 }
526 if (lines >= hist.getLines()-histCursor)
527 {
528 for (y = (hist.getLines()-histCursor); y < lines ; y++)
529 {
530 int yp = y*columns;
531 int yq = (y+histCursor)*columns;
532 int yr = (y-hist.getLines()+histCursor)*columns;
533 for (x = 0; x < columns; x++)
534 { int p = x + yp; int q = x + yq; int r = x + yr;
535 merged[p] = image[r];
536 if ( q >= sel_TL && q <= sel_BR )
537 reverseRendition(&merged[p]); // for selection
538 }
539
540 }
541 }
542 // evtl. inverse display
543 if (getMode(MODE_Screen))
544 { int i,n = lines*columns;
545 for (i = 0; i < n; i++)
546 reverseRendition(&merged[i]); // for reverse display
547 }
548 if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
549 reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
550 return merged;
551}
552
553
554/*!
555*/
556
557void Screen::reset()
558{
559 setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
560 resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
561 resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
562 setMode(MODE_Cursor); // cursor visible
563 resetMode(MODE_Screen); // screen not inverse
564 resetMode(MODE_NewLine);
565
566 tmargin=0;
567 bmargin=lines-1;
568
569 setDefaultRendition();
570 saveCursor();
571
572 clear();
573}
574
575/*! Clear the entire screen and home the cursor.
576*/
577
578void Screen::clear()
579{
580 clearEntireScreen();
581 home();
582}
583
584/*! Moves the cursor left one column.
585*/
586
587void Screen::BackSpace()
588{
589 cuX = QMAX(0,cuX-1);
590 if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
591}
592
593/*!
594*/
595
596void Screen::Tabulate()
597{
598 // note that TAB is a format effector (does not write ' ');
599 cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
600}
601
602void Screen::clearTabStops()
603{
604 for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
605}
606
607void Screen::changeTabStop(bool set)
608{
609 if (cuX >= columns) return;
610 tabstops[cuX] = set;
611}
612
613void Screen::initTabStops()
614{
615 if (tabstops) free(tabstops);
616 tabstops = (bool*)malloc(columns*sizeof(bool));
617 // Arrg! The 1st tabstop has to be one longer than the other.
618 // i.e. the kids start counting from 0 instead of 1.
619 // Other programs might behave correctly. Be aware.
620 for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
621}
622
623/*!
624 This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
625 depending on the NewLine Mode (LNM). This mode also
626 affects the key sequence returned for newline ([CR]LF).
627*/
628
629void Screen::NewLine()
630{
631 if (getMode(MODE_NewLine)) Return();
632 index();
633}
634
635/*! put `c' literally onto the screen at the current cursor position.
636
637 VT100 uses the convention to produce an automatic newline (am)
638 with the *first* character that would fall onto the next line (xenl).
639*/
640
641void Screen::checkSelection(int from, int to)
642{
643 if (sel_begin == -1) return;
644 int scr_TL = loc(0, hist.getLines());
645 //Clear entire selection if it overlaps region [from, to]
646 if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
647 {
648 clearSelection();
649 }
650}
651
652void Screen::ShowCharacter(unsigned short c)
653{
654 // Note that VT100 does wrapping BEFORE putting the character.
655 // This has impact on the assumption of valid cursor positions.
656 // We indicate the fact that a newline has to be triggered by
657 // putting the cursor one right to the last column of the screen.
658
659 if (cuX >= columns)
660 {
661 if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
662 }
663
664 if (getMode(MODE_Insert)) insertChars(1);
665
666 int i = loc(cuX,cuY);
667
668 checkSelection(i, i); // check if selection is still valid.
669
670 image[i].c = c;
671 image[i].f = ef_fg;
672 image[i].b = ef_bg;
673 image[i].r = ef_re;
674
675 cuX += 1;
676}
677
678// Region commands -------------------------------------------------------------
679
680
681/*! scroll up `n' lines within current region.
682 The `n' new lines are cleared.
683 \sa setRegion \sa scrollDown
684*/
685
686void Screen::scrollUp(int from, int n)
687{
688 if (n <= 0 || from + n > bmargin) return;
689 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
690 moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
691 clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
692}
693
694/*! scroll down `n' lines within current region.
695 The `n' new lines are cleared.
696 \sa setRegion \sa scrollUp
697*/
698
699void Screen::scrollDown(int from, int n)
700{
701//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
702 if (n <= 0) return;
703 if (from > bmargin) return;
704 if (from + n > bmargin) n = bmargin - from;
705 moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
706 clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
707}
708
709/*! position the cursor to a specific line and column. */
710void Screen::setCursorYX(int y, int x)
711{
712 setCursorY(y); setCursorX(x);
713}
714
715/*! Set the cursor to x-th line. */
716
717void Screen::setCursorX(int x)
718{
719 if (x == 0) x = 1; // Default
720 x -= 1; // Adjust
721 cuX = QMAX(0,QMIN(columns-1, x));
722}
723
724/*! Set the cursor to y-th line. */
725
726void Screen::setCursorY(int y)
727{
728 if (y == 0) y = 1; // Default
729 y -= 1; // Adjust
730 cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
731}
732
733/*! set cursor to the `left upper' corner of the screen (1,1).
734*/
735
736void Screen::home()
737{
738 cuX = 0;
739 cuY = 0;
740}
741
742/*! set cursor to the begin of the current line.
743*/
744
745void Screen::Return()
746{
747 cuX = 0;
748}
749
750/*! returns the current cursor columns.
751*/
752
753int Screen::getCursorX()
754{
755 return cuX;
756}
757
758/*! returns the current cursor line.
759*/
760
761int Screen::getCursorY()
762{
763 return cuY;
764}
765
766// Erasing ---------------------------------------------------------------------
767
768/*! \section Erasing
769
770 This group of operations erase parts of the screen contents by filling
771 it with spaces colored due to the current rendition settings.
772
773 Althought the cursor position is involved in most of these operations,
774 it is never modified by them.
775*/
776
777/*! fill screen between (including) `loca' and `loce' with spaces.
778
779 This is an internal helper functions. The parameter types are internal
780 addresses of within the screen image and make use of the way how the
781 screen matrix is mapped to the image vector.
782*/
783
784void Screen::clearImage(int loca, int loce, char c)
785{ int i;
786 int scr_TL=loc(0,hist.getLines());
787 //FIXME: check positions
788
789 //Clear entire selection if it overlaps region to be moved...
790 if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
791 {
792 clearSelection();
793 }
794 for (i = loca; i <= loce; i++)
795 {
796 image[i].c = c;
797 image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
798 image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
799 image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
800 }
801}
802
803/*! move image between (including) `loca' and `loce' to 'dst'.
804
805 This is an internal helper functions. The parameter types are internal
806 addresses of within the screen image and make use of the way how the
807 screen matrix is mapped to the image vector.
808*/
809
810void Screen::moveImage(int dst, int loca, int loce)
811{
812//FIXME: check positions
813 if (loce < loca) {
814 // kdDebug() << "WARNING!!! call to Screen:moveImage with loce < loca!" << endl;
815 return;
816 }
817 memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(Character));
818}
819
820/*! clear from (including) current cursor position to end of screen.
821*/
822
823void Screen::clearToEndOfScreen()
824{
825 clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
826}
827
828/*! clear from begin of screen to (including) current cursor position.
829*/
830
831void Screen::clearToBeginOfScreen()
832{
833 clearImage(loc(0,0),loc(cuX,cuY),' ');
834}
835
836/*! clear the entire screen.
837*/
838
839void Screen::clearEntireScreen()
840{
841 clearImage(loc(0,0),loc(columns-1,lines-1),' ');
842}
843
844/*! fill screen with 'E'
845 This is to aid screen alignment
846*/
847
848void Screen::helpAlign()
849{
850 clearImage(loc(0,0),loc(columns-1,lines-1),'E');
851}
852
853/*! clear from (including) current cursor position to end of current cursor line.
854*/
855
856void Screen::clearToEndOfLine()
857{
858 clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
859}
860
861/*! clear from begin of current cursor line to (including) current cursor position.
862*/
863
864void Screen::clearToBeginOfLine()
865{
866 clearImage(loc(0,cuY),loc(cuX,cuY),' ');
867}
868
869/*! clears entire current cursor line
870*/
871
872void Screen::clearEntireLine()
873{
874 clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
875}
876
877// Rendition ------------------------------------------------------------------
878
879/*!
880 set rendition mode
881*/
882
883void Screen::setRendition(int re)
884{
885 cu_re |= re;
886 effectiveRendition();
887}
888
889/*!
890 reset rendition mode
891*/
892
893void Screen::resetRendition(int re)
894{
895 cu_re &= ~re;
896 effectiveRendition();
897}
898
899/*!
900*/
901
902void Screen::setDefaultRendition()
903{
904 setForeColorToDefault();
905 setBackColorToDefault();
906 cu_re = DEFAULT_RENDITION;
907 effectiveRendition();
908}
909
910/*!
911*/
912
913void Screen::setForeColor(int fgcolor)
914{
915 cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
916 effectiveRendition();
917}
918
919/*!
920*/
921
922void Screen::setBackColor(int bgcolor)
923{
924 cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
925 effectiveRendition();
926}
927
928/*!
929*/
930
931void Screen::setBackColorToDefault()
932{
933 cu_bg = DEFAULT_BACK_COLOR;
934 effectiveRendition();
935}
936
937/*!
938*/
939
940void Screen::setForeColorToDefault()
941{
942 cu_fg = DEFAULT_FORE_COLOR;
943 effectiveRendition();
944}
945
946/* ------------------------------------------------------------------------- */
947/* */
948/* Marking & Selection */
949/* */
950/* ------------------------------------------------------------------------- */
951
952void Screen::clearSelection()
953{
954 sel_BR = -1;
955 sel_TL = -1;
956 sel_begin = -1;
957}
958
959void Screen::setSelBeginXY(const int x, const int y)
960{
961 sel_begin = loc(x,y+histCursor) ;
962 sel_BR = sel_begin;
963 sel_TL = sel_begin;
964}
965
966void Screen::setSelExtentXY(const int x, const int y)
967{
968 if (sel_begin == -1) return;
969 int l = loc(x,y + histCursor);
970
971 if (l < sel_begin)
972 {
973 sel_TL = l;
974 sel_BR = sel_begin;
975 }
976 else
977 {
978 /* FIXME, HACK to correct for x too far to the right... */
979 if (( x == columns )|| (x == 0)) l--;
980
981 sel_TL = sel_begin;
982 sel_BR = l;
983 }
984}
985
986QString Screen::getSelText(const BOOL preserve_line_breaks)
987{
988 if (sel_begin == -1)
989 return QString::null; // Selection got clear while selecting.
990
991 int *m; // buffer to fill.
992 int s, d; // source index, dest. index.
993 int hist_BR = loc(0, hist.getLines());
994 int hY = sel_TL / columns;
995 int hX = sel_TL % columns;
996 int eol; // end of line
997
998 s = sel_TL; // tracks copy in source.
999
1000 // allocate buffer for maximum
1001 // possible size...
1002 d = (sel_BR - sel_TL) / columns + 1;
1003 m = new int[d * (columns + 1) + 2];
1004 d = 0;
1005
1006 while (s <= sel_BR)
1007 {
1008 if (s < hist_BR)
1009 { // get lines from hist.history
1010 // buffer.
1011 eol = hist.getLineLen(hY);
1012
1013 if ((hY == (sel_BR / columns)) &&
1014 (eol >= (sel_BR % columns)))
1015 {
1016 eol = sel_BR % columns + 1;
1017 }
1018
1019 while (hX < eol)
1020 {
1021 m[d++] = hist.getCell(hY, hX++).c;
1022 s++;
1023 }
1024
1025 if (s <= sel_BR)
1026 {
1027 // The line break handling
1028 // It's different from the screen
1029 // image case!
1030 if (eol % columns == 0)
1031 {
1032 // That's either a completely filled
1033 // line or an empty line
1034 if (eol == 0)
1035 {
1036 m[d++] = '\n';
1037 }
1038 else
1039 {
1040 // We have a full line.
1041 // FIXME: How can we handle newlines
1042 // at this position?!
1043 }
1044 }
1045 else if ((eol + 1) % columns == 0)
1046 {
1047 // FIXME: We don't know if this was a
1048 // space at the last position or a
1049 // short line!!
1050 m[d++] = ' ';
1051 }
1052 else
1053 {
1054 // We have a short line here. Put a
1055 // newline or a space into the
1056 // buffer.
1057 m[d++] = preserve_line_breaks ? '\n' : ' ';
1058 }
1059 }
1060
1061 hY++;
1062 hX = 0;
1063 s = hY * columns;
1064 }
1065 else
1066 { // or from screen image.
1067 eol = (s / columns + 1) * columns - 1;
1068
1069 if (eol < sel_BR)
1070 {
1071 while ((eol > s) &&
1072 isspace(image[eol - hist_BR].c))
1073 {
1074 eol--;
1075 }
1076 }
1077 else
1078 {
1079 eol = sel_BR;
1080 }
1081
1082 while (s <= eol)
1083 {
1084 m[d++] = image[s++ - hist_BR].c;
1085 }
1086
1087 if (eol < sel_BR)
1088 {
1089 // eol processing see below ...
1090 if ((eol + 1) % columns == 0)
1091 {
1092 if (image[eol - hist_BR].c == ' ')
1093 {
1094 m[d++] = ' ';
1095 }
1096 }
1097 else
1098 {
1099 m[d++] = ((preserve_line_breaks ||
1100 ((eol % columns) == 0)) ?
1101 '\n' : ' ');
1102 }
1103 }
1104
1105 s = (eol / columns + 1) * columns;
1106 }
1107 }
1108
1109 QChar* qc = new QChar[d];
1110
1111 for (int i = 0; i < d; i++)
1112 {
1113 qc[i] = m[i];
1114 }
1115
1116 QString res(qc, d);
1117
1118 delete m;
1119 delete qc;
1120
1121 return res;
1122}
1123/* above ... end of line processing for selection -- psilva
1124cases:
1125
11261) (eol+1)%columns == 0 --> the whole line is filled.
1127 If the last char is a space, insert (preserve) space. otherwise
1128 leave the text alone, so that words that are broken by linewrap
1129 are preserved.
1130
1131FIXME:
1132 * this suppresses \n for command output that is
1133 sized to the exact column width of the screen.
1134
11352) eol%columns == 0 --> blank line.
1136 insert a \n unconditionally.
1137 Do it either you would because you are in preserve_line_break mode,
1138 or because it's an ASCII paragraph delimiter, so even when
1139 not preserving line_breaks, you want to preserve paragraph breaks.
1140
1141 3) else --> partially filled line
1142 insert a \n in preserve line break mode, else a space
1143 The space prevents concatenation of the last word of one
1144 line with the first of the next.
1145
1146*/
1147
1148void Screen::addHistLine()
1149{
1150 assert(hasScroll() || histCursor == 0);
1151
1152 // add to hist buffer
1153 // we have to take care about scrolling, too...
1154
1155 if (hasScroll())
1156 { Character dft;
1157
1158 int end = columns-1;
1159 while (end >= 0 && image[end] == dft)
1160 end -= 1;
1161
1162 hist.addCells(image,end+1);
1163 hist.addLine();
1164
1165 // adjust history cursor
1166 histCursor += (hist.getLines()-1 == histCursor);
1167 }
1168
1169 if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
1170}
1171
1172void Screen::setHistCursor(int cursor)
1173{
1174 histCursor = cursor; //FIXME:rangecheck
1175}
1176
1177int Screen::getHistCursor()
1178{
1179 return histCursor;
1180}
1181
1182int Screen::getHistLines()
1183{
1184 return hist.getLines();
1185}
1186
1187void Screen::setScroll(bool on)
1188{
1189 histCursor = 0;
1190 clearSelection();
1191 hist.setScroll(on);
1192}
1193
1194bool Screen::hasScroll()
1195{
1196 return hist.hasScroll();
1197}
diff --git a/noncore/apps/opie-console/screen.h b/noncore/apps/opie-console/screen.h
new file mode 100644
index 0000000..cd7422a
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.h
@@ -0,0 +1,259 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [screen.h] Screen Data Type */
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#ifndef SCREEN_H
20#define SCREEN_H
21
22/*! \file
23*/
24
25#include "common.h"
26#include "history.h"
27
28#define MODE_Origin 0
29#define MODE_Wrap 1
30#define MODE_Insert 2
31#define MODE_Screen 3
32#define MODE_Cursor 4
33#define MODE_NewLine 5
34#define MODES_SCREEN 6
35
36/*!
37*/
38struct ScreenParm
39{
40 int mode[MODES_SCREEN];
41};
42
43
44class Screen
45{
46public:
47 Screen(int lines, int columns);
48 ~Screen();
49
50public: // these are all `Screen' operations
51 //
52 // VT100/2 Operations ------------------
53 //
54 // Cursor Movement
55 //
56 void cursorUp (int n);
57 void cursorDown (int n);
58 void cursorLeft (int n);
59 void cursorRight (int n);
60 void setCursorY (int y);
61 void setCursorX (int x);
62 void setCursorYX (int y, int x);
63 void setMargins (int t, int b);
64 //
65 // Cursor Movement with Scrolling
66 //
67 void NewLine ();
68 void NextLine ();
69 void index ();
70 void reverseIndex();
71 //
72 void Return ();
73 void BackSpace ();
74 void Tabulate ();
75 //
76 // Editing
77 //
78 void eraseChars (int n);
79 void deleteChars (int n);
80 void insertChars (int n);
81 void deleteLines (int n);
82 void insertLines (int n);
83 //
84 // -------------------------------------
85 //
86 void clearTabStops();
87 void changeTabStop(bool set);
88 //
89 void resetMode (int n);
90 void setMode (int n);
91 void saveMode (int n);
92 void restoreMode (int n);
93 //
94 void saveCursor ();
95 void restoreCursor();
96 //
97 // -------------------------------------
98 //
99 void clearEntireScreen();
100 void clearToEndOfScreen();
101 void clearToBeginOfScreen();
102 //
103 void clearEntireLine();
104 void clearToEndOfLine();
105 void clearToBeginOfLine();
106 //
107 void helpAlign ();
108 //
109 // -------------------------------------
110 //
111 void setRendition (int rendition);
112 void resetRendition(int rendition);
113 void setForeColor (int fgcolor);
114 void setBackColor (int bgcolor);
115 //
116 void setDefaultRendition();
117 void setForeColorToDefault();
118 void setBackColorToDefault();
119 //
120 // -------------------------------------
121 //
122 BOOL getMode (int n);
123 //
124 // only for report cursor position
125 //
126 int getCursorX();
127 int getCursorY();
128 //
129 // -------------------------------------
130 //
131 void clear();
132 void home();
133 void reset();
134 //
135 void ShowCharacter(unsigned short c);
136 //
137 void resizeImage(int new_lines, int new_columns);
138 //
139 Character* getCookedImage();
140
141 /*! return the number of lines. */
142 int getLines() { return lines; }
143 /*! return the number of columns. */
144 int getColumns() { return columns; }
145
146 /*! set the position of the history cursor. */
147 void setHistCursor(int cursor);
148 /*! return the position of the history cursor. */
149 int getHistCursor();
150
151 int getHistLines ();
152 void setScroll(bool on);
153 bool hasScroll();
154
155 //
156 // Selection
157 //
158 void setSelBeginXY(const int x, const int y);
159 void setSelExtentXY(const int x, const int y);
160 void clearSelection();
161 QString getSelText(const BOOL preserve_line_breaks);
162
163 void checkSelection(int from, int to);
164
165private: // helper
166
167 void clearImage(int loca, int loce, char c);
168 void moveImage(int dst, int loca, int loce);
169
170 void scrollUp(int from, int i);
171 void scrollDown(int from, int i);
172
173 void addHistLine();
174
175 void initTabStops();
176
177 void effectiveRendition();
178 void reverseRendition(Character* p);
179
180private:
181
182 /*
183 The state of the screen is more complex as one would
184 expect first. The screem does really do part of the
185 emulation providing state informations in form of modes,
186 margins, tabulators, cursor etc.
187
188 Even more unexpected are variables to save and restore
189 parts of the state.
190 */
191
192 // screen image ----------------
193
194 int lines;
195 int columns;
196 Character *image; // [lines][columns]
197
198 // history buffer ---------------
199
200 int histCursor; // display position relative to start of the history buffer
201 HistoryScroll hist;
202
203 // cursor location
204
205 int cuX;
206 int cuY;
207
208 // cursor color and rendition info
209
210 UINT8 cu_fg; // foreground
211 UINT8 cu_bg; // background
212 UINT8 cu_re; // rendition
213
214 // margins ----------------
215
216 int tmargin; // top margin
217 int bmargin; // bottom margin
218
219 // states ----------------
220
221 ScreenParm currParm;
222
223 // ----------------------------
224
225 bool* tabstops;
226
227 // selection -------------------
228
229 int sel_begin; // The first location selected.
230 int sel_TL; // TopLeft Location.
231 int sel_BR; // Bottom Right Location.
232
233 // effective colors and rendition ------------
234
235 UINT8 ef_fg; // These are derived from
236 UINT8 ef_bg; // the cu_* variables above
237 UINT8 ef_re; // to speed up operation
238
239 //
240 // save cursor, rendition & states ------------
241 //
242
243 // cursor location
244
245 int sa_cuX;
246 int sa_cuY;
247
248 // rendition info
249
250 UINT8 sa_cu_re;
251 UINT8 sa_cu_fg;
252 UINT8 sa_cu_bg;
253
254 // modes
255
256 ScreenParm saveParm;
257};
258
259#endif // TESCREEN_H
diff --git a/noncore/apps/opie-console/screen.o b/noncore/apps/opie-console/screen.o
new file mode 100644
index 0000000..b2d0420
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.o
Binary files differ
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}
diff --git a/noncore/apps/opie-console/vt102emulation.h b/noncore/apps/opie-console/vt102emulation.h
new file mode 100644
index 0000000..018835e
--- a/dev/null
+++ b/noncore/apps/opie-console/vt102emulation.h
@@ -0,0 +1,153 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEmuVt102.h] X 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/* Ported embedded-konsole to opie-terminal */
19 /* */
20/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
21 /* */
22/* -------------------------------------------------------------------------- */
23
24#ifndef VT102EMU_H
25#define VT102EMU_H
26
27#include "widget.h"
28#include "screen.h"
29#include "emulation_layer.h"
30#include <qtimer.h>
31#include <stdio.h>
32
33//
34
35#define MODE_AppScreen (MODES_SCREEN+0)
36#define MODE_AppCuKeys (MODES_SCREEN+1)
37#define MODE_AppKeyPad (MODES_SCREEN+2)
38#define MODE_Mouse1000 (MODES_SCREEN+3)
39#define MODE_Ansi (MODES_SCREEN+4)
40#define MODE_total (MODES_SCREEN+5)
41
42struct DECpar
43{
44 BOOL mode[MODE_total];
45};
46
47struct CharCodes
48{
49 // coding info
50 char charset[4]; //
51 int cu_cs; // actual charset.
52 bool graphic; // Some VT100 tricks
53 bool pound ; // Some VT100 tricks
54 bool sa_graphic; // saved graphic
55 bool sa_pound; // saved pound
56};
57
58class Vt102Emulation: public EmulationLayer
59{ Q_OBJECT
60
61public:
62
63 Vt102Emulation(Widget* gui);
64 ~Vt102Emulation();
65
66public slots: // signals incoming from Widget
67
68 void onKeyPress(QKeyEvent*);
69 void onMouse(int cb, int cx, int cy);
70
71signals:
72
73 void changeTitle(int,const QString&);
74 void prevSession();
75 void nextSession();
76
77public:
78
79 void reset();
80
81 /**
82 * receive a char from IOLayer
83 */
84 void onRcvChar(int cc);
85
86 /**
87 * sends a list of bytes to the IOLayer
88 */
89 void sendString(const QByteArray);
90
91 /**
92 * @deprecated use QByteArray instead
93 * see sendString() above
94 */
95 void sendString(const char *);
96
97public:
98
99 BOOL getMode (int m);
100
101 void setMode (int m);
102 void resetMode (int m);
103 void saveMode (int m);
104 void restoreMode(int m);
105 void resetModes();
106
107 void setConnect(bool r);
108
109private:
110
111 void resetToken();
112#define MAXPBUF 80
113 void pushToToken(int cc);
114 int pbuf[MAXPBUF]; //FIXME: overflow?
115 int ppos;
116#define MAXARGS 15
117 void addDigit(int dig);
118 void addArgument();
119 int argv[MAXARGS];
120 int argc;
121 void initTokenizer();
122 int tbl[256];
123
124 void scan_buffer_report(); //FIXME: rename
125 void ReportErrorToken(); //FIXME: rename
126
127 void tau(int code, int p, int q);
128 void XtermHack();
129
130 //
131
132 void reportTerminalType();
133 void reportStatus();
134 void reportAnswerBack();
135 void reportCursorPosition();
136 void reportTerminalParms(int p);
137
138protected:
139
140 unsigned short applyCharset(unsigned short c);
141 void setCharset(int n, int cs);
142 void useCharset(int n);
143 void setAndUseCharset(int n, int cs);
144 void saveCursor();
145 void restoreCursor();
146 void resetCharset(int scrno);
147 CharCodes charset[2];
148
149 DECpar currParm;
150 DECpar saveParm;
151};
152
153#endif // ifndef ANSIEMU_H
diff --git a/noncore/apps/opie-console/vt102emulation.o b/noncore/apps/opie-console/vt102emulation.o
new file mode 100644
index 0000000..009a4fa
--- a/dev/null
+++ b/noncore/apps/opie-console/vt102emulation.o
Binary files differ