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,rec.left()+rec.width()/2,rec.top()+rec.height()/2);
01939 showChild(lab);
01940 }
01941 }
01942 }
01943 }
01944
01945
void KHTMLView::accessKeysTimeout()
01946 {
01947 d->accessKeysActivated=
false;
01948 d->accessKeysPreActivate =
false;
01949 m_part->
setStatusBarText(QString::null, KHTMLPart::BarOverrideText);
01950 emit hideAccessKeys();
01951 }
01952
01953
01954
bool KHTMLView::handleAccessKey(
const QKeyEvent* ev )
01955 {
01956
01957
01958
QChar c;
01959
if( ev->key() >= Key_A && ev->key() <= Key_Z )
01960 c =
'A' + ev->key() - Key_A;
01961
else if( ev->key() >= Key_0 && ev->key() <= Key_9 )
01962 c =
'0' + ev->key() - Key_0;
01963
else {
01964
01965
01966
if( ev->text().length() == 1 )
01967 c = ev->text()[ 0 ];
01968 }
01969
if( c.isNull())
01970
return false;
01971
return focusNodeWithAccessKey( c );
01972 }
01973
01974
bool KHTMLView::focusNodeWithAccessKey(
QChar c,
KHTMLView* caller )
01975 {
01976 DocumentImpl *doc = m_part->
xmlDocImpl();
01977
if( !doc )
01978
return false;
01979 ElementImpl* node = doc->findAccessKeyElement( c );
01980
if( !node ) {
01981
QPtrList<KParts::ReadOnlyPart> frames = m_part->
frames();
01982
for(
QPtrListIterator<KParts::ReadOnlyPart> it( frames );
01983 it != NULL;
01984 ++it ) {
01985
if( !(*it)->inherits(
"KHTMLPart" ))
01986
continue;
01987
KHTMLPart*
part = static_cast< KHTMLPart* >( *it );
01988
if( part->
view() && part->
view() != caller
01989 && part->
view()->
focusNodeWithAccessKey( c,
this ))
01990
return true;
01991 }
01992
01993
if (m_part->
parentPart() && m_part->
parentPart()->
view()
01994 && m_part->
parentPart()->
view() != caller )
01995
return m_part->
parentPart()->
view()->
focusNodeWithAccessKey( c,
this );
01996
return false;
01997 }
01998
01999
02000
#ifndef KHTML_NO_CARET
02001
02002
if (!m_part->
isCaretMode() && !m_part->
isEditable()
02003 && node->contentEditable()) {
02004 d->caretViewContext();
02005 moveCaretTo(node, 0L,
true);
02006 }
else {
02007 caretOff();
02008 }
02009
#endif // KHTML_NO_CARET
02010
02011
QRect r = node->getRect();
02012 ensureVisible( r.right(), r.bottom());
02013 ensureVisible( r.left(), r.top());
02014
02015
Node guard( node );
02016
if( node->isSelectable()) {
02017
if (node->id()==ID_LABEL) {
02018
02019 node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
02020
if (!node)
return true;
02021 guard = node;
02022 }
02023
02024 m_part->
xmlDocImpl()->setFocusNode(node);
02025
if( node != NULL && node->hasOneRef())
02026
return true;
02027 emit m_part->
nodeActivated(
Node(node));
02028
if( node != NULL && node->hasOneRef())
02029
return true;
02030 }
02031
02032
switch( node->id()) {
02033
case ID_A:
02034 static_cast< HTMLAnchorElementImpl* >( node )->click();
02035
break;
02036
case ID_INPUT:
02037 static_cast< HTMLInputElementImpl* >( node )->click();
02038
break;
02039
case ID_BUTTON:
02040 static_cast< HTMLButtonElementImpl* >( node )->click();
02041
break;
02042
case ID_AREA:
02043 static_cast< HTMLAreaElementImpl* >( node )->click();
02044
break;
02045
case ID_TEXTAREA:
02046
break;
02047
case ID_LEGEND:
02048
02049
break;
02050 }
02051
return true;
02052 }
02053
02054
void KHTMLView::setMediaType(
const QString &medium )
02055 {
02056 m_medium = medium;
02057 }
02058
02059
QString KHTMLView::mediaType()
const
02060
{
02061
return m_medium;
02062 }
02063
02064
void KHTMLView::setWidgetVisible(RenderWidget* w,
bool vis)
02065 {
02066
if (vis) {
02067 d->visibleWidgets.replace(w, w->widget());
02068 }
02069
else
02070 d->visibleWidgets.remove(w);
02071 }
02072
02073 void KHTMLView::print()
02074 {
02075
print(
false );
02076 }
02077
02078 void KHTMLView::print(
bool quick)
02079 {
02080
if(!m_part->
xmlDocImpl())
return;
02081 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->
xmlDocImpl()->renderer());
02082
if(!root)
return;
02083
02084
02085 KPrinter *printer =
new KPrinter(
true, QPrinter::PrinterResolution);
02086 printer->addDialogPage(
new KHTMLPrintSettings());
02087
QString docname = m_part->
xmlDocImpl()->URL().prettyURL();
02088
if ( !docname.isEmpty() )
02089 docname =
KStringHandler::csqueeze(docname, 80);
02090
if(quick || printer->setup(
this, i18n(
"Print %1").arg(docname))) {
02091 viewport()->setCursor( waitCursor );
02092
02093 printer->setFullPage(
false);
02094 printer->setCreator(
QString(
"KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
02095 printer->setDocName(docname);
02096
02097
QPainter *p =
new QPainter;
02098 p->begin( printer );
02099 khtml::setPrintPainter( p );
02100
02101 m_part->
xmlDocImpl()->setPaintDevice( printer );
02102
QString oldMediaType = mediaType();
02103 setMediaType(
"print" );
02104
02105
02106
02107 m_part->
xmlDocImpl()->setPrintStyleSheet( printer->option(
"app-khtml-printfriendly") ==
"true" ?
02108
"* { background-image: none !important;"
02109
" background-color: white !important;"
02110
" color: black !important; }"
02111
"body { margin: 0px !important; }"
02112
"html { margin: 0px !important; }" :
02113
"body { margin: 0px !important; }"
02114
"html { margin: 0px !important; }"
02115 );
02116
02117
QPaintDeviceMetrics metrics( printer );
02118
02119
02120
02121
02122
02123
02124
kdDebug(6000) <<
"printing: physical page width = " << metrics.width()
02125 <<
" height = " << metrics.height() <<
endl;
02126 root->setPrintingMode(
true);
02127 root->setWidth(metrics.width());
02128
02129 m_part->
xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
02130 m_part->
xmlDocImpl()->updateStyleSelector();
02131 root->setPrintImages( printer->option(
"app-khtml-printimages") ==
"true");
02132 root->setMinMaxKnown(
false );
02133 root->setLayouted(
false );
02134 root->layout();
02135 khtml::RenderWidget::flushWidgetResizes();
02136
02137
bool printHeader = (printer->option(
"app-khtml-printheader") ==
"true");
02138
02139
int headerHeight = 0;
02140
QFont headerFont(
"helvetica", 8);
02141
02142
QString headerLeft =
KGlobal::locale()->
formatDate(QDate::currentDate(),
true);
02143
QString headerMid = docname;
02144
QString headerRight;
02145
02146
if (printHeader)
02147 {
02148 p->setFont(headerFont);
02149 headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
02150 }
02151
02152
02153
kdDebug(6000) <<
"printing: html page width = " << root->docWidth()
02154 <<
" height = " << root->docHeight() <<
endl;
02155
kdDebug(6000) <<
"printing: margins left = " << printer->margins().width()
02156 <<
" top = " << printer->margins().height() <<
endl;
02157
kdDebug(6000) <<
"printing: paper width = " << metrics.width()
02158 <<
" height = " << metrics.height() <<
endl;
02159
02160
02161
int pageHeight = metrics.height();
02162
int pageWidth = metrics.width();
02163 p->setClipRect(0,0, pageWidth, pageHeight);
02164
02165 pageHeight -= headerHeight;
02166
02167
bool scalePage =
false;
02168
double scale = 0.0;
02169
#ifndef QT_NO_TRANSFORMATIONS
02170
if(root->docWidth() > metrics.width()) {
02171 scalePage =
true;
02172 scale = ((
double) metrics.width())/((
double) root->docWidth());
02173 pageHeight = (
int) (pageHeight/scale);
02174 pageWidth = (
int) (pageWidth/scale);
02175 headerHeight = (
int) (headerHeight/scale);
02176 }
02177
#endif
02178
kdDebug(6000) <<
"printing: scaled html width = " << pageWidth
02179 <<
" height = " << pageHeight <<
endl;
02180
02181
02182
if (printHeader)
02183 {
02184
int available_width = metrics.width() - 10 -
02185 2 * kMax(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
02186 p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
02187
if (available_width < 150)
02188 available_width = 150;
02189
int mid_width;
02190
int squeeze = 120;
02191
do {
02192 headerMid =
KStringHandler::csqueeze(docname, squeeze);
02193 mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
02194 squeeze -= 10;
02195 }
while (mid_width > available_width);
02196 }
02197
02198
int top = 0;
02199
int page = 1;
02200
while(top < root->docHeight()) {
02201
if(top > 0) printer->newPage();
02202
if (printHeader)
02203 {
02204
int dy = p->fontMetrics().lineSpacing();
02205 p->setPen(Qt::black);
02206 p->setFont(headerFont);
02207
02208 headerRight =
QString(
"#%1").arg(page);
02209
02210 p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
02211 p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
02212 p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
02213 }
02214
02215
#ifndef QT_NO_TRANSFORMATIONS
02216
if (scalePage)
02217 p->
scale(scale, scale);
02218
#endif
02219
p->
translate(0, headerHeight-top);
02220
02221 root->setTruncatedAt(top+pageHeight);
02222
02223 root->layer()->paint(p,
QRect(0, top, pageWidth, pageHeight));
02224
if (top + pageHeight >= root->docHeight())
02225
break;
02226
02227 top = root->truncatedAt();
02228 p->resetXForm();
02229 page++;
02230 }
02231
02232 p->end();
02233
delete p;
02234
02235
02236 root->setPrintingMode(
false);
02237 khtml::setPrintPainter( 0 );
02238 setMediaType( oldMediaType );
02239 m_part->
xmlDocImpl()->setPaintDevice(
this );
02240 m_part->
xmlDocImpl()->styleSelector()->computeFontSizes(m_part->
xmlDocImpl()->paintDeviceMetrics(), m_part->
zoomFactor());
02241 m_part->
xmlDocImpl()->updateStyleSelector();
02242 viewport()->unsetCursor();
02243 }
02244
delete printer;
02245 }
02246
02247
void KHTMLView::slotPaletteChanged()
02248 {
02249
if(!m_part->
xmlDocImpl())
return;
02250 DOM::DocumentImpl *document = m_part->
xmlDocImpl();
02251
if (!document->isHTMLDocument())
return;
02252 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
02253
if(!root)
return;
02254 root->style()->resetPalette();
02255 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
02256
if(!body)
return;
02257 body->setChanged(
true);
02258 body->recalcStyle( NodeImpl::Force );
02259 }
02260
02261
void KHTMLView::paint(
QPainter *p,
const QRect &rc,
int yOff,
bool *more)
02262 {
02263
if(!m_part->
xmlDocImpl())
return;
02264 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->
xmlDocImpl()->renderer());
02265
if(!root)
return;
02266
02267 m_part->
xmlDocImpl()->setPaintDevice(p->device());
02268 root->setPrintingMode(
true);
02269 root->setWidth(rc.width());
02270
02271 p->save();
02272 p->setClipRect(rc);
02273 p->
translate(rc.left(), rc.top());
02274
double scale = ((
double) rc.width()/(
double) root->docWidth());
02275
int height = (
int) ((
double) rc.height() / scale);
02276
#ifndef QT_NO_TRANSFORMATIONS
02277
p->
scale(scale, scale);
02278
#endif
02279
02280 root->layer()->paint(p,
QRect(0, yOff, root->docWidth(), height));
02281
if (more)
02282 *more = yOff + height < root->docHeight();
02283 p->restore();
02284
02285 root->setPrintingMode(
false);
02286 m_part->
xmlDocImpl()->setPaintDevice(
this );
02287 }
02288
02289
02290
void KHTMLView::useSlowRepaints()
02291 {
02292 d->useSlowRepaints =
true;
02293 setStaticBackground(
true);
02294 }
02295
02296
02297 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
02298 {
02299
#ifndef KHTML_NO_SCROLLBARS
02300
d->vmode = mode;
02301 QScrollView::setVScrollBarMode(mode);
02302
#else
02303
Q_UNUSED( mode );
02304
#endif
02305
}
02306
02307 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
02308 {
02309
#ifndef KHTML_NO_SCROLLBARS
02310
d->hmode = mode;
02311 QScrollView::setHScrollBarMode(mode);
02312
#else
02313
Q_UNUSED( mode );
02314
#endif
02315
}
02316
02317
void KHTMLView::restoreScrollBar()
02318 {
02319
int ow = visibleWidth();
02320 QScrollView::setVScrollBarMode(d->vmode);
02321
if (visibleWidth() != ow)
02322
layout();
02323 d->prevScrollbarVisible = verticalScrollBar()->isVisible();
02324 }
02325
02326
QStringList KHTMLView::formCompletionItems(
const QString &name)
const
02327
{
02328
if (!m_part->
settings()->
isFormCompletionEnabled())
02329
return QStringList();
02330
if (!d->formCompletions)
02331 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02332
return d->formCompletions->readListEntry(name);
02333 }
02334
02335
void KHTMLView::clearCompletionHistory(
const QString& name)
02336 {
02337
if (!d->formCompletions)
02338 {
02339 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02340 }
02341 d->formCompletions->writeEntry(name,
"");
02342 d->formCompletions->sync();
02343 }
02344
02345
void KHTMLView::addFormCompletionItem(
const QString &name,
const QString &value)
02346 {
02347
if (!m_part->
settings()->
isFormCompletionEnabled())
02348
return;
02349
02350
02351
02352
bool cc_number(
true);
02353
for (
unsigned int i = 0; i < value.length(); ++i)
02354 {
02355
QChar c(value[i]);
02356
if (!c.isNumber() && c !=
'-' && !c.isSpace())
02357 {
02358 cc_number =
false;
02359
break;
02360 }
02361 }
02362
if (cc_number)
02363
return;
02364
QStringList items = formCompletionItems(name);
02365
if (!items.contains(value))
02366 items.prepend(value);
02367
while ((
int)items.count() > m_part->
settings()->
maxFormCompletionItems())
02368 items.remove(items.fromLast());
02369 d->formCompletions->writeEntry(name, items);
02370 }
02371
02372
void KHTMLView::addNonPasswordStorableSite(
const QString& host)
02373 {
02374
if (!d->formCompletions) {
02375 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02376 }
02377
02378 d->formCompletions->setGroup(
"NonPasswordStorableSites");
02379
QStringList sites = d->formCompletions->readListEntry(
"Sites");
02380 sites.append(host);
02381 d->formCompletions->writeEntry(
"Sites", sites);
02382 d->formCompletions->sync();
02383 d->formCompletions->setGroup(QString::null);
02384 }
02385
02386
bool KHTMLView::nonPasswordStorableSite(
const QString& host)
const
02387
{
02388
if (!d->formCompletions) {
02389 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02390 }
02391 d->formCompletions->setGroup(
"NonPasswordStorableSites");
02392
QStringList sites = d->formCompletions->readListEntry(
"Sites");
02393 d->formCompletions->setGroup(QString::null);
02394
02395
return (sites.find(host) != sites.end());
02396 }
02397
02398
02399
bool KHTMLView::dispatchMouseEvent(
int eventId, DOM::NodeImpl *targetNode,
02400 DOM::NodeImpl *targetNodeNonShared,
bool cancelable,
02401
int detail,
QMouseEvent *_mouse,
bool setUnder,
02402
int mouseEventType)
02403 {
02404
if (d->underMouse)
02405 d->underMouse->deref();
02406 d->underMouse = targetNode;
02407
if (d->underMouse)
02408 d->underMouse->ref();
02409
02410
if (d->underMouseNonShared)
02411 d->underMouseNonShared->deref();
02412 d->underMouseNonShared = targetNodeNonShared;
02413
if (d->underMouseNonShared)
02414 d->underMouseNonShared->ref();
02415
02416
int exceptioncode = 0;
02417
int pageX = 0;
02418
int pageY = 0;
02419 viewportToContents(_mouse->x(), _mouse->y(), pageX, pageY);
02420
int clientX = pageX - contentsX();
02421
int clientY = pageY - contentsY();
02422
int screenX = _mouse->globalX();
02423
int screenY = _mouse->globalY();
02424
int button = -1;
02425
switch (_mouse->button()) {
02426
case LeftButton:
02427 button = 0;
02428
break;
02429
case MidButton:
02430 button = 1;
02431
break;
02432
case RightButton:
02433 button = 2;
02434
break;
02435
default:
02436
break;
02437 }
02438
if (d->accessKeysPreActivate && button!=-1)
02439 d->accessKeysPreActivate=
false;
02440
02441
bool ctrlKey = (_mouse->state() & ControlButton);
02442
bool altKey = (_mouse->state() & AltButton);
02443
bool shiftKey = (_mouse->state() & ShiftButton);
02444
bool metaKey = (_mouse->state() & MetaButton);
02445
02446
02447
if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) {
02448
02449
02450
02451 NodeImpl *oldUnder = 0;
02452
if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
02453 NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
02454 m_part->
xmlDocImpl()->prepareMouseEvent(
true, d->prevMouseX, d->prevMouseY, &mev );
02455 oldUnder = mev.innerNode.handle();
02456 }
02457
02458
if (oldUnder != targetNode) {
02459
02460
if (oldUnder){
02461 oldUnder->ref();
02462 MouseEventImpl *me =
new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
02463
true,
true,m_part->
xmlDocImpl()->defaultView(),
02464 0,screenX,screenY,clientX,clientY,pageX, pageY,
02465 ctrlKey,altKey,shiftKey,metaKey,
02466 button,targetNode);
02467 me->ref();
02468 oldUnder->dispatchEvent(me,exceptioncode,
true);
02469 me->deref();
02470 }
02471
02472
02473
if (targetNode) {
02474 MouseEventImpl *me =
new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
02475
true,
true,m_part->
xmlDocImpl()->defaultView(),
02476 0,screenX,screenY,clientX,clientY,pageX, pageY,
02477 ctrlKey,altKey,shiftKey,metaKey,
02478 button,oldUnder);
02479
02480 me->ref();
02481 targetNode->dispatchEvent(me,exceptioncode,
true);
02482 me->deref();
02483 }
02484
02485
if (oldUnder)
02486 oldUnder->deref();
02487 }
02488 }
02489
02490
bool swallowEvent =
false;
02491
02492
if (targetNode) {
02493
02494
bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
02495 _mouse->type() == QEvent::MouseButtonDblClick );
02496 MouseEventImpl *me =
new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
02497
true,cancelable,m_part->
xmlDocImpl()->defaultView(),
02498 detail,screenX,screenY,clientX,clientY,pageX, pageY,
02499 ctrlKey,altKey,shiftKey,metaKey,
02500 button,0, _mouse, dblclick );
02501 me->ref();
02502 targetNode->dispatchEvent(me,exceptioncode,
true);
02503
if (me->defaultHandled() || me->defaultPrevented())
02504 swallowEvent =
true;
02505 me->deref();
02506
02507
if (eventId == EventImpl::MOUSEDOWN_EVENT) {
02508
if (targetNode->isSelectable())
02509 m_part->
xmlDocImpl()->setFocusNode(targetNode);
02510
else
02511 m_part->
xmlDocImpl()->setFocusNode(0);
02512 }
02513 }
02514
02515
return swallowEvent;
02516 }
02517
02518
void KHTMLView::setIgnoreWheelEvents(
bool e )
02519 {
02520 d->ignoreWheelEvents = e;
02521 }
02522
02523
#ifndef QT_NO_WHEELEVENT
02524
02525
void KHTMLView::viewportWheelEvent(
QWheelEvent* e)
02526 {
02527
if (d->accessKeysPreActivate) d->accessKeysPreActivate=
false;
02528
02529
if ( ( e->state() & ControlButton) == ControlButton )
02530 {
02531 emit zoomView( - e->delta() );
02532 e->accept();
02533 }
02534
else if ( ( (d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
02535 || e->delta() > 0 && contentsY() <= 0
02536 || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight())
02537 && m_part->
parentPart() ) {
02538
kdDebug(6000) <<
this <<
" cz " << contentsY() <<
" ch " << contentsHeight() <<
" vh " << visibleHeight() <<
endl;
02539
if ( m_part->
parentPart()->
view() )
02540 m_part->
parentPart()->
view()->wheelEvent( e );
02541
kdDebug(6000) <<
"sent" <<
endl;
02542 e->ignore();
02543 }
02544
else if ( d->vmode == QScrollView::AlwaysOff ) {
02545 e->accept();
02546 }
02547
else {
02548 d->scrollBarMoved =
true;
02549 QScrollView::viewportWheelEvent( e );
02550
02551
QMouseEvent *tempEvent =
new QMouseEvent( QEvent::MouseMove,
QPoint(-1,-1),
QPoint(-1,-1), Qt::NoButton, e->state() );
02552 emit viewportMouseMoveEvent ( tempEvent );
02553
delete tempEvent;
02554 }
02555
02556 }
02557
#endif
02558
02559
void KHTMLView::dragEnterEvent(
QDragEnterEvent* ev )
02560 {
02561
02562
02563
02564
if ( m_part->
parentPart() )
02565 {
02566 QApplication::sendEvent(m_part->
parentPart()->
widget(), ev);
02567
return;
02568 }
02569 QScrollView::dragEnterEvent( ev );
02570 }
02571
02572
void KHTMLView::dropEvent(
QDropEvent *ev )
02573 {
02574
02575
02576
02577
if ( m_part->
parentPart() )
02578 {
02579 QApplication::sendEvent(m_part->
parentPart()->
widget(), ev);
02580
return;
02581 }
02582 QScrollView::dropEvent( ev );
02583 }
02584
02585
void KHTMLView::focusInEvent(
QFocusEvent *e )
02586 {
02587
#ifndef KHTML_NO_CARET
02588
02589
02590
if (d->m_caretViewContext &&
02591 d->m_caretViewContext->freqTimerId == -1 &&
02592 m_part->
xmlDocImpl()) {
02593 NodeImpl *caretNode = m_part->
xmlDocImpl()->focusNode();
02594
if (m_part->
isCaretMode()
02595 || m_part->
isEditable()
02596 || (caretNode && caretNode->renderer()
02597 && caretNode->renderer()->style()->userInput()
02598 == UI_ENABLED)) {
02599 d->m_caretViewContext->freqTimerId = startTimer(500);
02600 d->m_caretViewContext->visible =
true;
02601 }
02602 }
02603 showCaret();
02604
#endif // KHTML_NO_CARET
02605
QScrollView::focusInEvent( e );
02606 }
02607
02608
void KHTMLView::focusOutEvent(
QFocusEvent *e )
02609 {
02610
if(m_part) m_part->
stopAutoScroll();
02611
02612
#ifndef KHTML_NO_TYPE_AHEAD_FIND
02613
if(d->typeAheadActivated)
02614 {
02615 findTimeout();
02616 }
02617
#endif // KHTML_NO_TYPE_AHEAD_FIND
02618
02619
#ifndef KHTML_NO_CARET
02620
if (d->m_caretViewContext) {
02621
switch (d->m_caretViewContext->displayNonFocused) {
02622
case KHTMLPart::CaretInvisible:
02623 hideCaret();
02624
break;
02625
case KHTMLPart::CaretVisible: {
02626 killTimer(d->m_caretViewContext->freqTimerId);
02627 d->m_caretViewContext->freqTimerId = -1;
02628 NodeImpl *caretNode = m_part->
xmlDocImpl()->focusNode();
02629
if (!d->m_caretViewContext->visible && (m_part->
isCaretMode()
02630 || m_part->
isEditable()
02631 || (caretNode && caretNode->renderer()
02632 && caretNode->renderer()->style()->userInput()
02633 == UI_ENABLED))) {
02634 d->m_caretViewContext->visible =
true;
02635 showCaret(
true);
02636 }
02637
break;
02638 }
02639
case KHTMLPart::CaretBlink:
02640
02641
break;
02642 }
02643 }
02644
#endif // KHTML_NO_CARET
02645
QScrollView::focusOutEvent( e );
02646 }
02647
02648
void KHTMLView::slotScrollBarMoved()
02649 {
02650
if (!d->scrollingSelf)
02651 d->scrollBarMoved =
true;
02652 }
02653
02654
void KHTMLView::timerEvent (
QTimerEvent *e )
02655 {
02656
02657
if ( e->timerId() == d->scrollTimerId ) {
02658
if( d->scrollSuspended )
02659
return;
02660
switch (d->scrollDirection) {
02661
case KHTMLViewPrivate::ScrollDown:
02662
if (contentsY() + visibleHeight () >= contentsHeight())
02663 d->newScrollTimer(
this, 0);
02664
else
02665 scrollBy( 0, d->scrollBy );
02666
break;
02667
case KHTMLViewPrivate::ScrollUp:
02668
if (contentsY() <= 0)
02669 d->newScrollTimer(
this, 0);
02670
else
02671 scrollBy( 0, -d->scrollBy );
02672
break;
02673
case KHTMLViewPrivate::ScrollRight:
02674
if (contentsX() + visibleWidth () >= contentsWidth())
02675 d->newScrollTimer(
this, 0);
02676
else
02677 scrollBy( d->scrollBy, 0 );
02678
break;
02679
case KHTMLViewPrivate::ScrollLeft:
02680
if (contentsX() <= 0)
02681 d->newScrollTimer(
this, 0);
02682
else
02683 scrollBy( -d->scrollBy, 0 );
02684
break;
02685 }
02686
return;
02687 }
02688
else if ( e->timerId() == d->layoutTimerId ) {
02689 d->firstRelayout =
false;
02690 d->dirtyLayout =
true;
02691
layout();
02692 }
02693
#ifndef KHTML_NO_CARET
02694
else if (d->m_caretViewContext
02695 && e->timerId() == d->m_caretViewContext->freqTimerId) {
02696 d->m_caretViewContext->visible = !d->m_caretViewContext->visible;
02697
if (d->m_caretViewContext->displayed) {
02698 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02699 d->m_caretViewContext->width,
02700 d->m_caretViewContext->height);
02701 }
02702
02703
02704
return;
02705 }
02706
#endif
02707
02708
if( m_part->
xmlDocImpl() ) {
02709 DOM::DocumentImpl *document = m_part->
xmlDocImpl();
02710 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
02711
02712
if ( root && !root->layouted() ) {
02713 killTimer(d->repaintTimerId);
02714 d->repaintTimerId = 0;
02715 scheduleRelayout();
02716
return;
02717 }
02718 }
02719
02720 setStaticBackground(d->useSlowRepaints);
02721
02722
02723 killTimer(d->repaintTimerId);
02724 d->repaintTimerId = 0;
02725
02726
QRegion updateRegion;
02727
QMemArray<QRect> rects = d->updateRegion.rects();
02728
02729 d->updateRegion =
QRegion();
02730
02731
if ( rects.size() )
02732 updateRegion = rects[0];
02733
02734
for (
unsigned i = 1; i < rects.size(); ++i ) {
02735
QRect obR = updateRegion.boundingRect();
02736
QRegion newRegion = updateRegion.unite(rects[i]);
02737
if (2*newRegion.boundingRect().height() > 3*obR.height() )
02738 {
02739 repaintContents( obR );
02740 updateRegion = rects[i];
02741 }
02742
else
02743 updateRegion = newRegion;
02744 }
02745
02746
if ( !updateRegion.isNull() )
02747 repaintContents( updateRegion.boundingRect() );
02748
02749
if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
02750
QWidget* w;
02751 d->dirtyLayout =
false;
02752
02753
QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
02754
QPtrList<RenderWidget> toRemove;
02755
for (
QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
02756
int xp = 0, yp = 0;
02757 w = it.current();
02758 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
02759
if (!rw->absolutePosition(xp, yp) ||
02760 !visibleRect.intersects(
QRect(xp, yp, w->width(), w->height())))
02761 toRemove.append(rw);
02762 }
02763
for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
02764
if ( (w = d->visibleWidgets.take(r) ) )
02765 addChild(w, 0, -500000);
02766 }
02767
if (d->accessKeysActivated) emit repaintAccessKeys();
02768 }
02769
02770
void KHTMLView::scheduleRelayout(khtml::RenderObject * )
02771 {
02772
if (!d->layoutSchedulingEnabled || d->layoutTimerId)
02773
return;
02774
02775 d->layoutTimerId = startTimer( m_part->
xmlDocImpl() && m_part->
xmlDocImpl()->parsing()
02776 ? 1000 : 0 );
02777 }
02778
02779
void KHTMLView::unscheduleRelayout()
02780 {
02781
if (!d->layoutTimerId)
02782
return;
02783
02784 killTimer(d->layoutTimerId);
02785 d->layoutTimerId = 0;
02786 }
02787
02788
void KHTMLView::unscheduleRepaint()
02789 {
02790
if (!d->repaintTimerId)
02791
return;
02792
02793 killTimer(d->repaintTimerId);
02794 d->repaintTimerId = 0;
02795 }
02796
02797
void KHTMLView::scheduleRepaint(
int x,
int y,
int w,
int h)
02798 {
02799
bool parsing = !m_part->
xmlDocImpl() || m_part->
xmlDocImpl()->parsing();
02800
02801
02802
02803
02804
int time = parsing ? 300 : ( !d->complete ? 100 : 20 );
02805
02806
#ifdef DEBUG_FLICKER
02807
QPainter p;
02808 p.begin( viewport() );
02809
02810
int vx, vy;
02811 contentsToViewport( x, y, vx, vy );
02812 p.fillRect( vx, vy, w, h, Qt::red );
02813 p.end();
02814
#endif
02815
02816 d->updateRegion = d->updateRegion.unite(
QRect(x,y,w,h));
02817
02818
if ( !d->repaintTimerId )
02819 d->repaintTimerId = startTimer( time );
02820
02821
02822 }
02823
02824
void KHTMLView::complete()
02825 {
02826
02827
02828 d->complete =
true;
02829
02830
02831
if (d->layoutTimerId)
02832 {
02833
02834
02835 killTimer(d->layoutTimerId);
02836 d->layoutTimerId = startTimer( 0 );
02837 }
02838
02839
02840
if (d->repaintTimerId)
02841 {
02842
02843
02844 killTimer(d->repaintTimerId);
02845 d->repaintTimerId = startTimer( 20 );
02846 }
02847 }
02848
02849
#ifndef KHTML_NO_CARET
02850
02851
02852
02853
02854
#include "khtml_caret.cpp"
02855
02856
void KHTMLView::initCaret(
bool keepSelection)
02857 {
02858
#if DEBUG_CARETMODE > 0
02859
kdDebug(6200) <<
"begin initCaret" <<
endl;
02860
#endif
02861
02862
if (m_part->
xmlDocImpl()) {
02863
#if 0
02864
ElementImpl *listitem = m_part->
xmlDocImpl()->getElementById(
"__test_element__");
02865
if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
02866
#endif
02867
d->caretViewContext();
02868
bool cmoved = d->m_caretViewContext->caretMoved;
02869
if (m_part->
d->caretNode().isNull()) {
02870
02871 m_part->
d->caretNode() = m_part->
document();
02872 m_part->
d->caretOffset() = 0L;
02873
02874
02875
02876
if (!m_part->
d->caretNode().handle()->renderer())
return;
02877 }
02878
02879
02880
02881 moveCaretTo(m_part->
d->caretNode().handle(), m_part->
d->caretOffset(), !keepSelection);
02882
02883
02884 d->m_caretViewContext->caretMoved = cmoved;
02885 }
02886
#if DEBUG_CARETMODE > 0
02887
kdDebug(6200) <<
"end initCaret" <<
endl;
02888
#endif
02889
}
02890
02891
bool KHTMLView::caretOverrides()
const
02892
{
02893
bool cm = m_part->
isCaretMode();
02894
bool dm = m_part->
isEditable();
02895
return cm && !dm ?
false
02896 : (dm || m_part->
d->caretNode().handle()->contentEditable())
02897 && d->editorContext()->override;
02898 }
02899
02900
void KHTMLView::ensureNodeHasFocus(NodeImpl *node)
02901 {
02902
if (m_part->
isCaretMode() || m_part->
isEditable())
return;
02903
if (node->focused())
return;
02904
02905
02906 NodeImpl *firstAncestor = 0;
02907
while (node) {
02908
if (node->renderer()
02909 && node->renderer()->style()->userInput() != UI_ENABLED)
02910
break;
02911 firstAncestor = node;
02912 node = node->parentNode();
02913 }
02914
02915
if (!node) firstAncestor = 0;
02916
02917 DocumentImpl *doc = m_part->
xmlDocImpl();
02918
02919
if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer()
02920 && doc->focusNode()->renderer()->isWidget())
02921
return;
02922
02923
02924
#if DEBUG_CARETMODE > 1
02925
kdDebug(6200) <<
k_funcinfo <<
"firstAncestor " << firstAncestor <<
": "
02926 << (firstAncestor ? firstAncestor->nodeName().string() :
QString::null) <<
endl;
02927
#endif
02928
doc->setFocusNode(firstAncestor);
02929 emit m_part->
nodeActivated(
Node(firstAncestor));
02930 }
02931
02932
void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox)
02933 {
02934
if (!m_part || m_part->
d->caretNode().isNull())
return;
02935 d->caretViewContext();
02936 NodeImpl *caretNode = m_part->
d->caretNode().handle();
02937
#if DEBUG_CARETMODE > 0
02938
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;
02939
#endif
02940
caretNode->getCaret(m_part->
d->caretOffset(), caretOverrides(),
02941 d->m_caretViewContext->x, d->m_caretViewContext->y,
02942 d->m_caretViewContext->width,
02943 d->m_caretViewContext->height);
02944
02945
if (hintBox && d->m_caretViewContext->x == -1) {
02946
#if DEBUG_CARETMODE > 1
02947
kdDebug(6200) <<
"using hint inline box coordinates" <<
endl;
02948
#endif
02949
RenderObject *r = caretNode->renderer();
02950
const QFontMetrics &fm = r->style()->fontMetrics();
02951
int absx, absy;
02952 r->containingBlock()->absolutePosition(absx, absy,
02953
false);
02954 d->m_caretViewContext->x = absx + hintBox->xPos();
02955 d->m_caretViewContext->y = absy + hintBox->yPos();
02956
02957 d->m_caretViewContext->width = 1;
02958
02959
02960 d->m_caretViewContext->height = fm.height();
02961 }
02962
02963
#if DEBUG_CARETMODE > 4
02964
02965
#endif
02966
#if DEBUG_CARETMODE > 0
02967
kdDebug(6200) <<
"caret: ofs="<<m_part->
d->caretOffset()<<
" "
02968 <<
" x="<<d->m_caretViewContext->x<<
" y="<<d->m_caretViewContext->y
02969 <<
" h="<<d->m_caretViewContext->height<<
endl;
02970
#endif
02971
}
02972
02973
void KHTMLView::caretOn()
02974 {
02975
if (d->m_caretViewContext) {
02976 killTimer(d->m_caretViewContext->freqTimerId);
02977
02978
if (hasFocus() || d->m_caretViewContext->displayNonFocused
02979 == KHTMLPart::CaretBlink) {
02980 d->m_caretViewContext->freqTimerId = startTimer(500);
02981 }
else {
02982 d->m_caretViewContext->freqTimerId = -1;
02983 }
02984
02985 d->m_caretViewContext->visible =
true;
02986
if ((d->m_caretViewContext->displayed = (hasFocus()
02987 || d->m_caretViewContext->displayNonFocused
02988 != KHTMLPart::CaretInvisible))) {
02989 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02990 d->m_caretViewContext->width,
02991 d->m_caretViewContext->height);
02992 }
02993
02994 }
02995 }
02996
02997
void KHTMLView::caretOff()
02998 {
02999
if (d->m_caretViewContext) {
03000 killTimer(d->m_caretViewContext->freqTimerId);
03001 d->m_caretViewContext->freqTimerId = -1;
03002 d->m_caretViewContext->displayed =
false;
03003
if (d->m_caretViewContext->visible) {
03004 d->m_caretViewContext->visible =
false;
03005 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03006 d->m_caretViewContext->width,
03007 d->m_caretViewContext->height);
03008 }
03009
03010 }
03011 }
03012
03013
void KHTMLView::showCaret(
bool forceRepaint)
03014 {
03015
if (d->m_caretViewContext) {
03016 d->m_caretViewContext->displayed =
true;
03017
if (d->m_caretViewContext->visible) {
03018
if (!forceRepaint) {
03019 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03020 d->m_caretViewContext->width,
03021 d->m_caretViewContext->height);
03022 }
else {
03023 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03024 d->m_caretViewContext->width,
03025 d->m_caretViewContext->height);
03026 }
03027 }
03028
03029 }
03030 }
03031
03032
bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode,
long startOffset,
03033 NodeImpl *endNode,
long endOffset)
03034 {
03035 m_part->
d->m_selectionStart = m_part->
d->m_selectionEnd = m_part->
d->caretNode();
03036 m_part->
d->m_startOffset = m_part->
d->m_endOffset = m_part->
d->caretOffset();
03037 m_part->
d->m_extendAtEnd =
true;
03038
03039
bool folded = startNode != endNode || startOffset != endOffset;
03040
03041
03042
if (folded) {
03043 m_part->
xmlDocImpl()->clearSelection();
03044 }
03045
03046
return folded;
03047 }
03048
03049
void KHTMLView::hideCaret()
03050 {
03051
if (d->m_caretViewContext) {
03052
if (d->m_caretViewContext->visible) {
03053
03054 d->m_caretViewContext->visible =
false;
03055
03056
03057 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03058 d->m_caretViewContext->width,
03059 d->m_caretViewContext->height);
03060 d->m_caretViewContext->visible =
true;
03061 }
03062 d->m_caretViewContext->displayed =
false;
03063
03064 }
03065 }
03066
03067
int KHTMLView::caretDisplayPolicyNonFocused()
const
03068
{
03069
if (d->m_caretViewContext)
03070
return d->m_caretViewContext->displayNonFocused;
03071
else
03072
return KHTMLPart::CaretInvisible;
03073 }
03074
03075
void KHTMLView::setCaretDisplayPolicyNonFocused(
int policy)
03076 {
03077 d->caretViewContext();
03078
03079 d->m_caretViewContext->displayNonFocused = (
KHTMLPart::CaretDisplayPolicy)policy;
03080
03081
03082
if (!hasFocus()) {
03083
switch (d->m_caretViewContext->displayNonFocused) {
03084
case KHTMLPart::CaretInvisible:
03085 hideCaret();
03086
break;
03087
case KHTMLPart::CaretBlink:
03088
if (d->m_caretViewContext->freqTimerId != -1)
break;
03089 d->m_caretViewContext->freqTimerId = startTimer(500);
03090
03091
case KHTMLPart::CaretVisible:
03092 d->m_caretViewContext->displayed =
true;
03093 showCaret();
03094
break;
03095 }
03096 }
03097 }
03098
03099
bool KHTMLView::placeCaret(CaretBox *hintBox)
03100 {
03101
CaretViewContext *cv = d->caretViewContext();
03102 caretOff();
03103 NodeImpl *caretNode = m_part->
d->caretNode().handle();
03104
03105
if (!caretNode || !caretNode->renderer())
return false;
03106 ensureNodeHasFocus(caretNode);
03107
if (m_part->
isCaretMode() || m_part->
isEditable()
03108 || caretNode->renderer()->style()->userInput() == UI_ENABLED) {
03109 recalcAndStoreCaretPos(hintBox);
03110
03111 cv->
origX = cv->
x;
03112
03113 caretOn();
03114
return true;
03115 }
03116
return false;
03117 }
03118
03119
void KHTMLView::ensureCaretVisible()
03120 {
03121
CaretViewContext *cv = d->m_caretViewContext;
03122
if (!cv)
return;
03123 ensureVisible(cv->
x, cv->
y, cv->
width, cv->
height);
03124 d->scrollBarMoved =
false;
03125 }
03126
03127
bool KHTMLView::extendSelection(NodeImpl *oldStartSel,
long oldStartOfs,
03128 NodeImpl *oldEndSel,
long oldEndOfs)
03129 {
03130
bool changed =
false;
03131
if (m_part->
d->m_selectionStart == m_part->
d->m_selectionEnd
03132 && m_part->
d->m_startOffset == m_part->
d->m_endOffset) {
03133 changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03134 m_part->
d->m_extendAtEnd =
true;
03135 }
else do {
03136 changed = m_part->
d->m_selectionStart.handle() != oldStartSel
03137 || m_part->
d->m_startOffset != oldStartOfs
03138 || m_part->
d->m_selectionEnd.handle() != oldEndSel
03139 || m_part->
d->m_endOffset != oldEndOfs;
03140
if (!changed)
break;
03141
03142
03143 NodeImpl *startNode;
03144
long startOffset;
03145
if (m_part->
d->m_extendAtEnd) {
03146 startNode = m_part->
d->m_selectionStart.handle();
03147 startOffset = m_part->
d->m_startOffset;
03148 }
else {
03149 startNode = m_part->
d->m_selectionEnd.handle();
03150 startOffset = m_part->
d->m_endOffset;
03151 m_part->
d->m_selectionEnd = m_part->
d->m_selectionStart;
03152 m_part->
d->m_endOffset = m_part->
d->m_startOffset;
03153 m_part->
d->m_extendAtEnd =
true;
03154 }
03155
03156
bool swapNeeded =
false;
03157
if (!m_part->
d->m_selectionEnd.isNull() && startNode) {
03158 swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset,
03159 m_part->
d->m_selectionEnd.handle(),
03160 m_part->
d->m_endOffset) >= 0;
03161 }
03162
03163 m_part->
d->m_selectionStart = startNode;
03164 m_part->
d->m_startOffset = startOffset;
03165
03166
if (swapNeeded) {
03167 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionEnd.handle(),
03168 m_part->
d->m_endOffset, m_part->
d->m_selectionStart.handle(),
03169 m_part->
d->m_startOffset);
03170 }
else {
03171 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionStart.handle(),
03172 m_part->
d->m_startOffset, m_part->
d->m_selectionEnd.handle(),
03173 m_part->
d->m_endOffset);
03174 }
03175 }
while(
false);
03176
return changed;
03177 }
03178
03179
void KHTMLView::updateSelection(NodeImpl *oldStartSel,
long oldStartOfs,
03180 NodeImpl *oldEndSel,
long oldEndOfs)
03181 {
03182
if (m_part->
d->m_selectionStart == m_part->
d->m_selectionEnd
03183 && m_part->
d->m_startOffset == m_part->
d->m_endOffset) {
03184
if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) {
03185 m_part->
emitSelectionChanged();
03186 }
03187 m_part->
d->m_extendAtEnd =
true;
03188 }
else {
03189
03190
if (!m_part->
d->m_selectionEnd.isNull() && !m_part->
d->m_selectionEnd.isNull()) {
03191
bool swapNeeded = RangeImpl::compareBoundaryPoints(
03192 m_part->
d->m_selectionStart.handle(), m_part->
d->m_startOffset,
03193 m_part->
d->m_selectionEnd.handle(), m_part->
d->m_endOffset) >= 0;
03194
if (swapNeeded) {
03195
DOM::Node tmpNode = m_part->
d->m_selectionStart;
03196
long tmpOffset = m_part->
d->m_startOffset;
03197 m_part->
d->m_selectionStart = m_part->
d->m_selectionEnd;
03198 m_part->
d->m_startOffset = m_part->
d->m_endOffset;
03199 m_part->
d->m_selectionEnd = tmpNode;
03200 m_part->
d->m_endOffset = tmpOffset;
03201 m_part->
d->m_startBeforeEnd =
true;
03202 m_part->
d->m_extendAtEnd = !m_part->
d->m_extendAtEnd;
03203 }
03204 }
03205
03206 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionStart.handle(),
03207 m_part->
d->m_startOffset, m_part->
d->m_selectionEnd.handle(),
03208 m_part->
d->m_endOffset);
03209 m_part->
emitSelectionChanged();
03210 }
03211 }
03212
03213
void KHTMLView::caretKeyPressEvent(
QKeyEvent *_ke)
03214 {
03215 NodeImpl *oldStartSel = m_part->
d->m_selectionStart.handle();
03216
long oldStartOfs = m_part->
d->m_startOffset;
03217 NodeImpl *oldEndSel = m_part->
d->m_selectionEnd.handle();
03218
long oldEndOfs = m_part->
d->m_endOffset;
03219
03220 NodeImpl *oldCaretNode = m_part->
d->caretNode().handle();
03221
long oldOffset = m_part->
d->caretOffset();
03222
03223
bool ctrl = _ke->state() & ControlButton;
03224
03225
03226
switch(_ke->key()) {
03227
case Key_Space:
03228
break;
03229
03230
case Key_Down:
03231 moveCaretNextLine(1);
03232
break;
03233
03234
case Key_Up:
03235 moveCaretPrevLine(1);
03236
break;
03237
03238
case Key_Left:
03239 moveCaretBy(
false, ctrl ? CaretByWord : CaretByCharacter, 1);
03240
break;
03241
03242
case Key_Right:
03243 moveCaretBy(
true, ctrl ? CaretByWord : CaretByCharacter, 1);
03244
break;
03245
03246
case Key_Next:
03247 moveCaretNextPage();
03248
break;
03249
03250
case Key_Prior:
03251 moveCaretPrevPage();
03252
break;
03253
03254
case Key_Home:
03255
if (ctrl)
03256 moveCaretToDocumentBoundary(
false);
03257
else
03258 moveCaretToLineBegin();
03259
break;
03260
03261
case Key_End:
03262
if (ctrl)
03263 moveCaretToDocumentBoundary(
true);
03264
else
03265 moveCaretToLineEnd();
03266
break;
03267
03268 }
03269
03270
if ((m_part->
d->caretNode().handle() != oldCaretNode
03271 || m_part->
d->caretOffset() != oldOffset)
03272
03273 && !m_part->
d->caretNode().isNull()) {
03274
03275 d->m_caretViewContext->caretMoved =
true;
03276
03277
if (_ke->state() & ShiftButton) {
03278 updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03279 }
else {
03280
if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs))
03281 m_part->
emitSelectionChanged();
03282 }
03283
03284 m_part->
emitCaretPositionChanged(m_part->
d->caretNode(), m_part->
d->caretOffset());
03285 }
03286
03287 _ke->accept();
03288 }
03289
03290
bool KHTMLView::moveCaretTo(NodeImpl *node,
long offset,
bool clearSel)
03291 {
03292
if (!node)
return false;
03293 ElementImpl *baseElem = determineBaseElement(node);
03294 RenderFlow *base = static_cast<RenderFlow *>(baseElem ? baseElem->renderer() : 0);
03295
if (!node)
return false;
03296
03297
03298
03299
03300 CaretBoxLineDeleter cblDeleter;
03301
03302
long r_ofs;
03303 CaretBoxIterator cbit;
03304 CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit);
03305
if(!cbl) {
03306
kdWarning() <<
"KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL" <<
endl;
03307
return false;
03308 }
03309
03310
#if DEBUG_CARETMODE > 3
03311
if (cbl)
kdDebug(6200) << cbl->information() <<
endl;
03312
#endif
03313
CaretBox *box = *cbit;
03314
if (cbit != cbl->end() && box->object() != node->renderer()) {
03315
if (box->object()->element()) {
03316 mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(),
03317 box->isOutsideEnd(), node, offset);
03318
03319
#if DEBUG_CARETMODE > 1
03320
kdDebug(6200) <<
"set new node " << node->nodeName().string() <<
"@" << node <<
endl;
03321
#endif
03322
}
else {
03323
03324 box = 0;
03325
kdError(6200) <<
"Box contains no node! Crash imminent" <<
endl;
03326 }
03327 }
03328
03329 NodeImpl *oldStartSel = m_part->
d->m_selectionStart.handle();
03330
long oldStartOfs = m_part->
d->m_startOffset;
03331 NodeImpl *oldEndSel = m_part->
d->m_selectionEnd.handle();
03332
long oldEndOfs = m_part->
d->m_endOffset;
03333
03334
03335
bool posChanged = m_part->
d->caretNode().handle() != node
03336 || m_part->
d->caretOffset() != offset;
03337
bool selChanged =
false;
03338
03339 m_part->
d->caretNode() = node;
03340 m_part->
d->caretOffset() = offset;
03341
if (clearSel || !oldStartSel || !oldEndSel) {
03342 selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03343 }
else {
03344
03345
03346 selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03347
03348
03349 }
03350
03351 d->caretViewContext()->caretMoved =
true;
03352
03353
bool visible_caret = placeCaret(box);
03354
03355
03356
03357
03358
if (posChanged) {
03359 m_part->
emitCaretPositionChanged(visible_caret ? node : 0, offset);
03360 }
03361
03362
return selChanged;
03363 }
03364
03365
void KHTMLView::moveCaretByLine(
bool next,
int count)
03366 {
03367
Node &caretNodeRef = m_part->
d->caretNode();
03368
if (caretNodeRef.
isNull())
return;
03369
03370 NodeImpl *caretNode = caretNodeRef.
handle();
03371
03372
long offset = m_part->
d->caretOffset();
03373
03374
CaretViewContext *cv = d->caretViewContext();
03375
03376 ElementImpl *baseElem = determineBaseElement(caretNode);
03377 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03378
03379 ErgonomicEditableLineIterator it(ld.current(), cv->
origX);
03380
03381
03382
while (count > 0 && it != ld.end() && it != ld.preBegin()) {
03383 count--;
03384
if (
next) ++it;
else --it;
03385 }
03386
03387
03388
if (it == ld.end() || it == ld.preBegin())
return;
03389
03390
int x, absx, absy;
03391 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
03392
03393 placeCaretOnLine(caretBox, x, absx, absy);
03394 }
03395
03396
void KHTMLView::placeCaretOnLine(CaretBox *caretBox,
int x,
int absx,
int absy)
03397 {
03398
03399
if (!caretBox)
return;
03400
03401 RenderObject *caretRender = caretBox->object();
03402
03403
#if DEBUG_CARETMODE > 0
03404
kdDebug(6200) <<
"got valid caretBox " << caretBox <<
endl;
03405
kdDebug(6200) <<
"xPos: " << caretBox->xPos() <<
" yPos: " << caretBox->yPos()
03406 <<
" width: " << caretBox->width() <<
" height: " << caretBox->height() <<
endl;
03407 InlineTextBox *tb = static_cast<InlineTextBox *>(caretBox->inlineBox());
03408
if (caretBox->isInlineTextBox()) {
kdDebug(6200) <<
"contains \"" <<
QString(static_cast<RenderText *>(tb->object())->str->s + tb->m_start, tb->m_len) <<
"\"" <<
endl;}
03409
#endif
03410
03411
int caretHeight = caretBox->height();
03412
bool isText = caretBox->isInlineTextBox();
03413
int yOfs = 0;
03414
if (isText) {
03415
03416 RenderText *t = static_cast<RenderText *>(caretRender);
03417
const QFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine);
03418 caretHeight = fm.height();
03419 yOfs = caretBox->inlineBox()->baseline() - fm.ascent();
03420 }
03421
03422 caretOff();
03423
03424
03425 NodeImpl *caretNode;
03426
long &offset = m_part->
d->caretOffset();
03427 mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(),
03428 caretBox->isOutsideEnd(), caretNode, offset);
03429
03430
03431 d->m_caretViewContext->y = caretBox->yPos() + yOfs;
03432 d->m_caretViewContext->height = caretHeight;
03433 d->m_caretViewContext->width = 1;
03434
03435
int xPos = caretBox->xPos();
03436
int caretBoxWidth = caretBox->width();
03437 d->m_caretViewContext->x = xPos;
03438
03439
if (!caretBox->isOutside()) {
03440
03441
long r_ofs = 0;
03442
if (x <= xPos) {
03443 r_ofs = caretBox->minOffset();
03444
03445 }
else if (x > xPos && x <= xPos + caretBoxWidth) {
03446
if (isText) {
03447 r_ofs = static_cast<InlineTextBox *>(caretBox->inlineBox())
03448 ->offsetForPoint(x, d->m_caretViewContext->x);
03449
#if DEBUG_CARETMODE > 2
03450
kdDebug(6200) <<
"deviation from origX " << d->m_caretViewContext->x - x <<
endl;
03451
#endif
03452
#if 0
03453
}
else {
03454
if (xPos + caretBoxWidth - x < x - xPos) {
03455 d->m_caretViewContext->x = xPos + caretBoxWidth;
03456 r_ofs = caretNode ? caretNode->maxOffset() : 1;
03457 }
else {
03458 d->m_caretViewContext->x = xPos;
03459 r_ofs = caretNode ? caretNode->minOffset() : 0;
03460 }
03461
#endif
03462
}
03463 }
else {
03464 d->m_caretViewContext->x = xPos + caretBoxWidth;
03465 r_ofs = caretBox->maxOffset();
03466 }
03467 offset = r_ofs;
03468 }
03469
#if DEBUG_CARETMODE > 0
03470
kdDebug(6200) <<
"new offset: " << offset <<
endl;
03471
#endif
03472
03473 m_part->
d->caretNode() = caretNode;
03474 m_part->
d->caretOffset() = offset;
03475
03476 d->m_caretViewContext->x += absx;
03477 d->m_caretViewContext->y += absy;
03478
03479
#if DEBUG_CARETMODE > 1
03480
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;
03481
#endif
03482
03483 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03484 d->m_caretViewContext->width, d->m_caretViewContext->height);
03485 d->scrollBarMoved =
false;
03486
03487 ensureNodeHasFocus(caretNode);
03488 caretOn();
03489 }
03490
03491
void KHTMLView::moveCaretToLineBoundary(
bool end)
03492 {
03493
Node &caretNodeRef = m_part->
d->caretNode();
03494
if (caretNodeRef.
isNull())
return;
03495
03496 NodeImpl *caretNode = caretNodeRef.
handle();
03497
03498
long offset = m_part->
d->caretOffset();
03499
03500 ElementImpl *baseElem = determineBaseElement(caretNode);
03501 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03502
03503 EditableLineIterator it = ld.current();
03504
if (it == ld.end())
return;
03505
03506 EditableCaretBoxIterator fbit(it, end);
03507 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
03508 CaretBox *b = *fbit;
03509
03510 RenderObject *cb = b->containingBlock();
03511
int absx, absy;
03512
03513
if (cb) cb->absolutePosition(absx,absy);
03514
else absx = absy = 0;
03515
03516
int x = b->xPos() + (
end && !b->isOutside() ? b->width() : 0);
03517 d->m_caretViewContext->origX = absx + x;
03518 placeCaretOnLine(b, x, absx, absy);
03519 }
03520
03521
void KHTMLView::moveCaretToDocumentBoundary(
bool end)
03522 {
03523
Node &caretNodeRef = m_part->
d->caretNode();
03524
if (caretNodeRef.
isNull())
return;
03525
03526 NodeImpl *caretNode = caretNodeRef.
handle();
03527
03528
long offset = m_part->
d->caretOffset();
03529
03530 ElementImpl *baseElem = determineBaseElement(caretNode);
03531 LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem);
03532
03533 EditableLineIterator it(end ? ld.preEnd() : ld.begin(),
end);
03534
if (it == ld.end() || it == ld.preBegin())
return;
03535
03536 EditableCaretBoxIterator fbit = it;
03537 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
03538 CaretBox *b = *fbit;
03539
03540 RenderObject *cb = (*it)->containingBlock();
03541
int absx, absy;
03542
03543
if (cb) cb->absolutePosition(absx, absy);
03544
else absx = absy = 0;
03545
03546
int x = b->xPos();
03547 d->m_caretViewContext->origX = absx + x;
03548 placeCaretOnLine(b, x, absx, absy);
03549 }
03550
03551
void KHTMLView::moveCaretBy(
bool next, CaretMovement cmv,
int count)
03552 {
03553
if (!m_part)
return;
03554
Node &caretNodeRef = m_part->
d->caretNode();
03555
if (caretNodeRef.
isNull())
return;
03556
03557 NodeImpl *caretNode = caretNodeRef.
handle();
03558
03559
long &offset = m_part->
d->caretOffset();
03560
03561 ElementImpl *baseElem = determineBaseElement(caretNode);
03562 CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly;
03563 LinearDocument ld(m_part, caretNode, offset, advpol, baseElem);
03564
03565 EditableCharacterIterator it(&ld);
03566
while (!it.isEnd() && count > 0) {
03567 count--;
03568
if (cmv == CaretByCharacter) {
03569
if (
next) ++it;
03570
else --it;
03571 }
else if (cmv == CaretByWord) {
03572
if (
next) moveItToNextWord(it);
03573
else moveItToPrevWord(it);
03574 }
03575
03576 }
03577 CaretBox *hintBox = 0;
03578
if (!it.isEnd()) {
03579 NodeImpl *node = caretNodeRef.
handle();
03580 hintBox = it.caretBox();
03581
03582
03583 mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(),
03584 hintBox->isOutsideEnd(), node, offset);
03585
03586 caretNodeRef = node;
03587
#if DEBUG_CARETMODE > 2
03588
kdDebug(6200) <<
"set by valid node " << node <<
" " << (node?node->nodeName().string():
QString::null) <<
" offset: " << offset <<
endl;
03589
#endif
03590
}
else {
03591 offset =
next ? caretNode->maxOffset() : caretNode->minOffset();
03592
#if DEBUG_CARETMODE > 0
03593
kdDebug(6200) <<
"set by INvalid node. offset: " << offset <<
endl;
03594
#endif
03595
}
03596 placeCaretOnChar(hintBox);
03597 }
03598
03599
void KHTMLView::placeCaretOnChar(CaretBox *hintBox)
03600 {
03601 caretOff();
03602 recalcAndStoreCaretPos(hintBox);
03603 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03604 d->m_caretViewContext->width, d->m_caretViewContext->height);
03605 d->m_caretViewContext->origX = d->m_caretViewContext->x;
03606 d->scrollBarMoved =
false;
03607
#if DEBUG_CARETMODE > 3
03608
03609
#endif
03610
ensureNodeHasFocus(m_part->
d->caretNode().handle());
03611 caretOn();
03612 }
03613
03614
void KHTMLView::moveCaretByPage(
bool next)
03615 {
03616
Node &caretNodeRef = m_part->
d->caretNode();
03617
03618 NodeImpl *caretNode = caretNodeRef.
handle();
03619
03620
long offset = m_part->
d->caretOffset();
03621
03622
int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
03623
03624
int mindist = clipper()->height() - offs;
03625
03626
CaretViewContext *cv = d->caretViewContext();
03627
03628
03629 ElementImpl *baseElem = determineBaseElement(caretNode);
03630 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03631
03632 ErgonomicEditableLineIterator it(ld.current(), cv->
origX);
03633
03634 moveIteratorByPage(ld, it, mindist, next);
03635
03636
int x, absx, absy;
03637 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
03638
03639 placeCaretOnLine(caretBox, x, absx, absy);
03640 }
03641
03642
void KHTMLView::moveCaretPrevWord()
03643 {
03644 moveCaretBy(
false, CaretByWord, 1);
03645 }
03646
03647
void KHTMLView::moveCaretNextWord()
03648 {
03649 moveCaretBy(
true, CaretByWord, 1);
03650 }
03651
03652
void KHTMLView::moveCaretPrevLine(
int n)
03653 {
03654 moveCaretByLine(
false, n);
03655 }
03656
03657
void KHTMLView::moveCaretNextLine(
int n)
03658 {
03659 moveCaretByLine(
true, n);
03660 }
03661
03662
void KHTMLView::moveCaretPrevPage()
03663 {
03664 moveCaretByPage(
false);
03665 }
03666
03667
void KHTMLView::moveCaretNextPage()
03668 {
03669 moveCaretByPage(
true);
03670 }
03671
03672
void KHTMLView::moveCaretToLineBegin()
03673 {
03674 moveCaretToLineBoundary(
false);
03675 }
03676
03677
void KHTMLView::moveCaretToLineEnd()
03678 {
03679 moveCaretToLineBoundary(
true);
03680 }
03681
03682
#endif // KHTML_NO_CARET
03683
03684
#undef DEBUG_CARETMODE