[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

rjw rjw at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 05:52:37 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 2750082a691e63516936c4d5fe6b95093e22c7d0
Author: rjw <rjw at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Nov 21 23:47:10 2001 +0000

    First pass at events, very messy.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@468 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/khtml/khtmlview.cpp b/WebCore/khtml/khtmlview.cpp
index c9df49b..0b59bf0 100644
--- a/WebCore/khtml/khtmlview.cpp
+++ b/WebCore/khtml/khtmlview.cpp
@@ -323,7 +323,11 @@ void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
     }
 
     khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
 }
 
 void KHTMLView::layout(bool)
@@ -403,7 +407,11 @@ void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
 
     khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
 
     emit m_part->nodeActivated(mev.innerNode);
 }
@@ -441,7 +449,12 @@ void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
 
     khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 
     // ###
     //if ( url.length() )
@@ -531,7 +544,12 @@ void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
 
     khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 }
 
 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
@@ -559,7 +577,12 @@ void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
 
     khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 }
 
 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
diff --git a/WebCore/khtml/khtmlview.h b/WebCore/khtml/khtmlview.h
index 2e4ea59..76e848b 100644
--- a/WebCore/khtml/khtmlview.h
+++ b/WebCore/khtml/khtmlview.h
@@ -174,12 +174,6 @@ public:
 
     virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );
 
-signals:
-    void cleared();
-
-protected:
-    void clear();
-
     virtual void resizeEvent ( QResizeEvent * event );
     virtual void showEvent ( QShowEvent * );
     virtual void hideEvent ( QHideEvent *);
@@ -214,6 +208,13 @@ protected:
      */
     void doAutoScroll();
 
+signals:
+    void cleared();
+
+    void clear();
+
+protected:
+
 protected slots:
     void slotPaletteChanged();
 
diff --git a/WebCore/kwq/KWQApplication.mm b/WebCore/kwq/KWQApplication.mm
index 3943513..83ee325 100644
--- a/WebCore/kwq/KWQApplication.mm
+++ b/WebCore/kwq/KWQApplication.mm
@@ -76,7 +76,10 @@ void QApplication::restoreOverrideCursor()
 
 bool QApplication::sendEvent(QObject *o, QEvent *e)
 {
-//    _logNotYetImplemented();
+    QEvent::Type type = e->type();
+    
+    KWQDEBUG1 ("received %d\n", type);
+
     return FALSE;
 }
 
diff --git a/WebCore/kwq/KWQEvent.h b/WebCore/kwq/KWQEvent.h
index 69eafd0..53817be 100644
--- a/WebCore/kwq/KWQEvent.h
+++ b/WebCore/kwq/KWQEvent.h
@@ -64,7 +64,7 @@ public:
     QEvent() {}
 #endif
 
-    QEvent(Type);
+    QEvent( Type t ) : _type(t) {}
     virtual ~QEvent();
 
     // member functions --------------------------------------------------------
@@ -89,7 +89,7 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QEvent &operator=(const QEvent &);
 #endif
-
+    Type  _type;
 }; // class QEvent =============================================================
 
 
@@ -146,6 +146,9 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QMouseEvent &operator=(const QMouseEvent &);
 #endif
+    QPoint _position;
+    int	   _button; // ### Make ushort in 3.0? Here it's an int...
+    ushort _state; // ### ...and here an ushort. But both are ButtonState!
 
 }; // class QMouseEvent ========================================================
 
@@ -492,20 +495,11 @@ private:
 
 class QCustomEvent : public QEvent {
 public:
-
-    // typedefs ----------------------------------------------------------------
-    // enums -------------------------------------------------------------------
-    // constants ---------------------------------------------------------------
-    // static member functions -------------------------------------------------
-    
-    // constructors, copy constructors, and destructors ------------------------
-    
-// add no-arg constructor
-#ifdef _KWQ_PEDANTIC_
-    QCustomEvent() {}
-#endif
-
-    QCustomEvent(Type);
+    QCustomEvent( int type );
+    QCustomEvent( Type type, void *data )
+	: QEvent(type), d(data) {};
+    void       *data()	const	{ return d; }
+    void	setData( void* data )	{ d = data; }
 
 // add no-op destructor
 #ifdef _KWQ_PEDANTIC_
@@ -519,6 +513,7 @@ public:
 // private ---------------------------------------------------------------------
 
 private:
+    void       *d;
 
 // add copy constructor
 // this private declaration prevents copying
diff --git a/WebCore/kwq/KWQEvent.mm b/WebCore/kwq/KWQEvent.mm
index bedb650..ed4612b 100644
--- a/WebCore/kwq/KWQEvent.mm
+++ b/WebCore/kwq/KWQEvent.mm
@@ -31,11 +31,6 @@ static const QPoint ORIGIN(0,0);
 
 // class QEvent ================================================================
 
-QEvent::QEvent(Type)
-{
-    //_logNotYetImplemented();
-}
-
 
 QEvent::~QEvent()
 {
@@ -45,30 +40,25 @@ QEvent::~QEvent()
 
 QEvent::Type QEvent::type() const
 {
-    _logNotYetImplemented();
-    return MouseButtonPress;
+    return _type;
 }
 
 
 // class QMouseEvent ===========================================================
 
-QMouseEvent::QMouseEvent(Type type, const QPoint &pos, int button, int state)
-{
-    _logNotYetImplemented();
+QMouseEvent::QMouseEvent( Type t, const QPoint &pos, int b, int s )
+    : QEvent(t), _position(pos), _button(b), _state((ushort)s){
 }
 
-
 int QMouseEvent::x()
 {
-    _logNotYetImplemented();
-    return 0;
+    return (int)_position.x();
 }
 
 
 int QMouseEvent::y()
 {
-    _logNotYetImplemented();
-    return 0;
+    return (int)_position.y();
 }
 
 
@@ -88,30 +78,25 @@ int QMouseEvent::globalY()
 
 const QPoint &QMouseEvent::pos() const
 {
-    _logNotYetImplemented();
-    // FIXME: replace this hack
-    return ORIGIN;
+    return _position;
 }
 
 
 Qt::ButtonState QMouseEvent::button()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_button);
 }
 
 
 Qt::ButtonState QMouseEvent::state()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_state);
 }
 
 
 Qt::ButtonState QMouseEvent::stateAfter()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_state);
 }
 
 
@@ -224,7 +209,7 @@ void QWheelEvent::ignore()
 
 // class QCustomEvent ===========================================================
 
-QCustomEvent::QCustomEvent(Type)
+QCustomEvent::QCustomEvent( int type )
+    : QEvent( (QEvent::Type)type ), d( 0 )
 {
-    _logNotYetImplemented();
 }
diff --git a/WebCore/kwq/KWQFontMetrics.mm b/WebCore/kwq/KWQFontMetrics.mm
index 42242c9..a1dfa1d 100644
--- a/WebCore/kwq/KWQFontMetrics.mm
+++ b/WebCore/kwq/KWQFontMetrics.mm
@@ -78,36 +78,45 @@ const float LargeNumberForText = 1.0e7;
 
 static NSMutableDictionary *metricsCache = nil;
 
- at implementation KWQMetricsInfo
+/*
+    
+*/
+ at implementation KWQLayoutInfo
 
 + (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color
 {
-    KWQMetricsInfo *metricsCache = [KWQMetricsInfo getMetricsForFont: font];
+    KWQLayoutInfo *metricsCache = [KWQLayoutInfo getMetricsForFont: font];
     NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
     if (layoutManager != nil){
         unsigned numberOfGlyphs = [layoutManager numberOfGlyphs];
         [metricsCache setColor: color];
+        [metricsCache setFont: font];
+        [KWQTextStorage setString: string attributes: attributes];
         [layoutManager drawGlyphsForGlyphRange:NSMakeRange (0, numberOfGlyphs) atPoint:p];
     }
 }
 
-+ (KWQMetricsInfo *)getMetricsForFont: (NSFont *)aFont
+
++ (KWQLayoutInfo *)getMetricsForFont: (NSFont *)aFont
 {
-    KWQMetricsInfo *info = (KWQMetricsInfo *)[metricsCache objectForKey: aFont];
+    KWQLayoutInfo *info = (KWQLayoutInfo *)[metricsCache objectForKey: aFont];
     if (info == nil){
-        info = [[KWQMetricsInfo alloc] initWithFont: aFont];
-        [KWQMetricsInfo setMetric: info forFont: aFont];
+        info = [[KWQLayoutInfo alloc] initWithFont: aFont];
+        [KWQLayoutInfo setMetric: info forFont: aFont];
         [info release];
     }
     return info;
 }
-+ (void)setMetric: (KWQMetricsInfo *)info forFont: (NSFont *)aFont
+
+
++ (void)setMetric: (KWQLayoutInfo *)info forFont: (NSFont *)aFont
 {
     if (metricsCache == nil)
         metricsCache = [[NSMutableDictionary alloc] init];
     [metricsCache setObject: info forKey: aFont];
 }
 
+
 - initWithFont: (NSFont *)aFont
 {
     [super init];
@@ -158,6 +167,11 @@ static NSMutableDictionary *metricsCache = nil;
     [attributes setObject: color forKey: NSForegroundColorAttributeName];
 }
 
+- (void)setFont: (NSFont *)aFont
+{
+    [attributes setObject: aFont forKey: NSFontAttributeName];
+}
+
 - (void)dealloc
 {
     [attributes release];
@@ -173,7 +187,7 @@ public:
     QFontMetricsPrivate(NSFont *aFont) 
     {
         font = [aFont retain];
-        info = [[KWQMetricsInfo getMetricsForFont: aFont] retain];
+        info = [[KWQLayoutInfo getMetricsForFont: aFont] retain];
     }
     
     ~QFontMetricsPrivate()
@@ -189,7 +203,7 @@ public:
     }
     
 private:
-    KWQMetricsInfo *info;
+    KWQLayoutInfo *info;
     NSFont *font;
 };
 
diff --git a/WebCore/kwq/KWQKHTMLPart.mm b/WebCore/kwq/KWQKHTMLPart.mm
index 9800307..1c25e81 100644
--- a/WebCore/kwq/KWQKHTMLPart.mm
+++ b/WebCore/kwq/KWQKHTMLPart.mm
@@ -37,8 +37,10 @@
 #include <kcharsets.h>
 #include <kglobal.h>
 #include <html/htmltokenizer.h>
+#include <html/html_imageimpl.h>
 #include <xml/dom_docimpl.h>
 #include <html/html_documentimpl.h>
+#include <rendering/render_image.h>
 #include <loader.h>
 #include <kjs.h>
 #include <kjs_dom.h>
@@ -113,10 +115,27 @@ public:
     bool m_haveEncoding:1;
     bool m_haveCharset:1;
     bool m_onlyLocalReferences:1;
+    bool m_startBeforeEnd:1;
 
     KJSProxy *m_jscript;
     int m_runningScripts;
 
