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