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