+    QString m_strSelectedURL;
+    QString m_referrer;
+
+    bool m_bMousePressed;
+    DOM::Node m_mousePressNode; //node under the mouse when the mouse was pressed (set in the mouse handler)
+    DOM::Node m_selectionStart;
+    long m_startOffset;
+    DOM::Node m_selectionEnd;
+    long m_endOffset;
+    QString m_overURL;
+   
+    QPoint m_dragStartPos;
+#ifdef KHTML_NO_SELECTION
+    QPoint m_dragLastPos;
+#endif
+
     KHTMLPartPrivate(KHTMLPart *part)
     {
         if (!cache_init) {
@@ -732,6 +751,385 @@ const KHTMLSettings *KHTMLPart::settings() const
 }
 
 
+bool KHTMLPart::event( QEvent *event )
+{
+    if ( khtml::MousePressEvent::test( event ) )
+    {
+        khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseDoubleClickEvent::test( event ) )
+    {
+        khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseMoveEvent::test( event ) )
+    {
+        khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) ); 
+        return true;
+    }
+    
+    if ( khtml::MouseReleaseEvent::test( event ) )
+    {
+        khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::DrawContentsEvent::test( event ) )
+    {
+        khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
+        return true;
+    }
+    
+    return false;
+}
+
+void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
+{
+  DOM::DOMString url = event->url();
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = innerNode;
+
+   d->m_dragStartPos = _mouse->pos();
+
+  if ( event->url() != 0 )
+    d->m_strSelectedURL = event->url().string();
+  else
+    d->m_strSelectedURL = QString::null;
+
+  if ( _mouse->button() == LeftButton ||
+       _mouse->button() == MidButton )
+  {
+    d->m_bMousePressed = true;
+
+#ifndef KHTML_NO_SELECTION
+    if ( _mouse->button() == LeftButton )
+    {
+      if ( !innerNode.isNull() )
+      {
+          int offset;
+          DOM::Node node;
+          innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                            event->nodeAbsX(), event->nodeAbsY(),
+                                                 node, offset );
+
+        if ( node.isNull() || !node.handle() )
+        {
+            //kdDebug( 6000 ) << "Hmm, findSelectionNode returned no node" << endl;
+            d->m_selectionStart = innerNode;
+            d->m_startOffset = 0; //?
+        } else {
+            d->m_selectionStart = node;
+            d->m_startOffset = offset;
+        }
+        //kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
+        //              << " offset=" << d->m_startOffset << endl;
+        d->m_selectionEnd = d->m_selectionStart;
+        d->m_endOffset = d->m_startOffset;
+        d->m_doc->clearSelection();
+      }
+      else
+      {
+        d->m_selectionStart = DOM::Node();
+        d->m_selectionEnd = DOM::Node();
+      }
+      //emitSelectionChanged();
+      //startAutoScroll();
+    }
+#else
+    d->m_dragLastPos = _mouse->globalPos();
+#endif
+  }
+
+  if ( _mouse->button() == RightButton )
+  {
+    //popupMenu( splitUrlTarget(d->m_strSelectedURL) );
+    d->m_strSelectedURL = QString::null;
+  }
+}
+
+void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent * )
+{
+}
+
+static QString splitUrlTarget(const QString &url, QString *target=0)
+{
+   QString result = url;
+   if(url.left(7) == "target:")
+   {
+      KURL u(url);
+      result = u.ref();
+      if (target)
+         *target = u.host();
+   }
+   return result;
+}
+
+void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::DOMString url = event->url();
+  DOM::Node innerNode = event->innerNode();
+
+#define QT_NO_DRAGANDDROP 1
+#ifndef QT_NO_DRAGANDDROP
+  if( d->m_bMousePressed && (!d->m_strSelectedURL.isEmpty() || (!innerNode.isNull() && innerNode.elementId() == ID_IMG) ) &&
+      ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay() &&
+      d->m_bDnd && d->m_mousePressNode == innerNode ) {
+
+      QPixmap p;
+      QDragObject *drag = 0;
+      if( !d->m_strSelectedURL.isEmpty() ) {
+          KURL u( completeURL( splitUrlTarget(d->m_strSelectedURL)) );
+          KURL::List uris;
+          uris.append(u);
+          drag = KURLDrag::newDrag( uris, d->m_view->viewport() );
+          p = KMimeType::pixmapForURL(u, 0, KIcon::SizeMedium);
+      } else {
+          HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+          if( i ) {
+            drag = new QImageDrag( i->currentImage() , d->m_view->viewport() );
+            p = KMimeType::mimeType("image/*")->pixmap(KIcon::Desktop);
+          }
+      }
+
+    if ( !p.isNull() )
+      drag->setPixmap(p);
+
+    stopAutoScroll();
+    if(drag)
+        drag->drag();
+
+    // when we finish our drag, we need to undo our mouse press
+    d->m_bMousePressed = false;
+    d->m_strSelectedURL = "";
+    return;
+  }
+#endif
+
+  QString target;
+  QString surl = splitUrlTarget(url.string(), &target);
+
+  // Not clicked -> mouse over stuff
+  if ( !d->m_bMousePressed )
+  {
+    // The mouse is over something
+    if ( url.length() )
+    {
+      bool shiftPressed = ( _mouse->state() & ShiftButton );
+
+      // Image map
+      if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
+      {
+        HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+        if ( i && i->isServerMap() )
+        {
+          khtml::RenderImage *r = static_cast<khtml::RenderImage *>(i->renderer());
+          if(r)
+          {
+            int absx, absy, vx, vy;
+            r->absolutePosition(absx, absy);
+            //view()->contentsToViewport( absx, absy, vx, vy );
+
+            int x(_mouse->x() - vx), y(_mouse->y() - vy);
+
+            d->m_overURL = surl + QString("?%1,%2").arg(x).arg(y);
+            //overURL( d->m_overURL, target, shiftPressed );
+            return;
+          }
+        }
+      }
+
+      // normal link
+      QString target;
+      QString surl = splitUrlTarget(url.string(), &target);
+      if ( d->m_overURL.isEmpty() || d->m_overURL != surl )
+      {
+        d->m_overURL = surl;
+        //overURL( d->m_overURL, target, shiftPressed );
+      }
+    }
+    else  // Not over a link...
+    {
+      if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
+      {
+        d->m_overURL = QString::null;
+        //emit onURL( QString::null );
+        // Default statusbar text can be set from javascript. Otherwise it's empty.
+        //emit setStatusBarText( d->m_kjsDefaultStatusBarText );
+      }
+    }
+  }
+  else {
+#ifndef KHTML_NO_SELECTION
+    // selection stuff
+    if( d->m_bMousePressed && !innerNode.isNull() && ( _mouse->state() == LeftButton )) {
+      int offset;
+      DOM::Node node;
+      //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y()
+      //              << " nodeAbsX=" << event->nodeAbsX() << " nodeAbsY=" << event->nodeAbsY()
+      //              << endl;
+      innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                             event->nodeAbsX(), event->nodeAbsY(),
+                                             node, offset );
+      // When this stuff is finished, this should never happen.
+      // But currently....
+      if ( node.isNull() || !node.handle() )
+      {
+        //kdWarning( 6000 ) << "findSelectionNode returned no node" << endl;
+        d->m_selectionEnd = innerNode;
+        d->m_endOffset = 0; //?
+      }
+      else
+      {
+        d->m_selectionEnd = node;
+        d->m_endOffset = offset;
+      }
+      //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle()->renderer() << "/"
+      //                << d->m_endOffset << endl;
+
+      // we have to get to know if end is before start or not...
+      DOM::Node n = d->m_selectionStart;
+      d->m_startBeforeEnd = false;
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+        //d->m_view->viewport()->repaint(false);
+      }
+
+      if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
+      {
+        if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
+                           d->m_selectionEnd.handle(),d->m_startOffset);
+        else if (d->m_startBeforeEnd)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+                           d->m_selectionEnd.handle(),d->m_endOffset);
+        else
+          d->m_doc
+            ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
+                           d->m_selectionStart.handle(),d->m_startOffset);
+      }
+#else
+      if ( d->m_doc && d->m_view ) {
+        QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
+
+        if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
+          d->m_view->scrollBy( -diff.x(), -diff.y() );
+          d->m_dragLastPos = _mouse->globalPos();
+        }
+#endif
+    }
+  }
+
+}
+
+void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = DOM::Node();
+
+  if ( d->m_bMousePressed )
+    stopAutoScroll();
+
+  // Used to prevent mouseMoveEvent from initiating a drag before
+  // the mouse is pressed again.
+  d->m_bMousePressed = false;
+
+    openURL (KURL(completeURL( splitUrlTarget(d->m_strSelectedURL))));
+    
+#define QT_NO_CLIPBOARD 1
+#ifndef QT_NO_CLIPBOARD
+  if ((_mouse->button() == MidButton) && (event->url() == 0))
+  {
+    QClipboard *cb = QApplication::clipboard();
+    QCString plain("plain");
+    QString url = cb->text(plain);
+    KURL u(url);
+    if (u.isValid())
+    {
+      QString savedReferrer = d->m_referrer;
+      d->m_referrer = QString::null; // Disable referrer.
+      urlSelected(url, 0,0, "_top");
+      d->m_referrer = savedReferrer; // Restore original referrer.
+    }
+  }
+#endif
+
+#ifndef KHTML_NO_SELECTION
+  // delete selection in case start and end position are at the same point
+  if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
+    d->m_selectionStart = 0;
+    d->m_selectionEnd = 0;
+    d->m_startOffset = 0;
+    d->m_endOffset = 0;
+    //emitSelectionChanged();
+  } else {
+    // we have to get to know if end is before start or not...
+    DOM::Node n = d->m_selectionStart;
+    d->m_startBeforeEnd = false;
+    if( d->m_selectionStart == d->m_selectionEnd ) {
+      if( d->m_startOffset < d->m_endOffset )
+        d->m_startBeforeEnd = true;
+    } else {
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+      }
+    }
+    if(!d->m_startBeforeEnd)
+    {
+      DOM::Node tmpNode = d->m_selectionStart;
+      int tmpOffset = d->m_startOffset;
+      d->m_selectionStart = d->m_selectionEnd;
+      d->m_startOffset = d->m_endOffset;
+      d->m_selectionEnd = tmpNode;
+      d->m_endOffset = tmpOffset;
+      d->m_startBeforeEnd = true;
+    }
+    // get selected text and paste to the clipboard
+#ifndef QT_NO_CLIPBOARD
+    QString text = selectedText();
+    text.replace(QRegExp(QChar(0xa0)), " ");
+    QClipboard *cb = QApplication::clipboard();
+    cb->setText(text);
+#endif
+    //kdDebug( 6000 ) << "selectedText = " << text << endl;
+    //emitSelectionChanged();
+  }
+#endif
+}
+
+void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
+{
+}
+
+
+
 KJSProxy *KHTMLPart::jScript()
 {
   if ( !d->m_jscript )
@@ -880,9 +1278,7 @@ void KHTMLPart::submitForm( const char *action, const QString &url, const QByteA
     _logNeverImplemented();
 }
 
-
-void KHTMLPart::urlSelected( const QString &url, int button = 0, int state = 0,
-                        const QString &_target = QString::null )
+void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target )
 {
     _logNeverImplemented();
 }
@@ -896,9 +1292,9 @@ bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, con
 }
 
 
-void KHTMLPart::nodeActivated(const DOM::Node &)
+void KHTMLPart::nodeActivated(const DOM::Node &aNode)
 {
-    _logNeverImplemented();
+    KWQDEBUG2 ("name %s = %s\n", (const char *)aNode.nodeName().string(), (const char *)aNode.nodeValue().string());
 }
 
 
