Reviewed by Mark (age 21).
[WebKit-https.git] / WebKit / WebView / WebHTMLView.mm
index 2524d2c..0bed84c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
- *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import <WebCore/DragController.h>
 #import <WebCore/FloatRect.h>
 #import <WebCore/FocusController.h>
-#import <WebCore/FrameMac.h>
+#import <WebCore/Frame.h>
 #import <WebCore/HitTestResult.h>
 #import <WebCore/KeyboardEvent.h>
 #import <WebCore/MimeTypeRegistry.h>
 #import <WebCore/Page.h>
+#import <WebCore/PlatformKeyboardEvent.h>
+#import <WebCore/PlatformMouseEvent.h>
 #import <WebCore/Range.h>
 #import <WebCore/SelectionController.h>
+#import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebCoreTextRenderer.h>
-#import <WebCore/WebDataProtocol.h>
 #import <WebKit/DOM.h>
 #import <WebKit/DOMExtensions.h>
 #import <WebKit/DOMPrivate.h>
@@ -98,6 +100,9 @@ using namespace WebCore;
 
 extern "C" {
 
+// Fake URL scheme.
+static NSString *WebDataProtocolScheme = @"webkit-fake-url";
+
 // need to declare this because AppKit does not make it available as API or SPI
 extern NSString *NSMarkedClauseSegmentAttributeName; 
 extern NSString *NSTextInputReplacementRangeAttributeName; 
@@ -129,6 +134,7 @@ void _NSResetKillRingOperationFlag(void);
 
 @interface NSWindow (AppKitSecretsIKnowAbout)
 - (id)_newFirstResponderAfterResigning;
+- (void)_setForceActiveControls:(BOOL)flag;
 @end
 
 @interface NSAttributedString (AppKitSecretsIKnowAbout)
@@ -170,6 +176,7 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 #define AUTOSCROLL_INTERVAL             0.1f
 
 #define DRAG_LABEL_BORDER_X             4.0f
+//Keep border_y in synch with DragController::LinkDragBorderInset
 #define DRAG_LABEL_BORDER_Y             2.0f
 #define DRAG_LABEL_RADIUS               5.0f
 #define DRAG_LABEL_BORDER_Y_OFFSET              2.0f
@@ -196,7 +203,6 @@ static BOOL forceNSViewHitTest;
 // if YES, do the "top WebHTMLView" it test (which we'd like to do all the time but can't because of Java requirements [see bug 4349721])
 static BOOL forceWebHTMLViewHitTest;
 
-static NSEvent *performKeyEquivalentEvent;
 static WebHTMLView *lastHitView;
 
 @interface WebHTMLView (WebTextSizing) <_WebDocumentTextSizing>
@@ -229,7 +235,8 @@ static WebHTMLView *lastHitView;
 
 @interface WebHTMLView (WebNSTextInputSupport) <NSTextInput>
 - (void)_updateSelectionForInputManager;
-- (void)_insertText:(NSString *)text selectInsertedText:(BOOL)selectText;
+- (BOOL)_insertNewlineWithEvent:(KeyboardEvent*)event isLineBreak:(BOOL)isLineBreak;
+- (BOOL)_insertTabWithEvent:(KeyboardEvent*)event isBackTab:(BOOL)isBackTab;
 @end
 
 @interface WebHTMLView (WebEditingStyleSupport)
@@ -266,6 +273,11 @@ static WebHTMLView *lastHitView;
 - (void)_reflectSelection;
 @end
 
+struct WebHTMLViewInterpretKeyEventsParameters {
+    KeyboardEvent* event;
+    BOOL eventWasHandled;
+};
+
 @implementation WebHTMLViewPrivate
 
 - (void)dealloc
@@ -275,7 +287,6 @@ static WebHTMLView *lastHitView;
     
     [mouseDownEvent release];
     [keyDownEvent release];
-    [draggingImageURL release];
     [pluginController release];
     [toolTip release];
     [compController release];
@@ -290,7 +301,6 @@ static WebHTMLView *lastHitView;
 {
     [mouseDownEvent release];
     [keyDownEvent release];
-    [draggingImageURL release];
     [pluginController release];
     [toolTip release];
     [compController release];
@@ -300,7 +310,6 @@ static WebHTMLView *lastHitView;
 
     mouseDownEvent = nil;
     keyDownEvent = nil;
-    draggingImageURL = nil;
     pluginController = nil;
     toolTip = nil;
     compController = nil;
@@ -373,7 +382,8 @@ static WebHTMLView *lastHitView;
                 [resource release];
             }
         } else {
-            // Non-image file types
+            // Non-image file types; _web_userVisibleString is appropriate here because this will
+            // be pasted as visible text.
             NSString *url = [[[NSURL fileURLWithPath:path] _webkit_canonicalize] _web_userVisibleString];
             [domNodes addObject:[[[self _frame] DOMDocument] createTextNode: url]];
         }
@@ -406,6 +416,17 @@ static WebHTMLView *lastHitView;
     return elements;
 }
 
+static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
+    CFRelease(UUIDString);
+
+    return URL;
+}
+
 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
                                                inContext:(DOMRange *)context
                                           allowPlainText:(BOOL)allowPlainText
@@ -413,105 +434,62 @@ static WebHTMLView *lastHitView;
 {
     NSArray *types = [pasteboard types];
     *chosePlainText = NO;
+    DOMDocumentFragment *fragment;
 
-    if ([types containsObject:WebArchivePboardType]) {
-        WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
-        if (archive) {
-            DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
-            [archive release];
-            if (fragment) {
-                return fragment;
-            }
-        }
-    }
-    
-    if ([types containsObject:NSFilenamesPboardType]) {
-        DOMDocumentFragment *fragment = [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
-        if (fragment != nil) {
-            return fragment;
-        }
-    }
-    
-    NSURL *URL;
-    
-    if ([types containsObject:NSHTMLPboardType]) {
-        NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
-        // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
-        if ([HTMLString hasPrefix:@"Version:"]) {
-            NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
-            if (range.location != NSNotFound) {
-                HTMLString = [HTMLString substringFromIndex:range.location];
-            }
-        }
-        if ([HTMLString length] != 0) {
-            return [[self _bridge] documentFragmentWithMarkupString:HTMLString baseURLString:nil];
-        }
-    }
-        
-    NSAttributedString *string = nil;
-    if ([types containsObject:NSRTFDPboardType]) {
-        string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
-    }
-    if (string == nil && [types containsObject:NSRTFPboardType]) {
-        string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
-    }
-    if (string != nil) {
-        NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
-            [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
-            self, @"WebResourceHandler", nil];
-        NSArray *subresources;
-        DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
-                                                          document:[[self _frame] DOMDocument] 
-                                                documentAttributes:documentAttributes
-                                                      subresources:&subresources];
-        [documentAttributes release];
-        [string release];
+    if ([types containsObject:WebArchivePboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:WebArchivePboardType
+                                                inContext:context]))
         return fragment;
-    }
-    
-    if ([types containsObject:NSTIFFPboardType]) {
-        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
-                                                              URL:[NSURL _web_uniqueWebDataURLWithRelativeString:@"/image.tiff"]
-                                                         MIMEType:@"image/tiff" 
-                                                 textEncodingName:nil
-                                                        frameName:nil];
-        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
-        [resource release];
+                                           
+    if ([types containsObject:NSFilenamesPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSFilenamesPboardType
+                                                inContext:context]))
         return fragment;
