diff options
Diffstat (limited to 'khtml/khtmlview.cpp')
-rw-r--r-- | khtml/khtmlview.cpp | 4623 |
1 files changed, 0 insertions, 4623 deletions
diff --git a/khtml/khtmlview.cpp b/khtml/khtmlview.cpp deleted file mode 100644 index 4a5c7cf2d..000000000 --- a/khtml/khtmlview.cpp +++ /dev/null @@ -1,4623 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> - * 1999 Lars Knoll <knoll@kde.org> - * 1999 Antti Koivisto <koivisto@kde.org> - * 2000-2004 Dirk Mueller <mueller@kde.org> - * 2003 Leo Savernik <l.savernik@aon.at> - * 2003-2004 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include "khtmlview.moc" - -#include "khtmlview.h" - -#include "khtml_part.h" -#include "khtml_events.h" - -#include "html/html_documentimpl.h" -#include "html/html_inlineimpl.h" -#include "html/html_formimpl.h" -#include "rendering/render_arena.h" -#include "rendering/render_canvas.h" -#include "rendering/render_frames.h" -#include "rendering/render_replaced.h" -#include "rendering/render_layer.h" -#include "rendering/render_line.h" -#include "rendering/render_table.h" -// removeme -#define protected public -#include "rendering/render_text.h" -#undef protected -#include "xml/dom2_eventsimpl.h" -#include "css/cssstyleselector.h" -#include "css/csshelper.h" -#include "misc/htmlhashes.h" -#include "misc/helper.h" -#include "misc/loader.h" -#include "khtml_settings.h" -#include "khtml_printsettings.h" - -#include "khtmlpart_p.h" - -#ifndef KHTML_NO_CARET -#include "khtml_caret_p.h" -#include "xml/dom2_rangeimpl.h" -#endif - -#include <kapplication.h> -#include <kcursor.h> -#include <kdebug.h> -#include <kdialogbase.h> -#include <kiconloader.h> -#include <kimageio.h> -#include <klocale.h> -#include <knotifyclient.h> -#include <kprinter.h> -#include <ksimpleconfig.h> -#include <kstandarddirs.h> -#include <kstdaccel.h> -#include <kstringhandler.h> -#include <kurldrag.h> - -#include <tqbitmap.h> -#include <tqlabel.h> -#include <tqobjectlist.h> -#include <tqpaintdevicemetrics.h> -#include <tqpainter.h> -#include <tqptrdict.h> -#include <tqtooltip.h> -#include <tqstring.h> -#include <tqstylesheet.h> -#include <tqtimer.h> -#include <tqvaluevector.h> - -//#define DEBUG_NO_PAINT_BUFFER - -//#define DEBUG_FLICKER - -//#define DEBUG_PIXEL - -#ifdef Q_WS_X11 -#include <X11/Xlib.h> -#include <fixx11h.h> -#endif - -#define PAINT_BUFFER_HEIGHT 128 - -#if 0 -namespace khtml { - void dumpLineBoxes(RenderFlow *flow); -} -#endif - -using namespace DOM; -using namespace khtml; -class KHTMLToolTip; - - -#ifndef QT_NO_TOOLTIP - -class KHTMLToolTip : public TQToolTip -{ -public: - KHTMLToolTip(KHTMLView *view, KHTMLViewPrivate* vp) : TQToolTip(view->viewport()) - { - m_view = view; - m_viewprivate = vp; - }; - -protected: - virtual void maybeTip(const TQPoint &); - -private: - KHTMLView *m_view; - KHTMLViewPrivate* m_viewprivate; -}; - -#endif - -class KHTMLViewPrivate { - friend class KHTMLToolTip; -public: - - enum PseudoFocusNodes { - PFNone, - PFTop, - PFBottom - }; - - enum CompletedState { - CSNone = 0, - CSFull, - CSActionPending - }; - - KHTMLViewPrivate() - : underMouse( 0 ), underMouseNonShared( 0 ), visibleWidgets( 107 ) -#ifndef NO_SMOOTH_SCROLL_HACK - , dx(0), dy(0), ddx(0), ddy(0), rdx(0), rdy(0), scrolling(false) -#endif - { -#ifndef KHTML_NO_CARET - m_caretViewContext = 0; - m_editorContext = 0; -#endif // KHTML_NO_CARET - postponed_autorepeat = NULL; - reset(); - vmode = TQScrollView::Auto; - hmode = TQScrollView::Auto; - tp=0; - paintBuffer=0; - vertPaintBuffer=0; - formCompletions=0; - prevScrollbarVisible = true; - tooltip = 0; - possibleTripleClick = false; - emitCompletedAfterRepaint = CSNone; - cursor_icon_widget = NULL; - m_mouseScrollTimer = 0; - m_mouseScrollIndicator = 0; - } - ~KHTMLViewPrivate() - { - delete formCompletions; - delete tp; tp = 0; - delete paintBuffer; paintBuffer =0; - delete vertPaintBuffer; - delete postponed_autorepeat; - if (underMouse) - underMouse->deref(); - if (underMouseNonShared) - underMouseNonShared->deref(); - delete tooltip; -#ifndef KHTML_NO_CARET - delete m_caretViewContext; - delete m_editorContext; -#endif // KHTML_NO_CARET - delete cursor_icon_widget; - delete m_mouseScrollTimer; - delete m_mouseScrollIndicator; - } - void reset() - { - if (underMouse) - underMouse->deref(); - underMouse = 0; - if (underMouseNonShared) - underMouseNonShared->deref(); - underMouseNonShared = 0; - linkPressed = false; - useSlowRepaints = false; - tabMovePending = false; - lastTabbingDirection = true; - pseudoFocusNode = PFNone; -#ifndef KHTML_NO_SCROLLBARS - //We don't turn off the toolbars here - //since if the user turns them - //off, then chances are they want them turned - //off always - even after a reset. -#else - vmode = TQScrollView::AlwaysOff; - hmode = TQScrollView::AlwaysOff; -#endif -#ifdef DEBUG_PIXEL - timer.start(); - pixelbooth = 0; - repaintbooth = 0; -#endif - scrollBarMoved = false; - contentsMoving = false; - ignoreWheelEvents = false; - borderX = 30; - borderY = 30; - paged = false; - clickX = -1; - clickY = -1; - prevMouseX = -1; - prevMouseY = -1; - clickCount = 0; - isDoubleClick = false; - scrollingSelf = false; - delete postponed_autorepeat; - postponed_autorepeat = NULL; - layoutTimerId = 0; - repaintTimerId = 0; - scrollTimerId = 0; - scrollSuspended = false; - scrollSuspendPreActivate = false; - complete = false; - firstRelayout = true; - needsFullRepaint = true; - dirtyLayout = false; - layoutSchedulingEnabled = true; - painting = false; - updateRegion = TQRegion(); - m_dialogsAllowed = true; -#ifndef KHTML_NO_CARET - if (m_caretViewContext) { - m_caretViewContext->caretMoved = false; - m_caretViewContext->keyReleasePending = false; - }/*end if*/ -#endif // KHTML_NO_CARET -#ifndef KHTML_NO_TYPE_AHEAD_FIND - typeAheadActivated = false; -#endif // KHTML_NO_TYPE_AHEAD_FIND - accessKeysActivated = false; - accessKeysPreActivate = false; - - // We ref/deref to ensure defaultHTMLSettings is available - KHTMLFactory::ref(); - accessKeysEnabled = KHTMLFactory::defaultHTMLSettings()->accessKeysEnabled(); - KHTMLFactory::deref(); - - emitCompletedAfterRepaint = CSNone; - } - void newScrollTimer(TQWidget *view, int tid) - { - //kdDebug(6000) << "newScrollTimer timer " << tid << endl; - view->killTimer(scrollTimerId); - scrollTimerId = tid; - scrollSuspended = false; - } - enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown }; - - void adjustScroller(TQWidget *view, ScrollDirection direction, ScrollDirection oppositedir) - { - static const struct { int msec, pixels; } timings [] = { - {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1}, - {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0} - }; - if (!scrollTimerId || - (static_cast<int>(scrollDirection) != direction && - (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) { - scrollTiming = 6; - scrollBy = timings[scrollTiming].pixels; - scrollDirection = direction; - newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); - } else if (scrollDirection == direction && - timings[scrollTiming+1].msec && !scrollSuspended) { - scrollBy = timings[++scrollTiming].pixels; - newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); - } else if (scrollDirection == oppositedir) { - if (scrollTiming) { - scrollBy = timings[--scrollTiming].pixels; - newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); - } - } - scrollSuspended = false; - } - -#ifndef KHTML_NO_CARET - /** this function returns an instance of the caret view context. If none - * exists, it will be instantiated. - */ - CaretViewContext *caretViewContext() { - if (!m_caretViewContext) m_caretViewContext = new CaretViewContext(); - return m_caretViewContext; - } - /** this function returns an instance of the editor context. If none - * exists, it will be instantiated. - */ - EditorContext *editorContext() { - if (!m_editorContext) m_editorContext = new EditorContext(); - return m_editorContext; - } -#endif // KHTML_NO_CARET - -#ifdef DEBUG_PIXEL - TQTime timer; - unsigned int pixelbooth; - unsigned int repaintbooth; -#endif - - TQPainter *tp; - TQPixmap *paintBuffer; - TQPixmap *vertPaintBuffer; - NodeImpl *underMouse; - NodeImpl *underMouseNonShared; - - bool tabMovePending:1; - bool lastTabbingDirection:1; - PseudoFocusNodes pseudoFocusNode:2; - bool scrollBarMoved:1; - bool contentsMoving:1; - - TQScrollView::ScrollBarMode vmode; - TQScrollView::ScrollBarMode hmode; - bool prevScrollbarVisible:1; - bool linkPressed:1; - bool useSlowRepaints:1; - bool ignoreWheelEvents:1; - - int borderX, borderY; - KSimpleConfig *formCompletions; - - bool paged; - - int clickX, clickY, clickCount; - bool isDoubleClick; - - int prevMouseX, prevMouseY; - bool scrollingSelf; - int layoutTimerId; - TQKeyEvent* postponed_autorepeat; - - int repaintTimerId; - int scrollTimerId; - int scrollTiming; - int scrollBy; - ScrollDirection scrollDirection :2; - bool scrollSuspended :1; - bool scrollSuspendPreActivate :1; - bool complete :1; - bool firstRelayout :1; - bool layoutSchedulingEnabled :1; - bool needsFullRepaint :1; - bool painting :1; - bool possibleTripleClick :1; - bool dirtyLayout :1; - bool m_dialogsAllowed :1; - TQRegion updateRegion; - KHTMLToolTip *tooltip; - TQPtrDict<TQWidget> visibleWidgets; -#ifndef KHTML_NO_CARET - CaretViewContext *m_caretViewContext; - EditorContext *m_editorContext; -#endif // KHTML_NO_CARET -#ifndef KHTML_NO_TYPE_AHEAD_FIND - TQString findString; - TQTimer timer; - bool findLinksOnly; - bool typeAheadActivated; -#endif // KHTML_NO_TYPE_AHEAD_FIND - bool accessKeysEnabled; - bool accessKeysActivated; - bool accessKeysPreActivate; - CompletedState emitCompletedAfterRepaint; - - TQWidget* cursor_icon_widget; - - // scrolling activated by MMB - short m_mouseScroll_byX; - short m_mouseScroll_byY; - TQTimer *m_mouseScrollTimer; - TQWidget *m_mouseScrollIndicator; -#ifndef NO_SMOOTH_SCROLL_HACK - TQTimer timer2; - int dx; - int dy; - // Step size * 16 and residual to avoid huge difference between 1px/step and 2px/step - int ddx; - int ddy; - int rdx; - int rdy; - bool scrolling; -#endif -}; - -#ifndef QT_NO_TOOLTIP - -/** calculates the client-side image map rectangle for the given image element - * @param img image element - * @param scrollOfs scroll offset of viewport in content coordinates - * @param p position to be probed in viewport coordinates - * @param r returns the bounding rectangle in content coordinates - * @param s returns the title string - * @return true if an appropriate area was found -- only in this case r and - * s are valid, false otherwise - */ -static bool findImageMapRect(HTMLImageElementImpl *img, const TQPoint &scrollOfs, - const TQPoint &p, TQRect &r, TQString &s) -{ - HTMLMapElementImpl* map; - if (img && img->getDocument()->isHTMLDocument() && - (map = static_cast<HTMLDocumentImpl*>(img->getDocument())->getMap(img->imageMap()))) { - RenderObject::NodeInfo info(true, false); - RenderObject *rend = img->renderer(); - int ax, ay; - if (!rend || !rend->absolutePosition(ax, ay)) - return false; - // we're a client side image map - bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(), - p.y() - ay + scrollOfs.y(), rend->contentWidth(), - rend->contentHeight(), info); - if (inside && info.URLElement()) { - HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement()); - Q_ASSERT(area->id() == ID_AREA); - s = area->getAttribute(ATTR_TITLE).string(); - TQRegion reg = area->cachedRegion(); - if (!s.isEmpty() && !reg.isEmpty()) { - r = reg.boundingRect(); - r.moveBy(ax, ay); - return true; - } - } - } - return false; -} - -void KHTMLToolTip::maybeTip(const TQPoint& p) -{ - DOM::NodeImpl *node = m_viewprivate->underMouseNonShared; - TQRect region; - while ( node ) { - if ( node->isElementNode() ) { - DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node ); - TQRect r; - TQString s; - bool found = false; - // for images, check if it is part of a client-side image map, - // and query the <area>s' title attributes, too - if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) { - found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e), - m_view->viewportToContents(TQPoint(0, 0)), p, r, s); - } - if (!found) { - s = e->getAttribute( ATTR_TITLE ).string(); - r = node->getRect(); - } - region |= TQRect( m_view->contentsToViewport( r.topLeft() ), r.size() ); - if ( !s.isEmpty() ) { - tip( region, TQStyleSheet::convertFromPlainText( s, TQStyleSheetItem::WhiteSpaceNormal ) ); - break; - } - } - node = node->parentNode(); - } -} -#endif - -KHTMLView::KHTMLView( KHTMLPart *part, TQWidget *parent, const char *name) - : TQScrollView( parent, name, (WFlags)(WResizeNoErase | WRepaintNoErase) ) -{ - m_medium = "screen"; - - m_part = part; - d = new KHTMLViewPrivate; - TQScrollView::setVScrollBarMode(d->vmode); - TQScrollView::setHScrollBarMode(d->hmode); - connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), this, TQT_SLOT(slotPaletteChanged())); - connect(this, TQT_SIGNAL(contentsMoving(int, int)), this, TQT_SLOT(slotScrollBarMoved())); - - // initialize QScrollView - enableClipper(true); - // hack to get unclipped painting on the viewport. - static_cast<KHTMLView *>(TQT_TQWIDGET(viewport()))->setWFlags(WPaintUnclipped); - - setResizePolicy(Manual); - viewport()->setMouseTracking(true); - viewport()->setBackgroundMode(NoBackground); - - KImageIO::registerFormats(); - -#ifndef QT_NO_TOOLTIP - d->tooltip = new KHTMLToolTip( this, d ); -#endif - -#ifndef KHTML_NO_TYPE_AHEAD_FIND - connect(&d->timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(findTimeout())); -#endif // KHTML_NO_TYPE_AHEAD_FIND - - init(); - - viewport()->show(); -#ifndef NO_SMOOTH_SCROLL_HACK -#define timer timer2 - connect(&d->timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(scrollTick())); -#undef timer -#endif -} - -KHTMLView::~KHTMLView() -{ - closeChildDialogs(); - if (m_part) - { - //WABA: Is this Ok? Do I need to deref it as well? - //Does this need to be done somewhere else? - DOM::DocumentImpl *doc = m_part->xmlDocImpl(); - if (doc) - doc->detach(); - } - delete d; d = 0; -} - -void KHTMLView::init() -{ - if(!d->paintBuffer) d->paintBuffer = new TQPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT); - if(!d->vertPaintBuffer) - d->vertPaintBuffer = new TQPixmap(10, PAINT_BUFFER_HEIGHT); - if(!d->tp) d->tp = new TQPainter(); - - setFocusPolicy(TQ_StrongFocus); - viewport()->setFocusProxy(this); - - _marginWidth = -1; // undefined - _marginHeight = -1; - _width = 0; - _height = 0; - - installEventFilter(this); - - setAcceptDrops(true); - TQSize s = viewportSize(4095, 4095); - resizeContents(s.width(), s.height()); -} - -void KHTMLView::clear() -{ - // work around QScrollview's unbelievable bugginess - setStaticBackground(true); -#ifndef KHTML_NO_CARET - if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff(); -#endif - -#ifndef KHTML_NO_TYPE_AHEAD_FIND - if( d->typeAheadActivated ) - findTimeout(); -#endif - if (d->accessKeysEnabled && d->accessKeysActivated) - accessKeysTimeout(); - viewport()->unsetCursor(); - if ( d->cursor_icon_widget ) - d->cursor_icon_widget->hide(); - d->reset(); - TQT_TQOBJECT(this)->killTimers(); - emit cleared(); - - TQScrollView::setHScrollBarMode(d->hmode); - TQScrollView::setVScrollBarMode(d->vmode); - verticalScrollBar()->setEnabled( false ); - horizontalScrollBar()->setEnabled( false ); -} - -void KHTMLView::hideEvent(TQHideEvent* e) -{ - TQScrollView::hideEvent(e); - if ( m_part && m_part->xmlDocImpl() ) - m_part->xmlDocImpl()->docLoader()->pauseAnimations(); -} - -void KHTMLView::showEvent(TQShowEvent* e) -{ - TQScrollView::showEvent(e); - if ( m_part && m_part->xmlDocImpl() ) - m_part->xmlDocImpl()->docLoader()->resumeAnimations(); -} - -void KHTMLView::resizeEvent (TQResizeEvent* e) -{ - int dw = e->oldSize().width() - e->size().width(); - int dh = e->oldSize().height() - e->size().height(); - - // if we are shrinking the view, don't allow the content to overflow - // before the layout occurs - we don't know if we need scrollbars yet - dw = dw>0 ? kMax(0, contentsWidth()-dw) : contentsWidth(); - dh = dh>0 ? kMax(0, contentsHeight()-dh) : contentsHeight(); - - resizeContents(dw, dh); - - TQScrollView::resizeEvent(e); - - if ( m_part && m_part->xmlDocImpl() ) - m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false ); -} - -void KHTMLView::viewportResizeEvent (TQResizeEvent* e) -{ - TQScrollView::viewportResizeEvent(e); - - //int w = visibleWidth(); - //int h = visibleHeight(); - - if (d->layoutSchedulingEnabled) - layout(); -#ifndef KHTML_NO_CARET - else { - hideCaret(); - recalcAndStoreCaretPos(); - showCaret(); - }/*end if*/ -#endif - - TDEApplication::sendPostedEvents(viewport(), TQEvent::Paint); -} - -// this is to get rid of a compiler virtual overload mismatch warning. do not remove -void KHTMLView::drawContents( TQPainter*) -{ -} - -void KHTMLView::drawContents( TQPainter *p, int ex, int ey, int ew, int eh ) -{ -#ifdef DEBUG_PIXEL - - if ( d->timer.elapsed() > 5000 ) { - tqDebug( "drawed %d pixels in %d repaints the last %d milliseconds", - d->pixelbooth, d->repaintbooth, d->timer.elapsed() ); - d->timer.restart(); - d->pixelbooth = 0; - d->repaintbooth = 0; - } - d->pixelbooth += ew*eh; - d->repaintbooth++; -#endif - - //kdDebug( 6000 ) << "drawContents this="<< this <<" x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl; - if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) { - p->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base)); - return; - } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) { - // an external update request happens while we have a layout scheduled - unscheduleRelayout(); - layout(); - } - - if (d->painting) { - kdDebug( 6000 ) << "WARNING: drawContents reentered! " << endl; - return; - } - d->painting = true; - - TQPoint pt = contentsToViewport(TQPoint(ex, ey)); - TQRegion cr = TQRect(pt.x(), pt.y(), ew, eh); - - // kdDebug(6000) << "clip rect: " << TQRect(pt.x(), pt.y(), ew, eh) << endl; - for (TQPtrDictIterator<TQWidget> it(d->visibleWidgets); it.current(); ++it) { - TQWidget *w = it.current(); - RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() ); - if (w && rw && !rw->isKHTMLWidget()) { - int x, y; - rw->absolutePosition(x, y); - contentsToViewport(x, y, x, y); - int pbx = rw->borderLeft()+rw->paddingLeft(); - int pby = rw->borderTop()+rw->paddingTop(); - TQRect g = TQRect(x+pbx, y+pby, - rw->width()-pbx-rw->borderRight()-rw->paddingRight(), - rw->height()-pby-rw->borderBottom()-rw->paddingBottom()); - if ( !rw->isFrame() && ((g.top() > pt.y()+eh) || (g.bottom() <= pt.y()) || - (g.right() <= pt.x()) || (g.left() > pt.x()+ew) )) - continue; - RenderLayer* rl = rw->needsMask() ? rw->enclosingStackingContext() : 0; - TQRegion mask = rl ? rl->getMask() : TQRegion(); - if (!mask.isNull()) { - TQPoint o(0,0); - o = contentsToViewport(o); - mask.translate(o.x(),o.y()); - mask = mask.intersect( TQRect(g.x(),g.y(),g.width(),g.height()) ); - cr -= mask; - } else { - cr -= g; - } - } - } - -#if 0 - // this is commonly the case with framesets. we still do - // want to paint them, otherwise the widgets don't get placed. - if (cr.isEmpty()) { - d->painting = false; - return; - } -#endif - -#ifndef DEBUG_NO_PAINT_BUFFER - p->setClipRegion(cr); - - if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) { - if ( d->vertPaintBuffer->height() < visibleHeight() ) - d->vertPaintBuffer->resize(10, visibleHeight()); - d->tp->begin(d->vertPaintBuffer); - d->tp->translate(-ex, -ey); - d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base)); - m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, TQRect(ex, ey, ew, eh)); - d->tp->end(); - p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh); - } - else { - if ( d->paintBuffer->width() < visibleWidth() ) - d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT); - - int py=0; - while (py < eh) { - int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT; - d->tp->begin(d->paintBuffer); - d->tp->translate(-ex, -ey-py); - d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(TQColorGroup::Base)); - m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, TQRect(ex, ey+py, ew, ph)); - d->tp->end(); - - p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph); - py += PAINT_BUFFER_HEIGHT; - } - } -#else // !DEBUG_NO_PAINT_BUFFER -static int cnt=0; - ex = contentsX(); ey = contentsY(); - ew = visibleWidth(); eh = visibleHeight(); - TQRect pr(ex,ey,ew,eh); - kdDebug() << "[" << ++cnt << "]" << " clip region: " << pr << endl; -// p->setClipRegion(TQRect(0,0,ew,eh)); -// p->translate(-ex, -ey); - p->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base)); - m_part->xmlDocImpl()->renderer()->layer()->paint(p, pr); -#endif // DEBUG_NO_PAINT_BUFFER - -#ifndef KHTML_NO_CARET - if (d->m_caretViewContext && d->m_caretViewContext->visible) { - TQRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, d->m_caretViewContext->height); - if (pos.intersects(TQRect(ex, ey, ew, eh))) { - p->setRasterOp(XorROP); - p->setPen(white); - if (pos.width() == 1) - p->drawLine(pos.topLeft(), pos.bottomRight()); - else { - p->fillRect(pos, white); - }/*end if*/ - }/*end if*/ - }/*end if*/ -#endif // KHTML_NO_CARET - -// p->setPen(TQPen(magenta,0,DashDotDotLine)); -// p->drawRect(dbg_paint_rect); - - khtml::DrawContentsEvent event( p, ex, ey, ew, eh ); - TQApplication::sendEvent( m_part, &event ); - - d->painting = false; -} - -void KHTMLView::setMarginWidth(int w) -{ - // make it update the rendering area when set - _marginWidth = w; -} - -void KHTMLView::setMarginHeight(int h) -{ - // make it update the rendering area when set - _marginHeight = h; -} - -void KHTMLView::layout() -{ - if( m_part && m_part->xmlDocImpl() ) { - DOM::DocumentImpl *document = m_part->xmlDocImpl(); - - khtml::RenderCanvas* canvas = static_cast<khtml::RenderCanvas *>(document->renderer()); - if ( !canvas ) return; - - d->layoutSchedulingEnabled=false; - - // the reference object for the overflow property on canvas - RenderObject * ref = 0; - RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0; - - if (document->isHTMLDocument()) { - NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body(); - if(body && body->renderer() && body->id() == ID_FRAMESET) { - TQScrollView::setVScrollBarMode(AlwaysOff); - TQScrollView::setHScrollBarMode(AlwaysOff); - body->renderer()->setNeedsLayout(true); -// if (d->tooltip) { -// delete d->tooltip; -// d->tooltip = 0; -// } - } - else { - if (!d->tooltip) - d->tooltip = new KHTMLToolTip( this, d ); - // only apply body's overflow to canvas if root as a visible overflow - if (root) - ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer(); - } - } else { - ref = root; - } - if (ref) { - if( ref->style()->overflowX() == OHIDDEN ) { - if (d->hmode == Auto) TQScrollView::setHScrollBarMode(AlwaysOff); - } else if (ref->style()->overflowX() == OSCROLL ) { - if (d->hmode == Auto) TQScrollView::setHScrollBarMode(AlwaysOn); - } else { - if (TQScrollView::hScrollBarMode() == AlwaysOff) TQScrollView::setHScrollBarMode(d->hmode); - } if ( ref->style()->overflowY() == OHIDDEN ) { - if (d->vmode == Auto) TQScrollView::setVScrollBarMode(AlwaysOff); - } else if (ref->style()->overflowY() == OSCROLL ) { - if (d->vmode == Auto) TQScrollView::setVScrollBarMode(AlwaysOn); - } else { - if (TQScrollView::vScrollBarMode() == AlwaysOff) TQScrollView::setVScrollBarMode(d->vmode); - } - } - d->needsFullRepaint = d->firstRelayout; - if (_height != visibleHeight() || _width != visibleWidth()) {; - d->needsFullRepaint = true; - _height = visibleHeight(); - _width = visibleWidth(); - } - //TQTime qt; - //qt.start(); - canvas->layout(); - - emit finishedLayout(); - if (d->firstRelayout) { - // make sure firstRelayout is set to false now in case this layout - // wasn't scheduled - d->firstRelayout = false; - verticalScrollBar()->setEnabled( true ); - horizontalScrollBar()->setEnabled( true ); - } -#if 0 - ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__"); - if (listitem) kdDebug(6000) << "after layout, before repaint" << endl; - if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer())); -#endif -#ifndef KHTML_NO_CARET - hideCaret(); - if ((m_part->isCaretMode() || m_part->isEditable()) - && !d->complete && d->m_caretViewContext - && !d->m_caretViewContext->caretMoved) { - initCaret(); - } else { - recalcAndStoreCaretPos(); - showCaret(); - }/*end if*/ -#endif - if (d->accessKeysEnabled && d->accessKeysActivated) { - emit hideAccessKeys(); - displayAccessKeys(); - } - //kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl; - } - else - _width = visibleWidth(); - - killTimer(d->layoutTimerId); - d->layoutTimerId = 0; - d->layoutSchedulingEnabled=true; -} - -void KHTMLView::closeChildDialogs() -{ - TQObjectList *dlgs = queryList(TQDIALOG_OBJECT_NAME_STRING); - for (TQObject *dlg = dlgs->first(); dlg; dlg = dlgs->next()) - { - KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg ); - if ( dlgbase ) { - if ( dlgbase->testWFlags( WShowModal ) ) { - kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl; - // close() ends up calling TQButton::animateClick, which isn't immediate - // we need something the exits the event loop immediately (#49068) - dlgbase->cancel(); - } - } - else - { - kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << TQT_TQWIDGET(dlg) << endl; - TQT_TQWIDGET(dlg)->hide(); - } - } - delete dlgs; - d->m_dialogsAllowed = false; -} - -bool KHTMLView::dialogsAllowed() { - bool allowed = d->m_dialogsAllowed; - KHTMLPart* p = m_part->parentPart(); - if (p && p->view()) - allowed &= p->view()->dialogsAllowed(); - return allowed; -} - -void KHTMLView::closeEvent( TQCloseEvent* ev ) -{ - closeChildDialogs(); - TQScrollView::closeEvent( ev ); -} - -// -// Event Handling -// -///////////////// - -void KHTMLView::viewportMousePressEvent( TQMouseEvent *_mouse ) -{ - if (!m_part->xmlDocImpl()) return; - if (d->possibleTripleClick && ( _mouse->button() & Qt::MouseButtonMask ) == Qt::LeftButton) - { - viewportMouseDoubleClickEvent( _mouse ); // it handles triple clicks too - return; - } - - int xm, ym; - viewportToContents(_mouse->x(), _mouse->y(), xm, ym); - //kdDebug( 6000 ) << "mousePressEvent: viewport=("<<_mouse->x()<<"/"<<_mouse->y()<<"), contents=(" << xm << "/" << ym << ")\n"; - - d->isDoubleClick = false; - - DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress ); - m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); - - //kdDebug(6000) << "innerNode="<<mev.innerNode.nodeName().string()<<endl; - - if ( (_mouse->button() == Qt::MidButton) && - !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer && - mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) { - TQPoint point = mapFromGlobal( _mouse->globalPos() ); - - d->m_mouseScroll_byX = 0; - d->m_mouseScroll_byY = 0; - - d->m_mouseScrollTimer = new TQTimer( this ); - connect( d->m_mouseScrollTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotMouseScrollTimer()) ); - - if ( !d->m_mouseScrollIndicator ) { - TQPixmap pixmap, icon; - pixmap.resize( 48, 48 ); - pixmap.fill( TQColor( tqRgba( 127, 127, 127, 127 ) ) ); - - TQPainter p( &pixmap ); - icon = TDEGlobal::iconLoader()->loadIcon( "1uparrow", KIcon::Small ); - p.drawPixmap( 16, 0, icon ); - icon = TDEGlobal::iconLoader()->loadIcon( "1leftarrow", KIcon::Small ); - p.drawPixmap( 0, 16, icon ); - icon = TDEGlobal::iconLoader()->loadIcon( "1downarrow", KIcon::Small ); - p.drawPixmap( 16, 32,icon ); - icon = TDEGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Small ); - p.drawPixmap( 32, 16, icon ); - p.drawEllipse( 23, 23, 2, 2 ); - - d->m_mouseScrollIndicator = new TQWidget( this, 0 ); - d->m_mouseScrollIndicator->setFixedSize( 48, 48 ); - d->m_mouseScrollIndicator->setPaletteBackgroundPixmap( pixmap ); - } - d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 ); - - bool hasHorBar = visibleWidth() < contentsWidth(); - bool hasVerBar = visibleHeight() < contentsHeight(); - - TDEConfig *config = TDEGlobal::config(); - TDEConfigGroupSaver saver( config, "HTML Settings" ); - if ( config->readBoolEntry( "ShowMouseScrollIndicator", true ) ) { - d->m_mouseScrollIndicator->show(); - d->m_mouseScrollIndicator->unsetCursor(); - - TQBitmap mask = d->m_mouseScrollIndicator->paletteBackgroundPixmap()->createHeuristicMask( true ); - - if ( hasHorBar && !hasVerBar ) { - TQBitmap bm( 16, 16, true ); - bitBlt( &mask, 16, 0, &bm, 0, 0, -1, -1 ); - bitBlt( &mask, 16, 32, &bm, 0, 0, -1, -1 ); - d->m_mouseScrollIndicator->setCursor( KCursor::SizeHorCursor ); - } - else if ( !hasHorBar && hasVerBar ) { - TQBitmap bm( 16, 16, true ); - bitBlt( &mask, 0, 16, &bm, 0, 0, -1, -1 ); - bitBlt( &mask, 32, 16, &bm, 0, 0, -1, -1 ); - d->m_mouseScrollIndicator->setCursor( KCursor::SizeVerCursor ); - } - else - d->m_mouseScrollIndicator->setCursor( KCursor::SizeAllCursor ); - - d->m_mouseScrollIndicator->setMask( mask ); - } - else { - if ( hasHorBar && !hasVerBar ) - viewport()->setCursor( KCursor::SizeHorCursor ); - else if ( !hasHorBar && hasVerBar ) - viewport()->setCursor( KCursor::SizeVerCursor ); - else - viewport()->setCursor( KCursor::SizeAllCursor ); - } - - return; - } - else if ( d->m_mouseScrollTimer ) { - delete d->m_mouseScrollTimer; - d->m_mouseScrollTimer = 0; - - if ( d->m_mouseScrollIndicator ) - d->m_mouseScrollIndicator->hide(); - } - - d->clickCount = 1; - d->clickX = xm; - d->clickY = ym; - - bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, - d->clickCount,_mouse,true,DOM::NodeImpl::MousePress); - - khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0; - if (r && r->isWidget()) - _mouse->ignore(); - - if (!swallowEvent) { - emit m_part->nodeActivated(mev.innerNode); - - khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); - TQApplication::sendEvent( m_part, &event ); - // we might be deleted after this - } -} - -void KHTMLView::viewportMouseDoubleClickEvent( TQMouseEvent *_mouse ) -{ - if(!m_part->xmlDocImpl()) return; - - int xm, ym; - viewportToContents(_mouse->x(), _mouse->y(), xm, ym); - - kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl; - - d->isDoubleClick = true; - - DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick ); - m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); - - // We do the same thing as viewportMousePressEvent() here, since the DOM does not treat - // single and double-click events as separate (only the detail, i.e. number of clicks differs) - if (d->clickCount > 0 && - TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= TQApplication::startDragDistance()) - d->clickCount++; - else { // shouldn't happen, if Qt has the same criterias for double clicks. - d->clickCount = 1; - d->clickX = xm; - d->clickY = ym; - } - bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, - d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick); - - khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0; - if (r && r->isWidget()) - _mouse->ignore(); - - if (!swallowEvent) { - khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount ); - TQApplication::sendEvent( m_part, &event ); - } - - d->possibleTripleClick=true; - TQTimer::singleShot(TQApplication::doubleClickInterval(),this,TQT_SLOT(tripleClickTimeout())); -} - -void KHTMLView::tripleClickTimeout() -{ - d->possibleTripleClick = false; - d->clickCount = 0; -} - -static inline void forwardPeripheralEvent(khtml::RenderWidget* r, TQMouseEvent* me, int x, int y) -{ - int absx = 0; - int absy = 0; - r->absolutePosition(absx, absy); - TQPoint p(x-absx, y-absy); - TQMouseEvent fw(me->type(), p, me->button(), me->state()); - TQWidget* w = r->widget(); - TQScrollView* sc = ::tqqt_cast<TQScrollView*>(w); - if (sc && !::tqqt_cast<TQListBox*>(w)) - static_cast<khtml::RenderWidget::ScrollViewEventPropagator*>(sc)->sendEvent(TQT_TQEVENT(&fw)); - else if(w) - static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(TQT_TQEVENT(&fw)); -} - - -static bool targetOpensNewWindow(KHTMLPart *part, TQString target) -{ - if (!target.isEmpty() && (target.lower() != "_top") && - (target.lower() != "_self") && (target.lower() != "_parent")) { - if (target.lower() == "_blank") - return true; - else { - while (part->parentPart()) - part = part->parentPart(); - if (!part->frameExists(target)) - return true; - } - } - return false; -} - -void KHTMLView::viewportMouseMoveEvent( TQMouseEvent * _mouse ) -{ - if ( d->m_mouseScrollTimer ) { - TQPoint point = mapFromGlobal( _mouse->globalPos() ); - - int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24; - int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24; - - (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1; - (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1; - - double adX = TQABS(deltaX)/30.0; - double adY = TQABS(deltaY)/30.0; - - d->m_mouseScroll_byX = kMax(kMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN); - d->m_mouseScroll_byY = kMax(kMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN); - - if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) { - d->m_mouseScrollTimer->stop(); - } - else if (!d->m_mouseScrollTimer->isActive()) { - d->m_mouseScrollTimer->changeInterval( 20 ); - } - } - - if(!m_part->xmlDocImpl()) return; - - int xm, ym; - viewportToContents(_mouse->x(), _mouse->y(), xm, ym); - - DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove ); - // Do not modify :hover/:active state while mouse is pressed. - m_part->xmlDocImpl()->prepareMouseEvent( _mouse->state() & Qt::MouseButtonMask /*readonly ?*/, xm, ym, &mev ); - -// kdDebug(6000) << "mouse move: " << _mouse->pos() -// << " button " << _mouse->button() -// << " state " << _mouse->state() << endl; - - bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),false, - 0,_mouse,true,DOM::NodeImpl::MouseMove); - - if (d->clickCount > 0 && - TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > TQApplication::startDragDistance()) { - d->clickCount = 0; // moving the mouse outside the threshold invalidates the click - } - - // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events - m_part->executeScheduledScript(); - - DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode(); - if (fn && fn != mev.innerNode.handle() && - fn->renderer() && fn->renderer()->isWidget()) { - forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym); - } - - khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0; - khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0; - TQCursor c; - bool mailtoCursor = false; - bool newWindowCursor = false; - switch ( style ? style->cursor() : CURSOR_AUTO) { - case CURSOR_AUTO: - if ( r && r->isText() ) - c = KCursor::ibeamCursor(); - if ( mev.url.length() && m_part->settings()->changeCursor() ) { - c = m_part->urlCursor(); - if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0) - mailtoCursor = true; - else - newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() ); - } - - if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize()) - c = TQCursor(static_cast<RenderFrameSet*>(r)->cursorShape()); - - break; - case CURSOR_CROSS: - c = KCursor::crossCursor(); - break; - case CURSOR_POINTER: - c = m_part->urlCursor(); - if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0) - mailtoCursor = true; - else - newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() ); - break; - case CURSOR_PROGRESS: - c = KCursor::workingCursor(); - break; - case CURSOR_MOVE: - c = KCursor::sizeAllCursor(); - break; - case CURSOR_E_RESIZE: - case CURSOR_W_RESIZE: - c = KCursor::sizeHorCursor(); - break; - case CURSOR_N_RESIZE: - case CURSOR_S_RESIZE: - c = KCursor::sizeVerCursor(); - break; - case CURSOR_NE_RESIZE: - case CURSOR_SW_RESIZE: - c = KCursor::sizeBDiagCursor(); - break; - case CURSOR_NW_RESIZE: - case CURSOR_SE_RESIZE: - c = KCursor::sizeFDiagCursor(); - break; - case CURSOR_TEXT: - c = KCursor::ibeamCursor(); - break; - case CURSOR_WAIT: - c = KCursor::waitCursor(); - break; - case CURSOR_HELP: - c = KCursor::whatsThisCursor(); - break; - case CURSOR_DEFAULT: - break; - } - - if ( viewport()->cursor().handle() != c.handle() ) { - if( c.handle() == KCursor::arrowCursor().handle()) { - for (KHTMLPart* p = m_part; p; p = p->parentPart()) - p->view()->viewport()->unsetCursor(); - } - else { - viewport()->setCursor( c ); - } - } - - if ( ( mailtoCursor || newWindowCursor ) && isVisible() && hasFocus() ) { -#ifdef Q_WS_X11 - TQPixmap icon_pixmap = TDEGlobal::iconLoader()->loadIcon( mailtoCursor ? "mail_generic" : "window_new", KIcon::Small, 0, KIcon::DefaultState, 0, true ); - - if (d->cursor_icon_widget) { - const TQPixmap *pm = d->cursor_icon_widget->backgroundPixmap(); - if (!pm || pm->serialNumber()!=icon_pixmap.serialNumber()) { - delete d->cursor_icon_widget; - d->cursor_icon_widget = 0; - } - } - - if( !d->cursor_icon_widget ) { - d->cursor_icon_widget = new TQWidget( NULL, NULL, WX11BypassWM ); - XSetWindowAttributes attr; - attr.save_under = True; - XChangeWindowAttributes( tqt_xdisplay(), d->cursor_icon_widget->winId(), CWSaveUnder, &attr ); - d->cursor_icon_widget->resize( icon_pixmap.width(), icon_pixmap.height()); - if( icon_pixmap.mask() ) - d->cursor_icon_widget->setMask( *icon_pixmap.mask()); - else - d->cursor_icon_widget->clearMask(); - d->cursor_icon_widget->setBackgroundPixmap( icon_pixmap ); - d->cursor_icon_widget->erase(); - } - TQPoint c_pos = TQCursor::pos(); - d->cursor_icon_widget->move( c_pos.x() + 15, c_pos.y() + 15 ); - XRaiseWindow( tqt_xdisplay(), d->cursor_icon_widget->winId()); - TQApplication::flushX(); - d->cursor_icon_widget->show(); -#endif - } - else if ( d->cursor_icon_widget ) - d->cursor_icon_widget->hide(); - - if (r && r->isWidget()) { - _mouse->ignore(); - } - - - d->prevMouseX = xm; - d->prevMouseY = ym; - - if (!swallowEvent) { - khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); - TQApplication::sendEvent( m_part, &event ); - } -} - -void KHTMLView::viewportMouseReleaseEvent( TQMouseEvent * _mouse ) -{ - bool swallowEvent = false; - int xm, ym; - viewportToContents(_mouse->x(), _mouse->y(), xm, ym); - DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease ); - - if ( m_part->xmlDocImpl() ) - { - m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); - - swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, - d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease); - - if (d->clickCount > 0 && - TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= TQApplication::startDragDistance()) { - TQMouseEvent me(d->isDoubleClick ? TQEvent::MouseButtonDblClick : TQEvent::MouseButtonRelease, - _mouse->pos(), _mouse->button(), _mouse->state()); - dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, - d->clickCount, &me, true, DOM::NodeImpl::MouseRelease); - } - - DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode(); - if (fn && fn != mev.innerNode.handle() && - fn->renderer() && fn->renderer()->isWidget() && - _mouse->button() != Qt::MidButton) { - forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym); - } - - khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0; - if (r && r->isWidget()) - _mouse->ignore(); - } - - if (!swallowEvent) { - khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); - TQApplication::sendEvent( m_part, &event ); - } -} - -// returns true if event should be swallowed -bool KHTMLView::dispatchKeyEvent( TQKeyEvent *_ke ) -{ - if (!m_part->xmlDocImpl()) - return false; - // Pressing and releasing a key should generate keydown, keypress and keyup events - // Holding it down should generated keydown, keypress (repeatedly) and keyup events - // The problem here is that Qt generates two autorepeat events (keyrelease+keypress) - // for autorepeating, while DOM wants only one autorepeat event (keypress), so one - // of the Qt events shouldn't be passed to DOM, but it should be still filtered - // out if DOM would filter the autorepeat event. Additional problem is that Qt keyrelease - // events don't have text() set (Qt bug?), so DOM often would ignore the keypress event - // if it was created using Qt keyrelease, but Qt autorepeat keyrelease comes - // before Qt autorepeat keypress (i.e. problem whether to filter it out or not). - // The solution is to filter out and postpone the Qt autorepeat keyrelease until - // the following Qt keypress event comes. If DOM accepts the DOM keypress event, - // the postponed event will be simply discarded. If not, it will be passed to keyPressEvent() - // again, and here it will be ignored. - // - // Qt: Press | Release(autorepeat) Press(autorepeat) etc. | Release - // DOM: Down + Press | (nothing) Press | Up - - // It's also possible to get only Releases. E.g. the release of alt-tab, - // or when the keypresses get captured by an accel. - - if( _ke == d->postponed_autorepeat ) // replayed event - { - return false; - } - - if( _ke->type() == TQEvent::KeyPress ) - { - if( !_ke->isAutoRepeat()) - { - bool ret = dispatchKeyEventHelper( _ke, false ); // keydown - // don't send keypress even if keydown was blocked, like IE (and unlike Mozilla) - if( !ret && dispatchKeyEventHelper( _ke, true )) // keypress - ret = true; - return ret; - } - else // autorepeat - { - bool ret = dispatchKeyEventHelper( _ke, true ); // keypress - if( !ret && d->postponed_autorepeat ) - keyPressEvent( d->postponed_autorepeat ); - delete d->postponed_autorepeat; - d->postponed_autorepeat = NULL; - return ret; - } - } - else // TQEvent::KeyRelease - { - // Discard postponed "autorepeat key-release" events that didn't see - // a keypress after them (e.g. due to TQAccel) - if ( d->postponed_autorepeat ) { - delete d->postponed_autorepeat; - d->postponed_autorepeat = 0; - } - - if( !_ke->isAutoRepeat()) { - return dispatchKeyEventHelper( _ke, false ); // keyup - } - else - { - d->postponed_autorepeat = new TQKeyEvent( _ke->type(), _ke->key(), _ke->ascii(), _ke->state(), - _ke->text(), _ke->isAutoRepeat(), _ke->count()); - if( _ke->isAccepted()) - d->postponed_autorepeat->accept(); - else - d->postponed_autorepeat->ignore(); - return true; - } - } -} - -// returns true if event should be swallowed -bool KHTMLView::dispatchKeyEventHelper( TQKeyEvent *_ke, bool keypress ) -{ - DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode(); - if (keyNode) { - return keyNode->dispatchKeyEvent(_ke, keypress); - } else { // no focused node, send to document - return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress); - } -} - -void KHTMLView::keyPressEvent( TQKeyEvent *_ke ) -{ -#ifndef KHTML_NO_TYPE_AHEAD_FIND - if(d->typeAheadActivated) - { - // type-ahead find aka find-as-you-type - if(_ke->key() == Key_BackSpace) - { - d->findString = d->findString.left(d->findString.length() - 1); - - if(!d->findString.isEmpty()) - { - findAhead(false); - } - else - { - findTimeout(); - } - - d->timer.start(3000, true); - _ke->accept(); - return; - } - else if(_ke->key() == Key_Escape) - { - findTimeout(); - - _ke->accept(); - return; - } - else if(_ke->key() == Key_Space || !TQString(_ke->text()).stripWhiteSpace().isEmpty()) - { - d->findString += _ke->text(); - - findAhead(true); - - d->timer.start(3000, true); - _ke->accept(); - return; - } - } -#endif // KHTML_NO_TYPE_AHEAD_FIND - -#ifndef KHTML_NO_CARET - if (m_part->isEditable() || m_part->isCaretMode() - || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode() - && m_part->xmlDocImpl()->focusNode()->contentEditable())) { - d->caretViewContext()->keyReleasePending = true; - caretKeyPressEvent(_ke); - return; - } -#endif // KHTML_NO_CARET - - // If CTRL was hit, be prepared for access keys - if (d->accessKeysEnabled && _ke->key() == Key_Control && _ke->state()==0 && !d->accessKeysActivated) - { - d->accessKeysPreActivate=true; - _ke->accept(); - return; - } - - if (_ke->key() == Key_Shift && _ke->state()==0) - d->scrollSuspendPreActivate=true; - - // accesskey handling needs to be done before dispatching, otherwise e.g. lineedits - // may eat the event - - if (d->accessKeysEnabled && d->accessKeysActivated) - { - int state = ( _ke->state() & ( ShiftButton | ControlButton | AltButton | MetaButton )); - if ( state==0 || state==ShiftButton) { - if (_ke->key() != Key_Shift) accessKeysTimeout(); - handleAccessKey( _ke ); - _ke->accept(); - return; - } - accessKeysTimeout(); - } - - if ( dispatchKeyEvent( _ke )) { - // If either keydown or keypress was accepted by a widget, or canceled by JS, stop here. - _ke->accept(); - return; - } - - int offs = (clipper()->height() < 30) ? clipper()->height() : 30; - if (_ke->state() & TQt::ShiftButton) - switch(_ke->key()) - { - case Key_Space: - scrollBy( 0, -clipper()->height() + offs ); - if(d->scrollSuspended) - d->newScrollTimer(this, 0); - break; - - case Key_Down: - case Key_J: - d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp); - break; - - case Key_Up: - case Key_K: - d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown); - break; - - case Key_Left: - case Key_H: - d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight); - break; - - case Key_Right: - case Key_L: - d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft); - break; - } - else - switch ( _ke->key() ) - { - case Key_Down: - case Key_J: - if (!d->scrollTimerId || d->scrollSuspended) - scrollBy( 0, 10 * _ke->count() ); - if (d->scrollTimerId) - d->newScrollTimer(this, 0); - break; - - case Key_Space: - case Key_Next: - scrollBy( 0, clipper()->height() - offs ); - if(d->scrollSuspended) - d->newScrollTimer(this, 0); - break; - - case Key_Up: - case Key_K: - if (!d->scrollTimerId || d->scrollSuspended) - scrollBy( 0, -10 * _ke->count()); - if (d->scrollTimerId) - d->newScrollTimer(this, 0); - break; - - case Key_Prior: - scrollBy( 0, -clipper()->height() + offs ); - if(d->scrollSuspended) - d->newScrollTimer(this, 0); - break; - case Key_Right: - case Key_L: - if (!d->scrollTimerId || d->scrollSuspended) - scrollBy( 10 * _ke->count(), 0 ); - if (d->scrollTimerId) - d->newScrollTimer(this, 0); - break; - case Key_Left: - case Key_H: - if (!d->scrollTimerId || d->scrollSuspended) - scrollBy( -10 * _ke->count(), 0 ); - if (d->scrollTimerId) - d->newScrollTimer(this, 0); - break; - case Key_Enter: - case Key_Return: - // ### FIXME: - // or even better to HTMLAnchorElementImpl::event() - if (m_part->xmlDocImpl()) { - NodeImpl *n = m_part->xmlDocImpl()->focusNode(); - if (n) - n->setActive(); - } - break; - case Key_Home: - setContentsPos( 0, 0 ); - if(d->scrollSuspended) - d->newScrollTimer(this, 0); - break; - case Key_End: - setContentsPos( 0, contentsHeight() - visibleHeight() ); - if(d->scrollSuspended) - d->newScrollTimer(this, 0); - break; - case Key_Shift: - // what are you doing here? - _ke->ignore(); - return; - default: - if (d->scrollTimerId) - d->newScrollTimer(this, 0); - _ke->ignore(); - return; - } - - _ke->accept(); -} - -void KHTMLView::findTimeout() -{ -#ifndef KHTML_NO_TYPE_AHEAD_FIND - d->typeAheadActivated = false; - d->findString = ""; - m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText); - m_part->enableFindAheadActions( true ); -#endif // KHTML_NO_TYPE_AHEAD_FIND -} - -#ifndef KHTML_NO_TYPE_AHEAD_FIND -void KHTMLView::startFindAhead( bool linksOnly ) -{ - if( linksOnly ) - { - d->findLinksOnly = true; - m_part->setStatusBarText(i18n("Starting -- find links as you type"), - KHTMLPart::BarDefaultText); - } - else - { - d->findLinksOnly = false; - m_part->setStatusBarText(i18n("Starting -- find text as you type"), - KHTMLPart::BarDefaultText); - } - - m_part->findTextBegin(); - d->typeAheadActivated = true; - // disable, so that the shortcut ( / or ' by default ) doesn't interfere - m_part->enableFindAheadActions( false ); - d->timer.start(3000, true); -} - -void KHTMLView::findAhead(bool increase) -{ - TQString status; - - if(d->findLinksOnly) - { - m_part->findText(d->findString, KHTMLPart::FindNoPopups | - KHTMLPart::FindLinksOnly, this); - if(m_part->findTextNext()) - { - status = i18n("Link found: \"%1\"."); - } - else - { - if(increase) KNotifyClient::beep(); - status = i18n("Link not found: \"%1\"."); - } - } - else - { - m_part->findText(d->findString, KHTMLPart::FindNoPopups, this); - if(m_part->findTextNext()) - { - status = i18n("Text found: \"%1\"."); - } - else - { - if(increase) KNotifyClient::beep(); - status = i18n("Text not found: \"%1\"."); - } - } - - m_part->setStatusBarText(status.arg(d->findString.lower()), - KHTMLPart::BarDefaultText); -} - -void KHTMLView::updateFindAheadTimeout() -{ - if( d->typeAheadActivated ) - d->timer.start( 3000, true ); -} - -#endif // KHTML_NO_TYPE_AHEAD_FIND - -void KHTMLView::keyReleaseEvent(TQKeyEvent *_ke) -{ -#ifndef KHTML_NO_TYPE_AHEAD_FIND - if(d->typeAheadActivated) { - _ke->accept(); - return; - } -#endif - if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) { - //caretKeyReleaseEvent(_ke); - d->m_caretViewContext->keyReleasePending = false; - return; - } - - if( d->scrollSuspendPreActivate && _ke->key() != Key_Shift ) - d->scrollSuspendPreActivate = false; - if( _ke->key() == Key_Shift && d->scrollSuspendPreActivate && _ke->state() == TQt::ShiftButton - && !(TDEApplication::keyboardMouseState() & TQt::ShiftButton)) - { - if (d->scrollTimerId) - { - d->scrollSuspended = !d->scrollSuspended; -#ifndef NO_SMOOTH_SCROLL_HACK - if( d->scrollSuspended ) - stopScrolling(); -#endif - } - } - - if (d->accessKeysEnabled) - { - if (d->accessKeysPreActivate && _ke->key() != Key_Control) - d->accessKeysPreActivate=false; - if (d->accessKeysPreActivate && _ke->state() == TQt::ControlButton && !(TDEApplication::keyboardMouseState() & TQt::ControlButton)) - { - displayAccessKeys(); - m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText); - d->accessKeysActivated = true; - d->accessKeysPreActivate = false; - _ke->accept(); - return; - } - else if (d->accessKeysActivated) - { - accessKeysTimeout(); - _ke->accept(); - return; - } - } - - // Send keyup event - if ( dispatchKeyEvent( _ke ) ) - { - _ke->accept(); - return; - } - - TQScrollView::keyReleaseEvent(_ke); -} - -void KHTMLView::contentsContextMenuEvent ( TQContextMenuEvent * /*ce*/ ) -{ -// ### what kind of c*** is that ? -#if 0 - if (!m_part->xmlDocImpl()) return; - int xm = _ce->x(); - int ym = _ce->y(); - - DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove ); // ### not a mouse event! - m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev ); - - NodeImpl *targetNode = mev.innerNode.handle(); - if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) { - int absx = 0; - int absy = 0; - targetNode->renderer()->absolutePosition(absx,absy); - TQPoint pos(xm-absx,ym-absy); - - TQWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget(); - TQContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state()); - setIgnoreEvents(true); - TQApplication::sendEvent(w,&cme); - setIgnoreEvents(false); - } -#endif -} - -bool KHTMLView::focusNextPrevChild( bool next ) -{ - // Now try to find the next child - if (m_part->xmlDocImpl() && focusNextPrevNode(next)) - { - if (m_part->xmlDocImpl()->focusNode()) - kdDebug() << "focusNode.name: " - << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl; - return true; // focus node found - } - - // If we get here, pass tabbing control up to the next/previous child in our parent - d->pseudoFocusNode = KHTMLViewPrivate::PFNone; - if (m_part->parentPart() && m_part->parentPart()->view()) - return m_part->parentPart()->view()->focusNextPrevChild(next); - - return TQWidget::focusNextPrevChild(next); -} - -void KHTMLView::doAutoScroll() -{ - TQPoint pos = TQCursor::pos(); - pos = viewport()->mapFromGlobal( pos ); - - int xm, ym; - viewportToContents(pos.x(), pos.y(), xm, ym); - - pos = TQPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y()); - if ( (pos.y() < 0) || (pos.y() > visibleHeight()) || - (pos.x() < 0) || (pos.x() > visibleWidth()) ) - { - ensureVisible( xm, ym, 0, 5 ); - -#ifndef KHTML_NO_SELECTION - // extend the selection while scrolling - DOM::Node innerNode; - if (m_part->isExtendingSelection()) { - RenderObject::NodeInfo renderInfo(true/*readonly*/, false/*active*/); - m_part->xmlDocImpl()->renderer()->layer() - ->nodeAtPoint(renderInfo, xm, ym); - innerNode = renderInfo.innerNode(); - }/*end if*/ - - if (innerNode.handle() && innerNode.handle()->renderer()) { - int absX, absY; - innerNode.handle()->renderer()->absolutePosition(absX, absY); - - m_part->extendSelectionTo(xm, ym, absX, absY, innerNode); - }/*end if*/ -#endif // KHTML_NO_SELECTION - } -} - - -class HackWidget : public TQWidget -{ - public: - inline void setNoErase() { setWFlags(getWFlags()|WRepaintNoErase); } -}; - -bool KHTMLView::eventFilter(TQObject *o, TQEvent *e) -{ - if ( e->type() == TQEvent::AccelOverride ) { - TQKeyEvent* ke = (TQKeyEvent*) e; -//kdDebug(6200) << "TQEvent::AccelOverride" << endl; - if (m_part->isEditable() || m_part->isCaretMode() - || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode() - && m_part->xmlDocImpl()->focusNode()->contentEditable())) { -//kdDebug(6200) << "editable/navigable" << endl; - if ( (ke->state() & ControlButton) || (ke->state() & ShiftButton) ) { - switch ( ke->key() ) { - case Key_Left: - case Key_Right: - case Key_Up: - case Key_Down: - case Key_Home: - case Key_End: - ke->accept(); -//kdDebug(6200) << "eaten" << endl; - return true; - default: - break; - } - } - } - } - - if ( e->type() == TQEvent::Leave ) { - if ( d->cursor_icon_widget ) - d->cursor_icon_widget->hide(); - m_part->resetHoverText(); - } - - TQWidget *view = viewport(); - - if (TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(view)) { - // we need to install an event filter on all children of the viewport to - // be able to get correct stacking of children within the document. - if(e->type() == TQEvent::ChildInserted) { - TQObject *c = TQT_TQOBJECT(TQT_TQCHILDEVENT(e)->child()); - if (c->isWidgetType()) { - TQWidget *w = TQT_TQWIDGET(c); - // don't install the event filter on toplevels - if (w->parentWidget(true) == view) { - if (!strcmp(w->name(), "__khtml")) { - w->installEventFilter(this); - w->unsetCursor(); - if (!::tqqt_cast<TQFrame*>(w)) - w->setBackgroundMode( TQWidget::NoBackground ); - static_cast<HackWidget *>(w)->setNoErase(); - if (!w->childrenListObject().isEmpty()) { - TQObjectListIterator it(w->childrenListObject()); - for (; it.current(); ++it) { - TQWidget *widget = ::tqqt_cast<TQWidget *>(it.current()); - if (widget && !widget->isTopLevel()) { - if (!::tqqt_cast<TQFrame*>(w)) - widget->setBackgroundMode( TQWidget::NoBackground ); - static_cast<HackWidget *>(widget)->setNoErase(); - widget->installEventFilter(this); - } - } - } - } - } - } - } - } else if (o->isWidgetType()) { - TQWidget *v = TQT_TQWIDGET(o); - TQWidget *c = v; - while (v && v != view) { - c = v; - v = v->parentWidget(true); - } - - if (v && !strcmp(c->name(), "__khtml")) { - bool block = false; - TQWidget *w = TQT_TQWIDGET(o); - switch(e->type()) { - case TQEvent::Paint: - if (!allowWidgetPaintEvents) { - // eat the event. Like this we can control exactly when the widget - // get's repainted. - block = true; - int x = 0, y = 0; - TQWidget *v = w; - while (v && v != view) { - x += v->x(); - y += v->y(); - v = v->parentWidget(); - } - viewportToContents( x, y, x, y ); - TQPaintEvent *pe = TQT_TQPAINTEVENT(e); - bool asap = !d->contentsMoving && ::tqqt_cast<TQScrollView *>(c); - - // TQScrollView needs fast repaints - if ( asap && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() && - !static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) { - repaintContents(x + pe->rect().x(), y + pe->rect().y(), - pe->rect().width(), pe->rect().height(), true); - } else { - scheduleRepaint(x + pe->rect().x(), y + pe->rect().y(), - pe->rect().width(), pe->rect().height(), asap); - } - } - break; - case TQEvent::MouseMove: - case TQEvent::MouseButtonPress: - case TQEvent::MouseButtonRelease: - case TQEvent::MouseButtonDblClick: { - if ( (w->parentWidget() == view || ::tqqt_cast<TQScrollView*>(c)) && !::tqqt_cast<TQScrollBar *>(w)) { - TQMouseEvent *me = TQT_TQMOUSEEVENT(e); - TQPoint pt = w->mapTo( view, me->pos()); - TQMouseEvent me2(me->type(), pt, me->button(), me->state()); - - if (e->type() == TQEvent::MouseMove) - viewportMouseMoveEvent(&me2); - else if(e->type() == TQEvent::MouseButtonPress) - viewportMousePressEvent(&me2); - else if(e->type() == TQEvent::MouseButtonRelease) - viewportMouseReleaseEvent(&me2); - else - viewportMouseDoubleClickEvent(&me2); - block = true; - } - break; - } - case TQEvent::KeyPress: - case TQEvent::KeyRelease: - if (w->parentWidget() == view && !::tqqt_cast<TQScrollBar *>(w)) { - TQKeyEvent *ke = TQT_TQKEYEVENT(e); - if (e->type() == TQEvent::KeyPress) - keyPressEvent(ke); - else - keyReleaseEvent(ke); - block = true; - } - default: - break; - } - if (block) { - //tqDebug("eating event"); - return true; - } - } - } - -// kdDebug(6000) <<"passing event on to sv event filter object=" << o->className() << " event=" << e->type() << endl; - return TQScrollView::eventFilter(o, e); -} - - -DOM::NodeImpl *KHTMLView::nodeUnderMouse() const -{ - return d->underMouse; -} - -DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const -{ - return d->underMouseNonShared; -} - -bool KHTMLView::scrollTo(const TQRect &bounds) -{ - d->scrollingSelf = true; // so scroll events get ignored - - int x, y, xe, ye; - x = bounds.left(); - y = bounds.top(); - xe = bounds.right(); - ye = bounds.bottom(); - - //kdDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y<<endl; - - int deltax; - int deltay; - - int curHeight = visibleHeight(); - int curWidth = visibleWidth(); - - if (ye-y>curHeight-d->borderY) - ye = y + curHeight - d->borderY; - - if (xe-x>curWidth-d->borderX) - xe = x + curWidth - d->borderX; - - // is xpos of target left of the view's border? - if (x < contentsX() + d->borderX ) - deltax = x - contentsX() - d->borderX; - // is xpos of target right of the view's right border? - else if (xe + d->borderX > contentsX() + curWidth) - deltax = xe + d->borderX - ( contentsX() + curWidth ); - else - deltax = 0; - - // is ypos of target above upper border? - if (y < contentsY() + d->borderY) - deltay = y - contentsY() - d->borderY; - // is ypos of target below lower border? - else if (ye + d->borderY > contentsY() + curHeight) - deltay = ye + d->borderY - ( contentsY() + curHeight ); - else - deltay = 0; - - int maxx = curWidth-d->borderX; - int maxy = curHeight-d->borderY; - - int scrollX,scrollY; - - scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx); - scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy); - - if (contentsX() + scrollX < 0) - scrollX = -contentsX(); - else if (contentsWidth() - visibleWidth() - contentsX() < scrollX) - scrollX = contentsWidth() - visibleWidth() - contentsX(); - - if (contentsY() + scrollY < 0) - scrollY = -contentsY(); - else if (contentsHeight() - visibleHeight() - contentsY() < scrollY) - scrollY = contentsHeight() - visibleHeight() - contentsY(); - - scrollBy(scrollX, scrollY); - - d->scrollingSelf = false; - - if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) ) - return true; - else return false; - -} - -bool KHTMLView::focusNextPrevNode(bool next) -{ - // Sets the focus node of the document to be the node after (or if - // next is false, before) the current focus node. Only nodes that - // are selectable (i.e. for which isFocusable() returns true) are - // taken into account, and the order used is that specified in the - // HTML spec (see DocumentImpl::nextFocusNode() and - // DocumentImpl::previousFocusNode() for details). - - DocumentImpl *doc = m_part->xmlDocImpl(); - NodeImpl *oldFocusNode = doc->focusNode(); - - // See whether we're in the middle of detach. If so, we want to - // clear focus... The document code will be careful to not - // emit events in that case.. - if (oldFocusNode && oldFocusNode->renderer() && - !oldFocusNode->renderer()->parent()) { - doc->setFocusNode(0); - return true; - } - -#if 1 - // If the user has scrolled the document, then instead of picking - // the next focusable node in the document, use the first one that - // is within the visible area (if possible). - if (d->scrollBarMoved) - { - NodeImpl *toFocus; - if (next) - toFocus = doc->nextFocusNode(oldFocusNode); - else - toFocus = doc->previousFocusNode(oldFocusNode); - - if (!toFocus && oldFocusNode) - if (next) - toFocus = doc->nextFocusNode(NULL); - else - toFocus = doc->previousFocusNode(NULL); - - while (toFocus && toFocus != oldFocusNode) - { - - TQRect focusNodeRect = toFocus->getRect(); - if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) && - (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) { - { - TQRect r = toFocus->getRect(); - ensureVisible( r.right(), r.bottom()); - ensureVisible( r.left(), r.top()); - d->scrollBarMoved = false; - d->tabMovePending = false; - d->lastTabbingDirection = next; - d->pseudoFocusNode = KHTMLViewPrivate::PFNone; - m_part->xmlDocImpl()->setFocusNode(toFocus); - Node guard(toFocus); - if (!toFocus->hasOneRef() ) - { - emit m_part->nodeActivated(Node(toFocus)); - } - return true; - } - } - if (next) - toFocus = doc->nextFocusNode(toFocus); - else - toFocus = doc->previousFocusNode(toFocus); - - if (!toFocus && oldFocusNode) - if (next) - toFocus = doc->nextFocusNode(NULL); - else - toFocus = doc->previousFocusNode(NULL); - } - - d->scrollBarMoved = false; - } -#endif - - if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone) - { - ensureVisible(contentsX(), next?0:contentsHeight()); - d->scrollBarMoved = false; - d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom; - return true; - } - - NodeImpl *newFocusNode = NULL; - - if (d->tabMovePending && next != d->lastTabbingDirection) - { - //kdDebug ( 6000 ) << " tab move pending and tabbing direction changed!\n"; - newFocusNode = oldFocusNode; - } - else if (next) - { - if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop ) - newFocusNode = doc->nextFocusNode(oldFocusNode); - } - else - { - if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom ) - newFocusNode = doc->previousFocusNode(oldFocusNode); - } - - bool targetVisible = false; - if (!newFocusNode) - { - if ( next ) - { - targetVisible = scrollTo(TQRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0)); - } - else - { - targetVisible = scrollTo(TQRect(contentsX()+visibleWidth()/2,d->borderY,0,0)); - } - } - else - { -#ifndef KHTML_NO_CARET - // if it's an editable element, activate the caret - if (!m_part->isCaretMode() && !m_part->isEditable() - && newFocusNode->contentEditable()) { - d->caretViewContext(); - moveCaretTo(newFocusNode, 0L, true); - } else { - caretOff(); - } -#endif // KHTML_NO_CARET - - targetVisible = scrollTo(newFocusNode->getRect()); - } - - if (targetVisible) - { - //kdDebug ( 6000 ) << " target reached.\n"; - d->tabMovePending = false; - - m_part->xmlDocImpl()->setFocusNode(newFocusNode); - if (newFocusNode) - { - Node guard(newFocusNode); - if (!newFocusNode->hasOneRef() ) - { - emit m_part->nodeActivated(Node(newFocusNode)); - } - return true; - } - else - { - d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop; - return false; - } - } - else - { - if (!d->tabMovePending) - d->lastTabbingDirection = next; - d->tabMovePending = true; - return true; - } -} - -void KHTMLView::displayAccessKeys() -{ - TQValueVector< TQChar > taken; - displayAccessKeys( NULL, this, taken, false ); - displayAccessKeys( NULL, this, taken, true ); -} - -void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, TQValueVector< TQChar >& taken, bool use_fallbacks ) -{ - TQMap< ElementImpl*, TQChar > fallbacks; - if( use_fallbacks ) - fallbacks = buildFallbackAccessKeys(); - for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) { - if( n->isElementNode()) { - ElementImpl* en = static_cast< ElementImpl* >( n ); - DOMString s = en->getAttribute( ATTR_ACCESSKEY ); - TQString accesskey; - if( s.length() == 1 ) { - TQChar a = s.string()[ 0 ].upper(); - if( tqFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains - accesskey = a; - } - if( accesskey.isNull() && fallbacks.contains( en )) { - TQChar a = fallbacks[ en ].upper(); - if( tqFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains - accesskey = TQString( "<qt><i>" ) + a + "</i></qt>"; - } - if( !accesskey.isNull()) { - TQRect rec=en->getRect(); - TQLabel *lab=new TQLabel(accesskey,viewport(),0,(WFlags)WDestructiveClose); - connect( origview, TQT_SIGNAL(hideAccessKeys()), lab, TQT_SLOT(close()) ); - connect( this, TQT_SIGNAL(repaintAccessKeys()), lab, TQT_SLOT(repaint())); - lab->setPalette(TQToolTip::palette()); - lab->setLineWidth(2); - lab->setFrameStyle(TQFrame::Box | TQFrame::Plain); - lab->setMargin(3); - lab->adjustSize(); - addChild(lab, - KMIN(rec.left()+rec.width()/2, contentsWidth() - lab->width()), - KMIN(rec.top()+rec.height()/2, contentsHeight() - lab->height())); - showChild(lab); - taken.append( accesskey[ 0 ] ); - } - } - } - if( use_fallbacks ) - return; - TQPtrList<KParts::ReadOnlyPart> frames = m_part->frames(); - for( TQPtrListIterator<KParts::ReadOnlyPart> it( frames ); - it != NULL; - ++it ) { - if( !(*it)->inherits( "KHTMLPart" )) - continue; - KHTMLPart* part = static_cast< KHTMLPart* >( *it ); - if( part->view() && part->view() != caller ) - part->view()->displayAccessKeys( this, origview, taken, use_fallbacks ); - } - // pass up to the parent - if (m_part->parentPart() && m_part->parentPart()->view() - && m_part->parentPart()->view() != caller) - m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks ); -} - - - -void KHTMLView::accessKeysTimeout() -{ -d->accessKeysActivated=false; -d->accessKeysPreActivate = false; -m_part->setStatusBarText(TQString::null, KHTMLPart::BarOverrideText); -emit hideAccessKeys(); -} - -// Handling of the HTML accesskey attribute. -bool KHTMLView::handleAccessKey( const TQKeyEvent* ev ) -{ -// Qt interprets the keyevent also with the modifiers, and ev->text() matches that, -// but this code must act as if the modifiers weren't pressed - TQChar c; - if( ev->key() >= Key_A && ev->key() <= Key_Z ) - c = 'A' + ev->key() - Key_A; - else if( ev->key() >= Key_0 && ev->key() <= Key_9 ) - c = '0' + ev->key() - Key_0; - else { - // TODO fake XKeyEvent and XLookupString ? - // This below seems to work e.g. for eacute though. - if( ev->text().length() == 1 ) - c = ev->text()[ 0 ]; - } - if( c.isNull()) - return false; - return focusNodeWithAccessKey( c ); -} - -bool KHTMLView::focusNodeWithAccessKey( TQChar c, KHTMLView* caller ) -{ - DocumentImpl *doc = m_part->xmlDocImpl(); - if( !doc ) - return false; - ElementImpl* node = doc->findAccessKeyElement( c ); - if( !node ) { - TQPtrList<KParts::ReadOnlyPart> frames = m_part->frames(); - for( TQPtrListIterator<KParts::ReadOnlyPart> it( frames ); - it != NULL; - ++it ) { - if( !(*it)->inherits( "KHTMLPart" )) - continue; - KHTMLPart* part = static_cast< KHTMLPart* >( *it ); - if( part->view() && part->view() != caller - && part->view()->focusNodeWithAccessKey( c, this )) - return true; - } - // pass up to the parent - if (m_part->parentPart() && m_part->parentPart()->view() - && m_part->parentPart()->view() != caller - && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this )) - return true; - if( caller == NULL ) { // the active frame (where the accesskey was pressed) - TQMap< ElementImpl*, TQChar > fallbacks = buildFallbackAccessKeys(); - for( TQMap< ElementImpl*, TQChar >::ConstIterator it = fallbacks.begin(); - it != fallbacks.end(); - ++it ) - if( *it == c ) { - node = it.key(); - break; - } - } - if( node == NULL ) - return false; - } - - // Scroll the view as necessary to ensure that the new focus node is visible -#ifndef KHTML_NO_CARET - // if it's an editable element, activate the caret - if (!m_part->isCaretMode() && !m_part->isEditable() - && node->contentEditable()) { - d->caretViewContext(); - moveCaretTo(node, 0L, true); - } else { - caretOff(); - } -#endif // KHTML_NO_CARET - - TQRect r = node->getRect(); - ensureVisible( r.right(), r.bottom()); - ensureVisible( r.left(), r.top()); - - Node guard( node ); - if( node->isFocusable()) { - if (node->id()==ID_LABEL) { - // if Accesskey is a label, give focus to the label's referrer. - node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement()); - if (!node) return true; - guard = node; - } - // Set focus node on the document -#ifdef USE_QT4 - m_part->xmlDocImpl()->setFocusNode(node); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Shortcut ); - m_part->xmlDocImpl()->setFocusNode(node); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - if( node != NULL && node->hasOneRef()) // deleted, only held by guard - return true; - emit m_part->nodeActivated(Node(node)); - if( node != NULL && node->hasOneRef()) - return true; - } - - switch( node->id()) { - case ID_A: - static_cast< HTMLAnchorElementImpl* >( node )->click(); - break; - case ID_INPUT: - static_cast< HTMLInputElementImpl* >( node )->click(); - break; - case ID_BUTTON: - static_cast< HTMLButtonElementImpl* >( node )->click(); - break; - case ID_AREA: - static_cast< HTMLAreaElementImpl* >( node )->click(); - break; - case ID_TEXTAREA: - break; // just focusing it is enough - case ID_LEGEND: - // TODO - break; - } - return true; -} - -static TQString getElementText( NodeImpl* start, bool after ) -{ - TQString ret; // nextSibling(), to go after e.g. </select> - for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode(); - n != NULL; - n = after ? n->traverseNextNode() : n->traversePreviousNode()) { - if( n->isTextNode()) { - if( after ) - ret += static_cast< TextImpl* >( n )->toString().string(); - else - ret.prepend( static_cast< TextImpl* >( n )->toString().string()); - } else { - switch( n->id()) { - case ID_A: - case ID_FONT: - case ID_TT: - case ID_U: - case ID_B: - case ID_I: - case ID_S: - case ID_STRIKE: - case ID_BIG: - case ID_SMALL: - case ID_EM: - case ID_STRONG: - case ID_DFN: - case ID_CODE: - case ID_SAMP: - case ID_KBD: - case ID_VAR: - case ID_CITE: - case ID_ABBR: - case ID_ACRONYM: - case ID_SUB: - case ID_SUP: - case ID_SPAN: - case ID_NOBR: - case ID_WBR: - break; - case ID_TD: - if( ret.stripWhiteSpace().isEmpty()) - break; - // fall through - default: - return ret.simplifyWhiteSpace(); - } - } - } - return ret.simplifyWhiteSpace(); -} - -static TQMap< NodeImpl*, TQString > buildLabels( NodeImpl* start ) -{ - TQMap< NodeImpl*, TQString > ret; - for( NodeImpl* n = start; - n != NULL; - n = n->traverseNextNode()) { - if( n->id() == ID_LABEL ) { - HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n ); - NodeImpl* labelfor = label->getFormElement(); - if( labelfor ) - ret[ labelfor ] = label->innerText().string().simplifyWhiteSpace(); - } - } - return ret; -} - -namespace khtml { -struct AccessKeyData { - ElementImpl* element; - TQString text; - TQString url; - int priority; // 10(highest) - 0(lowest) -}; -} - -TQMap< ElementImpl*, TQChar > KHTMLView::buildFallbackAccessKeys() const -{ - // build a list of all possible candidate elements that could use an accesskey - TQValueList< AccessKeyData > data; - TQMap< NodeImpl*, TQString > labels = buildLabels( m_part->xmlDocImpl()); - for( NodeImpl* n = m_part->xmlDocImpl(); - n != NULL; - n = n->traverseNextNode()) { - if( n->isElementNode()) { - ElementImpl* element = static_cast< ElementImpl* >( n ); - if( element->getAttribute( ATTR_ACCESSKEY ).length() == 1 ) - continue; // has accesskey set, ignore - if( element->renderer() == NULL ) - continue; // not visible - TQString text; - TQString url; - int priority = 0; - bool ignore = false; - bool text_after = false; - bool text_before = false; - switch( element->id()) { - case ID_A: - url = khtml::parseURL(element->getAttribute(ATTR_HREF)).string(); - if( url.isEmpty()) // doesn't have href, it's only an anchor - continue; - text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace(); - priority = 2; - break; - case ID_INPUT: { - HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element ); - switch( in->inputType()) { - case HTMLInputElementImpl::SUBMIT: - text = in->value().string(); - if( text.isEmpty()) - text = i18n( "Submit" ); - priority = 7; - break; - case HTMLInputElementImpl::IMAGE: - text = in->altText().string(); - priority = 7; - break; - case HTMLInputElementImpl::BUTTON: - text = in->value().string(); - priority = 5; - break; - case HTMLInputElementImpl::RESET: - text = in->value().string(); - if( text.isEmpty()) - text = i18n( "Reset" ); - priority = 5; - break; - case HTMLInputElementImpl::HIDDEN: - ignore = true; - break; - case HTMLInputElementImpl::CHECKBOX: - case HTMLInputElementImpl::RADIO: - text_after = true; - priority = 5; - break; - case HTMLInputElementImpl::TEXT: - case HTMLInputElementImpl::PASSWORD: - case HTMLInputElementImpl::FILE: - text_before = true; - priority = 5; - break; - default: - priority = 5; - break; - } - break; - } - case ID_BUTTON: - text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace(); - switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) { - case HTMLButtonElementImpl::SUBMIT: - if( text.isEmpty()) - text = i18n( "Submit" ); - priority = 7; - break; - case HTMLButtonElementImpl::RESET: - if( text.isEmpty()) - text = i18n( "Reset" ); - priority = 5; - break; - default: - priority = 5; - break; - break; - } - case ID_SELECT: // these don't have accesskey attribute, but quick access may be handy - text_before = true; - text_after = true; - priority = 5; - break; - case ID_FRAME: - ignore = true; - break; - default: - ignore = !element->isFocusable(); - priority = 2; - break; - } - if( ignore ) - continue; - if( text.isNull() && labels.contains( element )) - text = labels[ element ]; - if( text.isNull() && text_before ) - text = getElementText( element, false ); - if( text.isNull() && text_after ) - text = getElementText( element, true ); - text = text.stripWhiteSpace(); - // increase priority of items which have explicitly specified accesskeys in the config - TQValueList< TQPair< TQString, TQChar > > priorities - = m_part->settings()->fallbackAccessKeysAssignments(); - for( TQValueList< TQPair< TQString, TQChar > >::ConstIterator it = priorities.begin(); - it != priorities.end(); - ++it ) { - if( text == (*it).first ) - priority = 10; - } - AccessKeyData tmp = { element, text, url, priority }; - data.append( tmp ); - } - } - - TQValueList< TQChar > keys; - for( char c = 'A'; c <= 'Z'; ++c ) - keys << c; - for( char c = '0'; c <= '9'; ++c ) - keys << c; - for( NodeImpl* n = m_part->xmlDocImpl(); - n != NULL; - n = n->traverseNextNode()) { - if( n->isElementNode()) { - ElementImpl* en = static_cast< ElementImpl* >( n ); - DOMString s = en->getAttribute( ATTR_ACCESSKEY ); - if( s.length() == 1 ) { - TQChar c = s.string()[ 0 ].upper(); - keys.remove( c ); // remove manually assigned accesskeys - } - } - } - - TQMap< ElementImpl*, TQChar > ret; - for( int priority = 10; - priority >= 0; - --priority ) { - for( TQValueList< AccessKeyData >::Iterator it = data.begin(); - it != data.end(); - ) { - if( (*it).priority != priority ) { - ++it; - continue; - } - if( keys.isEmpty()) - break; - TQString text = (*it).text; - TQChar key; - if( key.isNull() && !text.isEmpty()) { - TQValueList< TQPair< TQString, TQChar > > priorities - = m_part->settings()->fallbackAccessKeysAssignments(); - for( TQValueList< TQPair< TQString, TQChar > >::ConstIterator it = priorities.begin(); - it != priorities.end(); - ++it ) - if( text == (*it).first && keys.contains( (*it).second )) { - key = (*it).second; - break; - } - } - // try first to select the first character as the accesskey, - // then first character of the following words, - // and then simply the first free character - if( key.isNull() && !text.isEmpty()) { - TQStringList words = TQStringList::split( ' ', text ); - for( TQStringList::ConstIterator it = words.begin(); - it != words.end(); - ++it ) { - if( keys.contains( (*it)[ 0 ].upper())) { - key = (*it)[ 0 ].upper(); - break; - } - } - } - if( key.isNull() && !text.isEmpty()) { - for( unsigned int i = 0; - i < text.length(); - ++i ) { - if( keys.contains( text[ i ].upper())) { - key = text[ i ].upper(); - break; - } - } - } - if( key.isNull()) - key = keys.front(); - ret[ (*it).element ] = key; - keys.remove( key ); - TQString url = (*it).url; - it = data.remove( it ); - // assign the same accesskey also to other elements pointing to the same url - if( !url.isEmpty() && !url.startsWith( "javascript:", false )) { - for( TQValueList< AccessKeyData >::Iterator it2 = data.begin(); - it2 != data.end(); - ) { - if( (*it2).url == url ) { - ret[ (*it2).element ] = key; - if( it == it2 ) - ++it; - it2 = data.remove( it2 ); - } else - ++it2; - } - } - } - } - return ret; -} - -void KHTMLView::setMediaType( const TQString &medium ) -{ - m_medium = medium; -} - -TQString KHTMLView::mediaType() const -{ - return m_medium; -} - -bool KHTMLView::pagedMode() const -{ - return d->paged; -} - -void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis) -{ - if (vis) { - d->visibleWidgets.replace(w, w->widget()); - } - else - d->visibleWidgets.remove(w); -} - -bool KHTMLView::needsFullRepaint() const -{ - return d->needsFullRepaint; -} - -void KHTMLView::print() -{ - print( false ); -} - -void KHTMLView::print(bool quick) -{ - if(!m_part->xmlDocImpl()) return; - khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer()); - if(!root) return; - - KPrinter *printer = new KPrinter(true, TQPrinter::ScreenResolution); - printer->addDialogPage(new KHTMLPrintSettings()); - TQString docname = m_part->xmlDocImpl()->URL().prettyURL(); - if ( !docname.isEmpty() ) - docname = KStringHandler::csqueeze(docname, 80); - if(quick || printer->setup(this, i18n("Print %1").arg(docname))) { - viewport()->setCursor( tqwaitCursor ); // only viewport(), no TQApplication::, otherwise we get the busy cursor in tdeprint's dialogs - // set up KPrinter - printer->setFullPage(false); - printer->setCreator(TQString("KDE %1.%2.%3 HTML Library").arg(TDE_VERSION_MAJOR).arg(TDE_VERSION_MINOR).arg(TDE_VERSION_RELEASE)); - printer->setDocName(docname); - - TQPainter *p = new TQPainter; - p->begin( printer ); - khtml::setPrintPainter( p ); - - m_part->xmlDocImpl()->setPaintDevice( printer ); - TQString oldMediaType = mediaType(); - setMediaType( "print" ); - // We ignore margin settings for html and body when printing - // and use the default margins from the print-system - // (In Qt 3.0.x the default margins are hardcoded in Qt) - m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-khtml-printfriendly") == "true" ? - "* { background-image: none !important;" - " background-color: white !important;" - " color: black !important; }" - "body { margin: 0px !important; }" - "html { margin: 0px !important; }" : - "body { margin: 0px !important; }" - "html { margin: 0px !important; }" - ); - - TQPaintDeviceMetrics metrics( printer ); - - kdDebug(6000) << "printing: physical page width = " << metrics.width() - << " height = " << metrics.height() << endl; - root->setStaticMode(true); - root->setPagedMode(true); - root->setWidth(metrics.width()); -// root->setHeight(metrics.height()); - root->setPageTop(0); - root->setPageBottom(0); - d->paged = true; - - m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100); - m_part->xmlDocImpl()->updateStyleSelector(); - root->setPrintImages( printer->option("app-khtml-printimages") == "true"); - root->makePageBreakAvoidBlocks(); - - root->setNeedsLayoutAndMinMaxRecalc(); - root->layout(); - khtml::RenderWidget::flushWidgetResizes(); // make sure widgets have their final size - - // check sizes ask for action.. (scale or clip) - - bool printHeader = (printer->option("app-khtml-printheader") == "true"); - - int headerHeight = 0; - TQFont headerFont("Sans Serif", 8); - - TQString headerLeft = TDEGlobal::locale()->formatDate(TQDate::currentDate(),true); - TQString headerMid = docname; - TQString headerRight; - - if (printHeader) - { - p->setFont(headerFont); - headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2; - } - - // ok. now print the pages. - kdDebug(6000) << "printing: html page width = " << root->docWidth() - << " height = " << root->docHeight() << endl; - kdDebug(6000) << "printing: margins left = " << printer->margins().width() - << " top = " << printer->margins().height() << endl; - kdDebug(6000) << "printing: paper width = " << metrics.width() - << " height = " << metrics.height() << endl; - // if the width is too large to fit on the paper we just scale - // the whole thing. - int pageWidth = metrics.width(); - int pageHeight = metrics.height(); - p->setClipRect(0,0, pageWidth, pageHeight); - - pageHeight -= headerHeight; - - bool scalePage = false; - double scale = 0.0; -#ifndef QT_NO_TRANSFORMATIONS - if(root->docWidth() > metrics.width()) { - scalePage = true; - scale = ((double) metrics.width())/((double) root->docWidth()); - pageHeight = (int) (pageHeight/scale); - pageWidth = (int) (pageWidth/scale); - headerHeight = (int) (headerHeight/scale); - } -#endif - kdDebug(6000) << "printing: scaled html width = " << pageWidth - << " height = " << pageHeight << endl; - - root->setHeight(pageHeight); - root->setPageBottom(pageHeight); - root->setNeedsLayout(true); - root->layoutIfNeeded(); -// m_part->slotDebugRenderTree(); - - // Squeeze header to make it it on the page. - if (printHeader) - { - int available_width = metrics.width() - 10 - - 2 * kMax(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(), - p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width()); - if (available_width < 150) - available_width = 150; - int mid_width; - int squeeze = 120; - do { - headerMid = KStringHandler::csqueeze(docname, squeeze); - mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width(); - squeeze -= 10; - } while (mid_width > available_width); - } - - int top = 0; - int bottom = 0; - int page = 1; - while(top < root->docHeight()) { - if(top > 0) printer->newPage(); - p->setClipRect(0, 0, pageWidth, headerHeight, TQPainter::CoordDevice); - if (printHeader) - { - int dy = p->fontMetrics().lineSpacing(); - p->setPen(Qt::black); - p->setFont(headerFont); - - headerRight = TQString("#%1").arg(page); - - p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft); - p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid); - p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight); - } - - -#ifndef QT_NO_TRANSFORMATIONS - if (scalePage) - p->scale(scale, scale); -#endif - - p->setClipRect(0, headerHeight, pageWidth, pageHeight, TQPainter::CoordDevice); - p->translate(0, headerHeight-top); - - bottom = top+pageHeight; - - root->setPageTop(top); - root->setPageBottom(bottom); - root->setPageNumber(page); - - root->layer()->paint(p, TQRect(0, top, pageWidth, pageHeight)); -// m_part->xmlDocImpl()->renderer()->layer()->paint(p, TQRect(0, top, pageWidth, pageHeight)); -// root->repaint(); -// p->flush(); - kdDebug(6000) << "printed: page " << page <<" bottom At = " << bottom << endl; - - top = bottom; - p->resetXForm(); - page++; - } - - p->end(); - delete p; - - // and now reset the layout to the usual one... - root->setPagedMode(false); - root->setStaticMode(false); - d->paged = false; - khtml::setPrintPainter( 0 ); - setMediaType( oldMediaType ); - m_part->xmlDocImpl()->setPaintDevice( TQT_TQPAINTDEVICE(this) ); - m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor()); - m_part->xmlDocImpl()->updateStyleSelector(); - viewport()->unsetCursor(); - } - delete printer; -} - -void KHTMLView::slotPaletteChanged() -{ - if(!m_part->xmlDocImpl()) return; - DOM::DocumentImpl *document = m_part->xmlDocImpl(); - if (!document->isHTMLDocument()) return; - khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer()); - if(!root) return; - root->style()->resetPalette(); - NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body(); - if(!body) return; - body->setChanged(true); - body->recalcStyle( NodeImpl::Force ); -} - -void KHTMLView::paint(TQPainter *p, const TQRect &rc, int yOff, bool *more) -{ - if(!m_part->xmlDocImpl()) return; - khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer()); - if(!root) return; - - m_part->xmlDocImpl()->setPaintDevice(p->device()); - root->setPagedMode(true); - root->setStaticMode(true); - root->setWidth(rc.width()); - - p->save(); - p->setClipRect(rc); - p->translate(rc.left(), rc.top()); - double scale = ((double) rc.width()/(double) root->docWidth()); - int height = (int) ((double) rc.height() / scale); -#ifndef QT_NO_TRANSFORMATIONS - p->scale(scale, scale); -#endif - root->setPageTop(yOff); - root->setPageBottom(yOff+height); - - root->layer()->paint(p, TQRect(0, yOff, root->docWidth(), height)); - if (more) - *more = yOff + height < root->docHeight(); - p->restore(); - - root->setPagedMode(false); - root->setStaticMode(false); - m_part->xmlDocImpl()->setPaintDevice( TQT_TQPAINTDEVICE(this) ); -} - - -void KHTMLView::useSlowRepaints() -{ - d->useSlowRepaints = true; - setStaticBackground(true); -} - - -void KHTMLView::setVScrollBarMode ( ScrollBarMode mode ) -{ -#ifndef KHTML_NO_SCROLLBARS - d->vmode = mode; - TQScrollView::setVScrollBarMode(mode); -#else - Q_UNUSED( mode ); -#endif -} - -void KHTMLView::setHScrollBarMode ( ScrollBarMode mode ) -{ -#ifndef KHTML_NO_SCROLLBARS - d->hmode = mode; - TQScrollView::setHScrollBarMode(mode); -#else - Q_UNUSED( mode ); -#endif -} - -void KHTMLView::restoreScrollBar() -{ - int ow = visibleWidth(); - TQScrollView::setVScrollBarMode(d->vmode); - if (visibleWidth() != ow) - layout(); - d->prevScrollbarVisible = verticalScrollBar()->isVisible(); -} - -TQStringList KHTMLView::formCompletionItems(const TQString &name) const -{ - if (!m_part->settings()->isFormCompletionEnabled()) - return TQStringList(); - if (!d->formCompletions) - d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions")); - return d->formCompletions->readListEntry(name); -} - -void KHTMLView::clearCompletionHistory(const TQString& name) -{ - if (!d->formCompletions) - { - d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions")); - } - d->formCompletions->writeEntry(name, ""); - d->formCompletions->sync(); -} - -void KHTMLView::addFormCompletionItem(const TQString &name, const TQString &value) -{ - if (!m_part->settings()->isFormCompletionEnabled()) - return; - // don't store values that are all numbers or just numbers with - // dashes or spaces as those are likely credit card numbers or - // something similar - bool cc_number(true); - for (unsigned int i = 0; i < value.length(); ++i) - { - TQChar c(value[i]); - if (!c.isNumber() && c != '-' && !c.isSpace()) - { - cc_number = false; - break; - } - } - if (cc_number) - return; - TQStringList items = formCompletionItems(name); - if (!items.contains(value)) - items.prepend(value); - while ((int)items.count() > m_part->settings()->maxFormCompletionItems()) - items.remove(items.fromLast()); - d->formCompletions->writeEntry(name, items); -} - -void KHTMLView::removeFormCompletionItem(const TQString &name, const TQString &value) -{ - if (!m_part->settings()->isFormCompletionEnabled()) - return; - - TQStringList items = formCompletionItems(name); - if (items.remove(value)) - d->formCompletions->writeEntry(name, items); -} - -void KHTMLView::addNonPasswordStorableSite(const TQString& host) -{ - if (!d->formCompletions) { - d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions")); - } - - d->formCompletions->setGroup("NonPasswordStorableSites"); - TQStringList sites = d->formCompletions->readListEntry("Sites"); - sites.append(host); - d->formCompletions->writeEntry("Sites", sites); - d->formCompletions->sync(); - d->formCompletions->setGroup(TQString::null);//reset -} - -bool KHTMLView::nonPasswordStorableSite(const TQString& host) const -{ - if (!d->formCompletions) { - d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions")); - } - d->formCompletions->setGroup("NonPasswordStorableSites"); - TQStringList sites = d->formCompletions->readListEntry("Sites"); - d->formCompletions->setGroup(TQString::null);//reset - - return (sites.find(host) != sites.end()); -} - -// returns true if event should be swallowed -bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode, - DOM::NodeImpl *targetNodeNonShared, bool cancelable, - int detail,TQMouseEvent *_mouse, bool setUnder, - int mouseEventType) -{ - // if the target node is a text node, dispatch on the parent node - rdar://4196646 (and #76948) - if (targetNode && targetNode->isTextNode()) - targetNode = targetNode->parentNode(); - - if (d->underMouse) - d->underMouse->deref(); - d->underMouse = targetNode; - if (d->underMouse) - d->underMouse->ref(); - - if (d->underMouseNonShared) - d->underMouseNonShared->deref(); - d->underMouseNonShared = targetNodeNonShared; - if (d->underMouseNonShared) - d->underMouseNonShared->ref(); - - int exceptioncode = 0; - int pageX = 0; - int pageY = 0; - viewportToContents(_mouse->x(), _mouse->y(), pageX, pageY); - int clientX = pageX - contentsX(); - int clientY = pageY - contentsY(); - int screenX = _mouse->globalX(); - int screenY = _mouse->globalY(); - int button = -1; - switch (_mouse->button()) { - case Qt::LeftButton: - button = 0; - break; - case Qt::MidButton: - button = 1; - break; - case Qt::RightButton: - button = 2; - break; - default: - break; - } - if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1) - d->accessKeysPreActivate=false; - - bool ctrlKey = (_mouse->state() & ControlButton); - bool altKey = (_mouse->state() & AltButton); - bool shiftKey = (_mouse->state() & ShiftButton); - bool metaKey = (_mouse->state() & MetaButton); - - // mouseout/mouseover - if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) { - - // ### this code sucks. we should save the oldUnder instead of calculating - // it again. calculating is expensive! (Dirk) - NodeImpl *oldUnder = 0; - if (d->prevMouseX >= 0 && d->prevMouseY >= 0) { - NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType)); - m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev ); - oldUnder = mev.innerNode.handle(); - - if (oldUnder && oldUnder->isTextNode()) - oldUnder = oldUnder->parentNode(); - } -// tqDebug("oldunder=%p (%s), target=%p (%s) x/y=%d/%d", oldUnder, oldUnder ? oldUnder->renderer()->renderName() : 0, targetNode, targetNode ? targetNode->renderer()->renderName() : 0, _mouse->x(), _mouse->y()); - if (oldUnder != targetNode) { - // send mouseout event to the old node - if (oldUnder){ - oldUnder->ref(); - MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT, - true,true,m_part->xmlDocImpl()->defaultView(), - 0,screenX,screenY,clientX,clientY,pageX, pageY, - ctrlKey,altKey,shiftKey,metaKey, - button,targetNode); - me->ref(); - oldUnder->dispatchEvent(me,exceptioncode,true); - me->deref(); - } - - // send mouseover event to the new node - if (targetNode) { - MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT, - true,true,m_part->xmlDocImpl()->defaultView(), - 0,screenX,screenY,clientX,clientY,pageX, pageY, - ctrlKey,altKey,shiftKey,metaKey, - button,oldUnder); - - me->ref(); - targetNode->dispatchEvent(me,exceptioncode,true); - me->deref(); - } - - if (oldUnder) - oldUnder->deref(); - } - } - - bool swallowEvent = false; - - if (targetNode) { - // send the actual event - bool dblclick = ( eventId == EventImpl::CLICK_EVENT && - _mouse->type() == TQEvent::MouseButtonDblClick ); - MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId), - true,cancelable,m_part->xmlDocImpl()->defaultView(), - detail,screenX,screenY,clientX,clientY,pageX, pageY, - ctrlKey,altKey,shiftKey,metaKey, - button,0, _mouse, dblclick ); - me->ref(); - targetNode->dispatchEvent(me,exceptioncode,true); - bool defaultHandled = me->defaultHandled(); - if (defaultHandled || me->defaultPrevented()) - swallowEvent = true; - me->deref(); - - if (eventId == EventImpl::MOUSEDOWN_EVENT) { - // Focus should be shifted on mouse down, not on a click. -dwh - // Blur current focus node when a link/button is clicked; this - // is expected by some sites that rely on onChange handlers running - // from form fields before the button click is processed. - DOM::NodeImpl* nodeImpl = targetNode; - for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode()); - if (nodeImpl && nodeImpl->isMouseFocusable()) - m_part->xmlDocImpl()->setFocusNode(nodeImpl); - else if (!nodeImpl || !nodeImpl->focused()) - m_part->xmlDocImpl()->setFocusNode(0); - } - } - - return swallowEvent; -} - -void KHTMLView::setIgnoreWheelEvents( bool e ) -{ - d->ignoreWheelEvents = e; -} - -#ifndef QT_NO_WHEELEVENT - -void KHTMLView::viewportWheelEvent(TQWheelEvent* e) -{ - if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false; - - if ( ( e->state() & ControlButton) == ControlButton ) - { - emit zoomView( - e->delta() ); - e->accept(); - } - else if (d->firstRelayout) - { - e->accept(); - } - else if( ( (e->orientation() == Qt::Vertical && - ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible()) - || e->delta() > 0 && contentsY() <= 0 - || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight())) - || - (e->orientation() == Qt::Horizontal && - ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible()) - || e->delta() > 0 && contentsX() <=0 - || e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth()))) - && m_part->parentPart()) - { - if ( m_part->parentPart()->view() ) - m_part->parentPart()->view()->wheelEvent( e ); - e->ignore(); - } - else - { - d->scrollBarMoved = true; -#ifndef NO_SMOOTH_SCROLL_HACK - scrollViewWheelEvent( e ); -#else - TQScrollView::viewportWheelEvent( e ); -#endif - - TQMouseEvent *tempEvent = new TQMouseEvent( TQEvent::MouseMove, TQPoint(-1,-1), TQPoint(-1,-1), Qt::NoButton, e->state() ); - emit viewportMouseMoveEvent ( tempEvent ); - delete tempEvent; - } - -} -#endif - -void KHTMLView::dragEnterEvent( TQDragEnterEvent* ev ) -{ - // Handle drops onto frames (#16820) - // Drops on the main html part is handled by Konqueror (and shouldn't do anything - // in e.g. kmail, so not handled here). - if ( m_part->parentPart() ) - { - TQApplication::sendEvent(m_part->parentPart()->widget(), ev); - return; - } - TQScrollView::dragEnterEvent( ev ); -} - -void KHTMLView::dropEvent( TQDropEvent *ev ) -{ - // Handle drops onto frames (#16820) - // Drops on the main html part is handled by Konqueror (and shouldn't do anything - // in e.g. kmail, so not handled here). - if ( m_part->parentPart() ) - { - TQApplication::sendEvent(m_part->parentPart()->widget(), ev); - return; - } - TQScrollView::dropEvent( ev ); -} - -void KHTMLView::focusInEvent( TQFocusEvent *e ) -{ -#ifndef KHTML_NO_TYPE_AHEAD_FIND - m_part->enableFindAheadActions( true ); -#endif - DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0; - if (fn && fn->renderer() && fn->renderer()->isWidget() && - (e->reason() != TQFocusEvent::Mouse) && - static_cast<khtml::RenderWidget*>(fn->renderer())->widget()) - static_cast<khtml::RenderWidget*>(fn->renderer())->widget()->setFocus(); -#ifndef KHTML_NO_CARET - // Restart blink frequency timer if it has been killed, but only on - // editable nodes - if (d->m_caretViewContext && - d->m_caretViewContext->freqTimerId == -1 && - fn) { - if (m_part->isCaretMode() - || m_part->isEditable() - || (fn && fn->renderer() - && fn->renderer()->style()->userInput() - == UI_ENABLED)) { - d->m_caretViewContext->freqTimerId = startTimer(500); - d->m_caretViewContext->visible = true; - }/*end if*/ - }/*end if*/ - showCaret(); -#endif // KHTML_NO_CARET - TQScrollView::focusInEvent( e ); -} - -void KHTMLView::focusOutEvent( TQFocusEvent *e ) -{ - if(m_part) m_part->stopAutoScroll(); - -#ifndef KHTML_NO_TYPE_AHEAD_FIND - if(d->typeAheadActivated) - { - findTimeout(); - } - m_part->enableFindAheadActions( false ); -#endif // KHTML_NO_TYPE_AHEAD_FIND - -#ifndef KHTML_NO_CARET - if (d->m_caretViewContext) { - switch (d->m_caretViewContext->displayNonFocused) { - case KHTMLPart::CaretInvisible: - hideCaret(); - break; - case KHTMLPart::CaretVisible: { - killTimer(d->m_caretViewContext->freqTimerId); - d->m_caretViewContext->freqTimerId = -1; - NodeImpl *caretNode = m_part->xmlDocImpl()->focusNode(); - if (!d->m_caretViewContext->visible && (m_part->isCaretMode() - || m_part->isEditable() - || (caretNode && caretNode->renderer() - && caretNode->renderer()->style()->userInput() - == UI_ENABLED))) { - d->m_caretViewContext->visible = true; - showCaret(true); - }/*end if*/ - break; - } - case KHTMLPart::CaretBlink: - // simply leave as is - break; - }/*end switch*/ - }/*end if*/ -#endif // KHTML_NO_CARET - - if ( d->cursor_icon_widget ) - d->cursor_icon_widget->hide(); - - TQScrollView::focusOutEvent( e ); -} - -void KHTMLView::slotScrollBarMoved() -{ - if ( !d->firstRelayout && !d->complete && m_part->xmlDocImpl() && - d->layoutSchedulingEnabled) { - // contents scroll while we are not complete: we need to check our layout *now* - khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() ); - if (root && root->needsLayout()) { - unscheduleRelayout(); - layout(); - } - } - if (!d->scrollingSelf) { - d->scrollBarMoved = true; - d->contentsMoving = true; - // ensure quick reset of contentsMoving flag - scheduleRepaint(0, 0, 0, 0); - } - - if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement()) - m_part->xmlDocImpl()->documentElement()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false); -} - -void KHTMLView::timerEvent ( TQTimerEvent *e ) -{ -// kdDebug() << "timer event " << e->timerId() << endl; - if ( e->timerId() == d->scrollTimerId ) { - if( d->scrollSuspended ) - return; - switch (d->scrollDirection) { - case KHTMLViewPrivate::ScrollDown: - if (contentsY() + visibleHeight () >= contentsHeight()) - d->newScrollTimer(this, 0); - else - scrollBy( 0, d->scrollBy ); - break; - case KHTMLViewPrivate::ScrollUp: - if (contentsY() <= 0) - d->newScrollTimer(this, 0); - else - scrollBy( 0, -d->scrollBy ); - break; - case KHTMLViewPrivate::ScrollRight: - if (contentsX() + visibleWidth () >= contentsWidth()) - d->newScrollTimer(this, 0); - else - scrollBy( d->scrollBy, 0 ); - break; - case KHTMLViewPrivate::ScrollLeft: - if (contentsX() <= 0) - d->newScrollTimer(this, 0); - else - scrollBy( -d->scrollBy, 0 ); - break; - } - return; - } - else if ( e->timerId() == d->layoutTimerId ) { - d->dirtyLayout = true; - layout(); - if (d->firstRelayout) { - d->firstRelayout = false; - verticalScrollBar()->setEnabled( true ); - horizontalScrollBar()->setEnabled( true ); - } - } -#ifndef KHTML_NO_CARET - else if (d->m_caretViewContext - && e->timerId() == d->m_caretViewContext->freqTimerId) { - d->m_caretViewContext->visible = !d->m_caretViewContext->visible; - if (d->m_caretViewContext->displayed) { - updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - }/*end if*/ -// if (d->m_caretViewContext->visible) cout << "|" << flush; -// else cout << "" << flush; - return; - } -#endif - - d->contentsMoving = false; - if( m_part->xmlDocImpl() ) { - DOM::DocumentImpl *document = m_part->xmlDocImpl(); - khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer()); - - if ( root && root->needsLayout() ) { - killTimer(d->repaintTimerId); - d->repaintTimerId = 0; - scheduleRelayout(); - return; - } - } - - setStaticBackground(d->useSlowRepaints); - -// kdDebug() << "scheduled repaint "<< d->repaintTimerId << endl; - killTimer(d->repaintTimerId); - d->repaintTimerId = 0; - - TQRect updateRegion; - TQMemArray<TQRect> rects = d->updateRegion.rects(); - - d->updateRegion = TQRegion(); - - if ( rects.size() ) - updateRegion = rects[0]; - - for ( unsigned i = 1; i < rects.size(); ++i ) { - TQRect newRegion = updateRegion.unite(rects[i]); - if (2*newRegion.height() > 3*updateRegion.height() ) - { - repaintContents( updateRegion ); - updateRegion = rects[i]; - } - else - updateRegion = newRegion; - } - - if ( !updateRegion.isNull() ) - repaintContents( updateRegion ); - - // As widgets can only be accurately positioned during painting, every layout might - // dissociate a widget from its RenderWidget. E.g: if a RenderWidget was visible before layout, but the layout - // pushed it out of the viewport, it will not be repainted, and consequently it's assocoated widget won't be repositioned! - // Thus we need to check each supposedly 'visible' widget at the end of each layout, and remove it in case it's no more in sight. - - if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) { - TQWidget* w; - d->dirtyLayout = false; - - TQRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()); - TQPtrList<RenderWidget> toRemove; - for (TQPtrDictIterator<TQWidget> it(d->visibleWidgets); it.current(); ++it) { - int xp = 0, yp = 0; - w = it.current(); - RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() ); - if (!rw->absolutePosition(xp, yp) || - !visibleRect.intersects(TQRect(xp, yp, w->width(), w->height()))) - toRemove.append(rw); - } - for (RenderWidget* r = toRemove.first(); r; r = toRemove.next()) - if ( (w = d->visibleWidgets.take(r) ) ) - addChild(w, 0, -500000); - } - - emit repaintAccessKeys(); - if (d->emitCompletedAfterRepaint) { - bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull; - d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone; - if ( full ) - emit m_part->completed(); - else - emit m_part->completed(true); - } -} - -void KHTMLView::scheduleRelayout(khtml::RenderObject * /*clippedObj*/) -{ - if (!d->layoutSchedulingEnabled || d->layoutTimerId) - return; - - d->layoutTimerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing() - ? 1000 : 0 ); -} - -void KHTMLView::unscheduleRelayout() -{ - if (!d->layoutTimerId) - return; - - killTimer(d->layoutTimerId); - d->layoutTimerId = 0; -} - -void KHTMLView::unscheduleRepaint() -{ - if (!d->repaintTimerId) - return; - - killTimer(d->repaintTimerId); - d->repaintTimerId = 0; -} - -void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap) -{ - bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing(); - -// kdDebug() << "parsing " << parsing << endl; -// kdDebug() << "complete " << d->complete << endl; - - int time = parsing ? 300 : (!asap ? ( !d->complete ? 100 : 20 ) : 0); - -#ifdef DEBUG_FLICKER - TQPainter p; - p.begin( viewport() ); - - int vx, vy; - contentsToViewport( x, y, vx, vy ); - p.fillRect( vx, vy, w, h, TQt::red ); - p.end(); -#endif - - d->updateRegion = d->updateRegion.unite(TQRect(x,y,w,h)); - - if (asap && !parsing) - unscheduleRepaint(); - - if ( !d->repaintTimerId ) - d->repaintTimerId = startTimer( time ); - -// kdDebug() << "starting timer " << time << endl; -} - -void KHTMLView::complete( bool pendingAction ) -{ -// kdDebug() << "KHTMLView::complete()" << endl; - - d->complete = true; - - // is there a relayout pending? - if (d->layoutTimerId) - { -// kdDebug() << "requesting relayout now" << endl; - // do it now - killTimer(d->layoutTimerId); - d->layoutTimerId = startTimer( 0 ); - d->emitCompletedAfterRepaint = pendingAction ? - KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull; - } - - // is there a repaint pending? - if (d->repaintTimerId) - { -// kdDebug() << "requesting repaint now" << endl; - // do it now - killTimer(d->repaintTimerId); - d->repaintTimerId = startTimer( 20 ); - d->emitCompletedAfterRepaint = pendingAction ? - KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull; - } - - if (!d->emitCompletedAfterRepaint) - { - if (!pendingAction) - emit m_part->completed(); - else - emit m_part->completed(true); - } - -} - -void KHTMLView::slotMouseScrollTimer() -{ - scrollBy( d->m_mouseScroll_byX, d->m_mouseScroll_byY ); -} - -#ifndef KHTML_NO_CARET - -// ### the dependencies on static functions are a nightmare. just be -// hacky and include the implementation here. Clean me up, please. - -#include "khtml_caret.cpp" - -void KHTMLView::initCaret(bool keepSelection) -{ -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "begin initCaret" << endl; -#endif - // save caretMoved state as moveCaretTo changes it - if (m_part->xmlDocImpl()) { -#if 0 - ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__"); - if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer())); -#endif - d->caretViewContext(); - bool cmoved = d->m_caretViewContext->caretMoved; - if (m_part->d->caretNode().isNull()) { - // set to document, position will be sanitized anyway - m_part->d->caretNode() = m_part->document(); - m_part->d->caretOffset() = 0L; - // This sanity check is necessary for the not so unlikely case that - // setEditable or setCaretMode is called before any render objects have - // been created. - if (!m_part->d->caretNode().handle()->renderer()) return; - }/*end if*/ -// kdDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle() -// << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl; - // ### does not repaint the selection on keepSelection!=false - moveCaretTo(m_part->d->caretNode().handle(), m_part->d->caretOffset(), !keepSelection); -// kdDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle() -// << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl; - d->m_caretViewContext->caretMoved = cmoved; - }/*end if*/ -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "end initCaret" << endl; -#endif -} - -bool KHTMLView::caretOverrides() const -{ - bool cm = m_part->isCaretMode(); - bool dm = m_part->isEditable(); - return cm && !dm ? false - : (dm || m_part->d->caretNode().handle()->contentEditable()) - && d->editorContext()->override; -} - -void KHTMLView::ensureNodeHasFocus(NodeImpl *node) -{ - if (m_part->isCaretMode() || m_part->isEditable()) return; - if (node->focused()) return; - - // Find first ancestor whose "user-input" is "enabled" - NodeImpl *firstAncestor = 0; - while (node) { - if (node->renderer() - && node->renderer()->style()->userInput() != UI_ENABLED) - break; - firstAncestor = node; - node = node->parentNode(); - }/*wend*/ - - if (!node) firstAncestor = 0; - - DocumentImpl *doc = m_part->xmlDocImpl(); - // ensure that embedded widgets don't lose their focus - if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer() - && doc->focusNode()->renderer()->isWidget()) - return; - - // Set focus node on the document -#if DEBUG_CARETMODE > 1 - kdDebug(6200) << k_funcinfo << "firstAncestor " << firstAncestor << ": " - << (firstAncestor ? firstAncestor->nodeName().string() : TQString::null) << endl; -#endif - doc->setFocusNode(firstAncestor); - emit m_part->nodeActivated(Node(firstAncestor)); -} - -void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox) -{ - if (!m_part || m_part->d->caretNode().isNull()) return; - d->caretViewContext(); - NodeImpl *caretNode = m_part->d->caretNode().handle(); -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ? " "+caretNode->nodeName().string() : TQString::null) << " r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ? " \"" + TQConstString(static_cast<RenderText *>(caretNode->renderer())->str->s, kMin(static_cast<RenderText *>(caretNode->renderer())->str->l, 15u)).string() + "\"" : TQString::null) << endl; -#endif - caretNode->getCaret(m_part->d->caretOffset(), caretOverrides(), - d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - - if (hintBox && d->m_caretViewContext->x == -1) { -#if DEBUG_CARETMODE > 1 - kdDebug(6200) << "using hint inline box coordinates" << endl; -#endif - RenderObject *r = caretNode->renderer(); - const TQFontMetrics &fm = r->style()->fontMetrics(); - int absx, absy; - r->containingBlock()->absolutePosition(absx, absy, - false); // ### what about fixed? - d->m_caretViewContext->x = absx + hintBox->xPos(); - d->m_caretViewContext->y = absy + hintBox->yPos(); -// + hintBox->baseline() - fm.ascent(); - d->m_caretViewContext->width = 1; - // ### firstline not regarded. But I think it can be safely neglected - // as hint boxes are only used for empty lines. - d->m_caretViewContext->height = fm.height(); - }/*end if*/ - -#if DEBUG_CARETMODE > 4 -// kdDebug(6200) << "freqTimerId: "<<d->m_caretViewContext->freqTimerId<<endl; -#endif -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "caret: ofs="<<m_part->d->caretOffset()<<" " - <<" x="<<d->m_caretViewContext->x<<" y="<<d->m_caretViewContext->y - <<" h="<<d->m_caretViewContext->height<<endl; -#endif -} - -void KHTMLView::caretOn() -{ - if (d->m_caretViewContext) { - killTimer(d->m_caretViewContext->freqTimerId); - - if (hasFocus() || d->m_caretViewContext->displayNonFocused - == KHTMLPart::CaretBlink) { - d->m_caretViewContext->freqTimerId = startTimer(500); - } else { - d->m_caretViewContext->freqTimerId = -1; - }/*end if*/ - - d->m_caretViewContext->visible = true; - if ((d->m_caretViewContext->displayed = (hasFocus() - || d->m_caretViewContext->displayNonFocused - != KHTMLPart::CaretInvisible))) { - updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - }/*end if*/ -// kdDebug(6200) << "caret on" << endl; - }/*end if*/ -} - -void KHTMLView::caretOff() -{ - if (d->m_caretViewContext) { - killTimer(d->m_caretViewContext->freqTimerId); - d->m_caretViewContext->freqTimerId = -1; - d->m_caretViewContext->displayed = false; - if (d->m_caretViewContext->visible) { - d->m_caretViewContext->visible = false; - updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - }/*end if*/ -// kdDebug(6200) << "caret off" << endl; - }/*end if*/ -} - -void KHTMLView::showCaret(bool forceRepaint) -{ - if (d->m_caretViewContext) { - d->m_caretViewContext->displayed = true; - if (d->m_caretViewContext->visible) { - if (!forceRepaint) { - updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - } else { - repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - }/*end if*/ - }/*end if*/ -// kdDebug(6200) << "caret shown" << endl; - }/*end if*/ -} - -bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode, long startOffset, - NodeImpl *endNode, long endOffset) -{ - m_part->d->m_selectionStart = m_part->d->m_selectionEnd = m_part->d->caretNode(); - m_part->d->m_startOffset = m_part->d->m_endOffset = m_part->d->caretOffset(); - m_part->d->m_extendAtEnd = true; - - bool folded = startNode != endNode || startOffset != endOffset; - - // Only clear the selection if there has been one. - if (folded) { - m_part->xmlDocImpl()->clearSelection(); - }/*end if*/ - - return folded; -} - -void KHTMLView::hideCaret() -{ - if (d->m_caretViewContext) { - if (d->m_caretViewContext->visible) { -// kdDebug(6200) << "redraw caret hidden" << endl; - d->m_caretViewContext->visible = false; - // force repaint, otherwise the event won't be handled - // before the focus leaves the window - repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, - d->m_caretViewContext->height); - d->m_caretViewContext->visible = true; - }/*end if*/ - d->m_caretViewContext->displayed = false; -// kdDebug(6200) << "caret hidden" << endl; - }/*end if*/ -} - -int KHTMLView::caretDisplayPolicyNonFocused() const -{ - if (d->m_caretViewContext) - return d->m_caretViewContext->displayNonFocused; - else - return KHTMLPart::CaretInvisible; -} - -void KHTMLView::setCaretDisplayPolicyNonFocused(int policy) -{ - d->caretViewContext(); -// int old = d->m_caretViewContext->displayNonFocused; - d->m_caretViewContext->displayNonFocused = (KHTMLPart::CaretDisplayPolicy)policy; - - // make change immediately take effect if not focused - if (!hasFocus()) { - switch (d->m_caretViewContext->displayNonFocused) { - case KHTMLPart::CaretInvisible: - hideCaret(); - break; - case KHTMLPart::CaretBlink: - if (d->m_caretViewContext->freqTimerId != -1) break; - d->m_caretViewContext->freqTimerId = startTimer(500); - // fall through - case KHTMLPart::CaretVisible: - d->m_caretViewContext->displayed = true; - showCaret(); - break; - }/*end switch*/ - }/*end if*/ -} - -bool KHTMLView::placeCaret(CaretBox *hintBox) -{ - CaretViewContext *cv = d->caretViewContext(); - caretOff(); - NodeImpl *caretNode = m_part->d->caretNode().handle(); - // ### why is it sometimes null? - if (!caretNode || !caretNode->renderer()) return false; - ensureNodeHasFocus(caretNode); - if (m_part->isCaretMode() || m_part->isEditable() - || caretNode->renderer()->style()->userInput() == UI_ENABLED) { - recalcAndStoreCaretPos(hintBox); - - cv->origX = cv->x; - - caretOn(); - return true; - }/*end if*/ - return false; -} - -void KHTMLView::ensureCaretVisible() -{ - CaretViewContext *cv = d->m_caretViewContext; - if (!cv) return; - ensureVisible(cv->x, cv->y, cv->width, cv->height); - d->scrollBarMoved = false; -} - -bool KHTMLView::extendSelection(NodeImpl *oldStartSel, long oldStartOfs, - NodeImpl *oldEndSel, long oldEndOfs) -{ - bool changed = false; - if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd - && m_part->d->m_startOffset == m_part->d->m_endOffset) { - changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); - m_part->d->m_extendAtEnd = true; - } else do { - changed = m_part->d->m_selectionStart.handle() != oldStartSel - || m_part->d->m_startOffset != oldStartOfs - || m_part->d->m_selectionEnd.handle() != oldEndSel - || m_part->d->m_endOffset != oldEndOfs; - if (!changed) break; - - // determine start position -- caret position is always at end. - NodeImpl *startNode; - long startOffset; - if (m_part->d->m_extendAtEnd) { - startNode = m_part->d->m_selectionStart.handle(); - startOffset = m_part->d->m_startOffset; - } else { - startNode = m_part->d->m_selectionEnd.handle(); - startOffset = m_part->d->m_endOffset; - m_part->d->m_selectionEnd = m_part->d->m_selectionStart; - m_part->d->m_endOffset = m_part->d->m_startOffset; - m_part->d->m_extendAtEnd = true; - }/*end if*/ - - bool swapNeeded = false; - if (!m_part->d->m_selectionEnd.isNull() && startNode) { - swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset, - m_part->d->m_selectionEnd.handle(), - m_part->d->m_endOffset) >= 0; - }/*end if*/ - - m_part->d->m_selectionStart = startNode; - m_part->d->m_startOffset = startOffset; - - if (swapNeeded) { - m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionEnd.handle(), - m_part->d->m_endOffset, m_part->d->m_selectionStart.handle(), - m_part->d->m_startOffset); - } else { - m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(), - m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(), - m_part->d->m_endOffset); - }/*end if*/ - } while(false);/*end if*/ - return changed; -} - -void KHTMLView::updateSelection(NodeImpl *oldStartSel, long oldStartOfs, - NodeImpl *oldEndSel, long oldEndOfs) -{ - if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd - && m_part->d->m_startOffset == m_part->d->m_endOffset) { - if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) { - m_part->emitSelectionChanged(); - }/*end if*/ - m_part->d->m_extendAtEnd = true; - } else { - // check if the extending end has passed the immobile end - if (!m_part->d->m_selectionEnd.isNull() && !m_part->d->m_selectionEnd.isNull()) { - bool swapNeeded = RangeImpl::compareBoundaryPoints( - m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset, - m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0; - if (swapNeeded) { - DOM::Node tmpNode = m_part->d->m_selectionStart; - long tmpOffset = m_part->d->m_startOffset; - m_part->d->m_selectionStart = m_part->d->m_selectionEnd; - m_part->d->m_startOffset = m_part->d->m_endOffset; - m_part->d->m_selectionEnd = tmpNode; - m_part->d->m_endOffset = tmpOffset; - m_part->d->m_startBeforeEnd = true; - m_part->d->m_extendAtEnd = !m_part->d->m_extendAtEnd; - }/*end if*/ - }/*end if*/ - - m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(), - m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(), - m_part->d->m_endOffset); - m_part->emitSelectionChanged(); - }/*end if*/ -} - -void KHTMLView::caretKeyPressEvent(TQKeyEvent *_ke) -{ - NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle(); - long oldStartOfs = m_part->d->m_startOffset; - NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle(); - long oldEndOfs = m_part->d->m_endOffset; - - NodeImpl *oldCaretNode = m_part->d->caretNode().handle(); - long oldOffset = m_part->d->caretOffset(); - - bool ctrl = _ke->state() & ControlButton; - -// FIXME: this is that widely indented because I will write ifs around it. - switch(_ke->key()) { - case Key_Space: - break; - - case Key_Down: - moveCaretNextLine(1); - break; - - case Key_Up: - moveCaretPrevLine(1); - break; - - case Key_Left: - moveCaretBy(false, ctrl ? CaretByWord : CaretByCharacter, 1); - break; - - case Key_Right: - moveCaretBy(true, ctrl ? CaretByWord : CaretByCharacter, 1); - break; - - case Key_Next: - moveCaretNextPage(); - break; - - case Key_Prior: - moveCaretPrevPage(); - break; - - case Key_Home: - if (ctrl) - moveCaretToDocumentBoundary(false); - else - moveCaretToLineBegin(); - break; - - case Key_End: - if (ctrl) - moveCaretToDocumentBoundary(true); - else - moveCaretToLineEnd(); - break; - - }/*end switch*/ - - if ((m_part->d->caretNode().handle() != oldCaretNode - || m_part->d->caretOffset() != oldOffset) - // node should never be null, but faulty conditions may cause it to be - && !m_part->d->caretNode().isNull()) { - - d->m_caretViewContext->caretMoved = true; - - if (_ke->state() & ShiftButton) { // extend selection - updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); - } else { // clear any selection - if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) - m_part->emitSelectionChanged(); - }/*end if*/ - - m_part->emitCaretPositionChanged(m_part->d->caretNode(), m_part->d->caretOffset()); - }/*end if*/ - - _ke->accept(); -} - -bool KHTMLView::moveCaretTo(NodeImpl *node, long offset, bool clearSel) -{ - if (!node) return false; - ElementImpl *baseElem = determineBaseElement(node); - RenderFlow *base = static_cast<RenderFlow *>(baseElem ? baseElem->renderer() : 0); - if (!node) return false; - - // need to find out the node's inline box. If there is none, this function - // will snap to the next node that has one. This is necessary to make the - // caret visible in any case. - CaretBoxLineDeleter cblDeleter; -// RenderBlock *cb; - long r_ofs; - CaretBoxIterator cbit; - CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit); - if(!cbl) { - kdWarning() << "KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL" << endl; - return false; - } - -#if DEBUG_CARETMODE > 3 - if (cbl) kdDebug(6200) << cbl->information() << endl; -#endif - CaretBox *box = *cbit; - if (cbit != cbl->end() && box->object() != node->renderer()) { - if (box->object()->element()) { - mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(), - box->isOutsideEnd(), node, offset); - //if (!outside) offset = node->minOffset(); -#if DEBUG_CARETMODE > 1 - kdDebug(6200) << "set new node " << node->nodeName().string() << "@" << node << endl; -#endif - } else { // box has no associated element -> do not use - // this case should actually never happen. - box = 0; - kdError(6200) << "Box contains no node! Crash imminent" << endl; - }/*end if*/ - } - - NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle(); - long oldStartOfs = m_part->d->m_startOffset; - NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle(); - long oldEndOfs = m_part->d->m_endOffset; - - // test for position change - bool posChanged = m_part->d->caretNode().handle() != node - || m_part->d->caretOffset() != offset; - bool selChanged = false; - - m_part->d->caretNode() = node; - m_part->d->caretOffset() = offset; - if (clearSel || !oldStartSel || !oldEndSel) { - selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); - } else { - //kdDebug(6200) << "moveToCaret: extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd << endl; - //kdDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")" << endl; - selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); - //kdDebug(6200) << "after extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd << endl; - //kdDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")" << endl; - }/*end if*/ - - d->caretViewContext()->caretMoved = true; - - bool visible_caret = placeCaret(box); - - // FIXME: if the old position was !visible_caret, and the new position is - // also, then two caretPositionChanged signals with a null Node are - // emitted in series. - if (posChanged) { - m_part->emitCaretPositionChanged(visible_caret ? node : 0, offset); - }/*end if*/ - - return selChanged; -} - -void KHTMLView::moveCaretByLine(bool next, int count) -{ - Node &caretNodeRef = m_part->d->caretNode(); - if (caretNodeRef.isNull()) return; - - NodeImpl *caretNode = caretNodeRef.handle(); -// kdDebug(6200) << ": caretNode=" << caretNode << endl; - long offset = m_part->d->caretOffset(); - - CaretViewContext *cv = d->caretViewContext(); - - ElementImpl *baseElem = determineBaseElement(caretNode); - LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); - - ErgonomicEditableLineIterator it(ld.current(), cv->origX); - - // move count lines vertically - while (count > 0 && it != ld.end() && it != ld.preBegin()) { - count--; - if (next) ++it; else --it; - }/*wend*/ - - // Nothing? Then leave everything as is. - if (it == ld.end() || it == ld.preBegin()) return; - - int x, absx, absy; - CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy); - - placeCaretOnLine(caretBox, x, absx, absy); -} - -void KHTMLView::placeCaretOnLine(CaretBox *caretBox, int x, int absx, int absy) -{ - // paranoia sanity check - if (!caretBox) return; - - RenderObject *caretRender = caretBox->object(); - -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "got valid caretBox " << caretBox << endl; - kdDebug(6200) << "xPos: " << caretBox->xPos() << " yPos: " << caretBox->yPos() - << " width: " << caretBox->width() << " height: " << caretBox->height() << endl; - InlineTextBox *tb = static_cast<InlineTextBox *>(caretBox->inlineBox()); - if (caretBox->isInlineTextBox()) { kdDebug(6200) << "contains \"" << TQString(static_cast<RenderText *>(tb->object())->str->s + tb->m_start, tb->m_len) << "\"" << endl;} -#endif - // inquire height of caret - int caretHeight = caretBox->height(); - bool isText = caretBox->isInlineTextBox(); - int yOfs = 0; // y-offset for text nodes - if (isText) { - // text boxes need extrawurst - RenderText *t = static_cast<RenderText *>(caretRender); - const TQFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine); - caretHeight = fm.height(); - yOfs = caretBox->inlineBox()->baseline() - fm.ascent(); - }/*end if*/ - - caretOff(); - - // set new caret node - NodeImpl *caretNode; - long &offset = m_part->d->caretOffset(); - mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(), - caretBox->isOutsideEnd(), caretNode, offset); - - // set all variables not needing special treatment - d->m_caretViewContext->y = caretBox->yPos() + yOfs; - d->m_caretViewContext->height = caretHeight; - d->m_caretViewContext->width = 1; // FIXME: regard override - - int xPos = caretBox->xPos(); - int caretBoxWidth = caretBox->width(); - d->m_caretViewContext->x = xPos; - - if (!caretBox->isOutside()) { - // before or at beginning of inline box -> place at beginning - long r_ofs = 0; - if (x <= xPos) { - r_ofs = caretBox->minOffset(); - // somewhere within this block - } else if (x > xPos && x <= xPos + caretBoxWidth) { - if (isText) { // find out where exactly - r_ofs = static_cast<InlineTextBox *>(caretBox->inlineBox()) - ->offsetForPoint(x, d->m_caretViewContext->x); -#if DEBUG_CARETMODE > 2 - kdDebug(6200) << "deviation from origX " << d->m_caretViewContext->x - x << endl; -#endif -#if 0 - } else { // snap to nearest end - if (xPos + caretBoxWidth - x < x - xPos) { - d->m_caretViewContext->x = xPos + caretBoxWidth; - r_ofs = caretNode ? caretNode->maxOffset() : 1; - } else { - d->m_caretViewContext->x = xPos; - r_ofs = caretNode ? caretNode->minOffset() : 0; - }/*end if*/ -#endif - }/*end if*/ - } else { // after the inline box -> place at end - d->m_caretViewContext->x = xPos + caretBoxWidth; - r_ofs = caretBox->maxOffset(); - }/*end if*/ - offset = r_ofs; - }/*end if*/ -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "new offset: " << offset << endl; -#endif - - m_part->d->caretNode() = caretNode; - m_part->d->caretOffset() = offset; - - d->m_caretViewContext->x += absx; - d->m_caretViewContext->y += absy; - -#if DEBUG_CARETMODE > 1 - 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; -#endif - - ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, d->m_caretViewContext->height); - d->scrollBarMoved = false; - - ensureNodeHasFocus(caretNode); - caretOn(); -} - -void KHTMLView::moveCaretToLineBoundary(bool end) -{ - Node &caretNodeRef = m_part->d->caretNode(); - if (caretNodeRef.isNull()) return; - - NodeImpl *caretNode = caretNodeRef.handle(); -// kdDebug(6200) << ": caretNode=" << caretNode << endl; - long offset = m_part->d->caretOffset(); - - ElementImpl *baseElem = determineBaseElement(caretNode); - LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); - - EditableLineIterator it = ld.current(); - if (it == ld.end()) return; // should not happen, but who knows - - EditableCaretBoxIterator fbit(it, end); - Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin()); - CaretBox *b = *fbit; - - RenderObject *cb = b->containingBlock(); - int absx, absy; - - if (cb) cb->absolutePosition(absx,absy); - else absx = absy = 0; - - int x = b->xPos() + (end && !b->isOutside() ? b->width() : 0); - d->m_caretViewContext->origX = absx + x; - placeCaretOnLine(b, x, absx, absy); -} - -void KHTMLView::moveCaretToDocumentBoundary(bool end) -{ - Node &caretNodeRef = m_part->d->caretNode(); - if (caretNodeRef.isNull()) return; - - NodeImpl *caretNode = caretNodeRef.handle(); -// kdDebug(6200) << ": caretNode=" << caretNode << endl; - long offset = m_part->d->caretOffset(); - - ElementImpl *baseElem = determineBaseElement(caretNode); - LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem); - - EditableLineIterator it(end ? ld.preEnd() : ld.begin(), end); - if (it == ld.end() || it == ld.preBegin()) return; // should not happen, but who knows - - EditableCaretBoxIterator fbit = it; - Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin()); - CaretBox *b = *fbit; - - RenderObject *cb = (*it)->containingBlock(); - int absx, absy; - - if (cb) cb->absolutePosition(absx, absy); - else absx = absy = 0; - - int x = b->xPos()/* + (end ? b->width() : 0) reactivate for rtl*/; - d->m_caretViewContext->origX = absx + x; - placeCaretOnLine(b, x, absx, absy); -} - -void KHTMLView::moveCaretBy(bool next, CaretMovement cmv, int count) -{ - if (!m_part) return; - Node &caretNodeRef = m_part->d->caretNode(); - if (caretNodeRef.isNull()) return; - - NodeImpl *caretNode = caretNodeRef.handle(); -// kdDebug(6200) << ": caretNode=" << caretNode << endl; - long &offset = m_part->d->caretOffset(); - - ElementImpl *baseElem = determineBaseElement(caretNode); - CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly; - LinearDocument ld(m_part, caretNode, offset, advpol, baseElem); - - EditableCharacterIterator it(&ld); - while (!it.isEnd() && count > 0) { - count--; - if (cmv == CaretByCharacter) { - if (next) ++it; - else --it; - } else if (cmv == CaretByWord) { - if (next) moveItToNextWord(it); - else moveItToPrevWord(it); - }/*end if*/ -//kdDebug(6200) << "movecaret" << endl; - }/*wend*/ - CaretBox *hintBox = 0; // make gcc uninit warning disappear - if (!it.isEnd()) { - NodeImpl *node = caretNodeRef.handle(); - hintBox = it.caretBox(); -//kdDebug(6200) << "hintBox = " << hintBox << endl; -//kdDebug(6200) << " outside " << hintBox->isOutside() << " outsideEnd " << hintBox->isOutsideEnd() << " r " << it.renderer() << " ofs " << it.offset() << " cb " << hintBox->containingBlock() << endl; - mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(), - hintBox->isOutsideEnd(), node, offset); -//kdDebug(6200) << "mapRTD" << endl; - caretNodeRef = node; -#if DEBUG_CARETMODE > 2 - kdDebug(6200) << "set by valid node " << node << " " << (node?node->nodeName().string():TQString::null) << " offset: " << offset << endl; -#endif - } else { - offset = next ? caretNode->maxOffset() : caretNode->minOffset(); -#if DEBUG_CARETMODE > 0 - kdDebug(6200) << "set by INvalid node. offset: " << offset << endl; -#endif - }/*end if*/ - placeCaretOnChar(hintBox); -} - -void KHTMLView::placeCaretOnChar(CaretBox *hintBox) -{ - caretOff(); - recalcAndStoreCaretPos(hintBox); - ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y, - d->m_caretViewContext->width, d->m_caretViewContext->height); - d->m_caretViewContext->origX = d->m_caretViewContext->x; - d->scrollBarMoved = false; -#if DEBUG_CARETMODE > 3 - //if (caretNode->isTextNode()) kdDebug(6200) << "text[0] = " << (int)*((TextImpl *)caretNode)->data().unicode() << " text :\"" << ((TextImpl *)caretNode)->data().string() << "\"" << endl; -#endif - ensureNodeHasFocus(m_part->d->caretNode().handle()); - caretOn(); -} - -void KHTMLView::moveCaretByPage(bool next) -{ - Node &caretNodeRef = m_part->d->caretNode(); - if (caretNodeRef.isNull()) return; - - NodeImpl *caretNode = caretNodeRef.handle(); -// kdDebug(6200) << ": caretNode=" << caretNode << endl; - long offset = m_part->d->caretOffset(); - - int offs = (clipper()->height() < 30) ? clipper()->height() : 30; - // Minimum distance the caret must be moved - int mindist = clipper()->height() - offs; - - CaretViewContext *cv = d->caretViewContext(); -// int y = cv->y; // we always measure the top border - - ElementImpl *baseElem = determineBaseElement(caretNode); - LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); - - ErgonomicEditableLineIterator it(ld.current(), cv->origX); - - moveIteratorByPage(ld, it, mindist, next); - - int x, absx, absy; - CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy); - - placeCaretOnLine(caretBox, x, absx, absy); -} - -void KHTMLView::moveCaretPrevWord() -{ - moveCaretBy(false, CaretByWord, 1); -} - -void KHTMLView::moveCaretNextWord() -{ - moveCaretBy(true, CaretByWord, 1); -} - -void KHTMLView::moveCaretPrevLine(int n) -{ - moveCaretByLine(false, n); -} - -void KHTMLView::moveCaretNextLine(int n) -{ - moveCaretByLine(true, n); -} - -void KHTMLView::moveCaretPrevPage() -{ - moveCaretByPage(false); -} - -void KHTMLView::moveCaretNextPage() -{ - moveCaretByPage(true); -} - -void KHTMLView::moveCaretToLineBegin() -{ - moveCaretToLineBoundary(false); -} - -void KHTMLView::moveCaretToLineEnd() -{ - moveCaretToLineBoundary(true); -} - -#endif // KHTML_NO_CARET - -#ifndef NO_SMOOTH_SCROLL_HACK -#define timer timer2 - -// All scrolls must be completed within 240ms of last keypress -static const int SCROLL_TIME = 240; -// Each step is 20 ms == 50 frames/second -static const int SCROLL_TICK = 20; - -void KHTMLView::scrollBy(int dx, int dy) -{ - TDEConfigGroup cfg( TDEGlobal::config(), "KDE" ); - if( !cfg.readBoolEntry( "SmoothScrolling", false )) { - TQScrollView::scrollBy( dx, dy ); - return; - } - // scrolling destination - int full_dx = d->dx + dx; - int full_dy = d->dy + dy; - - // scrolling speed - int ddx = 0; - int ddy = 0; - - int steps = SCROLL_TIME/SCROLL_TICK; - - ddx = (full_dx*16)/steps; - ddy = (full_dy*16)/steps; - - // don't go under 1px/step - if (ddx > 0 && ddx < 16) ddx = 16; - if (ddy > 0 && ddy < 16) ddy = 16; - if (ddx < 0 && ddx > -16) ddx = -16; - if (ddy < 0 && ddy > -16) ddy = -16; - - d->dx = full_dx; - d->dy = full_dy; - d->ddx = ddx; - d->ddy = ddy; - - if (!d->scrolling) { - scrollTick(); - startScrolling(); - } -} - -void KHTMLView::scrollTick() { - if (d->dx == 0 && d->dy == 0) { - stopScrolling(); - return; - } - - int tddx = d->ddx + d->rdx; - int tddy = d->ddy + d->rdy; - - int ddx = tddx / 16; - int ddy = tddy / 16; - d->rdx = tddx % 16; - d->rdy = tddy % 16; - - if (d->dx > 0 && ddx > d->dx) ddx = d->dx; - else - if (d->dx < 0 && ddx < d->dx) ddx = d->dx; - - if (d->dy > 0 && ddy > d->dy) ddy = d->dy; - else - if (d->dy < 0 && ddy < d->dy) ddy = d->dy; - - d->dx -= ddx; - d->dy -= ddy; - -// TQScrollView::setContentsPos( contentsX() + ddx, contentsY() + ddy); - kapp->syncX(); - TQScrollView::scrollBy(ddx, ddy); -// Unaccelerated X can get seriously overloaded by scrolling and for some reason -// will send KeyPress events only infrequently. This should help to reduce -// the load. - kapp->syncX(); -} - -void KHTMLView::startScrolling() -{ - d->scrolling = true; - d->timer.start(SCROLL_TICK, false); -} - -void KHTMLView::stopScrolling() -{ - d->timer.stop(); - d->dx = d->dy = 0; - d->scrolling = false; -} - -// Overloaded from TQScrollView and TQScrollBar -void KHTMLView::scrollViewWheelEvent( TQWheelEvent *e ) -{ - int pageStep = verticalScrollBar()->pageStep(); - int lineStep = verticalScrollBar()->lineStep(); - int step = TQMIN( TQApplication::wheelScrollLines()*lineStep, pageStep ); - if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) ) - step = pageStep; - - if(e->orientation() == Qt::Horizontal) - scrollBy(-((e->delta()*step)/120), 0); - else if(e->orientation() == Qt::Vertical) - scrollBy(0,-((e->delta()*step)/120)); - - e->accept(); -} - -#undef timer - -#endif // NO_SMOOTH_SCROLL_HACK - -#undef DEBUG_CARETMODE |