diff --git a/WebCore/kwq/KWQKHTMLPartImpl.mm b/WebCore/kwq/KWQKHTMLPartImpl.mm
index 9800307..1c25e81 100644
--- a/WebCore/kwq/KWQKHTMLPartImpl.mm
+++ b/WebCore/kwq/KWQKHTMLPartImpl.mm
@@ -37,8 +37,10 @@
 #include <kcharsets.h>
 #include <kglobal.h>
 #include <html/htmltokenizer.h>
+#include <html/html_imageimpl.h>
 #include <xml/dom_docimpl.h>
 #include <html/html_documentimpl.h>
+#include <rendering/render_image.h>
 #include <loader.h>
 #include <kjs.h>
 #include <kjs_dom.h>
@@ -113,10 +115,27 @@ public:
     bool m_haveEncoding:1;
     bool m_haveCharset:1;
     bool m_onlyLocalReferences:1;
+    bool m_startBeforeEnd:1;
 
     KJSProxy *m_jscript;
     int m_runningScripts;
 
+    QString m_strSelectedURL;
+    QString m_referrer;
+
+    bool m_bMousePressed;
+    DOM::Node m_mousePressNode; //node under the mouse when the mouse was pressed (set in the mouse handler)
+    DOM::Node m_selectionStart;
+    long m_startOffset;
+    DOM::Node m_selectionEnd;
+    long m_endOffset;
+    QString m_overURL;
+   
+    QPoint m_dragStartPos;
+#ifdef KHTML_NO_SELECTION
+    QPoint m_dragLastPos;
+#endif
+
     KHTMLPartPrivate(KHTMLPart *part)
     {
         if (!cache_init) {
@@ -732,6 +751,385 @@ const KHTMLSettings *KHTMLPart::settings() const
 }
 
 
+bool KHTMLPart::event( QEvent *event )
+{
+    if ( khtml::MousePressEvent::test( event ) )
+    {
+        khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseDoubleClickEvent::test( event ) )
+    {
+        khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseMoveEvent::test( event ) )
+    {
+        khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) ); 
+        return true;
+    }
+    
+    if ( khtml::MouseReleaseEvent::test( event ) )
+    {
+        khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::DrawContentsEvent::test( event ) )
+    {
+        khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
+        return true;
+    }
+    
+    return false;
+}
+
+void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
+{
+  DOM::DOMString url = event->url();
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = innerNode;
+
+   d->m_dragStartPos = _mouse->pos();
+
+  if ( event->url() != 0 )
+    d->m_strSelectedURL = event->url().string();
+  else
+    d->m_strSelectedURL = QString::null;
+
+  if ( _mouse->button() == LeftButton ||
+       _mouse->button() == MidButton )
+  {
+    d->m_bMousePressed = true;
+
+#ifndef KHTML_NO_SELECTION
+    if ( _mouse->button() == LeftButton )
+    {
+      if ( !innerNode.isNull() )
+      {
+          int offset;
+          DOM::Node node;
+          innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                            event->nodeAbsX(), event->nodeAbsY(),
+                                                 node, offset );
+
+        if ( node.isNull() || !node.handle() )
+        {
+            //kdDebug( 6000 ) << "Hmm, findSelectionNode returned no node" << endl;
+            d->m_selectionStart = innerNode;
+            d->m_startOffset = 0; //?
+        } else {
+            d->m_selectionStart = node;
+            d->m_startOffset = offset;
+        }
+        //kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
+        //              << " offset=" << d->m_startOffset << endl;
+        d->m_selectionEnd = d->m_selectionStart;
+        d->m_endOffset = d->m_startOffset;
+        d->m_doc->clearSelection();
+      }
+      else
+      {
+        d->m_selectionStart = DOM::Node();
+        d->m_selectionEnd = DOM::Node();
+      }
+      //emitSelectionChanged();
+      //startAutoScroll();
+    }
+#else
+    d->m_dragLastPos = _mouse->globalPos();
+#endif
+  }
+
+  if ( _mouse->button() == RightButton )
+  {
+    //popupMenu( splitUrlTarget(d->m_strSelectedURL) );
+    d->m_strSelectedURL = QString::null;
+  }
+}
+
+void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent * )
+{
+}
+
+static QString splitUrlTarget(const QString &url, QString *target=0)
+{
+   QString result = url;
+   if(url.left(7) == "target:")
+   {
+      KURL u(url);
+      result = u.ref();
+      if (target)
+         *target = u.host();
+   }
+   return result;
+}
+
+void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::DOMString url = event->url();
+  DOM::Node innerNode = event->innerNode();
+
+#define QT_NO_DRAGANDDROP 1
+#ifndef QT_NO_DRAGANDDROP
+  if( d->m_bMousePressed && (!d->m_strSelectedURL.isEmpty() || (!innerNode.isNull() && innerNode.elementId() == ID_IMG) ) &&
+      ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay() &&
+      d->m_bDnd && d->m_mousePressNode == innerNode ) {
+
+      QPixmap p;
+      QDragObject *drag = 0;
+      if( !d->m_strSelectedURL.isEmpty() ) {
+          KURL u( completeURL( splitUrlTarget(d->m_strSelectedURL)) );
+          KURL::List uris;
+          uris.append(u);
+          drag = KURLDrag::newDrag( uris, d->m_view->viewport() );
+          p = KMimeType::pixmapForURL(u, 0, KIcon::SizeMedium);
+      } else {
+          HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+          if( i ) {
+            drag = new QImageDrag( i->currentImage() , d->m_view->viewport() );
+            p = KMimeType::mimeType("image/*")->pixmap(KIcon::Desktop);
+          }
+      }
+
+    if ( !p.isNull() )
+      drag->setPixmap(p);
+
+    stopAutoScroll();
+    if(drag)
+        drag->drag();
+
+    // when we finish our drag, we need to undo our mouse press
+    d->m_bMousePressed = false;
+    d->m_strSelectedURL = "";
+    return;
+  }
+#endif
+
+  QString target;
+  QString surl = splitUrlTarget(url.string(), &target);
+
+  // Not clicked -> mouse over stuff
+  if ( !d->m_bMousePressed )
+  {
+    // The mouse is over something
+    if ( url.length() )
+    {
+      bool shiftPressed = ( _mouse->state() & ShiftButton );
+
+      // Image map
+      if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
+      {
+        HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+        if ( i && i->isServerMap() )
+        {
+          khtml::RenderImage *r = static_cast<khtml::RenderImage *>(i->renderer());
+          if(r)
+          {
+            int absx, absy, vx, vy;
+            r->absolutePosition(absx, absy);
+            //view()->contentsToViewport( absx, absy, vx, vy );
+
+            int x(_mouse->x() - vx), y(_mouse->y() - vy);
+
+            d->m_overURL = surl + QString("?%1,%2").arg(x).arg(y);
+            //overURL( d->m_overURL, target, shiftPressed );
+            return;
+          }
+        }
+      }
+
+      // normal link
+      QString target;
+      QString surl = splitUrlTarget(url.string(), &target);
+      if ( d->m_overURL.isEmpty() || d->m_overURL != surl )
+      {
+        d->m_overURL = surl;
+        //overURL( d->m_overURL, target, shiftPressed );
+      }
+    }
+    else  // Not over a link...
+    {
+      if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
+      {
+        d->m_overURL = QString::null;
+        //emit onURL( QString::null );
+        // Default statusbar text can be set from javascript. Otherwise it's empty.
+        //emit setStatusBarText( d->m_kjsDefaultStatusBarText );
+      }
+    }
+  }
+  else {
+#ifndef KHTML_NO_SELECTION
+    // selection stuff
+    if( d->m_bMousePressed && !innerNode.isNull() && ( _mouse->state() == LeftButton )) {
+      int offset;
+      DOM::Node node;
+      //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y()
+      //              << " nodeAbsX=" << event->nodeAbsX() << " nodeAbsY=" << event->nodeAbsY()
+      //              << endl;
+      innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                             event->nodeAbsX(), event->nodeAbsY(),
+                                             node, offset );
+      // When this stuff is finished, this should never happen.
+      // But currently....
+      if ( node.isNull() || !node.handle() )
+      {
+        //kdWarning( 6000 ) << "findSelectionNode returned no node" << endl;
+        d->m_selectionEnd = innerNode;
+        d->m_endOffset = 0; //?
+      }
+      else
+      {
+        d->m_selectionEnd = node;
+        d->m_endOffset = offset;
+      }
+      //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle()->renderer() << "/"
+      //                << d->m_endOffset << endl;
+
+      // we have to get to know if end is before start or not...
+      DOM::Node n = d->m_selectionStart;
+      d->m_startBeforeEnd = false;
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+        //d->m_view->viewport()->repaint(false);
+      }
+
+      if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
+      {
+        if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
+                           d->m_selectionEnd.handle(),d->m_startOffset);
+        else if (d->m_startBeforeEnd)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+                           d->m_selectionEnd.handle(),d->m_endOffset);
+        else
+          d->m_doc
+            ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
+                           d->m_selectionStart.handle(),d->m_startOffset);
+      }
+#else
+      if ( d->m_doc && d->m_view ) {
+        QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
+
+        if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
+          d->m_view->scrollBy( -diff.x(), -diff.y() );
+          d->m_dragLastPos = _mouse->globalPos();
+        }
+#endif
+    }
+  }
+
+}
+
+void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = DOM::Node();
+
+  if ( d->m_bMousePressed )
+    stopAutoScroll();
+
+  // Used to prevent mouseMoveEvent from initiating a drag before
+  // the mouse is pressed again.
+  d->m_bMousePressed = false;
+
+    openURL (KURL(completeURL( splitUrlTarget(d->m_strSelectedURL))));
+    
+#define QT_NO_CLIPBOARD 1
+#ifndef QT_NO_CLIPBOARD
+  if ((_mouse->button() == MidButton) && (event->url() == 0))
+  {
+    QClipboard *cb = QApplication::clipboard();
+    QCString plain("plain");
+    QString url = cb->text(plain);
+    KURL u(url);
+    if (u.isValid())
+    {
+      QString savedReferrer = d->m_referrer;
+      d->m_referrer = QString::null; // Disable referrer.
+      urlSelected(url, 0,0, "_top");
+      d->m_referrer = savedReferrer; // Restore original referrer.
+    }
+  }
+#endif
+
+#ifndef KHTML_NO_SELECTION
+  // delete selection in case start and end position are at the same point
+  if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
+    d->m_selectionStart = 0;
+    d->m_selectionEnd = 0;
+    d->m_startOffset = 0;
+    d->m_endOffset = 0;
+    //emitSelectionChanged();
+  } else {
+    // we have to get to know if end is before start or not...
+    DOM::Node n = d->m_selectionStart;
+    d->m_startBeforeEnd = false;
+    if( d->m_selectionStart == d->m_selectionEnd ) {
+      if( d->m_startOffset < d->m_endOffset )
+        d->m_startBeforeEnd = true;
+    } else {
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+      }
+    }
+    if(!d->m_startBeforeEnd)
+    {
+      DOM::Node tmpNode = d->m_selectionStart;
+      int tmpOffset = d->m_startOffset;
+      d->m_selectionStart = d->m_selectionEnd;
+      d->m_startOffset = d->m_endOffset;
+      d->m_selectionEnd = tmpNode;
+      d->m_endOffset = tmpOffset;
+      d->m_startBeforeEnd = true;
+    }
+    // get selected text and paste to the clipboard
+#ifndef QT_NO_CLIPBOARD
+    QString text = selectedText();
+    text.replace(QRegExp(QChar(0xa0)), " ");
+    QClipboard *cb = QApplication::clipboard();
+    cb->setText(text);
+#endif
+    //kdDebug( 6000 ) << "selectedText = " << text << endl;
+    //emitSelectionChanged();
+  }
+#endif
+}
+
+void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
+{
+}
+
+
+
 KJSProxy *KHTMLPart::jScript()
 {
   if ( !d->m_jscript )
@@ -880,9 +1278,7 @@ void KHTMLPart::submitForm( const char *action, const QString &url, const QByteA
     _logNeverImplemented();
 }
 
-
-void KHTMLPart::urlSelected( const QString &url, int button = 0, int state = 0,
-                        const QString &_target = QString::null )
+void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target )
 {
     _logNeverImplemented();
 }
