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