From 999a0f2d22f132005bde62558ace48a0ce8b1dcc Mon Sep 17 00:00:00 2001 From: zecke Date: Sat, 16 Oct 2004 21:06:28 +0000 Subject: -Remove never finished classes by ibotty for the console widget -Put setCurrent into ComboboxHelper and remove duplication from the dialogs -Remove old and unneeded debug output -IOBt, IOIrda can share the implementation for sening,recieving and supports with IOSerial --- (limited to 'noncore/apps/opie-console/widget.cpp') diff --git a/noncore/apps/opie-console/widget.cpp b/noncore/apps/opie-console/widget.cpp deleted file mode 100644 index 4a578be..0000000 --- a/noncore/apps/opie-console/widget.cpp +++ b/dev/null @@ -1,1278 +0,0 @@ -/* ------------------------------------------------------------------------ */ -/* */ -/* [TEWidget.C] Terminal Emulation Widget */ -/* */ -/* ------------------------------------------------------------------------ */ -/* */ -/* Copyright (c) 1997,1998 by Lars Doelle */ -/* */ -/* This file is part of Konsole - an X terminal for KDE */ -/* */ -/* ------------------------------------------------------------------------ */ -/* */ -/* Ported Konsole to Qt/Embedded */ -/* */ -/* Copyright (C) 2000 by John Ryland */ -/* */ -/* -------------------------------------------------------------------------- */ - -/* ibot: - i changed - "currentSession->getEmulation()->sendString()" to - "currentSession->layer()->send()" - # this is not right! EmulationLayer should send it... - i changed all those to use emulationLayer()->send() instead - i had to create a QByteArray before... - -TODO: -alter Widget to use only QByteArray, where applicable. -*/ - - - -/*! \class Widget - - \brief Visible screen contents - - This class is responsible to map the `image' of a terminal emulation to the - display. All the dependency of the emulation to a specific GUI or toolkit is - localized here. Further, this widget has no knowledge about being part of an - emulation, it simply work within the terminal emulation framework by exposing - size and key events and by being ordered to show a new image. - -
    -
  • The internal image has the size of the widget (evtl. rounded up) -
  • The external image used in setImage can have any size. -
  • (internally) the external image is simply copied to the internal - when a setImage happens. During a resizeEvent no painting is done - a paintEvent is expected to follow anyway. -
- - \sa TEScreen \sa Emulation -*/ - -/* FIXME: - - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent - - 'font_a' not used in mouse events - - add destructor -*/ - -/* TODO - - evtl. be sensitive to `paletteChange' while using default colors. - - set different 'rounding' styles? I.e. have a mode to show clipped chars? -*/ - -// #include "config.h" -#include "widget.h" -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -// #include "widget.moc" -//#include -//#include -//#include -//#include -//#include - -#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__) -#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); } - -#define loc(X,Y) ((Y)*columns+(X)) - -//FIXME: the rim should normally be 1, 0 only when running in full screen mode. -#define rimX 0 // left/right rim width -#define rimY 0 // top/bottom rim high - -#define yMouseScroll 1 -// scroll increment used when dragging selection at top/bottom of window. - -/* ------------------------------------------------------------------------- */ -/* */ -/* Colors */ -/* */ -/* ------------------------------------------------------------------------- */ - -//FIXME: the default color table is in session.C now. -// We need a way to get rid of this one, here. -static const ColorEntry base_color_table[TABLE_COLORS] = -// The following are almost IBM standard color codes, with some slight -// gamma correction for the dim colors to compensate for bright X screens. -// It contains the 8 ansiterm/xterm colors in 2 intensities. -{ - // Fixme: could add faint colors here, also. - // normal - ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback - ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red - ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow - ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta - ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White - // intensiv - ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ), - ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ), - ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ), - ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), - ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ) -}; - -/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb) - - Code 0 1 2 3 4 5 6 7 - ----------- ------- ------- ------- ------- ------- ------- ------- ------- - ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White - IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White -*/ - -QColor Widget::getDefaultBackColor() -{ - return color_table[DEFAULT_BACK_COLOR].color; -} - -const ColorEntry* Widget::getColorTable() const -{ - return color_table; -} - -const ColorEntry* Widget::getdefaultColorTable() const -{ - return base_color_table; -} - - -const QPixmap *Widget::backgroundPixmap() -{ - static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm"); - const QPixmap *pm = bg; - return pm; -} - -void Widget::setColorTable(const ColorEntry table[]) -{ - for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i]; - - const QPixmap* pm = backgroundPixmap(); - if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color); - update(); -} - -//FIXME: add backgroundPixmapChanged. - -/* ------------------------------------------------------------------------- */ -/* */ -/* Font */ -/* */ -/* ------------------------------------------------------------------------- */ - -/* - The VT100 has 32 special graphical characters. The usual vt100 extended - xterm fonts have these at 0x00..0x1f. - - QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals - come in here as proper unicode characters. - - We treat non-iso10646 fonts as VT100 extended and do the requiered mapping - from unicode to 0x00..0x1f. The remaining translation is then left to the - QCodec. -*/ - -// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. - -unsigned short vt100_graphics[32] = -{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15 - 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, - 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, - 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, - 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7 -}; - -static QChar vt100extended(QChar c) -{ - switch (c.unicode()) - { - case 0x25c6 : return 1; - case 0x2592 : return 2; - case 0x2409 : return 3; - case 0x240c : return 4; - case 0x240d : return 5; - case 0x240a : return 6; - case 0x00b0 : return 7; - case 0x00b1 : return 8; - case 0x2424 : return 9; - case 0x240b : return 10; - case 0x2518 : return 11; - case 0x2510 : return 12; - case 0x250c : return 13; - case 0x2514 : return 14; - case 0x253c : return 15; - case 0xf800 : return 16; - case 0xf801 : return 17; - case 0x2500 : return 18; - case 0xf803 : return 19; - case 0xf804 : return 20; - case 0x251c : return 21; - case 0x2524 : return 22; - case 0x2534 : return 23; - case 0x252c : return 24; - case 0x2502 : return 25; - case 0x2264 : return 26; - case 0x2265 : return 27; - case 0x03c0 : return 28; - case 0x2260 : return 29; - case 0x00a3 : return 30; - case 0x00b7 : return 31; - } - return c; -} - -static QChar identicalMap(QChar c) -{ - return c; -} - -void Widget::fontChange(const QFont &) -{ - QFontMetrics fm(font()); - font_h = fm.height(); - font_w = fm.maxWidth(); - font_a = fm.ascent(); -//printf("font_h: %d\n",font_h); -//printf("font_w: %d\n",font_w); -//printf("font_a: %d\n",font_a); -//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii()); -//printf("rawname: %s\n",font().rawName().ascii()); - fontMap = -#if QT_VERSION < 300 - strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646") - ? vt100extended - : -#endif - identicalMap; - propagateSize(); - update(); -} - -void Widget::setVTFont(const QFont& f) -{ - QFrame::setFont(f); -} - -QFont Widget::getVTFont() { - return font(); -} - -void Widget::setFont(const QFont &) -{ - // ignore font change request if not coming from konsole itself -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Constructor / Destructor */ -/* */ -/* ------------------------------------------------------------------------- */ - -Widget::Widget(QWidget *parent, const char *name) : QFrame(parent,name) -{ -#ifndef QT_NO_CLIPBOARD - cb = QApplication::clipboard(); - QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), - this, SLOT(onClearSelection()) ); -#endif - - scrollbar = new QScrollBar(this); - scrollbar->setCursor( arrowCursor ); - connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); - - Config cfg("Konsole"); - cfg.setGroup("ScrollBar"); - switch( cfg.readNumEntry("Position",2)){ - case 0: - scrollLoc = SCRNONE; - break; - case 1: - scrollLoc = SCRLEFT; - break; - case 2: - scrollLoc = SCRRIGHT; - break; - }; - - blinkT = new QTimer(this); - connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent())); - // blinking = FALSE; - blinking = TRUE; - - resizing = FALSE; - actSel = 0; - image = 0; - lines = 1; - columns = 1; - font_w = 1; - font_h = 1; - font_a = 1; - word_selection_mode = FALSE; - - setMouseMarks(TRUE); - setVTFont( QFont("fixed") ); - setColorTable(base_color_table); // init color table - - qApp->installEventFilter( this ); //FIXME: see below -// KCursor::setAutoHideCursor( this, true ); - - // Init DnD //////////////////////////////////////////////////////////////// - currentSession = NULL; -// setAcceptDrops(true); // attempt -// m_drop = new QPopupMenu(this); -// m_drop->insertItem( QString("Paste"), 0); -// m_drop->insertItem( QString("cd"), 1); -// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int))); - - // we need focus so that the auto-hide cursor feature works - setFocus(); - setFocusPolicy( WheelFocus ); -} - -//FIXME: make proper destructor -// Here's a start (David) -Widget::~Widget() -{ - qApp->removeEventFilter( this ); - if (image) free(image); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Display Operations */ -/* */ -/* ------------------------------------------------------------------------- */ - -/*! - attributed string draw primitive -*/ - -void Widget::drawAttrStr(QPainter &paint, QRect rect, - QString& str, Character attr, BOOL pm, BOOL clear) -{ - if (pm && color_table[attr.b].transparent) - { - paint.setBackgroundMode( TransparentMode ); - if (clear) erase(rect); - } - else - { - if (blinking) - paint.fillRect(rect, color_table[attr.b].color); - else - { - paint.setBackgroundMode( OpaqueMode ); - paint.setBackgroundColor( color_table[attr.b].color ); - } - } - - if (color_table[attr.f].bold) - paint.setPen(QColor( 0x8F, 0x00, 0x00 )); - else - paint.setPen(color_table[attr.f].color); - - paint.drawText(rect.x(),rect.y()+font_a, str); - - if (attr.r & RE_UNDERLINE) - paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 ); -} - -/*! - The image can only be set completely. - - The size of the new image may or may not match the size of the widget. -*/ - -void Widget::setImage(const Character* const newimg, int lines, int columns) -{ int y,x,len; - const QPixmap* pm = backgroundPixmap(); - QPainter paint; - setUpdatesEnabled(FALSE); - paint.begin( this ); -HCNT("setImage"); - - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - hasBlinker = FALSE; - - int cf = -1; // undefined - int cb = -1; // undefined - int cr = -1; // undefined - - int lins = QMIN(this->lines, QMAX(0,lines )); - int cols = QMIN(this->columns,QMAX(0,columns)); - QChar *disstrU = new QChar[cols]; - -//{ static int cnt = 0; printf("setImage %d\n",cnt++); } - for (y = 0; y < lins; y++) - { - const Character* lcl = &image[y*this->columns]; - const Character* const ext = &newimg[y*columns]; - if (!resizing) // not while resizing, we're expecting a paintEvent - for (x = 0; x < cols; x++) - { - hasBlinker |= (ext[x].r & RE_BLINK); - if (ext[x] != lcl[x]) - { - cr = ext[x].r; - cb = ext[x].b; - if (ext[x].f != cf) cf = ext[x].f; - int lln = cols - x; - disstrU[0] = fontMap(ext[x+0].c); - for (len = 1; len < lln; len++) - { - if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr || - ext[x+len] == lcl[x+len] ) - break; - disstrU[len] = fontMap(ext[x+len].c); - } - QString unistr(disstrU,len); - drawAttrStr(paint, - QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), - unistr, ext[x], pm != NULL, true); - x += len - 1; - } - } - // finally, make `image' become `newimg'. - memcpy((void*)lcl,(const void*)ext,cols*sizeof(Character)); - } - drawFrame( &paint ); - paint.end(); - setUpdatesEnabled(TRUE); - if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms - if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; } - delete [] disstrU; -} - -// paint Event //////////////////////////////////////////////////// - -/*! - The difference of this routine vs. the `setImage' is, - that the drawing does not include a difference analysis - between the old and the new image. Instead, the internal - image is used and the painting bound by the PaintEvent box. -*/ - -void Widget::paintEvent( QPaintEvent* pe ) -{ - -//{ static int cnt = 0; printf("paint %d\n",cnt++); } - const QPixmap* pm = backgroundPixmap(); - QPainter paint; - setUpdatesEnabled(FALSE); - paint.begin( this ); - paint.setBackgroundMode( TransparentMode ); -HCNT("paintEvent"); - - // Note that the actual widget size can be slightly larger - // that the image (the size is truncated towards the smaller - // number of characters in `resizeEvent'. The paint rectangle - // can thus be larger than the image, but less then the size - // of one character. - - QRect rect = pe->rect().intersect(contentsRect()); - - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - - int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w)); - int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h)); - int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w)); - int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h)); - - /* - printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly, - rect.left(), rect.right(), rect.top(), rect.bottom()); - */ - - // if (pm != NULL && color_table[image->b].transparent) - // erase(rect); - // BL: I have no idea why we need this, and it breaks the refresh. - - QChar *disstrU = new QChar[columns]; - for (int y = luy; y <= rly; y++) - for (int x = lux; x <= rlx; x++) - { - int len = 1; - disstrU[0] = fontMap(image[loc(x,y)].c); - int cf = image[loc(x,y)].f; - int cb = image[loc(x,y)].b; - int cr = image[loc(x,y)].r; - while (x+len <= rlx && - image[loc(x+len,y)].f == cf && - image[loc(x+len,y)].b == cb && - image[loc(x+len,y)].r == cr ) - { - disstrU[len] = fontMap(image[loc(x+len,y)].c); - len += 1; - } - QString unistr(disstrU,len); - drawAttrStr(paint, - QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), - unistr, image[loc(x,y)], pm != NULL, false); - x += len - 1; - } - delete [] disstrU; - drawFrame( &paint ); - paint.end(); - setUpdatesEnabled(TRUE); -} - -void Widget::blinkEvent() -{ - blinking = !blinking; - repaint(FALSE); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Resizing */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Widget::resizeEvent(QResizeEvent* ev) -{ -// printf("resize: %d,%d\n",ev->size().width(),ev->size().height()); - //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h); - //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h); - //printf("curren: %d,%d\n",width(),height()); -HCNT("resizeEvent"); - - // see comment in `paintEvent' concerning the rounding. - //FIXME: could make a routine here; check width(),height() - assert(ev->size().width() == width()); - assert(ev->size().height() == height()); - - propagateSize(); -} - -void Widget::propagateSize() -{ - Character* oldimg = image; - int oldlin = lines; - int oldcol = columns; - makeImage(); - // we copy the old image to reduce flicker - int lins = QMIN(oldlin,lines); - int cols = QMIN(oldcol,columns); - if (oldimg) - { - for (int lin = 0; lin < lins; lin++) - memcpy((void*)&image[columns*lin], - (void*)&oldimg[oldcol*lin],cols*sizeof(Character)); - free(oldimg); //FIXME: try new,delete - } - else - clearImage(); - - //NOTE: control flows from the back through the chest right into the eye. - // `emu' will call back via `setImage'. - - resizing = TRUE; - emit changedImageSizeSignal(lines, columns); // expose resizeEvent - resizing = FALSE; -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Scrollbar */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Widget::scrollChanged(int) -{ - emit changedHistoryCursor(scrollbar->value()); //expose -} - -void Widget::setScroll(int cursor, int slines) -{ - disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); - scrollbar->setRange(0,slines); - scrollbar->setSteps(1,lines); - scrollbar->setValue(cursor); - connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); -} - -void Widget::setScrollbarLocation(int loc) -{ - if (scrollLoc == loc) return; // quickly - scrollLoc = loc; - propagateSize(); - update(); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Mouse */ -/* */ -/* ------------------------------------------------------------------------- */ - -/*! - Three different operations can be performed using the mouse, and the - routines in this section serve all of them: - - 1) The press/release events are exposed to the application - 2) Marking (press and move left button) and Pasting (press middle button) - 3) The right mouse button is used from the configuration menu - - NOTE: During the marking process we attempt to keep the cursor within - the bounds of the text as being displayed by setting the mouse position - whenever the mouse has left the text area. - - Two reasons to do so: - 1) QT does not allow the `grabMouse' to confine-to the Widget. - Thus a `XGrapPointer' would have to be used instead. - 2) Even if so, this would not help too much, since the text area - of the Widget is normally not identical with it's bounds. - - The disadvantage of the current handling is, that the mouse can visibly - leave the bounds of the widget and is then moved back. Because of the - current construction, and the reasons mentioned above, we cannot do better - without changing the overall construction. -*/ - -/*! -*/ - -void Widget::mousePressEvent(QMouseEvent* ev) -{ -//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); - if ( !contentsRect().contains(ev->pos()) ) return; - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - - word_selection_mode = FALSE; - -//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY); - if ( ev->button() == LeftButton) - { - QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); - - if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ; - - if (mouse_marks || (ev->state() & ShiftButton)) - { - emit clearSelectionSignal(); - iPntSel = pntSel = pos; - actSel = 1; // left mouse button pressed but nothing selected yet. - grabMouse( /*crossCursor*/ ); // handle with care! - } - else - { - emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button - } - } - if ( ev->button() == MidButton ) - { - emitSelection(); - } - if ( ev->button() == RightButton ) // Configure - { - emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() ); - } -} - -void Widget::mouseMoveEvent(QMouseEvent* ev) -{ - // for auto-hiding the cursor, we need mouseTracking - if (ev->state() == NoButton ) return; - - if (actSel == 0) return; - - // don't extend selection while pasting - if (ev->state() & MidButton) return; - - //if ( !contentsRect().contains(ev->pos()) ) return; - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - int scroll = scrollbar->value(); - - // we're in the process of moving the mouse with the left button pressed - // the mouse cursor will kept catched within the bounds of the text in - // this widget. - - // Adjust position within text area bounds. See FIXME above. - QPoint pos = ev->pos(); - if ( pos.x() < tLx+blX ) pos.setX( tLx+blX ); - if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w ); - if ( pos.y() < tLy+bY ) pos.setY( tLy+bY ); - if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 ); - // check if we produce a mouse move event by this - if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos)); - - if ( pos.y() == tLy+bY+lines*font_h-1 ) - { - scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward - } - if ( pos.y() == tLy+bY ) - { - scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback - } - - QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h); - QPoint ohere; - bool swapping = FALSE; - - if ( word_selection_mode ) - { - // Extend to word boundaries - int i; - int selClass; - - bool left_not_right = ( here.y() < iPntSel.y() || - here.y() == iPntSel.y() && here.x() < iPntSel.x() ); - bool old_left_not_right = ( pntSel.y() < iPntSel.y() || - pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() ); - swapping = left_not_right != old_left_not_right; - - // Find left (left_not_right ? from here : from start) - QPoint left = left_not_right ? here : iPntSel; - i = loc(left.x(),left.y()); - selClass = charClass(image[i].c); - while ( left.x() > 0 && charClass(image[i-1].c) == selClass ) - { i--; left.rx()--; } - - // Find left (left_not_right ? from start : from here) - QPoint right = left_not_right ? iPntSel : here; - i = loc(right.x(),right.y()); - selClass = charClass(image[i].c); - while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass ) - { i++; right.rx()++; } - - // Pick which is start (ohere) and which is extension (here) - if ( left_not_right ) - { - here = left; ohere = right; - } - else - { - here = right; ohere = left; - } - } - - if (here == pntSel && scroll == scrollbar->value()) return; // not moved - - if ( word_selection_mode ) { - if ( actSel < 2 || swapping ) { - emit beginSelectionSignal( ohere.x(), ohere.y() ); - } - } else if ( actSel < 2 ) { - emit beginSelectionSignal( pntSel.x(), pntSel.y() ); - } - - actSel = 2; // within selection - pntSel = here; - emit extendSelectionSignal( here.x(), here.y() ); -} - -void Widget::mouseReleaseEvent(QMouseEvent* ev) -{ -//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); - if ( ev->button() == LeftButton) - { - if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks); - preserve_line_breaks = TRUE; - actSel = 0; - - //FIXME: emits a release event even if the mouse is - // outside the range. The procedure used in `mouseMoveEvent' - // applies here, too. - - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - - if (!mouse_marks && !(ev->state() & ShiftButton)) - emit mouseSignal( 3, // release - (ev->x()-tLx-blX)/font_w + 1, - (ev->y()-tLy-bY)/font_h + 1 ); - releaseMouse(); - } -} - -void Widget::mouseDoubleClickEvent(QMouseEvent* ev) -{ - if ( ev->button() != LeftButton) return; - - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); - - // pass on double click as two clicks. - if (!mouse_marks && !(ev->state() & ShiftButton)) - { - emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button - emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release - emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button - return; - } - - - emit clearSelectionSignal(); - QPoint bgnSel = pos; - QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); - int i = loc(bgnSel.x(),bgnSel.y()); - iPntSel = bgnSel; - - word_selection_mode = TRUE; - - // find word boundaries... - int selClass = charClass(image[i].c); - { - // set the start... - int x = bgnSel.x(); - while ( x > 0 && charClass(image[i-1].c) == selClass ) - { i--; x--; } - bgnSel.setX(x); - emit beginSelectionSignal( bgnSel.x(), bgnSel.y() ); - - // set the end... - i = loc( endSel.x(), endSel.y() ); - x = endSel.x(); - while( x < columns-1 && charClass(image[i+1].c) == selClass ) - { i++; x++ ; } - endSel.setX(x); - actSel = 2; // within selection - emit extendSelectionSignal( endSel.x(), endSel.y() ); - emit endSelectionSignal(preserve_line_breaks); - preserve_line_breaks = TRUE; - } -} - -void Widget::focusInEvent( QFocusEvent * ) -{ - - // do nothing, to prevent repainting -} - - -void Widget::focusOutEvent( QFocusEvent * ) -{ - // do nothing, to prevent repainting -} - -bool Widget::focusNextPrevChild( bool next ) -{ - if (next) - return false; // This disables changing the active part in konqueror - // when pressing Tab - return QFrame::focusNextPrevChild( next ); -} - - -int Widget::charClass(char ch) const -{ - // This might seem like overkill, but imagine if ch was a Unicode - // character (Qt 2.0 QChar) - it might then be sensible to separate - // the different language ranges, etc. - - if ( isspace(ch) ) return ' '; - - static const char *word_characters = ":@-./_~"; - if ( isalnum(ch) || strchr(word_characters, ch) ) - return 'a'; - - // Everything else is weird - return 1; -} - -void Widget::setMouseMarks(bool on) -{ - mouse_marks = on; - setCursor( mouse_marks ? ibeamCursor : arrowCursor ); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Clipboard */ -/* */ -/* ------------------------------------------------------------------------- */ - -#undef KeyPress - -void Widget::emitSelection() -// Paste Clipboard by simulating keypress events -{ -#ifndef QT_NO_CLIPBOARD - QString text = QApplication::clipboard()->text(); - if ( ! text.isNull() ) - { - text.replace(QRegExp("\n"), "\r"); - QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); - emit keyPressedSignal(&e); // expose as a big fat keypress event - emit clearSelectionSignal(); - } -#endif -} - -void Widget::emitText(QString text) -{ - QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); - emit keyPressedSignal(&e); // expose as a big fat keypress event -} - -void Widget::pasteClipboard( ) -{ - emitSelection(); -} - -void Widget::setSelection(const QString& t) -{ -#ifndef QT_NO_CLIPBOARD - // Disconnect signal while WE set the clipboard - QObject *cb = QApplication::clipboard(); - QObject::disconnect( cb, SIGNAL(dataChanged()), - this, SLOT(onClearSelection()) ); - - QApplication::clipboard()->setText(t); - - QObject::connect( cb, SIGNAL(dataChanged()), - this, SLOT(onClearSelection()) ); -#endif -} - -void Widget::onClearSelection() -{ - emit clearSelectionSignal(); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Keyboard */ -/* */ -/* ------------------------------------------------------------------------- */ - -//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent' -// due to a bug in `QT' or the ignorance of the author to prevent -// repaint events being emitted to the screen whenever one leaves -// or reenters the screen to/from another application. -// -// Troll says one needs to change focusInEvent() and focusOutEvent(), -// which would also let you have an in-focus cursor and an out-focus -// cursor like xterm does. - -// for the auto-hide cursor feature, I added empty focusInEvent() and -// focusOutEvent() so that update() isn't called. -// For auto-hide, we need to get keypress-events, but we only get them when -// we have focus. - -void Widget::doScroll(int lines) -{ - scrollbar->setValue(scrollbar->value()+lines); -} - -bool Widget::eventFilter( QObject *obj, QEvent *e ) -{ - if ( (e->type() == QEvent::Accel || - e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) { - static_cast( e )->ignore(); - return true; - } - if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ ) - return FALSE; // not us - if ( e->type() == QEvent::Wheel) { - QApplication::sendEvent(scrollbar, e); - } - -#ifdef FAKE_CTRL_AND_ALT - static bool control = FALSE; - static bool alt = FALSE; - bool dele=FALSE; - if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { - QKeyEvent* ke = (QKeyEvent*)e; - bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat(); - switch (ke->key()) { - case Key_F9: // let this be "Control" - control = keydown; - e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state()); - dele=TRUE; - break; - case Key_F13: // let this be "Alt" - alt = keydown; - e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state()); - dele=TRUE; - break; - default: - if ( control ) { - int a = toupper(ke->ascii())-64; - if ( a >= 0 && a < ' ' ) { - e = new QKeyEvent(e->type(), ke->key(), - a, ke->state()|ControlButton, QChar(a,0)); - dele=TRUE; - } - } - if ( alt ) { - e = new QKeyEvent(e->type(), ke->key(), - ke->ascii(), ke->state()|AltButton, ke->text()); - dele=TRUE; - } - } - } -#endif - - if ( e->type() == QEvent::KeyPress ) { - QKeyEvent* ke = (QKeyEvent*)e; - actSel=0; // Key stroke implies a screen update, so Widget won't - // know where the current selection is. - - if( ke->state() == ShiftButton && ke->key() == Key_Tab) { //lets hardcode this sucker - emitText("\\"); // expose - } else - emit keyPressedSignal(ke); // expose - ke->accept(); -#ifdef FAKE_CTRL_AND_ALT - if ( dele ) delete e; -#endif - return true; // stop the event - } - if ( e->type() == QEvent::Enter ) { - QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()), - this, SLOT(onClearSelection()) ); - } - if ( e->type() == QEvent::Leave ) { - QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), - this, SLOT(onClearSelection()) ); - } - return QFrame::eventFilter( obj, e ); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Frame */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Widget::frameChanged() -{ - propagateSize(); - update(); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Sound */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Widget::Bell() -{ - QApplication::beep(); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Auxiluary */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Widget::clearImage() -// initialize the image -// for internal use only -{ - for (int y = 0; y < lines; y++) - for (int x = 0; x < columns; x++) - { - image[loc(x,y)].c = 0xff; //' '; - image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR; - image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR; - image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION; - } -} - -// Create Image /////////////////////////////////////////////////////// - -void Widget::calcGeometry() -{ - //FIXME: set rimX == rimY == 0 when running in full screen mode. - - scrollbar->resize(QApplication::style().scrollBarExtent().width(), - contentsRect().height()); - switch(scrollLoc) - { - case SCRNONE : - columns = ( contentsRect().width() - 2 * rimX ) / font_w; - blX = (contentsRect().width() - (columns*font_w) ) / 2; - brX = blX; - scrollbar->hide(); - break; - case SCRLEFT : - columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; - brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; - blX = brX + scrollbar->width(); - scrollbar->move(contentsRect().topLeft()); - scrollbar->show(); - break; - case SCRRIGHT: - columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; - blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; - brX = blX; - scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0)); - scrollbar->show(); - break; - } - //FIXME: support 'rounding' styles - lines = ( contentsRect().height() - 2 * rimY ) / font_h; - bY = (contentsRect().height() - (lines *font_h)) / 2; -} - -void Widget::makeImage() -//FIXME: rename 'calcGeometry? -{ - calcGeometry(); - image = (Character*) malloc(lines*columns*sizeof(Character)); - clearImage(); -} - -// calculate the needed size -QSize Widget::calcSize(int cols, int lins) const -{ - int frw = width() - contentsRect().width(); - int frh = height() - contentsRect().height(); - int scw = (scrollLoc==SCRNONE?0:scrollbar->width()); - return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh ); -} - -QSize Widget::sizeHint() const -{ - return size(); -} - -void Widget::styleChange(QStyle &) -{ - propagateSize(); -} - -#ifndef QT_NO_DRAGANDDROP - -/* --------------------------------------------------------------------- */ -/* */ -/* Drag & Drop */ -/* */ -/* --------------------------------------------------------------------- */ - - -void Widget::dragEnterEvent(QDragEnterEvent* e) -{ - e->accept(QTextDrag::canDecode(e) || - QUriDrag::canDecode(e)); -} - -void Widget::dropEvent(QDropEvent* event) -{ - // The current behaviour when url(s) are dropped is - // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd - // * in all other cases, just paste - // (for non-local ones, or for a list of URLs, 'cd' is nonsense) - QStrList strlist; - int file_count = 0; - dropText = ""; - bool bPopup = true; - - if(QUriDrag::decode(event, strlist)) { - if (strlist.count()) { - for(const char* p = strlist.first(); p; p = strlist.next()) { - if(file_count++ > 0) { - dropText += " "; - bPopup = false; // more than one file, don't popup - } - -/* - KURL url(p); - if (url.isLocalFile()) { - dropText += url.path(); // local URL : remove protocol - } - else { - dropText += url.prettyURL(); - bPopup = false; // a non-local file, don't popup - } -*/ - - } - - if (bPopup) - // m_drop->popup(pos() + event->pos()); - m_drop->popup(mapToGlobal(event->pos())); - else - { - if (currentSession) { - //currentSession->getEmulation()->sendString(dropText.local8Bit()); - QByteArray tmp; - // ibot: this should be pretty wrong... - // now it sends to the right layer - currentSession-> emulationLayer()->send( tmp.setRawData( dropText.local8Bit())); - } - // kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; - } - } - } - else if(QTextDrag::decode(event, dropText)) { -// kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; - if (currentSession) { - //currentSession->getEmulation()->sendString(dropText.local8Bit()); - QByteArray tmp; - currentSession->emulationLayer()->send( tmp.setRawData( dropText.local8Bit())); - } - // Paste it - } -} -#endif - - -void Widget::drop_menu_activated(int item) -{ -#ifndef QT_NO_DRAGANDDROP - QByteArray tmp; - switch (item) - { - case 0: // paste - //currentSession->getEmulation()->sendString(dropText.local8Bit()); - currentSession->emulationLayer()->send( tmp.setRawData( dropText.local8Bit())); - -// KWM::activate((Window)this->winId()); - break; - case 1: // cd ... - //currentSession->getEmulation()->sendString("cd "); - tmp.setRawData( "cd " ); - currentSession->emulationLayer()->send( tmp ); - struct stat statbuf; - if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 ) - { - if ( !S_ISDIR(statbuf.st_mode) ) - { -/* - KURL url; - url.setPath( dropText ); - dropText = url.directory( true, false ); // remove filename -*/ - } - } - dropText.replace(QRegExp(" "), "\\ "); // escape spaces - QByteArray tmp2; - tmp.setRawDate( dropText.local8Bit() + "\n" ); - //currentSession->getEmulation()->sendString(dropText.local8Bit()); - //currentSession->getEmulation()->sendString("\n"); - currentSession->emulationLayer()->send( tmp ); -// KWM::activate((Window)this->winId()); - break; - } -#endif -} - -- cgit v0.9.0.2