@@ -896,9 +1292,9 @@ bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, con
 }
 
 
-void KHTMLPart::nodeActivated(const DOM::Node &)
+void KHTMLPart::nodeActivated(const DOM::Node &aNode)
 {
-    _logNeverImplemented();
+    KWQDEBUG2 ("name %s = %s\n", (const char *)aNode.nodeName().string(), (const char *)aNode.nodeValue().string());
 }
 
 
diff --git a/WebCore/kwq/KWQKPartsEvent.mm b/WebCore/kwq/KWQKPartsEvent.mm
index af77203..1db8659 100644
--- a/WebCore/kwq/KWQKPartsEvent.mm
+++ b/WebCore/kwq/KWQKPartsEvent.mm
@@ -28,24 +28,30 @@
 
 class QPainter;
 
+#define KPARTS_EVENT_MAGIC 42
+
 namespace KParts {
 
-bool Event::test(const QEvent *)
+bool Event::test(const QEvent *event)
 {
-    _logNotYetImplemented();
-    return FALSE;
+  if ( !event )
+    return false;
+  
+  return ( event->type() == (QEvent::Type)(1000 + KPARTS_EVENT_MAGIC ) );
 }
 
-bool Event::test(const QEvent *, const char *)
+bool Event::test(const QEvent *event, const char *name)
 {
-    _logNotYetImplemented();
-    return FALSE;
+  if ( !test( event ) )
+    return false;
+  
+  return ( strcmp( name, (const char *)((QCustomEvent *)event)->data() ) == 0 );
 }
 
 
-Event::Event(const char *)
+Event::Event(const char *eventName)
+ : QCustomEvent( (QEvent::Type)(1000 + KPARTS_EVENT_MAGIC), (void *)eventName )
 {
-    //_logNotYetImplemented();
 }
 
 } // namespace KParts
diff --git a/WebCore/kwq/KWQMetrics.h b/WebCore/kwq/KWQMetrics.h
index bba5e2c..be095c8 100644
--- a/WebCore/kwq/KWQMetrics.h
+++ b/WebCore/kwq/KWQMetrics.h
@@ -27,19 +27,20 @@
 
 #import <Cocoa/Cocoa.h>
 
- at interface KWQMetricsInfo : NSObject
+ at interface KWQLayoutInfo : NSObject
 {
     NSMutableDictionary *attributes;
     NSMutableDictionary *fragmentCache;
 }
 
 + (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color;
-+ (KWQMetricsInfo *)getMetricsForFont: (NSFont *)aFont;
-+ (void)setMetric: (KWQMetricsInfo *)info forFont: (NSFont *)aFont;
++ (KWQLayoutInfo *)getMetricsForFont: (NSFont *)aFont;
++ (void)setMetric: (KWQLayoutInfo *)info forFont: (NSFont *)aFont;
 - initWithFont: (NSFont *)aFont;
 - (NSRect)rectForString:(NSString *)string;
 - (NSLayoutManager *)layoutManagerForString: (NSString *)string;
 - (void)setColor: (NSColor *)color;
+- (void)setFont: (NSFont *)aFont;
 @end
 
 @interface KWQLayoutFragment : NSObject
diff --git a/WebCore/kwq/KWQPainter.mm b/WebCore/kwq/KWQPainter.mm
index 10a0acc..9274f51 100644
--- a/WebCore/kwq/KWQPainter.mm
+++ b/WebCore/kwq/KWQPainter.mm
@@ -457,10 +457,13 @@ void QPainter::drawTiledPixmap( int x, int y, int w, int h,
     drawTile( this, x, y, w, h, pixmap, sx, sy );
 }
 
+#define FAST_CACHE_DRAWING 1
+
+#ifdef HACK_FAST_DRAWING
 @interface NSLayoutManager (Private)
 - (char *)_packedGlyphs:(NSMultibyteGlyphPacking)packing range:(NSRange)glyphRange length:(unsigned *)len;
 @end
-
+#endif
 
 // y is the baseline
 void QPainter::drawText(int x, int y, const QString &qstring, int len)
@@ -482,17 +485,21 @@ void QPainter::drawText(int x, int y, const QString &qstring, int len)
     // This will draw the text from the top of the bounding box down.
     // Qt expects to draw from the baseline.
     y = y - (int)([font defaultLineHeightForFont] + [font descender]);
-    //[string drawAtPoint:NSMakePoint(x, y) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, data->qpen.color().color, NSForegroundColorAttributeName, nil]];
 
-    [KWQMetricsInfo drawString: string atPoint: NSMakePoint(x, y) withFont: font color: data->qpen.color().color];
-//    KWQMetricsInfo *metricsCache = [KWQMetricsInfo getMetricsForFont: font];
-//    NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
-//    if (layoutManager != nil){
-//        unsigned numberOfGlyphs = [layoutManager numberOfGlyphs];
-//        [metricsCache setColor: data->qpen.color().color];
-//        [layoutManager drawGlyphsForGlyphRange:NSMakeRange (0, numberOfGlyphs) atPoint:NSMakePoint(x, y)];
+#ifdef SLOW_SAFE_DRAWING
+
+    [string drawAtPoint:NSMakePoint(x, y) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, data->qpen.color().color, NSForegroundColorAttributeName, nil]];
+
+#elif FAST_CACHE_DRAWING
+
+    [KWQLayoutInfo drawString: string atPoint: NSMakePoint(x, y) withFont: font color: data->qpen.color().color];
+
+#elif HACK_FAST_DRAWING
+
+    KWQLayoutInfo *metricsCache = [KWQLayoutInfo getMetricsForFont: font];
+    NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
+    if (layoutManager != nil){
 
-/*
         [font set];
         [data->qpen.color().color set];
         
@@ -507,8 +514,9 @@ void QPainter::drawText(int x, int y, const QString &qstring, int len)
         [layoutManager showPackedGlyphs:glyphBuf length:glyphLen glyphRange:NSMakeRange (0, numberOfGlyphs)  atPoint:NSMakePoint(x, y) font:font color:data->qpen.color().color printingAdjustment:NSMakeSize(0.0, 0.0)];
 
         [graphicsContext setShouldAntialias: flag];
-*/
-//    }
+    }
+
+#endif
 
 
     _unlockFocus();
diff --git a/WebCore/kwq/KWQScrollView.mm b/WebCore/kwq/KWQScrollView.mm
index 633e91a..21ace9c 100644
--- a/WebCore/kwq/KWQScrollView.mm
+++ b/WebCore/kwq/KWQScrollView.mm
@@ -201,7 +201,10 @@ QPoint QScrollView::contentsToViewport(const QPoint &)
 
 void QScrollView::viewportToContents(int vx, int vy, int& x, int& y)
 {
-    _logNeverImplemented();
+    NSPoint p = NSMakePoint (vx, vy);
+    NSPoint np = [getView() convertPoint: NSMakePoint (vx, vy) fromView: nil];
+    x = (int)np.x;
+    y = (int)np.y;
 }
 
 
diff --git a/WebCore/kwq/KWQTextContainer.mm b/WebCore/kwq/KWQTextContainer.mm
index dbdd824..5601b2a 100644
--- a/WebCore/kwq/KWQTextContainer.mm
+++ b/WebCore/kwq/KWQTextContainer.mm
@@ -22,6 +22,17 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
+ 
+ /*
+    This class an it's companion KWQTextStorage are used to optimize 
+    our interaction with NSLayoutManager.  They do very little.
+    KWQTextContainer has a fixed geometry.  It only ever containers
+    a short run of text corresponding to a khtml TextSlave.
+    
+    Both KWQTextStorage and KWQTextContainer are used as singletons.  They
+    are set/reset for layout and rendering.
+ */
+ 
 
 #import <Cocoa/Cocoa.h>
 
@@ -73,28 +84,26 @@ static KWQTextContainer *sharedInstance = nil;
 
 - (void)setContainerSize:(NSSize)aSize
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setContainerSize:(NSSize)aSize"];
 }
 
 - (void)setHeightTracksTextView:(BOOL)flag
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setHeightTracksTextView:(BOOL)flag"];
 }
 
 - (BOOL)heightTracksTextView
 {
-    KWQDEBUG ("not implemented\n");
     return NO;
 }
 
 - (void)setWidthTracksTextView:(BOOL)flag
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setWidthTracksTextView:(BOOL)flag"];
 }
 
 - (BOOL)widthTracksTextView
 {
-    KWQDEBUG ("not implemented\n");
     return NO;
 }
 
diff --git a/WebCore/kwq/KWQTextStorage.h b/WebCore/kwq/KWQTextStorage.h
index 573a68b..37c691e 100644
--- a/WebCore/kwq/KWQTextStorage.h
+++ b/WebCore/kwq/KWQTextStorage.h
@@ -33,4 +33,7 @@
     NSLayoutManager *_layoutManager;
 }
 
++ setString:(NSString *)str attributes:(NSDictionary *)attrs;
+- (void)setString: (NSString *)aString attributes: (NSDictionary *)at;
+
 @end
diff --git a/WebCore/kwq/KWQTextStorage.mm b/WebCore/kwq/KWQTextStorage.mm
index 440f257..1e9a5dc 100644
--- a/WebCore/kwq/KWQTextStorage.mm
+++ b/WebCore/kwq/KWQTextStorage.mm
@@ -29,8 +29,31 @@
 
 #import <KWQTextStorage.h>
 
+/*
+    This class is a dumb text storage implementation.  It is optimized for speed,
+    not flexibility.  It only support read-only text with font and color attributes.
+    
+    It is used, along with KWQTextContainer to spoof NSLayoutManager.  KWQTextStorage
+    and KWQTextContainer are both used as singletons.  They are set/reset to contain the
+    correct attributes (font and color only) during layout and rendering.
+*/
+
 @implementation KWQTextStorage
 
+static KWQTextStorage *sharedInstance = nil;
+
++ (KWQTextStorage *)sharedInstance
+{
+    if (sharedInstance == nil)
+        sharedInstance = [[KWQTextStorage alloc] init];
+    return sharedInstance;
+}
+
++ setString:(NSString *)str attributes:(NSDictionary *)attrs 
+{
+    [[KWQTextStorage sharedInstance] setString: str attributes: attrs];
+}
+
 - (id)initWithString:(NSString *)str attributes:(NSDictionary *)attrs 
 {
     attrString = [str retain];
@@ -81,51 +104,77 @@
     return [attrString length];
 }
 