-    }
     
-    if ([types containsObject:NSPICTPboardType]) {
-        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPICTPboardType]
-                                                              URL:[NSURL _web_uniqueWebDataURLWithRelativeString:@"/image.pict"]
-                                                         MIMEType:@"image/pict" 
-                                                 textEncodingName:nil
-                                                        frameName:nil];
-        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
-        [resource release];
+    if ([types containsObject:NSHTMLPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSHTMLPboardType
+                                                inContext:context]))
         return fragment;
-    }    
     
-    if ((URL = [NSURL URLFromPasteboard:pasteboard])) {
-        DOMDocument* document = [[self _frame] DOMDocument];
-        ASSERT(document);
-        if (document) {
-            DOMHTMLAnchorElement* anchor = (DOMHTMLAnchorElement*)[document createElement:@"a"];
-            NSString *URLString = [URL _web_userVisibleString];
-            NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType];
-            DOMText* text = [document createTextNode:URLTitleString];
-            [anchor setHref:URLString];
-            [anchor appendChild:text];
-            DOMDocumentFragment* fragment = [document createDocumentFragment];
-            [fragment appendChild:anchor];
-            if ([URLString length] > 0)
-                return fragment;
-        }
-    }
+    if ([types containsObject:NSRTFPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSRTFPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSRTFDPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSRTFDPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSTIFFPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSTIFFPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSPICTPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSPICTPboardType
+                                                inContext:context]))
+        return fragment;
     
-    if (allowPlainText && [types containsObject:NSStringPboardType]) {
+    if ([types containsObject:NSURLPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSURLPboardType
+                                                inContext:context]))
+        return fragment;
+        
+    if (allowPlainText && [types containsObject:NSStringPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard
+                                                  forType:NSStringPboardType
+                                                inContext:context])) {
         *chosePlainText = YES;
-        return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]
-                                              inContext:context];
+        return fragment;
     }
     
     return nil;
@@ -1157,14 +1135,14 @@ static WebHTMLView *lastHitView;
                          windowNumber:[[view window] windowNumber]
                          context:[[NSApp currentEvent] context]
                          eventNumber:0 clickCount:0 pressure:0];
-        if (FrameMac* lastHitCoreFrame = core([lastHitView _frame]))
+        if (Frame* lastHitCoreFrame = core([lastHitView _frame]))
             lastHitCoreFrame->eventHandler()->mouseMoved(event);
     }
 
     lastHitView = view;
 
     if (view) {
-        if (FrameMac* coreFrame = core([view _frame]))
+        if (Frame* coreFrame = core([view _frame]))
             coreFrame->eventHandler()->mouseMoved(event);
 
         NSPoint point = [view convertPoint:[event locationInWindow] fromView:nil];
@@ -1222,23 +1200,18 @@ static WebHTMLView *lastHitView;
     return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
 }
 
-- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+- (NSImage *)_dragImageForURL:(NSString*)urlString withLabel:(NSString*)label
 {
-    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
-
     BOOL drawURLString = YES;
     BOOL clipURLString = NO, clipLabelString = NO;
     
-    NSString *label = [element objectForKey: WebElementLinkLabelKey];
-    NSString *urlString = [linkURL _web_userVisibleString];
-    
     if (!label) {
         drawURLString = NO;
         label = urlString;
     }
     
     NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DRAG_LINK_LABEL_FONT_SIZE]
-                                                   toHaveTrait:NSBoldFontMask];
+                                                           toHaveTrait:NSBoldFontMask];
     NSFont *urlFont = [NSFont systemFontOfSize: DRAG_LINK_URL_FONT_SIZE];
     NSSize labelSize;
     labelSize.width = [label _web_widthWithFont: labelFont];
@@ -1278,27 +1251,36 @@ static WebHTMLView *lastHitView;
     [path appendBezierPathWithRect: NSMakeRect(0.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 10.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DRAG_LABEL_RADIUS - 20.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 20.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path fill];
-        
+    
     NSColor *topColor = [NSColor colorWithCalibratedWhite:0.0f alpha:0.75f];
     NSColor *bottomColor = [NSColor colorWithCalibratedWhite:1.0f alpha:0.5f];
     if (drawURLString) {
         if (clipURLString)
             urlString = [WebStringTruncator centerTruncateString: urlString toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:urlFont];
-
+        
         [urlString _web_drawDoubledAtPoint:NSMakePoint(DRAG_LABEL_BORDER_X, DRAG_LABEL_BORDER_Y - [urlFont descender]) 
-             withTopColor:topColor bottomColor:bottomColor font:urlFont];
+                              withTopColor:topColor bottomColor:bottomColor font:urlFont];
     }
-
+    
     if (clipLabelString)
         label = [WebStringTruncator rightTruncateString: label toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:labelFont];
     [label _web_drawDoubledAtPoint:NSMakePoint (DRAG_LABEL_BORDER_X, imageSize.height - DRAG_LABEL_BORDER_Y_OFFSET - [labelFont pointSize])
-             withTopColor:topColor bottomColor:bottomColor font:labelFont];
+                      withTopColor:topColor bottomColor:bottomColor font:labelFont];
     
     [dragImage unlockFocus];
     
     return dragImage;
 }
 
+- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+{
+    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
+    
+    NSString *label = [element objectForKey: WebElementLinkLabelKey];
+    NSString *urlString = [linkURL _web_userVisibleString];
+    return [self _dragImageForURL:urlString withLabel:label];
+}
+
 - (BOOL)_startDraggingImage:(NSImage *)wcDragImage at:(NSPoint)wcDragLoc operation:(NSDragOperation)op event:(NSEvent *)mouseDraggedEvent sourceIsDHTML:(BOOL)srcIsDHTML DHTMLWroteData:(BOOL)dhtmlWroteData
 {
     WebHTMLView *topHTMLView = [self _topHTMLView];
@@ -1316,14 +1298,12 @@ static WebHTMLView *lastHitView;
     NSURL *imageURL = [element objectForKey:WebElementImageURLKey];
     BOOL isSelected = [[element objectForKey:WebElementIsSelectedKey] boolValue];
 
-    [_private->draggingImageURL release];
-    _private->draggingImageURL = nil;
-
     NSPoint mouseDraggedPoint = [self convertPoint:[mouseDraggedEvent locationInWindow] fromView:nil];
     
     Page* page = core([self _webView]);
     ASSERT(page);
     DragController *dragController = page->dragController();
+    dragController->setDraggingImageURL(KURL());
     dragController->setDragOperation((DragOperation)op);     // will be DragNone if WebCore doesn't care
     
     NSImage *dragImage = nil;
@@ -1341,7 +1321,7 @@ static WebHTMLView *lastHitView;
             dragLoc = NSMakePoint(mouseDraggedPoint.x - wcDragLoc.x, mouseDraggedPoint.y + wcDragLoc.y);
         else
             dragLoc = NSMakePoint(mouseDownPoint.x - wcDragLoc.x, mouseDownPoint.y + wcDragLoc.y);
-        _private->dragOffset = wcDragLoc;
+        dragController->setDragOffset(IntPoint(wcDragLoc));
     }
     
     WebView *webView = [self _webView];
