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