+- (void)setString: (NSString *)aString attributes: (NSDictionary *)at
+{
+    if (aString != attrString){
+        [attrString release];
+        attrString = [aString retain];
+    }
+
+    if (at != attributes){
+        [attributes release];
+        attributes = [at retain];
+    }
+}
+
+
 - (NSString *)string 
 {
     return attrString;
 }
 
+
 - (NSDictionary *)attributesAtIndex:(unsigned)location effectiveRange:(NSRangePointer)range 
 {
-    range->location = 0;
-    range->length = [self length];
+    if (range != 0){
+        range->location = 0;
+        range->length = [self length];
+    }
     return attributes;
 }
 
+
 - (NSDictionary *)attributesAtIndex:(unsigned)location longestEffectiveRange:(NSRangePointer)range inRange:(NSRange)rangeLimit
 {
-    range->location = rangeLimit.location;
-    range->length = rangeLimit.length;
+    if (range != 0){
+        range->location = rangeLimit.location;
+        range->length = rangeLimit.length;
+    }
     return attributes;
 }
 
+
 - (id)attribute:(NSString *)attrName atIndex:(unsigned)location effectiveRange:(NSRangePointer)range 
 {
-    range->location = 0;
-    range->length = [self length];
+    if (range != 0){
+        range->location = 0;
+        range->length = [self length];
+    }
     return [attributes objectForKey: attrName];
 }
 
+
 - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range 
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range"];
 }
 
 
 - (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)str 
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)str"];
 }
 
+
 - (void)addAttribute:(NSString *)name value:value range:(NSRange)range
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)addAttribute:(NSString *)name value:value range:(NSRange)range"];
 }
 
+
 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange"];
     return nil;
 }
 
diff --git a/WebCore/kwq/KWQView.mm b/WebCore/kwq/KWQView.mm
index f3ce72d..7c266c1 100644
--- a/WebCore/kwq/KWQView.mm
+++ b/WebCore/kwq/KWQView.mm
@@ -29,6 +29,7 @@
 #include <khtmlview.h>
 #include <qwidget.h>
 #include <qpainter.h>
+#include <qevent.h>
 #include <html/html_documentimpl.h>
 
 
@@ -217,12 +218,46 @@
 
 - (void)mouseUp: (NSEvent *)event
 {
-    KWQDEBUGLEVEL1 (0x100, "mouseUp %s\n", DEBUG_OBJECT(event));
+    int button, state;
+     
+    if ([event type] == NSLeftMouseDown){
+        button = Qt::LeftButton;
+        state = Qt::LeftButton;
+    }
+    else if ([event type] == NSRightMouseDown){
+        button = Qt::RightButton;
+        state = Qt::RightButton;
+    }
+    else if ([event type] == NSOtherMouseDown){
+        button = Qt::MidButton;
+        state = Qt::MidButton;
+    }
+    NSPoint p = [event locationInWindow];
+    
+    QMouseEvent *kEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(p.x, p.y), button, state);
+    ((KHTMLView *)widget)->viewportMouseReleaseEvent(kEvent);
 }
 
 - (void)mouseDown: (NSEvent *)event
 {
-    KWQDEBUGLEVEL1 (0x100, "mouseDown %s\n", DEBUG_OBJECT(event));
+    int button, state;
+     
+    if ([event type] == NSLeftMouseDown){
+        button = Qt::LeftButton;
+        state = Qt::LeftButton;
+    }
+    else if ([event type] == NSRightMouseDown){
+        button = Qt::RightButton;
+        state = Qt::RightButton;
+    }
+    else if ([event type] == NSOtherMouseDown){
+        button = Qt::MidButton;
+        state = Qt::MidButton;
+    }
+    NSPoint p = [event locationInWindow];
+    
+    QMouseEvent *kEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(p.x, p.y), button, state);
+    ((KHTMLView *)widget)->viewportMousePressEvent(kEvent);
 }
 
 - (void)mouseDragged: (NSEvent *)event
diff --git a/WebCore/kwq/qt/qevent.h b/WebCore/kwq/qt/qevent.h
index 69eafd0..53817be 100644
--- a/WebCore/kwq/qt/qevent.h
+++ b/WebCore/kwq/qt/qevent.h
@@ -64,7 +64,7 @@ public:
     QEvent() {}
 #endif
 
-    QEvent(Type);
+    QEvent( Type t ) : _type(t) {}
     virtual ~QEvent();
 
     // member functions --------------------------------------------------------
@@ -89,7 +89,7 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QEvent &operator=(const QEvent &);
 #endif
-
+    Type  _type;
 }; // class QEvent =============================================================
 
 
@@ -146,6 +146,9 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QMouseEvent &operator=(const QMouseEvent &);
 #endif
+    QPoint _position;
+    int	   _button; // ### Make ushort in 3.0? Here it's an int...
+    ushort _state; // ### ...and here an ushort. But both are ButtonState!
 
 }; // class QMouseEvent ========================================================
 
@@ -492,20 +495,11 @@ private:
 
 class QCustomEvent : public QEvent {
 public:
-
-    // typedefs ----------------------------------------------------------------
-    // enums -------------------------------------------------------------------
-    // constants ---------------------------------------------------------------
-    // static member functions -------------------------------------------------
-    
-    // constructors, copy constructors, and destructors ------------------------
-    
-// add no-arg constructor
-#ifdef _KWQ_PEDANTIC_
-    QCustomEvent() {}
-#endif
-
-    QCustomEvent(Type);
+    QCustomEvent( int type );
+    QCustomEvent( Type type, void *data )
+	: QEvent(type), d(data) {};
+    void       *data()	const	{ return d; }
+    void	setData( void* data )	{ d = data; }
 
 // add no-op destructor
 #ifdef _KWQ_PEDANTIC_
@@ -519,6 +513,7 @@ public:
 // private ---------------------------------------------------------------------
 
 private:
+    void       *d;
 
 // add copy constructor
 // this private declaration prevents copying
diff --git a/WebCore/src/kdelibs/khtml/khtmlview.cpp b/WebCore/src/kdelibs/khtml/khtmlview.cpp
index c9df49b..0b59bf0 100644
--- a/WebCore/src/kdelibs/khtml/khtmlview.cpp
+++ b/WebCore/src/kdelibs/khtml/khtmlview.cpp
@@ -323,7 +323,11 @@ void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
     }
 
     khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
 }
 
 void KHTMLView::layout(bool)
@@ -403,7 +407,11 @@ void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
 
     khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
 
     emit m_part->nodeActivated(mev.innerNode);
 }
@@ -441,7 +449,12 @@ void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
 
     khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 
     // ###
     //if ( url.length() )
@@ -531,7 +544,12 @@ void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
 
     khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 }
 
 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
@@ -559,7 +577,12 @@ void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
 
     khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.innerNode );
     event.setNodePos( mev.nodeAbsX, mev.nodeAbsY );
+#ifdef _KWQ_
+    m_part->event (&event);
+#else
     QApplication::sendEvent( m_part, &event );
+#endif
+
 }
 
 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
diff --git a/WebCore/src/kdelibs/khtml/khtmlview.h b/WebCore/src/kdelibs/khtml/khtmlview.h
index 2e4ea59..76e848b 100644
--- a/WebCore/src/kdelibs/khtml/khtmlview.h
+++ b/WebCore/src/kdelibs/khtml/khtmlview.h
@@ -174,12 +174,6 @@ public:
 
     virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );
 
-signals:
-    void cleared();
-
-protected:
-    void clear();
-
     virtual void resizeEvent ( QResizeEvent * event );
     virtual void showEvent ( QShowEvent * );
     virtual void hideEvent ( QHideEvent *);
@@ -214,6 +208,13 @@ protected:
      */
     void doAutoScroll();
 
+signals:
+    void cleared();
+
+    void clear();
+
+protected:
+
 protected slots:
     void slotPaletteChanged();
 
diff --git a/WebCore/src/kwq/KWQApplication.mm b/WebCore/src/kwq/KWQApplication.mm
index 3943513..83ee325 100644
--- a/WebCore/src/kwq/KWQApplication.mm
+++ b/WebCore/src/kwq/KWQApplication.mm
@@ -76,7 +76,10 @@ void QApplication::restoreOverrideCursor()
 
 bool QApplication::sendEvent(QObject *o, QEvent *e)
 {
-//    _logNotYetImplemented();
+    QEvent::Type type = e->type();
+    
+    KWQDEBUG1 ("received %d\n", type);
+
     return FALSE;
 }
 
diff --git a/WebCore/src/kwq/KWQEvent.mm b/WebCore/src/kwq/KWQEvent.mm
index bedb650..ed4612b 100644
--- a/WebCore/src/kwq/KWQEvent.mm
+++ b/WebCore/src/kwq/KWQEvent.mm
@@ -31,11 +31,6 @@ static const QPoint ORIGIN(0,0);
 
 // class QEvent ================================================================
 
-QEvent::QEvent(Type)
-{
-    //_logNotYetImplemented();
-}
-
 
 QEvent::~QEvent()
 {
@@ -45,30 +40,25 @@ QEvent::~QEvent()
 
 QEvent::Type QEvent::type() const
 {
-    _logNotYetImplemented();
-    return MouseButtonPress;
+    return _type;
 }
 
 
 // class QMouseEvent ===========================================================
 
-QMouseEvent::QMouseEvent(Type type, const QPoint &pos, int button, int state)
-{
-    _logNotYetImplemented();
+QMouseEvent::QMouseEvent( Type t, const QPoint &pos, int b, int s )
+    : QEvent(t), _position(pos), _button(b), _state((ushort)s){
 }
 
-
 int QMouseEvent::x()
 {
-    _logNotYetImplemented();
-    return 0;
+    return (int)_position.x();
 }
 
 
 int QMouseEvent::y()
 {
-    _logNotYetImplemented();
-    return 0;
+    return (int)_position.y();
 }
 
 
@@ -88,30 +78,25 @@ int QMouseEvent::globalY()
 
 const QPoint &QMouseEvent::pos() const
 {
-    _logNotYetImplemented();
-    // FIXME: replace this hack
-    return ORIGIN;
+    return _position;
 }
 
 
 Qt::ButtonState QMouseEvent::button()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_button);
 }
 
 
 Qt::ButtonState QMouseEvent::state()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_state);
 }
 
 
 Qt::ButtonState QMouseEvent::stateAfter()
 {
-    _logNotYetImplemented();
-    return Qt::NoButton;
+    return Qt::ButtonState(_state);
 }
 
 
@@ -224,7 +209,7 @@ void QWheelEvent::ignore()
 
 // class QCustomEvent ===========================================================
 
-QCustomEvent::QCustomEvent(Type)
+QCustomEvent::QCustomEvent( int type )
+    : QEvent( (QEvent::Type)type ), d( 0 )
 {
-    _logNotYetImplemented();
 }
diff --git a/WebCore/src/kwq/KWQFontMetrics.mm b/WebCore/src/kwq/KWQFontMetrics.mm
index 42242c9..a1dfa1d 100644
--- a/WebCore/src/kwq/KWQFontMetrics.mm
+++ b/WebCore/src/kwq/KWQFontMetrics.mm
@@ -78,36 +78,45 @@ const float LargeNumberForText = 1.0e7;
 
 static NSMutableDictionary *metricsCache = nil;
 
