summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-console/emulation_layer.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-console/emulation_layer.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/emulation_layer.cpp24
1 files changed, 12 insertions, 12 deletions
diff --git a/noncore/apps/opie-console/emulation_layer.cpp b/noncore/apps/opie-console/emulation_layer.cpp
index 2bef801..fd30ad7 100644
--- a/noncore/apps/opie-console/emulation_layer.cpp
+++ b/noncore/apps/opie-console/emulation_layer.cpp
@@ -1,312 +1,312 @@
1/* -------------------------------------------------------------------------- */ 1/* -------------------------------------------------------------------------- */
2/* */ 2/* */
3/* [emulation_layer.cpp] Terminal Emulation Decoder */ 3/* [emulation_layer.cpp] Terminal Emulation Decoder */
4/* */ 4/* */
5/* -------------------------------------------------------------------------- */ 5/* -------------------------------------------------------------------------- */
6/* */ 6/* */
7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ 7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
8/* */ 8/* */
9/* This file is part of Konsole - an X terminal for KDE */ 9/* This file is part of Konsole - an X terminal for KDE */
10/* */ 10/* */
11/* -------------------------------------------------------------------------- */ 11/* -------------------------------------------------------------------------- */
12 /* */ 12 /* */
13/* Ported Konsole to Qt/Embedded */ 13/* Ported Konsole to Qt/Embedded */
14 /* */ 14 /* */
15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ 15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
16 /* */ 16 /* */
17/* -------------------------------------------------------------------------- */ 17/* -------------------------------------------------------------------------- */
18 /* */ 18 /* */
19/* Modified to suit opie-console */ 19/* Modified to suit opie-console */
20 /* */ 20 /* */
21/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */ 21/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
22 /* */ 22 /* */
23/* -------------------------------------------------------------------------- */ 23/* -------------------------------------------------------------------------- */
24 24
25/*! \class EmulationLayer 25/*! \class EmulationLayer
26 26
27 \brief Mediator between Widget and Screen. 27 \brief Mediator between Widget and Screen.
28 28
29 This class is responsible to scan the escapes sequences of the terminal 29 This class is responsible to scan the escapes sequences of the terminal
30 emulation and to map it to their corresponding semantic complements. 30 emulation and to map it to their corresponding semantic complements.
31 Thus this module knows mainly about decoding escapes sequences and 31 Thus this module knows mainly about decoding escapes sequences and
32 is a stateless device w.r.t. the semantics. 32 is a stateless device w.r.t. the semantics.
33 33
34 It is also responsible to refresh the Widget by certain rules. 34 It is also responsible to refresh the Widget by certain rules.
35 35
36 \sa Widget \sa Screen 36 \sa Widget \sa Screen
37 37
38 \par A note on refreshing 38 \par A note on refreshing
39 39
40 Although the modifications to the current screen image could immediately 40 Although the modifications to the current screen image could immediately
41 be propagated via `Widget' to the graphical surface, we have chosen 41 be propagated via `Widget' to the graphical surface, we have chosen
42 another way here. 42 another way here.
43 43
44 The reason for doing so is twofold. 44 The reason for doing so is twofold.
45 45
46 First, experiments show that directly displaying the operation results 46 First, experiments show that directly displaying the operation results
47 in slowing down the overall performance of emulations. Displaying 47 in slowing down the overall performance of emulations. Displaying
48 individual characters using X11 creates a lot of overhead. 48 individual characters using X11 creates a lot of overhead.
49 49
50 Second, by using the following refreshing method, the screen operations 50 Second, by using the following refreshing method, the screen operations
51 can be completely separated from the displaying. This greatly simplifies 51 can be completely separated from the displaying. This greatly simplifies
52 the programmer's task of coding and maintaining the screen operations, 52 the programmer's task of coding and maintaining the screen operations,
53 since one need not worry about differential modifications on the 53 since one need not worry about differential modifications on the
54 display affecting the operation of concern. 54 display affecting the operation of concern.
55 55
56 We use a refreshing algorithm here that has been adoped from rxvt/kvt. 56 We use a refreshing algorithm here that has been adoped from rxvt/kvt.
57 57
58 By this, refreshing is driven by a timer, which is (re)started whenever 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'. 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 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 61 refresh. This rule suits both bulk display operation as done by curses as
62 well as individual characters typed. 62 well as individual characters typed.
63 (BULK_TIMEOUT < 1000 / max characters received from keyboard per second). 63 (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
64 64
65 Additionally, we trigger refreshing by newlines comming in to make visual 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 66 snapshots of lists as produced by `cat', `ls' and likely programs, thereby
67 producing the illusion of a permanent and immediate display operation. 67 producing the illusion of a permanent and immediate display operation.
68 68
69 As a sort of catch-all needed for cases where none of the above 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 70 conditions catch, the screen refresh is also triggered by a count
71 of incoming bulks (`bulk_incnt'). 71 of incoming bulks (`bulk_incnt').
72*/ 72*/
73 73
74/* FIXME 74/* FIXME
75 - evtl. the bulk operations could be made more transparent. 75 - evtl. the bulk operations could be made more transparent.
76*/ 76*/
77 77
78#include "emulation_layer.h" 78#include "emulation_layer.h"
79#include <stdio.h> 79#include <stdio.h>
80#include <stdlib.h> 80#include <stdlib.h>
81#include <unistd.h> 81#include <unistd.h>
82 82
83 83
84/* ------------------------------------------------------------------------- */ 84/* ------------------------------------------------------------------------- */
85/* */ 85/* */
86/* EmulationLayer */ 86/* EmulationLayer */
87/* */ 87/* */
88/* ------------------------------------------------------------------------- */ 88/* ------------------------------------------------------------------------- */
89 89
90#define CNTL(c) ((c)-'@') 90#define CNTL(c) ((c)-'@')
91 91
92/*! 92/*!
93*/ 93*/
94 94
95EmulationLayer::EmulationLayer( WidgetLayer* gui ) 95EmulationLayer::EmulationLayer( WidgetLayer* gui )
96: decoder((QTextDecoder*)NULL) 96: decoder((QTextDecoder*)NULL)
97{ 97{
98 this->gui = gui; 98 this->gui = gui;
99 99
100 screen[0] = new Screen(gui->lines(),gui->columns()); 100 screen[0] = new Screen(gui->lines(),gui->columns());
101 screen[1] = new Screen(gui->lines(),gui->columns()); 101 screen[1] = new Screen(gui->lines(),gui->columns());
102 scr = screen[0]; 102 scr = screen[0];
103 103
104 bulk_nlcnt = 0; // reset bulk newline counter 104 bulk_nlcnt = 0; // reset bulk newline counter
105 bulk_incnt = 0; // reset bulk counter 105 bulk_incnt = 0; // reset bulk counter
106 connected = FALSE; 106 connected = FALSE;
107 107
108 QObject::connect(&bulk_timer, SIGNAL( timeout() ), this, SLOT( showBulk() ) ); 108 QObject::connect(&bulk_timer, SIGNAL( timeout() ), this, SLOT( showBulk() ) );
109 QObject::connect(gui,SIGNAL( imageSizeChanged( int, int ) ), 109 QObject::connect(gui,SIGNAL( imageSizeChanged(int,int) ),
110 this,SLOT( onImageSizeChange( int, int ) ) ); 110 this,SLOT( onImageSizeChange(int,int) ) );
111 QObject::connect(gui,SIGNAL( changedHistoryCursor( int ) ), 111 QObject::connect(gui,SIGNAL( changedHistoryCursor(int) ),
112 this,SLOT( historyCursorChange( int ) ) ); 112 this,SLOT( historyCursorChange(int) ) );
113 QObject::connect(gui,SIGNAL( keyPressed( QKeyEvent* ) ), 113 QObject::connect(gui,SIGNAL( keyPressed(QKeyEvent*) ),
114 this,SLOT( onKeyPress( QKeyEvent* ) ) ); 114 this,SLOT( onKeyPress(QKeyEvent*) ) );
115 QObject::connect(gui,SIGNAL( selectionBegin( const int, const int) ), 115 QObject::connect(gui,SIGNAL( selectionBegin(const int,const int) ),
116 this,SLOT( onSelectionBegin( const int, const int ) ) ); 116 this,SLOT( onSelectionBegin(const int,const int) ) );
117 QObject::connect(gui,SIGNAL( selectionExtended( const int, const int ) ), 117 QObject::connect(gui,SIGNAL( selectionExtended(const int,const int) ),
118 this,SLOT( onSelectionExtend( const int,const int ) ) ); 118 this,SLOT( onSelectionExtend(const int,const int) ) );
119 QObject::connect(gui,SIGNAL( selectionEnd( const bool ) ), 119 QObject::connect(gui,SIGNAL( selectionEnd(const bool) ),
120 this,SLOT( setSelection( const bool ) ) ); 120 this,SLOT( setSelection(const bool) ) );
121 QObject::connect(gui,SIGNAL( selectionCleared() ), 121 QObject::connect(gui,SIGNAL( selectionCleared() ),
122 this,SLOT( clearSelection() ) ); 122 this,SLOT( clearSelection() ) );
123} 123}
124 124
125/*! 125/*!
126*/ 126*/
127 127
128EmulationLayer::~EmulationLayer() 128EmulationLayer::~EmulationLayer()
129{ 129{
130 delete screen[0]; 130 delete screen[0];
131 delete screen[1]; 131 delete screen[1];
132 bulk_timer.stop(); 132 bulk_timer.stop();
133} 133}
134 134
135/*! change between primary and alternate screen 135/*! change between primary and alternate screen
136*/ 136*/
137 137
138void EmulationLayer::setScreen(int n) 138void EmulationLayer::setScreen(int n)
139{ 139{
140 scr = screen[n&1]; 140 scr = screen[n&1];
141} 141}
142 142
143void EmulationLayer::setHistory(bool on) 143void EmulationLayer::setHistory(bool on)
144{ 144{
145 screen[0]->setScroll(on); 145 screen[0]->setScroll(on);
146 if (!connected) return; 146 if (!connected) return;
147 showBulk(); 147 showBulk();
148} 148}
149 149
150bool EmulationLayer::history() 150bool EmulationLayer::history()
151{ 151{
152 return screen[0]->hasScroll(); 152 return screen[0]->hasScroll();
153} 153}
154 154
155void EmulationLayer::setCodec(int c) 155void EmulationLayer::setCodec(int c)
156{ 156{
157 //FIXME: check whether we have to free codec 157 //FIXME: check whether we have to free codec
158 codec = c ? QTextCodec::codecForName("utf8") 158 codec = c ? QTextCodec::codecForName("utf8")
159 : QTextCodec::codecForLocale(); 159 : QTextCodec::codecForLocale();
160 if (decoder) delete decoder; 160 if (decoder) delete decoder;
161 decoder = codec->makeDecoder(); 161 decoder = codec->makeDecoder();
162} 162}
163 163
164void EmulationLayer::setKeytrans(int no) 164void EmulationLayer::setKeytrans(int no)
165{ 165{
166 keytrans = KeyTrans::find(no); 166 keytrans = KeyTrans::find(no);
167} 167}
168 168
169void EmulationLayer::setKeytrans(const char * no) 169void EmulationLayer::setKeytrans(const char * no)
170{ 170{
171 keytrans = KeyTrans::find(no); 171 keytrans = KeyTrans::find(no);
172} 172}
173 173
174// Interpreting Codes --------------------------------------------------------- 174// Interpreting Codes ---------------------------------------------------------
175 175
176/* 176/*
177 This section deals with decoding the incoming character stream. 177 This section deals with decoding the incoming character stream.
178 Decoding means here, that the stream is first seperated into `tokens' 178 Decoding means here, that the stream is first seperated into `tokens'
179 which are then mapped to a `meaning' provided as operations by the 179 which are then mapped to a `meaning' provided as operations by the
180 `Screen' class. 180 `Screen' class.
181*/ 181*/
182 182
183/*! 183/*!
184*/ 184*/
185 185
186void EmulationLayer::onRcvChar(int c) 186void EmulationLayer::onRcvChar(int c)
187// process application unicode input to terminal 187// process application unicode input to terminal
188// this is a trivial scanner 188// this is a trivial scanner
189{ 189{
190 c &= 0xff; 190 c &= 0xff;
191 switch (c) 191 switch (c)
192 { 192 {
193 case '\b' : scr->BackSpace(); break; 193 case '\b' : scr->BackSpace(); break;
194 case '\t' : scr->Tabulate(); break; 194 case '\t' : scr->Tabulate(); break;
195 case '\n' : scr->NewLine(); break; 195 case '\n' : scr->NewLine(); break;
196 case '\r' : scr->Return(); break; 196 case '\r' : scr->Return(); break;
197 case 0x07 : gui->bell(); break; 197 case 0x07 : gui->bell(); break;
198 default : scr->ShowCharacter(c); break; 198 default : scr->ShowCharacter(c); break;
199 }; 199 };
200} 200}
201 201
202/* ------------------------------------------------------------------------- */ 202/* ------------------------------------------------------------------------- */
203/* */ 203/* */
204/* Keyboard Handling */ 204/* Keyboard Handling */
205/* */ 205/* */
206/* ------------------------------------------------------------------------- */ 206/* ------------------------------------------------------------------------- */
207 207
208/*! 208/*!
209*/ 209*/
210 210
211void EmulationLayer::onKeyPress( QKeyEvent* ev ) 211void EmulationLayer::onKeyPress( QKeyEvent* ev )
212{ 212{
213 if (!connected) return; // someone else gets the keys 213 if (!connected) return; // someone else gets the keys
214 if (scr->getHistCursor() != scr->getHistLines()); 214 if (scr->getHistCursor() != scr->getHistLines());
215 scr->setHistCursor(scr->getHistLines()); 215 scr->setHistCursor(scr->getHistLines());
216 if (!ev->text().isEmpty()) 216 if (!ev->text().isEmpty())
217 { // A block of text 217 { // A block of text
218 // Note that the text is proper unicode. 218 // Note that the text is proper unicode.
219 // We should do a conversion here, but since this 219 // We should do a conversion here, but since this
220 // routine will never be used, we simply emit plain ascii. 220 // routine will never be used, we simply emit plain ascii.
221 sendString( ev->text().ascii() ); //,ev->text().length()); 221 sendString( ev->text().ascii() ); //,ev->text().length());
222 } 222 }
223 else if (ev->ascii()>0) 223 else if (ev->ascii()>0)
224 { 224 {
225 QByteArray c = QByteArray( 1 ); 225 QByteArray c = QByteArray( 1 );
226 c.at( 0 ) = ev->ascii(); 226 c.at( 0 ) = ev->ascii();
227 // ibot: qbytearray is emited not char* 227 // ibot: qbytearray is emited not char*
228 228
229 emit sndBlock( (QByteArray) c ); 229 emit sndBlock( (QByteArray) c );
230 } 230 }
231} 231}
232 232
233// Unblocking, Byte to Unicode translation --------------------------------- -- 233// Unblocking, Byte to Unicode translation --------------------------------- --
234 234
235/* 235/*
236 We are doing code conversion from locale to unicode first. 236 We are doing code conversion from locale to unicode first.
237*/ 237*/
238 238
239void EmulationLayer::onRcvBlock(const QByteArray &s ) 239void EmulationLayer::onRcvBlock(const QByteArray &s )
240{ 240{
241 bulkStart(); 241 bulkStart();
242 bulk_incnt += 1; 242 bulk_incnt += 1;
243 for (int i = 0; i < s.size(); i++) 243 for (int i = 0; i < s.size(); i++)
244 { 244 {
245 //TODO: ibot: maybe decoding qbytearray to unicode in io_layer? 245 //TODO: ibot: maybe decoding qbytearray to unicode in io_layer?
246 QString result = decoder->toUnicode(&s[i],1); 246 QString result = decoder->toUnicode(&s[i],1);
247 int reslen = result.length(); 247 int reslen = result.length();
248 for (int j = 0; j < reslen; j++) 248 for (int j = 0; j < reslen; j++)
249 onRcvChar(result[j].unicode()); 249 onRcvChar(result[j].unicode());
250 if (s[i] == '\n') bulkNewline(); 250 if (s[i] == '\n') bulkNewline();
251 } 251 }
252 bulkEnd(); 252 bulkEnd();
253} 253}
254 254
255// Selection --------------------------------------------------------------- -- 255// Selection --------------------------------------------------------------- --
256 256
257void EmulationLayer::onSelectionBegin(const int x, const int y) { 257void EmulationLayer::onSelectionBegin(const int x, const int y) {
258 if (!connected) return; 258 if (!connected) return;
259 scr->setSelBeginXY(x,y); 259 scr->setSelBeginXY(x,y);
260 showBulk(); 260 showBulk();
261} 261}
262 262
263void EmulationLayer::onSelectionExtend(const int x, const int y) { 263void EmulationLayer::onSelectionExtend(const int x, const int y) {
264 if (!connected) return; 264 if (!connected) return;
265 scr->setSelExtentXY(x,y); 265 scr->setSelExtentXY(x,y);
266 showBulk(); 266 showBulk();
267} 267}
268 268
269void EmulationLayer::setSelection(const BOOL preserve_line_breaks) { 269void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
270 if (!connected) return; 270 if (!connected) return;
271 QString t = scr->getSelText(preserve_line_breaks); 271 QString t = scr->getSelText(preserve_line_breaks);
272 if (!t.isNull()) gui->setSelection(t); 272 if (!t.isNull()) gui->setSelection(t);
273} 273}
274 274
275void EmulationLayer::clearSelection() { 275void EmulationLayer::clearSelection() {
276 if (!connected) return; 276 if (!connected) return;
277 scr->clearSelection(); 277 scr->clearSelection();
278 showBulk(); 278 showBulk();
279} 279}
280 280
281// Refreshing -------------------------------------------------------------- -- 281// Refreshing -------------------------------------------------------------- --
282 282
283#define BULK_TIMEOUT 20 283#define BULK_TIMEOUT 20
284 284
285/*! 285/*!
286 called when \n comes in. Evtl. triggers showBulk at endBulk 286 called when \n comes in. Evtl. triggers showBulk at endBulk
287*/ 287*/
288 288
289void EmulationLayer::bulkNewline() 289void EmulationLayer::bulkNewline()
290{ 290{
291 bulk_nlcnt += 1; 291 bulk_nlcnt += 1;
292 bulk_incnt = 0; // reset bulk counter since `nl' rule applies 292 bulk_incnt = 0; // reset bulk counter since `nl' rule applies
293} 293}
294 294
295/*! 295/*!
296*/ 296*/
297 297
298void EmulationLayer::showBulk() 298void EmulationLayer::showBulk()
299{ 299{
300 bulk_nlcnt = 0; // reset bulk newline counter 300 bulk_nlcnt = 0; // reset bulk newline counter
301 bulk_incnt = 0; // reset bulk counter 301 bulk_incnt = 0; // reset bulk counter
302 if (connected) 302 if (connected)
303 { 303 {
304 QArray<Character> image = scr->getCookedImage(); // get the image 304 QArray<Character> image = scr->getCookedImage(); // get the image
305 gui->setImage(image, 305 gui->setImage(image,
306 scr->getLines(), 306 scr->getLines(),
307 scr->getColumns()); // actual refresh 307 scr->getColumns()); // actual refresh
308 delete image; 308 delete image;
309 //FIXME: check that we do not trigger other draw event here. 309 //FIXME: check that we do not trigger other draw event here.
310 gui->setScroll(scr->getHistCursor(),scr->getHistLines()); 310 gui->setScroll(scr->getHistCursor(),scr->getHistLines());
311 } 311 }
312} 312}