@@ -1355,13 +1335,13 @@ static WebHTMLView *lastHitView;
     if (imageURL != nil
             && [node isKindOfClass:[DOMElement class]]
             && [(DOMElement *)node image]
-            && (_private->dragSourceActionMask & WebDragSourceActionImage)) {
+            && (dragController->dragSourceAction() & WebDragSourceActionImage)) {
         id source = self;
         if (!dhtmlWroteData) {
             // Select the image when it is dragged. This allows the image to be moved via MoveSelectionCommandImpl and this matches NSTextView's behavior.
             ASSERT(node != nil);
             [webView setSelectedDOMRange:[[node ownerDocument] _createRangeWithNode:node] affinity:NSSelectionAffinityDownstream];
-            _private->draggingImageURL = [imageURL retain];
+            dragController->setDraggingImageURL(imageURL);
             
             WebArchive *archive;
             
@@ -1379,14 +1359,16 @@ static WebHTMLView *lastHitView;
                                                                   source:self];
         }
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionImage fromPoint:mouseDownPoint withPasteboard:pasteboard];
-        if (dragImage == nil)
+        if (dragImage == nil) {
+            NSPoint point = dragController->dragOffset();
             [self _web_DragImageForElement:(DOMElement *)node
                                       rect:[self convertRect:[[element objectForKey:WebElementImageRectKey] rectValue] fromView:innerHTMLView]
                                      event:_private->mouseDownEvent
                                 pasteboard:pasteboard
                                     source:source
-                                    offset:&_private->dragOffset];
-        else
+                                    offset:&point];
+            dragController->setDragOffset(IntPoint(point));
+        } else
             [self dragImage:dragImage
                          at:dragLoc
                      offset:NSZeroSize
@@ -1394,7 +1376,7 @@ static WebHTMLView *lastHitView;
                  pasteboard:pasteboard
                      source:source
                   slideBack:YES];
-    } else if (linkURL && (_private->dragSourceActionMask & WebDragSourceActionLink)) {
+    } else if (linkURL && (dragController->dragSourceAction() & WebDragSourceActionLink)) {
         if (!dhtmlWroteData) {
             NSArray *types = [NSPasteboard _web_writableTypesForURL];
             [pasteboard declareTypes:types owner:self];
@@ -1405,8 +1387,7 @@ static WebHTMLView *lastHitView;
             dragImage = [self _dragImageForLinkElement:element];
             NSSize offset = NSMakeSize([dragImage size].width / 2, -DRAG_LABEL_BORDER_Y);
             dragLoc = NSMakePoint(mouseDraggedPoint.x - offset.width, mouseDraggedPoint.y - offset.height);
-            _private->dragOffset.x = offset.width;
-            _private->dragOffset.y = -offset.height;        // inverted because we are flipped
+            dragController->setDragOffset(IntPoint((int)offset.width, -(int)offset.height)); // height inverted because we are flipped
         }
         // HACK:  We should pass the mouseDown event instead of the mouseDragged!  This hack gets rid of
         // a flash of the image at the mouseDown location when the drag starts.
@@ -1417,7 +1398,7 @@ static WebHTMLView *lastHitView;
              pasteboard:pasteboard
                  source:self
               slideBack:YES];
-    } else if (isSelected && (_private->dragSourceActionMask & WebDragSourceActionSelection)) {
+    } else if (isSelected && (dragController->dragSourceAction() & WebDragSourceActionSelection)) {
         if (!dhtmlWroteData)
             [innerHTMLView _writeSelectionToPasteboard:pasteboard];
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionSelection fromPoint:mouseDownPoint withPasteboard:pasteboard];
@@ -1425,8 +1406,8 @@ static WebHTMLView *lastHitView;
             dragImage = [innerHTMLView _selectionDraggingImage];
             NSRect draggingRect = [self convertRect:[innerHTMLView _selectionDraggingRect] fromView:innerHTMLView];
             dragLoc = NSMakePoint(NSMinX(draggingRect), NSMaxY(draggingRect));