- at implementation KWQMetricsInfo
+/*
+    
+*/
+ at implementation KWQLayoutInfo
 
 + (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color
 {
-    KWQMetricsInfo *metricsCache = [KWQMetricsInfo getMetricsForFont: font];
+    KWQLayoutInfo *metricsCache = [KWQLayoutInfo getMetricsForFont: font];
     NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
     if (layoutManager != nil){
         unsigned numberOfGlyphs = [layoutManager numberOfGlyphs];
         [metricsCache setColor: color];
+        [metricsCache setFont: font];
+        [KWQTextStorage setString: string attributes: attributes];
         [layoutManager drawGlyphsForGlyphRange:NSMakeRange (0, numberOfGlyphs) atPoint:p];
     }
 }
 
-+ (KWQMetricsInfo *)getMetricsForFont: (NSFont *)aFont
+
++ (KWQLayoutInfo *)getMetricsForFont: (NSFont *)aFont
 {
-    KWQMetricsInfo *info = (KWQMetricsInfo *)[metricsCache objectForKey: aFont];
+    KWQLayoutInfo *info = (KWQLayoutInfo *)[metricsCache objectForKey: aFont];
     if (info == nil){
-        info = [[KWQMetricsInfo alloc] initWithFont: aFont];
-        [KWQMetricsInfo setMetric: info forFont: aFont];
+        info = [[KWQLayoutInfo alloc] initWithFont: aFont];
+        [KWQLayoutInfo setMetric: info forFont: aFont];
         [info release];
     }
     return info;
 }
-+ (void)setMetric: (KWQMetricsInfo *)info forFont: (NSFont *)aFont
+
+
++ (void)setMetric: (KWQLayoutInfo *)info forFont: (NSFont *)aFont
 {
     if (metricsCache == nil)
         metricsCache = [[NSMutableDictionary alloc] init];
     [metricsCache setObject: info forKey: aFont];
 }
 
+
 - initWithFont: (NSFont *)aFont
 {
     [super init];
@@ -158,6 +167,11 @@ static NSMutableDictionary *metricsCache = nil;
     [attributes setObject: color forKey: NSForegroundColorAttributeName];
 }
 
+- (void)setFont: (NSFont *)aFont
+{
+    [attributes setObject: aFont forKey: NSFontAttributeName];
+}
+
 - (void)dealloc
 {
     [attributes release];
@@ -173,7 +187,7 @@ public:
     QFontMetricsPrivate(NSFont *aFont) 
     {
         font = [aFont retain];
-        info = [[KWQMetricsInfo getMetricsForFont: aFont] retain];
+        info = [[KWQLayoutInfo getMetricsForFont: aFont] retain];
     }
     
     ~QFontMetricsPrivate()
@@ -189,7 +203,7 @@ public:
     }
     
 private:
-    KWQMetricsInfo *info;
+    KWQLayoutInfo *info;
     NSFont *font;
 };
 
diff --git a/WebCore/src/kwq/KWQKHTMLPart.h b/WebCore/src/kwq/KWQKHTMLPart.h
index edea99b..d2f27a0 100644
--- a/WebCore/src/kwq/KWQKHTMLPart.h
+++ b/WebCore/src/kwq/KWQKHTMLPart.h
@@ -33,6 +33,8 @@
 #include <kparts/part.h>
 #include <kparts/browserextension.h>
 
+#include <khtml_events.h>
+
 #include <kjs_proxy.h>
 
 #if (defined(__APPLE__) && defined(__OBJC__) && defined(__cplusplus))
@@ -563,6 +565,14 @@ public:
     void stopAutoScroll();
     virtual void overURL( const QString &url, const QString &target ); // ### KDE 3.0: make private (merge)
 
+    bool event( QEvent *event );
+    void khtmlMousePressEvent( khtml::MousePressEvent *event );
+    void khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent * );
+    void khtmlMouseMoveEvent( khtml::MouseMoveEvent *event );
+    void khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event );
+    void khtmlDrawContentsEvent( khtml::DrawContentsEvent * );
+
+
 #ifdef _KWQ_
     void init();
 #if (defined(__APPLE__) && defined(__OBJC__) && defined(__cplusplus))
diff --git a/WebCore/src/kwq/KWQKHTMLPart.mm b/WebCore/src/kwq/KWQKHTMLPart.mm
index 9800307..1c25e81 100644
--- a/WebCore/src/kwq/KWQKHTMLPart.mm
+++ b/WebCore/src/kwq/KWQKHTMLPart.mm
@@ -37,8 +37,10 @@
 #include <kcharsets.h>
 #include <kglobal.h>
 #include <html/htmltokenizer.h>
+#include <html/html_imageimpl.h>
 #include <xml/dom_docimpl.h>
 #include <html/html_documentimpl.h>
+#include <rendering/render_image.h>
 #include <loader.h>
 #include <kjs.h>
 #include <kjs_dom.h>
@@ -113,10 +115,27 @@ public:
     bool m_haveEncoding:1;
     bool m_haveCharset:1;
     bool m_onlyLocalReferences:1;
+    bool m_startBeforeEnd:1;
 
     KJSProxy *m_jscript;
     int m_runningScripts;
 
+    QString m_strSelectedURL;
+    QString m_referrer;
+
+    bool m_bMousePressed;
+    DOM::Node m_mousePressNode; //node under the mouse when the mouse was pressed (set in the mouse handler)
+    DOM::Node m_selectionStart;
+    long m_startOffset;
+    DOM::Node m_selectionEnd;
+    long m_endOffset;
+    QString m_overURL;
+   
+    QPoint m_dragStartPos;
+#ifdef KHTML_NO_SELECTION
+    QPoint m_dragLastPos;
+#endif
+
     KHTMLPartPrivate(KHTMLPart *part)
     {
         if (!cache_init) {
@@ -732,6 +751,385 @@ const KHTMLSettings *KHTMLPart::settings() const
 }
 
 
+bool KHTMLPart::event( QEvent *event )
+{
+    if ( khtml::MousePressEvent::test( event ) )
+    {
+        khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseDoubleClickEvent::test( event ) )
+    {
+        khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::MouseMoveEvent::test( event ) )
+    {
+        khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) ); 
+        return true;
+    }
+    
+    if ( khtml::MouseReleaseEvent::test( event ) )
+    {
+        khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
+        return true;
+    }
+    
+    if ( khtml::DrawContentsEvent::test( event ) )
+    {
+        khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
+        return true;
+    }
+    
+    return false;
+}
+
+void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
+{
+  DOM::DOMString url = event->url();
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = innerNode;
+
+   d->m_dragStartPos = _mouse->pos();
+
+  if ( event->url() != 0 )
+    d->m_strSelectedURL = event->url().string();
+  else
+    d->m_strSelectedURL = QString::null;
+
+  if ( _mouse->button() == LeftButton ||
+       _mouse->button() == MidButton )
+  {
+    d->m_bMousePressed = true;
+
+#ifndef KHTML_NO_SELECTION
+    if ( _mouse->button() == LeftButton )
+    {
+      if ( !innerNode.isNull() )
+      {
+          int offset;
+          DOM::Node node;
+          innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                            event->nodeAbsX(), event->nodeAbsY(),
+                                                 node, offset );
+
+        if ( node.isNull() || !node.handle() )
+        {
+            //kdDebug( 6000 ) << "Hmm, findSelectionNode returned no node" << endl;
+            d->m_selectionStart = innerNode;
+            d->m_startOffset = 0; //?
+        } else {
+            d->m_selectionStart = node;
+            d->m_startOffset = offset;
+        }
+        //kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
+        //              << " offset=" << d->m_startOffset << endl;
+        d->m_selectionEnd = d->m_selectionStart;
+        d->m_endOffset = d->m_startOffset;
+        d->m_doc->clearSelection();
+      }
+      else
+      {
+        d->m_selectionStart = DOM::Node();
+        d->m_selectionEnd = DOM::Node();
+      }
+      //emitSelectionChanged();
+      //startAutoScroll();
+    }
+#else
+    d->m_dragLastPos = _mouse->globalPos();
+#endif
+  }
+
+  if ( _mouse->button() == RightButton )
+  {
+    //popupMenu( splitUrlTarget(d->m_strSelectedURL) );
+    d->m_strSelectedURL = QString::null;
+  }
+}
+
+void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent * )
+{
+}
+
+static QString splitUrlTarget(const QString &url, QString *target=0)
+{
+   QString result = url;
+   if(url.left(7) == "target:")
+   {
+      KURL u(url);
+      result = u.ref();
+      if (target)
+         *target = u.host();
+   }
+   return result;
+}
+
+void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::DOMString url = event->url();
+  DOM::Node innerNode = event->innerNode();
+
+#define QT_NO_DRAGANDDROP 1
+#ifndef QT_NO_DRAGANDDROP
+  if( d->m_bMousePressed && (!d->m_strSelectedURL.isEmpty() || (!innerNode.isNull() && innerNode.elementId() == ID_IMG) ) &&
+      ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay() &&
+      d->m_bDnd && d->m_mousePressNode == innerNode ) {
+
+      QPixmap p;
+      QDragObject *drag = 0;
+      if( !d->m_strSelectedURL.isEmpty() ) {
+          KURL u( completeURL( splitUrlTarget(d->m_strSelectedURL)) );
+          KURL::List uris;
+          uris.append(u);
+          drag = KURLDrag::newDrag( uris, d->m_view->viewport() );
+          p = KMimeType::pixmapForURL(u, 0, KIcon::SizeMedium);
+      } else {
+          HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+          if( i ) {
+            drag = new QImageDrag( i->currentImage() , d->m_view->viewport() );
+            p = KMimeType::mimeType("image/*")->pixmap(KIcon::Desktop);
+          }
+      }
+
+    if ( !p.isNull() )
+      drag->setPixmap(p);
+
+    stopAutoScroll();
+    if(drag)
+        drag->drag();
+
+    // when we finish our drag, we need to undo our mouse press
+    d->m_bMousePressed = false;
+    d->m_strSelectedURL = "";
+    return;
+  }
+#endif
+
+  QString target;
+  QString surl = splitUrlTarget(url.string(), &target);
+
+  // Not clicked -> mouse over stuff
+  if ( !d->m_bMousePressed )
+  {
+    // The mouse is over something
+    if ( url.length() )
+    {
+      bool shiftPressed = ( _mouse->state() & ShiftButton );
+
+      // Image map
+      if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
+      {
+        HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+        if ( i && i->isServerMap() )
+        {
+          khtml::RenderImage *r = static_cast<khtml::RenderImage *>(i->renderer());
+          if(r)
+          {
+            int absx, absy, vx, vy;
+            r->absolutePosition(absx, absy);
+            //view()->contentsToViewport( absx, absy, vx, vy );
+
+            int x(_mouse->x() - vx), y(_mouse->y() - vy);
+
+            d->m_overURL = surl + QString("?%1,%2").arg(x).arg(y);
+            //overURL( d->m_overURL, target, shiftPressed );
+            return;
+          }
+        }
+      }
+
+      // normal link
+      QString target;
+      QString surl = splitUrlTarget(url.string(), &target);
+      if ( d->m_overURL.isEmpty() || d->m_overURL != surl )
+      {
+        d->m_overURL = surl;
+        //overURL( d->m_overURL, target, shiftPressed );
+      }
+    }
+    else  // Not over a link...
+    {
+      if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
+      {
+        d->m_overURL = QString::null;
+        //emit onURL( QString::null );
+        // Default statusbar text can be set from javascript. Otherwise it's empty.
+        //emit setStatusBarText( d->m_kjsDefaultStatusBarText );
+      }
+    }
+  }
+  else {
+#ifndef KHTML_NO_SELECTION
+    // selection stuff
+    if( d->m_bMousePressed && !innerNode.isNull() && ( _mouse->state() == LeftButton )) {
+      int offset;
+      DOM::Node node;
+      //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y()
+      //              << " nodeAbsX=" << event->nodeAbsX() << " nodeAbsY=" << event->nodeAbsY()
+      //              << endl;
+      innerNode.handle()->findSelectionNode( event->x(), event->y(),
+                                             event->nodeAbsX(), event->nodeAbsY(),
+                                             node, offset );
+      // When this stuff is finished, this should never happen.
+      // But currently....
+      if ( node.isNull() || !node.handle() )
+      {
+        //kdWarning( 6000 ) << "findSelectionNode returned no node" << endl;
+        d->m_selectionEnd = innerNode;
+        d->m_endOffset = 0; //?
+      }
+      else
+      {
+        d->m_selectionEnd = node;
+        d->m_endOffset = offset;
+      }
+      //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle()->renderer() << "/"
+      //                << d->m_endOffset << endl;
+
+      // we have to get to know if end is before start or not...
+      DOM::Node n = d->m_selectionStart;
+      d->m_startBeforeEnd = false;
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+        //d->m_view->viewport()->repaint(false);
+      }
+
+      if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
+      {
+        if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
+                           d->m_selectionEnd.handle(),d->m_startOffset);
+        else if (d->m_startBeforeEnd)
+          d->m_doc
+            ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+                           d->m_selectionEnd.handle(),d->m_endOffset);
+        else
+          d->m_doc
+            ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
+                           d->m_selectionStart.handle(),d->m_startOffset);
+      }
+#else
+      if ( d->m_doc && d->m_view ) {
+        QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
+
+        if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
+          d->m_view->scrollBy( -diff.x(), -diff.y() );
+          d->m_dragLastPos = _mouse->globalPos();
+        }
+#endif
+    }
+  }
+
+}
+
+void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
+{
+  QMouseEvent *_mouse = event->qmouseEvent();
+  DOM::Node innerNode = event->innerNode();
+  d->m_mousePressNode = DOM::Node();
+
+  if ( d->m_bMousePressed )
+    stopAutoScroll();
+
+  // Used to prevent mouseMoveEvent from initiating a drag before
+  // the mouse is pressed again.
+  d->m_bMousePressed = false;
+
+    openURL (KURL(completeURL( splitUrlTarget(d->m_strSelectedURL))));
+    
+#define QT_NO_CLIPBOARD 1
+#ifndef QT_NO_CLIPBOARD
+  if ((_mouse->button() == MidButton) && (event->url() == 0))
+  {
+    QClipboard *cb = QApplication::clipboard();
+    QCString plain("plain");
+    QString url = cb->text(plain);
+    KURL u(url);
+    if (u.isValid())
+    {
+      QString savedReferrer = d->m_referrer;
+      d->m_referrer = QString::null; // Disable referrer.
+      urlSelected(url, 0,0, "_top");
+      d->m_referrer = savedReferrer; // Restore original referrer.
+    }
+  }
+#endif
+
+#ifndef KHTML_NO_SELECTION
+  // delete selection in case start and end position are at the same point
+  if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
+    d->m_selectionStart = 0;
+    d->m_selectionEnd = 0;
+    d->m_startOffset = 0;
+    d->m_endOffset = 0;
+    //emitSelectionChanged();
+  } else {
+    // we have to get to know if end is before start or not...
+    DOM::Node n = d->m_selectionStart;
+    d->m_startBeforeEnd = false;
+    if( d->m_selectionStart == d->m_selectionEnd ) {
+      if( d->m_startOffset < d->m_endOffset )
+        d->m_startBeforeEnd = true;
+    } else {
+      while(!n.isNull()) {
+        if(n == d->m_selectionEnd) {
+          d->m_startBeforeEnd = true;
+          break;
+        }
+        DOM::Node next = n.firstChild();
+        if(next.isNull()) next = n.nextSibling();
+        while( next.isNull() && !n.parentNode().isNull() ) {
+          n = n.parentNode();
+          next = n.nextSibling();
+        }
+        n = next;
+      }
+    }
+    if(!d->m_startBeforeEnd)
+    {
+      DOM::Node tmpNode = d->m_selectionStart;
+      int tmpOffset = d->m_startOffset;
+      d->m_selectionStart = d->m_selectionEnd;
+      d->m_startOffset = d->m_endOffset;
+      d->m_selectionEnd = tmpNode;
+      d->m_endOffset = tmpOffset;
+      d->m_startBeforeEnd = true;
+    }
+    // get selected text and paste to the clipboard
+#ifndef QT_NO_CLIPBOARD
+    QString text = selectedText();
+    text.replace(QRegExp(QChar(0xa0)), " ");
+    QClipboard *cb = QApplication::clipboard();
+    cb->setText(text);
+#endif
+    //kdDebug( 6000 ) << "selectedText = " << text << endl;
+    //emitSelectionChanged();
+  }
+#endif
+}
+
+void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
+{
+}
+
+
+
 KJSProxy *KHTMLPart::jScript()
 {
   if ( !d->m_jscript )
@@ -880,9 +1278,7 @@ void KHTMLPart::submitForm( const char *action, const QString &url, const QByteA
     _logNeverImplemented();
 }
 
-
-void KHTMLPart::urlSelected( const QString &url, int button = 0, int state = 0,
-                        const QString &_target = QString::null )
+void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target )
 {
     _logNeverImplemented();
 }
