00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "khtmlview.moc"
00028
00029 #include "khtmlview.h"
00030
00031 #include "khtml_part.h"
00032 #include "khtml_events.h"
00033
00034 #include "html/html_documentimpl.h"
00035 #include "html/html_inlineimpl.h"
00036 #include "html/html_formimpl.h"
00037 #include "rendering/render_arena.h"
00038 #include "rendering/render_canvas.h"
00039 #include "rendering/render_frames.h"
00040 #include "rendering/render_replaced.h"
00041 #include "rendering/render_layer.h"
00042 #include "rendering/render_line.h"
00043 #include "rendering/render_table.h"
00044
00045 #define protected public
00046 #include "rendering/render_text.h"
00047 #undef protected
00048 #include "xml/dom2_eventsimpl.h"
00049 #include "css/cssstyleselector.h"
00050 #include "css/csshelper.h"
00051 #include "misc/htmlhashes.h"
00052 #include "misc/helper.h"
00053 #include "misc/loader.h"
00054 #include "khtml_settings.h"
00055 #include "khtml_printsettings.h"
00056
00057 #include "khtmlpart_p.h"
00058
00059 #ifndef KHTML_NO_CARET
00060 #include "khtml_caret_p.h"
00061 #include "xml/dom2_rangeimpl.h"
00062 #endif
00063
00064 #include <kapplication.h>
00065 #include <kcursor.h>
00066 #include <kdebug.h>
00067 #include <kdialogbase.h>
00068 #include <kiconloader.h>
00069 #include <kimageio.h>
00070 #include <klocale.h>
00071 #include <knotifyclient.h>
00072 #include <kprinter.h>
00073 #include <ksimpleconfig.h>
00074 #include <kstandarddirs.h>
00075 #include <kstdaccel.h>
00076 #include <kstringhandler.h>
00077 #include <kurldrag.h>
00078
00079 #include <qbitmap.h>
00080 #include <qlabel.h>
00081 #include <qobjectlist.h>
00082 #include <qpaintdevicemetrics.h>
00083 #include <qpainter.h>
00084 #include <qptrdict.h>
00085 #include <qtooltip.h>
00086 #include <qstring.h>
00087 #include <qstylesheet.h>
00088 #include <qtimer.h>
00089 #include <qvaluevector.h>
00090
00091
00092
00093
00094
00095
00096
00097 #ifdef Q_WS_X11
00098 #include <X11/Xlib.h>
00099 #include <fixx11h.h>
00100 #endif
00101
00102 #define PAINT_BUFFER_HEIGHT 128
00103
00104 #if 0
00105 namespace khtml {
00106 void dumpLineBoxes(RenderFlow *flow);
00107 }
00108 #endif
00109
00110 using namespace DOM;
00111 using namespace khtml;
00112 class KHTMLToolTip;
00113
00114
00115 #ifndef QT_NO_TOOLTIP
00116
00117 class KHTMLToolTip : public QToolTip
00118 {
00119 public:
00120 KHTMLToolTip(KHTMLView *view, KHTMLViewPrivate* vp) : QToolTip(view->viewport())
00121 {
00122 m_view = view;
00123 m_viewprivate = vp;
00124 };
00125
00126 protected:
00127 virtual void maybeTip(const QPoint &);
00128
00129 private:
00130 KHTMLView *m_view;
00131 KHTMLViewPrivate* m_viewprivate;
00132 };
00133
00134 #endif
00135
00136 class KHTMLViewPrivate {
00137 friend class KHTMLToolTip;
00138 public:
00139
00140 enum PseudoFocusNodes {
00141 PFNone,
00142 PFTop,
00143 PFBottom
00144 };
00145
00146 enum CompletedState {
00147 CSNone = 0,
00148 CSFull,
00149 CSActionPending
00150 };
00151
00152 KHTMLViewPrivate()
00153 : underMouse( 0 ), underMouseNonShared( 0 ), visibleWidgets( 107 )
00154 {
00155 #ifndef KHTML_NO_CARET
00156 m_caretViewContext = 0;
00157 m_editorContext = 0;
00158 #endif // KHTML_NO_CARET
00159 postponed_autorepeat = NULL;
00160 reset();
00161 vmode = QScrollView::Auto;
00162 hmode = QScrollView::Auto;
00163 tp=0;
00164 paintBuffer=0;
00165 vertPaintBuffer=0;
00166 formCompletions=0;
00167 prevScrollbarVisible = true;
00168 tooltip = 0;
00169 possibleTripleClick = false;
00170 emitCompletedAfterRepaint = CSNone;
00171 cursor_icon_widget = NULL;
00172 m_mouseScrollTimer = 0;
00173 m_mouseScrollIndicator = 0;
00174 }
00175 ~KHTMLViewPrivate()
00176 {
00177 delete formCompletions;
00178 delete tp; tp = 0;
00179 delete paintBuffer; paintBuffer =0;
00180 delete vertPaintBuffer;
00181 delete postponed_autorepeat;
00182 if (underMouse)
00183 underMouse->deref();
00184 if (underMouseNonShared)
00185 underMouseNonShared->deref();
00186 delete tooltip;
00187 #ifndef KHTML_NO_CARET
00188 delete m_caretViewContext;
00189 delete m_editorContext;
00190 #endif // KHTML_NO_CARET
00191 delete cursor_icon_widget;
00192 delete m_mouseScrollTimer;
00193 delete m_mouseScrollIndicator;
00194 }
00195 void reset()
00196 {
00197 if (underMouse)
00198 underMouse->deref();
00199 underMouse = 0;
00200 if (underMouseNonShared)
00201 underMouseNonShared->deref();
00202 underMouseNonShared = 0;
00203 linkPressed = false;
00204 useSlowRepaints = false;
00205 tabMovePending = false;
00206 lastTabbingDirection = true;
00207 pseudoFocusNode = PFNone;
00208 #ifndef KHTML_NO_SCROLLBARS
00209
00210
00211
00212
00213 #else
00214 vmode = QScrollView::AlwaysOff;
00215 hmode = QScrollView::AlwaysOff;
00216 #endif
00217 #ifdef DEBUG_PIXEL
00218 timer.start();
00219 pixelbooth = 0;
00220 repaintbooth = 0;
00221 #endif
00222 scrollBarMoved = false;
00223 contentsMoving = false;
00224 ignoreWheelEvents = false;
00225 borderX = 30;
00226 borderY = 30;
00227 paged = false;
00228 clickX = -1;
00229 clickY = -1;
00230 prevMouseX = -1;
00231 prevMouseY = -1;
00232 clickCount = 0;
00233 isDoubleClick = false;
00234 scrollingSelf = false;
00235 delete postponed_autorepeat;
00236 postponed_autorepeat = NULL;
00237 layoutTimerId = 0;
00238 repaintTimerId = 0;
00239 scrollTimerId = 0;
00240 scrollSuspended = false;
00241 scrollSuspendPreActivate = false;
00242 complete = false;
00243 firstRelayout = true;
00244 needsFullRepaint = true;
00245 dirtyLayout = false;
00246 layoutSchedulingEnabled = true;
00247 painting = false;
00248 updateRegion = QRegion();
00249 m_dialogsAllowed = true;
00250 #ifndef KHTML_NO_CARET
00251 if (m_caretViewContext) {
00252 m_caretViewContext->caretMoved = false;
00253 m_caretViewContext->keyReleasePending = false;
00254 }
00255 #endif // KHTML_NO_CARET
00256 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00257 typeAheadActivated = false;
00258 #endif // KHTML_NO_TYPE_AHEAD_FIND
00259 accessKeysActivated = false;
00260 accessKeysPreActivate = false;
00261
00262
00263 KHTMLFactory::ref();
00264 accessKeysEnabled = KHTMLFactory::defaultHTMLSettings()->accessKeysEnabled();
00265 KHTMLFactory::deref();
00266
00267 emitCompletedAfterRepaint = CSNone;
00268 }
00269 void newScrollTimer(QWidget *view, int tid)
00270 {
00271
00272 view->killTimer(scrollTimerId);
00273 scrollTimerId = tid;
00274 scrollSuspended = false;
00275 }
00276 enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
00277
00278 void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
00279 {
00280 static const struct { int msec, pixels; } timings [] = {
00281 {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
00282 {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
00283 };
00284 if (!scrollTimerId ||
00285 (static_cast<int>(scrollDirection) != direction &&
00286 (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) {
00287 scrollTiming = 6;
00288 scrollBy = timings[scrollTiming].pixels;
00289 scrollDirection = direction;
00290 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00291 } else if (scrollDirection == direction &&
00292 timings[scrollTiming+1].msec && !scrollSuspended) {
00293 scrollBy = timings[++scrollTiming].pixels;
00294 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00295 } else if (scrollDirection == oppositedir) {
00296 if (scrollTiming) {
00297 scrollBy = timings[--scrollTiming].pixels;
00298 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00299 }
00300 }
00301 scrollSuspended = false;
00302 }
00303
00304 #ifndef KHTML_NO_CARET
00305
00308 CaretViewContext *caretViewContext() {
00309 if (!m_caretViewContext) m_caretViewContext = new CaretViewContext();
00310 return m_caretViewContext;
00311 }
00315 EditorContext *editorContext() {
00316 if (!m_editorContext) m_editorContext = new EditorContext();
00317 return m_editorContext;
00318 }
00319 #endif // KHTML_NO_CARET
00320
00321 #ifdef DEBUG_PIXEL
00322 QTime timer;
00323 unsigned int pixelbooth;
00324 unsigned int repaintbooth;
00325 #endif
00326
00327 QPainter *tp;
00328 QPixmap *paintBuffer;
00329 QPixmap *vertPaintBuffer;
00330 NodeImpl *underMouse;
00331 NodeImpl *underMouseNonShared;
00332
00333 bool tabMovePending:1;
00334 bool lastTabbingDirection:1;
00335 PseudoFocusNodes pseudoFocusNode:2;
00336 bool scrollBarMoved:1;
00337 bool contentsMoving:1;
00338
00339 QScrollView::ScrollBarMode vmode;
00340 QScrollView::ScrollBarMode hmode;
00341 bool prevScrollbarVisible:1;
00342 bool linkPressed:1;
00343 bool useSlowRepaints:1;
00344 bool ignoreWheelEvents:1;
00345
00346 int borderX, borderY;
00347 KSimpleConfig *formCompletions;
00348
00349 bool paged;
00350
00351 int clickX, clickY, clickCount;
00352 bool isDoubleClick;
00353
00354 int prevMouseX, prevMouseY;
00355 bool scrollingSelf;
00356 int layoutTimerId;
00357 QKeyEvent* postponed_autorepeat;
00358
00359 int repaintTimerId;
00360 int scrollTimerId;
00361 int scrollTiming;
00362 int scrollBy;
00363 ScrollDirection scrollDirection :2;
00364 bool scrollSuspended :1;
00365 bool scrollSuspendPreActivate :1;
00366 bool complete :1;
00367 bool firstRelayout :1;
00368 bool layoutSchedulingEnabled :1;
00369 bool needsFullRepaint :1;
00370 bool painting :1;
00371 bool possibleTripleClick :1;
00372 bool dirtyLayout :1;
00373 bool m_dialogsAllowed :1;
00374 QRegion updateRegion;
00375 KHTMLToolTip *tooltip;
00376 QPtrDict<QWidget> visibleWidgets;
00377 #ifndef KHTML_NO_CARET
00378 CaretViewContext *m_caretViewContext;
00379 EditorContext *m_editorContext;
00380 #endif // KHTML_NO_CARET
00381 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00382 QString findString;
00383 QTimer timer;
00384 bool findLinksOnly;
00385 bool typeAheadActivated;
00386 #endif // KHTML_NO_TYPE_AHEAD_FIND
00387 bool accessKeysEnabled;
00388 bool accessKeysActivated;
00389 bool accessKeysPreActivate;
00390 CompletedState emitCompletedAfterRepaint;
00391
00392 QWidget* cursor_icon_widget;
00393
00394
00395 short m_mouseScroll_byX;
00396 short m_mouseScroll_byY;
00397 QTimer *m_mouseScrollTimer;
00398 QWidget *m_mouseScrollIndicator;
00399 };
00400
00401 #ifndef QT_NO_TOOLTIP
00402
00412 static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs,
00413 const QPoint &p, QRect &r, QString &s)
00414 {
00415 HTMLMapElementImpl* map;
00416 if (img && img->getDocument()->isHTMLDocument() &&
00417 (map = static_cast<HTMLDocumentImpl*>(img->getDocument())->getMap(img->imageMap()))) {
00418 RenderObject::NodeInfo info(true, false);
00419 RenderObject *rend = img->renderer();
00420 int ax, ay;
00421 if (!rend || !rend->absolutePosition(ax, ay))
00422 return false;
00423
00424 bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(),
00425 p.y() - ay + scrollOfs.y(), rend->contentWidth(),
00426 rend->contentHeight(), info);
00427 if (inside && info.URLElement()) {
00428 HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement());
00429 Q_ASSERT(area->id() == ID_AREA);
00430 s = area->getAttribute(ATTR_TITLE).string();
00431 QRegion reg = area->cachedRegion();
00432 if (!s.isEmpty() && !reg.isEmpty()) {
00433 r = reg.boundingRect();
00434 r.moveBy(ax, ay);
00435 return true;
00436 }
00437 }
00438 }
00439 return false;
00440 }
00441
00442 void KHTMLToolTip::maybeTip(const QPoint& p)
00443 {
00444 DOM::NodeImpl *node = m_viewprivate->underMouseNonShared;
00445 QRect region;
00446 while ( node ) {
00447 if ( node->isElementNode() ) {
00448 DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node );
00449 QRect r;
00450 QString s;
00451 bool found = false;
00452
00453
00454 if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) {
00455 found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e),
00456 m_view->viewportToContents(QPoint(0, 0)), p, r, s);
00457 }
00458 if (!found) {
00459 s = e->getAttribute( ATTR_TITLE ).string();
00460 r = node->getRect();
00461 }
00462 region |= QRect( m_view->contentsToViewport( r.topLeft() ), r.size() );
00463 if ( !s.isEmpty() ) {
00464 tip( region, QStyleSheet::convertFromPlainText( s, QStyleSheetItem::WhiteSpaceNormal ) );
00465 break;
00466 }
00467 }
00468 node = node->parentNode();
00469 }
00470 }
00471 #endif
00472
00473 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
00474 : QScrollView( parent, name, WResizeNoErase | WRepaintNoErase )
00475 {
00476 m_medium = "screen";
00477
00478 m_part = part;
00479 d = new KHTMLViewPrivate;
00480 QScrollView::setVScrollBarMode(d->vmode);
00481 QScrollView::setHScrollBarMode(d->hmode);
00482 connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged()));
00483 connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotScrollBarMoved()));
00484
00485
00486 enableClipper(true);
00487
00488 static_cast<KHTMLView *>(static_cast<QWidget *>(viewport()))->setWFlags(WPaintUnclipped);
00489
00490 setResizePolicy(Manual);
00491 viewport()->setMouseTracking(true);
00492 viewport()->setBackgroundMode(NoBackground);
00493
00494 KImageIO::registerFormats();
00495
00496 #ifndef QT_NO_TOOLTIP
00497 d->tooltip = new KHTMLToolTip( this, d );
00498 #endif
00499
00500 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00501 connect(&d->timer, SIGNAL(timeout()), this, SLOT(findTimeout()));
00502 #endif // KHTML_NO_TYPE_AHEAD_FIND
00503
00504 init();
00505
00506 viewport()->show();
00507 }
00508
00509 KHTMLView::~KHTMLView()
00510 {
00511 closeChildDialogs();
00512 if (m_part)
00513 {
00514
00515
00516 DOM::DocumentImpl *doc = m_part->xmlDocImpl();
00517 if (doc)
00518 doc->detach();
00519 }
00520 delete d; d = 0;
00521 }
00522
00523 void KHTMLView::init()
00524 {
00525 if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
00526 if(!d->vertPaintBuffer)
00527 d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
00528 if(!d->tp) d->tp = new QPainter();
00529
00530 setFocusPolicy(QWidget::StrongFocus);
00531 viewport()->setFocusProxy(this);
00532
00533 _marginWidth = -1;
00534 _marginHeight = -1;
00535 _width = 0;
00536 _height = 0;
00537
00538 installEventFilter(this);
00539
00540 setAcceptDrops(true);
00541 QSize s = viewportSize(4095, 4095);
00542 resizeContents(s.width(), s.height());
00543 }
00544
00545 void KHTMLView::clear()
00546 {
00547
00548 setStaticBackground(true);
00549 #ifndef KHTML_NO_CARET
00550 if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff();
00551 #endif
00552
00553 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00554 if( d->typeAheadActivated )
00555 findTimeout();
00556 #endif
00557 if (d->accessKeysEnabled && d->accessKeysActivated)
00558 accessKeysTimeout();
00559 viewport()->unsetCursor();
00560 if ( d->cursor_icon_widget )
00561 d->cursor_icon_widget->hide();
00562 d->reset();
00563 killTimers();
00564 emit cleared();
00565
00566 QScrollView::setHScrollBarMode(d->hmode);
00567 QScrollView::setVScrollBarMode(d->vmode);
00568 verticalScrollBar()->setEnabled( false );
00569 horizontalScrollBar()->setEnabled( false );
00570 }
00571
00572 void KHTMLView::hideEvent(QHideEvent* e)
00573 {
00574 QScrollView::hideEvent(e);
00575 if ( m_part && m_part->xmlDocImpl() )
00576 m_part->xmlDocImpl()->docLoader()->pauseAnimations();
00577 }
00578
00579 void KHTMLView::showEvent(QShowEvent* e)
00580 {
00581 QScrollView::showEvent(e);
00582 if ( m_part && m_part->xmlDocImpl() )
00583 m_part->xmlDocImpl()->docLoader()->resumeAnimations();
00584 }
00585
00586 void KHTMLView::resizeEvent (QResizeEvent* e)
00587 {
00588 int dw = e->oldSize().width() - e->size().width();
00589 int dh = e->oldSize().height() - e->size().height();
00590
00591
00592
00593 dw = dw>0 ? kMax(0, contentsWidth()-dw) : contentsWidth();
00594 dh = dh>0 ? kMax(0, contentsHeight()-dh) : contentsHeight();
00595
00596 resizeContents(dw, dh);
00597
00598 QScrollView::resizeEvent(e);
00599
00600 if ( m_part && m_part->xmlDocImpl() )
00601 m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
00602 }
00603
00604 void KHTMLView::viewportResizeEvent (QResizeEvent* e)
00605 {
00606 QScrollView::viewportResizeEvent(e);
00607
00608
00609
00610
00611 if (d->layoutSchedulingEnabled)
00612 layout();
00613 #ifndef KHTML_NO_CARET
00614 else {
00615 hideCaret();
00616 recalcAndStoreCaretPos();
00617 showCaret();
00618 }
00619 #endif
00620
00621 KApplication::sendPostedEvents(viewport(), QEvent::Paint);
00622 }
00623
00624
00625 void KHTMLView::drawContents( QPainter*)
00626 {
00627 }
00628
00629 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
00630 {
00631 #ifdef DEBUG_PIXEL
00632
00633 if ( d->timer.elapsed() > 5000 ) {
00634 qDebug( "drawed %d pixels in %d repaints the last %d milliseconds",
00635 d->pixelbooth, d->repaintbooth, d->timer.elapsed() );
00636 d->timer.restart();
00637 d->pixelbooth = 0;
00638 d->repaintbooth = 0;
00639 }
00640 d->pixelbooth += ew*eh;
00641 d->repaintbooth++;
00642 #endif
00643
00644
00645 if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
00646 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00647 return;
00648 } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
00649
00650 unscheduleRelayout();
00651 layout();
00652 }
00653
00654 if (d->painting) {
00655 kdDebug( 6000 ) << "WARNING: drawContents reentered! " << endl;
00656 return;
00657 }
00658 d->painting = true;
00659
00660 QPoint pt = contentsToViewport(QPoint(ex, ey));
00661 QRegion cr = QRect(pt.x(), pt.y(), ew, eh);
00662
00663
00664 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
00665 QWidget *w = it.current();
00666 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
00667 if (w && rw && !rw->isKHTMLWidget()) {
00668 int x, y;
00669 rw->absolutePosition(x, y);
00670 contentsToViewport(x, y, x, y);
00671 int pbx = rw->borderLeft()+rw->paddingLeft();
00672 int pby = rw->borderTop()+rw->paddingTop();
00673 QRect g = QRect(x+pbx, y+pby,
00674 rw->width()-pbx-rw->borderRight()-rw->paddingRight(),
00675 rw->height()-pby-rw->borderBottom()-rw->paddingBottom());
00676 if ( !rw->isFrame() && ((g.top() > pt.y()+eh) || (g.bottom() <= pt.y()) ||
00677 (g.right() <= pt.x()) || (g.left() > pt.x()+ew) ))
00678 continue;
00679 RenderLayer* rl = rw->needsMask() ? rw->enclosingStackingContext() : 0;
00680 QRegion mask = rl ? rl->getMask() : QRegion();
00681 if (!mask.isNull()) {
00682 QPoint o(0,0);
00683 o = contentsToViewport(o);
00684 mask.translate(o.x(),o.y());
00685 mask = mask.intersect( QRect(g.x(),g.y(),g.width(),g.height()) );
00686 cr -= mask;
00687 } else {
00688 cr -= g;
00689 }
00690 }
00691 }
00692
00693 #if 0
00694
00695
00696 if (cr.isEmpty()) {
00697 d->painting = false;
00698 return;
00699 }
00700 #endif
00701
00702 #ifndef DEBUG_NO_PAINT_BUFFER
00703 p->setClipRegion(cr);
00704
00705 if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
00706 if ( d->vertPaintBuffer->height() < visibleHeight() )
00707 d->vertPaintBuffer->resize(10, visibleHeight());
00708 d->tp->begin(d->vertPaintBuffer);
00709 d->tp->translate(-ex, -ey);
00710 d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00711 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey, ew, eh));
00712 d->tp->end();
00713 p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
00714 }
00715 else {
00716 if ( d->paintBuffer->width() < visibleWidth() )
00717 d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
00718
00719 int py=0;
00720 while (py < eh) {
00721 int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
00722 d->tp->begin(d->paintBuffer);
00723 d->tp->translate(-ex, -ey-py);
00724 d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
00725 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey+py, ew, ph));
00726 d->tp->end();
00727
00728 p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
00729 py += PAINT_BUFFER_HEIGHT;
00730 }
00731 }
00732 #else // !DEBUG_NO_PAINT_BUFFER
00733 static int cnt=0;
00734 ex = contentsX(); ey = contentsY();
00735 ew = visibleWidth(); eh = visibleHeight();
00736 QRect pr(ex,ey,ew,eh);
00737 kdDebug() << "[" << ++cnt << "]" << " clip region: " << pr << endl;
00738
00739
00740 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00741 m_part->xmlDocImpl()->renderer()->layer()->paint(p, pr);
00742 #endif // DEBUG_NO_PAINT_BUFFER
00743
00744 #ifndef KHTML_NO_CARET
00745 if (d->m_caretViewContext && d->m_caretViewContext->visible) {
00746 QRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y,
00747 d->m_caretViewContext->width, d->m_caretViewContext->height);
00748 if (pos.intersects(QRect(ex, ey, ew, eh))) {
00749 p->setRasterOp(XorROP);
00750 p->setPen(white);
00751 if (pos.width() == 1)
00752 p->drawLine(pos.topLeft(), pos.bottomRight());
00753 else {
00754 p->fillRect(pos, white);
00755 }
00756 }
00757 }
00758 #endif // KHTML_NO_CARET
00759
00760
00761
00762
00763 khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
00764 QApplication::sendEvent( m_part, &event );
00765
00766 d->painting = false;
00767 }
00768
00769 void KHTMLView::setMarginWidth(int w)
00770 {
00771
00772 _marginWidth = w;
00773 }
00774
00775 void KHTMLView::setMarginHeight(int h)
00776 {
00777
00778 _marginHeight = h;
00779 }
00780
00781 void KHTMLView::layout()
00782 {
00783 if( m_part && m_part->xmlDocImpl() ) {
00784 DOM::DocumentImpl *document = m_part->xmlDocImpl();
00785
00786 khtml::RenderCanvas* canvas = static_cast<khtml::RenderCanvas *>(document->renderer());
00787 if ( !canvas ) return;
00788
00789 d->layoutSchedulingEnabled=false;
00790
00791
00792 RenderObject * ref = 0;
00793 RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0;
00794
00795 if (document->isHTMLDocument()) {
00796 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00797 if(body && body->renderer() && body->id() == ID_FRAMESET) {
00798 QScrollView::setVScrollBarMode(AlwaysOff);
00799 QScrollView::setHScrollBarMode(AlwaysOff);
00800 body->renderer()->setNeedsLayout(true);
00801
00802
00803
00804
00805 }
00806 else {
00807 if (!d->tooltip)
00808 d->tooltip = new KHTMLToolTip( this, d );
00809
00810 if (root)
00811 ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer();
00812 }
00813 } else {
00814 ref = root;
00815 }
00816 if (ref) {
00817 if( ref->style()->overflowX() == OHIDDEN ) {
00818 if (d->hmode == Auto) QScrollView::setHScrollBarMode(AlwaysOff);
00819 } else if (ref->style()->overflowX() == OSCROLL ) {
00820 if (d->hmode == Auto) QScrollView::setHScrollBarMode(AlwaysOn);
00821 } else {
00822 if (QScrollView::hScrollBarMode() == AlwaysOff) QScrollView::setHScrollBarMode(d->hmode);
00823 } if ( ref->style()->overflowY() == OHIDDEN ) {
00824 if (d->vmode == Auto) QScrollView::setVScrollBarMode(AlwaysOff);
00825 } else if (ref->style()->overflowY() == OSCROLL ) {
00826 if (d->vmode == Auto) QScrollView::setVScrollBarMode(AlwaysOn);
00827 } else {
00828 if (QScrollView::vScrollBarMode() == AlwaysOff) QScrollView::setVScrollBarMode(d->vmode);
00829 }
00830 }
00831 d->needsFullRepaint = d->firstRelayout;
00832 if (_height != visibleHeight() || _width != visibleWidth()) {;
00833 d->needsFullRepaint = true;
00834 _height = visibleHeight();
00835 _width = visibleWidth();
00836 }
00837
00838
00839 canvas->layout();
00840
00841 emit finishedLayout();
00842 if (d->firstRelayout) {
00843
00844
00845 d->firstRelayout = false;
00846 verticalScrollBar()->setEnabled( true );
00847 horizontalScrollBar()->setEnabled( true );
00848 }
00849 #if 0
00850 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
00851 if (listitem) kdDebug(6000) << "after layout, before repaint" << endl;
00852 if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
00853 #endif
00854 #ifndef KHTML_NO_CARET
00855 hideCaret();
00856 if ((m_part->isCaretMode() || m_part->isEditable())
00857 && !d->complete && d->m_caretViewContext
00858 && !d->m_caretViewContext->caretMoved) {
00859 initCaret();
00860 } else {
00861 recalcAndStoreCaretPos();
00862 showCaret();
00863 }
00864 #endif
00865 if (d->accessKeysEnabled && d->accessKeysActivated) {
00866 emit hideAccessKeys();
00867 displayAccessKeys();
00868 }
00869
00870 }
00871 else
00872 _width = visibleWidth();
00873
00874 killTimer(d->layoutTimerId);
00875 d->layoutTimerId = 0;
00876 d->layoutSchedulingEnabled=true;
00877 }
00878
00879 void KHTMLView::closeChildDialogs()
00880 {
00881 QObjectList *dlgs = queryList("QDialog");
00882 for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
00883 {
00884 KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
00885 if ( dlgbase ) {
00886 if ( dlgbase->testWFlags( WShowModal ) ) {
00887 kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
00888
00889
00890 dlgbase->cancel();
00891 }
00892 }
00893 else
00894 {
00895 kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) << endl;
00896 static_cast<QWidget*>(dlg)->hide();
00897 }
00898 }
00899 delete dlgs;
00900 d->m_dialogsAllowed = false;
00901 }
00902
00903 bool KHTMLView::dialogsAllowed() {
00904 bool allowed = d->m_dialogsAllowed;
00905 KHTMLPart* p = m_part->parentPart();
00906 if (p && p->view())
00907 allowed &= p->view()->dialogsAllowed();
00908 return allowed;
00909 }
00910
00911 void KHTMLView::closeEvent( QCloseEvent* ev )
00912 {
00913 closeChildDialogs();
00914 QScrollView::closeEvent( ev );
00915 }
00916
00917
00918
00919
00921
00922 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
00923 {
00924 if (!m_part->xmlDocImpl()) return;
00925 if (d->possibleTripleClick && ( _mouse->button() & MouseButtonMask ) == LeftButton)
00926 {
00927 viewportMouseDoubleClickEvent( _mouse );
00928 return;
00929 }
00930
00931 int xm, ym;
00932 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00933
00934
00935 d->isDoubleClick = false;
00936
00937 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
00938 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00939
00940
00941
00942 if ( (_mouse->button() == MidButton) &&
00943 !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
00944 mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
00945 QPoint point = mapFromGlobal( _mouse->globalPos() );
00946
00947 d->m_mouseScroll_byX = 0;
00948 d->m_mouseScroll_byY = 0;
00949
00950 d->m_mouseScrollTimer = new QTimer( this );
00951 connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) );
00952
00953 if ( !d->m_mouseScrollIndicator ) {
00954 QPixmap pixmap, icon;
00955 pixmap.resize( 48, 48 );
00956 pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) );
00957
00958 QPainter p( &pixmap );
00959 icon = KGlobal::iconLoader()->loadIcon( "1uparrow", KIcon::Small );
00960 p.drawPixmap( 16, 0, icon );
00961 icon = KGlobal::iconLoader()->loadIcon( "1leftarrow", KIcon::Small );
00962 p.drawPixmap( 0, 16, icon );
00963 icon = KGlobal::iconLoader()->loadIcon( "1downarrow", KIcon::Small );
00964 p.drawPixmap( 16, 32,icon );
00965 icon = KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Small );
00966 p.drawPixmap( 32, 16, icon );
00967 p.drawEllipse( 23, 23, 2, 2 );
00968
00969 d->m_mouseScrollIndicator = new QWidget( this, 0 );
00970 d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
00971 d->m_mouseScrollIndicator->setPaletteBackgroundPixmap( pixmap );
00972 }
00973 d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
00974
00975 bool hasHorBar = visibleWidth() < contentsWidth();
00976 bool hasVerBar = visibleHeight() < contentsHeight();
00977
00978 KConfig *config = KGlobal::config();
00979 KConfigGroupSaver saver( config, "HTML Settings" );
00980 if ( config->readBoolEntry( "ShowMouseScrollIndicator", true ) ) {
00981 d->m_mouseScrollIndicator->show();
00982 d->m_mouseScrollIndicator->unsetCursor();
00983
00984 QBitmap mask = d->m_mouseScrollIndicator->paletteBackgroundPixmap()->createHeuristicMask( true );
00985
00986 if ( hasHorBar && !hasVerBar ) {
00987 QBitmap bm( 16, 16, true );
00988 bitBlt( &mask, 16, 0, &bm, 0, 0, -1, -1 );
00989 bitBlt( &mask, 16, 32, &bm, 0, 0, -1, -1 );
00990 d->m_mouseScrollIndicator->setCursor( KCursor::SizeHorCursor );
00991 }
00992 else if ( !hasHorBar && hasVerBar ) {
00993 QBitmap bm( 16, 16, true );
00994 bitBlt( &mask, 0, 16, &bm, 0, 0, -1, -1 );
00995 bitBlt( &mask, 32, 16, &bm, 0, 0, -1, -1 );
00996 d->m_mouseScrollIndicator->setCursor( KCursor::SizeVerCursor );
00997 }
00998 else
00999 d->m_mouseScrollIndicator->setCursor( KCursor::SizeAllCursor );
01000
01001 d->m_mouseScrollIndicator->setMask( mask );
01002 }
01003 else {
01004 if ( hasHorBar && !hasVerBar )
01005 viewport()->setCursor( KCursor::SizeHorCursor );
01006 else if ( !hasHorBar && hasVerBar )
01007 viewport()->setCursor( KCursor::SizeVerCursor );
01008 else
01009 viewport()->setCursor( KCursor::SizeAllCursor );
01010 }
01011
01012 return;
01013 }
01014 else if ( d->m_mouseScrollTimer ) {
01015 delete d->m_mouseScrollTimer;
01016 d->m_mouseScrollTimer = 0;
01017
01018 if ( d->m_mouseScrollIndicator )
01019 d->m_mouseScrollIndicator->hide();
01020 }
01021
01022 d->clickCount = 1;
01023 d->clickX = xm;
01024 d->clickY = ym;
01025
01026 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01027 d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
01028
01029 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01030 if (r && r->isWidget())
01031 _mouse->ignore();
01032
01033 if (!swallowEvent) {
01034 emit m_part->nodeActivated(mev.innerNode);
01035
01036 khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01037 QApplication::sendEvent( m_part, &event );
01038
01039 }
01040 }
01041
01042 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
01043 {
01044 if(!m_part->xmlDocImpl()) return;
01045
01046 int xm, ym;
01047 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01048
01049 kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
01050
01051 d->isDoubleClick = true;
01052
01053 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
01054 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01055
01056
01057
01058 if (d->clickCount > 0 &&
01059 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
01060 d->clickCount++;
01061 else {
01062 d->clickCount = 1;
01063 d->clickX = xm;
01064 d->clickY = ym;
01065 }
01066 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01067 d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
01068
01069 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01070 if (r && r->isWidget())
01071 _mouse->ignore();
01072
01073 if (!swallowEvent) {
01074 khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
01075 QApplication::sendEvent( m_part, &event );
01076 }
01077
01078 d->possibleTripleClick=true;
01079 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
01080 }
01081
01082 void KHTMLView::tripleClickTimeout()
01083 {
01084 d->possibleTripleClick = false;
01085 d->clickCount = 0;
01086 }
01087
01088 static inline void forwardPeripheralEvent(khtml::RenderWidget* r, QMouseEvent* me, int x, int y)
01089 {
01090 int absx = 0;
01091 int absy = 0;
01092 r->absolutePosition(absx, absy);
01093 QPoint p(x-absx, y-absy);
01094 QMouseEvent fw(me->type(), p, me->button(), me->state());
01095 QWidget* w = r->widget();
01096 QScrollView* sc = ::qt_cast<QScrollView*>(w);
01097 if (sc && !::qt_cast<QListBox*>(w))
01098 static_cast<khtml::RenderWidget::ScrollViewEventPropagator*>(sc)->sendEvent(&fw);
01099 else if(w)
01100 static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(&fw);
01101 }
01102
01103
01104 static bool targetOpensNewWindow(KHTMLPart *part, QString target)
01105 {
01106 if (!target.isEmpty() && (target.lower() != "_top") &&
01107 (target.lower() != "_self") && (target.lower() != "_parent")) {
01108 if (target.lower() == "_blank")
01109 return true;
01110 else {
01111 while (part->parentPart())
01112 part = part->parentPart();
01113 if (!part->frameExists(target))
01114 return true;
01115 }
01116 }
01117 return false;
01118 }
01119
01120 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
01121 {
01122 if ( d->m_mouseScrollTimer ) {
01123 QPoint point = mapFromGlobal( _mouse->globalPos() );
01124
01125 int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
01126 int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
01127
01128 (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
01129 (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
01130
01131 double adX = QABS(deltaX)/30.0;
01132 double adY = QABS(deltaY)/30.0;
01133
01134 d->m_mouseScroll_byX = kMax(kMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN);
01135 d->m_mouseScroll_byY = kMax(kMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN);
01136
01137 if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
01138 d->m_mouseScrollTimer->stop();
01139 }
01140 else if (!d->m_mouseScrollTimer->isActive()) {
01141 d->m_mouseScrollTimer->changeInterval( 20 );
01142 }
01143 }
01144
01145 if(!m_part->xmlDocImpl()) return;
01146
01147 int xm, ym;
01148 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01149
01150 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
01151
01152 m_part->xmlDocImpl()->prepareMouseEvent( _mouse->state() & Qt::MouseButtonMask , xm, ym, &mev );
01153
01154
01155
01156
01157
01158 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),false,
01159 0,_mouse,true,DOM::NodeImpl::MouseMove);
01160
01161 if (d->clickCount > 0 &&
01162 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
01163 d->clickCount = 0;
01164 }
01165
01166
01167 m_part->executeScheduledScript();
01168
01169 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01170 if (fn && fn != mev.innerNode.handle() &&
01171 fn->renderer() && fn->renderer()->isWidget()) {
01172 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
01173 }
01174
01175 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01176 khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
01177 QCursor c;
01178 bool mailtoCursor = false;
01179 bool newWindowCursor = false;
01180 switch ( style ? style->cursor() : CURSOR_AUTO) {
01181 case CURSOR_AUTO:
01182 if ( r && r->isText() )
01183 c = KCursor::ibeamCursor();
01184 if ( mev.url.length() && m_part->settings()->changeCursor() ) {
01185 c = m_part->urlCursor();
01186 if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
01187 mailtoCursor = true;
01188 else
01189 newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
01190 }
01191
01192 if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
01193 c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
01194
01195 break;
01196 case CURSOR_CROSS:
01197 c = KCursor::crossCursor();
01198 break;
01199 case CURSOR_POINTER:
01200 c = m_part->urlCursor();
01201 if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
01202 mailtoCursor = true;
01203 else
01204 newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
01205 break;
01206 case CURSOR_PROGRESS:
01207 c = KCursor::workingCursor();
01208 break;
01209 case CURSOR_MOVE:
01210 c = KCursor::sizeAllCursor();
01211 break;
01212 case CURSOR_E_RESIZE:
01213 case CURSOR_W_RESIZE:
01214 c = KCursor::sizeHorCursor();
01215 break;
01216 case CURSOR_N_RESIZE:
01217 case CURSOR_S_RESIZE:
01218 c = KCursor::sizeVerCursor();
01219 break;
01220 case CURSOR_NE_RESIZE:
01221 case CURSOR_SW_RESIZE:
01222 c = KCursor::sizeBDiagCursor();
01223 break;
01224 case CURSOR_NW_RESIZE:
01225 case CURSOR_SE_RESIZE:
01226 c = KCursor::sizeFDiagCursor();
01227 break;
01228 case CURSOR_TEXT:
01229 c = KCursor::ibeamCursor();
01230 break;
01231 case CURSOR_WAIT:
01232 c = KCursor::waitCursor();
01233 break;
01234 case CURSOR_HELP:
01235 c = KCursor::whatsThisCursor();
01236 break;
01237 case CURSOR_DEFAULT:
01238 break;
01239 }
01240
01241 if ( viewport()->cursor().handle() != c.handle() ) {
01242 if( c.handle() == KCursor::arrowCursor().handle()) {
01243 for (KHTMLPart* p = m_part; p; p = p->parentPart())
01244 p->view()->viewport()->unsetCursor();
01245 }
01246 else {
01247 viewport()->setCursor( c );
01248 }
01249 }
01250
01251 if ( ( mailtoCursor || newWindowCursor ) && isVisible() && hasFocus() ) {
01252 #ifdef Q_WS_X11
01253 QPixmap icon_pixmap = KGlobal::iconLoader()->loadIcon( mailtoCursor ? "mail_generic" : "window_new", KIcon::Small, 0, KIcon::DefaultState, 0, true );
01254
01255 if (d->cursor_icon_widget) {
01256 const QPixmap *pm = d->cursor_icon_widget->backgroundPixmap();
01257 if (!pm || pm->serialNumber()!=icon_pixmap.serialNumber()) {
01258 delete d->cursor_icon_widget;
01259 d->cursor_icon_widget = 0;
01260 }
01261 }
01262
01263 if( !d->cursor_icon_widget ) {
01264 d->cursor_icon_widget = new QWidget( NULL, NULL, WX11BypassWM );
01265 XSetWindowAttributes attr;
01266 attr.save_under = True;
01267 XChangeWindowAttributes( qt_xdisplay(), d->cursor_icon_widget->winId(), CWSaveUnder, &attr );
01268 d->cursor_icon_widget->resize( icon_pixmap.width(), icon_pixmap.height());
01269 if( icon_pixmap.mask() )
01270 d->cursor_icon_widget->setMask( *icon_pixmap.mask());
01271 else
01272 d->cursor_icon_widget->clearMask();
01273 d->cursor_icon_widget->setBackgroundPixmap( icon_pixmap );
01274 d->cursor_icon_widget->erase();
01275 }
01276 QPoint c_pos = QCursor::pos();
01277 d->cursor_icon_widget->move( c_pos.x() + 15, c_pos.y() + 15 );
01278 XRaiseWindow( qt_xdisplay(), d->cursor_icon_widget->winId());
01279 QApplication::flushX();
01280 d->cursor_icon_widget->show();
01281 #endif
01282 }
01283 else if ( d->cursor_icon_widget )
01284 d->cursor_icon_widget->hide();
01285
01286 if (r && r->isWidget()) {
01287 _mouse->ignore();
01288 }
01289
01290
01291 d->prevMouseX = xm;
01292 d->prevMouseY = ym;
01293
01294 if (!swallowEvent) {
01295 khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01296 QApplication::sendEvent( m_part, &event );
01297 }
01298 }
01299
01300 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
01301 {
01302 bool swallowEvent = false;
01303 int xm, ym;
01304 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01305 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
01306
01307 if ( m_part->xmlDocImpl() )
01308 {
01309 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01310
01311 swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01312 d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
01313
01314 if (d->clickCount > 0 &&
01315 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) {
01316 QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease,
01317 _mouse->pos(), _mouse->button(), _mouse->state());
01318 dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01319 d->clickCount, &me, true, DOM::NodeImpl::MouseRelease);
01320 }
01321
01322 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01323 if (fn && fn != mev.innerNode.handle() &&
01324 fn->renderer() && fn->renderer()->isWidget() &&
01325 _mouse->button() != MidButton) {
01326 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
01327 }
01328
01329 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01330 if (r && r->isWidget())
01331 _mouse->ignore();
01332 }
01333
01334 if (!swallowEvent) {
01335 khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01336 QApplication::sendEvent( m_part, &event );
01337 }
01338 }
01339
01340
01341 bool KHTMLView::dispatchKeyEvent( QKeyEvent *_ke )
01342 {
01343 if (!m_part->xmlDocImpl())
01344 return false;
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 if( _ke == d->postponed_autorepeat )
01366 {
01367 return false;
01368 }
01369
01370 if( _ke->type() == QEvent::KeyPress )
01371 {
01372 if( !_ke->isAutoRepeat())
01373 {
01374 bool ret = dispatchKeyEventHelper( _ke, false );
01375
01376 if( !ret && dispatchKeyEventHelper( _ke, true ))
01377 ret = true;
01378 return ret;
01379 }
01380 else
01381 {
01382 bool ret = dispatchKeyEventHelper( _ke, true );
01383 if( !ret && d->postponed_autorepeat )
01384 keyPressEvent( d->postponed_autorepeat );
01385 delete d->postponed_autorepeat;
01386 d->postponed_autorepeat = NULL;
01387 return ret;
01388 }
01389 }
01390 else
01391 {
01392
01393
01394 if ( d->postponed_autorepeat ) {
01395 delete d->postponed_autorepeat;
01396 d->postponed_autorepeat = 0;
01397 }
01398
01399 if( !_ke->isAutoRepeat()) {
01400 return dispatchKeyEventHelper( _ke, false );
01401 }
01402 else
01403 {
01404 d->postponed_autorepeat = new QKeyEvent( _ke->type(), _ke->key(), _ke->ascii(), _ke->state(),
01405 _ke->text(), _ke->isAutoRepeat(), _ke->count());
01406 if( _ke->isAccepted())
01407 d->postponed_autorepeat->accept();
01408 else
01409 d->postponed_autorepeat->ignore();
01410 return true;
01411 }
01412 }
01413 }
01414
01415
01416 bool KHTMLView::dispatchKeyEventHelper( QKeyEvent *_ke, bool keypress )
01417 {
01418 DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode();
01419 if (keyNode) {
01420 return keyNode->dispatchKeyEvent(_ke, keypress);
01421 } else {
01422 return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
01423 }
01424 }
01425
01426 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
01427 {
01428 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01429 if(d->typeAheadActivated)
01430 {
01431
01432 if(_ke->key() == Key_BackSpace)
01433 {
01434 d->findString = d->findString.left(d->findString.length() - 1);
01435
01436 if(!d->findString.isEmpty())
01437 {
01438 findAhead(false);
01439 }
01440 else
01441 {
01442 findTimeout();
01443 }
01444
01445 d->timer.start(3000, true);
01446 _ke->accept();
01447 return;
01448 }
01449 else if(_ke->key() == Key_Escape)
01450 {
01451 findTimeout();
01452
01453 _ke->accept();
01454 return;
01455 }
01456 else if(_ke->key() == Key_Space || !_ke->text().stripWhiteSpace().isEmpty())
01457 {
01458 d->findString += _ke->text();
01459
01460 findAhead(true);
01461
01462 d->timer.start(3000, true);
01463 _ke->accept();
01464 return;
01465 }
01466 }
01467 #endif // KHTML_NO_TYPE_AHEAD_FIND
01468
01469 #ifndef KHTML_NO_CARET
01470 if (m_part->isEditable() || m_part->isCaretMode()
01471 || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
01472 && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
01473 d->caretViewContext()->keyReleasePending = true;
01474 caretKeyPressEvent(_ke);
01475 return;
01476 }
01477 #endif // KHTML_NO_CARET
01478
01479
01480 if (d->accessKeysEnabled && _ke->key() == Key_Control && _ke->state()==0 && !d->accessKeysActivated)
01481 {
01482 d->accessKeysPreActivate=true;
01483 _ke->accept();
01484 return;
01485 }
01486
01487 if (_ke->key() == Key_Shift && _ke->state()==0)
01488 d->scrollSuspendPreActivate=true;
01489
01490
01491
01492
01493 if (d->accessKeysEnabled && d->accessKeysActivated)
01494 {
01495 int state = ( _ke->state() & ( ShiftButton | ControlButton | AltButton | MetaButton ));
01496 if ( state==0 || state==ShiftButton) {
01497 if (_ke->key() != Key_Shift) accessKeysTimeout();
01498 handleAccessKey( _ke );
01499 _ke->accept();
01500 return;
01501 }
01502 accessKeysTimeout();
01503 }
01504
01505 if ( dispatchKeyEvent( _ke )) {
01506
01507 _ke->accept();
01508 return;
01509 }
01510
01511 int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
01512 if (_ke->state() & Qt::ShiftButton)
01513 switch(_ke->key())
01514 {
01515 case Key_Space:
01516 scrollBy( 0, -clipper()->height() + offs );
01517 if(d->scrollSuspended)
01518 d->newScrollTimer(this, 0);
01519 break;
01520
01521 case Key_Down:
01522 case Key_J:
01523 d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
01524 break;
01525
01526 case Key_Up:
01527 case Key_K:
01528 d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
01529 break;
01530
01531 case Key_Left:
01532 case Key_H:
01533 d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
01534 break;
01535
01536 case Key_Right:
01537 case Key_L:
01538 d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
01539 break;
01540 }
01541 else
01542 switch ( _ke->key() )
01543 {
01544 case Key_Down:
01545 case Key_J:
01546 if (!d->scrollTimerId || d->scrollSuspended)
01547 scrollBy( 0, 10 );
01548 if (d->scrollTimerId)
01549 d->newScrollTimer(this, 0);
01550 break;
01551
01552 case Key_Space:
01553 case Key_Next:
01554 scrollBy( 0, clipper()->height() - offs );
01555 if(d->scrollSuspended)
01556 d->newScrollTimer(this, 0);
01557 break;
01558
01559 case Key_Up:
01560 case Key_K:
01561 if (!d->scrollTimerId || d->scrollSuspended)
01562 scrollBy( 0, -10 );
01563 if (d->scrollTimerId)
01564 d->newScrollTimer(this, 0);
01565 break;
01566
01567 case Key_Prior:
01568 scrollBy( 0, -clipper()->height() + offs );
01569 if(d->scrollSuspended)
01570 d->newScrollTimer(this, 0);
01571 break;
01572 case Key_Right:
01573 case Key_L:
01574 if (!d->scrollTimerId || d->scrollSuspended)
01575 scrollBy( 10, 0 );
01576 if (d->scrollTimerId)
01577 d->newScrollTimer(this, 0);
01578 break;
01579 case Key_Left:
01580 case Key_H:
01581 if (!d->scrollTimerId || d->scrollSuspended)
01582 scrollBy( -10, 0 );
01583 if (d->scrollTimerId)
01584 d->newScrollTimer(this, 0);
01585 break;
01586 case Key_Enter:
01587 case Key_Return:
01588
01589
01590 if (m_part->xmlDocImpl()) {
01591 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
01592 if (n)
01593 n->setActive();
01594 }
01595 break;
01596 case Key_Home:
01597 setContentsPos( 0, 0 );
01598 if(d->scrollSuspended)
01599 d->newScrollTimer(this, 0);
01600 break;
01601 case Key_End:
01602 setContentsPos( 0, contentsHeight() - visibleHeight() );
01603 if(d->scrollSuspended)
01604 d->newScrollTimer(this, 0);
01605 break;
01606 case Key_Shift:
01607
01608 _ke->ignore();
01609 return;
01610 default:
01611 if (d->scrollTimerId)
01612 d->newScrollTimer(this, 0);
01613 _ke->ignore();
01614 return;
01615 }
01616
01617 _ke->accept();
01618 }
01619
01620 void KHTMLView::findTimeout()
01621 {
01622 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01623 d->typeAheadActivated = false;
01624 d->findString = "";
01625 m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText);
01626 m_part->enableFindAheadActions( true );
01627 #endif // KHTML_NO_TYPE_AHEAD_FIND
01628 }
01629
01630 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01631 void KHTMLView::startFindAhead( bool linksOnly )
01632 {
01633 if( linksOnly )
01634 {
01635 d->findLinksOnly = true;
01636 m_part->setStatusBarText(i18n("Starting -- find links as you type"),
01637 KHTMLPart::BarDefaultText);
01638 }
01639 else
01640 {
01641 d->findLinksOnly = false;
01642 m_part->setStatusBarText(i18n("Starting -- find text as you type"),
01643 KHTMLPart::BarDefaultText);
01644 }
01645
01646 m_part->findTextBegin();
01647 d->typeAheadActivated = true;
01648
01649 m_part->enableFindAheadActions( false );
01650 d->timer.start(3000, true);
01651 }
01652
01653 void KHTMLView::findAhead(bool increase)
01654 {
01655 QString status;
01656
01657 if(d->findLinksOnly)
01658 {
01659 m_part->findText(d->findString, KHTMLPart::FindNoPopups |
01660 KHTMLPart::FindLinksOnly, this);
01661 if(m_part->findTextNext())
01662 {
01663 status = i18n("Link found: \"%1\".");
01664 }
01665 else
01666 {
01667 if(increase) KNotifyClient::beep();
01668 status = i18n("Link not found: \"%1\".");
01669 }
01670 }
01671 else
01672 {
01673 m_part->findText(d->findString, KHTMLPart::FindNoPopups, this);
01674 if(m_part->findTextNext())
01675 {
01676 status = i18n("Text found: \"%1\".");
01677 }
01678 else
01679 {
01680 if(increase) KNotifyClient::beep();
01681 status = i18n("Text not found: \"%1\".");
01682 }
01683 }
01684
01685 m_part->setStatusBarText(status.arg(d->findString.lower()),
01686 KHTMLPart::BarDefaultText);
01687 }
01688
01689 void KHTMLView::updateFindAheadTimeout()
01690 {
01691 if( d->typeAheadActivated )
01692 d->timer.start( 3000, true );
01693 }
01694
01695 #endif // KHTML_NO_TYPE_AHEAD_FIND
01696
01697 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
01698 {
01699 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01700 if(d->typeAheadActivated) {
01701 _ke->accept();
01702 return;
01703 }
01704 #endif
01705 if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) {
01706
01707 d->m_caretViewContext->keyReleasePending = false;
01708 return;
01709 }
01710
01711 if( d->scrollSuspendPreActivate && _ke->key() != Key_Shift )
01712 d->scrollSuspendPreActivate = false;
01713 if( _ke->key() == Key_Shift && d->scrollSuspendPreActivate && _ke->state() == Qt::ShiftButton
01714 && !(KApplication::keyboardMouseState() & Qt::ShiftButton))
01715 if (d->scrollTimerId)
01716 d->scrollSuspended = !d->scrollSuspended;
01717
01718 if (d->accessKeysEnabled)
01719 {
01720 if (d->accessKeysPreActivate && _ke->key() != Key_Control)
01721 d->accessKeysPreActivate=false;
01722 if (d->accessKeysPreActivate && _ke->state() == Qt::ControlButton && !(KApplication::keyboardMouseState() & Qt::ControlButton))
01723 {
01724 displayAccessKeys();
01725 m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText);
01726 d->accessKeysActivated = true;
01727 d->accessKeysPreActivate = false;
01728 _ke->accept();
01729 return;
01730 }
01731 else if (d->accessKeysActivated)
01732 {
01733 accessKeysTimeout();
01734 _ke->accept();
01735 return;
01736 }
01737 }
01738
01739
01740 if ( dispatchKeyEvent( _ke ) )
01741 {
01742 _ke->accept();
01743 return;
01744 }
01745
01746 QScrollView::keyReleaseEvent(_ke);
01747 }
01748
01749 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent * )
01750 {
01751
01752 #if 0
01753 if (!m_part->xmlDocImpl()) return;
01754 int xm = _ce->x();
01755 int ym = _ce->y();
01756
01757 DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove );
01758 m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
01759
01760 NodeImpl *targetNode = mev.innerNode.handle();
01761 if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
01762 int absx = 0;
01763 int absy = 0;
01764 targetNode->renderer()->absolutePosition(absx,absy);
01765 QPoint pos(xm-absx,ym-absy);
01766
01767 QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
01768 QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
01769 setIgnoreEvents(true);
01770 QApplication::sendEvent(w,&cme);
01771 setIgnoreEvents(false);
01772 }
01773 #endif
01774 }
01775
01776 bool KHTMLView::focusNextPrevChild( bool next )
01777 {
01778
01779 if (m_part->xmlDocImpl() && focusNextPrevNode(next))
01780 {
01781 if (m_part->xmlDocImpl()->focusNode())
01782 kdDebug() << "focusNode.name: "
01783 << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl;
01784 return true;
01785 }
01786
01787
01788 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
01789 if (m_part->parentPart() && m_part->parentPart()->view())
01790 return m_part->parentPart()->view()->focusNextPrevChild(next);
01791
01792 return QWidget::focusNextPrevChild(next);
01793 }
01794
01795 void KHTMLView::doAutoScroll()
01796 {
01797 QPoint pos = QCursor::pos();
01798 pos = viewport()->mapFromGlobal( pos );
01799
01800 int xm, ym;
01801 viewportToContents(pos.x(), pos.y(), xm, ym);
01802
01803 pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
01804 if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
01805 (pos.x() < 0) || (pos.x() > visibleWidth()) )
01806 {
01807 ensureVisible( xm, ym, 0, 5 );
01808
01809 #ifndef KHTML_NO_SELECTION
01810
01811 DOM::Node innerNode;
01812 if (m_part->isExtendingSelection()) {
01813 RenderObject::NodeInfo renderInfo(true, false);
01814 m_part->xmlDocImpl()->renderer()->layer()
01815 ->nodeAtPoint(renderInfo, xm, ym);
01816 innerNode = renderInfo.innerNode();
01817 }
01818
01819 if (innerNode.handle() && innerNode.handle()->renderer()) {
01820 int absX, absY;
01821 innerNode.handle()->renderer()->absolutePosition(absX, absY);
01822
01823 m_part->extendSelectionTo(xm, ym, absX, absY, innerNode);
01824 }
01825 #endif // KHTML_NO_SELECTION
01826 }
01827 }
01828
01829
01830 class HackWidget : public QWidget
01831 {
01832 public:
01833 inline void setNoErase() { setWFlags(getWFlags()|WRepaintNoErase); }
01834 };
01835
01836 bool KHTMLView::eventFilter(QObject *o, QEvent *e)
01837 {
01838 if ( e->type() == QEvent::AccelOverride ) {
01839 QKeyEvent* ke = (QKeyEvent*) e;
01840
01841 if (m_part->isEditable() || m_part->isCaretMode()
01842 || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
01843 && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
01844
01845 if ( (ke->state() & ControlButton) || (ke->state() & ShiftButton) ) {
01846 switch ( ke->key() ) {
01847 case Key_Left:
01848 case Key_Right:
01849 case Key_Up:
01850 case Key_Down:
01851 case Key_Home:
01852 case Key_End:
01853 ke->accept();
01854
01855 return true;
01856 default:
01857 break;
01858 }
01859 }
01860 }
01861 }
01862
01863 if ( e->type() == QEvent::Leave ) {
01864 if ( d->cursor_icon_widget )
01865 d->cursor_icon_widget->hide();
01866 m_part->resetHoverText();
01867 }
01868
01869 QWidget *view = viewport();
01870
01871 if (o == view) {
01872
01873
01874 if(e->type() == QEvent::ChildInserted) {
01875 QObject *c = static_cast<QChildEvent *>(e)->child();
01876 if (c->isWidgetType()) {
01877 QWidget *w = static_cast<QWidget *>(c);
01878
01879 if (w->parentWidget(true) == view) {
01880 if (!strcmp(w->name(), "__khtml")) {
01881 w->installEventFilter(this);
01882 w->unsetCursor();
01883 if (!::qt_cast<QFrame*>(w))
01884 w->setBackgroundMode( QWidget::NoBackground );
01885 static_cast<HackWidget *>(w)->setNoErase();
01886 if (w->children()) {
01887 QObjectListIterator it(*w->children());
01888 for (; it.current(); ++it) {
01889 QWidget *widget = ::qt_cast<QWidget *>(it.current());
01890 if (widget && !widget->isTopLevel()) {
01891 if (!::qt_cast<QFrame*>(w))
01892 widget->setBackgroundMode( QWidget::NoBackground );
01893 static_cast<HackWidget *>(widget)->setNoErase();
01894 widget->installEventFilter(this);
01895 }
01896 }
01897 }
01898 }
01899 }
01900 }
01901 }
01902 } else if (o->isWidgetType()) {
01903 QWidget *v = static_cast<QWidget *>(o);
01904 QWidget *c = v;
01905 while (v && v != view) {
01906 c = v;
01907 v = v->parentWidget(true);
01908 }
01909
01910 if (v && !strcmp(c->name(), "__khtml")) {
01911 bool block = false;
01912 QWidget *w = static_cast<QWidget *>(o);
01913 switch(e->type()) {
01914 case QEvent::Paint:
01915 if (!allowWidgetPaintEvents) {
01916
01917
01918 block = true;
01919 int x = 0, y = 0;
01920 QWidget *v = w;
01921 while (v && v != view) {
01922 x += v->x();
01923 y += v->y();
01924 v = v->parentWidget();
01925 }
01926 viewportToContents( x, y, x, y );
01927 QPaintEvent *pe = static_cast<QPaintEvent *>(e);
01928 bool asap = !d->contentsMoving && ::qt_cast<QScrollView *>(c);
01929
01930
01931 if ( asap && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() &&
01932 !static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
01933 repaintContents(x + pe->rect().x(), y + pe->rect().y(),
01934 pe->rect().width(), pe->rect().height(), true);
01935 } else {
01936 scheduleRepaint(x + pe->rect().x(), y + pe->rect().y(),
01937 pe->rect().width(), pe->rect().height(), asap);
01938 }
01939 }
01940 break;
01941 case QEvent::MouseMove:
01942 case QEvent::MouseButtonPress:
01943 case QEvent::MouseButtonRelease:
01944 case QEvent::MouseButtonDblClick: {
01945 if ( (w->parentWidget() == view || ::qt_cast<QScrollView*>(c)) && !::qt_cast<QScrollBar *>(w)) {
01946 QMouseEvent *me = static_cast<QMouseEvent *>(e);
01947 QPoint pt = w->mapTo( view, me->pos());
01948 QMouseEvent me2(me->type(), pt, me->button(), me->state());
01949
01950 if (e->type() == QEvent::MouseMove)
01951 viewportMouseMoveEvent(&me2);
01952 else if(e->type() == QEvent::MouseButtonPress)
01953 viewportMousePressEvent(&me2);
01954 else if(e->type() == QEvent::MouseButtonRelease)
01955 viewportMouseReleaseEvent(&me2);
01956 else
01957 viewportMouseDoubleClickEvent(&me2);
01958 block = true;
01959 }
01960 break;
01961 }
01962 case QEvent::KeyPress:
01963 case QEvent::KeyRelease:
01964 if (w->parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
01965 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
01966 if (e->type() == QEvent::KeyPress)
01967 keyPressEvent(ke);
01968 else
01969 keyReleaseEvent(ke);
01970 block = true;
01971 }
01972 default:
01973 break;
01974 }
01975 if (block) {
01976
01977 return true;
01978 }
01979 }
01980 }
01981
01982
01983 return QScrollView::eventFilter(o, e);
01984 }
01985
01986
01987 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
01988 {
01989 return d->underMouse;
01990 }
01991
01992 DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const
01993 {
01994 return d->underMouseNonShared;
01995 }
01996
01997 bool KHTMLView::scrollTo(const QRect &bounds)
01998 {
01999 d->scrollingSelf = true;
02000
02001 int x, y, xe, ye;
02002 x = bounds.left();
02003 y = bounds.top();
02004 xe = bounds.right();
02005 ye = bounds.bottom();
02006
02007
02008
02009 int deltax;
02010 int deltay;
02011
02012 int curHeight = visibleHeight();
02013 int curWidth = visibleWidth();
02014
02015 if (ye-y>curHeight-d->borderY)
02016 ye = y + curHeight - d->borderY;
02017
02018 if (xe-x>curWidth-d->borderX)
02019 xe = x + curWidth - d->borderX;
02020
02021
02022 if (x < contentsX() + d->borderX )
02023 deltax = x - contentsX() - d->borderX;
02024
02025 else if (xe + d->borderX > contentsX() + curWidth)
02026 deltax = xe + d->borderX - ( contentsX() + curWidth );
02027 else
02028 deltax = 0;
02029
02030
02031 if (y < contentsY() + d->borderY)
02032 deltay = y - contentsY() - d->borderY;
02033
02034 else if (ye + d->borderY > contentsY() + curHeight)
02035 deltay = ye + d->borderY - ( contentsY() + curHeight );
02036 else
02037 deltay = 0;
02038
02039 int maxx = curWidth-d->borderX;
02040 int maxy = curHeight-d->borderY;
02041
02042 int scrollX,scrollY;
02043
02044 scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
02045 scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
02046
02047 if (contentsX() + scrollX < 0)
02048 scrollX = -contentsX();
02049 else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
02050 scrollX = contentsWidth() - visibleWidth() - contentsX();
02051
02052 if (contentsY() + scrollY < 0)
02053 scrollY = -contentsY();
02054 else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
02055 scrollY = contentsHeight() - visibleHeight() - contentsY();
02056
02057 scrollBy(scrollX, scrollY);
02058
02059 d->scrollingSelf = false;
02060
02061 if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) )
02062 return true;
02063 else return false;
02064
02065 }
02066
02067 bool KHTMLView::focusNextPrevNode(bool next)
02068 {
02069
02070
02071
02072
02073
02074
02075
02076 DocumentImpl *doc = m_part->xmlDocImpl();
02077 NodeImpl *oldFocusNode = doc->focusNode();
02078
02079
02080
02081
02082 if (oldFocusNode && oldFocusNode->renderer() &&
02083 !oldFocusNode->renderer()->parent()) {
02084 doc->setFocusNode(0);
02085 return true;
02086 }
02087
02088 #if 1
02089
02090
02091
02092 if (d->scrollBarMoved)
02093 {
02094 NodeImpl *toFocus;
02095 if (next)
02096 toFocus = doc->nextFocusNode(oldFocusNode);
02097 else
02098 toFocus = doc->previousFocusNode(oldFocusNode);
02099
02100 if (!toFocus && oldFocusNode)
02101 if (next)
02102 toFocus = doc->nextFocusNode(NULL);
02103 else
02104 toFocus = doc->previousFocusNode(NULL);
02105
02106 while (toFocus && toFocus != oldFocusNode)
02107 {
02108
02109 QRect focusNodeRect = toFocus->getRect();
02110 if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
02111 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
02112 {
02113 QRect r = toFocus->getRect();
02114 ensureVisible( r.right(), r.bottom());
02115 ensureVisible( r.left(), r.top());
02116 d->scrollBarMoved = false;
02117 d->tabMovePending = false;
02118 d->lastTabbingDirection = next;
02119 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
02120 m_part->xmlDocImpl()->setFocusNode(toFocus);
02121 Node guard(toFocus);
02122 if (!toFocus->hasOneRef() )
02123 {
02124 emit m_part->nodeActivated(Node(toFocus));
02125 }
02126 return true;
02127 }
02128 }
02129 if (next)
02130 toFocus = doc->nextFocusNode(toFocus);
02131 else
02132 toFocus = doc->previousFocusNode(toFocus);
02133
02134 if (!toFocus && oldFocusNode)
02135 if (next)
02136 toFocus = doc->nextFocusNode(NULL);
02137 else
02138 toFocus = doc->previousFocusNode(NULL);
02139 }
02140
02141 d->scrollBarMoved = false;
02142 }
02143 #endif
02144
02145 if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone)
02146 {
02147 ensureVisible(contentsX(), next?0:contentsHeight());
02148 d->scrollBarMoved = false;
02149 d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom;
02150 return true;
02151 }
02152
02153 NodeImpl *newFocusNode = NULL;
02154
02155 if (d->tabMovePending && next != d->lastTabbingDirection)
02156 {
02157
02158 newFocusNode = oldFocusNode;
02159 }
02160 else if (next)
02161 {
02162 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop )
02163 newFocusNode = doc->nextFocusNode(oldFocusNode);
02164 }
02165 else
02166 {
02167 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom )
02168 newFocusNode = doc->previousFocusNode(oldFocusNode);
02169 }
02170
02171 bool targetVisible = false;
02172 if (!newFocusNode)
02173 {
02174 if ( next )
02175 {
02176 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0));
02177 }
02178 else
02179 {
02180 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,d->borderY,0,0));
02181 }
02182 }
02183 else
02184 {
02185 #ifndef KHTML_NO_CARET
02186
02187 if (!m_part->isCaretMode() && !m_part->isEditable()
02188 && newFocusNode->contentEditable()) {
02189 d->caretViewContext();
02190 moveCaretTo(newFocusNode, 0L, true);
02191 } else {
02192 caretOff();
02193 }
02194 #endif // KHTML_NO_CARET
02195
02196 targetVisible = scrollTo(newFocusNode->getRect());
02197 }
02198
02199 if (targetVisible)
02200 {
02201
02202 d->tabMovePending = false;
02203
02204 m_part->xmlDocImpl()->setFocusNode(newFocusNode);
02205 if (newFocusNode)
02206 {
02207 Node guard(newFocusNode);
02208 if (!newFocusNode->hasOneRef() )
02209 {
02210 emit m_part->nodeActivated(Node(newFocusNode));
02211 }
02212 return true;
02213 }
02214 else
02215 {
02216 d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop;
02217 return false;
02218 }
02219 }
02220 else
02221 {
02222 if (!d->tabMovePending)
02223 d->lastTabbingDirection = next;
02224 d->tabMovePending = true;
02225 return true;
02226 }
02227 }
02228
02229 void KHTMLView::displayAccessKeys()
02230 {
02231 QValueVector< QChar > taken;
02232 displayAccessKeys( NULL, this, taken, false );
02233 displayAccessKeys( NULL, this, taken, true );
02234 }
02235
02236 void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, QValueVector< QChar >& taken, bool use_fallbacks )
02237 {
02238 QMap< ElementImpl*, QChar > fallbacks;
02239 if( use_fallbacks )
02240 fallbacks = buildFallbackAccessKeys();
02241 for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) {
02242 if( n->isElementNode()) {
02243 ElementImpl* en = static_cast< ElementImpl* >( n );
02244 DOMString s = en->getAttribute( ATTR_ACCESSKEY );
02245 QString accesskey;
02246 if( s.length() == 1 ) {
02247 QChar a = s.string()[ 0 ].upper();
02248 if( qFind( taken.begin(), taken.end(), a ) == taken.end())
02249 accesskey = a;
02250 }
02251 if( accesskey.isNull() && fallbacks.contains( en )) {
02252 QChar a = fallbacks[ en ].upper();
02253 if( qFind( taken.begin(), taken.end(), a ) == taken.end())
02254 accesskey = QString( "<qt><i>" ) + a + "</i></qt>";
02255 }
02256 if( !accesskey.isNull()) {
02257 QRect rec=en->getRect();
02258 QLabel *lab=new QLabel(accesskey,viewport(),0,Qt::WDestructiveClose);
02259 connect( origview, SIGNAL(hideAccessKeys()), lab, SLOT(close()) );
02260 connect( this, SIGNAL(repaintAccessKeys()), lab, SLOT(repaint()));
02261 lab->setPalette(QToolTip::palette());
02262 lab->setLineWidth(2);
02263 lab->setFrameStyle(QFrame::Box | QFrame::Plain);
02264 lab->setMargin(3);
02265 lab->adjustSize();
02266 addChild(lab,
02267 KMIN(rec.left()+rec.width()/2, contentsWidth() - lab->width()),
02268 KMIN(rec.top()+rec.height()/2, contentsHeight() - lab->height()));
02269 showChild(lab);
02270 taken.append( accesskey[ 0 ] );
02271 }
02272 }
02273 }
02274 if( use_fallbacks )
02275 return;
02276 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
02277 for( QPtrListIterator<KParts::ReadOnlyPart> it( frames );
02278 it != NULL;
02279 ++it ) {
02280 if( !(*it)->inherits( "KHTMLPart" ))
02281 continue;
02282 KHTMLPart* part = static_cast< KHTMLPart* >( *it );
02283 if( part->view() && part->view() != caller )
02284 part->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
02285 }
02286
02287 if (m_part->parentPart() && m_part->parentPart()->view()
02288 && m_part->parentPart()->view() != caller)
02289 m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
02290 }
02291
02292
02293
02294 void KHTMLView::accessKeysTimeout()
02295 {
02296 d->accessKeysActivated=false;
02297 d->accessKeysPreActivate = false;
02298 m_part->setStatusBarText(QString::null, KHTMLPart::BarOverrideText);
02299 emit hideAccessKeys();
02300 }
02301
02302
02303 bool KHTMLView::handleAccessKey( const QKeyEvent* ev )
02304 {
02305
02306
02307 QChar c;
02308 if( ev->key() >= Key_A && ev->key() <= Key_Z )
02309 c = 'A' + ev->key() - Key_A;
02310 else if( ev->key() >= Key_0 && ev->key() <= Key_9 )
02311 c = '0' + ev->key() - Key_0;
02312 else {
02313
02314
02315 if( ev->text().length() == 1 )
02316 c = ev->text()[ 0 ];
02317 }
02318 if( c.isNull())
02319 return false;
02320 return focusNodeWithAccessKey( c );
02321 }
02322
02323 bool KHTMLView::focusNodeWithAccessKey( QChar c, KHTMLView* caller )
02324 {
02325 DocumentImpl *doc = m_part->xmlDocImpl();
02326 if( !doc )
02327 return false;
02328 ElementImpl* node = doc->findAccessKeyElement( c );
02329 if( !node ) {
02330 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
02331 for( QPtrListIterator<KParts::ReadOnlyPart> it( frames );
02332 it != NULL;
02333 ++it ) {
02334 if( !(*it)->inherits( "KHTMLPart" ))
02335 continue;
02336 KHTMLPart* part = static_cast< KHTMLPart* >( *it );
02337 if( part->view() && part->view() != caller
02338 && part->view()->focusNodeWithAccessKey( c, this ))
02339 return true;
02340 }
02341
02342 if (m_part->parentPart() && m_part->parentPart()->view()
02343 && m_part->parentPart()->view() != caller
02344 && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this ))
02345 return true;
02346 if( caller == NULL ) {
02347 QMap< ElementImpl*, QChar > fallbacks = buildFallbackAccessKeys();
02348 for( QMap< ElementImpl*, QChar >::ConstIterator it = fallbacks.begin();
02349 it != fallbacks.end();
02350 ++it )
02351 if( *it == c ) {
02352 node = it.key();
02353 break;
02354 }
02355 }
02356 if( node == NULL )
02357 return false;
02358 }
02359
02360
02361 #ifndef KHTML_NO_CARET
02362
02363 if (!m_part->isCaretMode() && !m_part->isEditable()
02364 && node->contentEditable()) {
02365 d->caretViewContext();
02366 moveCaretTo(node, 0L, true);
02367 } else {
02368 caretOff();
02369 }
02370 #endif // KHTML_NO_CARET
02371
02372 QRect r = node->getRect();
02373 ensureVisible( r.right(), r.bottom());
02374 ensureVisible( r.left(), r.top());
02375
02376 Node guard( node );
02377 if( node->isFocusable()) {
02378 if (node->id()==ID_LABEL) {
02379
02380 node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
02381 if (!node) return true;
02382 guard = node;
02383 }
02384
02385 QFocusEvent::setReason( QFocusEvent::Shortcut );
02386 m_part->xmlDocImpl()->setFocusNode(node);
02387 QFocusEvent::resetReason();
02388 if( node != NULL && node->hasOneRef())
02389 return true;
02390 emit m_part->nodeActivated(Node(node));
02391 if( node != NULL && node->hasOneRef())
02392 return true;
02393 }
02394
02395 switch( node->id()) {
02396 case ID_A:
02397 static_cast< HTMLAnchorElementImpl* >( node )->click();
02398 break;
02399 case ID_INPUT:
02400 static_cast< HTMLInputElementImpl* >( node )->click();
02401 break;
02402 case ID_BUTTON:
02403 static_cast< HTMLButtonElementImpl* >( node )->click();
02404 break;
02405 case ID_AREA:
02406 static_cast< HTMLAreaElementImpl* >( node )->click();
02407 break;
02408 case ID_TEXTAREA:
02409 break;
02410 case ID_LEGEND:
02411
02412 break;
02413 }
02414 return true;
02415 }
02416
02417 static QString getElementText( NodeImpl* start, bool after )
02418 {
02419 QString ret;
02420 for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode();
02421 n != NULL;
02422 n = after ? n->traverseNextNode() : n->traversePreviousNode()) {
02423 if( n->isTextNode()) {
02424 if( after )
02425 ret += static_cast< TextImpl* >( n )->toString().string();
02426 else
02427 ret.prepend( static_cast< TextImpl* >( n )->toString().string());
02428 } else {
02429 switch( n->id()) {
02430 case ID_A:
02431 case ID_FONT:
02432 case ID_TT:
02433 case ID_U:
02434 case ID_B:
02435 case ID_I:
02436 case ID_S:
02437 case ID_STRIKE:
02438 case ID_BIG:
02439 case ID_SMALL:
02440 case ID_EM:
02441 case ID_STRONG:
02442 case ID_DFN:
02443 case ID_CODE:
02444 case ID_SAMP:
02445 case ID_KBD:
02446 case ID_VAR:
02447 case ID_CITE:
02448 case ID_ABBR:
02449 case ID_ACRONYM:
02450 case ID_SUB:
02451 case ID_SUP:
02452 case ID_SPAN:
02453 case ID_NOBR:
02454 case ID_WBR:
02455 break;
02456 case ID_TD:
02457 if( ret.stripWhiteSpace().isEmpty())
02458 break;
02459
02460 default:
02461 return ret.simplifyWhiteSpace();
02462 }
02463 }
02464 }
02465 return ret.simplifyWhiteSpace();
02466 }
02467
02468 static QMap< NodeImpl*, QString > buildLabels( NodeImpl* start )
02469 {
02470 QMap< NodeImpl*, QString > ret;
02471 for( NodeImpl* n = start;
02472 n != NULL;
02473 n = n->traverseNextNode()) {
02474 if( n->id() == ID_LABEL ) {
02475 HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n );
02476 NodeImpl* labelfor = label->getFormElement();
02477 if( labelfor )
02478 ret[ labelfor ] = label->innerText().string().simplifyWhiteSpace();
02479 }
02480 }
02481 return ret;
02482 }
02483
02484 namespace khtml {
02485 struct AccessKeyData {
02486 ElementImpl* element;
02487 QString text;
02488 QString url;
02489 int priority;
02490 };
02491 }
02492
02493 QMap< ElementImpl*, QChar > KHTMLView::buildFallbackAccessKeys() const
02494 {
02495
02496 QValueList< AccessKeyData > data;
02497 QMap< NodeImpl*, QString > labels = buildLabels( m_part->xmlDocImpl());
02498 for( NodeImpl* n = m_part->xmlDocImpl();
02499 n != NULL;
02500 n = n->traverseNextNode()) {
02501 if( n->isElementNode()) {
02502 ElementImpl* element = static_cast< ElementImpl* >( n );
02503 if( element->getAttribute( ATTR_ACCESSKEY ).length() == 1 )
02504 continue;
02505 if( element->renderer() == NULL )
02506 continue;
02507 QString text;
02508 QString url;
02509 int priority = 0;
02510 bool ignore = false;
02511 bool text_after = false;
02512 bool text_before = false;
02513 switch( element->id()) {
02514 case ID_A:
02515 url = khtml::parseURL(element->getAttribute(ATTR_HREF)).string();
02516 if( url.isEmpty())
02517 continue;
02518 text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace();
02519 priority = 2;
02520 break;
02521 case ID_INPUT: {
02522 HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element );
02523 switch( in->inputType()) {
02524 case HTMLInputElementImpl::SUBMIT:
02525 text = in->value().string();
02526 if( text.isEmpty())
02527 text = i18n( "Submit" );
02528 priority = 7;
02529 break;
02530 case HTMLInputElementImpl::IMAGE:
02531 text = in->altText().string();
02532 priority = 7;
02533 break;
02534 case HTMLInputElementImpl::BUTTON:
02535 text = in->value().string();
02536 priority = 5;
02537 break;
02538 case HTMLInputElementImpl::RESET:
02539 text = in->value().string();
02540 if( text.isEmpty())
02541 text = i18n( "Reset" );
02542 priority = 5;
02543 break;
02544 case HTMLInputElementImpl::HIDDEN:
02545 ignore = true;
02546 break;
02547 case HTMLInputElementImpl::CHECKBOX:
02548 case HTMLInputElementImpl::RADIO:
02549 text_after = true;
02550 priority = 5;
02551 break;
02552 case HTMLInputElementImpl::TEXT:
02553 case HTMLInputElementImpl::PASSWORD:
02554 case HTMLInputElementImpl::FILE:
02555 text_before = true;
02556 priority = 5;
02557 break;
02558 default:
02559 priority = 5;
02560 break;
02561 }
02562 break;
02563 }
02564 case ID_BUTTON:
02565 text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace();
02566 switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) {
02567 case HTMLButtonElementImpl::SUBMIT:
02568 if( text.isEmpty())
02569 text = i18n( "Submit" );
02570 priority = 7;
02571 break;
02572 case HTMLButtonElementImpl::RESET:
02573 if( text.isEmpty())
02574 text = i18n( "Reset" );
02575 priority = 5;
02576 break;
02577 default:
02578 priority = 5;
02579 break;
02580 break;
02581 }
02582 case ID_SELECT:
02583 text_before = true;
02584 text_after = true;
02585 priority = 5;
02586 break;
02587 case ID_FRAME:
02588 ignore = true;
02589 break;
02590 default:
02591 ignore = !element->isFocusable();
02592 priority = 2;
02593 break;
02594 }
02595 if( ignore )
02596 continue;
02597 if( text.isNull() && labels.contains( element ))
02598 text = labels[ element ];
02599 if( text.isNull() && text_before )
02600 text = getElementText( element, false );
02601 if( text.isNull() && text_after )
02602 text = getElementText( element, true );
02603 text = text.stripWhiteSpace();
02604
02605 QValueList< QPair< QString, QChar > > priorities
02606 = m_part->settings()->fallbackAccessKeysAssignments();
02607 for( QValueList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
02608 it != priorities.end();
02609 ++it ) {
02610 if( text == (*it).first )
02611 priority = 10;
02612 }
02613 AccessKeyData tmp = { element, text, url, priority };
02614 data.append( tmp );
02615 }
02616 }
02617
02618 QValueList< QChar > keys;
02619 for( char c = 'A'; c <= 'Z'; ++c )
02620 keys << c;
02621 for( char c = '0'; c <= '9'; ++c )
02622 keys << c;
02623 for( NodeImpl* n = m_part->xmlDocImpl();
02624 n != NULL;
02625 n = n->traverseNextNode()) {
02626 if( n->isElementNode()) {
02627 ElementImpl* en = static_cast< ElementImpl* >( n );
02628 DOMString s = en->getAttribute( ATTR_ACCESSKEY );
02629 if( s.length() == 1 ) {
02630 QChar c = s.string()[ 0 ].upper();
02631 keys.remove( c );
02632 }
02633 }
02634 }
02635
02636 QMap< ElementImpl*, QChar > ret;
02637 for( int priority = 10;
02638 priority >= 0;
02639 --priority ) {
02640 for( QValueList< AccessKeyData >::Iterator it = data.begin();
02641 it != data.end();
02642 ) {
02643 if( (*it).priority != priority ) {
02644 ++it;
02645 continue;
02646 }
02647 if( keys.isEmpty())
02648 break;
02649 QString text = (*it).text;
02650 QChar key;
02651 if( key.isNull() && !text.isEmpty()) {
02652 QValueList< QPair< QString, QChar > > priorities
02653 = m_part->settings()->fallbackAccessKeysAssignments();
02654 for( QValueList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
02655 it != priorities.end();
02656 ++it )
02657 if( text == (*it).first && keys.contains( (*it).second )) {
02658 key = (*it).second;
02659 break;
02660 }
02661 }
02662
02663
02664
02665 if( key.isNull() && !text.isEmpty()) {
02666 QStringList words = QStringList::split( ' ', text );
02667 for( QStringList::ConstIterator it = words.begin();
02668 it != words.end();
02669 ++it ) {
02670 if( keys.contains( (*it)[ 0 ].upper())) {
02671 key = (*it)[ 0 ].upper();
02672 break;
02673 }
02674 }
02675 }
02676 if( key.isNull() && !text.isEmpty()) {
02677 for( unsigned int i = 0;
02678 i < text.length();
02679 ++i ) {
02680 if( keys.contains( text[ i ].upper())) {
02681 key = text[ i ].upper();
02682 break;
02683 }
02684 }
02685 }
02686 if( key.isNull())
02687 key = keys.front();
02688 ret[ (*it).element ] = key;
02689 keys.remove( key );
02690 QString url = (*it).url;
02691 it = data.remove( it );
02692
02693 if( !url.isEmpty() && !url.startsWith( "javascript:", false )) {
02694 for( QValueList< AccessKeyData >::Iterator it2 = data.begin();
02695 it2 != data.end();
02696 ) {
02697 if( (*it2).url == url ) {
02698 ret[ (*it2).element ] = key;
02699 if( it == it2 )
02700 ++it;
02701 it2 = data.remove( it2 );
02702 } else
02703 ++it2;
02704 }
02705 }
02706 }
02707 }
02708 return ret;
02709 }
02710
02711 void KHTMLView::setMediaType( const QString &medium )
02712 {
02713 m_medium = medium;
02714 }
02715
02716 QString KHTMLView::mediaType() const
02717 {
02718 return m_medium;
02719 }
02720
02721 bool KHTMLView::pagedMode() const
02722 {
02723 return d->paged;
02724 }
02725
02726 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
02727 {
02728 if (vis) {
02729 d->visibleWidgets.replace(w, w->widget());
02730 }
02731 else
02732 d->visibleWidgets.remove(w);
02733 }
02734
02735 bool KHTMLView::needsFullRepaint() const
02736 {
02737 return d->needsFullRepaint;
02738 }
02739
02740 void KHTMLView::print()
02741 {
02742 print( false );
02743 }
02744
02745 void KHTMLView::print(bool quick)
02746 {
02747 if(!m_part->xmlDocImpl()) return;
02748 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
02749 if(!root) return;
02750
02751 KPrinter *printer = new KPrinter(true, QPrinter::ScreenResolution);
02752 printer->addDialogPage(new KHTMLPrintSettings());
02753 QString docname = m_part->xmlDocImpl()->URL().prettyURL();
02754 if ( !docname.isEmpty() )
02755 docname = KStringHandler::csqueeze(docname, 80);
02756 if(quick || printer->setup(this, i18n("Print %1").arg(docname))) {
02757 viewport()->setCursor( waitCursor );
02758
02759 printer->setFullPage(false);
02760 printer->setCreator(QString("KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
02761 printer->setDocName(docname);
02762
02763 QPainter *p = new QPainter;
02764 p->begin( printer );
02765 khtml::setPrintPainter( p );
02766
02767 m_part->xmlDocImpl()->setPaintDevice( printer );
02768 QString oldMediaType = mediaType();
02769 setMediaType( "print" );
02770
02771
02772
02773 m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-khtml-printfriendly") == "true" ?
02774 "* { background-image: none !important;"
02775 " background-color: white !important;"
02776 " color: black !important; }"
02777 "body { margin: 0px !important; }"
02778 "html { margin: 0px !important; }" :
02779 "body { margin: 0px !important; }"
02780 "html { margin: 0px !important; }"
02781 );
02782
02783 QPaintDeviceMetrics metrics( printer );
02784
02785 kdDebug(6000) << "printing: physical page width = " << metrics.width()
02786 << " height = " << metrics.height() << endl;
02787 root->setStaticMode(true);
02788 root->setPagedMode(true);
02789 root->setWidth(metrics.width());
02790
02791 root->setPageTop(0);
02792 root->setPageBottom(0);
02793 d->paged = true;
02794
02795 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
02796 m_part->xmlDocImpl()->updateStyleSelector();
02797 root->setPrintImages( printer->option("app-khtml-printimages") == "true");
02798 root->makePageBreakAvoidBlocks();
02799
02800 root->setNeedsLayoutAndMinMaxRecalc();
02801 root->layout();
02802 khtml::RenderWidget::flushWidgetResizes();
02803
02804
02805
02806 bool printHeader = (printer->option("app-khtml-printheader") == "true");
02807
02808 int headerHeight = 0;
02809 QFont headerFont("Sans Serif", 8);
02810
02811 QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),true);
02812 QString headerMid = docname;
02813 QString headerRight;
02814
02815 if (printHeader)
02816 {
02817 p->setFont(headerFont);
02818 headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
02819 }
02820
02821
02822 kdDebug(6000) << "printing: html page width = " << root->docWidth()
02823 << " height = " << root->docHeight() << endl;
02824 kdDebug(6000) << "printing: margins left = " << printer->margins().width()
02825 << " top = " << printer->margins().height() << endl;
02826 kdDebug(6000) << "printing: paper width = " << metrics.width()
02827 << " height = " << metrics.height() << endl;
02828
02829
02830 int pageWidth = metrics.width();
02831 int pageHeight = metrics.height();
02832 p->setClipRect(0,0, pageWidth, pageHeight);
02833
02834 pageHeight -= headerHeight;
02835
02836 bool scalePage = false;
02837 double scale = 0.0;
02838 #ifndef QT_NO_TRANSFORMATIONS
02839 if(root->docWidth() > metrics.width()) {
02840 scalePage = true;
02841 scale = ((double) metrics.width())/((double) root->docWidth());
02842 pageHeight = (int) (pageHeight/scale);
02843 pageWidth = (int) (pageWidth/scale);
02844 headerHeight = (int) (headerHeight/scale);
02845 }
02846 #endif
02847 kdDebug(6000) << "printing: scaled html width = " << pageWidth
02848 << " height = " << pageHeight << endl;
02849
02850 root->setHeight(pageHeight);
02851 root->setPageBottom(pageHeight);
02852 root->setNeedsLayout(true);
02853 root->layoutIfNeeded();
02854
02855
02856
02857 if (printHeader)
02858 {
02859 int available_width = metrics.width() - 10 -
02860 2 * kMax(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
02861 p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
02862 if (available_width < 150)
02863 available_width = 150;
02864 int mid_width;
02865 int squeeze = 120;
02866 do {
02867 headerMid = KStringHandler::csqueeze(docname, squeeze);
02868 mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
02869 squeeze -= 10;
02870 } while (mid_width > available_width);
02871 }
02872
02873 int top = 0;
02874 int bottom = 0;
02875 int page = 1;
02876 while(top < root->docHeight()) {
02877 if(top > 0) printer->newPage();
02878 p->setClipRect(0, 0, pageWidth, headerHeight, QPainter::CoordDevice);
02879 if (printHeader)
02880 {
02881 int dy = p->fontMetrics().lineSpacing();
02882 p->setPen(Qt::black);
02883 p->setFont(headerFont);
02884
02885 headerRight = QString("#%1").arg(page);
02886
02887 p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
02888 p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
02889 p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
02890 }
02891
02892
02893 #ifndef QT_NO_TRANSFORMATIONS
02894 if (scalePage)
02895 p->scale(scale, scale);
02896 #endif
02897
02898 p->setClipRect(0, headerHeight, pageWidth, pageHeight, QPainter::CoordDevice);
02899 p->translate(0, headerHeight-top);
02900
02901 bottom = top+pageHeight;
02902
02903 root->setPageTop(top);
02904 root->setPageBottom(bottom);
02905 root->setPageNumber(page);
02906
02907 root->layer()->paint(p, QRect(0, top, pageWidth, pageHeight));
02908
02909
02910
02911 kdDebug(6000) << "printed: page " << page <<" bottom At = " << bottom << endl;
02912
02913 top = bottom;
02914 p->resetXForm();
02915 page++;
02916 }
02917
02918 p->end();
02919 delete p;
02920
02921
02922 root->setPagedMode(false);
02923 root->setStaticMode(false);
02924 d->paged = false;
02925 khtml::setPrintPainter( 0 );
02926 setMediaType( oldMediaType );
02927 m_part->xmlDocImpl()->setPaintDevice( this );
02928 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor());
02929 m_part->xmlDocImpl()->updateStyleSelector();
02930 viewport()->unsetCursor();
02931 }
02932 delete printer;
02933 }
02934
02935 void KHTMLView::slotPaletteChanged()
02936 {
02937 if(!m_part->xmlDocImpl()) return;
02938 DOM::DocumentImpl *document = m_part->xmlDocImpl();
02939 if (!document->isHTMLDocument()) return;
02940 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
02941 if(!root) return;
02942 root->style()->resetPalette();
02943 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
02944 if(!body) return;
02945 body->setChanged(true);
02946 body->recalcStyle( NodeImpl::Force );
02947 }
02948
02949 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
02950 {
02951 if(!m_part->xmlDocImpl()) return;
02952 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
02953 if(!root) return;
02954
02955 m_part->xmlDocImpl()->setPaintDevice(p->device());
02956 root->setPagedMode(true);
02957 root->setStaticMode(true);
02958 root->setWidth(rc.width());
02959
02960 p->save();
02961 p->setClipRect(rc);
02962 p->translate(rc.left(), rc.top());
02963 double scale = ((double) rc.width()/(double) root->docWidth());
02964 int height = (int) ((double) rc.height() / scale);
02965 #ifndef QT_NO_TRANSFORMATIONS
02966 p->scale(scale, scale);
02967 #endif
02968 root->setPageTop(yOff);
02969 root->setPageBottom(yOff+height);
02970
02971 root->layer()->paint(p, QRect(0, yOff, root->docWidth(), height));
02972 if (more)
02973 *more = yOff + height < root->docHeight();
02974 p->restore();
02975
02976 root->setPagedMode(false);
02977 root->setStaticMode(false);
02978 m_part->xmlDocImpl()->setPaintDevice( this );
02979 }
02980
02981
02982 void KHTMLView::useSlowRepaints()
02983 {
02984 d->useSlowRepaints = true;
02985 setStaticBackground(true);
02986 }
02987
02988
02989 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
02990 {
02991 #ifndef KHTML_NO_SCROLLBARS
02992 d->vmode = mode;
02993 QScrollView::setVScrollBarMode(mode);
02994 #else
02995 Q_UNUSED( mode );
02996 #endif
02997 }
02998
02999 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
03000 {
03001 #ifndef KHTML_NO_SCROLLBARS
03002 d->hmode = mode;
03003 QScrollView::setHScrollBarMode(mode);
03004 #else
03005 Q_UNUSED( mode );
03006 #endif
03007 }
03008
03009 void KHTMLView::restoreScrollBar()
03010 {
03011 int ow = visibleWidth();
03012 QScrollView::setVScrollBarMode(d->vmode);
03013 if (visibleWidth() != ow)
03014 layout();
03015 d->prevScrollbarVisible = verticalScrollBar()->isVisible();
03016 }
03017
03018 QStringList KHTMLView::formCompletionItems(const QString &name) const
03019 {
03020 if (!m_part->settings()->isFormCompletionEnabled())
03021 return QStringList();
03022 if (!d->formCompletions)
03023 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
03024 return d->formCompletions->readListEntry(name);
03025 }
03026
03027 void KHTMLView::clearCompletionHistory(const QString& name)
03028 {
03029 if (!d->formCompletions)
03030 {
03031 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
03032 }
03033 d->formCompletions->writeEntry(name, "");
03034 d->formCompletions->sync();
03035 }
03036
03037 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
03038 {
03039 if (!m_part->settings()->isFormCompletionEnabled())
03040 return;
03041
03042
03043
03044 bool cc_number(true);
03045 for (unsigned int i = 0; i < value.length(); ++i)
03046 {
03047 QChar c(value[i]);
03048 if (!c.isNumber() && c != '-' && !c.isSpace())
03049 {
03050 cc_number = false;
03051 break;
03052 }
03053 }
03054 if (cc_number)
03055 return;
03056 QStringList items = formCompletionItems(name);
03057 if (!items.contains(value))
03058 items.prepend(value);
03059 while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
03060 items.remove(items.fromLast());
03061 d->formCompletions->writeEntry(name, items);
03062 }
03063
03064 void KHTMLView::addNonPasswordStorableSite(const QString& host)
03065 {
03066 if (!d->formCompletions) {
03067 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
03068 }
03069
03070 d->formCompletions->setGroup("NonPasswordStorableSites");
03071 QStringList sites = d->formCompletions->readListEntry("Sites");
03072 sites.append(host);
03073 d->formCompletions->writeEntry("Sites", sites);
03074 d->formCompletions->sync();
03075 d->formCompletions->setGroup(QString::null);
03076 }
03077
03078 bool KHTMLView::nonPasswordStorableSite(const QString& host) const
03079 {
03080 if (!d->formCompletions) {
03081 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
03082 }
03083 d->formCompletions->setGroup("NonPasswordStorableSites");
03084 QStringList sites = d->formCompletions->readListEntry("Sites");
03085 d->formCompletions->setGroup(QString::null);
03086
03087 return (sites.find(host) != sites.end());
03088 }
03089
03090
03091 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
03092 DOM::NodeImpl *targetNodeNonShared, bool cancelable,
03093 int detail,QMouseEvent *_mouse, bool setUnder,
03094 int mouseEventType)
03095 {
03096
03097 if (targetNode && targetNode->isTextNode())
03098 targetNode = targetNode->parentNode();
03099
03100 if (d->underMouse)
03101 d->underMouse->deref();
03102 d->underMouse = targetNode;
03103 if (d->underMouse)
03104 d->underMouse->ref();
03105
03106 if (d->underMouseNonShared)
03107 d->underMouseNonShared->deref();
03108 d->underMouseNonShared = targetNodeNonShared;
03109 if (d->underMouseNonShared)
03110 d->underMouseNonShared->ref();
03111
03112 int exceptioncode = 0;
03113 int pageX = 0;
03114 int pageY = 0;
03115 viewportToContents(_mouse->x(), _mouse->y(), pageX, pageY);
03116 int clientX = pageX - contentsX();
03117 int clientY = pageY - contentsY();
03118 int screenX = _mouse->globalX();
03119 int screenY = _mouse->globalY();
03120 int button = -1;
03121 switch (_mouse->button()) {
03122 case LeftButton:
03123 button = 0;
03124 break;
03125 case MidButton:
03126 button = 1;
03127 break;
03128 case RightButton:
03129 button = 2;
03130 break;
03131 default:
03132 break;
03133 }
03134 if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1)
03135 d->accessKeysPreActivate=false;
03136
03137 bool ctrlKey = (_mouse->state() & ControlButton);
03138 bool altKey = (_mouse->state() & AltButton);
03139 bool shiftKey = (_mouse->state() & ShiftButton);
03140 bool metaKey = (_mouse->state() & MetaButton);
03141
03142
03143 if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) {
03144
03145
03146
03147 NodeImpl *oldUnder = 0;
03148 if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
03149 NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
03150 m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
03151 oldUnder = mev.innerNode.handle();
03152
03153 if (oldUnder && oldUnder->isTextNode())
03154 oldUnder = oldUnder->parentNode();
03155 }
03156
03157 if (oldUnder != targetNode) {
03158
03159 if (oldUnder){
03160 oldUnder->ref();
03161 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
03162 true,true,m_part->xmlDocImpl()->defaultView(),
03163 0,screenX,screenY,clientX,clientY,pageX, pageY,
03164 ctrlKey,altKey,shiftKey,metaKey,
03165 button,targetNode);
03166 me->ref();
03167 oldUnder->dispatchEvent(me,exceptioncode,true);
03168 me->deref();
03169 }
03170
03171
03172 if (targetNode) {
03173 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
03174 true,true,m_part->xmlDocImpl()->defaultView(),
03175 0,screenX,screenY,clientX,clientY,pageX, pageY,
03176 ctrlKey,altKey,shiftKey,metaKey,
03177 button,oldUnder);
03178
03179 me->ref();
03180 targetNode->dispatchEvent(me,exceptioncode,true);
03181 me->deref();
03182 }
03183
03184 if (oldUnder)
03185 oldUnder->deref();
03186 }
03187 }
03188
03189 bool swallowEvent = false;
03190
03191 if (targetNode) {
03192
03193 bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
03194 _mouse->type() == QEvent::MouseButtonDblClick );
03195 MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
03196 true,cancelable,m_part->xmlDocImpl()->defaultView(),
03197 detail,screenX,screenY,clientX,clientY,pageX, pageY,
03198 ctrlKey,altKey,shiftKey,metaKey,
03199 button,0, _mouse, dblclick );
03200 me->ref();
03201 targetNode->dispatchEvent(me,exceptioncode,true);
03202 bool defaultHandled = me->defaultHandled();
03203 if (defaultHandled || me->defaultPrevented())
03204 swallowEvent = true;
03205 me->deref();
03206
03207 if (eventId == EventImpl::MOUSEDOWN_EVENT) {
03208
03209
03210
03211
03212 DOM::NodeImpl* nodeImpl = targetNode;
03213 for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode());
03214 if (nodeImpl && nodeImpl->isMouseFocusable())
03215 m_part->xmlDocImpl()->setFocusNode(nodeImpl);
03216 else if (!nodeImpl || !nodeImpl->focused())
03217 m_part->xmlDocImpl()->setFocusNode(0);
03218 }
03219 }
03220
03221 return swallowEvent;
03222 }
03223
03224 void KHTMLView::setIgnoreWheelEvents( bool e )
03225 {
03226 d->ignoreWheelEvents = e;
03227 }
03228
03229 #ifndef QT_NO_WHEELEVENT
03230
03231 void KHTMLView::viewportWheelEvent(QWheelEvent* e)
03232 {
03233 if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false;
03234
03235 if ( ( e->state() & ControlButton) == ControlButton )
03236 {
03237 emit zoomView( - e->delta() );
03238 e->accept();
03239 }
03240 else if (d->firstRelayout)
03241 {
03242 e->accept();
03243 }
03244 else if( ( (e->orientation() == Vertical &&
03245 ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
03246 || e->delta() > 0 && contentsY() <= 0
03247 || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight()))
03248 ||
03249 (e->orientation() == Horizontal &&
03250 ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible())
03251 || e->delta() > 0 && contentsX() <=0
03252 || e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth())))
03253 && m_part->parentPart())
03254 {
03255 if ( m_part->parentPart()->view() )
03256 m_part->parentPart()->view()->wheelEvent( e );
03257 e->ignore();
03258 }
03259 else
03260 {
03261 d->scrollBarMoved = true;
03262 QScrollView::viewportWheelEvent( e );
03263
03264 QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, QPoint(-1,-1), QPoint(-1,-1), Qt::NoButton, e->state() );
03265 emit viewportMouseMoveEvent ( tempEvent );
03266 delete tempEvent;
03267 }
03268
03269 }
03270 #endif
03271
03272 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
03273 {
03274
03275
03276
03277 if ( m_part->parentPart() )
03278 {
03279 QApplication::sendEvent(m_part->parentPart()->widget(), ev);
03280 return;
03281 }
03282 QScrollView::dragEnterEvent( ev );
03283 }
03284
03285 void KHTMLView::dropEvent( QDropEvent *ev )
03286 {
03287
03288
03289
03290 if ( m_part->parentPart() )
03291 {
03292 QApplication::sendEvent(m_part->parentPart()->widget(), ev);
03293 return;
03294 }
03295 QScrollView::dropEvent( ev );
03296 }
03297
03298 void KHTMLView::focusInEvent( QFocusEvent *e )
03299 {
03300 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03301 m_part->enableFindAheadActions( true );
03302 #endif
03303 DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0;
03304 if (fn && fn->renderer() && fn->renderer()->isWidget() &&
03305 (e->reason() != QFocusEvent::Mouse) &&
03306 static_cast<khtml::RenderWidget*>(fn->renderer())->widget())
03307 static_cast<khtml::RenderWidget*>(fn->renderer())->widget()->setFocus();
03308 #ifndef KHTML_NO_CARET
03309
03310
03311 if (d->m_caretViewContext &&
03312 d->m_caretViewContext->freqTimerId == -1 &&
03313 fn) {
03314 if (m_part->isCaretMode()
03315 || m_part->isEditable()
03316 || (fn && fn->renderer()
03317 && fn->renderer()->style()->userInput()
03318 == UI_ENABLED)) {
03319 d->m_caretViewContext->freqTimerId = startTimer(500);
03320 d->m_caretViewContext->visible = true;
03321 }
03322 }
03323 showCaret();
03324 #endif // KHTML_NO_CARET
03325 QScrollView::focusInEvent( e );
03326 }
03327
03328 void KHTMLView::focusOutEvent( QFocusEvent *e )
03329 {
03330 if(m_part) m_part->stopAutoScroll();
03331
03332 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03333 if(d->typeAheadActivated)
03334 {
03335 findTimeout();
03336 }
03337 m_part->enableFindAheadActions( false );
03338 #endif // KHTML_NO_TYPE_AHEAD_FIND
03339
03340 #ifndef KHTML_NO_CARET
03341 if (d->m_caretViewContext) {
03342 switch (d->m_caretViewContext->displayNonFocused) {
03343 case KHTMLPart::CaretInvisible:
03344 hideCaret();
03345 break;
03346 case KHTMLPart::CaretVisible: {
03347 killTimer(d->m_caretViewContext->freqTimerId);
03348 d->m_caretViewContext->freqTimerId = -1;
03349 NodeImpl *caretNode = m_part->xmlDocImpl()->focusNode();
03350 if (!d->m_caretViewContext->visible && (m_part->isCaretMode()
03351 || m_part->isEditable()
03352 || (caretNode && caretNode->renderer()
03353 && caretNode->renderer()->style()->userInput()
03354 == UI_ENABLED))) {
03355 d->m_caretViewContext->visible = true;
03356 showCaret(true);
03357 }
03358 break;
03359 }
03360 case KHTMLPart::CaretBlink:
03361
03362 break;
03363 }
03364 }
03365 #endif // KHTML_NO_CARET
03366
03367 if ( d->cursor_icon_widget )
03368 d->cursor_icon_widget->hide();
03369
03370 QScrollView::focusOutEvent( e );
03371 }
03372
03373 void KHTMLView::slotScrollBarMoved()
03374 {
03375 if ( !d->firstRelayout && !d->complete && m_part->xmlDocImpl() &&
03376 d->layoutSchedulingEnabled) {
03377
03378 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() );
03379 if (root && root->needsLayout()) {
03380 unscheduleRelayout();
03381 layout();
03382 }
03383 }
03384 if (!d->scrollingSelf) {
03385 d->scrollBarMoved = true;
03386 d->contentsMoving = true;
03387
03388 scheduleRepaint(0, 0, 0, 0);
03389 }
03390
03391 if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement())
03392 m_part->xmlDocImpl()->documentElement()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
03393 }
03394
03395 void KHTMLView::timerEvent ( QTimerEvent *e )
03396 {
03397
03398 if ( e->timerId() == d->scrollTimerId ) {
03399 if( d->scrollSuspended )
03400 return;
03401 switch (d->scrollDirection) {
03402 case KHTMLViewPrivate::ScrollDown:
03403 if (contentsY() + visibleHeight () >= contentsHeight())
03404 d->newScrollTimer(this, 0);
03405 else
03406 scrollBy( 0, d->scrollBy );
03407 break;
03408 case KHTMLViewPrivate::ScrollUp:
03409 if (contentsY() <= 0)
03410 d->newScrollTimer(this, 0);
03411 else
03412 scrollBy( 0, -d->scrollBy );
03413 break;
03414 case KHTMLViewPrivate::ScrollRight:
03415 if (contentsX() + visibleWidth () >= contentsWidth())
03416 d->newScrollTimer(this, 0);
03417 else
03418 scrollBy( d->scrollBy, 0 );
03419 break;
03420 case KHTMLViewPrivate::ScrollLeft:
03421 if (contentsX() <= 0)
03422 d->newScrollTimer(this, 0);
03423 else
03424 scrollBy( -d->scrollBy, 0 );
03425 break;
03426 }
03427 return;
03428 }
03429 else if ( e->timerId() == d->layoutTimerId ) {
03430 d->dirtyLayout = true;
03431 layout();
03432 if (d->firstRelayout) {
03433 d->firstRelayout = false;
03434 verticalScrollBar()->setEnabled( true );
03435 horizontalScrollBar()->setEnabled( true );
03436 }
03437 }
03438 #ifndef KHTML_NO_CARET
03439 else if (d->m_caretViewContext
03440 && e->timerId() == d->m_caretViewContext->freqTimerId) {
03441 d->m_caretViewContext->visible = !d->m_caretViewContext->visible;
03442 if (d->m_caretViewContext->displayed) {
03443 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03444 d->m_caretViewContext->width,
03445 d->m_caretViewContext->height);
03446 }
03447
03448
03449 return;
03450 }
03451 #endif
03452
03453 d->contentsMoving = false;
03454 if( m_part->xmlDocImpl() ) {
03455 DOM::DocumentImpl *document = m_part->xmlDocImpl();
03456 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
03457
03458 if ( root && root->needsLayout() ) {
03459 killTimer(d->repaintTimerId);
03460 d->repaintTimerId = 0;
03461 scheduleRelayout();
03462 return;
03463 }
03464 }
03465
03466 setStaticBackground(d->useSlowRepaints);
03467
03468
03469 killTimer(d->repaintTimerId);
03470 d->repaintTimerId = 0;
03471
03472 QRect updateRegion;
03473 QMemArray<QRect> rects = d->updateRegion.rects();
03474
03475 d->updateRegion = QRegion();
03476
03477 if ( rects.size() )
03478 updateRegion = rects[0];
03479
03480 for ( unsigned i = 1; i < rects.size(); ++i ) {
03481 QRect newRegion = updateRegion.unite(rects[i]);
03482 if (2*newRegion.height() > 3*updateRegion.height() )
03483 {
03484 repaintContents( updateRegion );
03485 updateRegion = rects[i];
03486 }
03487 else
03488 updateRegion = newRegion;
03489 }
03490
03491 if ( !updateRegion.isNull() )
03492 repaintContents( updateRegion );
03493
03494
03495
03496
03497
03498
03499 if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
03500 QWidget* w;
03501 d->dirtyLayout = false;
03502
03503 QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
03504 QPtrList<RenderWidget> toRemove;
03505 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
03506 int xp = 0, yp = 0;
03507 w = it.current();
03508 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
03509 if (!rw->absolutePosition(xp, yp) ||
03510 !visibleRect.intersects(QRect(xp, yp, w->width(), w->height())))
03511 toRemove.append(rw);
03512 }
03513 for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
03514 if ( (w = d->visibleWidgets.take(r) ) )
03515 addChild(w, 0, -500000);
03516 }
03517
03518 emit repaintAccessKeys();
03519 if (d->emitCompletedAfterRepaint) {
03520 bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull;
03521 d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone;
03522 if ( full )
03523 emit m_part->completed();
03524 else
03525 emit m_part->completed(true);
03526 }
03527 }
03528
03529 void KHTMLView::scheduleRelayout(khtml::RenderObject * )
03530 {
03531 if (!d->layoutSchedulingEnabled || d->layoutTimerId)
03532 return;
03533
03534 d->layoutTimerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()
03535 ? 1000 : 0 );
03536 }
03537
03538 void KHTMLView::unscheduleRelayout()
03539 {
03540 if (!d->layoutTimerId)
03541 return;
03542
03543 killTimer(d->layoutTimerId);
03544 d->layoutTimerId = 0;
03545 }
03546
03547 void KHTMLView::unscheduleRepaint()
03548 {
03549 if (!d->repaintTimerId)
03550 return;
03551
03552 killTimer(d->repaintTimerId);
03553 d->repaintTimerId = 0;
03554 }
03555
03556 void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap)
03557 {
03558 bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing();
03559
03560
03561
03562
03563 int time = parsing ? 300 : (!asap ? ( !d->complete ? 100 : 20 ) : 0);
03564
03565 #ifdef DEBUG_FLICKER
03566 QPainter p;
03567 p.begin( viewport() );
03568
03569 int vx, vy;
03570 contentsToViewport( x, y, vx, vy );
03571 p.fillRect( vx, vy, w, h, Qt::red );
03572 p.end();
03573 #endif
03574
03575 d->updateRegion = d->updateRegion.unite(QRect(x,y,w,h));
03576
03577 if (asap && !parsing)
03578 unscheduleRepaint();
03579
03580 if ( !d->repaintTimerId )
03581 d->repaintTimerId = startTimer( time );
03582
03583
03584 }
03585
03586 void KHTMLView::complete( bool pendingAction )
03587 {
03588
03589
03590 d->complete = true;
03591
03592
03593 if (d->layoutTimerId)
03594 {
03595
03596
03597 killTimer(d->layoutTimerId);
03598 d->layoutTimerId = startTimer( 0 );
03599 d->emitCompletedAfterRepaint = pendingAction ?
03600 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
03601 }
03602
03603
03604 if (d->repaintTimerId)
03605 {
03606
03607
03608 killTimer(d->repaintTimerId);
03609 d->repaintTimerId = startTimer( 20 );
03610 d->emitCompletedAfterRepaint = pendingAction ?
03611 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
03612 }
03613
03614 if (!d->emitCompletedAfterRepaint)
03615 {
03616 if (!pendingAction)
03617 emit m_part->completed();
03618 else
03619 emit m_part->completed(true);
03620 }
03621
03622 }
03623
03624 void KHTMLView::slotMouseScrollTimer()
03625 {
03626 scrollBy( d->m_mouseScroll_byX, d->m_mouseScroll_byY );
03627 }
03628
03629 #ifndef KHTML_NO_CARET
03630
03631
03632
03633
03634 #include "khtml_caret.cpp"
03635
03636 void KHTMLView::initCaret(bool keepSelection)
03637 {
03638 #if DEBUG_CARETMODE > 0
03639 kdDebug(6200) << "begin initCaret" << endl;
03640 #endif
03641
03642 if (m_part->xmlDocImpl()) {
03643 #if 0
03644 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
03645 if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
03646 #endif
03647 d->caretViewContext();
03648 bool cmoved = d->m_caretViewContext->caretMoved;
03649 if (m_part->d->caretNode().isNull()) {
03650
03651 m_part->d->caretNode() = m_part->document();
03652 m_part->d->caretOffset() = 0L;
03653
03654
03655
03656 if (!m_part->d->caretNode().handle()->renderer()) return;
03657 }
03658
03659
03660
03661 moveCaretTo(m_part->d->caretNode().handle(), m_part->d->caretOffset(), !keepSelection);
03662
03663
03664 d->m_caretViewContext->caretMoved = cmoved;
03665 }
03666 #if DEBUG_CARETMODE > 0
03667 kdDebug(6200) << "end initCaret" << endl;
03668 #endif
03669 }
03670
03671 bool KHTMLView::caretOverrides() const
03672 {
03673 bool cm = m_part->isCaretMode();
03674 bool dm = m_part->isEditable();
03675 return cm && !dm ? false
03676 : (dm || m_part->d->caretNode().handle()->contentEditable())
03677 && d->editorContext()->override;
03678 }
03679
03680 void KHTMLView::ensureNodeHasFocus(NodeImpl *node)
03681 {
03682 if (m_part->isCaretMode() || m_part->isEditable()) return;
03683 if (node->focused()) return;
03684
03685
03686 NodeImpl *firstAncestor = 0;
03687 while (node) {
03688 if (node->renderer()
03689 && node->renderer()->style()->userInput() != UI_ENABLED)
03690 break;
03691 firstAncestor = node;
03692 node = node->parentNode();
03693 }
03694
03695 if (!node) firstAncestor = 0;
03696
03697 DocumentImpl *doc = m_part->xmlDocImpl();
03698
03699 if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer()
03700 && doc->focusNode()->renderer()->isWidget())
03701 return;
03702
03703
03704 #if DEBUG_CARETMODE > 1
03705 kdDebug(6200) << k_funcinfo << "firstAncestor " << firstAncestor << ": "
03706 << (firstAncestor ? firstAncestor->nodeName().string() : QString::null) << endl;
03707 #endif
03708 doc->setFocusNode(firstAncestor);
03709 emit m_part->nodeActivated(Node(firstAncestor));
03710 }
03711
03712 void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox)
03713 {
03714 if (!m_part || m_part->d->caretNode().isNull()) return;
03715 d->caretViewContext();
03716 NodeImpl *caretNode = m_part->d->caretNode().handle();
03717 #if DEBUG_CARETMODE > 0
03718 kdDebug(6200) << "recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ? " "+caretNode->nodeName().string() : QString::null) << " r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ? " \"" + QConstString(static_cast<RenderText *>(caretNode->renderer())->str->s, kMin(static_cast<RenderText *>(caretNode->renderer())->str->l, 15u)).string() + "\"" : QString::null) << endl;
03719 #endif
03720 caretNode->getCaret(m_part->d->caretOffset(), caretOverrides(),
03721 d->m_caretViewContext->x, d->m_caretViewContext->y,
03722 d->m_caretViewContext->width,
03723 d->m_caretViewContext->height);
03724
03725 if (hintBox && d->m_caretViewContext->x == -1) {
03726 #if DEBUG_CARETMODE > 1
03727 kdDebug(6200) << "using hint inline box coordinates" << endl;
03728 #endif
03729 RenderObject *r = caretNode->renderer();
03730 const QFontMetrics &fm = r->style()->fontMetrics();
03731 int absx, absy;
03732 r->containingBlock()->absolutePosition(absx, absy,
03733 false);
03734 d->m_caretViewContext->x = absx + hintBox->xPos();
03735 d->m_caretViewContext->y = absy + hintBox->yPos();
03736
03737 d->m_caretViewContext->width = 1;
03738
03739
03740 d->m_caretViewContext->height = fm.height();
03741 }
03742
03743 #if DEBUG_CARETMODE > 4
03744
03745 #endif
03746 #if DEBUG_CARETMODE > 0
03747 kdDebug(6200) << "caret: ofs="<<m_part->d->caretOffset()<<" "
03748 <<" x="<<d->m_caretViewContext->x<<" y="<<d->m_caretViewContext->y
03749 <<" h="<<d->m_caretViewContext->height<<endl;
03750 #endif
03751 }
03752
03753 void KHTMLView::caretOn()
03754 {
03755 if (d->m_caretViewContext) {
03756 killTimer(d->m_caretViewContext->freqTimerId);
03757
03758 if (hasFocus() || d->m_caretViewContext->displayNonFocused
03759 == KHTMLPart::CaretBlink) {
03760 d->m_caretViewContext->freqTimerId = startTimer(500);
03761 } else {
03762 d->m_caretViewContext->freqTimerId = -1;
03763 }
03764
03765 d->m_caretViewContext->visible = true;
03766 if ((d->m_caretViewContext->displayed = (hasFocus()
03767 || d->m_caretViewContext->displayNonFocused
03768 != KHTMLPart::CaretInvisible))) {
03769 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03770 d->m_caretViewContext->width,
03771 d->m_caretViewContext->height);
03772 }
03773
03774 }
03775 }
03776
03777 void KHTMLView::caretOff()
03778 {
03779 if (d->m_caretViewContext) {
03780 killTimer(d->m_caretViewContext->freqTimerId);
03781 d->m_caretViewContext->freqTimerId = -1;
03782 d->m_caretViewContext->displayed = false;
03783 if (d->m_caretViewContext->visible) {
03784 d->m_caretViewContext->visible = false;
03785 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03786 d->m_caretViewContext->width,
03787 d->m_caretViewContext->height);
03788 }
03789
03790 }
03791 }
03792
03793 void KHTMLView::showCaret(bool forceRepaint)
03794 {
03795 if (d->m_caretViewContext) {
03796 d->m_caretViewContext->displayed = true;
03797 if (d->m_caretViewContext->visible) {
03798 if (!forceRepaint) {
03799 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03800 d->m_caretViewContext->width,
03801 d->m_caretViewContext->height);
03802 } else {
03803 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03804 d->m_caretViewContext->width,
03805 d->m_caretViewContext->height);
03806 }
03807 }
03808
03809 }
03810 }
03811
03812 bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode, long startOffset,
03813 NodeImpl *endNode, long endOffset)
03814 {
03815 m_part->d->m_selectionStart = m_part->d->m_selectionEnd = m_part->d->caretNode();
03816 m_part->d->m_startOffset = m_part->d->m_endOffset = m_part->d->caretOffset();
03817 m_part->d->m_extendAtEnd = true;
03818
03819 bool folded = startNode != endNode || startOffset != endOffset;
03820
03821
03822 if (folded) {
03823 m_part->xmlDocImpl()->clearSelection();
03824 }
03825
03826 return folded;
03827 }
03828
03829 void KHTMLView::hideCaret()
03830 {
03831 if (d->m_caretViewContext) {
03832 if (d->m_caretViewContext->visible) {
03833
03834 d->m_caretViewContext->visible = false;
03835
03836
03837 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03838 d->m_caretViewContext->width,
03839 d->m_caretViewContext->height);
03840 d->m_caretViewContext->visible = true;
03841 }
03842 d->m_caretViewContext->displayed = false;
03843
03844 }
03845 }
03846
03847 int KHTMLView::caretDisplayPolicyNonFocused() const
03848 {
03849 if (d->m_caretViewContext)
03850 return d->m_caretViewContext->displayNonFocused;
03851 else
03852 return KHTMLPart::CaretInvisible;
03853 }
03854
03855 void KHTMLView::setCaretDisplayPolicyNonFocused(int policy)
03856 {
03857 d->caretViewContext();
03858
03859 d->m_caretViewContext->displayNonFocused = (KHTMLPart::CaretDisplayPolicy)policy;
03860
03861
03862 if (!hasFocus()) {
03863 switch (d->m_caretViewContext->displayNonFocused) {
03864 case KHTMLPart::CaretInvisible:
03865 hideCaret();
03866 break;
03867 case KHTMLPart::CaretBlink:
03868 if (d->m_caretViewContext->freqTimerId != -1) break;
03869 d->m_caretViewContext->freqTimerId = startTimer(500);
03870
03871 case KHTMLPart::CaretVisible:
03872 d->m_caretViewContext->displayed = true;
03873 showCaret();
03874 break;
03875 }
03876 }
03877 }
03878
03879 bool KHTMLView::placeCaret(CaretBox *hintBox)
03880 {
03881 CaretViewContext *cv = d->caretViewContext();
03882 caretOff();
03883 NodeImpl *caretNode = m_part->d->caretNode().handle();
03884
03885 if (!caretNode || !caretNode->renderer()) return false;
03886 ensureNodeHasFocus(caretNode);
03887 if (m_part->isCaretMode() || m_part->isEditable()
03888 || caretNode->renderer()->style()->userInput() == UI_ENABLED) {
03889 recalcAndStoreCaretPos(hintBox);
03890
03891 cv->origX = cv->x;
03892
03893 caretOn();
03894 return true;
03895 }
03896 return false;
03897 }
03898
03899 void KHTMLView::ensureCaretVisible()
03900 {
03901 CaretViewContext *cv = d->m_caretViewContext;
03902 if (!cv) return;
03903 ensureVisible(cv->x, cv->y, cv->width, cv->height);
03904 d->scrollBarMoved = false;
03905 }
03906
03907 bool KHTMLView::extendSelection(NodeImpl *oldStartSel, long oldStartOfs,
03908 NodeImpl *oldEndSel, long oldEndOfs)
03909 {
03910 bool changed = false;
03911 if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
03912 && m_part->d->m_startOffset == m_part->d->m_endOffset) {
03913 changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03914 m_part->d->m_extendAtEnd = true;
03915 } else do {
03916 changed = m_part->d->m_selectionStart.handle() != oldStartSel
03917 || m_part->d->m_startOffset != oldStartOfs
03918 || m_part->d->m_selectionEnd.handle() != oldEndSel
03919 || m_part->d->m_endOffset != oldEndOfs;
03920 if (!changed) break;
03921
03922
03923 NodeImpl *startNode;
03924 long startOffset;
03925 if (m_part->d->m_extendAtEnd) {
03926 startNode = m_part->d->m_selectionStart.handle();
03927 startOffset = m_part->d->m_startOffset;
03928 } else {
03929 startNode = m_part->d->m_selectionEnd.handle();
03930 startOffset = m_part->d->m_endOffset;
03931 m_part->d->m_selectionEnd = m_part->d->m_selectionStart;
03932 m_part->d->m_endOffset = m_part->d->m_startOffset;
03933 m_part->d->m_extendAtEnd = true;
03934 }
03935
03936 bool swapNeeded = false;
03937 if (!m_part->d->m_selectionEnd.isNull() && startNode) {
03938 swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset,
03939 m_part->d->m_selectionEnd.handle(),
03940 m_part->d->m_endOffset) >= 0;
03941 }
03942
03943 m_part->d->m_selectionStart = startNode;
03944 m_part->d->m_startOffset = startOffset;
03945
03946 if (swapNeeded) {
03947 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionEnd.handle(),
03948 m_part->d->m_endOffset, m_part->d->m_selectionStart.handle(),
03949 m_part->d->m_startOffset);
03950 } else {
03951 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
03952 m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
03953 m_part->d->m_endOffset);
03954 }
03955 } while(false);
03956 return changed;
03957 }
03958
03959 void KHTMLView::updateSelection(NodeImpl *oldStartSel, long oldStartOfs,
03960 NodeImpl *oldEndSel, long oldEndOfs)
03961 {
03962 if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
03963 && m_part->d->m_startOffset == m_part->d->m_endOffset) {
03964 if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) {
03965 m_part->emitSelectionChanged();
03966 }
03967 m_part->d->m_extendAtEnd = true;
03968 } else {
03969
03970 if (!m_part->d->m_selectionEnd.isNull() && !m_part->d->m_selectionEnd.isNull()) {
03971 bool swapNeeded = RangeImpl::compareBoundaryPoints(
03972 m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset,
03973 m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0;
03974 if (swapNeeded) {
03975 DOM::Node tmpNode = m_part->d->m_selectionStart;
03976 long tmpOffset = m_part->d->m_startOffset;
03977 m_part->d->m_selectionStart = m_part->d->m_selectionEnd;
03978 m_part->d->m_startOffset = m_part->d->m_endOffset;
03979 m_part->d->m_selectionEnd = tmpNode;
03980 m_part->d->m_endOffset = tmpOffset;
03981 m_part->d->m_startBeforeEnd = true;
03982 m_part->d->m_extendAtEnd = !m_part->d->m_extendAtEnd;
03983 }
03984 }
03985
03986 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
03987 m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
03988 m_part->d->m_endOffset);
03989 m_part->emitSelectionChanged();
03990 }
03991 }
03992
03993 void KHTMLView::caretKeyPressEvent(QKeyEvent *_ke)
03994 {
03995 NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
03996 long oldStartOfs = m_part->d->m_startOffset;
03997 NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
03998 long oldEndOfs = m_part->d->m_endOffset;
03999
04000 NodeImpl *oldCaretNode = m_part->d->caretNode().handle();
04001 long oldOffset = m_part->d->caretOffset();
04002
04003 bool ctrl = _ke->state() & ControlButton;
04004
04005
04006 switch(_ke->key()) {
04007 case Key_Space:
04008 break;
04009
04010 case Key_Down:
04011 moveCaretNextLine(1);
04012 break;
04013
04014 case Key_Up:
04015 moveCaretPrevLine(1);
04016 break;
04017
04018 case Key_Left:
04019 moveCaretBy(false, ctrl ? CaretByWord : CaretByCharacter, 1);
04020 break;
04021
04022 case Key_Right:
04023 moveCaretBy(true, ctrl ? CaretByWord : CaretByCharacter, 1);
04024 break;
04025
04026 case Key_Next:
04027 moveCaretNextPage();
04028 break;
04029
04030 case Key_Prior:
04031 moveCaretPrevPage();
04032 break;
04033
04034 case Key_Home:
04035 if (ctrl)
04036 moveCaretToDocumentBoundary(false);
04037 else
04038 moveCaretToLineBegin();
04039 break;
04040
04041 case Key_End:
04042 if (ctrl)
04043 moveCaretToDocumentBoundary(true);
04044 else
04045 moveCaretToLineEnd();
04046 break;
04047
04048 }
04049
04050 if ((m_part->d->caretNode().handle() != oldCaretNode
04051 || m_part->d->caretOffset() != oldOffset)
04052
04053 && !m_part->d->caretNode().isNull()) {
04054
04055 d->m_caretViewContext->caretMoved = true;
04056
04057 if (_ke->state() & ShiftButton) {
04058 updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
04059 } else {
04060 if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs))
04061 m_part->emitSelectionChanged();
04062 }
04063
04064 m_part->emitCaretPositionChanged(m_part->d->caretNode(), m_part->d->caretOffset());
04065 }
04066
04067 _ke->accept();
04068 }
04069
04070 bool KHTMLView::moveCaretTo(NodeImpl *node, long offset, bool clearSel)
04071 {
04072 if (!node) return false;
04073 ElementImpl *baseElem = determineBaseElement(node);
04074 RenderFlow *base = static_cast<RenderFlow *>(baseElem ? baseElem->renderer() : 0);
04075 if (!node) return false;
04076
04077
04078
04079
04080 CaretBoxLineDeleter cblDeleter;
04081
04082 long r_ofs;
04083 CaretBoxIterator cbit;
04084 CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit);
04085 if(!cbl) {
04086 kdWarning() << "KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL" << endl;
04087 return false;
04088 }
04089
04090 #if DEBUG_CARETMODE > 3
04091 if (cbl) kdDebug(6200) << cbl->information() << endl;
04092 #endif
04093 CaretBox *box = *cbit;
04094 if (cbit != cbl->end() && box->object() != node->renderer()) {
04095 if (box->object()->element()) {
04096 mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(),
04097 box->isOutsideEnd(), node, offset);
04098
04099 #if DEBUG_CARETMODE > 1
04100 kdDebug(6200) << "set new node " << node->nodeName().string() << "@" << node << endl;
04101 #endif
04102 } else {
04103
04104 box = 0;
04105 kdError(6200) << "Box contains no node! Crash imminent" << endl;
04106 }
04107 }
04108
04109 NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
04110 long oldStartOfs = m_part->d->m_startOffset;
04111 NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
04112 long oldEndOfs = m_part->d->m_endOffset;
04113
04114
04115 bool posChanged = m_part->d->caretNode().handle() != node
04116 || m_part->d->caretOffset() != offset;
04117 bool selChanged = false;
04118
04119 m_part->d->caretNode() = node;
04120 m_part->d->caretOffset() = offset;
04121 if (clearSel || !oldStartSel || !oldEndSel) {
04122 selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
04123 } else {
04124
04125
04126 selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
04127
04128
04129 }
04130
04131 d->caretViewContext()->caretMoved = true;
04132
04133 bool visible_caret = placeCaret(box);
04134
04135
04136
04137
04138 if (posChanged) {
04139 m_part->emitCaretPositionChanged(visible_caret ? node : 0, offset);
04140 }
04141
04142 return selChanged;
04143 }
04144
04145 void KHTMLView::moveCaretByLine(bool next, int count)
04146 {
04147 Node &caretNodeRef = m_part->d->caretNode();
04148 if (caretNodeRef.isNull()) return;
04149
04150 NodeImpl *caretNode = caretNodeRef.handle();
04151
04152 long offset = m_part->d->caretOffset();
04153
04154 CaretViewContext *cv = d->caretViewContext();
04155
04156 ElementImpl *baseElem = determineBaseElement(caretNode);
04157 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
04158
04159 ErgonomicEditableLineIterator it(ld.current(), cv->origX);
04160
04161
04162 while (count > 0 && it != ld.end() && it != ld.preBegin()) {
04163 count--;
04164 if (next) ++it; else --it;
04165 }
04166
04167
04168 if (it == ld.end() || it == ld.preBegin()) return;
04169
04170 int x, absx, absy;
04171 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
04172
04173 placeCaretOnLine(caretBox, x, absx, absy);
04174 }
04175
04176 void KHTMLView::placeCaretOnLine(CaretBox *caretBox, int x, int absx, int absy)
04177 {
04178
04179 if (!caretBox) return;
04180
04181 RenderObject *caretRender = caretBox->object();
04182
04183 #if DEBUG_CARETMODE > 0
04184 kdDebug(6200) << "got valid caretBox " << caretBox << endl;
04185 kdDebug(6200) << "xPos: " << caretBox->xPos() << " yPos: " << caretBox->yPos()
04186 << " width: " << caretBox->width() << " height: " << caretBox->height() << endl;
04187 InlineTextBox *tb = static_cast<InlineTextBox *>(caretBox->inlineBox());
04188 if (caretBox->isInlineTextBox()) { kdDebug(6200) << "contains \"" << QString(static_cast<RenderText *>(tb->object())->str->s + tb->m_start, tb->m_len) << "\"" << endl;}
04189 #endif
04190
04191 int caretHeight = caretBox->height();
04192 bool isText = caretBox->isInlineTextBox();
04193 int yOfs = 0;
04194 if (isText) {
04195
04196 RenderText *t = static_cast<RenderText *>(caretRender);
04197 const QFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine);
04198 caretHeight = fm.height();
04199 yOfs = caretBox->inlineBox()->baseline() - fm.ascent();
04200 }
04201
04202 caretOff();
04203
04204
04205 NodeImpl *caretNode;
04206 long &offset = m_part->d->caretOffset();
04207 mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(),
04208 caretBox->isOutsideEnd(), caretNode, offset);
04209
04210
04211 d->m_caretViewContext->y = caretBox->yPos() + yOfs;
04212 d->m_caretViewContext->height = caretHeight;
04213 d->m_caretViewContext->width = 1;
04214
04215 int xPos = caretBox->xPos();
04216 int caretBoxWidth = caretBox->width();
04217 d->m_caretViewContext->x = xPos;
04218
04219 if (!caretBox->isOutside()) {
04220
04221 long r_ofs = 0;
04222 if (x <= xPos) {
04223 r_ofs = caretBox->minOffset();
04224
04225 } else if (x > xPos && x <= xPos + caretBoxWidth) {
04226 if (isText) {
04227 r_ofs = static_cast<InlineTextBox *>(caretBox->inlineBox())
04228 ->offsetForPoint(x, d->m_caretViewContext->x);
04229 #if DEBUG_CARETMODE > 2
04230 kdDebug(6200) << "deviation from origX " << d->m_caretViewContext->x - x << endl;
04231 #endif
04232 #if 0
04233 } else {
04234 if (xPos + caretBoxWidth - x < x - xPos) {
04235 d->m_caretViewContext->x = xPos + caretBoxWidth;
04236 r_ofs = caretNode ? caretNode->maxOffset() : 1;
04237 } else {
04238 d->m_caretViewContext->x = xPos;
04239 r_ofs = caretNode ? caretNode->minOffset() : 0;
04240 }
04241 #endif
04242 }
04243 } else {
04244 d->m_caretViewContext->x = xPos + caretBoxWidth;
04245 r_ofs = caretBox->maxOffset();
04246 }
04247 offset = r_ofs;
04248 }
04249 #if DEBUG_CARETMODE > 0
04250 kdDebug(6200) << "new offset: " << offset << endl;
04251 #endif
04252
04253 m_part->d->caretNode() = caretNode;
04254 m_part->d->caretOffset() = offset;
04255
04256 d->m_caretViewContext->x += absx;
04257 d->m_caretViewContext->y += absy;
04258
04259 #if DEBUG_CARETMODE > 1
04260 kdDebug(6200) << "new caret position: x " << d->m_caretViewContext->x << " y " << d->m_caretViewContext->y << " w " << d->m_caretViewContext->width << " h " << d->m_caretViewContext->height << " absx " << absx << " absy " << absy << endl;
04261 #endif
04262
04263 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
04264 d->m_caretViewContext->width, d->m_caretViewContext->height);
04265 d->scrollBarMoved = false;
04266
04267 ensureNodeHasFocus(caretNode);
04268 caretOn();
04269 }
04270
04271 void KHTMLView::moveCaretToLineBoundary(bool end)
04272 {
04273 Node &caretNodeRef = m_part->d->caretNode();
04274 if (caretNodeRef.isNull()) return;
04275
04276 NodeImpl *caretNode = caretNodeRef.handle();
04277
04278 long offset = m_part->d->caretOffset();
04279
04280 ElementImpl *baseElem = determineBaseElement(caretNode);
04281 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
04282
04283 EditableLineIterator it = ld.current();
04284 if (it == ld.end()) return;
04285
04286 EditableCaretBoxIterator fbit(it, end);
04287 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
04288 CaretBox *b = *fbit;
04289
04290 RenderObject *cb = b->containingBlock();
04291 int absx, absy;
04292
04293 if (cb) cb->absolutePosition(absx,absy);
04294 else absx = absy = 0;
04295
04296 int x = b->xPos() + (end && !b->isOutside() ? b->width() : 0);
04297 d->m_caretViewContext->origX = absx + x;
04298 placeCaretOnLine(b, x, absx, absy);
04299 }
04300
04301 void KHTMLView::moveCaretToDocumentBoundary(bool end)
04302 {
04303 Node &caretNodeRef = m_part->d->caretNode();
04304 if (caretNodeRef.isNull()) return;
04305
04306 NodeImpl *caretNode = caretNodeRef.handle();
04307
04308 long offset = m_part->d->caretOffset();
04309
04310 ElementImpl *baseElem = determineBaseElement(caretNode);
04311 LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem);
04312
04313 EditableLineIterator it(end ? ld.preEnd() : ld.begin(), end);
04314 if (it == ld.end() || it == ld.preBegin()) return;
04315
04316 EditableCaretBoxIterator fbit = it;
04317 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
04318 CaretBox *b = *fbit;
04319
04320 RenderObject *cb = (*it)->containingBlock();
04321 int absx, absy;
04322
04323 if (cb) cb->absolutePosition(absx, absy);
04324 else absx = absy = 0;
04325
04326 int x = b->xPos();
04327 d->m_caretViewContext->origX = absx + x;
04328 placeCaretOnLine(b, x, absx, absy);
04329 }
04330
04331 void KHTMLView::moveCaretBy(bool next, CaretMovement cmv, int count)
04332 {
04333 if (!m_part) return;
04334 Node &caretNodeRef = m_part->d->caretNode();
04335 if (caretNodeRef.isNull()) return;
04336
04337 NodeImpl *caretNode = caretNodeRef.handle();
04338
04339 long &offset = m_part->d->caretOffset();
04340
04341 ElementImpl *baseElem = determineBaseElement(caretNode);
04342 CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly;
04343 LinearDocument ld(m_part, caretNode, offset, advpol, baseElem);
04344
04345 EditableCharacterIterator it(&ld);
04346 while (!it.isEnd() && count > 0) {
04347 count--;
04348 if (cmv == CaretByCharacter) {
04349 if (next) ++it;
04350 else --it;
04351 } else if (cmv == CaretByWord) {
04352 if (next) moveItToNextWord(it);
04353 else moveItToPrevWord(it);
04354 }
04355
04356 }
04357 CaretBox *hintBox = 0;
04358 if (!it.isEnd()) {
04359 NodeImpl *node = caretNodeRef.handle();
04360 hintBox = it.caretBox();
04361
04362
04363 mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(),
04364 hintBox->isOutsideEnd(), node, offset);
04365
04366 caretNodeRef = node;
04367 #if DEBUG_CARETMODE > 2
04368 kdDebug(6200) << "set by valid node " << node << " " << (node?node->nodeName().string():QString::null) << " offset: " << offset << endl;
04369 #endif
04370 } else {
04371 offset = next ? caretNode->maxOffset() : caretNode->minOffset();
04372 #if DEBUG_CARETMODE > 0
04373 kdDebug(6200) << "set by INvalid node. offset: " << offset << endl;
04374 #endif
04375 }
04376 placeCaretOnChar(hintBox);
04377 }
04378
04379 void KHTMLView::placeCaretOnChar(CaretBox *hintBox)
04380 {
04381 caretOff();
04382 recalcAndStoreCaretPos(hintBox);
04383 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
04384 d->m_caretViewContext->width, d->m_caretViewContext->height);
04385 d->m_caretViewContext->origX = d->m_caretViewContext->x;
04386 d->scrollBarMoved = false;
04387 #if DEBUG_CARETMODE > 3
04388
04389 #endif
04390 ensureNodeHasFocus(m_part->d->caretNode().handle());
04391 caretOn();
04392 }
04393
04394 void KHTMLView::moveCaretByPage(bool next)
04395 {
04396 Node &caretNodeRef = m_part->d->caretNode();
04397 if (caretNodeRef.isNull()) return;
04398
04399 NodeImpl *caretNode = caretNodeRef.handle();
04400
04401 long offset = m_part->d->caretOffset();
04402
04403 int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
04404
04405 int mindist = clipper()->height() - offs;
04406
04407 CaretViewContext *cv = d->caretViewContext();
04408
04409
04410 ElementImpl *baseElem = determineBaseElement(caretNode);
04411 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
04412
04413 ErgonomicEditableLineIterator it(ld.current(), cv->origX);
04414
04415 moveIteratorByPage(ld, it, mindist, next);
04416
04417 int x, absx, absy;
04418 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
04419
04420 placeCaretOnLine(caretBox, x, absx, absy);
04421 }
04422
04423 void KHTMLView::moveCaretPrevWord()
04424 {
04425 moveCaretBy(false, CaretByWord, 1);
04426 }
04427
04428 void KHTMLView::moveCaretNextWord()
04429 {
04430 moveCaretBy(true, CaretByWord, 1);
04431 }
04432
04433 void KHTMLView::moveCaretPrevLine(int n)
04434 {
04435 moveCaretByLine(false, n);
04436 }
04437
04438 void KHTMLView::moveCaretNextLine(int n)
04439 {
04440 moveCaretByLine(true, n);
04441 }
04442
04443 void KHTMLView::moveCaretPrevPage()
04444 {
04445 moveCaretByPage(false);
04446 }
04447
04448 void KHTMLView::moveCaretNextPage()
04449 {
04450 moveCaretByPage(true);
04451 }
04452
04453 void KHTMLView::moveCaretToLineBegin()
04454 {
04455 moveCaretToLineBoundary(false);
04456 }
04457
04458 void KHTMLView::moveCaretToLineEnd()
04459 {
04460 moveCaretToLineBoundary(true);
04461 }
04462
04463 #endif // KHTML_NO_CARET
04464
04465 #undef DEBUG_CARETMODE