-            _private->dragOffset.x = mouseDownPoint.x - dragLoc.x;
-            _private->dragOffset.y = dragLoc.y - mouseDownPoint.y;        // inverted because we are flipped
+            dragController->setDragOffset(IntPoint((int)(mouseDownPoint.x - dragLoc.x),
+                                                   (int)(dragLoc.y - mouseDownPoint.y)));        // y inverted because we are flipped
         }
         [self dragImage:dragImage
                      at:dragLoc
@@ -1436,7 +1417,7 @@ static WebHTMLView *lastHitView;
                  source:self
               slideBack:YES];
     } else if (srcIsDHTML) {
-        ASSERT(_private->dragSourceActionMask & WebDragSourceActionDHTML);
+        ASSERT(dragController->dragSourceAction() & WebDragSourceActionDHTML);
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionDHTML fromPoint:mouseDownPoint withPasteboard:pasteboard];
         if (dragImage == nil) {
             // WebCore should have given us an image, but we'll make one up
@@ -1445,8 +1426,7 @@ static WebHTMLView *lastHitView;
             dragImage = [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
             NSSize imageSize = [dragImage size];
             dragLoc = NSMakePoint(mouseDownPoint.x - imageSize.width / 2, mouseDownPoint.y + imageSize.height / 2);
-            _private->dragOffset.x = imageSize.width / 2;
-            _private->dragOffset.y = imageSize.height / 2;
+            dragController->setDragOffset(IntPoint((int)(imageSize.width / 2), (int)(imageSize.height / 2)));
         }
         [self dragImage:dragImage
                      at:dragLoc
@@ -1469,35 +1449,6 @@ static WebHTMLView *lastHitView;
     [self _startAutoscrollTimer:event]; 
 } 
 
-- (BOOL)_mayStartDragAtEventLocation:(NSPoint)location
-{
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView)
-        return [topHTMLView _mayStartDragAtEventLocation:location];
-
-    NSPoint mouseDownPoint = [self convertPoint:location fromView:nil];
-    NSDictionary *mouseDownElement = [self elementAtPoint:mouseDownPoint allowShadowContent:YES];
-
-    ASSERT([self _webView]);
-
-    if ([mouseDownElement objectForKey:WebElementImageKey]
-            && [mouseDownElement objectForKey:WebElementImageURLKey]
-            && [[[self _webView] preferences] loadsImagesAutomatically]
-            && (_private->dragSourceActionMask & WebDragSourceActionImage))
-        return YES;
-    
-    if ([mouseDownElement objectForKey:WebElementLinkURLKey]
-            && (_private->dragSourceActionMask & WebDragSourceActionLink)
-            && [[mouseDownElement objectForKey:WebElementLinkIsLiveKey] boolValue])
-        return YES;
-    
-    if ([[mouseDownElement objectForKey:WebElementIsSelectedKey] boolValue]
-            && (_private->dragSourceActionMask & WebDragSourceActionSelection))
-        return YES;
-    
-    return NO;
-}
-
 - (WebPluginController *)_pluginController
 {
     return _private->pluginController;
@@ -1639,7 +1590,7 @@ static WebHTMLView *lastHitView;
 
 - (BOOL)_isEditable
 {
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (!coreFrame)
         return NO;
     return coreFrame->selectionController()->isContentEditable();
@@ -1731,7 +1682,7 @@ static WebHTMLView *lastHitView;
 
 - (BOOL)_web_firstResponderCausesFocusDisplay
 {
-    return [self _web_firstResponderIsSelfOrDescendantView] || [[self window] firstResponder] == [self _frameView];
+    return [[self window] firstResponder] == self || [[self window] firstResponder] == [self _frameView];
 }
 
 - (void)_updateActiveState
@@ -1762,7 +1713,7 @@ static WebHTMLView *lastHitView;
     BOOL windowIsKey = [window isKeyWindow];
     BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow];
 
-    BOOL isActive = !_private->resigningFirstResponder && windowIsKey && (_private->descendantBecomingFirstResponder || [self _web_firstResponderCausesFocusDisplay]);
+    BOOL isActive = !_private->resigningFirstResponder && windowIsKey && [self _web_firstResponderCausesFocusDisplay];
     frame->setIsActive(isActive);            
 
     Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
@@ -1826,6 +1777,115 @@ static WebHTMLView *lastHitView;
     [self removeAllToolTips];
     [_private clear];
     _private->closed = YES;
+    Page* page = core([self _webView]);
+    if (page)
+        page->dragController()->setDraggingImageURL(KURL());
+}
+
+- (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
+                                                 forType:(NSString *)pboardType
+                                               inContext:(DOMRange *)context
+{
+    if (pboardType == WebArchivePboardType) {
+        WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
+        [archive release];
+        return fragment;
+    }
+    if (pboardType == NSFilenamesPboardType)
+        return [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
+        
+    if (pboardType == NSHTMLPboardType) {
+        NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
+        // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
+        if ([HTMLString hasPrefix:@"Version:"]) {
+            NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
+            if (range.location != NSNotFound)
+                HTMLString = [HTMLString substringFromIndex:range.location];
+        }
+        if ([HTMLString length] == 0)
+            return nil;
+        
+        return [[self _bridge] documentFragmentWithMarkupString:HTMLString baseURLString:nil];
+    }
+    if (pboardType == NSRTFPboardType || pboardType == NSRTFDPboardType) {
+        NSAttributedString *string = nil;
+        if (pboardType == NSRTFDPboardType)
+            string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
+        if (string == nil)
+            string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
+        if (string == nil)
+            return nil;
+            
+        NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
+            [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
+            self, @"WebResourceHandler", nil];
+        NSArray *subresources;
+        
+        BOOL wasDeferringCallbacks = [[self _webView] defersCallbacks];
+        if (!wasDeferringCallbacks)
+            [[self _webView] setDefersCallbacks:YES];
+            
+        DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
+                                                          document:[[self _frame] DOMDocument] 
+                                                documentAttributes:documentAttributes
+                                                      subresources:&subresources];
+        
+        NSEnumerator *e = [subresources objectEnumerator];
+        WebResource *r;
+        while ((r = [e nextObject]))
+            [[self _dataSource] addSubresource:r];
+        
+        if (!wasDeferringCallbacks)
+            [[self _webView] setDefersCallbacks:NO];
+        
+        [documentAttributes release];
+        [string release];
+        return fragment;
+    }
+    if (pboardType == NSTIFFPboardType) {
+        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
+                                                              URL:uniqueURLWithRelativePart(@"image.tiff")
+                                                         MIMEType:@"image/tiff" 
+                                                 textEncodingName:nil
+                                                        frameName:nil];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
+        [resource release];
+        return fragment;
+    }
+    if (pboardType == NSPICTPboardType) {
+        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPICTPboardType]
+                                                              URL:uniqueURLWithRelativePart(@"image.pict")
+                                                         MIMEType:@"image/pict" 
+                                                 textEncodingName:nil
+                                                        frameName:nil];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
+        [resource release];
+        return fragment;
+    }
+    if (pboardType == NSURLPboardType) {
+        NSURL *URL = [NSURL URLFromPasteboard:pasteboard];
+        DOMDocument* document = [[self _frame] DOMDocument];
+        ASSERT(document);
+        if (!document)
+            return nil;
+        DOMHTMLAnchorElement *anchor = (DOMHTMLAnchorElement *)[document createElement:@"a"];
+        NSString *URLString = [URL _web_originalDataAsString];
+        if ([URLString length] == 0)
+            return nil;
+        NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType];
+        DOMText *text = [document createTextNode:URLTitleString];
+        [anchor setHref:URLString];
+        [anchor appendChild:text];
+        DOMDocumentFragment *fragment = [document createDocumentFragment];
+        [fragment appendChild:anchor];
+        return fragment;
+    }
+    if (pboardType == NSStringPboardType)
+        return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]
+                                              inContext:context];
+                                              
+    return nil;
 }
 
 @end
@@ -1904,6 +1964,9 @@ static WebHTMLView *lastHitView;
     [NSApp registerServicesMenuSendTypes:[[self class] _selectionPasteboardTypes] 
                              returnTypes:[[self class] _insertablePasteboardTypes]];
     _NSInitializeKillRing();
+#ifndef BUILDING_ON_TIGER
+    WebCoreObjCFinalizeOnMainThread(self);
+#endif
 }
 
 - (void)_resetCachedWebPreferences:(NSNotification *)ignored
@@ -1922,6 +1985,8 @@ static WebHTMLView *lastHitView;
     if (!self)
         return nil;
     