@@ -896,9 +1292,9 @@ bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, con
 }
 
 
-void KHTMLPart::nodeActivated(const DOM::Node &)
+void KHTMLPart::nodeActivated(const DOM::Node &aNode)
 {
-    _logNeverImplemented();
+    KWQDEBUG2 ("name %s = %s\n", (const char *)aNode.nodeName().string(), (const char *)aNode.nodeValue().string());
 }
 
 
diff --git a/WebCore/src/kwq/KWQKPartsEvent.mm b/WebCore/src/kwq/KWQKPartsEvent.mm
index af77203..1db8659 100644
--- a/WebCore/src/kwq/KWQKPartsEvent.mm
+++ b/WebCore/src/kwq/KWQKPartsEvent.mm
@@ -28,24 +28,30 @@
 
 class QPainter;
 
+#define KPARTS_EVENT_MAGIC 42
+
 namespace KParts {
 
-bool Event::test(const QEvent *)
+bool Event::test(const QEvent *event)
 {
-    _logNotYetImplemented();
-    return FALSE;
+  if ( !event )
+    return false;
+  
+  return ( event->type() == (QEvent::Type)(1000 + KPARTS_EVENT_MAGIC ) );
 }
 
-bool Event::test(const QEvent *, const char *)
+bool Event::test(const QEvent *event, const char *name)
 {
-    _logNotYetImplemented();
-    return FALSE;
+  if ( !test( event ) )
+    return false;
+  
+  return ( strcmp( name, (const char *)((QCustomEvent *)event)->data() ) == 0 );
 }
 
 
-Event::Event(const char *)
+Event::Event(const char *eventName)
+ : QCustomEvent( (QEvent::Type)(1000 + KPARTS_EVENT_MAGIC), (void *)eventName )
 {
-    //_logNotYetImplemented();
 }
 
 } // namespace KParts
diff --git a/WebCore/src/kwq/KWQMetrics.h b/WebCore/src/kwq/KWQMetrics.h
index bba5e2c..be095c8 100644
--- a/WebCore/src/kwq/KWQMetrics.h
+++ b/WebCore/src/kwq/KWQMetrics.h
@@ -27,19 +27,20 @@
 
 #import <Cocoa/Cocoa.h>
 
- at interface KWQMetricsInfo : NSObject
+ at interface KWQLayoutInfo : NSObject
 {
     NSMutableDictionary *attributes;
     NSMutableDictionary *fragmentCache;
 }
 
 + (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color;
-+ (KWQMetricsInfo *)getMetricsForFont: (NSFont *)aFont;
-+ (void)setMetric: (KWQMetricsInfo *)info forFont: (NSFont *)aFont;
++ (KWQLayoutInfo *)getMetricsForFont: (NSFont *)aFont;
++ (void)setMetric: (KWQLayoutInfo *)info forFont: (NSFont *)aFont;
 - initWithFont: (NSFont *)aFont;
 - (NSRect)rectForString:(NSString *)string;
 - (NSLayoutManager *)layoutManagerForString: (NSString *)string;
 - (void)setColor: (NSColor *)color;
+- (void)setFont: (NSFont *)aFont;
 @end
 
 @interface KWQLayoutFragment : NSObject
diff --git a/WebCore/src/kwq/KWQPainter.mm b/WebCore/src/kwq/KWQPainter.mm
index 10a0acc..9274f51 100644
--- a/WebCore/src/kwq/KWQPainter.mm
+++ b/WebCore/src/kwq/KWQPainter.mm
@@ -457,10 +457,13 @@ void QPainter::drawTiledPixmap( int x, int y, int w, int h,
     drawTile( this, x, y, w, h, pixmap, sx, sy );
 }
 
+#define FAST_CACHE_DRAWING 1
+
+#ifdef HACK_FAST_DRAWING
 @interface NSLayoutManager (Private)
 - (char *)_packedGlyphs:(NSMultibyteGlyphPacking)packing range:(NSRange)glyphRange length:(unsigned *)len;
 @end
-
+#endif
 
 // y is the baseline
 void QPainter::drawText(int x, int y, const QString &qstring, int len)
@@ -482,17 +485,21 @@ void QPainter::drawText(int x, int y, const QString &qstring, int len)
     // This will draw the text from the top of the bounding box down.
     // Qt expects to draw from the baseline.
     y = y - (int)([font defaultLineHeightForFont] + [font descender]);
-    //[string drawAtPoint:NSMakePoint(x, y) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, data->qpen.color().color, NSForegroundColorAttributeName, nil]];
 
-    [KWQMetricsInfo drawString: string atPoint: NSMakePoint(x, y) withFont: font color: data->qpen.color().color];
-//    KWQMetricsInfo *metricsCache = [KWQMetricsInfo getMetricsForFont: font];
-//    NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
-//    if (layoutManager != nil){
-//        unsigned numberOfGlyphs = [layoutManager numberOfGlyphs];
-//        [metricsCache setColor: data->qpen.color().color];
-//        [layoutManager drawGlyphsForGlyphRange:NSMakeRange (0, numberOfGlyphs) atPoint:NSMakePoint(x, y)];
+#ifdef SLOW_SAFE_DRAWING
+
+    [string drawAtPoint:NSMakePoint(x, y) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, data->qpen.color().color, NSForegroundColorAttributeName, nil]];
+
+#elif FAST_CACHE_DRAWING
+
+    [KWQLayoutInfo drawString: string atPoint: NSMakePoint(x, y) withFont: font color: data->qpen.color().color];
+
+#elif HACK_FAST_DRAWING
+
+    KWQLayoutInfo *metricsCache = [KWQLayoutInfo getMetricsForFont: font];
+    NSLayoutManager *layoutManager = [metricsCache layoutManagerForString: string];
+    if (layoutManager != nil){
 
-/*
         [font set];
         [data->qpen.color().color set];
         
@@ -507,8 +514,9 @@ void QPainter::drawText(int x, int y, const QString &qstring, int len)
         [layoutManager showPackedGlyphs:glyphBuf length:glyphLen glyphRange:NSMakeRange (0, numberOfGlyphs)  atPoint:NSMakePoint(x, y) font:font color:data->qpen.color().color printingAdjustment:NSMakeSize(0.0, 0.0)];
 
         [graphicsContext setShouldAntialias: flag];
-*/
-//    }
+    }
+
+#endif
 
 
     _unlockFocus();
