Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

emulation_layer.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------- */
00002 /*                                                                            */
00003 /* [emulation_layer.cpp]        Terminal Emulation Decoder                    */
00004 /*                                                                            */
00005 /* -------------------------------------------------------------------------- */
00006 /*                                                                            */
00007 /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>            */
00008 /*                                                                            */
00009 /* This file is part of Konsole - an X terminal for KDE                       */
00010 /*                                                                            */
00011 /* -------------------------------------------------------------------------- */
00012 /*                                                                            */
00013 /* Ported Konsole to Qt/Embedded                                              */
00014 /*                                                                            */
00015 /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com>                  */
00016 /*                                                                            */
00017 /* -------------------------------------------------------------------------- */
00018 /*                                                                            */
00019 /* Modified to suit opie-console                                              */
00020 /*                                                                            */
00021 /* Copyright (C) 2002 by opie developers <opie@handhelds.org>                 */
00022 /*                                                                            */
00023 /* -------------------------------------------------------------------------- */
00024 
00074 /* FIXME
00075    - evtl. the bulk operations could be made more transparent.
00076 */
00077 
00078 #include "emulation_layer.h"
00079 #include <stdio.h>
00080 #include <stdlib.h>
00081 #include <unistd.h>
00082 
00083 
00084 /* ------------------------------------------------------------------------- */
00085 /*                                                                           */
00086 /*                               EmulationLayer                                  */
00087 /*                                                                           */
00088 /* ------------------------------------------------------------------------- */
00089 
00090 #define CNTL(c) ((c)-'@')
00091 
00095 EmulationLayer::EmulationLayer( WidgetLayer* gui )
00096 : decoder((QTextDecoder*)NULL)
00097 {
00098   this->gui = gui;
00099 
00100   screen[0] = new Screen(gui->lines(),gui->columns());
00101   screen[1] = new Screen(gui->lines(),gui->columns());
00102   scr = screen[0];
00103 
00104   bulk_nlcnt = 0; // reset bulk newline counter
00105   bulk_incnt = 0; // reset bulk counter
00106   connected  = FALSE;
00107 
00108   QObject::connect(&bulk_timer, SIGNAL( timeout() ), this, SLOT( showBulk() ) );
00109   QObject::connect(gui,SIGNAL( imageSizeChanged(int,int) ),
00110                    this,SLOT( onImageSizeChange(int,int) ) );
00111   QObject::connect(gui,SIGNAL( changedHistoryCursor(int) ),
00112                    this,SLOT( historyCursorChange(int) ) );
00113   QObject::connect(gui,SIGNAL( keyPressed(QKeyEvent*) ),
00114                    this,SLOT( onKeyPress(QKeyEvent*) ) );
00115   QObject::connect(gui,SIGNAL( selectionBegin(const int,const int) ),
00116                    this,SLOT( onSelectionBegin(const int,const int) ) );
00117   QObject::connect(gui,SIGNAL( selectionExtended(const int,const int) ),
00118                    this,SLOT( onSelectionExtend(const int,const int) ) );
00119   QObject::connect(gui,SIGNAL( selectionEnd(const bool) ),
00120                    this,SLOT( setSelection(const bool) ) );
00121   QObject::connect(gui,SIGNAL( selectionCleared() ),
00122                    this,SLOT( clearSelection() ) );
00123 }
00124 
00128 EmulationLayer::~EmulationLayer()
00129 {
00130   delete screen[0];
00131   delete screen[1];
00132   bulk_timer.stop();
00133 }
00134 
00138 void EmulationLayer::setScreen(int n)
00139 {
00140   scr = screen[n&1];
00141 }
00142 
00143 void EmulationLayer::setHistory(bool on)
00144 {
00145   screen[0]->setScroll(on);
00146   if (!connected) return;
00147   showBulk();
00148 }
00149 
00150 bool EmulationLayer::history()
00151 {
00152   return screen[0]->hasScroll();
00153 }
00154 
00155 void EmulationLayer::setCodec(int c)
00156 {
00157   //FIXME: check whether we have to free codec
00158   codec = c ? QTextCodec::codecForName("utf8")
00159             : QTextCodec::codecForLocale();
00160   if (decoder) delete decoder;
00161   decoder = codec->makeDecoder();
00162 }
00163 
00164 void EmulationLayer::setKeytrans(int no)
00165 {
00166   keytrans = KeyTrans::find(no);
00167 }
00168 
00169 void EmulationLayer::setKeytrans(const char * no)
00170 {
00171   keytrans = KeyTrans::find(no);
00172 }
00173 
00174 // Interpreting Codes ---------------------------------------------------------
00175 
00176 /*
00177    This section deals with decoding the incoming character stream.
00178    Decoding means here, that the stream is first seperated into `tokens'
00179    which are then mapped to a `meaning' provided as operations by the
00180    `Screen' class.
00181 */
00182 
00186 void EmulationLayer::onRcvChar(int c)
00187 // process application unicode input to terminal
00188 // this is a trivial scanner
00189 {
00190   c &= 0xff;
00191   switch (c)
00192   {
00193     case '\b'      : scr->BackSpace();                 break;
00194     case '\t'      : scr->Tabulate();                  break;
00195     case '\n'      : scr->NewLine();                   break;
00196     case '\r'      : scr->Return();                    break;
00197     case 0x07      : gui->bell();                      break;
00198     default        : scr->ShowCharacter(c);            break;
00199   };
00200 }
00201 
00202 /* ------------------------------------------------------------------------- */
00203 /*                                                                           */
00204 /*                             Keyboard Handling                             */
00205 /*                                                                           */
00206 /* ------------------------------------------------------------------------- */
00207 
00211 void EmulationLayer::onKeyPress( QKeyEvent* ev )
00212 {
00213   if (!connected) return; // someone else gets the keys
00214   if (scr->getHistCursor() != scr->getHistLines());
00215     scr->setHistCursor(scr->getHistLines());
00216   if (!ev->text().isEmpty())
00217   { // A block of text
00218     // Note that the text is proper unicode.
00219     // We should do a conversion here, but since this
00220     // routine will never be used, we simply emit plain ascii.
00221     sendString( ev->text().ascii() ); //,ev->text().length());
00222   }
00223   else if (ev->ascii()>0)
00224   {
00225     QByteArray c = QByteArray( 1 );
00226     c.at( 0 ) = ev->ascii();
00227     // ibot: qbytearray is emited not char*
00228     
00229     emit sndBlock( (QByteArray) c );
00230   }
00231 }
00232 
00233 // Unblocking, Byte to Unicode translation --------------------------------- --
00234 
00235 /*
00236    We are doing code conversion from locale to unicode first.
00237 */
00238 
00239 void EmulationLayer::onRcvBlock(const QByteArray &s )
00240 {
00241   bulkStart();
00242   bulk_incnt += 1;
00243   for (int i = 0; i < s.size(); i++)
00244   {
00245     //TODO: ibot: maybe decoding qbytearray to unicode in io_layer? 
00246     QString result = decoder->toUnicode(&s[i],1);
00247     int reslen = result.length();
00248     for (int j = 0; j < reslen; j++)
00249       onRcvChar(result[j].unicode());
00250     if (s[i] == '\n') bulkNewline();
00251   }
00252   bulkEnd();
00253 }
00254 
00255 // Selection --------------------------------------------------------------- --
00256 
00257 void EmulationLayer::onSelectionBegin(const int x, const int y) {
00258   if (!connected) return;
00259   scr->setSelBeginXY(x,y);
00260   showBulk();
00261 }
00262 
00263 void EmulationLayer::onSelectionExtend(const int x, const int y) {
00264   if (!connected) return;
00265   scr->setSelExtentXY(x,y);
00266   showBulk();
00267 }
00268 
00269 void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
00270   if (!connected) return;
00271   QString t = scr->getSelText(preserve_line_breaks);
00272   if (!t.isNull()) gui->setSelection(t);
00273 }
00274 
00275 void EmulationLayer::clearSelection() {
00276   if (!connected) return;
00277   scr->clearSelection();
00278   showBulk();
00279 }
00280 
00281 // Refreshing -------------------------------------------------------------- --
00282 
00283 #define BULK_TIMEOUT 20
00284 
00289 void EmulationLayer::bulkNewline()
00290 {
00291   bulk_nlcnt += 1;
00292   bulk_incnt = 0;  // reset bulk counter since `nl' rule applies
00293 }
00294 
00298 void EmulationLayer::showBulk()
00299 {
00300   bulk_nlcnt = 0;                       // reset bulk newline counter
00301   bulk_incnt = 0;                       // reset bulk counter
00302   if (connected)
00303   {
00304     QArray<Character> image = scr->getCookedImage();    // get the image
00305     gui->setImage(image,
00306                   scr->getLines(),
00307                   scr->getColumns());     // actual refresh
00308     delete image;
00309     //FIXME: check that we do not trigger other draw event here.
00310     gui->setScroll(scr->getHistCursor(),scr->getHistLines());
00311   }
00312 }
00313 
00314 void EmulationLayer::bulkStart()
00315 {
00316   if (bulk_timer.isActive()) bulk_timer.stop();
00317 }
00318 
00319 void EmulationLayer::bulkEnd()
00320 {
00321   if ( bulk_nlcnt > gui->lines() || bulk_incnt > 20 )
00322     showBulk();                         // resets bulk_??cnt to 0, too.
00323   else
00324     bulk_timer.start(BULK_TIMEOUT,TRUE);
00325 }
00326 
00327 void EmulationLayer::setConnect(bool c)
00328 {
00329   connected = c;
00330   if ( connected)
00331   {
00332     onImageSizeChange(gui->lines(), gui->columns());
00333     showBulk();
00334   }
00335   else
00336   {
00337     scr->clearSelection();
00338   }
00339 }
00340 
00341 // ---------------------------------------------------------------------------
00342 
00349 void EmulationLayer::onImageSizeChange(int lines, int columns)
00350 {
00351   if (!connected) return;
00352   screen[0]->resizeImage(lines,columns);
00353   screen[1]->resizeImage(lines,columns);
00354   showBulk();
00355   emit ImageSizeChanged(lines,columns);   // propagate event to serial line
00356 }
00357 
00358 void EmulationLayer::onHistoryCursorChange(int cursor)
00359 {
00360   if (!connected) return;
00361   scr->setHistCursor(cursor);
00362   showBulk();
00363 }
00364 
00365 void EmulationLayer::setColumns(int columns)
00366 {
00367   //FIXME: this goes strange ways.
00368   //       Can we put this straight or explain it at least?
00369   emit changeColumns(columns);
00370 }
00371 

Generated on Sat Nov 5 16:16:49 2005 for OPIE by  doxygen 1.4.2