+    [self setFocusRingType:NSFocusRingTypeNone];
+    
     // Make all drawing go through us instead of subviews.
     if (NSAppKitVersionNumber >= 711) {
         [self _setDrawsOwnDescendants:YES];
@@ -1952,6 +2017,7 @@ static WebHTMLView *lastHitView;
 
 - (void)finalize
 {
+    ASSERT_MAIN_THREAD();
     // We can't assert that close has already been called because
     // this view can be removed from it's superview, even though
     // it could be needed later, so close if needed.
@@ -2016,7 +2082,7 @@ static WebHTMLView *lastHitView;
 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 
 {
     SEL action = [item action];
-    FrameMac* frame = core([self _frame]);
+    Frame* frame = core([self _frame]);
 
     if (action == @selector(changeSpelling:)
             || action == @selector(_changeSpellingFromMenu:)
@@ -2088,7 +2154,7 @@ static WebHTMLView *lastHitView;
         return [self _canEdit];
     
     if (action == @selector(showGuessPanel:)) {
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
         // Match OS X AppKit behavior for post-Tiger. Don't change Tiger behavior.
         NSMenuItem *menuItem = (NSMenuItem *)item;
         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
@@ -2224,7 +2290,7 @@ static WebHTMLView *lastHitView;
         return [self _hasSelection];
     } 
     
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
     if (action == @selector(toggleGrammarChecking:)) {
         // FIXME 4799134: WebView is the bottleneck for this grammar-checking logic, but we must validate 
         // the selector here because we implement it here, and we must implement it here because the AppKit 
@@ -2286,7 +2352,7 @@ static WebHTMLView *lastHitView;
     if (nextResponder == self)
         return YES;
 
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     bool selectionIsEditable = coreFrame && coreFrame->selectionController()->isContentEditable();
     bool nextResponderIsInWebView = [nextResponder isKindOfClass:[NSView class]]
         && [nextResponder isDescendantOf:[[[self _webView] mainFrame] frameView]];
@@ -2560,7 +2626,7 @@ static WebHTMLView *lastHitView;
         return nil;
     }
 
-    handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(event);
+    handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event));
     _private->handlingMouseDownEvent = NO;
 
     if (!handledEvent)
@@ -2779,7 +2845,7 @@ static WebHTMLView *lastHitView;
 - (void)scrollWheel:(NSEvent *)event
 {
     [self retain];
-    FrameMac* frame = core([self _frame]);
+    Frame* frame = core([self _frame]);
     if (!frame || !frame->eventHandler()->wheelEvent(event))
         [[self nextResponder] scrollWheel:event];    
     [self release];
@@ -2801,7 +2867,7 @@ static WebHTMLView *lastHitView;
     
     if (hitHTMLView) {
         bool result = false;
-        if (FrameMac* coreFrame = core([hitHTMLView _frame])) {
+        if (Frame* coreFrame = core([hitHTMLView _frame])) {
             coreFrame->eventHandler()->setActivationEventNumber([event eventNumber]);
             [hitHTMLView _setMouseDownEvent:event];
             if ([hitHTMLView _isSelectionEvent:event])
@@ -2820,7 +2886,7 @@ static WebHTMLView *lastHitView;
     if (hitHTMLView) {
         bool result = false;
         if ([hitHTMLView _isSelectionEvent:event])
-            if (FrameMac* coreFrame = core([hitHTMLView _frame])) {
+            if (Frame* coreFrame = core([hitHTMLView _frame])) {
                 [hitHTMLView _setMouseDownEvent:event];
                 result = coreFrame->eventHandler()->eventMayStartDrag(event);
                 [hitHTMLView _setMouseDownEvent:nil];
@@ -2876,29 +2942,8 @@ done:
            source:(id)source
         slideBack:(BOOL)slideBack
 {
-    [self _stopAutoscrollTimer];
-
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView) {
-        [topHTMLView dragImage:dragImage at:[self convertPoint:at toView:topHTMLView]
-            offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
-        return;
-    }
-
-    WebView *webView = [self _webView];
-    Page *page = core(webView);
-    ASSERT(page);
-    page->dragController()->setDidInitiateDrag(true);
-    
-    // Retain this view during the drag because it may be released before the drag ends.
-    [self retain];
-
-    id UIDelegate = [webView UIDelegate];
-    // If a delegate takes over the drag but never calls draggedImage: endedAt:, we'll leak the WebHTMLView.
-    if ([UIDelegate respondsToSelector:@selector(webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:)])
-        [UIDelegate webView:webView dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack forView:self];
-    else
-        [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
+    ASSERT(self == [self _topHTMLView]);
+    [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
 }
 
 - (void)mouseDragged:(NSEvent *)event
@@ -2918,10 +2963,13 @@ done:
 
 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
 {
-    ASSERT([self _isTopHTMLView]);
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
     
     Page *page = core([self _webView]);
-    ASSERT(page);
+    
+    if (!page)
+        return NSDragOperationNone;
+    
     if (page->dragController()->dragOperation() == DragOperationNone)
         return NSDragOperationGeneric | NSDragOperationCopy;
     
@@ -2930,23 +2978,33 @@ done:
 
 - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenLoc
 {
-    ASSERT([self _isTopHTMLView]);
-
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
+    
     NSPoint windowImageLoc = [[self window] convertScreenToBase:screenLoc];
-    NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + _private->dragOffset.x, windowImageLoc.y + _private->dragOffset.y);
+    NSPoint windowMouseLoc = windowImageLoc;
+    
+    if (Page* page = core([self _webView])) {
+        DragController* dragController = page->dragController();
+        NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + dragController->dragOffset().x(), windowImageLoc.y + dragController->dragOffset().y());
+    }
+    
     [[self _bridge] dragSourceMovedTo:windowMouseLoc];
 }
 
 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
 {
     ASSERT(![self _webView] || [self _isTopHTMLView]);
-
+    
     NSPoint windowImageLoc = [[self window] convertScreenToBase:aPoint];
-    NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + _private->dragOffset.x, windowImageLoc.y + _private->dragOffset.y);
+    NSPoint windowMouseLoc = windowImageLoc;
+    
+    if (Page* page = core([self _webView])) {
+        DragController* dragController = page->dragController();
+        windowMouseLoc = NSMakePoint(windowImageLoc.x + dragController->dragOffset().x(), windowImageLoc.y + dragController->dragOffset().y());
+        dragController->dragEnded();
+    }
+    
     [[self _bridge] dragSourceEndedAt:windowMouseLoc operation:operation];
-    Page *page = core([self _webView]);
-    ASSERT(page);
-    page->dragController()->dragEnded();
     
     // Prevent queued mouseDragged events from coming after the drag and fake mouseUp event.
     _private->ignoringMouseDraggedEvents = YES;
@@ -2961,17 +3019,23 @@ done:
                                              context:[[NSApp currentEvent] context]
                                          eventNumber:0 clickCount:0 pressure:0];
     [self mouseUp:fakeEvent]; // This will also update the mouseover state.
-    
-    // Balance the previous retain from when the drag started.
-    [self release];
 }
 
 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
 {
-    ASSERT([self _isTopHTMLView]);
-    ASSERT(_private->draggingImageURL);
-
-    NSFileWrapper *wrapper = [[self _dataSource] _fileWrapperForURL:_private->draggingImageURL];
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
+    Page* page = core([self _webView]);
+    
+    //If a load occurs midway through a drag, the view may be detached, which gives
+    //us no ability to get to the original Page, so we cannot access any drag state
+    //FIXME: is there a way to recover?
+    if (!page) 
+        return nil; 
+    
+    KURL imageURL = page->dragController()->draggingImageURL();
+    ASSERT(!imageURL.isEmpty());
+    
+    NSFileWrapper *wrapper = [[self _dataSource] _fileWrapperForURL:imageURL.getNSURL()];
     if (wrapper == nil) {
         LOG_ERROR("Failed to create image file. Did the source image change while dragging? (<rdar://problem/4244861>)");
         return nil;
@@ -3042,22 +3106,7 @@ done:
     page->focusController()->setFocusedFrame(frame);
     if (Document* document = frame->document())
         document->setFocusedNode(0);
-    
-    BOOL createdFakeEvent = NO;
-    KeyboardEvent* currentEvent = frame->eventHandler()->currentKeyboardEvent().get();
-    if (!currentEvent) {
-        // If we didn't get an event (for example, when using eventSender.keyDown() under DumpRenderTree), just fake a Tab keydown.
-        currentEvent = new KeyboardEvent(EventNames::keydownEvent, true, true,
-                                         frame->document() ? frame->document()->defaultView() : 0,
-                                         "U+000009", KeyboardEvent::DOM_KEY_LOCATION_STANDARD, false, false, false, false, false);
-        createdFakeEvent = YES;
-    }
-    
-    page->focusController()->advanceFocus(currentEvent);
-    
-    if (createdFakeEvent)
-        delete currentEvent;
-
+    page->focusController()->advanceFocus(frame->eventHandler()->currentKeyboardEvent().get());
     return YES;
 }
 
@@ -3691,8 +3740,10 @@ done:
 
     EAffinity affinity = coreFrame->selectionController()->affinity();
     WebView *webView = [self _webView];
-    if ([[webView _editingDelegateForwarder] webView:webView shouldChangeSelectedDOMRange:[self _selectedRange] toDOMRange:domRange affinity:kit(affinity) stillSelecting:NO])
-        selectRange(coreFrame->selectionController(), range.get(), affinity, true);
+    if ([[webView _editingDelegateForwarder] webView:webView shouldChangeSelectedDOMRange:[self _selectedRange] toDOMRange:domRange affinity:kit(affinity) stillSelecting:NO]) {
+        ExceptionCode ec = 0;
+        coreFrame->selectionController()->setSelectedRange(range.get(), affinity, true, ec);
+    }
 }
 
 - (void)selectParagraph:(id)sender
@@ -3717,7 +3768,7 @@ done:
 
 - (void)delete:(id)sender
 {
-#if USING_WEBCORE_DELETE
+#ifdef USING_WEBCORE_DELETE
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->performDelete();
@@ -3921,12 +3972,8 @@ done:
     // But don't do it if we have already handled the event.
     // Pressing Esc results in a fake event being sent - don't pass it to WebCore.
     if (!eventWasSentToWebCore && event == [NSApp currentEvent] && self == [[self window] firstResponder])
-        if (Frame* frame = core([self _frame])) {
-            NSEvent *savedPerformKeyEquivalentEvent = performKeyEquivalentEvent;
-            performKeyEquivalentEvent = event;
+        if (Frame* frame = core([self _frame]))
             ret = frame->eventHandler()->keyEvent(event);
-            performKeyEquivalentEvent = savedPerformKeyEquivalentEvent;
-        }
 
     if (!ret)
         ret = [super performKeyEquivalent:event];
@@ -4249,54 +4296,27 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 
 - (void)insertTab:(id)sender
 {
-    [self insertText:@"\t"];
+    [self _insertTabWithEvent:0 isBackTab:NO];
 }
 
 - (void)insertBacktab:(id)sender
 {
-    // Doing nothing matches normal NSTextView behavior. If we ever use WebView for a field-editor-type purpose
-    // we might add code here.
+    [self _insertTabWithEvent:0 isBackTab:YES];
 }
 
 - (void)insertNewline:(id)sender
 {
-    if (![self _canEdit])
-        return;
-        
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
-        if ([self _canEditRichly])
-            [bridge insertParagraphSeparator];
-        else
-            [bridge insertLineBreak];
-    }
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)insertLineBreak:(id)sender
 {
-    if (![self _canEdit])
-        return;
-        
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped])
-        [bridge insertLineBreak];
+    [self _insertNewlineWithEvent:0 isLineBreak:YES];
 }
 
 - (void)insertParagraphSeparator:(id)sender
 {
-    if (![self _canEdit])
-        return;
-
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
-        if ([self _canEditRichly])
-            [bridge insertParagraphSeparator];
-        else
-            [bridge insertLineBreak];
-    }
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)_changeWordCaseWithSelector:(SEL)selector
@@ -4431,7 +4451,7 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
     }
     
     NSPanel *spellingPanel = [checker spellingPanel];
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
     // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
     // to match rest of OS X.
     if ([spellingPanel isVisible]) {
@@ -4506,12 +4526,12 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 
 - (void)insertNewlineIgnoringFieldEditor:(id)sender
 {
-    [self insertNewline:sender];
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)insertTabIgnoringFieldEditor:(id)sender
 {
-    [self insertTab:sender];
+    [self _insertTabWithEvent:0 isBackTab:NO];
 }
 
 - (void)subscript:(id)sender
@@ -4555,9 +4575,10 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
         return;
     
     NSString* yankee = _NSYankFromKillRing();
-    if ([yankee length])
-        [self insertText:yankee];
-    else
+    if ([yankee length]) {
+        if (Frame* coreFrame = core([self _frame]))
+            coreFrame->editor()->insertText(yankee, false);
+    } else
         [self deleteBackward:nil];
 
     _NSSetKillRingToYankedState();
@@ -4569,9 +4590,10 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
         return;
 
     NSString* yankee = _NSYankPreviousFromKillRing();
-    if ([yankee length])
-        [self _insertText:yankee selectInsertedText:YES];
-    else
+    if ([yankee length]) {
+        if (Frame* coreFrame = core([self _frame]))
+            coreFrame->editor()->insertText(yankee, true);
+    } else
         [self deleteBackward:nil];
         
     _NSSetKillRingToYankedState();
@@ -4622,40 +4644,31 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 {
     WebFrameBridge *bridge = [self _bridge];
     DOMRange *mark = [bridge markDOMRange];
-    if (mark == nil) {
-        NSBeep();
-        return;
-    }
     DOMRange *selection = [self _selectedRange];
     Frame* coreFrame = core([self _frame]);
-    NS_DURING
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(unionDOMRanges(mark, selection)), DOWNSTREAM, true);
-    NS_HANDLER
+    if (!mark || !selection || !coreFrame) {
         NSBeep();
-    NS_ENDHANDLER
+        return;
+    }
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(unionDOMRanges(mark, [self _selectedRange])), DOWNSTREAM, true, ec);
 }
 
 - (void)swapWithMark:(id)sender
 {
     WebFrameBridge *bridge = [self _bridge];
     DOMRange *mark = [bridge markDOMRange];
-
-    if (mark == nil) {
-        NSBeep();
-        return;
-    }
-
     DOMRange *selection = [self _selectedRange];
     Frame* coreFrame = core([self _frame]);
-    NS_DURING
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(mark), DOWNSTREAM, true);
-    NS_HANDLER
+    if (!mark || !selection || !coreFrame) {
         NSBeep();
         return;
-    NS_ENDHANDLER
-    [bridge setMarkDOMRange:selection];
+    }
+
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(mark), DOWNSTREAM, true, ec);
+    if (ec == 0)
+        [bridge setMarkDOMRange:selection];
 }
 
 - (void)transpose:(id)sender
@@ -4677,8 +4690,11 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         return;
 
     Frame* coreFrame = core([self _frame]);
-    if (coreFrame)
-        selectRange(coreFrame->selectionController(), core(r), DOWNSTREAM, true);
+    if (!coreFrame)
+        return;
+
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(r), DOWNSTREAM, true, ec);
     if ([self _shouldReplaceSelectionWithText:transposed givenAction:WebViewInsertActionTyped])
         [bridge replaceSelectionWithText:transposed selectReplacement:NO smartReplace:NO];
 }
