849795d9534c22a714d308f3b8e92fdf5933c30c
[WebKit-https.git] / WebCore / bridge / mac / WebCoreFrameBridge.mm
1 /*
2  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2005, 2006 Alexey Proskuryakov (ap@nypop.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #import "config.h"
28 #import "WebCoreFrameBridge.h"
29
30 #import "Cache.h"
31 #import "DOMInternal.h"
32 #import "DocumentTypeImpl.h"
33 #import "FrameTree.h"
34 #import "FrameView.h"
35 #import "HTMLFormElementImpl.h"
36 #import "HTMLInputElementImpl.h"
37 #import "KWQAccObjectCache.h"
38 #import "KWQCharsets.h"
39 #import "KWQClipboard.h"
40 #import "KWQEditCommand.h"
41 #import "KWQFont.h"
42 #import "KWQFoundationExtras.h"
43 #import "KWQLoader.h"
44 #import "KWQPageState.h"
45 #import "KWQPrinter.h"
46 #import "KWQRenderTreeDebug.h"
47 #import "KWQTextCodec.h"
48 #import "KWQView.h"
49 #import "MacFrame.h"
50 #import "NodeImpl.h"
51 #import "PageMac.h"
52 #import "SelectionController.h"
53 #import "WebCoreFrameNamespaces.h"
54 #import "WebCorePageBridge.h"
55 #import "WebCoreSettings.h"
56 #import "WebCoreTextRendererFactory.h"
57 #import "WebCoreViewFactory.h"
58 #import "csshelper.h"
59 #import "DeleteSelectionCommand.h"
60 #import "dom2_eventsimpl.h"
61 #import "dom2_range.h"
62 #import "dom2_rangeimpl.h"
63 #import "dom2_viewsimpl.h"
64 #import "dom_node.h"
65 #import "dom_position.h"
66 #import "html_documentimpl.h"
67 #import "html_imageimpl.h"
68 #import "htmlediting.h"
69 #import "htmlnames.h"
70 #import "kjs_proxy.h"
71 #import "kjs_window.h"
72 #import "loader.h"
73 #import "markup.h"
74 #import "MoveSelectionCommand.h"
75 #import "render_canvas.h"
76 #import "render_frames.h"
77 #import "render_image.h"
78 #import "render_replaced.h"
79 #import "render_style.h"
80 #import "ReplaceSelectionCommand.h"
81 #import "TypingCommand.h"
82 #import "VisiblePosition.h"
83 #import "visible_text.h"
84 #import "visible_units.h"
85 #import "xml_tokenizer.h"
86 #import <JavaScriptCore/date_object.h>
87 #import <JavaScriptCore/interpreter.h>
88 #import <JavaScriptCore/jni_jsobject.h>
89 #import <JavaScriptCore/npruntime.h>
90 #import <JavaScriptCore/object.h>
91 #import <JavaScriptCore/property_map.h>
92 #import <JavaScriptCore/runtime_root.h>
93 #import <kxmlcore/Assertions.h>
94
95 @class NSView;
96
97 using namespace WebCore;
98 using namespace HTMLNames;
99
100 using KJS::ExecState;
101 using KJS::Interpreter;
102 using KJS::JSLock;
103 using KJS::JSObject;
104 using KJS::JSValue;
105 using KJS::SavedProperties;
106 using KJS::SavedBuiltins;
107 using KJS::Window;
108 using KJS::BooleanType;
109 using KJS::StringType;
110 using KJS::NumberType;
111 using KJS::ObjectType;
112 using KJS::UnspecifiedType;
113 using KJS::UndefinedType;
114 using KJS::NullType;
115 using KJS::GetterSetterType;
116 using KJS::UString;
117 using KJS::Identifier;
118 using KJS::List;
119 using KJS::JSType;
120 using KJS::DateInstance;
121
122 using KJS::Bindings::RootObject;
123
124 using WebCore::RenderObject;
125
126 NSString *WebCoreElementDOMNodeKey =            @"WebElementDOMNode";
127 NSString *WebCoreElementFrameKey =              @"WebElementFrame";
128 NSString *WebCoreElementImageAltStringKey =     @"WebElementImageAltString";
129 NSString *WebCoreElementImageRectKey =          @"WebElementImageRect";
130 NSString *WebCoreElementImageURLKey =           @"WebElementImageURL";
131 NSString *WebCoreElementIsSelectedKey =         @"WebElementIsSelected";
132 NSString *WebCoreElementLinkURLKey =            @"WebElementLinkURL";
133 NSString *WebCoreElementLinkTargetFrameKey =    @"WebElementTargetFrame";
134 NSString *WebCoreElementLinkLabelKey =          @"WebElementLinkLabel";
135 NSString *WebCoreElementLinkTitleKey =          @"WebElementLinkTitle";
136 NSString *WebCoreElementNameKey =               @"WebElementName";
137 NSString *WebCoreElementTitleKey =              @"WebCoreElementTitle"; // not in WebKit API for now, could be in API some day
138
139 NSString *WebCorePageCacheStateKey =            @"WebCorePageCacheState";
140
141 @interface WebCoreFrameBridge (WebCoreBridgeInternal)
142 - (RootObject *)executionContextForView:(NSView *)aView;
143 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point;
144 @end
145
146 static RootObject *rootForView(void *v)
147 {
148     NSView *aView = (NSView *)v;
149     WebCoreFrameBridge *aBridge = [[WebCoreViewFactory sharedFactory] bridgeForView:aView];
150     RootObject *root = 0;
151
152     if (aBridge)
153         root = [aBridge executionContextForView:aView];
154
155     return root;
156 }
157
158 static pthread_t mainThread = 0;
159
160 static void updateRenderingForBindings (ExecState *exec, JSObject *rootObject)
161 {
162     if (pthread_self() != mainThread)
163         return;
164         
165     if (!rootObject)
166         return;
167         
168     Window *window = static_cast<Window*>(rootObject);
169     if (!window)
170         return;
171         
172     DocumentImpl *doc = static_cast<DocumentImpl*>(window->frame()->document());
173     if (doc)
174         doc->updateRendering();
175 }
176
177 static BOOL frameHasSelection(WebCoreFrameBridge *bridge)
178 {
179     if (!bridge)
180         return NO;
181     
182     Frame *frame = [bridge impl];
183     if (!frame)
184         return NO;
185         
186     if (frame->selection().isNone())
187         return NO;
188
189     // If a part has a selection, it should also have a document.        
190     ASSERT(frame->document());
191
192     return YES;
193 }
194
195 static BOOL hasCaseInsensitivePrefix(NSString *string, NSString *prefix)
196 {
197     return [string rangeOfString:prefix options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location !=
198         NSNotFound;
199 }
200
201 static BOOL isCaseSensitiveEqual(NSString *a, NSString *b)
202 {
203     return [a caseInsensitiveCompare:b] == NSOrderedSame;
204 }
205
206 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
207 {
208     NSAppleEventDescriptor* aeDesc = 0;
209     switch (jsValue->type()) {
210         case BooleanType:
211             aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
212             break;
213         case StringType:
214             aeDesc = [NSAppleEventDescriptor descriptorWithString:jsValue->getString().domString()];
215             break;
216         case NumberType: {
217             Float64 value = jsValue->getNumber();
218             aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
219             break;
220         }
221         case ObjectType: {
222             JSObject* object = jsValue->getObject();
223             if (object->inherits(&DateInstance::info)) {
224                 DateInstance* date = static_cast<DateInstance*>(object);
225                 double ms = 0;
226                 int tzOffset = 0;
227                 if (date->getTime(ms, tzOffset)) {
228                     CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
229                     LongDateTime ldt;
230                     if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
231                         aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
232                 }
233             }
234             if (!aeDesc) {
235                 JSValue* primitive = object->toPrimitive(exec);
236                 if (exec->hadException()) {
237                     exec->clearException();
238                     return [NSAppleEventDescriptor nullDescriptor];
239                 }
240                 return aeDescFromJSValue(exec, primitive);
241             }
242             break;
243         }
244         default:
245             LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
246             // no break;
247         case UnspecifiedType:
248         case UndefinedType:
249         case NullType:
250         case GetterSetterType:
251             aeDesc = [NSAppleEventDescriptor nullDescriptor];
252             break;
253     }
254     
255     return aeDesc;
256 }
257
258 @implementation WebCoreFrameBridge
259
260 static bool initializedObjectCacheSize = false;
261 static bool initializedKJS = false;
262
263 static inline WebCoreFrameBridge *bridge(Frame *frame)
264 {
265     if (!frame)
266         return nil;
267     return Mac(frame)->bridge();
268 }
269
270 - (WebCoreFrameBridge *)firstChild
271 {
272     return bridge(m_frame->tree()->firstChild());
273 }
274
275 - (WebCoreFrameBridge *)lastChild
276 {
277     return bridge(m_frame->tree()->lastChild());
278 }
279
280 - (unsigned)childCount
281 {
282     return m_frame->tree()->childCount();
283 }
284
285 - (WebCoreFrameBridge *)previousSibling;
286 {
287     return bridge(m_frame->tree()->previousSibling());
288 }
289
290 - (WebCoreFrameBridge *)nextSibling;
291 {
292     return bridge(m_frame->tree()->nextSibling());
293 }
294
295 - (BOOL)isDescendantOfFrame:(WebCoreFrameBridge *)ancestor
296 {
297     for (WebCoreFrameBridge *frame = self; frame; frame = [frame parent])
298         if (frame == ancestor)
299             return YES;
300
301     return NO;
302 }
303
304 - (WebCoreFrameBridge *)traverseNextFrameStayWithin:(WebCoreFrameBridge *)stayWithin
305 {
306     WebCoreFrameBridge *firstChild = [self firstChild];
307     if (firstChild) {
308         ASSERT(!stayWithin || [firstChild isDescendantOfFrame:stayWithin]);
309         return firstChild;
310     }
311
312     if (self == stayWithin)
313         return 0;
314
315     WebCoreFrameBridge *nextSibling = [self nextSibling];
316     if (nextSibling) {
317         assert(!stayWithin || [nextSibling isDescendantOfFrame:stayWithin]);
318         return nextSibling;
319     }
320
321     WebCoreFrameBridge *frame = self;
322     while (frame && !nextSibling && (!stayWithin || [frame parent] != stayWithin)) {
323         frame = (WebCoreFrameBridge *)[frame parent];
324         nextSibling = [frame nextSibling];
325     }
326
327     if (frame) {
328         ASSERT(!stayWithin || !nextSibling || [nextSibling isDescendantOfFrame:stayWithin]);
329         return nextSibling;
330     }
331
332     return nil;
333 }
334
335 - (void)appendChild:(WebCoreFrameBridge *)child
336 {
337     m_frame->tree()->appendChild(adoptRef(child->m_frame));
338 }
339
340 - (void)removeChild:(WebCoreFrameBridge *)child
341 {
342     m_frame->tree()->removeChild(child->m_frame);
343 }
344
345 - (WebCoreFrameBridge *)childFrameNamed:(NSString *)name
346 {
347     // FIXME: with a better data structure this could be O(1) instead of O(n) in number 
348     // of child frames
349     for (WebCoreFrameBridge *child = [self firstChild]; child; child = [child nextSibling])
350         if ([[child name] isEqualToString:name])
351             return child;
352
353     return nil;
354 }
355
356 // Returns the last child of us and any children, or self
357 - (WebCoreFrameBridge *)_deepLastChildFrame
358 {
359     WebCoreFrameBridge *result = self;
360     for (WebCoreFrameBridge *lastChild = [self lastChild]; lastChild; lastChild = [lastChild lastChild])
361         result = lastChild;
362
363     return result;
364 }
365
366 // Return next frame to be traversed, visiting children after parent
367 - (WebCoreFrameBridge *)nextFrameWithWrap:(BOOL)wrapFlag
368 {
369     WebCoreFrameBridge *result = [self traverseNextFrameStayWithin:nil];
370
371     if (!result && wrapFlag)
372         return [self mainFrame];
373
374     return result;
375 }
376
377 // Return previous frame to be traversed, exact reverse order of _nextFrame
378 - (WebCoreFrameBridge *)previousFrameWithWrap:(BOOL)wrapFlag
379 {
380     // FIXME: besides the wrap feature, this is just the traversePreviousNode algorithm
381
382     WebCoreFrameBridge *prevSibling = [self previousSibling];
383     if (prevSibling)
384         return [prevSibling _deepLastChildFrame];
385     if ([self parent])
386         return [self parent];
387     
388     // no siblings, no parent, self==top
389     if (wrapFlag)
390         return [self _deepLastChildFrame];
391
392     // top view is always the last one in this ordering, so prev is nil without wrap
393     return nil;
394 }
395
396 - (void)setFrameNamespace:(NSString *)ns
397 {
398     ASSERT(self == [self mainFrame]);
399
400     if (ns != _frameNamespace){
401         [WebCoreFrameNamespaces removeFrame:self fromNamespace:_frameNamespace];
402         ns = [ns copy];
403         [_frameNamespace release];
404         _frameNamespace = ns;
405         [WebCoreFrameNamespaces addFrame:self toNamespace:_frameNamespace];
406     }
407 }
408
409 - (NSString *)frameNamespace
410 {
411     ASSERT(self == [self mainFrame]);
412     return _frameNamespace;
413 }
414
415 - (BOOL)_shouldAllowAccessFrom:(WebCoreFrameBridge *)source
416 {
417     // if no source frame, allow access
418     if (source == nil)
419         return YES;
420
421     //   - allow access if the two frames are in the same window
422     if ([self mainFrame] == [source mainFrame])
423         return YES;
424
425     //   - allow if the request is made from a local file.
426     NSString *sourceDomain = [self domain];
427     if ([sourceDomain length] == 0)
428         return YES;
429
430     //   - allow access if this frame or one of its ancestors
431     //     has the same origin as source
432     for (WebCoreFrameBridge *ancestor = self; ancestor; ancestor = [ancestor parent]) {
433         NSString *ancestorDomain = [ancestor domain];
434         if (ancestorDomain != nil && 
435             isCaseSensitiveEqual(sourceDomain, ancestorDomain))
436             return YES;
437         
438         ancestor = [ancestor parent];
439     }
440
441     //   - allow access if this frame is a toplevel window and the source
442     //     can access its opener. Note that we only allow one level of
443     //     recursion here.
444     if ([self parent] == nil) {
445         NSString *openerDomain = [[self opener] domain];
446         if (openerDomain != nil && isCaseSensitiveEqual(sourceDomain, openerDomain))
447             return YES;
448     }
449     
450     // otherwise deny access
451     return NO;
452 }
453
454 - (WebCoreFrameBridge *)_descendantFrameNamed:(NSString *)name sourceFrame:(WebCoreFrameBridge *)source
455 {
456     for (WebCoreFrameBridge *frame = self; frame; frame = [frame traverseNextFrameStayWithin:self])
457         // for security reasons, we do not want to even make frames visible to frames that
458         // can't access them 
459         if ([[frame name] isEqualToString:name] && [frame _shouldAllowAccessFrom:source])
460             return frame;
461
462     return nil;
463 }
464
465 - (WebCoreFrameBridge *)_frameInAnyWindowNamed:(NSString *)name sourceFrame:(WebCoreFrameBridge *)source
466 {
467     ASSERT(self == [self mainFrame]);
468
469     // Try this WebView first.
470     WebCoreFrameBridge *frame = [self _descendantFrameNamed:name sourceFrame:source];
471
472     if (frame != nil)
473         return frame;
474
475     // Try other WebViews in the same set
476
477     if ([self frameNamespace] != nil) {
478         NSEnumerator *enumerator = [WebCoreFrameNamespaces framesInNamespace:[self frameNamespace]];
479         WebCoreFrameBridge *searchFrame;
480         while ((searchFrame = [enumerator nextObject]))
481             frame = [searchFrame _descendantFrameNamed:name sourceFrame:source];
482     }
483
484     return frame;
485 }
486
487 - (WebCoreFrameBridge *)findFrameNamed:(NSString *)name
488 {
489     // First, deal with 'special' names.
490     if ([name isEqualToString:@"_self"] || [name isEqualToString:@"_current"])
491         return self;
492     
493     if ([name isEqualToString:@"_top"])
494         return [self mainFrame];
495     
496     if ([name isEqualToString:@"_parent"]) {
497         WebCoreFrameBridge *parent = [self parent];
498         return parent ? parent : self;
499     }
500     
501     if ([name isEqualToString:@"_blank"])
502         return nil;
503
504     // Search from this frame down.
505     WebCoreFrameBridge *frame = [self _descendantFrameNamed:name sourceFrame:self];
506
507     // Search in the main frame for this window then in others.
508     if (!frame)
509         frame = [[self mainFrame] _frameInAnyWindowNamed:name sourceFrame:self];
510
511     return frame;
512 }
513
514 + (NSArray *)supportedMIMETypes
515 {
516     return [NSArray arrayWithObjects:
517         @"text/html",
518         @"text/xml",
519         @"text/xsl",
520         @"application/xml",
521         @"application/xhtml+xml",
522         @"application/rss+xml",
523         @"application/atom+xml",
524         @"application/x-webarchive",
525         @"multipart/x-mixed-replace",
526 #if SVG_SUPPORT
527         @"image/svg+xml",
528 #endif
529         nil];
530 }
531
532 + (WebCoreFrameBridge *)bridgeForDOMDocument:(DOMDocument *)document
533 {
534     Frame *frame = [document _documentImpl]->frame();
535     return frame ? Mac(frame)->bridge() : nil;
536 }
537
538 - (id)initMainFrameWithPage:(WebCorePageBridge *)page
539 {
540     if (!initializedKJS) {
541         mainThread = pthread_self();
542         RootObject::setFindRootObjectForNativeHandleFunction(rootForView);
543         KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
544         initializedKJS = true;
545     }
546     
547     if (!(self = [super init]))
548         return nil;
549
550     m_frame = new MacFrame([page impl], 0);
551     m_frame->setBridge(self);
552     _shouldCreateRenderers = YES;
553
554     // FIXME: This is one-time initialization, but it gets the value of the setting from the
555     // current WebView. That's a mismatch and not good!
556     if (!initializedObjectCacheSize) {
557         Cache::setSize([self getObjectCacheSize]);
558         initializedObjectCacheSize = true;
559     }
560     
561     return self;
562 }
563
564 - (id)initSubframeWithRenderer:(RenderPart *)renderer
565 {
566     if (!(self = [super init]))
567         return nil;
568     
569     m_frame = new MacFrame(renderer->node()->getDocument()->frame()->page(), renderer);
570     m_frame->setBridge(self);
571     _shouldCreateRenderers = YES;
572     return self;
573 }
574
575 - (WebCorePageBridge *)page
576 {
577     return Mac(m_frame->page())->bridge();
578 }
579
580 - (void)initializeSettings: (WebCoreSettings *)settings
581 {
582     m_frame->setSettings ([settings settings]);
583 }
584
585 - (void)dealloc
586 {
587     [self removeFromFrame];
588     [super dealloc];
589 }
590
591 - (void)finalize
592 {
593     // FIXME: This work really should not be done at deallocation time.
594     // We need to do it at some well-defined time instead.
595
596     [self removeFromFrame];
597     m_frame->setBridge(nil);
598         
599     [super finalize];
600 }
601
602 - (MacFrame *)part
603 {
604     return m_frame;
605 }
606
607 - (WebCoreFrameBridge *)parent
608 {
609     MacFrame *parentFrame = Mac(m_frame->tree()->parent());
610     if (!parentFrame)
611         return nil;
612     return parentFrame->bridge();
613 }
614
615 - (void)provisionalLoadStarted
616 {
617     m_frame->provisionalLoadStarted();
618 }
619
620 - (void)openURL:(NSURL *)URL reload:(BOOL)reload contentType:(NSString *)contentType refresh:(NSString *)refresh lastModified:(NSDate *)lastModified pageCache:(NSDictionary *)pageCache
621 {
622     if (pageCache) {
623         KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
624         m_frame->openURLFromPageCache(state);
625         [state invalidate];
626         return;
627     }
628         
629     // arguments
630     URLArgs args(m_frame->browserExtension()->urlArgs());
631     args.reload = reload;
632     if (contentType) {
633         args.serviceType = QString::fromNSString(contentType);
634     }
635     m_frame->browserExtension()->setURLArgs(args);
636
637     // opening the URL
638     if (m_frame->didOpenURL(URL)) {
639         // things we have to set up after calling didOpenURL
640         if (refresh) {
641             m_frame->addMetaData("http-refresh", QString::fromNSString(refresh));
642         }
643         if (lastModified) {
644             NSString *modifiedString = [lastModified descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
645             m_frame->addMetaData("modified", QString::fromNSString(modifiedString));
646         }
647     }
648 }
649
650 - (void)setEncoding:(NSString *)encoding userChosen:(BOOL)userChosen
651 {
652     m_frame->setEncoding(QString::fromNSString(encoding), userChosen);
653 }
654
655 - (void)addData:(NSData *)data
656 {
657     DocumentImpl *doc = m_frame->document();
658     
659     // Document may be nil if the part is about to redirect
660     // as a result of JS executing during load, i.e. one frame
661     // changing another's location before the frame's document
662     // has been created. 
663     if (doc){
664         doc->setShouldCreateRenderers([self shouldCreateRenderers]);
665         m_frame->addData((const char *)[data bytes], [data length]);
666     }
667 }
668
669 - (void)closeURL
670 {
671     m_frame->closeURL();
672 }
673
674 - (void)stopLoading
675 {
676     m_frame->stopLoading();
677 }
678
679 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache
680 {
681     m_frame->didNotOpenURL(KURL(URL).url());
682
683     // We might have made a page cache item, but now we're bailing out due to an error before we ever
684     // transitioned to the new page (before WebFrameState==commit).  The goal here is to restore any state
685     // so that the existing view (that wenever got far enough to replace) can continue being used.
686     DocumentImpl *doc = m_frame->document();
687     if (doc) {
688         doc->setInPageCache(NO);
689     }
690     KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
691     [state invalidate];
692 }
693
694 - (BOOL)canLoadURL:(NSURL *)URL fromReferrer:(NSString *)referrer hideReferrer:(BOOL *)hideReferrer
695 {
696     BOOL referrerIsWebURL = hasCaseInsensitivePrefix(referrer, @"http:") || hasCaseInsensitivePrefix(referrer, @"https:");
697     BOOL referrerIsLocalURL = hasCaseInsensitivePrefix(referrer, @"file:") || hasCaseInsensitivePrefix(referrer, @"applewebdata:");
698     BOOL URLIsFileURL = [URL scheme] != NULL && [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
699     
700     *hideReferrer = !referrerIsWebURL;
701     return !URLIsFileURL || referrerIsLocalURL;
702 }
703
704 - (void)saveDocumentState
705 {
706     DocumentImpl *doc = m_frame->document();
707     if (doc != 0){
708         QStringList list = doc->docState();
709         NSMutableArray *documentState = [[[NSMutableArray alloc] init] autorelease];
710         
711         for (uint i = 0; i < list.count(); i++){
712             QString s = list[i];
713             [documentState addObject: [NSString stringWithCharacters: (const unichar *)s.unicode() length: s.length()]];
714         }
715         [self saveDocumentState: documentState];
716     }
717 }
718
719 - (void)restoreDocumentState
720 {
721     DocumentImpl *doc = m_frame->document();
722     
723     if (doc != 0){
724         NSArray *documentState = [self documentState];
725         
726         QStringList s;
727         for (uint i = 0; i < [documentState count]; i++){
728             NSString *string = [documentState objectAtIndex: i];
729             s.append(QString::fromNSString(string));
730         }
731             
732         doc->setRestoreState(s);
733     }
734 }
735
736 - (void)scrollToAnchorWithURL:(NSURL *)URL
737 {
738     m_frame->scrollToAnchor(KURL(URL).url().latin1());
739 }
740
741 - (BOOL)scrollOverflowInDirection:(WebScrollDirection)direction granularity:(WebScrollGranularity)granularity
742 {
743     if (m_frame == NULL) {
744         return NO;
745     }
746     return m_frame->scrollOverflow((KWQScrollDirection)direction, (KWQScrollGranularity)granularity);
747 }
748
749 - (BOOL)sendScrollWheelEvent:(NSEvent *)event
750 {
751     return m_frame ? m_frame->wheelEvent(event) : NO;
752 }
753
754 - (BOOL)saveDocumentToPageCache
755 {
756     DocumentImpl *doc = m_frame->document();
757     if (!doc)
758         return NO;
759     if (!doc->view())
760         return NO;
761
762     m_frame->clearTimers();
763
764     JSLock lock;
765
766     SavedProperties *windowProperties = new SavedProperties;
767     m_frame->saveWindowProperties(windowProperties);
768
769     SavedProperties *locationProperties = new SavedProperties;
770     m_frame->saveLocationProperties(locationProperties);
771     
772     SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
773     m_frame->saveInterpreterBuiltins(*interpreterBuiltins);
774
775     KWQPageState *pageState = [[KWQPageState alloc] initWithDocument:doc
776                                                                  URL:m_frame->url()
777                                                     windowProperties:windowProperties
778                                                   locationProperties:locationProperties
779                                                  interpreterBuiltins:interpreterBuiltins
780                                                       pausedTimeouts:m_frame->pauseTimeouts()];
781
782     BOOL result = [self saveDocumentToPageCache:pageState];
783
784     [pageState release];
785
786     return result;
787 }
788
789 - (BOOL)canCachePage
790 {
791     return m_frame->canCachePage();
792 }
793
794 - (void)clear
795 {
796     m_frame->clear();
797 }
798
799 - (void)end
800 {
801     m_frame->end();
802 }
803
804 - (void)stop
805 {
806     m_frame->stop();
807 }
808
809 - (void)clearFrame
810 {
811     m_frame = 0;
812 }
813
814 - (void)handleFallbackContent
815 {
816     // this needs to be callable even after teardown of the frame
817     if (!m_frame)
818         return;
819     m_frame->handleFallbackContent();
820 }
821
822 - (void)createFrameViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
823 {
824     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
825     [self removeFromFrame];
826
827     FrameView* kview = new FrameView(m_frame);
828     m_frame->setView(kview);
829     kview->deref();
830
831     kview->setView(view);
832     if (mw >= 0)
833         kview->setMarginWidth(mw);
834     if (mh >= 0)
835         kview->setMarginHeight(mh);
836 }
837
838 - (void)scrollToAnchor:(NSString *)a
839 {
840     m_frame->gotoAnchor(QString::fromNSString(a));
841 }
842
843 - (BOOL)isSelectionEditable
844 {
845     // EDIT FIXME: This needs to consider the entire selected range
846     NodeImpl *startNode = m_frame->selection().start().node();
847     return startNode ? startNode->isContentEditable() : NO;
848 }
849
850 - (WebSelectionState)selectionState
851 {
852     switch (m_frame->selection().state()) {
853         case WebCore::Selection::NONE:
854             return WebSelectionStateNone;
855         case WebCore::Selection::CARET:
856             return WebSelectionStateCaret;
857         case WebCore::Selection::RANGE:
858             return WebSelectionStateRange;
859     }
860     
861     ASSERT_NOT_REACHED();
862     return WebSelectionStateNone;
863 }
864
865 - (NSString *)_documentTypeString
866 {
867     NSString *documentTypeString = nil;
868     DocumentImpl *doc = m_frame->document();
869     if (doc) {
870         DocumentTypeImpl *doctype = doc->realDocType();
871         if (doctype) {
872             documentTypeString = doctype->toString().qstring().getNSString();
873         }
874     }
875     return documentTypeString;
876 }
877
878 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
879 {
880     NSString *documentTypeString = [self _documentTypeString];
881     if (documentTypeString && markupString) {
882         return [NSString stringWithFormat:@"%@%@", documentTypeString, markupString];
883     } else if (documentTypeString) {
884         return documentTypeString;
885     } else if (markupString) {
886         return markupString;
887     } else {
888         return @"";
889     }
890 }
891
892 - (NSArray *)nodesFromList:(QPtrList<NodeImpl> *)nodeList
893 {
894     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
895     for (QPtrListIterator<NodeImpl> i(*nodeList); i.current(); ++i) {
896         [nodes addObject:[DOMNode _nodeWithImpl:i.current()]];
897     }
898     return nodes;
899 }
900
901 - (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
902 {
903     // FIXME: This is never "for interchange". Is that right? See the next method.
904     QPtrList<NodeImpl> nodeList;
905     NSString *markupString = createMarkup([node _nodeImpl], IncludeNode, nodes ? &nodeList : 0).getNSString();
906     if (nodes) {
907         *nodes = [self nodesFromList:&nodeList];
908     }
909     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
910 }
911
912 - (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
913 {
914     // FIXME: This is always "for interchange". Is that right? See the previous method.
915     QPtrList<NodeImpl> nodeList;
916     NSString *markupString = createMarkup([range _rangeImpl], nodes ? &nodeList : 0, AnnotateForInterchange).getNSString();
917     if (nodes) {
918         *nodes = [self nodesFromList:&nodeList];
919     }
920     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
921 }
922
923 - (NSString *)selectedString
924 {
925     QString text = m_frame->selectedText();
926     text.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
927     return [[text.getNSString() copy] autorelease];
928 }
929
930 - (NSString *)stringForRange:(DOMRange *)range
931 {
932     QString text = plainText([range _rangeImpl]);
933     text.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
934     return [[text.getNSString() copy] autorelease];
935 }
936
937 - (void)selectAll
938 {
939     m_frame->selectAll();
940 }
941
942 - (void)deselectAll
943 {
944     [self deselectText];
945     DocumentImpl *doc = m_frame->document();
946     if (doc) {
947         doc->setFocusNode(0);
948     }
949 }
950
951 - (void)deselectText
952 {
953     // FIXME: 6498 Should just be able to call m_frame->selection().clear()
954     m_frame->setSelection(SelectionController());
955 }
956
957 - (BOOL)isFrameSet
958 {
959     return m_frame->isFrameSet();
960 }
961
962 - (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
963 {
964     m_frame->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
965     DocumentImpl *doc = m_frame->document();
966     if (doc)
967         doc->setPrinting(deviceType == WebCoreDevicePrinter);
968     return m_frame->reparseConfiguration();
969 }
970
971 static BOOL nowPrinting(WebCoreFrameBridge *self)
972 {
973     DocumentImpl *doc = self->m_frame->document();
974     return doc && doc->printing();
975 }
976
977 // Set or unset the printing mode in the view.  We only toy with this if we're printing.
978 - (void)_setupRootForPrinting:(BOOL)onOrOff
979 {
980     if (nowPrinting(self)) {
981         RenderCanvas *root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
982         if (root) {
983             root->setPrintingMode(onOrOff);
984         }
985     }
986 }
987
988 - (void)forceLayoutAdjustingViewSize:(BOOL)flag
989 {
990     [self _setupRootForPrinting:YES];
991     m_frame->forceLayout();
992     if (flag) {
993         [self adjustViewSize];
994     }
995     [self _setupRootForPrinting:NO];
996 }
997
998 - (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
999 {
1000     [self _setupRootForPrinting:YES];
1001     m_frame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth);
1002     if (flag) {
1003         [self adjustViewSize];
1004     }
1005     [self _setupRootForPrinting:NO];
1006 }
1007
1008 - (void)sendResizeEvent
1009 {
1010     m_frame->sendResizeEvent();
1011 }
1012
1013 - (void)sendScrollEvent
1014 {
1015     m_frame->sendScrollEvent();
1016 }
1017
1018 - (void)drawRect:(NSRect)rect withPainter:(QPainter *)p
1019 {
1020     [self _setupRootForPrinting:YES];
1021     m_frame->paint(p, enclosingIntRect(rect));
1022     [self _setupRootForPrinting:NO];
1023 }
1024
1025 - (void)drawRect:(NSRect)rect
1026 {
1027     QPainter painter(nowPrinting(self));
1028     bool displaysWithFocusAttributes = m_frame->displaysWithFocusAttributes();
1029     painter.setUsesInactiveTextBackgroundColor(!displaysWithFocusAttributes);
1030     [self drawRect:rect withPainter:&painter];
1031 }
1032
1033 // Used by pagination code called from AppKit when a standalone web page is printed.
1034 - (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
1035 {
1036     [self _setupRootForPrinting:YES];
1037     NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
1038     if (printWidthScaleFactor <= 0) {
1039         LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
1040         return pages;
1041     }
1042     
1043     if (printHeight <= 0) {
1044         LOG_ERROR("printHeight has bad value %.2f", printHeight);
1045         return pages;
1046     }
1047
1048     if (!m_frame || !m_frame->document() || !m_frame->view()) return pages;
1049     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1050     if (!root) return pages;
1051     
1052     FrameView* view = m_frame->view();
1053     NSView* documentView = view->getDocumentView();
1054     if (!documentView)
1055         return pages;
1056
1057     float currPageHeight = printHeight;
1058     float docHeight = root->layer()->height();
1059     float docWidth = root->layer()->width();
1060     float printWidth = docWidth/printWidthScaleFactor;
1061     
1062     // We need to give the part the opportunity to adjust the page height at each step.
1063     for (float i = 0; i < docHeight; i += currPageHeight) {
1064         float proposedBottom = kMin(docHeight, i + printHeight);
1065         m_frame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
1066         currPageHeight = kMax(1.0f, proposedBottom - i);
1067         for (float j = 0; j < docWidth; j += printWidth) {
1068             NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
1069             [pages addObject: val];
1070         }
1071     }
1072     [self _setupRootForPrinting:NO];
1073     
1074     return pages;
1075 }
1076
1077 // This is to support the case where a webview is embedded in the view that's being printed
1078 - (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
1079 {
1080     [self _setupRootForPrinting:YES];
1081     m_frame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
1082     [self _setupRootForPrinting:NO];
1083 }
1084
1085 - (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
1086 {
1087     NSMutableArray *children = [[NSMutableArray alloc] init];
1088     for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
1089         [children addObject:[self copyRenderNode:child copier:copier]];
1090     }
1091           
1092     NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
1093     
1094     RenderWidget *renderWidget = node->isWidget() ? static_cast<RenderWidget *>(node) : 0;
1095     Widget *widget = renderWidget ? renderWidget->widget() : 0;
1096     NSView *view = widget ? widget->getView() : nil;
1097     
1098     int nx, ny;
1099     node->absolutePosition(nx,ny);
1100     NSObject *copiedNode = [copier nodeWithName:name
1101                                        position:NSMakePoint(nx,ny)
1102                                            rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
1103                                            view:view
1104                                        children:children];
1105     
1106     [name release];
1107     [children release];
1108     
1109     return copiedNode;
1110 }
1111
1112 - (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
1113 {
1114     RenderObject *renderer = m_frame->renderer();
1115     if (!renderer) {
1116         return nil;
1117     }
1118     return [self copyRenderNode:renderer copier:copier];
1119 }
1120
1121 - (void)removeFromFrame
1122 {
1123     if (m_frame)
1124         m_frame->setView(0);
1125 }
1126
1127 - (void)installInFrame:(NSView *)view
1128 {
1129     // If this isn't the main frame, it must have a render m_frame set, or it
1130     // won't ever get installed in the view hierarchy.
1131     ASSERT(self == [self mainFrame] || m_frame->ownerRenderer());
1132
1133     m_frame->view()->setView(view);
1134     // FIXME: frame tries to do this too, is it needed?
1135     if (m_frame->ownerRenderer()) {
1136         m_frame->ownerRenderer()->setWidget(m_frame->view());
1137         // Now the render part owns the view, so we don't any more.
1138     }
1139
1140     m_frame->view()->initScrollBars();
1141 }
1142
1143 - (void)setActivationEventNumber:(int)num
1144 {
1145     m_frame->setActivationEventNumber(num);
1146 }
1147
1148 - (void)mouseDown:(NSEvent *)event
1149 {
1150     m_frame->mouseDown(event);
1151 }
1152
1153 - (void)mouseDragged:(NSEvent *)event
1154 {
1155     m_frame->mouseDragged(event);
1156 }
1157
1158 - (void)mouseUp:(NSEvent *)event
1159 {
1160     m_frame->mouseUp(event);
1161 }
1162
1163 - (void)mouseMoved:(NSEvent *)event
1164 {
1165     m_frame->mouseMoved(event);
1166 }
1167
1168 - (BOOL)sendContextMenuEvent:(NSEvent *)event
1169 {
1170     return m_frame->sendContextMenuEvent(event);
1171 }
1172
1173 - (DOMElement *)elementForView:(NSView *)view
1174 {
1175     // FIXME: implemented currently for only a subset of the KWQ widgets
1176     if ([view conformsToProtocol:@protocol(KWQWidgetHolder)]) {
1177         NSView <KWQWidgetHolder> *widgetHolder = view;
1178         Widget *widget = [widgetHolder widget];
1179         if (widget != nil && widget->eventFilterObject() != nil) {
1180             NodeImpl *node = static_cast<const RenderWidget *>(widget->eventFilterObject())->element();
1181             return [DOMElement _elementWithImpl:static_cast<ElementImpl *>(node)];
1182         }
1183     }
1184     return nil;
1185 }
1186
1187 static HTMLInputElementImpl *inputElementFromDOMElement(DOMElement *element)
1188 {
1189     NodeImpl *node = [element _nodeImpl];
1190     if (node->hasTagName(inputTag)) {
1191         return static_cast<HTMLInputElementImpl *>(node);
1192     }
1193     return nil;
1194 }
1195
1196 static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
1197 {
1198     NodeImpl *node = [element _nodeImpl];
1199     // This should not be necessary, but an XSL file on
1200     // maps.google.com crashes otherwise because it is an xslt file
1201     // that contains <form> elements that aren't in any namespace, so
1202     // they come out as generic CML elements
1203     if (node && node->hasTagName(formTag)) {
1204         return static_cast<HTMLFormElementImpl *>(node);
1205     }
1206     return nil;
1207 }
1208
1209 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
1210 {
1211     HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
1212     if (formElement) {
1213         Vector<HTMLGenericFormElementImpl*>& elements = formElement->formElements;
1214         AtomicString targetName = name;
1215         for (unsigned int i = 0; i < elements.size(); i++) {
1216             HTMLGenericFormElementImpl *elt = elements[i];
1217             // Skip option elements, other duds
1218             if (elt->name() == targetName)
1219                 return [DOMElement _elementWithImpl:elt];
1220         }
1221     }
1222     return nil;
1223 }
1224
1225 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
1226 {
1227     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1228     return inputElement != nil
1229         && inputElement->inputType() == HTMLInputElementImpl::TEXT
1230         && inputElement->autoComplete();
1231 }
1232
1233 - (BOOL)elementIsPassword:(DOMElement *)element
1234 {
1235     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1236     return inputElement != nil
1237         && inputElement->inputType() == HTMLInputElementImpl::PASSWORD;
1238 }
1239
1240 - (DOMElement *)formForElement:(DOMElement *)element;
1241 {
1242     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1243     if (inputElement) {
1244         HTMLFormElementImpl *formElement = inputElement->form();
1245         if (formElement) {
1246             return [DOMElement _elementWithImpl:formElement];
1247         }
1248     }
1249     return nil;
1250 }
1251
1252 - (DOMElement *)currentForm
1253 {
1254     HTMLFormElementImpl *formElement = m_frame->currentForm();
1255     return formElement ? [DOMElement _elementWithImpl:formElement] : nil;
1256 }
1257
1258 - (NSArray *)controlsInForm:(DOMElement *)form
1259 {
1260     NSMutableArray *results = nil;
1261     HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
1262     if (formElement) {
1263         Vector<HTMLGenericFormElementImpl*>& elements = formElement->formElements;
1264         for (unsigned int i = 0; i < elements.size(); i++) {
1265             if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1266                 DOMElement *de = [DOMElement _elementWithImpl:elements.at(i)];
1267                 if (!results) {
1268                     results = [NSMutableArray arrayWithObject:de];
1269                 } else {
1270                     [results addObject:de];
1271                 }
1272             }
1273         }
1274     }
1275     return results;
1276 }
1277
1278 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
1279 {
1280     return m_frame->searchForLabelsBeforeElement(labels, [element _elementImpl]);
1281 }
1282
1283 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
1284 {
1285     return m_frame->matchLabelsAgainstElement(labels, [element _elementImpl]);
1286 }
1287
1288 - (NSDictionary *)elementAtPoint:(NSPoint)point
1289 {
1290     RenderObject *renderer = m_frame->renderer();
1291     if (!renderer) 
1292         return nil;
1293     
1294     RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
1295     
1296     NSMutableDictionary *element = [NSMutableDictionary dictionary];
1297     [element setObject:[NSNumber numberWithBool:m_frame->isPointInsideSelection((int)point.x, (int)point.y)]
1298                 forKey:WebCoreElementIsSelectedKey];
1299
1300     // Find the title in the nearest enclosing DOM node.
1301     // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
1302     for (NodeImpl *titleNode = nodeInfo.innerNode(); titleNode; titleNode = titleNode->parentNode()) {
1303         if (titleNode->isElementNode()) {
1304             const AtomicString& title = static_cast<ElementImpl *>(titleNode)->getAttribute(titleAttr);
1305             if (!title.isNull()) {
1306                 // We found a node with a title.
1307                 QString titleText = title.qstring();
1308                 titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1309                 [element setObject:titleText.getNSString() forKey:WebCoreElementTitleKey];
1310                 break;
1311             }
1312         }
1313     }
1314
1315     NodeImpl *URLNode = nodeInfo.URLElement();
1316     if (URLNode) {
1317         ElementImpl *e = static_cast<ElementImpl *>(URLNode);
1318         DocumentImpl *doc = e->getDocument();
1319         ASSERT(doc);
1320         
1321         const AtomicString& title = e->getAttribute(titleAttr);
1322         if (!title.isEmpty()) {
1323             QString titleText = title.qstring();
1324             titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1325             [element setObject:titleText.getNSString() forKey:WebCoreElementLinkTitleKey];
1326         }
1327         
1328         const AtomicString& link = e->getAttribute(hrefAttr);
1329         if (!link.isNull()) {
1330             QString t = plainText(rangeOfContents(e).get());
1331             if (!t.isEmpty()) {
1332                 [element setObject:t.getNSString() forKey:WebCoreElementLinkLabelKey];
1333             }
1334             QString URLString = parseURL(link).qstring();
1335             [element setObject:doc->completeURL(URLString).getNSString() forKey:WebCoreElementLinkURLKey];
1336         }
1337         
1338         DOMString target = e->getAttribute(targetAttr);
1339         if (target.isEmpty() && doc) { // FIXME: Take out this doc check when we're not just before a release.
1340             target = doc->baseTarget();
1341         }
1342         if (!target.isEmpty()) {
1343             [element setObject:target.qstring().getNSString() forKey:WebCoreElementLinkTargetFrameKey];
1344         }
1345     }
1346
1347     NodeImpl *node = nodeInfo.innerNonSharedNode();
1348     if (node) {
1349         [element setObject:[DOMNode _nodeWithImpl:node] forKey:WebCoreElementDOMNodeKey];
1350     
1351         // Only return image information if there is an image.
1352         if (node->renderer() && node->renderer()->isImage()) {
1353             RenderImage *r = static_cast<RenderImage *>(node->renderer());
1354             int x, y;
1355             if (r->absolutePosition(x, y)) {
1356                 NSValue *rect = [NSValue valueWithRect:NSMakeRect(x, y, r->contentWidth(), r->contentHeight())];
1357                 [element setObject:rect forKey:WebCoreElementImageRectKey];
1358             }
1359
1360             ElementImpl *i = static_cast<ElementImpl*>(node);
1361     
1362             // FIXME: Code copied from RenderImage::updateFromElement; should share.
1363             DOMString attr;
1364             if (i->hasTagName(objectTag)) {
1365                 attr = i->getAttribute(dataAttr);
1366             } else {
1367                 attr = i->getAttribute(srcAttr);
1368             }
1369             if (!attr.isEmpty()) {
1370                 QString URLString = parseURL(attr).qstring();
1371                 [element setObject:i->getDocument()->completeURL(URLString).getNSString() forKey:WebCoreElementImageURLKey];
1372             }
1373             
1374             // FIXME: Code copied from RenderImage::updateFromElement; should share.
1375             DOMString alt;
1376             if (i->hasTagName(inputTag))
1377                 alt = static_cast<HTMLInputElementImpl *>(i)->altText();
1378             else if (i->hasTagName(imgTag))
1379                 alt = static_cast<HTMLImageElementImpl *>(i)->altText();
1380             if (!alt.isNull()) {
1381                 QString altText = alt.qstring();
1382                 altText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1383                 [element setObject:altText.getNSString() forKey:WebCoreElementImageAltStringKey];
1384             }
1385         }
1386     }
1387     
1388     return element;
1389 }
1390
1391 - (NSURL *)URLWithAttributeString:(NSString *)string
1392 {
1393     DocumentImpl *doc = m_frame->document();
1394     if (!doc) {
1395         return nil;
1396     }
1397     QString rel = parseURL(QString::fromNSString(string)).qstring();
1398     return KURL(doc->baseURL(), rel, doc->decoder() ? doc->decoder()->codec() : 0).getNSURL();
1399 }
1400
1401 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1402 {
1403     return m_frame->findString(string, forward, caseFlag, wrapFlag);
1404 }
1405
1406 - (unsigned)highlightAllMatchesForString:(NSString *)string caseSensitive:(BOOL)caseFlag
1407 {
1408     return m_frame->highlightAllMatchesForString(QString::fromNSString(string), caseFlag);
1409 }
1410
1411 - (void)clearHighlightedMatches
1412 {
1413     DocumentImpl *doc = m_frame->document();
1414     if (!doc) {
1415         return;
1416     }
1417     doc->removeMarkers(DocumentMarker::TextMatch);
1418 }
1419
1420 - (NSString *)advanceToNextMisspelling
1421 {
1422     return m_frame->advanceToNextMisspelling().getNSString();
1423 }
1424
1425 - (NSString *)advanceToNextMisspellingStartingJustBeforeSelection
1426 {
1427     return m_frame->advanceToNextMisspelling(true).getNSString();
1428 }
1429
1430 - (void)unmarkAllMisspellings
1431 {
1432     DocumentImpl *doc = m_frame->document();
1433     if (!doc) {
1434         return;
1435     }
1436     doc->removeMarkers(DocumentMarker::Spelling);
1437 }
1438
1439 - (void)setTextSizeMultiplier:(float)multiplier
1440 {
1441     int newZoomFactor = (int)rint(multiplier * 100);
1442     if (m_frame->zoomFactor() == newZoomFactor) {
1443         return;
1444     }
1445     m_frame->setZoomFactor(newZoomFactor);
1446 }
1447
1448 - (CFStringEncoding)textEncoding
1449 {
1450     return KWQCFStringEncodingFromIANACharsetName(m_frame->encoding().latin1());
1451 }
1452
1453 - (NSView *)nextKeyView
1454 {
1455     DocumentImpl *doc = m_frame->document();
1456     if (!doc) {
1457         return nil;
1458     }
1459     return m_frame->nextKeyView(doc->focusNode(), KWQSelectingNext);
1460 }
1461
1462 - (NSView *)previousKeyView
1463 {
1464     DocumentImpl *doc = m_frame->document();
1465     if (!doc) {
1466         return nil;
1467     }
1468     return m_frame->nextKeyView(doc->focusNode(), KWQSelectingPrevious);
1469 }
1470
1471 - (NSView *)nextKeyViewInsideWebFrameViews
1472 {
1473     DocumentImpl *doc = m_frame->document();
1474     if (!doc) {
1475         return nil;
1476     }
1477     
1478     return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingNext);
1479 }
1480
1481 - (NSView *)previousKeyViewInsideWebFrameViews
1482 {
1483     DocumentImpl *doc = m_frame->document();
1484     if (!doc) {
1485         return nil;
1486     }
1487
1488     return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingPrevious);
1489 }
1490
1491 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
1492 {
1493     return [self stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
1494 }
1495
1496 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1497 {
1498     m_frame->createEmptyDocument();
1499     JSValue* result = m_frame->executeScript(0, QString::fromNSString(string), forceUserGesture);
1500     if (!result || !result->isString())
1501         return 0;
1502     JSLock lock;
1503     return result->getString().domString();
1504 }
1505
1506 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)string
1507 {
1508     m_frame->createEmptyDocument();
1509     JSValue* result = m_frame->executeScript(0, QString::fromNSString(string), true);
1510     if (!result) // FIXME: pass errors
1511         return 0;
1512     JSLock lock;
1513     return aeDescFromJSValue(m_frame->jScript()->interpreter()->globalExec(), result);
1514 }
1515
1516 - (WebScriptObject *)windowScriptObject
1517 {
1518     return m_frame->windowScriptObject();
1519 }
1520
1521 - (NPObject *)windowScriptNPObject
1522 {
1523     return m_frame->windowScriptNPObject();
1524 }
1525
1526 - (DOMDocument *)DOMDocument
1527 {
1528     return [DOMDocument _documentWithImpl:m_frame->document()];
1529 }
1530
1531 - (DOMHTMLElement *)frameElement
1532 {
1533     return (DOMHTMLElement *)[[self DOMDocument] _ownerElement];
1534 }
1535
1536 - (NSAttributedString *)selectedAttributedString
1537 {
1538     // FIXME: should be a no-arg version of attributedString() that does this
1539     return m_frame->attributedString(m_frame->selection().start().node(), m_frame->selection().start().offset(), m_frame->selection().end().node(), m_frame->selection().end().offset());
1540 }
1541
1542 - (NSAttributedString *)attributedStringFrom:(DOMNode *)start startOffset:(int)startOffset to:(DOMNode *)end endOffset:(int)endOffset
1543 {
1544     return m_frame->attributedString([start _nodeImpl], startOffset, [end _nodeImpl], endOffset);
1545 }
1546
1547 - (NSRect)selectionRect
1548 {
1549     return m_frame->selectionRect(); 
1550 }
1551
1552 - (NSRect)visibleSelectionRect
1553 {
1554     return m_frame->visibleSelectionRect(); 
1555 }
1556
1557 - (void)centerSelectionInVisibleArea
1558 {
1559     m_frame->centerSelectionInVisibleArea(); 
1560 }
1561
1562 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1563 {
1564     return [node _nodeImpl]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1565 }
1566 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1567 {
1568     int extraWidthToEndOfLine = 0;
1569     IntRect startCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range startOffset], DOWNSTREAM, &extraWidthToEndOfLine);
1570     IntRect endCaretRect = [[range endContainer] _nodeImpl]->renderer()->caretRect([range endOffset], UPSTREAM);
1571
1572     if (startCaretRect.y() == endCaretRect.y()) {
1573         // start and end are on the same line
1574         return IntRect(MIN(startCaretRect.x(), endCaretRect.x()), 
1575                      startCaretRect.y(), 
1576                      abs(endCaretRect.x() - startCaretRect.x()),
1577                      MAX(startCaretRect.height(), endCaretRect.height()));
1578     }
1579
1580     // start and end aren't on the same line, so go from start to the end of its line
1581     return IntRect(startCaretRect.x(), 
1582                  startCaretRect.y(),
1583                  startCaretRect.width() + extraWidthToEndOfLine,
1584                  startCaretRect.height());
1585 }
1586
1587 - (NSImage *)selectionImage
1588 {
1589     return m_frame->selectionImage();
1590 }
1591
1592 - (void)setName:(NSString *)name
1593 {
1594     m_frame->tree()->setName(name);
1595 }
1596
1597 - (NSString *)name
1598 {
1599     return m_frame->tree()->name();
1600 }
1601
1602 - (void)_addFramePathToString:(NSMutableString *)path
1603 {
1604     NSString *name = [self name];
1605     if ([name hasPrefix:@"<!--framePath "]) {
1606         // we have a generated name - take the path from our name
1607         NSRange ourPathRange = {14, [name length] - 14 - 3};
1608         [path appendString:[name substringWithRange:ourPathRange]];
1609     } else {
1610         // we don't have a generated name - just add our simple name to the end
1611         [[self parent] _addFramePathToString:path];
1612         [path appendString:@"/"];
1613         if (name)
1614             [path appendString:name];
1615     }
1616 }
1617
1618 // Generate a repeatable name for a child about to be added to us.  The name must be
1619 // unique within the frame tree.  The string we generate includes a "path" of names
1620 // from the root frame down to us.  For this path to be unique, each set of siblings must
1621 // contribute a unique name to the path, which can't collide with any HTML-assigned names.
1622 // We generate this path component by index in the child list along with an unlikely frame name.
1623 - (NSString *)generateFrameName
1624 {
1625     NSMutableString *path = [NSMutableString stringWithCapacity:256];
1626     [path insertString:@"<!--framePath " atIndex:0];
1627     [self _addFramePathToString:path];
1628     // The new child's path component is all but the 1st char and the last 3 chars
1629     // FIXME: Shouldn't this number be the index of this frame in its parent rather than the child count?
1630     [path appendFormat:@"/<!--frame%d-->-->", [self childCount]];
1631     return path;
1632 }
1633
1634 - (NSURL *)URL
1635 {
1636     return m_frame->url().getNSURL();
1637 }
1638
1639 - (NSURL *)baseURL
1640 {
1641     return m_frame->completeURL(m_frame->document()->baseURL()).getNSURL();
1642 }
1643
1644 - (NSString *)referrer
1645 {
1646     return m_frame->referrer().getNSString();
1647 }
1648
1649 - (NSString *)domain
1650 {
1651     DocumentImpl *doc = m_frame->document();
1652     if (doc && doc->isHTMLDocument()) {
1653         return doc->domain().qstring().getNSString();
1654     }
1655     return nil;
1656 }
1657
1658 - (WebCoreFrameBridge *)opener
1659 {
1660     Frame *openerPart = m_frame->opener();
1661
1662     if (openerPart)
1663         return Mac(openerPart)->bridge();
1664
1665     return nil;
1666 }
1667
1668 - (void)setOpener:(WebCoreFrameBridge *)bridge;
1669 {
1670     Frame *p = [bridge impl];
1671     
1672     if (p)
1673         p->setOpener(m_frame);
1674 }
1675
1676 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
1677 {
1678     if (textEncoding == kCFStringEncodingInvalidId || textEncoding == kCFStringEncodingISOLatin1) {
1679         textEncoding = kCFStringEncodingWindowsLatin1;
1680     }
1681     return QTextCodec(textEncoding).toUnicode((const char*)[data bytes], [data length]).getNSString();
1682 }
1683
1684 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1685 {
1686     CFStringEncoding textEncoding = KWQCFStringEncodingFromIANACharsetName([textEncodingName lossyCString]);
1687     return [WebCoreFrameBridge stringWithData:data textEncoding:textEncoding];
1688 }
1689
1690 - (BOOL)needsLayout
1691 {
1692     RenderObject *renderer = m_frame->renderer();
1693     return renderer ? renderer->needsLayout() : false;
1694 }
1695
1696 - (void)setNeedsLayout
1697 {
1698     RenderObject *renderer = m_frame->renderer();
1699     if (renderer)
1700         renderer->setNeedsLayout(true);
1701 }
1702
1703 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1704 {
1705     return m_frame->keyEvent(event);
1706 }
1707
1708 - (NSString *)renderTreeAsExternalRepresentation
1709 {
1710     return externalRepresentation(m_frame->renderer()).getNSString();
1711 }
1712
1713 - (void)setSelectionFromNone
1714 {
1715     m_frame->setSelectionFromNone();
1716 }
1717
1718 - (void)setDisplaysWithFocusAttributes:(BOOL)flag
1719 {
1720     m_frame->setDisplaysWithFocusAttributes(flag);
1721 }
1722
1723 - (void)setWindowHasFocus:(BOOL)flag
1724 {
1725     m_frame->setWindowHasFocus(flag);
1726 }
1727
1728 - (void)setShouldCreateRenderers:(BOOL)f
1729 {
1730     _shouldCreateRenderers = f;
1731 }
1732
1733 - (BOOL)shouldCreateRenderers
1734 {
1735     return _shouldCreateRenderers;
1736 }
1737
1738 - (int)numPendingOrLoadingRequests
1739 {
1740     DocumentImpl *doc = m_frame->document();
1741     
1742     if (doc)
1743         return KWQNumberOfPendingOrLoadingRequests (doc->docLoader());
1744     return 0;
1745 }
1746
1747 - (BOOL)doneProcessingData
1748 {
1749     DocumentImpl *doc = m_frame->document();
1750     if (doc) {
1751         Tokenizer* tok = doc->tokenizer();
1752         if (tok)
1753             return !tok->processingData();
1754     }
1755     return YES;
1756 }
1757
1758 - (BOOL)shouldClose
1759 {
1760     return m_frame->shouldClose();
1761 }
1762
1763 - (NSColor *)bodyBackgroundColor
1764 {
1765     return m_frame->bodyBackgroundColor();
1766 }
1767
1768 - (NSColor *)selectionColor
1769 {
1770     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1771     if (root) {
1772         RenderStyle *pseudoStyle = root->getPseudoStyle(RenderStyle::SELECTION);
1773         if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) {
1774             return nsColor(pseudoStyle->backgroundColor());
1775         }
1776     }
1777     return m_frame->displaysWithFocusAttributes() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1778 }
1779
1780 - (void)adjustViewSize
1781 {
1782     FrameView *view = m_frame->view();
1783     if (view)
1784         view->adjustViewSize();
1785 }
1786
1787 -(id)accessibilityTree
1788 {
1789     KWQAccObjectCache::enableAccessibility();
1790     if (!m_frame || !m_frame->document()) return nil;
1791     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1792     if (!root) return nil;
1793     return m_frame->document()->getAccObjectCache()->accObject(root);
1794 }
1795
1796 - (void)setDrawsBackground:(BOOL)drawsBackground
1797 {
1798     if (m_frame && m_frame->view())
1799         m_frame->view()->setTransparent(!drawsBackground);
1800 }
1801
1802 - (void)undoEditing:(id)arg
1803 {
1804     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1805     [arg command]->unapply();
1806 }
1807
1808 - (void)redoEditing:(id)arg
1809 {
1810     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1811     [arg command]->reapply();
1812 }
1813
1814 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebBridgeSelectionGranularity)granularity
1815 {
1816     if (!frameHasSelection(self))
1817         return nil;
1818         
1819     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1820     SelectionController selection(m_frame->selection());
1821     selection.expandUsingGranularity(static_cast<ETextGranularity>(granularity));
1822     return [DOMRange _rangeWithImpl:selection.toRange().get()];
1823 }
1824
1825 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1826 {
1827     if (!frameHasSelection(self))
1828         return nil;
1829         
1830     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1831     SelectionController selection(m_frame->selection());
1832     selection.modify(static_cast<SelectionController::EAlter>(alteration), 
1833                      static_cast<SelectionController::EDirection>(direction), 
1834                      static_cast<ETextGranularity>(granularity));
1835     return [DOMRange _rangeWithImpl:selection.toRange().get()];
1836 }
1837
1838 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1839 {
1840     if (!frameHasSelection(self))
1841         return;
1842         
1843     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1844     SelectionController selection(m_frame->selection());
1845     selection.modify(static_cast<SelectionController::EAlter>(alteration), 
1846                      static_cast<SelectionController::EDirection>(direction), 
1847                      static_cast<ETextGranularity>(granularity));
1848
1849     // save vertical navigation x position if necessary; many types of motion blow it away
1850     int xPos = Frame::NoXPosForVerticalArrowNavigation;
1851     switch (granularity) {
1852         case WebBridgeSelectByLine:
1853         case WebBridgeSelectByParagraph:
1854             xPos = m_frame->xPosForVerticalArrowNavigation();
1855             break;
1856         case WebBridgeSelectByCharacter:
1857         case WebBridgeSelectByWord:
1858         case WebBridgeSelectToLineBoundary:
1859         case WebBridgeSelectToParagraphBoundary:
1860         case WebBridgeSelectToDocumentBoundary:
1861             break;
1862     }
1863
1864     
1865     // setting the selection always clears saved vertical navigation x position
1866     m_frame->setSelection(selection);
1867     
1868     // altering the selection also sets the granularity back to character
1869     // NOTE: The one exception is that we need to keep word granularity
1870     // to preserve smart delete behavior when extending by word.  e.g. double-click,
1871     // then shift-option-rightarrow, then delete needs to smart delete, per TextEdit.
1872     if (!((alteration == WebSelectByExtending) &&
1873           (granularity == WebBridgeSelectByWord) && (m_frame->selectionGranularity() == WORD)))
1874         m_frame->setSelectionGranularity(static_cast<ETextGranularity>(WebBridgeSelectByCharacter));
1875     
1876     // restore vertical navigation x position if necessary
1877     if (xPos != Frame::NoXPosForVerticalArrowNavigation)
1878         m_frame->setXPosForVerticalArrowNavigation(xPos);
1879
1880     m_frame->selectFrameElementInParentIfFullySelected();
1881
1882     [self ensureSelectionVisible];
1883 }
1884
1885 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1886 {
1887     if (!frameHasSelection(self))
1888         return nil;
1889         
1890     SelectionController selection(m_frame->selection());
1891     selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1892     return [DOMRange _rangeWithImpl:selection.toRange().get()];
1893 }
1894
1895 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1896 {
1897     if (!frameHasSelection(self))
1898         return;
1899         
1900     SelectionController selection(m_frame->selection());
1901     selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1902
1903     // setting the selection always clears saved vertical navigation x position, so preserve it
1904     int xPos = m_frame->xPosForVerticalArrowNavigation();
1905     m_frame->setSelection(selection);
1906     m_frame->setSelectionGranularity(static_cast<ETextGranularity>(WebBridgeSelectByCharacter));
1907     m_frame->setXPosForVerticalArrowNavigation(xPos);
1908
1909     m_frame->selectFrameElementInParentIfFullySelected();
1910
1911     [self ensureSelectionVisible];
1912 }
1913
1914 - (WebBridgeSelectionGranularity)selectionGranularity
1915 {
1916     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1917     return static_cast<WebBridgeSelectionGranularity>(m_frame->selectionGranularity());
1918 }
1919
1920 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity closeTyping:(BOOL)closeTyping
1921 {
1922     NodeImpl *startContainer = [[range startContainer] _nodeImpl];
1923     NodeImpl *endContainer = [[range endContainer] _nodeImpl];
1924     ASSERT(startContainer);
1925     ASSERT(endContainer);
1926     ASSERT(startContainer->getDocument());
1927     ASSERT(startContainer->getDocument() == endContainer->getDocument());
1928     
1929     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1930
1931     EAffinity affinity = static_cast<EAffinity>(selectionAffinity);
1932     
1933     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1934     // they start at the beginning of the next line instead
1935     if (![range collapsed])
1936         affinity = DOWNSTREAM;
1937     
1938     // FIXME: Can we provide extentAffinity?
1939     VisiblePosition visibleStart(startContainer, [range startOffset], affinity);
1940     VisiblePosition visibleEnd(endContainer, [range endOffset], SEL_DEFAULT_AFFINITY);
1941     SelectionController selection(visibleStart, visibleEnd);
1942     m_frame->setSelection(selection, closeTyping);
1943 }
1944
1945 - (DOMRange *)selectedDOMRange
1946 {
1947     return [DOMRange _rangeWithImpl:m_frame->selection().toRange().get()];
1948 }
1949
1950 - (NSRange)convertToNSRange:(RangeImpl *)range
1951 {
1952     if (!range || range->isDetached()) {
1953         return NSMakeRange(NSNotFound, 0);
1954     }
1955
1956     RefPtr<RangeImpl> fromStartRange(m_frame->document()->createRange());
1957     int exception = 0;
1958
1959     fromStartRange->setEnd(range->startContainer(exception), range->startOffset(exception), exception);
1960     int startPosition = TextIterator::rangeLength(fromStartRange.get());
1961
1962     fromStartRange->setEnd(range->endContainer(exception), range->endOffset(exception), exception);
1963     int endPosition = TextIterator::rangeLength(fromStartRange.get());
1964
1965     return NSMakeRange(startPosition, endPosition - startPosition);
1966 }
1967
1968 - (PassRefPtr<RangeImpl>)convertToDOMRange:(NSRange)nsrange
1969 {
1970     if (nsrange.location > INT_MAX)
1971         return 0;
1972     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1973         nsrange.length = INT_MAX - nsrange.location;
1974
1975     return TextIterator::rangeFromLocationAndLength(m_frame->document(), nsrange.location, nsrange.length);
1976 }
1977
1978 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1979 {
1980     return [DOMRange _rangeWithImpl:[self convertToDOMRange:nsrange].get()];
1981 }
1982
1983 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1984 {
1985     return [self convertToNSRange:[range _rangeImpl]];
1986 }
1987
1988 - (void)selectNSRange:(NSRange)range
1989 {
1990     m_frame->setSelection(SelectionController([self convertToDOMRange:range].get(), SEL_DEFAULT_AFFINITY));
1991 }
1992
1993 - (NSRange)selectedNSRange
1994 {
1995     return [self convertToNSRange:m_frame->selection().toRange().get()];
1996 }
1997
1998 - (NSSelectionAffinity)selectionAffinity
1999 {
2000     return static_cast<NSSelectionAffinity>(m_frame->selection().affinity());
2001 }
2002
2003 - (void)setMarkDOMRange:(DOMRange *)range
2004 {
2005     RangeImpl* r = [range _rangeImpl];
2006     m_frame->setMark(Selection(startPosition(r), endPosition(r), SEL_DEFAULT_AFFINITY));
2007 }
2008
2009 - (DOMRange *)markDOMRange
2010 {
2011     return [DOMRange _rangeWithImpl:m_frame->mark().toRange().get()];
2012 }
2013
2014 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges
2015 {
2016     m_frame->setMarkedTextRange([range _rangeImpl], attributes, ranges);
2017 }
2018
2019 - (DOMRange *)markedTextDOMRange
2020 {
2021     return [DOMRange _rangeWithImpl:m_frame->markedTextRange()];
2022 }
2023
2024 - (NSRange)markedTextNSRange
2025 {
2026     return [self convertToNSRange:m_frame->markedTextRange()];
2027 }
2028
2029 - (void)replaceMarkedTextWithText:(NSString *)text
2030 {
2031     if (!frameHasSelection(self))
2032         return;
2033     
2034     int exception = 0;
2035
2036     RangeImpl *markedTextRange = m_frame->markedTextRange();
2037     if (markedTextRange && !markedTextRange->collapsed(exception))
2038         TypingCommand::deleteKeyPressed(m_frame->document(), NO);
2039     
2040     if ([text length] > 0)
2041         TypingCommand::insertText(m_frame->document(), text, YES);
2042     
2043     [self ensureSelectionVisible];
2044 }
2045
2046 - (BOOL)canDeleteRange:(DOMRange *)range
2047 {
2048     NodeImpl *startContainer = [[range startContainer] _nodeImpl];
2049     NodeImpl *endContainer = [[range endContainer] _nodeImpl];
2050     if (startContainer == nil || endContainer == nil)
2051         return NO;
2052     
2053     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
2054         return NO;
2055     
2056     if ([range collapsed]) {
2057         VisiblePosition start(startContainer, [range startOffset], DOWNSTREAM);
2058         if (isStartOfEditableContent(start))
2059             return NO;
2060     }
2061     
2062     return YES;
2063 }
2064
2065 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
2066 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
2067 // the text surrounding the deletion.
2068 - (DOMRange *)smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
2069 {
2070     NodeImpl *startContainer = [[proposedRange startContainer] _nodeImpl];
2071     NodeImpl *endContainer = [[proposedRange endContainer] _nodeImpl];
2072     if (startContainer == nil || endContainer == nil)
2073         return nil;
2074
2075     ASSERT(startContainer->getDocument());
2076     ASSERT(startContainer->getDocument() == endContainer->getDocument());
2077     
2078     m_frame->document()->updateLayoutIgnorePendingStylesheets();
2079
2080     Position start(startContainer, [proposedRange startOffset]);
2081     Position end(endContainer, [proposedRange endOffset]);
2082     Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
2083     if (newStart.isNull())
2084         newStart = start;
2085     Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
2086     if (newEnd.isNull())
2087         newEnd = end;
2088
2089     RefPtr<RangeImpl> range = m_frame->document()->createRange();
2090     int exception = 0;
2091     range->setStart(newStart.node(), newStart.offset(), exception);
2092     range->setEnd(newStart.node(), newStart.offset(), exception);
2093     return [DOMRange _rangeWithImpl:range.get()];
2094 }
2095
2096 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
2097 // punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference
2098 // in beforeString and afterString any whitespace that should be added, unless either or both are
2099 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
2100 - (void)smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
2101 {
2102     // give back nil pointers in case of early returns
2103     if (beforeString)
2104         *beforeString = nil;
2105     if (afterString)
2106         *afterString = nil;
2107         
2108     // inspect destination
2109     NodeImpl *startContainer = [[rangeToReplace startContainer] _nodeImpl];
2110     NodeImpl *endContainer = [[rangeToReplace endContainer] _nodeImpl];
2111
2112     Position startPos(startContainer, [rangeToReplace startOffset]);
2113     Position endPos(endContainer, [rangeToReplace endOffset]);
2114
2115     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
2116     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
2117     
2118     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
2119     if (startVisiblePos.isNull() || endVisiblePos.isNull())
2120         return;
2121
2122     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
2123     if (addLeadingSpace) {
2124         QChar previousChar = startVisiblePos.previous().character();
2125         if (!previousChar.isNull()) {
2126             addLeadingSpace = !m_frame->isCharacterSmartReplaceExempt(previousChar, true);
2127         }
2128     }
2129     
2130     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
2131     if (addTrailingSpace) {
2132         QChar thisChar = endVisiblePos.character();
2133         if (!thisChar.isNull()) {
2134             addTrailingSpace = !m_frame->isCharacterSmartReplaceExempt(thisChar, false);
2135         }
2136     }
2137     
2138     // inspect source
2139     bool hasWhitespaceAtStart = false;
2140     bool hasWhitespaceAtEnd = false;
2141     unsigned pasteLength = [pasteString length];
2142     if (pasteLength > 0) {
2143         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
2144         
2145         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
2146             hasWhitespaceAtStart = YES;
2147         }
2148         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
2149             hasWhitespaceAtEnd = YES;
2150         }
2151     }
2152     
2153     // issue the verdict
2154     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
2155         *beforeString = @" ";
2156     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
2157         *afterString = @" ";
2158 }
2159
2160 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
2161 {
2162     if (!m_frame || !m_frame->document())
2163         return 0;
2164
2165     return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromMarkup(m_frame->document(),
2166         QString::fromNSString(markupString), QString::fromNSString(baseURLString)).get()];
2167 }
2168
2169 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
2170 {
2171     if (!frameHasSelection(self) || !text)
2172         return 0;
2173     
2174     return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromText(m_frame->document(), QString::fromNSString(text)).get()];
2175 }
2176
2177 - (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
2178 {
2179     NSEnumerator *nodeEnum = [nodes objectEnumerator];
2180     DOMNode *node;
2181     QPtrList<NodeImpl> nodeList;
2182     
2183     if (!m_frame || !m_frame->document())
2184         return 0;
2185     
2186     while ((node = [nodeEnum nextObject])) {
2187         nodeList.append([node _nodeImpl]);
2188     }
2189     
2190     return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromNodeList(m_frame->document(), nodeList).get()];
2191 }
2192
2193 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
2194 {
2195     if (!frameHasSelection(self) || !fragment)
2196         return;
2197     
2198     EditCommandPtr(new ReplaceSelectionCommand(m_frame->document(), [fragment _fragmentImpl], selectReplacement, smartReplace, matchStyle)).apply();
2199     [self ensureSelectionVisible];
2200 }
2201
2202 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2203 {
2204     DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
2205     [fragment appendChild:node];
2206     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
2207 }
2208
2209 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2210 {
2211     DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
2212     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
2213 }
2214
2215 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2216 {
2217     [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
2218 }
2219
2220 - (void)insertLineBreak
2221 {
2222     if (!frameHasSelection(self))
2223         return;
2224     
2225     TypingCommand::insertLineBreak(m_frame->document());
2226     [self ensureSelectionVisible];
2227 }
2228
2229 - (void)insertParagraphSeparator
2230 {
2231     if (!frameHasSelection(self))
2232         return;
2233     
2234     TypingCommand::insertParagraphSeparator(m_frame->document());
2235     [self ensureSelectionVisible];
2236 }
2237
2238 - (void)insertParagraphSeparatorInQuotedContent
2239 {
2240     if (!frameHasSelection(self))
2241         return;
2242     
2243     TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document());
2244     [self ensureSelectionVisible];
2245 }
2246
2247 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
2248 {
2249     if (!frameHasSelection(self))
2250         return;
2251     
2252     TypingCommand::insertText(m_frame->document(), text, selectInsertedText);
2253     [self ensureSelectionVisible];
2254 }
2255
2256 - (void)setSelectionToDragCaret
2257 {
2258     m_frame->setSelection(m_frame->dragCaret());
2259 }
2260
2261 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
2262 {
2263     Position base = m_frame->dragCaret().base();
2264     EditCommandPtr(new MoveSelectionCommand(m_frame->document(), [selectionFragment _fragmentImpl], base, smartMove)).apply();
2265 }
2266
2267 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
2268 {
2269     RenderObject *renderer = m_frame->renderer();
2270     if (!renderer) {
2271         return VisiblePosition();
2272     }
2273     
2274     RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
2275     
2276     NodeImpl *node = nodeInfo.innerNode();
2277     if (!node || !node->renderer())
2278         return VisiblePosition();
2279     
2280     return node->renderer()->positionForCoordinates((int)point.x, (int)point.y);
2281 }
2282
2283 - (void)moveDragCaretToPoint:(NSPoint)point
2284 {   
2285     SelectionController dragCaret([self _visiblePositionForPoint:point]);
2286     m_frame->setDragCaret(dragCaret);
2287 }
2288
2289 - (void)removeDragCaret
2290 {
2291     m_frame->setDragCaret(SelectionController());
2292 }
2293
2294 - (DOMRange *)dragCaretDOMRange
2295 {
2296     return [DOMRange _rangeWithImpl:m_frame->dragCaret().toRange().get()];
2297 }
2298
2299 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
2300 {
2301     VisiblePosition position = [self _visiblePositionForPoint:point];
2302     return position.isNull() ? nil : [DOMRange _rangeWithImpl:SelectionController(position).toRange().get()];
2303 }
2304
2305 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
2306 {
2307     VisiblePosition position = [self _visiblePositionForPoint:point];
2308     if (position.isNull())
2309         return nil;
2310     
2311     VisiblePosition previous = position.previous();
2312     if (previous.isNotNull()) {
2313         DOMRange *previousCharacterRange = [DOMRange _rangeWithImpl:makeRange(previous, position).get()];
2314         NSRect rect = [self firstRectForDOMRange:previousCharacterRange];
2315         if (NSPointInRect(point, rect))
2316             return previousCharacterRange;
2317     }
2318
2319     VisiblePosition next = position.next();
2320     if (next.isNotNull()) {
2321         DOMRange *nextCharacterRange = [DOMRange _rangeWithImpl:makeRange(position, next).get()];
2322         NSRect rect = [self firstRectForDOMRange:nextCharacterRange];
2323         if (NSPointInRect(point, rect))
2324             return nextCharacterRange;
2325     }
2326     
2327     return nil;
2328 }
2329
2330 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
2331 {
2332     if (!frameHasSelection(self))
2333         return;
2334     
2335     EditCommandPtr(new DeleteSelectionCommand(m_frame->document(), smartDelete)).apply();
2336 }
2337
2338 - (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2339 {
2340     if (!m_frame || !m_frame->document())
2341         return;
2342     
2343     TypingCommand::deleteKeyPressed(m_frame->document(), smartDelete);
2344     [self ensureSelectionVisible];
2345 }
2346
2347 - (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2348 {
2349     if (!m_frame || !m_frame->document())
2350         return;
2351     
2352     TypingCommand::forwardDeleteKeyPressed(m_frame->document(), smartDelete);
2353     [self ensureSelectionVisible];
2354 }
2355
2356 - (DOMCSSStyleDeclaration *)typingStyle
2357 {
2358     if (!m_frame || !m_frame->typingStyle())
2359         return nil;
2360     return [DOMCSSStyleDeclaration _styleDeclarationWithImpl:m_frame->typingStyle()->copy().get()];
2361 }
2362
2363 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2364 {
2365     if (!m_frame)
2366         return;
2367     m_frame->computeAndSetTypingStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2368 }
2369
2370 - (void)applyStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2371 {
2372     if (!m_frame)
2373         return;
2374     m_frame->applyStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2375 }
2376
2377 - (void)applyParagraphStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2378 {
2379     if (!m_frame)
2380         return;
2381     m_frame->applyParagraphStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2382 }
2383
2384 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
2385 {
2386     if (!m_frame)
2387         return NO;
2388     return m_frame->selectionStartHasStyle([style _styleDeclarationImpl]);
2389 }
2390
2391 - (NSCellStateValue)selectionHasStyle:(DOMCSSStyleDeclaration *)style
2392 {
2393     if (!m_frame)
2394         return NSOffState;
2395     switch (m_frame->selectionHasStyle([style _styleDeclarationImpl])) {
2396         case Frame::falseTriState:
2397             return NSOffState;
2398         case Frame::trueTriState:
2399             return NSOnState;
2400         case Frame::mixedTriState:
2401             return NSMixedState;
2402     }
2403     return NSOffState;
2404 }
2405
2406 - (void)applyEditingStyleToBodyElement
2407 {
2408     if (!m_frame)
2409         return;
2410     m_frame->applyEditingStyleToBodyElement();
2411 }
2412
2413 - (void)removeEditingStyleFromBodyElement
2414 {
2415     if (!m_frame)
2416         return;
2417     m_frame->removeEditingStyleFromBodyElement();
2418 }
2419
2420 - (void)applyEditingStyleToElement:(DOMElement *)element
2421 {
2422     if (!m_frame)
2423         return;
2424     m_frame->applyEditingStyleToElement([element _elementImpl]);
2425 }
2426
2427 - (void)removeEditingStyleFromElement:(DOMElement *)element
2428 {
2429     if (!m_frame)
2430         return;
2431     m_frame->removeEditingStyleFromElement([element _elementImpl]);
2432 }
2433
2434 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
2435 {
2436     bool multipleFonts = false;
2437     NSFont *font = nil;
2438     if (m_frame)
2439         font = m_frame->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
2440     if (hasMultipleFonts)
2441         *hasMultipleFonts = multipleFonts;
2442     return font;
2443 }
2444
2445 - (NSDictionary *)fontAttributesForSelectionStart
2446 {
2447     return m_frame ? m_frame->fontAttributesForSelectionStart() : nil;
2448 }
2449
2450 - (NSWritingDirection)baseWritingDirectionForSelectionStart
2451 {
2452     return m_frame ? m_frame->baseWritingDirectionForSelectionStart() : NSWritingDirectionLeftToRight;
2453 }
2454
2455 - (void)ensureSelectionVisible
2456 {
2457     if (!frameHasSelection(self))
2458         return;
2459     
2460     FrameView *v = m_frame->view();
2461     if (!v)
2462         return;
2463
2464     Position extent = m_frame->selection().extent();
2465     if (extent.isNull())
2466         return;
2467     
2468     RenderObject *renderer = extent.node()->renderer();
2469     if (!renderer)
2470         return;
2471     
2472     NSView *documentView = v->getDocumentView();
2473     if (!documentView)
2474         return;
2475     
2476     IntRect extentRect = renderer->caretRect(extent.offset(), m_frame->selection().affinity());
2477     RenderLayer *layer = renderer->enclosingLayer();
2478     if (layer)
2479         layer->scrollRectToVisible(extentRect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
2480 }
2481
2482 // [info draggingLocation] is in window coords
2483
2484 - (BOOL)eventMayStartDrag:(NSEvent *)event
2485 {
2486     return m_frame ? m_frame->eventMayStartDrag(event) : NO;
2487 }
2488
2489 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
2490 {
2491     NSDragOperation op = NSDragOperationNone;
2492     if (m_frame) {
2493         RefPtr<FrameView> v = m_frame->view();
2494         if (v) {
2495             KWQClipboard::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
2496             RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
2497             NSDragOperation srcOp = [info draggingSourceOperationMask];
2498             clipboard->setSourceOperation(srcOp);
2499
2500             if (v->updateDragAndDrop(IntPoint([info draggingLocation]), clipboard.get())) {
2501                 // *op unchanged if no source op was set
2502                 if (!clipboard->destinationOperation(&op)) {
2503                     // The element accepted but they didn't pick an operation, so we pick one for them
2504                     // (as does WinIE).
2505                     if (srcOp & NSDragOperationCopy) {
2506                         op = NSDragOperationCopy;
2507                     } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
2508                         op = NSDragOperationMove;
2509                     } else if (srcOp & NSDragOperationLink) {
2510                         op = NSDragOperationLink;
2511                     } else {
2512                         op = NSDragOperationGeneric;
2513                     }
2514                 } else if (!(op & srcOp)) {
2515                     // make sure WC picked an op that was offered.  Cocoa doesn't seem to enforce this,
2516                     // but IE does.
2517                     op = NSDragOperationNone;
2518                 }
2519             }
2520             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
2521             return op;
2522         }
2523     }
2524     return op;
2525 }
2526
2527 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
2528 {
2529     if (m_frame) {
2530         RefPtr<FrameView> v = m_frame->view();
2531         if (v) {
2532             // Sending an event can result in the destruction of the view and part.
2533             KWQClipboard::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
2534             RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
2535             clipboard->setSourceOperation([info draggingSourceOperationMask]);            
2536             v->cancelDragAndDrop(IntPoint([info draggingLocation]), clipboard.get());
2537             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
2538         }
2539     }
2540 }
2541
2542 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
2543 {
2544     if (m_frame) {
2545         RefPtr<FrameView> v = m_frame->view();
2546         if (v) {
2547             // Sending an event can result in the destruction of the view and part.
2548             RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], KWQClipboard::Readable);
2549             clipboard->setSourceOperation([info draggingSourceOperationMask]);
2550             BOOL result = v->performDragAndDrop(IntPoint([info draggingLocation]), clipboard.get());
2551             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
2552             return result;
2553         }
2554     }
2555     return NO;
2556 }
2557
2558 - (void)dragSourceMovedTo:(NSPoint)windowLoc
2559 {
2560     if (m_frame) {
2561         m_frame->dragSourceMovedTo(IntPoint(windowLoc));
2562     }
2563 }
2564
2565 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
2566 {
2567     if (m_frame) {
2568         m_frame->dragSourceEndedAt(IntPoint(windowLoc), operation);
2569     }
2570 }
2571
2572 - (BOOL)mayDHTMLCut
2573 {
2574     return m_frame->mayCut();
2575 }
2576
2577 - (BOOL)mayDHTMLCopy
2578 {
2579     return m_frame->mayCopy();
2580 }
2581
2582 - (BOOL)mayDHTMLPaste
2583 {
2584     return m_frame->mayPaste();
2585 }
2586
2587 - (BOOL)tryDHTMLCut
2588 {
2589     return m_frame->tryCut();
2590 }
2591
2592 - (BOOL)tryDHTMLCopy
2593 {
2594     return m_frame->tryCopy();
2595 }
2596
2597 - (BOOL)tryDHTMLPaste
2598 {
2599     return m_frame->tryPaste();
2600 }
2601
2602 - (DOMRange *)rangeOfCharactersAroundCaret
2603 {
2604     if (!m_frame)
2605         return nil;
2606         
2607     SelectionController selection(m_frame->selection());
2608     if (!selection.isCaret())
2609         return nil;
2610
2611     VisiblePosition caret(selection.start(), selection.affinity());
2612     VisiblePosition next = caret.next();
2613     VisiblePosition previous = caret.previous();
2614     if (previous.isNull() || next.isNull() || caret == next || caret == previous)
2615         return nil;
2616
2617     return [DOMRange _rangeWithImpl:makeRange(previous, next).get()];
2618 }
2619
2620 - (NSMutableDictionary *)dashboardRegions
2621 {
2622     return m_frame->dashboardRegionsDictionary();
2623 }
2624
2625 @end
2626
2627 @implementation WebCoreFrameBridge (WebCoreBridgeInternal)
2628
2629 - (RootObject *)executionContextForView:(NSView *)aView
2630 {
2631     MacFrame *frame = [self impl];
2632     RootObject *root = new RootObject(aView);    // The root gets deleted by JavaScriptCore.
2633     root->setRootObjectImp(Window::retrieveWindow(frame));
2634     root->setInterpreter(frame->jScript()->interpreter());
2635     frame->addPluginRootObject(root);
2636     return root;
2637 }
2638
2639 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point
2640 {
2641     RenderObject *renderer = m_frame->renderer();
2642
2643     RenderObject::NodeInfo nodeInfo(true, true);
2644     renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
2645
2646     NodeImpl *n;
2647     Widget *widget = 0;
2648     IntPoint widgetPoint(point);
2649     
2650     while (true) {
2651         n = nodeInfo.innerNode();
2652         if (!n || !n->renderer() || !n->renderer()->isWidget())
2653             break;
2654         widget = static_cast<RenderWidget *>(n->renderer())->widget();
2655         if (!widget || !widget->isFrameView())
2656             break;
2657         Frame *kpart = static_cast<HTMLFrameElementImpl *>(n)->contentPart();
2658         if (!kpart || !static_cast<MacFrame *>(kpart)->renderer())
2659             break;
2660         int absX, absY;
2661         n->renderer()->absolutePosition(absX, absY, true);
2662         FrameView *view = static_cast<FrameView *>(widget);
2663         widgetPoint.setX(widgetPoint.x() - absX + view->contentsX());
2664         widgetPoint.setY(widgetPoint.y() - absY + view->contentsY());
2665
2666         RenderObject::NodeInfo widgetNodeInfo(true, true);
2667         static_cast<MacFrame *>(kpart)->renderer()->layer()->hitTest(widgetNodeInfo, widgetPoint.x(), widgetPoint.y());
2668         nodeInfo = widgetNodeInfo;
2669     }
2670     
2671     return nodeInfo;
2672 }
2673
2674 @end
2675
2676 @implementation WebCoreFrameBridge (WebCoreInternalUse)
2677
2678 - (MacFrame*)impl
2679 {
2680     return m_frame;
2681 }
2682
2683 @end