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