@@ -4896,26 +4912,6 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         core([self _frame])->editor()->setStartNewKillRingSequence(true);
 }
 
-- (void)_formControlIsBecomingFirstResponder:(NSView *)formControl
-{
-    if (![formControl isDescendantOf:self])
-        return;
-    _private->descendantBecomingFirstResponder = YES;
-    [self _updateActiveState];
-    _private->descendantBecomingFirstResponder = NO;
-}
-
-- (void)_formControlIsResigningFirstResponder:(NSView *)formControl
-{
-    // set resigningFirstResponder so _updateActiveState behaves the same way it does when
-    // the WebHTMLView itself is resigningFirstResponder; don't use the primary selection feedback.
-    // If the first responder is in the process of being set on the WebHTMLView itself, it will
-    // get another chance at _updateActiveState in its own becomeFirstResponder method.
-    _private->resigningFirstResponder = YES;
-    [self _updateActiveState];
-    _private->resigningFirstResponder = NO;
-}
-
 - (void)_updateFontPanel
 {
     // FIXME: NSTextView bails out if becoming or resigning first responder, for which it has ivar flags. Not
@@ -4946,23 +4942,6 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     // not reflected in the font panel. Maybe someday this will change.
 }
 
-- (unsigned)_delegateDragSourceActionMask
-{
-    ASSERT(_private->mouseDownEvent != nil);
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView) {
-        [topHTMLView _setMouseDownEvent:_private->mouseDownEvent];
-        unsigned result = [topHTMLView _delegateDragSourceActionMask];
-        [topHTMLView _setMouseDownEvent:nil];
-        return result;
-    }
-
-    WebView *webView = [self _webView];
-    NSPoint point = [webView convertPoint:[_private->mouseDownEvent locationInWindow] fromView:nil];
-    _private->dragSourceActionMask = [[webView _UIDelegateForwarder] webView:webView dragSourceActionMaskForPoint:point];
-    return _private->dragSourceActionMask;
-}
-
 - (BOOL)_canSmartCopyOrDelete
 {
     return [[self _webView] smartInsertDeleteEnabled] && [[self _bridge] selectionGranularity] == WordGranularity;
@@ -4994,6 +4973,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     return textView == _private->firstResponderTextViewAtMouseDownTime;
 }
 
