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

TEWidget.cpp

Go to the documentation of this file.
00001 /* ------------------------------------------------------------------------ */
00002 /*                                                                          */
00003 /* [TEWidget.C]            Terminal Emulation Widget                        */
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 /* -------------------------------------------------------------------------- */
00039 /* FIXME:
00040    - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent
00041    - 'font_a' not used in mouse events
00042    - add destructor
00043 */
00044 
00045 /* TODO
00046    - evtl. be sensitive to `paletteChange' while using default colors.
00047    - set different 'rounding' styles? I.e. have a mode to show clipped chars?
00048 */
00049 
00050 // #include "config.h"
00051 #include "TEWidget.h"
00052 #include "session.h"
00053 #include <qpe/config.h>
00054 
00055 
00056 #if !(QT_NO_COP)
00057 #include <qpe/qcopenvelope_qws.h>
00058 #endif
00059 
00060 #include <qclipboard.h>
00061 
00062 #ifndef QT_NO_DRAGANDDROP
00063 #include <qdragobject.h>
00064 #include <qfile.h>
00065 #endif
00066 
00067 #include <stdio.h>
00068 #include <stdlib.h>
00069 #include <unistd.h>
00070 #include <ctype.h>
00071 #include <sys/stat.h>
00072 #include <sys/types.h>
00073 #include <signal.h>
00074 
00075 #include <assert.h>
00076 
00077 // #include "TEWidget.moc"
00078 //#include <kapp.h>
00079 //#include <kcursor.h>
00080 //#include <kurl.h>
00081 //#include <kdebug.h>
00082 //#include <klocale.h>
00083 
00084 #define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__)
00085 #define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); }
00086 
00087 #define loc(X,Y) ((Y)*columns+(X))
00088 
00089 //FIXME: the rim should normally be 1, 0 only when running in full screen mode.
00090 #define rimX 0      // left/right rim width
00091 #define rimY 0      // top/bottom rim high
00092 
00093 #define SCRWIDTH 16 // width of the scrollbar
00094 
00095 #define yMouseScroll 1
00096 // scroll increment used when dragging selection at top/bottom of window.
00097 
00098 /* ------------------------------------------------------------------------- */
00099 /*                                                                           */
00100 /*                                Colors                                     */
00101 /*                                                                           */
00102 /* ------------------------------------------------------------------------- */
00103 
00104 //FIXME: the default color table is in session.C now.
00105 //       We need a way to get rid of this one, here.
00106 static const ColorEntry base_color_table[TABLE_COLORS] =
00107 // The following are almost IBM standard color codes, with some slight
00108 // gamma correction for the dim colors to compensate for bright X screens.
00109 // It contains the 8 ansiterm/xterm colors in 2 intensities.
00110 {
00111   // Fixme: could add faint colors here, also.
00112   // normal
00113   ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback
00114   ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
00115   ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
00116   ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue,  Magenta
00117   ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan,  White
00118   // intensiv
00119   ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
00120   ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
00121   ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
00122   ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ),
00123   ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
00124 };
00125 
00126 /* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
00127 
00128    Code        0       1       2       3       4       5       6       7
00129    ----------- ------- ------- ------- ------- ------- ------- ------- -------
00130    ANSI  (bgr) Black   Red     Green   Yellow  Blue    Magenta Cyan    White
00131    IBMPC (rgb) Black   Blue    Green   Cyan    Red     Magenta Yellow  White
00132 */
00133 
00134 QColor TEWidget::getDefaultBackColor()
00135 {
00136   return color_table[DEFAULT_BACK_COLOR].color;
00137 }
00138 
00139 const ColorEntry* TEWidget::getColorTable() const
00140 {
00141   return color_table;
00142 }
00143 
00144 const ColorEntry* TEWidget::getdefaultColorTable() const
00145 {
00146   return base_color_table;
00147 }
00148 
00149 
00150 const QPixmap *TEWidget::backgroundPixmap()
00151 {
00152   static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm");
00153   const QPixmap *pm = bg;
00154   return pm;
00155 }
00156 
00157 void TEWidget::setColorTable(const ColorEntry table[])
00158 {
00159   for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i];
00160 
00161   const QPixmap* pm = backgroundPixmap();
00162   if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color);
00163   update();
00164 }
00165 
00166 //FIXME: add backgroundPixmapChanged.
00167 
00168 /* ------------------------------------------------------------------------- */
00169 /*                                                                           */
00170 /*                                   Font                                    */
00171 /*                                                                           */
00172 /* ------------------------------------------------------------------------- */
00173 
00174 /*
00175    The VT100 has 32 special graphical characters. The usual vt100 extended
00176    xterm fonts have these at 0x00..0x1f.
00177 
00178    QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
00179    come in here as proper unicode characters.
00180 
00181    We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
00182    from unicode to 0x00..0x1f. The remaining translation is then left to the
00183    QCodec.
00184 */
00185 
00186 // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
00187 
00188 unsigned short vt100_graphics[32] =
00189 { // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15
00190   0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
00191   0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
00192   0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
00193   0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
00194 };
00195 
00196 static QChar vt100extended(QChar c)
00197 {
00198   switch (c.unicode())
00199   {
00200     case 0x25c6 : return  1;
00201     case 0x2592 : return  2;
00202     case 0x2409 : return  3;
00203     case 0x240c : return  4;
00204     case 0x240d : return  5;
00205     case 0x240a : return  6;
00206     case 0x00b0 : return  7;
00207     case 0x00b1 : return  8;
00208     case 0x2424 : return  9;
00209     case 0x240b : return 10;
00210     case 0x2518 : return 11;
00211     case 0x2510 : return 12;
00212     case 0x250c : return 13;
00213     case 0x2514 : return 14;
00214     case 0x253c : return 15;
00215     case 0xf800 : return 16;
00216     case 0xf801 : return 17;
00217     case 0x2500 : return 18;
00218     case 0xf803 : return 19;
00219     case 0xf804 : return 20;
00220     case 0x251c : return 21;
00221     case 0x2524 : return 22;
00222     case 0x2534 : return 23;
00223     case 0x252c : return 24;
00224     case 0x2502 : return 25;
00225     case 0x2264 : return 26;
00226     case 0x2265 : return 27;
00227     case 0x03c0 : return 28;
00228     case 0x2260 : return 29;
00229     case 0x00a3 : return 30;
00230     case 0x00b7 : return 31;
00231   }
00232   return c;
00233 }
00234 
00235 static QChar identicalMap(QChar c)
00236 {
00237   return c;
00238 }
00239 
00240 void TEWidget::fontChange(const QFont &)
00241 {
00242   QFontMetrics fm(font());
00243   font_h = fm.height();
00244   //  font_w = fm.maxWidth();
00245   font_w = fm.width("m");
00246   font_a = fm.ascent();
00247   printf("font h=%d max_width=%d width_m=%d assent=%d\n", font_h,
00248          fm.maxWidth(), font_w, font_a);
00249 
00250   //printf("font_h: %d\n",font_h);
00251   //printf("font_w: %d\n",font_w);
00252   //printf("font_a: %d\n",font_a);
00253   //printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii());
00254   //printf("rawname: %s\n",font().rawName().ascii());
00255   fontMap =
00256 #if QT_VERSION < 0x030000
00257   strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646")
00258           ? vt100extended
00259           :
00260 #endif
00261   identicalMap;
00262   propagateSize();
00263   update();
00264 }
00265 
00266 void TEWidget::setVTFont(const QFont& f)
00267 {
00268   QFrame::setFont(f);
00269 }
00270 
00271 QFont TEWidget::getVTFont() {
00272   return font();
00273 }
00274 
00275 void TEWidget::setFont(const QFont &)
00276 {
00277   // ignore font change request if not coming from konsole itself
00278 }
00279 
00280 /* ------------------------------------------------------------------------- */
00281 /*                                                                           */
00282 /*                         Constructor / Destructor                          */
00283 /*                                                                           */
00284 /* ------------------------------------------------------------------------- */
00285 
00286 TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name)
00287 {
00288 #ifndef QT_NO_CLIPBOARD
00289   cb = QApplication::clipboard();
00290   QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
00291                     this, SLOT(onClearSelection()) );
00292 #endif
00293 
00294   scrollbar = new QScrollBar(this);
00295   scrollbar->setCursor( arrowCursor );
00296   connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
00297 
00298   hScrollbar = new QScrollBar(this);
00299   hScrollbar->setCursor( arrowCursor );
00300   hScrollbar->setOrientation(QScrollBar::Horizontal);
00301   //  hScrollbar->setMaximumHeight(16);
00302 
00303   connect( hScrollbar, SIGNAL(valueChanged(int)), this, SLOT( hScrollChanged(int)));
00304 
00305   Config cfg( "Konsole" );
00306   cfg.setGroup("ScrollBar");
00307   switch( cfg.readNumEntry("Position",2)){
00308   case 0:
00309       scrollLoc = SCRNONE;
00310       break;
00311   case 1:
00312       scrollLoc = SCRLEFT;
00313       break;
00314   case 2:
00315       scrollLoc = SCRRIGHT;
00316       break;
00317   };
00318 
00319   useHorzScroll=cfg.readBoolEntry("HorzScroll",0);
00320 
00321   blinkT   = new QTimer(this);
00322   connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent()));
00323   // blinking = FALSE;
00324   blinking = TRUE;
00325 
00326   resizing = FALSE;
00327   actSel   = 0;
00328   image    = 0;
00329   lines    = 1;
00330   columns  = 1;
00331   font_w   = 1;
00332   font_h   = 1;
00333   font_a   = 1;
00334   word_selection_mode = FALSE;
00335   hposition = 0;
00336   vcolumns = 0;
00337   useBeep = true;
00338 
00339   setMouseMarks(TRUE);
00340   setVTFont( QFont("fixed") );
00341   setColorTable(base_color_table); // init color table
00342 
00343   qApp->installEventFilter( this ); //FIXME: see below
00344 //  KCursor::setAutoHideCursor( this, true );
00345 
00346   // Init DnD ////////////////////////////////////////////////////////////////
00347   currentSession = NULL;
00348 //  setAcceptDrops(true); // attempt
00349 //  m_drop = new QPopupMenu(this);
00350 //  m_drop->insertItem( QString("Paste"), 0);
00351 //  m_drop->insertItem( QString("cd"),    1);
00352 //  connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int)));
00353 
00354   // we need focus so that the auto-hide cursor feature works
00355   setFocus();
00356   setFocusPolicy( WheelFocus );
00357 }
00358 
00359 //FIXME: make proper destructor
00360 // Here's a start (David)
00361 TEWidget::~TEWidget()
00362 {
00363   qApp->removeEventFilter( this );
00364   if (image) free(image);
00365 }
00366 
00367 /* ------------------------------------------------------------------------- */
00368 /*                                                                           */
00369 /*                             Display Operations                            */
00370 /*                                                                           */
00371 /* ------------------------------------------------------------------------- */
00372 
00377 void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
00378                            QString& str, ca attr, BOOL pm, BOOL clear)
00379 {
00380   if (pm && color_table[attr.b].transparent)
00381   {
00382     paint.setBackgroundMode( TransparentMode );
00383     if (clear) erase(rect);
00384   }
00385   else
00386   {
00387     if (blinking)
00388       paint.fillRect(rect, color_table[attr.b].color);
00389     else
00390     {
00391       paint.setBackgroundMode( OpaqueMode );
00392       paint.setBackgroundColor( color_table[attr.b].color );
00393     }
00394   }
00395 
00396   if (color_table[attr.f].bold)
00397     paint.setPen(QColor( 0x8F, 0x00, 0x00 ));
00398   else
00399     paint.setPen(color_table[attr.f].color);
00400 
00401   paint.drawText(rect.x(),rect.y()+font_a, str);
00402 
00403   if (attr.r & RE_UNDERLINE)
00404     paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 );
00405 }
00406 
00413 void TEWidget::setImage(const ca* const newimg, int lines, int columns)
00414 { int y,x,len;
00415   const QPixmap* pm = backgroundPixmap();
00416   QPainter paint;
00417   setUpdatesEnabled(FALSE);
00418   paint.begin( this );
00419 HCNT("setImage");
00420 
00421   QPoint tL  = contentsRect().topLeft();
00422   int    tLx = tL.x();
00423   int    tLy = tL.y();
00424   hasBlinker = FALSE;
00425 
00426   int cf  = -1; // undefined
00427   int cb  = -1; // undefined
00428   int cr  = -1; // undefined
00429 
00430   int lins = QMIN(this->lines,  QMAX(0,lines  ));
00431   int cols = QMIN(this->columns,QMAX(0,columns));
00432   QChar *disstrU = new QChar[cols];
00433   for (y = 0; y < lins; y++) {
00434     const ca*       lcl = &image[y*this->columns];
00435     const ca* const ext = &newimg[y*columns];
00436     if (!resizing) // not while resizing, we're expecting a paintEvent
00437     for (x = 0; x < cols; x++)
00438     {
00439       hasBlinker |= (ext[x].r & RE_BLINK);
00440       if (ext[x] != lcl[x])
00441       {
00442         cr = ext[x].r;
00443         cb = ext[x].b;
00444         if (ext[x].f != cf) cf = ext[x].f;
00445         int lln = cols - x;
00446         disstrU[0] = fontMap(ext[x+0].c);
00447         for (len = 1; len < lln; len++)
00448         {
00449           if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
00450               ext[x+len] == lcl[x+len] )
00451             break;
00452           disstrU[len] = fontMap(ext[x+len].c);
00453         }
00454         QString unistr(disstrU,len);
00455         drawAttrStr(paint,
00456                     QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
00457                     unistr, ext[x], pm != NULL, true);
00458         x += len - 1;
00459       }
00460     }
00461     // finally, make `image' become `newimg'.
00462     memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
00463   }
00464   drawFrame( &paint );
00465   paint.end();
00466   setUpdatesEnabled(TRUE);
00467   if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
00468   if (!hasBlinker &&  blinkT->isActive()) { blinkT->stop(); blinking = FALSE; }
00469   delete [] disstrU;
00470 }
00471 
00472 // paint Event ////////////////////////////////////////////////////
00473 
00481 void TEWidget::paintEvent( QPaintEvent* pe )
00482 {
00483 
00484 //{ static int cnt = 0; printf("paint %d\n",cnt++); }
00485   const QPixmap* pm = backgroundPixmap();
00486   QPainter paint;
00487   setUpdatesEnabled(FALSE);
00488   paint.begin( this );
00489   paint.setBackgroundMode( TransparentMode );
00490 HCNT("paintEvent");
00491 
00492   // Note that the actual widget size can be slightly larger
00493   // that the image (the size is truncated towards the smaller
00494   // number of characters in `resizeEvent'. The paint rectangle
00495   // can thus be larger than the image, but less then the size
00496   // of one character.
00497 
00498   QRect rect = pe->rect().intersect(contentsRect());
00499 
00500   QPoint tL  = contentsRect().topLeft();
00501   int    tLx = tL.x();
00502   int    tLy = tL.y();
00503 
00504   int lux = QMIN(columns-1, QMAX(0,(rect.left()   - tLx - blX ) / font_w));
00505   int luy = QMIN(lines-1,   QMAX(0,(rect.top()    - tLy - bY  ) / font_h));
00506   int rlx = QMIN(columns-1, QMAX(0,(rect.right()  - tLx - blX ) / font_w));
00507   int rly = QMIN(lines-1,   QMAX(0,(rect.bottom() - tLy - bY  ) / font_h));
00508 
00509   /*
00510  printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly,
00511   rect.left(), rect.right(), rect.top(), rect.bottom());
00512   */
00513 
00514   //  if (pm != NULL && color_table[image->b].transparent)
00515   //  erase(rect);
00516   // BL: I have no idea why we need this, and it breaks the refresh.
00517 
00518   QChar *disstrU = new QChar[columns];
00519   for (int y = luy; y <= rly; y++)
00520   for (int x = lux; x <= rlx; x++)
00521   {
00522     int len = 1;
00523     disstrU[0] = fontMap(image[loc(x,y)].c);
00524     int cf = image[loc(x,y)].f;
00525     int cb = image[loc(x,y)].b;
00526     int cr = image[loc(x,y)].r;
00527     while (x+len <= rlx &&
00528            image[loc(x+len,y)].f == cf &&
00529            image[loc(x+len,y)].b == cb &&
00530            image[loc(x+len,y)].r == cr )
00531     {
00532       disstrU[len] = fontMap(image[loc(x+len,y)].c);
00533       len += 1;
00534     }
00535     QString unistr(disstrU,len);
00536     drawAttrStr(paint,
00537                 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
00538                 unistr, image[loc(x,y)], pm != NULL, false);
00539     x += len - 1;
00540   }
00541   delete [] disstrU;
00542   drawFrame( &paint );
00543   paint.end();
00544   setUpdatesEnabled(TRUE);
00545 }
00546 
00547 void TEWidget::blinkEvent()
00548 {
00549   blinking = !blinking;
00550   repaint(FALSE);
00551 }
00552 
00553 /* ------------------------------------------------------------------------- */
00554 /*                                                                           */
00555 /*                                  Resizing                                 */
00556 /*                                                                           */
00557 /* ------------------------------------------------------------------------- */
00558 
00559 void TEWidget::resizeEvent(QResizeEvent* ev)
00560 {
00561 //  printf("resize: %d,%d\n",ev->size().width(),ev->size().height());
00562   //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h);
00563   //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h);
00564   //printf("curren: %d,%d\n",width(),height());
00565 HCNT("resizeEvent");
00566 
00567   // see comment in `paintEvent' concerning the rounding.
00568   //FIXME: could make a routine here; check width(),height()
00569   assert(ev->size().width() == width());
00570   assert(ev->size().height() == height());
00571 
00572   propagateSize();
00573 }
00574 
00575 void TEWidget::propagateSize()
00576 {
00577   ca* oldimg = image;
00578   int oldlin = lines;
00579   int oldcol = columns;
00580   makeImage();
00581   // we copy the old image to reduce flicker
00582   int lins = QMIN(oldlin,lines);
00583   int cols = QMIN(oldcol,columns);
00584   if (oldimg)
00585   {
00586     for (int lin = 0; lin < lins; lin++)
00587       memcpy((void*)&image[columns*lin],
00588              (void*)&oldimg[oldcol*lin],cols*sizeof(ca));
00589     free(oldimg); //FIXME: try new,delete
00590   }
00591   else
00592     clearImage();
00593 
00594   //NOTE: control flows from the back through the chest right into the eye.
00595   //      `emu' will call back via `setImage'.
00596 
00597   resizing = TRUE;
00598   emit changedImageSizeSignal(lines, columns); // expose resizeEvent
00599   resizing = FALSE;
00600 }
00601 
00602 /* ------------------------------------------------------------------------- */
00603 /*                                                                           */
00604 /*                                Scrollbar                                  */
00605 /*                                                                           */
00606 /* ------------------------------------------------------------------------- */
00607 
00608 void TEWidget::scrollChanged(int) {
00609   emit changedHistoryCursor(scrollbar->value()); //expose
00610 }
00611 
00612 void TEWidget::hScrollChanged(int loc) {
00613   hposition = loc;
00614   propagateSize();
00615   update();
00616 
00617 //  emit changedHorzCursor( hScrollbar->value()); //expose
00618 }
00619 
00620 void TEWidget::setScroll(int cursor, int slines)
00621 {
00622   disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
00623   scrollbar->setRange(0,slines);
00624   scrollbar->setSteps(1,lines);
00625   scrollbar->setValue(cursor);
00626   connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
00627 }
00628 
00629 void TEWidget::setScrollbarLocation(int loc)
00630 {
00631   if (scrollLoc == loc) return; // quickly
00632   scrollLoc = loc;
00633   propagateSize();
00634   update();
00635 }
00636 
00637 /* ------------------------------------------------------------------------- */
00638 /*                                                                           */
00639 /*                                   Mouse                                   */
00640 /*                                                                           */
00641 /* ------------------------------------------------------------------------- */
00642 
00670 void TEWidget::mousePressEvent(QMouseEvent* ev)
00671 {
00672 //printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
00673   if ( !contentsRect().contains(ev->pos()) ) return;
00674   QPoint tL  = contentsRect().topLeft();
00675   int    tLx = tL.x();
00676   int    tLy = tL.y();
00677 
00678   mouse_down_x = ev->x();
00679   mouse_down_y = ev->y();
00680 
00681 //printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY);
00682   if ( ev->button() == LeftButton)
00683   {
00684     QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
00685 
00686     word_selection_mode = (ev->state() & ShiftButton);
00687 
00688     if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ;
00689 
00690     if (mouse_marks || (ev->state() & ShiftButton))
00691     {
00692       emit clearSelectionSignal();
00693       iPntSel = pntSel = pos;
00694       actSel = 1; // left mouse button pressed but nothing selected yet.
00695       grabMouse(   /*crossCursor*/  ); // handle with care!
00696     }
00697     else
00698     {
00699       emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button
00700     }
00701   }
00702   if ( ev->button() == MidButton )
00703   {
00704     emitSelection();
00705   }
00706   if ( ev->button() == RightButton ) // Configure
00707   {
00708     emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() );
00709   }
00710 }
00711 
00712 void TEWidget::mouseMoveEvent(QMouseEvent* ev)
00713 {
00714   // for auto-hiding the cursor, we need mouseTracking
00715   if (ev->state() == NoButton ) return;
00716 
00717   if (actSel == 0) return;
00718 
00719  // don't extend selection while pasting
00720   if (ev->state() & MidButton) return;
00721 
00722   //if ( !contentsRect().contains(ev->pos()) ) return;
00723   QPoint tL  = contentsRect().topLeft();
00724   int    tLx = tL.x();
00725   int    tLy = tL.y();
00726   int    scroll = scrollbar->value();
00727 //  int    hScroll = hScrollbar->value();
00728 
00729   // we're in the process of moving the mouse with the left button pressed
00730   // the mouse cursor will kept catched within the bounds of the text in
00731   // this widget.
00732 
00733   // Adjust position within text area bounds. See FIXME above.
00734   QPoint pos = ev->pos();
00735   if ( pos.x() < tLx+blX )                  pos.setX( tLx+blX );
00736   if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w );
00737   if ( pos.y() < tLy+bY )                   pos.setY( tLy+bY );
00738   if ( pos.y() > tLy+bY+lines*font_h-1 )    pos.setY( tLy+bY+lines*font_h-1 );
00739   // check if we produce a mouse move event by this
00740   if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos));
00741 
00742   if ( pos.y() == tLy+bY+lines*font_h-1 )
00743   {
00744     scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward
00745   }
00746   if ( pos.y() == tLy+bY )
00747   {
00748     scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback
00749   }
00750 
00751   QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h);
00752   QPoint ohere;
00753   bool swapping = FALSE;
00754 
00755   if ( word_selection_mode )
00756   {
00757     // Extend to word boundaries
00758     int i;
00759     int selClass;
00760 
00761     bool left_not_right = ( here.y() < iPntSel.y() ||
00762      here.y() == iPntSel.y() && here.x() < iPntSel.x() );
00763     bool old_left_not_right = ( pntSel.y() < iPntSel.y() ||
00764      pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() );
00765     swapping = left_not_right != old_left_not_right;
00766 
00767     // Find left (left_not_right ? from here : from start)
00768     QPoint left = left_not_right ? here : iPntSel;
00769     i = loc(left.x(),left.y());
00770     selClass = charClass(image[i].c);
00771     while ( left.x() > 0 && charClass(image[i-1].c) == selClass )
00772     { i--; left.rx()--; }
00773 
00774     // Find left (left_not_right ? from start : from here)
00775     QPoint right = left_not_right ? iPntSel : here;
00776     i = loc(right.x(),right.y());
00777     selClass = charClass(image[i].c);
00778     while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass )
00779     { i++; right.rx()++; }
00780 
00781     // Pick which is start (ohere) and which is extension (here)
00782     if ( left_not_right )
00783     {
00784       here = left; ohere = right;
00785     }
00786     else
00787     {
00788       here = right; ohere = left;
00789     }
00790   }
00791 
00792   if (here == pntSel && scroll == scrollbar->value()) return; // not moved
00793 
00794   if ( word_selection_mode ) {
00795     if ( actSel < 2 || swapping ) {
00796       emit beginSelectionSignal( ohere.x(), ohere.y() );
00797     }
00798   } else if ( actSel < 2 ) {
00799     emit beginSelectionSignal( pntSel.x(), pntSel.y() );
00800   }
00801 
00802   actSel = 2; // within selection
00803   pntSel = here;
00804   emit extendSelectionSignal( here.x(), here.y() );
00805 }
00806 
00807 void TEWidget::mouseReleaseEvent(QMouseEvent* ev)
00808 {
00809 //printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
00810   if ( ev->button() == LeftButton)
00811   {
00812     if (QABS(ev->x() - mouse_down_x) < 3
00813         && QABS(ev->y() - mouse_down_y) < 3
00814         && ev->y() < qApp->desktop()->height()/8) {
00815       emit setFullScreen(false);
00816     }
00817 
00818     if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks);
00819     preserve_line_breaks = TRUE;
00820     actSel = 0;
00821 
00822     //FIXME: emits a release event even if the mouse is
00823     //       outside the range. The procedure used in `mouseMoveEvent'
00824     //       applies here, too.
00825 
00826     QPoint tL  = contentsRect().topLeft();
00827     int    tLx = tL.x();
00828     int    tLy = tL.y();
00829 
00830     if (!mouse_marks && !(ev->state() & ShiftButton))
00831       emit mouseSignal( 3, // release
00832                         (ev->x()-tLx-blX)/font_w + 1,
00833                         (ev->y()-tLy-bY)/font_h + 1 );
00834     releaseMouse();
00835   }
00836 }
00837 
00838 void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev)
00839 {
00840   if ( ev->button() != LeftButton) return;
00841 
00842   QPoint tL  = contentsRect().topLeft();
00843   int    tLx = tL.x();
00844   int    tLy = tL.y();
00845   QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
00846 
00847   // pass on double click as two clicks.
00848   if (!mouse_marks && !(ev->state() & ShiftButton))
00849   {
00850     emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
00851     emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release
00852     emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
00853     return;
00854   }
00855 
00856 
00857   emit clearSelectionSignal();
00858   QPoint bgnSel = pos;
00859   QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
00860   int i = loc(bgnSel.x(),bgnSel.y());
00861   iPntSel = bgnSel;
00862 
00863   word_selection_mode = TRUE;
00864 
00865   // find word boundaries...
00866   int selClass = charClass(image[i].c);
00867   {
00868     // set the start...
00869      int x = bgnSel.x();
00870      while ( x > 0 && charClass(image[i-1].c) == selClass )
00871      { i--; x--; }
00872      bgnSel.setX(x);
00873      emit beginSelectionSignal( bgnSel.x(), bgnSel.y() );
00874 
00875      // set the end...
00876      i = loc( endSel.x(), endSel.y() );
00877      x = endSel.x();
00878      while( x < columns-1 && charClass(image[i+1].c) == selClass )
00879      { i++; x++ ; }
00880      endSel.setX(x);
00881      actSel = 2; // within selection
00882      emit extendSelectionSignal( endSel.x(), endSel.y() );
00883      emit endSelectionSignal(preserve_line_breaks);
00884      preserve_line_breaks = TRUE;
00885    }
00886 }
00887 
00888 void TEWidget::focusInEvent( QFocusEvent * )
00889 {
00890 
00891     // do nothing, to prevent repainting
00892 }
00893 
00894 
00895 void TEWidget::focusOutEvent( QFocusEvent * )
00896 {
00897     // do nothing, to prevent repainting
00898 }
00899 
00900 bool TEWidget::focusNextPrevChild( bool next )
00901 {
00902   if (next)
00903     return false; // This disables changing the active part in konqueror
00904                   // when pressing Tab
00905   return QFrame::focusNextPrevChild( next );
00906 }
00907 
00908 
00909 int TEWidget::charClass(char ch) const
00910 {
00911     // This might seem like overkill, but imagine if ch was a Unicode
00912     // character (Qt 2.0 QChar) - it might then be sensible to separate
00913     // the different language ranges, etc.
00914 
00915     if ( isspace(ch) ) return ' ';
00916 
00917     static const char *word_characters = ":@-./_~";
00918     if ( isalnum(ch) || strchr(word_characters, ch) )
00919     return 'a';
00920 
00921     // Everything else is weird
00922     return 1;
00923 }
00924 
00925 void TEWidget::setMouseMarks(bool on)
00926 {
00927   mouse_marks = on;
00928   setCursor( mouse_marks ? ibeamCursor : arrowCursor );
00929 }
00930 
00931 /* ------------------------------------------------------------------------- */
00932 /*                                                                           */
00933 /*                               Clipboard                                   */
00934 /*                                                                           */
00935 /* ------------------------------------------------------------------------- */
00936 
00937 #undef KeyPress
00938 
00939 void TEWidget::emitSelection()
00940 // Paste Clipboard by simulating keypress events
00941 {
00942 #ifndef QT_NO_CLIPBOARD
00943   QString text = QApplication::clipboard()->text();
00944 //      odebug << text << oendl; 
00945   if ( ! text.isNull())
00946   {
00947     text.replace(QRegExp("\n"), "\r");
00948     QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
00949     emit keyPressedSignal(&e); // expose as a big fat keypress event
00950     emit clearSelectionSignal();
00951   }
00952 #endif
00953 }
00954 
00955 void TEWidget::emitText(QString text)
00956 {
00957   QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
00958   emit keyPressedSignal(&e); // expose as a big fat keypress event
00959 }
00960 
00961 void TEWidget::pasteClipboard( )
00962 {
00963   emitSelection();
00964 }
00965 
00966 void TEWidget::setSelection(const QString& t)
00967 {
00968 #ifndef QT_NO_CLIPBOARD
00969   // Disconnect signal while WE set the clipboard
00970   QObject *cb = QApplication::clipboard();
00971   QObject::disconnect( cb, SIGNAL(dataChanged()),
00972                      this, SLOT(onClearSelection()) );
00973 
00974   QApplication::clipboard()->setText(t);
00975 
00976   QObject::connect( cb, SIGNAL(dataChanged()),
00977                      this, SLOT(onClearSelection()) );
00978 #endif
00979 }
00980 
00981 void TEWidget::onClearSelection()
00982 {
00983   emit clearSelectionSignal();
00984 }
00985 
00986 /* ------------------------------------------------------------------------- */
00987 /*                                                                           */
00988 /*                                Keyboard                                   */
00989 /*                                                                           */
00990 /* ------------------------------------------------------------------------- */
00991 
00992 //FIXME: an `eventFilter' has been installed instead of a `keyPressEvent'
00993 //       due to a bug in `QT' or the ignorance of the author to prevent
00994 //       repaint events being emitted to the screen whenever one leaves
00995 //       or reenters the screen to/from another application.
00996 //
00997 //   Troll says one needs to change focusInEvent() and focusOutEvent(),
00998 //   which would also let you have an in-focus cursor and an out-focus
00999 //   cursor like xterm does.
01000 
01001 // for the auto-hide cursor feature, I added empty focusInEvent() and
01002 // focusOutEvent() so that update() isn't called.
01003 // For auto-hide, we need to get keypress-events, but we only get them when
01004 // we have focus.
01005 
01006 void TEWidget::doScroll(int lines)
01007 {
01008   scrollbar->setValue(scrollbar->value()+lines);
01009 }
01010 
01011 void TEWidget::doHScroll(int lines) {
01012   hScrollbar->setValue( hScrollbar->value()+lines);
01013 }
01014 
01015 bool TEWidget::eventFilter( QObject *obj, QEvent *e )
01016 {
01017     if ( (e->type() == QEvent::Accel ||
01018           e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this )  {
01019         static_cast<QKeyEvent *>( e )->ignore();
01020         return true;
01021     }
01022     if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ )
01023         return FALSE; // not us
01024     if ( e->type() == QEvent::Wheel)  {
01025         QApplication::sendEvent(scrollbar, e);
01026     }
01027 
01028 #ifdef FAKE_CTRL_AND_ALT
01029     static bool control = FALSE;
01030     static bool alt = FALSE;
01031 //    odebug << " Has a keyboard with no CTRL and ALT keys, but we fake it:" << oendl; 
01032     bool dele=FALSE;
01033     if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) {
01034         QKeyEvent* ke = (QKeyEvent*)e;
01035         bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat();
01036         switch (ke->key()) {
01037           case Key_F9: // let this be "Control"
01038               control = keydown;
01039               e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state());
01040               dele=TRUE;
01041               break;
01042           case Key_F13: // let this be "Alt"
01043               alt = keydown;
01044               e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state());
01045               dele=TRUE;
01046               break;
01047           default:
01048               if ( control ) {
01049                   int a = toupper(ke->ascii())-64;
01050                   if ( a >= 0 && a < ' ' ) {
01051                       e = new QKeyEvent(e->type(), ke->key(),
01052                                         a, ke->state()|ControlButton, QChar(a,0));
01053                       dele=TRUE;
01054                   }
01055               }
01056               if ( alt ) {
01057                   e = new QKeyEvent(e->type(), ke->key(),
01058                                     ke->ascii(), ke->state()|AltButton, ke->text());
01059                   dele=TRUE;
01060               }
01061         }
01062     }
01063 #endif
01064 
01065     if ( e->type() == QEvent::KeyPress )  {
01066         QKeyEvent* ke = (QKeyEvent*)e;
01067         actSel=0; // Key stroke implies a screen update, so TEWidget won't
01068           // know where the current selection is.
01069 
01070 //     odebug << "key pressed is 0x" << ke->key() << ", ascii is 0x" << ke->ascii() << ", state " << ke->state() << "" << oendl; 
01071 
01072         bool special_function = true;
01073         switch(ke->key()) {
01074           //    case 0x201b:  // fn-5
01075           //    case Key_F1:
01076           // switch sessions (?)
01077           // emitText("\\"); // expose  (??)
01078           //      break;
01079 
01080         case 0x2016:  // fn-p
01081         case Key_F2:
01082           pasteClipboard();
01083           break;
01084 
01085         case 0x2018:  // fn-S
01086         case Key_F3:
01087           emit changeSession(1);
01088           break;
01089 
01090         case 0x2019: // fn-n
01091           emit newSession();
01092           break;
01093 
01094         case Qt::Key_Tab:
01095           if (ke->state() == ControlButton) {
01096             emit changeSession(1);
01097           } else {
01098             special_function = false;
01099           }
01100           break;
01101 
01102 #if 0
01103         case Qt::Key_Left:
01104           if (vcolumns == 0) {
01105             emit changeSession(-1);
01106           } else {
01107             special_function = false;
01108           }
01109           break;
01110 
01111         case Qt::Key_Right:
01112           if (vcolumns == 0) {
01113             emit changeSession(1);
01114           } else {
01115             special_function = false;
01116           }
01117           break;
01118 #endif
01119 
01120         case 0x201b:  // fn-5
01121         case Key_F4:
01122           emit toggleFullScreen();
01123           break;
01124 
01125         case 0x200f:  // fn-1 magnify minus
01126         case Key_F5:
01127           emit changeFontSize(-1);
01128           break;
01129 
01130         case 0x2010:  // fn-2 magnify plus
01131         case Key_F6:
01132           emit changeFontSize(1);
01133           break;
01134 
01135         default:
01136           special_function = false;
01137         }
01138         if (special_function) {
01139           return true;
01140         }
01141         //        else if( ke->state() == ControlButton && ke->key() == Key_V) {
01142         //          pasteClipboard();
01143         //        }
01144         //        else if( ke->state() == ControlButton && ke->key() == Key_C) {
01145         //          pasteClipboard();
01146         //        }
01147         emit keyPressedSignal(ke); // expose
01148         ke->accept();
01149 #ifdef FAKE_CTRL_AND_ALT
01150         if ( dele ) delete e;
01151 #endif
01152         return true;               // stop the event
01153     }
01154     if ( e->type() == QEvent::Enter )  {
01155         QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()),
01156                              this, SLOT(onClearSelection()) );
01157     }
01158     if ( e->type() == QEvent::Leave )  {
01159         QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
01160                           this, SLOT(onClearSelection()) );
01161     }
01162     return QFrame::eventFilter( obj, e );
01163 }
01164 
01165 /* ------------------------------------------------------------------------- */
01166 /*                                                                           */
01167 /*                                  Frame                                    */
01168 /*                                                                           */
01169 /* ------------------------------------------------------------------------- */
01170 
01171 void TEWidget::frameChanged()
01172 {
01173   propagateSize();
01174   update();
01175 }
01176 /* ------------------------------------------------------------------------- */
01177 /*                                                                           */
01178 /*                                   Sound                                   */
01179 /*                                                                           */
01180 /* ------------------------------------------------------------------------- */
01181 
01182 void TEWidget::Bell()
01183 {
01184 //#ifdef QT_QWS_SL5XXX
01185 //# ifndef QT_NO_COP
01186     if(useBeep)
01187         QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
01188 
01189 //# endif
01190 //#else
01191 //# ifndef QT_NO_SOUND
01192 //    QSound::play(Resource::findSound("alarm"));
01193 //# endif
01194 //#endif
01195 
01196 //    QApplication::beep();
01197 }
01198 
01199 /* ------------------------------------------------------------------------- */
01200 /*                                                                           */
01201 /*                                 Auxiluary                                 */
01202 /*                                                                           */
01203 /* ------------------------------------------------------------------------- */
01204 
01205 void TEWidget::clearImage()
01206 // initialize the image
01207 // for internal use only
01208 {
01209   for (int y = 0; y < lines; y++)
01210   for (int x = 0; x < columns; x++)
01211   {
01212     image[loc(x,y)].c = 0xff; //' ';
01213     image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR;
01214     image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR;
01215     image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION;
01216   }
01217 }
01218 
01219 // Create Image ///////////////////////////////////////////////////////
01220 
01221 void TEWidget::calcGeometry()
01222 {
01223     int showhscrollbar = 1;
01224     int hwidth = 0;
01225     int dcolumns = 0;
01226     Config cfg( "Konsole" );
01227     cfg.setGroup("ScrollBar");
01228     useHorzScroll=cfg.readBoolEntry("HorzScroll",0);
01229 
01230     if(vcolumns == 0) showhscrollbar = 0;
01231     if(showhscrollbar == 1) hwidth = QApplication::style().scrollBarExtent().width();
01232 
01233     scrollbar->resize(QApplication::style().scrollBarExtent().width(),
01234                       contentsRect().height() - hwidth);
01235 
01236     switch(scrollLoc)  {
01237       case SCRNONE :
01238           columns = ( contentsRect().width() - 2 * rimX ) / font_w;
01239           dcolumns = columns;
01240           if(vcolumns) columns = vcolumns;
01241           blX = (contentsRect().width() - (columns*font_w) ) / 2;
01242           if(showhscrollbar)
01243               blX = -hposition * font_w;
01244           brX = blX;
01245           scrollbar->hide();
01246           break;
01247       case SCRLEFT :
01248           columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
01249           dcolumns = columns;
01250           if(vcolumns) columns = vcolumns;
01251           brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
01252           if(showhscrollbar)
01253               brX = -hposition * font_w;
01254           blX = brX + scrollbar->width();
01255           scrollbar->move(contentsRect().topLeft());
01256           scrollbar->show();
01257           break;
01258       case SCRRIGHT:
01259           columns = ( contentsRect().width()  - 2 * rimX - scrollbar->width()) / font_w;
01260           dcolumns = columns;
01261           if(vcolumns) columns = vcolumns;
01262           blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
01263           if(showhscrollbar)
01264               blX = -hposition * font_w;
01265           brX = blX;
01266           scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0));
01267           scrollbar->show();
01268           break;
01269     }
01270       //FIXME: support 'rounding' styles
01271     lines   = ( contentsRect().height() - 2 * rimY  ) / font_h;
01272     bY = (contentsRect().height() - (lines  *font_h)) / 2;
01273 
01274     if(showhscrollbar == 1)  {
01275         hScrollbar->resize(contentsRect().width() - hwidth, hwidth);
01276         hScrollbar->setRange(0, vcolumns - dcolumns);
01277 
01278         QPoint p = contentsRect().bottomLeft();
01279         if(scrollLoc == SCRLEFT)
01280             hScrollbar->move(QPoint(p.x()+hwidth, p.y() - hwidth));
01281         else
01282             hScrollbar->move(QPoint(p.x(), p.y() - hwidth));
01283 
01284         hScrollbar->show();
01285     }
01286     else hScrollbar->hide();
01287 
01288     if(showhscrollbar == 1)  {
01289         lines = lines - (hwidth / font_h) - 1;
01290         if(lines < 1) lines = 1;
01291     }
01292   //FIXME: support 'rounding' styles
01293 }
01294 
01295 void TEWidget::makeImage()
01296 //FIXME: rename 'calcGeometry?
01297 {
01298   calcGeometry();
01299   image = (ca*) malloc(lines*columns*sizeof(ca));
01300   clearImage();
01301 }
01302 
01303 // calculate the needed size
01304 QSize TEWidget::calcSize(int cols, int lins) const
01305 {
01306   int frw = width() - contentsRect().width();
01307   int frh = height() - contentsRect().height();
01308   int scw = (scrollLoc==SCRNONE?0:scrollbar->width());
01309   return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh );
01310 }
01311 
01312 QSize TEWidget::sizeHint() const
01313 {
01314    return size();
01315 }
01316 
01317 void TEWidget::styleChange(QStyle &)
01318 {
01319     propagateSize();
01320 }
01321 
01322 #ifndef QT_NO_DRAGANDDROP
01323 
01324 /* --------------------------------------------------------------------- */
01325 /*                                                                       */
01326 /* Drag & Drop                                                           */
01327 /*                                                                       */
01328 /* --------------------------------------------------------------------- */
01329 
01330 
01331 void TEWidget::dragEnterEvent(QDragEnterEvent* e)
01332 {
01333   e->accept(QTextDrag::canDecode(e) ||
01334       QUriDrag::canDecode(e));
01335 }
01336 
01337 void TEWidget::dropEvent(QDropEvent* event)
01338 {
01339     // The current behaviour when url(s) are dropped is
01340     // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd
01341     // * in all other cases, just paste
01342     //   (for non-local ones, or for a list of URLs, 'cd' is nonsense)
01343   QStrList strlist;
01344   int file_count = 0;
01345   dropText = "";
01346   bool bPopup = true;
01347 
01348   if(QUriDrag::decode(event, strlist)) {
01349     if (strlist.count()) {
01350       for(const char* p = strlist.first(); p; p = strlist.next()) {
01351         if(file_count++ > 0) {
01352           dropText += " ";
01353           bPopup = false; // more than one file, don't popup
01354         }
01355 
01356 /*
01357         KURL url(p);
01358         if (url.isLocalFile()) {
01359           dropText += url.path(); // local URL : remove protocol
01360         }
01361         else {
01362           dropText += url.prettyURL();
01363           bPopup = false; // a non-local file, don't popup
01364         }
01365 */
01366 
01367       }
01368 
01369       if (bPopup)
01370         // m_drop->popup(pos() + event->pos());
01371   m_drop->popup(mapToGlobal(event->pos()));
01372       else
01373   {
01374     if (currentSession) {
01375       currentSession->getEmulation()->sendString(dropText.local8Bit());
01376     }
01377 //    kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
01378   }
01379     }
01380   }
01381   else if(QTextDrag::decode(event, dropText)) {
01382 //    kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
01383     if (currentSession) {
01384       currentSession->getEmulation()->sendString(dropText.local8Bit());
01385     }
01386     // Paste it
01387   }
01388 }
01389 #endif
01390 
01391 
01392 void TEWidget::drop_menu_activated(int item)
01393 {
01394 #ifndef QT_NO_DRAGANDDROP
01395   switch (item)
01396   {
01397     case 0: // paste
01398       currentSession->getEmulation()->sendString(dropText.local8Bit());
01399 //    KWM::activate((Window)this->winId());
01400       break;
01401     case 1: // cd ...
01402       currentSession->getEmulation()->sendString("cd ");
01403       struct stat statbuf;
01404       if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 )
01405       {
01406         if ( !S_ISDIR(statbuf.st_mode) )
01407         {
01408 /*
01409           KURL url;
01410           url.setPath( dropText );
01411           dropText = url.directory( true, false ); // remove filename
01412 */
01413         }
01414       }
01415       dropText.replace(QRegExp(" "), "\\ "); // escape spaces
01416       currentSession->getEmulation()->sendString(dropText.local8Bit());
01417       currentSession->getEmulation()->sendString("\n");
01418 //    KWM::activate((Window)this->winId());
01419       break;
01420   }
01421 #else
01422   Q_UNUSED(item);  
01423 #endif
01424 }
01425 
01426 void TEWidget::setWrapAt(int columns)
01427 {
01428   vcolumns = columns;
01429   propagateSize();
01430   update();
01431 }

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