-rw-r--r-- | noncore/apps/opie-console/widget.cpp | 5 |
1 files changed, 0 insertions, 5 deletions
diff --git a/noncore/apps/opie-console/widget.cpp b/noncore/apps/opie-console/widget.cpp index c51983f..4a578be 100644 --- a/noncore/apps/opie-console/widget.cpp +++ b/noncore/apps/opie-console/widget.cpp @@ -486,798 +486,793 @@ HCNT("paintEvent"); 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<QKeyEvent *>( 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; -// odebug << " Has a keyboard with no CTRL and ALT keys, but we fake it:" << oendl; 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. -// odebug << "key pressed is 0x" << ke->key() << "" << oendl; - if( ke->state() == ShiftButton && ke->key() == Key_Tab) { //lets hardcode this sucker - -// odebug << "key pressed 2 is 0x" << ke->key() << "" << oendl; 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 } |