+
+- (NSEvent *)_mouseDownEvent
+{
+    return _private->mouseDownEvent;
+}
+
 - (void)_pauseNullEventsForAllNetscapePlugins
 {
     NSArray *subviews = [self subviews];
@@ -5037,7 +5022,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)copy:(id)sender
 {
-#if USING_WEBCORE_COPY
+#ifdef USING_WEBCORE_COPY
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->copy();
@@ -5055,12 +5040,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)cut:(id)sender
 {
-#if USING_WEBCORE_CUT
+#ifdef USING_WEBCORE_CUT
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->cut();
 #else
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (coreFrame && coreFrame->editor()->tryDHTMLCut())
         return; // DHTML did the whole operation
     if (!coreFrame->editor()->canCut()) {
@@ -5078,12 +5063,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)paste:(id)sender
 {
-#if USING_WEBCORE_PASTE
+#ifdef USING_WEBCORE_PASTE
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->paste();
 #else
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (coreFrame && coreFrame->editor()->tryDHTMLPaste())
         return; // DHTML did the whole operation
     if (!coreFrame->editor()->canPaste())
@@ -5091,7 +5076,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     if (coreFrame && coreFrame->selectionController()->isContentRichlyEditable())
         [self _pasteWithPasteboard:[NSPasteboard generalPasteboard] allowPlainText:YES];
     else
-        [self _pasteAsPlainTextWithPasteboard:[NSPasteboard generalPasteboard]];
+        coreFrame->editor()->pasteAsPlainText();
 #endif
 }
 
@@ -5114,7 +5099,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     return [self _documentFragmentFromPasteboard:pasteboard inContext:nil allowPlainText:NO chosePlainText:&discard];
 }
 
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
 
 - (BOOL)isGrammarCheckingEnabled
 {
@@ -5137,9 +5122,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [[self _webView] toggleGrammarChecking:sender];
 }
 
-#endif /* !BUILDING_ON_TIGER */
 
-#if !BUILDING_ON_TIGER
 static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 {
     NSRect allScreensFrame = NSZeroRect;
@@ -5171,7 +5154,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     // We soft link to get the function that displays the dictionary (either pop-up window or app) to avoid the performance
     // penalty of linking to another framework. This function changed signature as well as framework between Tiger and Leopard,
     // so the two cases are handled separately.
-#if BUILDING_ON_TIGER
+#ifdef BUILDING_ON_TIGER
     static bool lookedForFunction = false;
     
     typedef OSStatus (*ServiceWindowShowFunction)(id inWordString, NSRect inWordBoundary, UInt16 inLineDirection);
@@ -5242,16 +5225,18 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     [self _updateMouseoverWithFakeEvent];
 }
 
-- (BOOL)_interceptEditingKeyEvent:(NSEvent *)event
+- (BOOL)_interceptEditingKeyEvent:(KeyboardEvent *)event
 {
-    // We shouldn't call interpretKeyEvents: on an event from performKeyEquivalent.
-    if (event == performKeyEquivalentEvent)
-        return NO;
-
-    // Ask AppKit to process the key event -- it will call back with the appropriate selector(s).
-    [self interpretKeyEvents:[NSArray arrayWithObject:event]];
-    // FIXME: We return YES here even though AppKit might have decided to not do anything with the event.
-    return YES;
+    // Ask AppKit to process the key event -- it will call back with either insertText or doCommandBySelector.
+    WebHTMLViewInterpretKeyEventsParameters parameters;
+    parameters.eventWasHandled = false;
+    if (const PlatformKeyboardEvent* platformEvent = event->keyEvent()) {
+        parameters.event = event;
+        _private->interpretKeyEventsParameters = &parameters;
+        [self interpretKeyEvents:[NSArray arrayWithObject:platformEvent->macEvent()]];
+        _private->interpretKeyEventsParameters = 0;
+    }
+    return parameters.eventWasHandled;
 }
 
 @end
@@ -5359,18 +5344,15 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 
 - (void)unmarkText
 {
-    [[self _bridge] setMarkedTextDOMRange:nil customAttributes:nil ranges:nil];
-}
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
 
-- (void)_selectMarkedText
-{
-    if ([self hasMarkedText]) {
-        WebFrameBridge *bridge = [self _bridge];
-        DOMRange *markedTextRange = [bridge markedTextDOMRange];
-        Frame* coreFrame = core([self _frame]);
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(markedTextRange), DOWNSTREAM, false);
-    }
+    if (parameters)
+        parameters->eventWasHandled = YES;
+
+    if (Frame* coreFrame = core([self _frame]))
+        coreFrame->editor()->unmarkText();
 }
 
 - (void)_selectRangeInMarkedText:(NSRange)range
@@ -5390,8 +5372,10 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     [selectedRange setEnd:[markedTextRange startContainer] offset:selectionEnd];
 
     Frame* coreFrame = core([self _frame]);
-    if (coreFrame)
-        selectRange(coreFrame->selectionController(), core(selectedRange), DOWNSTREAM, false);
+    if (coreFrame) {
+        ExceptionCode ec = 0;
+        coreFrame->selectionController()->setSelectedRange(core(selectedRange), DOWNSTREAM, false, ec);
+    }
 }
 
 - (void)_extractAttributes:(NSArray **)a ranges:(NSArray **)r fromAttributedString:(NSAttributedString *)string
