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

TEmulation.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------- */
00002 /*                                                                            */
00003 /* [TEmulation.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 
00068 /* FIXME
00069    - evtl. the bulk operations could be made more transparent.
00070 */
00071 
00072 #include "TEmulation.h"
00073 
00074 /* STD */
00075 #include <stdio.h>
00076 #include <stdlib.h>
00077 #include <unistd.h>
00078 
00079 
00080 /* ------------------------------------------------------------------------- */
00081 /*                                                                           */
00082 /*                               TEmulation                                  */
00083 /*                                                                           */
00084 /* ------------------------------------------------------------------------- */
00085 
00086 #define CNTL(c) ((c)-'@')
00087 
00091 TEmulation::TEmulation(TEWidget* gui)
00092 : decoder((QTextDecoder*)NULL)
00093 {
00094   this->gui = gui;
00095 
00096   screen[0] = new TEScreen(gui->Lines(),gui->Columns());
00097   screen[1] = new TEScreen(gui->Lines(),gui->Columns());
00098   scr = screen[0];
00099 
00100   bulk_nlcnt = 0; // reset bulk newline counter
00101   bulk_incnt = 0; // reset bulk counter
00102   connected  = FALSE;
00103 
00104   QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
00105   QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)),
00106                    this,SLOT(onImageSizeChange(int,int)));
00107   QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
00108                    this,SLOT(onHistoryCursorChange(int)));
00109   QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
00110                    this,SLOT(onKeyPress(QKeyEvent*)));
00111   QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)),
00112                    this,SLOT(onSelectionBegin(const int,const int)) );
00113   QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
00114                    this,SLOT(onSelectionExtend(const int,const int)) );
00115   QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)),
00116                    this,SLOT(setSelection(const BOOL)) );
00117   QObject::connect(gui,SIGNAL(clearSelectionSignal()),
00118                    this,SLOT(clearSelection()) );
00119 }
00120 
00124 TEmulation::~TEmulation()
00125 {
00126   delete screen[0];
00127   delete screen[1];
00128   bulk_timer.stop();
00129 }
00130 
00134 void TEmulation::setScreen(int n)
00135 {
00136   scr = screen[n&1];
00137 }
00138 
00139 void TEmulation::setHistory(bool on)
00140 {
00141   screen[0]->setScroll(on);
00142   if (!connected) return;
00143   showBulk();
00144 }
00145 
00146 bool TEmulation::history()
00147 {
00148   return screen[0]->hasScroll();
00149 }
00150 
00151 void TEmulation::setCodec(int c)
00152 {
00153   //FIXME: check whether we have to free codec
00154   codec = c ? QTextCodec::codecForName("utf8")
00155             : QTextCodec::codecForLocale();
00156   if (decoder) delete decoder;
00157   decoder = codec->makeDecoder();
00158 }
00159 
00160 void TEmulation::setKeytrans(int no)
00161 {
00162   keytrans = KeyTrans::find(no);
00163 }
00164 
00165 void TEmulation::setKeytrans(const char * no)
00166 {
00167   keytrans = KeyTrans::find(no);
00168 }
00169 
00170 // Interpreting Codes ---------------------------------------------------------
00171 
00172 /*
00173    This section deals with decoding the incoming character stream.
00174    Decoding means here, that the stream is first seperated into `tokens'
00175    which are then mapped to a `meaning' provided as operations by the
00176    `Screen' class.
00177 */
00178 
00182 void TEmulation::onRcvChar(int c)
00183 // process application unicode input to terminal
00184 // this is a trivial scanner
00185 {
00186   c &= 0xff;
00187   switch (c)
00188   {
00189     case '\b'      : scr->BackSpace();                 break;
00190     case '\t'      : scr->Tabulate();                  break;
00191     case '\n'      : scr->NewLine();                   break;
00192     case '\r'      : scr->Return();                    break;
00193     case 0x07      : gui->Bell();                      break;
00194     default        : scr->ShowCharacter(c);            break;
00195   };
00196 }
00197 
00198 /* ------------------------------------------------------------------------- */
00199 /*                                                                           */
00200 /*                             Keyboard Handling                             */
00201 /*                                                                           */
00202 /* ------------------------------------------------------------------------- */
00203 
00207 void TEmulation::onKeyPress( QKeyEvent* ev )
00208 {
00209   if (!connected) return; // someone else gets the keys
00210   if (scr->getHistCursor() != scr->getHistLines());
00211     scr->setHistCursor(scr->getHistLines());
00212   if (!ev->text().isEmpty())
00213   { // A block of text
00214     // Note that the text is proper unicode.
00215     // We should do a conversion here, but since this
00216     // routine will never be used, we simply emit plain ascii.
00217     emit sndBlock(ev->text().ascii(),ev->text().length());
00218   }
00219   else if (ev->ascii()>0)
00220   { unsigned char c[1];
00221     c[0] = ev->ascii();
00222     emit sndBlock((char*)c,1);
00223   }
00224 }
00225 
00226 // Unblocking, Byte to Unicode translation --------------------------------- --
00227 
00228 /*
00229    We are doing code conversion from locale to unicode first.
00230 */
00231 
00232 void TEmulation::onRcvBlock(const char *s, int len)
00233 {
00234   bulkStart();
00235   bulk_incnt += 1;
00236   for (int i = 0; i < len; i++)
00237   {
00238     QString result = decoder->toUnicode(&s[i],1);
00239     int reslen = result.length();
00240     for (int j = 0; j < reslen; j++)
00241       onRcvChar(result[j].unicode());
00242     if (s[i] == '\n') bulkNewline();
00243   }
00244   bulkEnd();
00245 }
00246 
00247 // Selection --------------------------------------------------------------- --
00248 
00249 void TEmulation::onSelectionBegin(const int x, const int y) {
00250   if (!connected) return;
00251   scr->setSelBeginXY(x,y);
00252   showBulk();
00253 }
00254 
00255 void TEmulation::onSelectionExtend(const int x, const int y) {
00256   if (!connected) return;
00257   scr->setSelExtentXY(x,y);
00258   showBulk();
00259 }
00260 
00261 void TEmulation::setSelection(const BOOL preserve_line_breaks) {
00262   if (!connected) return;
00263   QString t = scr->getSelText(preserve_line_breaks);
00264   if (!t.isNull()) gui->setSelection(t);
00265 }
00266 
00267 void TEmulation::clearSelection() {
00268   if (!connected) return;
00269   scr->clearSelection();
00270   showBulk();
00271 }
00272 void TEmulation::streamHistory(QTextStream* stream) {
00273   *stream << scr->getHistory();
00274 }
00275 // Refreshing -------------------------------------------------------------- --
00276 
00277 #define BULK_TIMEOUT 20
00278 
00283 void TEmulation::bulkNewline()
00284 {
00285   bulk_nlcnt += 1;
00286   bulk_incnt = 0;  // reset bulk counter since `nl' rule applies
00287 }
00288 
00292 void TEmulation::showBulk()
00293 {
00294   bulk_nlcnt = 0;                       // reset bulk newline counter
00295   bulk_incnt = 0;                       // reset bulk counter
00296   if (connected)
00297   {
00298     ca* image = scr->getCookedImage();    // get the image
00299     gui->setImage(image,
00300                   scr->getLines(),
00301                   scr->getColumns());     // actual refresh
00302     free(image);
00303     //FIXME: check that we do not trigger other draw event here.
00304     gui->setScroll(scr->getHistCursor(),scr->getHistLines());
00305   }
00306 }
00307 
00308 void TEmulation::bulkStart()
00309 {
00310   if (bulk_timer.isActive()) bulk_timer.stop();
00311 }
00312 
00313 void TEmulation::bulkEnd()
00314 {
00315   if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
00316     showBulk();                         // resets bulk_??cnt to 0, too.
00317   else
00318     bulk_timer.start(BULK_TIMEOUT,TRUE);
00319 }
00320 
00321 void TEmulation::setConnect(bool c)
00322 {
00323   connected = c;
00324   if ( connected)
00325   {
00326     onImageSizeChange(gui->Lines(), gui->Columns());
00327     showBulk();
00328   }
00329   else
00330   {
00331     scr->clearSelection();
00332   }
00333 }
00334 
00335 // ---------------------------------------------------------------------------
00336 
00343 void TEmulation::onImageSizeChange(int lines, int columns)
00344 {
00345   if (!connected) return;
00346   screen[0]->resizeImage(lines,columns);
00347   screen[1]->resizeImage(lines,columns);
00348   showBulk();
00349   emit ImageSizeChanged(lines,columns);   // propagate event to serial line
00350 }
00351 
00352 void TEmulation::onHistoryCursorChange(int cursor)
00353 {
00354   if (!connected) return;
00355   scr->setHistCursor(cursor);
00356   showBulk();
00357 }
00358 
00359 void TEmulation::setColumns(int columns)
00360 {
00361   //FIXME: this goes strange ways.
00362   //       Can we put this straight or explain it at least?
00363   emit changeColumns(columns);
00364 }

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