diff --git a/WebCore/src/kwq/KWQScrollView.mm b/WebCore/src/kwq/KWQScrollView.mm
index 633e91a..21ace9c 100644
--- a/WebCore/src/kwq/KWQScrollView.mm
+++ b/WebCore/src/kwq/KWQScrollView.mm
@@ -201,7 +201,10 @@ QPoint QScrollView::contentsToViewport(const QPoint &)
 
 void QScrollView::viewportToContents(int vx, int vy, int& x, int& y)
 {
-    _logNeverImplemented();
+    NSPoint p = NSMakePoint (vx, vy);
+    NSPoint np = [getView() convertPoint: NSMakePoint (vx, vy) fromView: nil];
+    x = (int)np.x;
+    y = (int)np.y;
 }
 
 
diff --git a/WebCore/src/kwq/KWQTextContainer.mm b/WebCore/src/kwq/KWQTextContainer.mm
index dbdd824..5601b2a 100644
--- a/WebCore/src/kwq/KWQTextContainer.mm
+++ b/WebCore/src/kwq/KWQTextContainer.mm
@@ -22,6 +22,17 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
+ 
+ /*
+    This class an it's companion KWQTextStorage are used to optimize 
+    our interaction with NSLayoutManager.  They do very little.
+    KWQTextContainer has a fixed geometry.  It only ever containers
+    a short run of text corresponding to a khtml TextSlave.
+    
+    Both KWQTextStorage and KWQTextContainer are used as singletons.  They
+    are set/reset for layout and rendering.
+ */
+ 
 
 #import <Cocoa/Cocoa.h>
 
@@ -73,28 +84,26 @@ static KWQTextContainer *sharedInstance = nil;
 
 - (void)setContainerSize:(NSSize)aSize
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setContainerSize:(NSSize)aSize"];
 }
 
 - (void)setHeightTracksTextView:(BOOL)flag
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setHeightTracksTextView:(BOOL)flag"];
 }
 
 - (BOOL)heightTracksTextView
 {
-    KWQDEBUG ("not implemented\n");
     return NO;
 }
 
 - (void)setWidthTracksTextView:(BOOL)flag
 {
-    KWQDEBUG ("not implemented\n");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setWidthTracksTextView:(BOOL)flag"];
 }
 
 - (BOOL)widthTracksTextView
 {
-    KWQDEBUG ("not implemented\n");
     return NO;
 }
 
diff --git a/WebCore/src/kwq/KWQTextStorage.h b/WebCore/src/kwq/KWQTextStorage.h
index 573a68b..37c691e 100644
--- a/WebCore/src/kwq/KWQTextStorage.h
+++ b/WebCore/src/kwq/KWQTextStorage.h
@@ -33,4 +33,7 @@
     NSLayoutManager *_layoutManager;
 }
 
++ setString:(NSString *)str attributes:(NSDictionary *)attrs;
+- (void)setString: (NSString *)aString attributes: (NSDictionary *)at;
+
 @end
diff --git a/WebCore/src/kwq/KWQTextStorage.mm b/WebCore/src/kwq/KWQTextStorage.mm
index 440f257..1e9a5dc 100644
--- a/WebCore/src/kwq/KWQTextStorage.mm
+++ b/WebCore/src/kwq/KWQTextStorage.mm
@@ -29,8 +29,31 @@
 
 #import <KWQTextStorage.h>
 
+/*
+    This class is a dumb text storage implementation.  It is optimized for speed,
+    not flexibility.  It only support read-only text with font and color attributes.
+    
+    It is used, along with KWQTextContainer to spoof NSLayoutManager.  KWQTextStorage
+    and KWQTextContainer are both used as singletons.  They are set/reset to contain the
+    correct attributes (font and color only) during layout and rendering.
+*/
+
 @implementation KWQTextStorage
 
+static KWQTextStorage *sharedInstance = nil;
+
++ (KWQTextStorage *)sharedInstance
+{
+    if (sharedInstance == nil)
+        sharedInstance = [[KWQTextStorage alloc] init];
+    return sharedInstance;
+}
+
++ setString:(NSString *)str attributes:(NSDictionary *)attrs 
+{
+    [[KWQTextStorage sharedInstance] setString: str attributes: attrs];
+}
+
 - (id)initWithString:(NSString *)str attributes:(NSDictionary *)attrs 
 {
     attrString = [str retain];
@@ -81,51 +104,77 @@
     return [attrString length];
 }
 
+- (void)setString: (NSString *)aString attributes: (NSDictionary *)at
+{
+    if (aString != attrString){
+        [attrString release];
+        attrString = [aString retain];
+    }
+
+    if (at != attributes){
+        [attributes release];
+        attributes = [at retain];
+    }
+}
+
+
 - (NSString *)string 
 {
     return attrString;
 }
 
+
 - (NSDictionary *)attributesAtIndex:(unsigned)location effectiveRange:(NSRangePointer)range 
 {
-    range->location = 0;
-    range->length = [self length];
+    if (range != 0){
+        range->location = 0;
+        range->length = [self length];
+    }
     return attributes;
 }
 
+
 - (NSDictionary *)attributesAtIndex:(unsigned)location longestEffectiveRange:(NSRangePointer)range inRange:(NSRange)rangeLimit
 {
-    range->location = rangeLimit.location;
-    range->length = rangeLimit.length;
+    if (range != 0){
+        range->location = rangeLimit.location;
+        range->length = rangeLimit.length;
+    }
     return attributes;
 }
 
+
 - (id)attribute:(NSString *)attrName atIndex:(unsigned)location effectiveRange:(NSRangePointer)range 
 {
-    range->location = 0;
-    range->length = [self length];
+    if (range != 0){
+        range->location = 0;
+        range->length = [self length];
+    }
     return [attributes objectForKey: attrName];
 }
 
+
 - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range 
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range"];
 }
 
 
 - (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)str 
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)str"];
 }
 
+
 - (void)addAttribute:(NSString *)name value:value range:(NSRange)range
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (void)addAttribute:(NSString *)name value:value range:(NSRange)range"];
 }
 
+
 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange
 {
-    KWQDEBUG ("not implemented");
+    [NSException raise:@"NOT IMPLEMENTED" format:@"- (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange"];
     return nil;
 }
 
diff --git a/WebCore/src/kwq/KWQView.mm b/WebCore/src/kwq/KWQView.mm
index f3ce72d..7c266c1 100644
--- a/WebCore/src/kwq/KWQView.mm
+++ b/WebCore/src/kwq/KWQView.mm
@@ -29,6 +29,7 @@
 #include <khtmlview.h>
 #include <qwidget.h>
 #include <qpainter.h>
+#include <qevent.h>
 #include <html/html_documentimpl.h>
 
 
@@ -217,12 +218,46 @@
 
 - (void)mouseUp: (NSEvent *)event
 {
-    KWQDEBUGLEVEL1 (0x100, "mouseUp %s\n", DEBUG_OBJECT(event));
+    int button, state;
+     
+    if ([event type] == NSLeftMouseDown){
+        button = Qt::LeftButton;
+        state = Qt::LeftButton;
+    }
+    else if ([event type] == NSRightMouseDown){
+        button = Qt::RightButton;
+        state = Qt::RightButton;
+    }
+    else if ([event type] == NSOtherMouseDown){
+        button = Qt::MidButton;
+        state = Qt::MidButton;
+    }
+    NSPoint p = [event locationInWindow];
+    
+    QMouseEvent *kEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(p.x, p.y), button, state);
+    ((KHTMLView *)widget)->viewportMouseReleaseEvent(kEvent);
 }
 
 - (void)mouseDown: (NSEvent *)event
 {
-    KWQDEBUGLEVEL1 (0x100, "mouseDown %s\n", DEBUG_OBJECT(event));
+    int button, state;
+     
+    if ([event type] == NSLeftMouseDown){
+        button = Qt::LeftButton;
+        state = Qt::LeftButton;
+    }
+    else if ([event type] == NSRightMouseDown){
+        button = Qt::RightButton;
+        state = Qt::RightButton;
+    }
+    else if ([event type] == NSOtherMouseDown){
+        button = Qt::MidButton;
+        state = Qt::MidButton;
+    }
+    NSPoint p = [event locationInWindow];
+    
+    QMouseEvent *kEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(p.x, p.y), button, state);
+    ((KHTMLView *)widget)->viewportMousePressEvent(kEvent);
 }
 
 - (void)mouseDragged: (NSEvent *)event
diff --git a/WebCore/src/kwq/qt/qevent.h b/WebCore/src/kwq/qt/qevent.h
index 69eafd0..53817be 100644
--- a/WebCore/src/kwq/qt/qevent.h
+++ b/WebCore/src/kwq/qt/qevent.h
@@ -64,7 +64,7 @@ public:
     QEvent() {}
 #endif
 
-    QEvent(Type);
+    QEvent( Type t ) : _type(t) {}
     virtual ~QEvent();
 
     // member functions --------------------------------------------------------
@@ -89,7 +89,7 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QEvent &operator=(const QEvent &);
 #endif
-
+    Type  _type;
 }; // class QEvent =============================================================
 
 
@@ -146,6 +146,9 @@ private:
 #ifdef _KWQ_PEDANTIC_
     QMouseEvent &operator=(const QMouseEvent &);
 #endif
+    QPoint _position;
+    int	   _button; // ### Make ushort in 3.0? Here it's an int...
+    ushort _state; // ### ...and here an ushort. But both are ButtonState!
 
 }; // class QMouseEvent ========================================================
 
@@ -492,20 +495,11 @@ private:
 
 class QCustomEvent : public QEvent {
 public:
-
-    // typedefs ----------------------------------------------------------------
-    // enums -------------------------------------------------------------------
-    // constants ---------------------------------------------------------------
-    // static member functions -------------------------------------------------
-    
-    // constructors, copy constructors, and destructors ------------------------
-    
-// add no-arg constructor
-#ifdef _KWQ_PEDANTIC_
-    QCustomEvent() {}
-#endif
-
-    QCustomEvent(Type);
+    QCustomEvent( int type );
+    QCustomEvent( Type type, void *data )
+	: QEvent(type), d(data) {};
+    void       *data()	const	{ return d; }
+    void	setData( void* data )	{ d = data; }
 
 // add no-op destructor
 #ifdef _KWQ_PEDANTIC_
@@ -519,6 +513,7 @@ public:
 // private ---------------------------------------------------------------------
 
 private:
+    void       *d;
 
 // add copy constructor
 // this private declaration prevents copying

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list