@@ -5413,6 +5397,17 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 
 - (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange
 {
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
+
+    if (parameters)
+        parameters->eventWasHandled = YES;
+
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return;
+
     WebFrameBridge *bridge = [self _bridge];
 
     if (![self _isEditable])
@@ -5430,11 +5425,11 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
             [[self _bridge] selectNSRange:NSRangeFromString(rangeString)];
     }
 
-    _private->ignoreMarkedTextSelectionChange = YES;
+    coreFrame->editor()->setIgnoreMarkedTextSelectionChange(true);
 
     // if we had marked text already, we need to make sure to replace
     // that, instead of the selection/caret
-    [self _selectMarkedText];
+    coreFrame->editor()->selectMarkedText();
 
     NSString *text = string;
     NSArray *attributes = nil;
@@ -5449,65 +5444,75 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     if ([self hasMarkedText])
         [self _selectRangeInMarkedText:newSelRange];
 
-    _private->ignoreMarkedTextSelectionChange = NO;
+    coreFrame->editor()->setIgnoreMarkedTextSelectionChange(false);
 }
 
 - (void)doCommandBySelector:(SEL)aSelector
 {
-    WebView *webView = [self _webView];
-    if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector])
-        [super doCommandBySelector:aSelector];
-}
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
 
-- (void)_discardMarkedText
-{
-    if (![self hasMarkedText])
+    if (aSelector == @selector(noop:))
         return;
 
-    _private->ignoreMarkedTextSelectionChange = YES;
+    KeyboardEvent* event = parameters ? parameters->event : 0;
+    bool eventWasHandled = true;
 
-    [self _selectMarkedText];
-    [self unmarkText];
-    [[NSInputManager currentInputManager] markedTextAbandoned:self];
-    // FIXME: Should we be calling the delegate here?
-    if (Frame* coreFrame = core([self _frame]))
-        coreFrame->editor()->deleteSelectionWithSmartDelete(false);
-
-    _private->ignoreMarkedTextSelectionChange = NO;
-}
-
-- (void)_insertText:(NSString *)text selectInsertedText:(BOOL)selectText
-{
-    if (text == nil || [text length] == 0 || (![self _isEditable] && ![self hasMarkedText]))
-        return;
-
-    if (![self _shouldReplaceSelectionWithText:text givenAction:WebViewInsertActionTyped]) {
-        [self _discardMarkedText];
-        return;
+    WebView *webView = [self _webView];
+    if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector]) {
+        if (aSelector == @selector(insertNewline:) || aSelector == @selector(insertParagraphSeparator:) || aSelector == @selector(insertNewlineIgnoringFieldEditor:))
+            eventWasHandled = [self _insertNewlineWithEvent:event isLineBreak:NO];
+        else if (aSelector == @selector(insertLineBreak:))
+            eventWasHandled = [self _insertNewlineWithEvent:event isLineBreak:YES];
+        else if (aSelector == @selector(insertTab:) || aSelector == @selector(insertTabIgnoringFieldEditor:))
+            eventWasHandled = [self _insertTabWithEvent:event isBackTab:NO];
+        else if (aSelector == @selector(insertBacktab:))
+            eventWasHandled = [self _insertTabWithEvent:event isBackTab:YES];
+        else
+            [super doCommandBySelector:aSelector];
     }
 
-    _private->ignoreMarkedTextSelectionChange = YES;
-
-    // If we had marked text, we replace that, instead of the selection/caret.
-    [self _selectMarkedText];
-
-    [[self _bridge] insertText:text selectInsertedText:selectText];
-
-    _private->ignoreMarkedTextSelectionChange = NO;
-
-    // Inserting unmarks any marked text.
-    [self unmarkText];
+    if (parameters)
+        parameters->eventWasHandled = eventWasHandled;
 }
 
 - (void)insertText:(id)string
 {
-    // We don't yet support inserting an attributed string but input methods don't appear to require this.
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
+
+    // We don't support inserting an attributed string but input methods don't appear to require this.
     NSString *text;
     if ([string isKindOfClass:[NSAttributedString class]])
         text = [string string];
     else
         text = string;
-    [self _insertText:text selectInsertedText:NO];
+
+    bool eventHandled = false;
+    if ([text length]) {
+        Frame* coreFrame = core([self _frame]);
+        KeyboardEvent* event = parameters ? parameters->event : 0;
+        String eventText = text;
+        eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore
+        eventHandled = coreFrame && coreFrame->eventHandler()->handleTextInputEvent(eventText, event);
+    }
+
+    if (parameters)
+        parameters->eventWasHandled = eventHandled;
+}
+
+- (BOOL)_insertNewlineWithEvent:(KeyboardEvent*)event isLineBreak:(BOOL)isLineBreak
+{
+    Frame* coreFrame = core([self _frame]);
+    return coreFrame && coreFrame->eventHandler()->handleTextInputEvent("\n", event, isLineBreak);
+}
+
+- (BOOL)_insertTabWithEvent:(KeyboardEvent*)event isBackTab:(BOOL)isBackTab
+{
+    Frame* coreFrame = core([self _frame]);
+    return coreFrame && coreFrame->eventHandler()->handleTextInputEvent("\t", event, false, isBackTab);
 }
 
 - (BOOL)_selectionIsInsideMarkedText
@@ -5535,7 +5540,14 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 
 - (void)_updateSelectionForInputManager
 {
-    if (![self hasMarkedText] || _private->ignoreMarkedTextSelectionChange)
+    if (![self hasMarkedText])
+        return;
+
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return;
+
+    if (coreFrame->editor()->ignoreMarkedTextSelectionChange())
         return;
 
     if ([self _selectionIsInsideMarkedText]) {
@@ -5610,7 +5622,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     [_tableView setDrawsGrid:NO];
     [_tableView setCornerView:nil];
     [_tableView setHeaderView:nil];
-    [_tableView setAutoresizesAllColumnsToFit:YES];
+    [_tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
     [_tableView setDelegate:self];
     [_tableView setDataSource:self];
     [_tableView setTarget:self];
@@ -5629,7 +5641,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
     [scrollView release];
     [_popupWindow setHasShadow:YES];
     [_popupWindow setOneShot:YES];
-    //[_popupWindow _setForceActiveControls:YES];   // AK secret - no known problem from leaving this out
+    [_popupWindow _setForceActiveControls:YES];
     [_popupWindow setReleasedWhenClosed:NO];
 }
 
@@ -5922,7 +5934,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 {
     NSAttributedString *attributedString = [self _attributeStringFromDOMRange:[self _selectedRange]];
     if (!attributedString) {
-        FrameMac* coreFrame = core([self _frame]);
+        Frame* coreFrame = core([self _frame]);
         if (coreFrame) {
             RefPtr<Range> range = coreFrame->selectionController()->selection().toRange();
             attributedString = [NSAttributedString _web_attributedStringFromRange:range.get()];
@@ -5962,3 +5974,18 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
 }
 
 @end
+
+// This is used by AppKit and is included here so that WebDataProtocolScheme is only defined once.
+@implementation NSURL (WebDataURL)
+
++ (NSURL *)_web_uniqueWebDataURL
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@", WebDataProtocolScheme, UUIDString]];
+    CFRelease(UUIDString);
+    return URL;
+}
+
+@end