2 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) 2005, 2006 Alexey Proskuryakov (ap@nypop.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #import "WebCoreFrameBridge.h"
31 #import "DOMInternal.h"
32 #import "DocumentTypeImpl.h"
35 #import "HTMLFormElementImpl.h"
36 #import "HTMLInputElementImpl.h"
37 #import "KWQAccObjectCache.h"
38 #import "KWQCharsets.h"
39 #import "KWQClipboard.h"
40 #import "KWQEditCommand.h"
42 #import "KWQFoundationExtras.h"
44 #import "KWQPageState.h"
45 #import "KWQPrinter.h"
46 #import "KWQRenderTreeDebug.h"
47 #import "KWQTextCodec.h"
52 #import "SelectionController.h"
53 #import "WebCoreFrameNamespaces.h"
54 #import "WebCorePageBridge.h"
55 #import "WebCoreSettings.h"
56 #import "WebCoreTextRendererFactory.h"
57 #import "WebCoreViewFactory.h"
59 #import "DeleteSelectionCommand.h"
60 #import "dom2_eventsimpl.h"
61 #import "dom2_range.h"
62 #import "dom2_rangeimpl.h"
63 #import "dom2_viewsimpl.h"
65 #import "dom_position.h"
66 #import "html_documentimpl.h"
67 #import "html_imageimpl.h"
68 #import "htmlediting.h"
71 #import "kjs_window.h"
74 #import "MoveSelectionCommand.h"
75 #import "render_canvas.h"
76 #import "render_frames.h"
77 #import "render_image.h"
78 #import "render_replaced.h"
79 #import "render_style.h"
80 #import "ReplaceSelectionCommand.h"
81 #import "TypingCommand.h"
82 #import "VisiblePosition.h"
83 #import "visible_text.h"
84 #import "visible_units.h"
85 #import "xml_tokenizer.h"
86 #import <JavaScriptCore/date_object.h>
87 #import <JavaScriptCore/interpreter.h>
88 #import <JavaScriptCore/jni_jsobject.h>
89 #import <JavaScriptCore/npruntime.h>
90 #import <JavaScriptCore/object.h>
91 #import <JavaScriptCore/property_map.h>
92 #import <JavaScriptCore/runtime_root.h>
93 #import <kxmlcore/Assertions.h>
97 using namespace WebCore;
98 using namespace HTMLNames;
100 using KJS::ExecState;
101 using KJS::Interpreter;
105 using KJS::SavedProperties;
106 using KJS::SavedBuiltins;
108 using KJS::BooleanType;
109 using KJS::StringType;
110 using KJS::NumberType;
111 using KJS::ObjectType;
112 using KJS::UnspecifiedType;
113 using KJS::UndefinedType;
115 using KJS::GetterSetterType;
117 using KJS::Identifier;
120 using KJS::DateInstance;
122 using KJS::Bindings::RootObject;
124 using WebCore::RenderObject;
126 NSString *WebCoreElementDOMNodeKey = @"WebElementDOMNode";
127 NSString *WebCoreElementFrameKey = @"WebElementFrame";
128 NSString *WebCoreElementImageAltStringKey = @"WebElementImageAltString";
129 NSString *WebCoreElementImageRectKey = @"WebElementImageRect";
130 NSString *WebCoreElementImageURLKey = @"WebElementImageURL";
131 NSString *WebCoreElementIsSelectedKey = @"WebElementIsSelected";
132 NSString *WebCoreElementLinkURLKey = @"WebElementLinkURL";
133 NSString *WebCoreElementLinkTargetFrameKey = @"WebElementTargetFrame";
134 NSString *WebCoreElementLinkLabelKey = @"WebElementLinkLabel";
135 NSString *WebCoreElementLinkTitleKey = @"WebElementLinkTitle";
136 NSString *WebCoreElementNameKey = @"WebElementName";
137 NSString *WebCoreElementTitleKey = @"WebCoreElementTitle"; // not in WebKit API for now, could be in API some day
139 NSString *WebCorePageCacheStateKey = @"WebCorePageCacheState";
141 @interface WebCoreFrameBridge (WebCoreBridgeInternal)
142 - (RootObject *)executionContextForView:(NSView *)aView;
143 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point;
146 static RootObject *rootForView(void *v)
148 NSView *aView = (NSView *)v;
149 WebCoreFrameBridge *aBridge = [[WebCoreViewFactory sharedFactory] bridgeForView:aView];
150 RootObject *root = 0;
153 root = [aBridge executionContextForView:aView];
158 static pthread_t mainThread = 0;
160 static void updateRenderingForBindings (ExecState *exec, JSObject *rootObject)
162 if (pthread_self() != mainThread)
168 Window *window = static_cast<Window*>(rootObject);
172 DocumentImpl *doc = static_cast<DocumentImpl*>(window->frame()->document());
174 doc->updateRendering();
177 static BOOL frameHasSelection(WebCoreFrameBridge *bridge)
182 Frame *frame = [bridge impl];
186 if (frame->selection().isNone())
189 // If a part has a selection, it should also have a document.
190 ASSERT(frame->document());
195 static BOOL hasCaseInsensitivePrefix(NSString *string, NSString *prefix)
197 return [string rangeOfString:prefix options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location !=
201 static BOOL isCaseSensitiveEqual(NSString *a, NSString *b)
203 return [a caseInsensitiveCompare:b] == NSOrderedSame;
206 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
208 NSAppleEventDescriptor* aeDesc = 0;
209 switch (jsValue->type()) {
211 aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
214 aeDesc = [NSAppleEventDescriptor descriptorWithString:jsValue->getString().domString()];
217 Float64 value = jsValue->getNumber();
218 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
222 JSObject* object = jsValue->getObject();
223 if (object->inherits(&DateInstance::info)) {
224 DateInstance* date = static_cast<DateInstance*>(object);
227 if (date->getTime(ms, tzOffset)) {
228 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
230 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
231 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
235 JSValue* primitive = object->toPrimitive(exec);
236 if (exec->hadException()) {
237 exec->clearException();
238 return [NSAppleEventDescriptor nullDescriptor];
240 return aeDescFromJSValue(exec, primitive);
245 LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
247 case UnspecifiedType:
250 case GetterSetterType:
251 aeDesc = [NSAppleEventDescriptor nullDescriptor];
258 @implementation WebCoreFrameBridge
260 static bool initializedObjectCacheSize = false;
261 static bool initializedKJS = false;
263 static inline WebCoreFrameBridge *bridge(Frame *frame)
267 return Mac(frame)->bridge();
270 - (WebCoreFrameBridge *)firstChild
272 return bridge(m_frame->tree()->firstChild());
275 - (WebCoreFrameBridge *)lastChild
277 return bridge(m_frame->tree()->lastChild());
280 - (unsigned)childCount
282 return m_frame->tree()->childCount();
285 - (WebCoreFrameBridge *)previousSibling;
287 return bridge(m_frame->tree()->previousSibling());
290 - (WebCoreFrameBridge *)nextSibling;
292 return bridge(m_frame->tree()->nextSibling());
295 - (BOOL)isDescendantOfFrame:(WebCoreFrameBridge *)ancestor
297 for (WebCoreFrameBridge *frame = self; frame; frame = [frame parent])
298 if (frame == ancestor)
304 - (WebCoreFrameBridge *)traverseNextFrameStayWithin:(WebCoreFrameBridge *)stayWithin
306 WebCoreFrameBridge *firstChild = [self firstChild];
308 ASSERT(!stayWithin || [firstChild isDescendantOfFrame:stayWithin]);
312 if (self == stayWithin)
315 WebCoreFrameBridge *nextSibling = [self nextSibling];
317 assert(!stayWithin || [nextSibling isDescendantOfFrame:stayWithin]);
321 WebCoreFrameBridge *frame = self;
322 while (frame && !nextSibling && (!stayWithin || [frame parent] != stayWithin)) {
323 frame = (WebCoreFrameBridge *)[frame parent];
324 nextSibling = [frame nextSibling];
328 ASSERT(!stayWithin || !nextSibling || [nextSibling isDescendantOfFrame:stayWithin]);
335 - (void)appendChild:(WebCoreFrameBridge *)child
337 m_frame->tree()->appendChild(adoptRef(child->m_frame));
340 - (void)removeChild:(WebCoreFrameBridge *)child
342 m_frame->tree()->removeChild(child->m_frame);
345 - (WebCoreFrameBridge *)childFrameNamed:(NSString *)name
347 // FIXME: with a better data structure this could be O(1) instead of O(n) in number
349 for (WebCoreFrameBridge *child = [self firstChild]; child; child = [child nextSibling])
350 if ([[child name] isEqualToString:name])
356 // Returns the last child of us and any children, or self
357 - (WebCoreFrameBridge *)_deepLastChildFrame
359 WebCoreFrameBridge *result = self;
360 for (WebCoreFrameBridge *lastChild = [self lastChild]; lastChild; lastChild = [lastChild lastChild])
366 // Return next frame to be traversed, visiting children after parent
367 - (WebCoreFrameBridge *)nextFrameWithWrap:(BOOL)wrapFlag
369 WebCoreFrameBridge *result = [self traverseNextFrameStayWithin:nil];
371 if (!result && wrapFlag)
372 return [self mainFrame];
377 // Return previous frame to be traversed, exact reverse order of _nextFrame
378 - (WebCoreFrameBridge *)previousFrameWithWrap:(BOOL)wrapFlag
380 // FIXME: besides the wrap feature, this is just the traversePreviousNode algorithm
382 WebCoreFrameBridge *prevSibling = [self previousSibling];
384 return [prevSibling _deepLastChildFrame];
386 return [self parent];
388 // no siblings, no parent, self==top
390 return [self _deepLastChildFrame];
392 // top view is always the last one in this ordering, so prev is nil without wrap
396 - (void)setFrameNamespace:(NSString *)ns
398 ASSERT(self == [self mainFrame]);
400 if (ns != _frameNamespace){
401 [WebCoreFrameNamespaces removeFrame:self fromNamespace:_frameNamespace];
403 [_frameNamespace release];
404 _frameNamespace = ns;
405 [WebCoreFrameNamespaces addFrame:self toNamespace:_frameNamespace];
409 - (NSString *)frameNamespace
411 ASSERT(self == [self mainFrame]);
412 return _frameNamespace;
415 - (BOOL)_shouldAllowAccessFrom:(WebCoreFrameBridge *)source
417 // if no source frame, allow access
421 // - allow access if the two frames are in the same window
422 if ([self mainFrame] == [source mainFrame])
425 // - allow if the request is made from a local file.
426 NSString *sourceDomain = [self domain];
427 if ([sourceDomain length] == 0)
430 // - allow access if this frame or one of its ancestors
431 // has the same origin as source
432 for (WebCoreFrameBridge *ancestor = self; ancestor; ancestor = [ancestor parent]) {
433 NSString *ancestorDomain = [ancestor domain];
434 if (ancestorDomain != nil &&
435 isCaseSensitiveEqual(sourceDomain, ancestorDomain))
438 ancestor = [ancestor parent];
441 // - allow access if this frame is a toplevel window and the source
442 // can access its opener. Note that we only allow one level of
444 if ([self parent] == nil) {
445 NSString *openerDomain = [[self opener] domain];
446 if (openerDomain != nil && isCaseSensitiveEqual(sourceDomain, openerDomain))
450 // otherwise deny access
454 - (WebCoreFrameBridge *)_descendantFrameNamed:(NSString *)name sourceFrame:(WebCoreFrameBridge *)source
456 for (WebCoreFrameBridge *frame = self; frame; frame = [frame traverseNextFrameStayWithin:self])
457 // for security reasons, we do not want to even make frames visible to frames that
459 if ([[frame name] isEqualToString:name] && [frame _shouldAllowAccessFrom:source])
465 - (WebCoreFrameBridge *)_frameInAnyWindowNamed:(NSString *)name sourceFrame:(WebCoreFrameBridge *)source
467 ASSERT(self == [self mainFrame]);
469 // Try this WebView first.
470 WebCoreFrameBridge *frame = [self _descendantFrameNamed:name sourceFrame:source];
475 // Try other WebViews in the same set
477 if ([self frameNamespace] != nil) {
478 NSEnumerator *enumerator = [WebCoreFrameNamespaces framesInNamespace:[self frameNamespace]];
479 WebCoreFrameBridge *searchFrame;
480 while ((searchFrame = [enumerator nextObject]))
481 frame = [searchFrame _descendantFrameNamed:name sourceFrame:source];
487 - (WebCoreFrameBridge *)findFrameNamed:(NSString *)name
489 // First, deal with 'special' names.
490 if ([name isEqualToString:@"_self"] || [name isEqualToString:@"_current"])
493 if ([name isEqualToString:@"_top"])
494 return [self mainFrame];
496 if ([name isEqualToString:@"_parent"]) {
497 WebCoreFrameBridge *parent = [self parent];
498 return parent ? parent : self;
501 if ([name isEqualToString:@"_blank"])
504 // Search from this frame down.
505 WebCoreFrameBridge *frame = [self _descendantFrameNamed:name sourceFrame:self];
507 // Search in the main frame for this window then in others.
509 frame = [[self mainFrame] _frameInAnyWindowNamed:name sourceFrame:self];
514 + (NSArray *)supportedMIMETypes
516 return [NSArray arrayWithObjects:
521 @"application/xhtml+xml",
522 @"application/rss+xml",
523 @"application/atom+xml",
524 @"application/x-webarchive",
525 @"multipart/x-mixed-replace",
532 + (WebCoreFrameBridge *)bridgeForDOMDocument:(DOMDocument *)document
534 Frame *frame = [document _documentImpl]->frame();
535 return frame ? Mac(frame)->bridge() : nil;
538 - (id)initMainFrameWithPage:(WebCorePageBridge *)page
540 if (!initializedKJS) {
541 mainThread = pthread_self();
542 RootObject::setFindRootObjectForNativeHandleFunction(rootForView);
543 KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
544 initializedKJS = true;
547 if (!(self = [super init]))
550 m_frame = new MacFrame([page impl], 0);
551 m_frame->setBridge(self);
552 _shouldCreateRenderers = YES;
554 // FIXME: This is one-time initialization, but it gets the value of the setting from the
555 // current WebView. That's a mismatch and not good!
556 if (!initializedObjectCacheSize) {
557 Cache::setSize([self getObjectCacheSize]);
558 initializedObjectCacheSize = true;
564 - (id)initSubframeWithRenderer:(RenderPart *)renderer
566 if (!(self = [super init]))
569 m_frame = new MacFrame(renderer->node()->getDocument()->frame()->page(), renderer);
570 m_frame->setBridge(self);
571 _shouldCreateRenderers = YES;
575 - (WebCorePageBridge *)page
577 return Mac(m_frame->page())->bridge();
580 - (void)initializeSettings: (WebCoreSettings *)settings
582 m_frame->setSettings ([settings settings]);
587 [self removeFromFrame];
593 // FIXME: This work really should not be done at deallocation time.
594 // We need to do it at some well-defined time instead.
596 [self removeFromFrame];
597 m_frame->setBridge(nil);
607 - (WebCoreFrameBridge *)parent
609 MacFrame *parentFrame = Mac(m_frame->tree()->parent());
612 return parentFrame->bridge();
615 - (void)provisionalLoadStarted
617 m_frame->provisionalLoadStarted();
620 - (void)openURL:(NSURL *)URL reload:(BOOL)reload contentType:(NSString *)contentType refresh:(NSString *)refresh lastModified:(NSDate *)lastModified pageCache:(NSDictionary *)pageCache
623 KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
624 m_frame->openURLFromPageCache(state);
630 URLArgs args(m_frame->browserExtension()->urlArgs());
631 args.reload = reload;
633 args.serviceType = QString::fromNSString(contentType);
635 m_frame->browserExtension()->setURLArgs(args);
638 if (m_frame->didOpenURL(URL)) {
639 // things we have to set up after calling didOpenURL
641 m_frame->addMetaData("http-refresh", QString::fromNSString(refresh));
644 NSString *modifiedString = [lastModified descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
645 m_frame->addMetaData("modified", QString::fromNSString(modifiedString));
650 - (void)setEncoding:(NSString *)encoding userChosen:(BOOL)userChosen
652 m_frame->setEncoding(QString::fromNSString(encoding), userChosen);
655 - (void)addData:(NSData *)data
657 DocumentImpl *doc = m_frame->document();
659 // Document may be nil if the part is about to redirect
660 // as a result of JS executing during load, i.e. one frame
661 // changing another's location before the frame's document
664 doc->setShouldCreateRenderers([self shouldCreateRenderers]);
665 m_frame->addData((const char *)[data bytes], [data length]);
676 m_frame->stopLoading();
679 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache
681 m_frame->didNotOpenURL(KURL(URL).url());
683 // We might have made a page cache item, but now we're bailing out due to an error before we ever
684 // transitioned to the new page (before WebFrameState==commit). The goal here is to restore any state
685 // so that the existing view (that wenever got far enough to replace) can continue being used.
686 DocumentImpl *doc = m_frame->document();
688 doc->setInPageCache(NO);
690 KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
694 - (BOOL)canLoadURL:(NSURL *)URL fromReferrer:(NSString *)referrer hideReferrer:(BOOL *)hideReferrer
696 BOOL referrerIsWebURL = hasCaseInsensitivePrefix(referrer, @"http:") || hasCaseInsensitivePrefix(referrer, @"https:");
697 BOOL referrerIsLocalURL = hasCaseInsensitivePrefix(referrer, @"file:") || hasCaseInsensitivePrefix(referrer, @"applewebdata:");
698 BOOL URLIsFileURL = [URL scheme] != NULL && [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
700 *hideReferrer = !referrerIsWebURL;
701 return !URLIsFileURL || referrerIsLocalURL;
704 - (void)saveDocumentState
706 DocumentImpl *doc = m_frame->document();
708 QStringList list = doc->docState();
709 NSMutableArray *documentState = [[[NSMutableArray alloc] init] autorelease];
711 for (uint i = 0; i < list.count(); i++){
713 [documentState addObject: [NSString stringWithCharacters: (const unichar *)s.unicode() length: s.length()]];
715 [self saveDocumentState: documentState];
719 - (void)restoreDocumentState
721 DocumentImpl *doc = m_frame->document();
724 NSArray *documentState = [self documentState];
727 for (uint i = 0; i < [documentState count]; i++){
728 NSString *string = [documentState objectAtIndex: i];
729 s.append(QString::fromNSString(string));
732 doc->setRestoreState(s);
736 - (void)scrollToAnchorWithURL:(NSURL *)URL
738 m_frame->scrollToAnchor(KURL(URL).url().latin1());
741 - (BOOL)scrollOverflowInDirection:(WebScrollDirection)direction granularity:(WebScrollGranularity)granularity
743 if (m_frame == NULL) {
746 return m_frame->scrollOverflow((KWQScrollDirection)direction, (KWQScrollGranularity)granularity);
749 - (BOOL)sendScrollWheelEvent:(NSEvent *)event
751 return m_frame ? m_frame->wheelEvent(event) : NO;
754 - (BOOL)saveDocumentToPageCache
756 DocumentImpl *doc = m_frame->document();
762 m_frame->clearTimers();
766 SavedProperties *windowProperties = new SavedProperties;
767 m_frame->saveWindowProperties(windowProperties);
769 SavedProperties *locationProperties = new SavedProperties;
770 m_frame->saveLocationProperties(locationProperties);
772 SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
773 m_frame->saveInterpreterBuiltins(*interpreterBuiltins);
775 KWQPageState *pageState = [[KWQPageState alloc] initWithDocument:doc
777 windowProperties:windowProperties
778 locationProperties:locationProperties
779 interpreterBuiltins:interpreterBuiltins
780 pausedTimeouts:m_frame->pauseTimeouts()];
782 BOOL result = [self saveDocumentToPageCache:pageState];
791 return m_frame->canCachePage();
814 - (void)handleFallbackContent
816 // this needs to be callable even after teardown of the frame
819 m_frame->handleFallbackContent();
822 - (void)createFrameViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
824 // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
825 [self removeFromFrame];
827 FrameView* kview = new FrameView(m_frame);
828 m_frame->setView(kview);
831 kview->setView(view);
833 kview->setMarginWidth(mw);
835 kview->setMarginHeight(mh);
838 - (void)scrollToAnchor:(NSString *)a
840 m_frame->gotoAnchor(QString::fromNSString(a));
843 - (BOOL)isSelectionEditable
845 // EDIT FIXME: This needs to consider the entire selected range
846 NodeImpl *startNode = m_frame->selection().start().node();
847 return startNode ? startNode->isContentEditable() : NO;
850 - (WebSelectionState)selectionState
852 switch (m_frame->selection().state()) {
853 case WebCore::Selection::NONE:
854 return WebSelectionStateNone;
855 case WebCore::Selection::CARET:
856 return WebSelectionStateCaret;
857 case WebCore::Selection::RANGE:
858 return WebSelectionStateRange;
861 ASSERT_NOT_REACHED();
862 return WebSelectionStateNone;
865 - (NSString *)_documentTypeString
867 NSString *documentTypeString = nil;
868 DocumentImpl *doc = m_frame->document();
870 DocumentTypeImpl *doctype = doc->realDocType();
872 documentTypeString = doctype->toString().qstring().getNSString();
875 return documentTypeString;
878 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
880 NSString *documentTypeString = [self _documentTypeString];
881 if (documentTypeString && markupString) {
882 return [NSString stringWithFormat:@"%@%@", documentTypeString, markupString];
883 } else if (documentTypeString) {
884 return documentTypeString;
885 } else if (markupString) {
892 - (NSArray *)nodesFromList:(QPtrList<NodeImpl> *)nodeList
894 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
895 for (QPtrListIterator<NodeImpl> i(*nodeList); i.current(); ++i) {
896 [nodes addObject:[DOMNode _nodeWithImpl:i.current()]];
901 - (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
903 // FIXME: This is never "for interchange". Is that right? See the next method.
904 QPtrList<NodeImpl> nodeList;
905 NSString *markupString = createMarkup([node _nodeImpl], IncludeNode, nodes ? &nodeList : 0).getNSString();
907 *nodes = [self nodesFromList:&nodeList];
909 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
912 - (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
914 // FIXME: This is always "for interchange". Is that right? See the previous method.
915 QPtrList<NodeImpl> nodeList;
916 NSString *markupString = createMarkup([range _rangeImpl], nodes ? &nodeList : 0, AnnotateForInterchange).getNSString();
918 *nodes = [self nodesFromList:&nodeList];
920 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
923 - (NSString *)selectedString
925 QString text = m_frame->selectedText();
926 text.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
927 return [[text.getNSString() copy] autorelease];
930 - (NSString *)stringForRange:(DOMRange *)range
932 QString text = plainText([range _rangeImpl]);
933 text.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
934 return [[text.getNSString() copy] autorelease];
939 m_frame->selectAll();
945 DocumentImpl *doc = m_frame->document();
947 doc->setFocusNode(0);
953 // FIXME: 6498 Should just be able to call m_frame->selection().clear()
954 m_frame->setSelection(SelectionController());
959 return m_frame->isFrameSet();
962 - (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
964 m_frame->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
965 DocumentImpl *doc = m_frame->document();
967 doc->setPrinting(deviceType == WebCoreDevicePrinter);
968 return m_frame->reparseConfiguration();
971 static BOOL nowPrinting(WebCoreFrameBridge *self)
973 DocumentImpl *doc = self->m_frame->document();
974 return doc && doc->printing();
977 // Set or unset the printing mode in the view. We only toy with this if we're printing.
978 - (void)_setupRootForPrinting:(BOOL)onOrOff
980 if (nowPrinting(self)) {
981 RenderCanvas *root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
983 root->setPrintingMode(onOrOff);
988 - (void)forceLayoutAdjustingViewSize:(BOOL)flag
990 [self _setupRootForPrinting:YES];
991 m_frame->forceLayout();
993 [self adjustViewSize];
995 [self _setupRootForPrinting:NO];
998 - (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
1000 [self _setupRootForPrinting:YES];
1001 m_frame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth);
1003 [self adjustViewSize];
1005 [self _setupRootForPrinting:NO];
1008 - (void)sendResizeEvent
1010 m_frame->sendResizeEvent();
1013 - (void)sendScrollEvent
1015 m_frame->sendScrollEvent();
1018 - (void)drawRect:(NSRect)rect withPainter:(QPainter *)p
1020 [self _setupRootForPrinting:YES];
1021 m_frame->paint(p, enclosingIntRect(rect));
1022 [self _setupRootForPrinting:NO];
1025 - (void)drawRect:(NSRect)rect
1027 QPainter painter(nowPrinting(self));
1028 bool displaysWithFocusAttributes = m_frame->displaysWithFocusAttributes();
1029 painter.setUsesInactiveTextBackgroundColor(!displaysWithFocusAttributes);
1030 [self drawRect:rect withPainter:&painter];
1033 // Used by pagination code called from AppKit when a standalone web page is printed.
1034 - (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
1036 [self _setupRootForPrinting:YES];
1037 NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
1038 if (printWidthScaleFactor <= 0) {
1039 LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
1043 if (printHeight <= 0) {
1044 LOG_ERROR("printHeight has bad value %.2f", printHeight);
1048 if (!m_frame || !m_frame->document() || !m_frame->view()) return pages;
1049 RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1050 if (!root) return pages;
1052 FrameView* view = m_frame->view();
1053 NSView* documentView = view->getDocumentView();
1057 float currPageHeight = printHeight;
1058 float docHeight = root->layer()->height();
1059 float docWidth = root->layer()->width();
1060 float printWidth = docWidth/printWidthScaleFactor;
1062 // We need to give the part the opportunity to adjust the page height at each step.
1063 for (float i = 0; i < docHeight; i += currPageHeight) {
1064 float proposedBottom = kMin(docHeight, i + printHeight);
1065 m_frame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
1066 currPageHeight = kMax(1.0f, proposedBottom - i);
1067 for (float j = 0; j < docWidth; j += printWidth) {
1068 NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
1069 [pages addObject: val];
1072 [self _setupRootForPrinting:NO];
1077 // This is to support the case where a webview is embedded in the view that's being printed
1078 - (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
1080 [self _setupRootForPrinting:YES];
1081 m_frame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
1082 [self _setupRootForPrinting:NO];
1085 - (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
1087 NSMutableArray *children = [[NSMutableArray alloc] init];
1088 for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
1089 [children addObject:[self copyRenderNode:child copier:copier]];
1092 NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
1094 RenderWidget *renderWidget = node->isWidget() ? static_cast<RenderWidget *>(node) : 0;
1095 Widget *widget = renderWidget ? renderWidget->widget() : 0;
1096 NSView *view = widget ? widget->getView() : nil;
1099 node->absolutePosition(nx,ny);
1100 NSObject *copiedNode = [copier nodeWithName:name
1101 position:NSMakePoint(nx,ny)
1102 rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
1112 - (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
1114 RenderObject *renderer = m_frame->renderer();
1118 return [self copyRenderNode:renderer copier:copier];
1121 - (void)removeFromFrame
1124 m_frame->setView(0);
1127 - (void)installInFrame:(NSView *)view
1129 // If this isn't the main frame, it must have a render m_frame set, or it
1130 // won't ever get installed in the view hierarchy.
1131 ASSERT(self == [self mainFrame] || m_frame->ownerRenderer());
1133 m_frame->view()->setView(view);
1134 // FIXME: frame tries to do this too, is it needed?
1135 if (m_frame->ownerRenderer()) {
1136 m_frame->ownerRenderer()->setWidget(m_frame->view());
1137 // Now the render part owns the view, so we don't any more.
1140 m_frame->view()->initScrollBars();
1143 - (void)setActivationEventNumber:(int)num
1145 m_frame->setActivationEventNumber(num);
1148 - (void)mouseDown:(NSEvent *)event
1150 m_frame->mouseDown(event);
1153 - (void)mouseDragged:(NSEvent *)event
1155 m_frame->mouseDragged(event);
1158 - (void)mouseUp:(NSEvent *)event
1160 m_frame->mouseUp(event);
1163 - (void)mouseMoved:(NSEvent *)event
1165 m_frame->mouseMoved(event);
1168 - (BOOL)sendContextMenuEvent:(NSEvent *)event
1170 return m_frame->sendContextMenuEvent(event);
1173 - (DOMElement *)elementForView:(NSView *)view
1175 // FIXME: implemented currently for only a subset of the KWQ widgets
1176 if ([view conformsToProtocol:@protocol(KWQWidgetHolder)]) {
1177 NSView <KWQWidgetHolder> *widgetHolder = view;
1178 Widget *widget = [widgetHolder widget];
1179 if (widget != nil && widget->eventFilterObject() != nil) {
1180 NodeImpl *node = static_cast<const RenderWidget *>(widget->eventFilterObject())->element();
1181 return [DOMElement _elementWithImpl:static_cast<ElementImpl *>(node)];
1187 static HTMLInputElementImpl *inputElementFromDOMElement(DOMElement *element)
1189 NodeImpl *node = [element _nodeImpl];
1190 if (node->hasTagName(inputTag)) {
1191 return static_cast<HTMLInputElementImpl *>(node);
1196 static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
1198 NodeImpl *node = [element _nodeImpl];
1199 // This should not be necessary, but an XSL file on
1200 // maps.google.com crashes otherwise because it is an xslt file
1201 // that contains <form> elements that aren't in any namespace, so
1202 // they come out as generic CML elements
1203 if (node && node->hasTagName(formTag)) {
1204 return static_cast<HTMLFormElementImpl *>(node);
1209 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
1211 HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
1213 Vector<HTMLGenericFormElementImpl*>& elements = formElement->formElements;
1214 AtomicString targetName = name;
1215 for (unsigned int i = 0; i < elements.size(); i++) {
1216 HTMLGenericFormElementImpl *elt = elements[i];
1217 // Skip option elements, other duds
1218 if (elt->name() == targetName)
1219 return [DOMElement _elementWithImpl:elt];
1225 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
1227 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1228 return inputElement != nil
1229 && inputElement->inputType() == HTMLInputElementImpl::TEXT
1230 && inputElement->autoComplete();
1233 - (BOOL)elementIsPassword:(DOMElement *)element
1235 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1236 return inputElement != nil
1237 && inputElement->inputType() == HTMLInputElementImpl::PASSWORD;
1240 - (DOMElement *)formForElement:(DOMElement *)element;
1242 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
1244 HTMLFormElementImpl *formElement = inputElement->form();
1246 return [DOMElement _elementWithImpl:formElement];
1252 - (DOMElement *)currentForm
1254 HTMLFormElementImpl *formElement = m_frame->currentForm();
1255 return formElement ? [DOMElement _elementWithImpl:formElement] : nil;
1258 - (NSArray *)controlsInForm:(DOMElement *)form
1260 NSMutableArray *results = nil;
1261 HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
1263 Vector<HTMLGenericFormElementImpl*>& elements = formElement->formElements;
1264 for (unsigned int i = 0; i < elements.size(); i++) {
1265 if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1266 DOMElement *de = [DOMElement _elementWithImpl:elements.at(i)];
1268 results = [NSMutableArray arrayWithObject:de];
1270 [results addObject:de];
1278 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
1280 return m_frame->searchForLabelsBeforeElement(labels, [element _elementImpl]);
1283 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
1285 return m_frame->matchLabelsAgainstElement(labels, [element _elementImpl]);
1288 - (NSDictionary *)elementAtPoint:(NSPoint)point
1290 RenderObject *renderer = m_frame->renderer();
1294 RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
1296 NSMutableDictionary *element = [NSMutableDictionary dictionary];
1297 [element setObject:[NSNumber numberWithBool:m_frame->isPointInsideSelection((int)point.x, (int)point.y)]
1298 forKey:WebCoreElementIsSelectedKey];
1300 // Find the title in the nearest enclosing DOM node.
1301 // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
1302 for (NodeImpl *titleNode = nodeInfo.innerNode(); titleNode; titleNode = titleNode->parentNode()) {
1303 if (titleNode->isElementNode()) {
1304 const AtomicString& title = static_cast<ElementImpl *>(titleNode)->getAttribute(titleAttr);
1305 if (!title.isNull()) {
1306 // We found a node with a title.
1307 QString titleText = title.qstring();
1308 titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1309 [element setObject:titleText.getNSString() forKey:WebCoreElementTitleKey];
1315 NodeImpl *URLNode = nodeInfo.URLElement();
1317 ElementImpl *e = static_cast<ElementImpl *>(URLNode);
1318 DocumentImpl *doc = e->getDocument();
1321 const AtomicString& title = e->getAttribute(titleAttr);
1322 if (!title.isEmpty()) {
1323 QString titleText = title.qstring();
1324 titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1325 [element setObject:titleText.getNSString() forKey:WebCoreElementLinkTitleKey];
1328 const AtomicString& link = e->getAttribute(hrefAttr);
1329 if (!link.isNull()) {
1330 QString t = plainText(rangeOfContents(e).get());
1332 [element setObject:t.getNSString() forKey:WebCoreElementLinkLabelKey];
1334 QString URLString = parseURL(link).qstring();
1335 [element setObject:doc->completeURL(URLString).getNSString() forKey:WebCoreElementLinkURLKey];
1338 DOMString target = e->getAttribute(targetAttr);
1339 if (target.isEmpty() && doc) { // FIXME: Take out this doc check when we're not just before a release.
1340 target = doc->baseTarget();
1342 if (!target.isEmpty()) {
1343 [element setObject:target.qstring().getNSString() forKey:WebCoreElementLinkTargetFrameKey];
1347 NodeImpl *node = nodeInfo.innerNonSharedNode();
1349 [element setObject:[DOMNode _nodeWithImpl:node] forKey:WebCoreElementDOMNodeKey];
1351 // Only return image information if there is an image.
1352 if (node->renderer() && node->renderer()->isImage()) {
1353 RenderImage *r = static_cast<RenderImage *>(node->renderer());
1355 if (r->absolutePosition(x, y)) {
1356 NSValue *rect = [NSValue valueWithRect:NSMakeRect(x, y, r->contentWidth(), r->contentHeight())];
1357 [element setObject:rect forKey:WebCoreElementImageRectKey];
1360 ElementImpl *i = static_cast<ElementImpl*>(node);
1362 // FIXME: Code copied from RenderImage::updateFromElement; should share.
1364 if (i->hasTagName(objectTag)) {
1365 attr = i->getAttribute(dataAttr);
1367 attr = i->getAttribute(srcAttr);
1369 if (!attr.isEmpty()) {
1370 QString URLString = parseURL(attr).qstring();
1371 [element setObject:i->getDocument()->completeURL(URLString).getNSString() forKey:WebCoreElementImageURLKey];
1374 // FIXME: Code copied from RenderImage::updateFromElement; should share.
1376 if (i->hasTagName(inputTag))
1377 alt = static_cast<HTMLInputElementImpl *>(i)->altText();
1378 else if (i->hasTagName(imgTag))
1379 alt = static_cast<HTMLImageElementImpl *>(i)->altText();
1380 if (!alt.isNull()) {
1381 QString altText = alt.qstring();
1382 altText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
1383 [element setObject:altText.getNSString() forKey:WebCoreElementImageAltStringKey];
1391 - (NSURL *)URLWithAttributeString:(NSString *)string
1393 DocumentImpl *doc = m_frame->document();
1397 QString rel = parseURL(QString::fromNSString(string)).qstring();
1398 return KURL(doc->baseURL(), rel, doc->decoder() ? doc->decoder()->codec() : 0).getNSURL();
1401 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1403 return m_frame->findString(string, forward, caseFlag, wrapFlag);
1406 - (unsigned)highlightAllMatchesForString:(NSString *)string caseSensitive:(BOOL)caseFlag
1408 return m_frame->highlightAllMatchesForString(QString::fromNSString(string), caseFlag);
1411 - (void)clearHighlightedMatches
1413 DocumentImpl *doc = m_frame->document();
1417 doc->removeMarkers(DocumentMarker::TextMatch);
1420 - (NSString *)advanceToNextMisspelling
1422 return m_frame->advanceToNextMisspelling().getNSString();
1425 - (NSString *)advanceToNextMisspellingStartingJustBeforeSelection
1427 return m_frame->advanceToNextMisspelling(true).getNSString();
1430 - (void)unmarkAllMisspellings
1432 DocumentImpl *doc = m_frame->document();
1436 doc->removeMarkers(DocumentMarker::Spelling);
1439 - (void)setTextSizeMultiplier:(float)multiplier
1441 int newZoomFactor = (int)rint(multiplier * 100);
1442 if (m_frame->zoomFactor() == newZoomFactor) {
1445 m_frame->setZoomFactor(newZoomFactor);
1448 - (CFStringEncoding)textEncoding
1450 return KWQCFStringEncodingFromIANACharsetName(m_frame->encoding().latin1());
1453 - (NSView *)nextKeyView
1455 DocumentImpl *doc = m_frame->document();
1459 return m_frame->nextKeyView(doc->focusNode(), KWQSelectingNext);
1462 - (NSView *)previousKeyView
1464 DocumentImpl *doc = m_frame->document();
1468 return m_frame->nextKeyView(doc->focusNode(), KWQSelectingPrevious);
1471 - (NSView *)nextKeyViewInsideWebFrameViews
1473 DocumentImpl *doc = m_frame->document();
1478 return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingNext);
1481 - (NSView *)previousKeyViewInsideWebFrameViews
1483 DocumentImpl *doc = m_frame->document();
1488 return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingPrevious);
1491 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
1493 return [self stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
1496 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1498 m_frame->createEmptyDocument();
1499 JSValue* result = m_frame->executeScript(0, QString::fromNSString(string), forceUserGesture);
1500 if (!result || !result->isString())
1503 return result->getString().domString();
1506 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)string
1508 m_frame->createEmptyDocument();
1509 JSValue* result = m_frame->executeScript(0, QString::fromNSString(string), true);
1510 if (!result) // FIXME: pass errors
1513 return aeDescFromJSValue(m_frame->jScript()->interpreter()->globalExec(), result);
1516 - (WebScriptObject *)windowScriptObject
1518 return m_frame->windowScriptObject();
1521 - (NPObject *)windowScriptNPObject
1523 return m_frame->windowScriptNPObject();
1526 - (DOMDocument *)DOMDocument
1528 return [DOMDocument _documentWithImpl:m_frame->document()];
1531 - (DOMHTMLElement *)frameElement
1533 return (DOMHTMLElement *)[[self DOMDocument] _ownerElement];
1536 - (NSAttributedString *)selectedAttributedString
1538 // FIXME: should be a no-arg version of attributedString() that does this
1539 return m_frame->attributedString(m_frame->selection().start().node(), m_frame->selection().start().offset(), m_frame->selection().end().node(), m_frame->selection().end().offset());
1542 - (NSAttributedString *)attributedStringFrom:(DOMNode *)start startOffset:(int)startOffset to:(DOMNode *)end endOffset:(int)endOffset
1544 return m_frame->attributedString([start _nodeImpl], startOffset, [end _nodeImpl], endOffset);
1547 - (NSRect)selectionRect
1549 return m_frame->selectionRect();
1552 - (NSRect)visibleSelectionRect
1554 return m_frame->visibleSelectionRect();
1557 - (void)centerSelectionInVisibleArea
1559 m_frame->centerSelectionInVisibleArea();
1562 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1564 return [node _nodeImpl]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1566 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1568 int extraWidthToEndOfLine = 0;
1569 IntRect startCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range startOffset], DOWNSTREAM, &extraWidthToEndOfLine);
1570 IntRect endCaretRect = [[range endContainer] _nodeImpl]->renderer()->caretRect([range endOffset], UPSTREAM);
1572 if (startCaretRect.y() == endCaretRect.y()) {
1573 // start and end are on the same line
1574 return IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
1576 abs(endCaretRect.x() - startCaretRect.x()),
1577 MAX(startCaretRect.height(), endCaretRect.height()));
1580 // start and end aren't on the same line, so go from start to the end of its line
1581 return IntRect(startCaretRect.x(),
1583 startCaretRect.width() + extraWidthToEndOfLine,
1584 startCaretRect.height());
1587 - (NSImage *)selectionImage
1589 return m_frame->selectionImage();
1592 - (void)setName:(NSString *)name
1594 m_frame->tree()->setName(name);
1599 return m_frame->tree()->name();
1602 - (void)_addFramePathToString:(NSMutableString *)path
1604 NSString *name = [self name];
1605 if ([name hasPrefix:@"<!--framePath "]) {
1606 // we have a generated name - take the path from our name
1607 NSRange ourPathRange = {14, [name length] - 14 - 3};
1608 [path appendString:[name substringWithRange:ourPathRange]];
1610 // we don't have a generated name - just add our simple name to the end
1611 [[self parent] _addFramePathToString:path];
1612 [path appendString:@"/"];
1614 [path appendString:name];
1618 // Generate a repeatable name for a child about to be added to us. The name must be
1619 // unique within the frame tree. The string we generate includes a "path" of names
1620 // from the root frame down to us. For this path to be unique, each set of siblings must
1621 // contribute a unique name to the path, which can't collide with any HTML-assigned names.
1622 // We generate this path component by index in the child list along with an unlikely frame name.
1623 - (NSString *)generateFrameName
1625 NSMutableString *path = [NSMutableString stringWithCapacity:256];
1626 [path insertString:@"<!--framePath " atIndex:0];
1627 [self _addFramePathToString:path];
1628 // The new child's path component is all but the 1st char and the last 3 chars
1629 // FIXME: Shouldn't this number be the index of this frame in its parent rather than the child count?
1630 [path appendFormat:@"/<!--frame%d-->-->", [self childCount]];
1636 return m_frame->url().getNSURL();
1641 return m_frame->completeURL(m_frame->document()->baseURL()).getNSURL();
1644 - (NSString *)referrer
1646 return m_frame->referrer().getNSString();
1649 - (NSString *)domain
1651 DocumentImpl *doc = m_frame->document();
1652 if (doc && doc->isHTMLDocument()) {
1653 return doc->domain().qstring().getNSString();
1658 - (WebCoreFrameBridge *)opener
1660 Frame *openerPart = m_frame->opener();
1663 return Mac(openerPart)->bridge();
1668 - (void)setOpener:(WebCoreFrameBridge *)bridge;
1670 Frame *p = [bridge impl];
1673 p->setOpener(m_frame);
1676 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
1678 if (textEncoding == kCFStringEncodingInvalidId || textEncoding == kCFStringEncodingISOLatin1) {
1679 textEncoding = kCFStringEncodingWindowsLatin1;
1681 return QTextCodec(textEncoding).toUnicode((const char*)[data bytes], [data length]).getNSString();
1684 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1686 CFStringEncoding textEncoding = KWQCFStringEncodingFromIANACharsetName([textEncodingName lossyCString]);
1687 return [WebCoreFrameBridge stringWithData:data textEncoding:textEncoding];
1692 RenderObject *renderer = m_frame->renderer();
1693 return renderer ? renderer->needsLayout() : false;
1696 - (void)setNeedsLayout
1698 RenderObject *renderer = m_frame->renderer();
1700 renderer->setNeedsLayout(true);
1703 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1705 return m_frame->keyEvent(event);
1708 - (NSString *)renderTreeAsExternalRepresentation
1710 return externalRepresentation(m_frame->renderer()).getNSString();
1713 - (void)setSelectionFromNone
1715 m_frame->setSelectionFromNone();
1718 - (void)setDisplaysWithFocusAttributes:(BOOL)flag
1720 m_frame->setDisplaysWithFocusAttributes(flag);
1723 - (void)setWindowHasFocus:(BOOL)flag
1725 m_frame->setWindowHasFocus(flag);
1728 - (void)setShouldCreateRenderers:(BOOL)f
1730 _shouldCreateRenderers = f;
1733 - (BOOL)shouldCreateRenderers
1735 return _shouldCreateRenderers;
1738 - (int)numPendingOrLoadingRequests
1740 DocumentImpl *doc = m_frame->document();
1743 return KWQNumberOfPendingOrLoadingRequests (doc->docLoader());
1747 - (BOOL)doneProcessingData
1749 DocumentImpl *doc = m_frame->document();
1751 Tokenizer* tok = doc->tokenizer();
1753 return !tok->processingData();
1760 return m_frame->shouldClose();
1763 - (NSColor *)bodyBackgroundColor
1765 return m_frame->bodyBackgroundColor();
1768 - (NSColor *)selectionColor
1770 RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1772 RenderStyle *pseudoStyle = root->getPseudoStyle(RenderStyle::SELECTION);
1773 if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) {
1774 return nsColor(pseudoStyle->backgroundColor());
1777 return m_frame->displaysWithFocusAttributes() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1780 - (void)adjustViewSize
1782 FrameView *view = m_frame->view();
1784 view->adjustViewSize();
1787 -(id)accessibilityTree
1789 KWQAccObjectCache::enableAccessibility();
1790 if (!m_frame || !m_frame->document()) return nil;
1791 RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1792 if (!root) return nil;
1793 return m_frame->document()->getAccObjectCache()->accObject(root);
1796 - (void)setDrawsBackground:(BOOL)drawsBackground
1798 if (m_frame && m_frame->view())
1799 m_frame->view()->setTransparent(!drawsBackground);
1802 - (void)undoEditing:(id)arg
1804 ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1805 [arg command]->unapply();
1808 - (void)redoEditing:(id)arg
1810 ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1811 [arg command]->reapply();
1814 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebBridgeSelectionGranularity)granularity
1816 if (!frameHasSelection(self))
1819 // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1820 SelectionController selection(m_frame->selection());
1821 selection.expandUsingGranularity(static_cast<ETextGranularity>(granularity));
1822 return [DOMRange _rangeWithImpl:selection.toRange().get()];
1825 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1827 if (!frameHasSelection(self))
1830 // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1831 SelectionController selection(m_frame->selection());
1832 selection.modify(static_cast<SelectionController::EAlter>(alteration),
1833 static_cast<SelectionController::EDirection>(direction),
1834 static_cast<ETextGranularity>(granularity));
1835 return [DOMRange _rangeWithImpl:selection.toRange().get()];
1838 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1840 if (!frameHasSelection(self))
1843 // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1844 SelectionController selection(m_frame->selection());
1845 selection.modify(static_cast<SelectionController::EAlter>(alteration),
1846 static_cast<SelectionController::EDirection>(direction),
1847 static_cast<ETextGranularity>(granularity));
1849 // save vertical navigation x position if necessary; many types of motion blow it away
1850 int xPos = Frame::NoXPosForVerticalArrowNavigation;
1851 switch (granularity) {
1852 case WebBridgeSelectByLine:
1853 case WebBridgeSelectByParagraph:
1854 xPos = m_frame->xPosForVerticalArrowNavigation();
1856 case WebBridgeSelectByCharacter:
1857 case WebBridgeSelectByWord:
1858 case WebBridgeSelectToLineBoundary:
1859 case WebBridgeSelectToParagraphBoundary:
1860 case WebBridgeSelectToDocumentBoundary:
1865 // setting the selection always clears saved vertical navigation x position
1866 m_frame->setSelection(selection);
1868 // altering the selection also sets the granularity back to character
1869 // NOTE: The one exception is that we need to keep word granularity
1870 // to preserve smart delete behavior when extending by word. e.g. double-click,
1871 // then shift-option-rightarrow, then delete needs to smart delete, per TextEdit.
1872 if (!((alteration == WebSelectByExtending) &&
1873 (granularity == WebBridgeSelectByWord) && (m_frame->selectionGranularity() == WORD)))
1874 m_frame->setSelectionGranularity(static_cast<ETextGranularity>(WebBridgeSelectByCharacter));
1876 // restore vertical navigation x position if necessary
1877 if (xPos != Frame::NoXPosForVerticalArrowNavigation)
1878 m_frame->setXPosForVerticalArrowNavigation(xPos);
1880 m_frame->selectFrameElementInParentIfFullySelected();
1882 [self ensureSelectionVisible];
1885 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1887 if (!frameHasSelection(self))
1890 SelectionController selection(m_frame->selection());
1891 selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1892 return [DOMRange _rangeWithImpl:selection.toRange().get()];
1895 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1897 if (!frameHasSelection(self))
1900 SelectionController selection(m_frame->selection());
1901 selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1903 // setting the selection always clears saved vertical navigation x position, so preserve it
1904 int xPos = m_frame->xPosForVerticalArrowNavigation();
1905 m_frame->setSelection(selection);
1906 m_frame->setSelectionGranularity(static_cast<ETextGranularity>(WebBridgeSelectByCharacter));
1907 m_frame->setXPosForVerticalArrowNavigation(xPos);
1909 m_frame->selectFrameElementInParentIfFullySelected();
1911 [self ensureSelectionVisible];
1914 - (WebBridgeSelectionGranularity)selectionGranularity
1916 // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1917 return static_cast<WebBridgeSelectionGranularity>(m_frame->selectionGranularity());
1920 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity closeTyping:(BOOL)closeTyping
1922 NodeImpl *startContainer = [[range startContainer] _nodeImpl];
1923 NodeImpl *endContainer = [[range endContainer] _nodeImpl];
1924 ASSERT(startContainer);
1925 ASSERT(endContainer);
1926 ASSERT(startContainer->getDocument());
1927 ASSERT(startContainer->getDocument() == endContainer->getDocument());
1929 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1931 EAffinity affinity = static_cast<EAffinity>(selectionAffinity);
1933 // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1934 // they start at the beginning of the next line instead
1935 if (![range collapsed])
1936 affinity = DOWNSTREAM;
1938 // FIXME: Can we provide extentAffinity?
1939 VisiblePosition visibleStart(startContainer, [range startOffset], affinity);
1940 VisiblePosition visibleEnd(endContainer, [range endOffset], SEL_DEFAULT_AFFINITY);
1941 SelectionController selection(visibleStart, visibleEnd);
1942 m_frame->setSelection(selection, closeTyping);
1945 - (DOMRange *)selectedDOMRange
1947 return [DOMRange _rangeWithImpl:m_frame->selection().toRange().get()];
1950 - (NSRange)convertToNSRange:(RangeImpl *)range
1952 if (!range || range->isDetached()) {
1953 return NSMakeRange(NSNotFound, 0);
1956 RefPtr<RangeImpl> fromStartRange(m_frame->document()->createRange());
1959 fromStartRange->setEnd(range->startContainer(exception), range->startOffset(exception), exception);
1960 int startPosition = TextIterator::rangeLength(fromStartRange.get());
1962 fromStartRange->setEnd(range->endContainer(exception), range->endOffset(exception), exception);
1963 int endPosition = TextIterator::rangeLength(fromStartRange.get());
1965 return NSMakeRange(startPosition, endPosition - startPosition);
1968 - (PassRefPtr<RangeImpl>)convertToDOMRange:(NSRange)nsrange
1970 if (nsrange.location > INT_MAX)
1972 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1973 nsrange.length = INT_MAX - nsrange.location;
1975 return TextIterator::rangeFromLocationAndLength(m_frame->document(), nsrange.location, nsrange.length);
1978 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1980 return [DOMRange _rangeWithImpl:[self convertToDOMRange:nsrange].get()];
1983 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1985 return [self convertToNSRange:[range _rangeImpl]];
1988 - (void)selectNSRange:(NSRange)range
1990 m_frame->setSelection(SelectionController([self convertToDOMRange:range].get(), SEL_DEFAULT_AFFINITY));
1993 - (NSRange)selectedNSRange
1995 return [self convertToNSRange:m_frame->selection().toRange().get()];
1998 - (NSSelectionAffinity)selectionAffinity
2000 return static_cast<NSSelectionAffinity>(m_frame->selection().affinity());
2003 - (void)setMarkDOMRange:(DOMRange *)range
2005 RangeImpl* r = [range _rangeImpl];
2006 m_frame->setMark(Selection(startPosition(r), endPosition(r), SEL_DEFAULT_AFFINITY));
2009 - (DOMRange *)markDOMRange
2011 return [DOMRange _rangeWithImpl:m_frame->mark().toRange().get()];
2014 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges
2016 m_frame->setMarkedTextRange([range _rangeImpl], attributes, ranges);
2019 - (DOMRange *)markedTextDOMRange
2021 return [DOMRange _rangeWithImpl:m_frame->markedTextRange()];
2024 - (NSRange)markedTextNSRange
2026 return [self convertToNSRange:m_frame->markedTextRange()];
2029 - (void)replaceMarkedTextWithText:(NSString *)text
2031 if (!frameHasSelection(self))
2036 RangeImpl *markedTextRange = m_frame->markedTextRange();
2037 if (markedTextRange && !markedTextRange->collapsed(exception))
2038 TypingCommand::deleteKeyPressed(m_frame->document(), NO);
2040 if ([text length] > 0)
2041 TypingCommand::insertText(m_frame->document(), text, YES);
2043 [self ensureSelectionVisible];
2046 - (BOOL)canDeleteRange:(DOMRange *)range
2048 NodeImpl *startContainer = [[range startContainer] _nodeImpl];
2049 NodeImpl *endContainer = [[range endContainer] _nodeImpl];
2050 if (startContainer == nil || endContainer == nil)
2053 if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
2056 if ([range collapsed]) {
2057 VisiblePosition start(startContainer, [range startOffset], DOWNSTREAM);
2058 if (isStartOfEditableContent(start))
2065 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
2066 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
2067 // the text surrounding the deletion.
2068 - (DOMRange *)smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
2070 NodeImpl *startContainer = [[proposedRange startContainer] _nodeImpl];
2071 NodeImpl *endContainer = [[proposedRange endContainer] _nodeImpl];
2072 if (startContainer == nil || endContainer == nil)
2075 ASSERT(startContainer->getDocument());
2076 ASSERT(startContainer->getDocument() == endContainer->getDocument());
2078 m_frame->document()->updateLayoutIgnorePendingStylesheets();
2080 Position start(startContainer, [proposedRange startOffset]);
2081 Position end(endContainer, [proposedRange endOffset]);
2082 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
2083 if (newStart.isNull())
2085 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
2086 if (newEnd.isNull())
2089 RefPtr<RangeImpl> range = m_frame->document()->createRange();
2091 range->setStart(newStart.node(), newStart.offset(), exception);
2092 range->setEnd(newStart.node(), newStart.offset(), exception);
2093 return [DOMRange _rangeWithImpl:range.get()];
2096 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
2097 // punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference
2098 // in beforeString and afterString any whitespace that should be added, unless either or both are
2099 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
2100 - (void)smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
2102 // give back nil pointers in case of early returns
2104 *beforeString = nil;
2108 // inspect destination
2109 NodeImpl *startContainer = [[rangeToReplace startContainer] _nodeImpl];
2110 NodeImpl *endContainer = [[rangeToReplace endContainer] _nodeImpl];
2112 Position startPos(startContainer, [rangeToReplace startOffset]);
2113 Position endPos(endContainer, [rangeToReplace endOffset]);
2115 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
2116 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
2118 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
2119 if (startVisiblePos.isNull() || endVisiblePos.isNull())
2122 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
2123 if (addLeadingSpace) {
2124 QChar previousChar = startVisiblePos.previous().character();
2125 if (!previousChar.isNull()) {
2126 addLeadingSpace = !m_frame->isCharacterSmartReplaceExempt(previousChar, true);
2130 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
2131 if (addTrailingSpace) {
2132 QChar thisChar = endVisiblePos.character();
2133 if (!thisChar.isNull()) {
2134 addTrailingSpace = !m_frame->isCharacterSmartReplaceExempt(thisChar, false);
2139 bool hasWhitespaceAtStart = false;
2140 bool hasWhitespaceAtEnd = false;
2141 unsigned pasteLength = [pasteString length];
2142 if (pasteLength > 0) {
2143 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
2145 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
2146 hasWhitespaceAtStart = YES;
2148 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
2149 hasWhitespaceAtEnd = YES;
2153 // issue the verdict
2154 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
2155 *beforeString = @" ";
2156 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
2157 *afterString = @" ";
2160 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
2162 if (!m_frame || !m_frame->document())
2165 return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromMarkup(m_frame->document(),
2166 QString::fromNSString(markupString), QString::fromNSString(baseURLString)).get()];
2169 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
2171 if (!frameHasSelection(self) || !text)
2174 return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromText(m_frame->document(), QString::fromNSString(text)).get()];
2177 - (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
2179 NSEnumerator *nodeEnum = [nodes objectEnumerator];
2181 QPtrList<NodeImpl> nodeList;
2183 if (!m_frame || !m_frame->document())
2186 while ((node = [nodeEnum nextObject])) {
2187 nodeList.append([node _nodeImpl]);
2190 return [DOMDocumentFragment _documentFragmentWithImpl:createFragmentFromNodeList(m_frame->document(), nodeList).get()];
2193 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
2195 if (!frameHasSelection(self) || !fragment)
2198 EditCommandPtr(new ReplaceSelectionCommand(m_frame->document(), [fragment _fragmentImpl], selectReplacement, smartReplace, matchStyle)).apply();
2199 [self ensureSelectionVisible];
2202 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2204 DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
2205 [fragment appendChild:node];
2206 [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
2209 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2211 DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
2212 [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
2215 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
2217 [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
2220 - (void)insertLineBreak
2222 if (!frameHasSelection(self))
2225 TypingCommand::insertLineBreak(m_frame->document());
2226 [self ensureSelectionVisible];
2229 - (void)insertParagraphSeparator
2231 if (!frameHasSelection(self))
2234 TypingCommand::insertParagraphSeparator(m_frame->document());
2235 [self ensureSelectionVisible];
2238 - (void)insertParagraphSeparatorInQuotedContent
2240 if (!frameHasSelection(self))
2243 TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document());
2244 [self ensureSelectionVisible];
2247 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
2249 if (!frameHasSelection(self))
2252 TypingCommand::insertText(m_frame->document(), text, selectInsertedText);
2253 [self ensureSelectionVisible];
2256 - (void)setSelectionToDragCaret
2258 m_frame->setSelection(m_frame->dragCaret());
2261 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
2263 Position base = m_frame->dragCaret().base();
2264 EditCommandPtr(new MoveSelectionCommand(m_frame->document(), [selectionFragment _fragmentImpl], base, smartMove)).apply();
2267 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
2269 RenderObject *renderer = m_frame->renderer();
2271 return VisiblePosition();
2274 RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
2276 NodeImpl *node = nodeInfo.innerNode();
2277 if (!node || !node->renderer())
2278 return VisiblePosition();
2280 return node->renderer()->positionForCoordinates((int)point.x, (int)point.y);
2283 - (void)moveDragCaretToPoint:(NSPoint)point
2285 SelectionController dragCaret([self _visiblePositionForPoint:point]);
2286 m_frame->setDragCaret(dragCaret);
2289 - (void)removeDragCaret
2291 m_frame->setDragCaret(SelectionController());
2294 - (DOMRange *)dragCaretDOMRange
2296 return [DOMRange _rangeWithImpl:m_frame->dragCaret().toRange().get()];
2299 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
2301 VisiblePosition position = [self _visiblePositionForPoint:point];
2302 return position.isNull() ? nil : [DOMRange _rangeWithImpl:SelectionController(position).toRange().get()];
2305 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
2307 VisiblePosition position = [self _visiblePositionForPoint:point];
2308 if (position.isNull())
2311 VisiblePosition previous = position.previous();
2312 if (previous.isNotNull()) {
2313 DOMRange *previousCharacterRange = [DOMRange _rangeWithImpl:makeRange(previous, position).get()];
2314 NSRect rect = [self firstRectForDOMRange:previousCharacterRange];
2315 if (NSPointInRect(point, rect))
2316 return previousCharacterRange;
2319 VisiblePosition next = position.next();
2320 if (next.isNotNull()) {
2321 DOMRange *nextCharacterRange = [DOMRange _rangeWithImpl:makeRange(position, next).get()];
2322 NSRect rect = [self firstRectForDOMRange:nextCharacterRange];
2323 if (NSPointInRect(point, rect))
2324 return nextCharacterRange;
2330 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
2332 if (!frameHasSelection(self))
2335 EditCommandPtr(new DeleteSelectionCommand(m_frame->document(), smartDelete)).apply();
2338 - (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2340 if (!m_frame || !m_frame->document())
2343 TypingCommand::deleteKeyPressed(m_frame->document(), smartDelete);
2344 [self ensureSelectionVisible];
2347 - (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2349 if (!m_frame || !m_frame->document())
2352 TypingCommand::forwardDeleteKeyPressed(m_frame->document(), smartDelete);
2353 [self ensureSelectionVisible];
2356 - (DOMCSSStyleDeclaration *)typingStyle
2358 if (!m_frame || !m_frame->typingStyle())
2360 return [DOMCSSStyleDeclaration _styleDeclarationWithImpl:m_frame->typingStyle()->copy().get()];
2363 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2367 m_frame->computeAndSetTypingStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2370 - (void)applyStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2374 m_frame->applyStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2377 - (void)applyParagraphStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2381 m_frame->applyParagraphStyle([style _styleDeclarationImpl], static_cast<EditAction>(undoAction));
2384 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
2388 return m_frame->selectionStartHasStyle([style _styleDeclarationImpl]);
2391 - (NSCellStateValue)selectionHasStyle:(DOMCSSStyleDeclaration *)style
2395 switch (m_frame->selectionHasStyle([style _styleDeclarationImpl])) {
2396 case Frame::falseTriState:
2398 case Frame::trueTriState:
2400 case Frame::mixedTriState:
2401 return NSMixedState;
2406 - (void)applyEditingStyleToBodyElement
2410 m_frame->applyEditingStyleToBodyElement();
2413 - (void)removeEditingStyleFromBodyElement
2417 m_frame->removeEditingStyleFromBodyElement();
2420 - (void)applyEditingStyleToElement:(DOMElement *)element
2424 m_frame->applyEditingStyleToElement([element _elementImpl]);
2427 - (void)removeEditingStyleFromElement:(DOMElement *)element
2431 m_frame->removeEditingStyleFromElement([element _elementImpl]);
2434 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
2436 bool multipleFonts = false;
2439 font = m_frame->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
2440 if (hasMultipleFonts)
2441 *hasMultipleFonts = multipleFonts;
2445 - (NSDictionary *)fontAttributesForSelectionStart
2447 return m_frame ? m_frame->fontAttributesForSelectionStart() : nil;
2450 - (NSWritingDirection)baseWritingDirectionForSelectionStart
2452 return m_frame ? m_frame->baseWritingDirectionForSelectionStart() : NSWritingDirectionLeftToRight;
2455 - (void)ensureSelectionVisible
2457 if (!frameHasSelection(self))
2460 FrameView *v = m_frame->view();
2464 Position extent = m_frame->selection().extent();
2465 if (extent.isNull())
2468 RenderObject *renderer = extent.node()->renderer();
2472 NSView *documentView = v->getDocumentView();
2476 IntRect extentRect = renderer->caretRect(extent.offset(), m_frame->selection().affinity());
2477 RenderLayer *layer = renderer->enclosingLayer();
2479 layer->scrollRectToVisible(extentRect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
2482 // [info draggingLocation] is in window coords
2484 - (BOOL)eventMayStartDrag:(NSEvent *)event
2486 return m_frame ? m_frame->eventMayStartDrag(event) : NO;
2489 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
2491 NSDragOperation op = NSDragOperationNone;
2493 RefPtr<FrameView> v = m_frame->view();
2495 KWQClipboard::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
2496 RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
2497 NSDragOperation srcOp = [info draggingSourceOperationMask];
2498 clipboard->setSourceOperation(srcOp);
2500 if (v->updateDragAndDrop(IntPoint([info draggingLocation]), clipboard.get())) {
2501 // *op unchanged if no source op was set
2502 if (!clipboard->destinationOperation(&op)) {
2503 // The element accepted but they didn't pick an operation, so we pick one for them
2505 if (srcOp & NSDragOperationCopy) {
2506 op = NSDragOperationCopy;
2507 } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
2508 op = NSDragOperationMove;
2509 } else if (srcOp & NSDragOperationLink) {
2510 op = NSDragOperationLink;
2512 op = NSDragOperationGeneric;
2514 } else if (!(op & srcOp)) {
2515 // make sure WC picked an op that was offered. Cocoa doesn't seem to enforce this,
2517 op = NSDragOperationNone;
2520 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
2527 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
2530 RefPtr<FrameView> v = m_frame->view();
2532 // Sending an event can result in the destruction of the view and part.
2533 KWQClipboard::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
2534 RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
2535 clipboard->setSourceOperation([info draggingSourceOperationMask]);
2536 v->cancelDragAndDrop(IntPoint([info draggingLocation]), clipboard.get());
2537 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
2542 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
2545 RefPtr<FrameView> v = m_frame->view();
2547 // Sending an event can result in the destruction of the view and part.
2548 RefPtr<KWQClipboard> clipboard = new KWQClipboard(true, [info draggingPasteboard], KWQClipboard::Readable);
2549 clipboard->setSourceOperation([info draggingSourceOperationMask]);
2550 BOOL result = v->performDragAndDrop(IntPoint([info draggingLocation]), clipboard.get());
2551 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
2558 - (void)dragSourceMovedTo:(NSPoint)windowLoc
2561 m_frame->dragSourceMovedTo(IntPoint(windowLoc));
2565 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
2568 m_frame->dragSourceEndedAt(IntPoint(windowLoc), operation);
2574 return m_frame->mayCut();
2577 - (BOOL)mayDHTMLCopy
2579 return m_frame->mayCopy();
2582 - (BOOL)mayDHTMLPaste
2584 return m_frame->mayPaste();
2589 return m_frame->tryCut();
2592 - (BOOL)tryDHTMLCopy
2594 return m_frame->tryCopy();
2597 - (BOOL)tryDHTMLPaste
2599 return m_frame->tryPaste();
2602 - (DOMRange *)rangeOfCharactersAroundCaret
2607 SelectionController selection(m_frame->selection());
2608 if (!selection.isCaret())
2611 VisiblePosition caret(selection.start(), selection.affinity());
2612 VisiblePosition next = caret.next();
2613 VisiblePosition previous = caret.previous();
2614 if (previous.isNull() || next.isNull() || caret == next || caret == previous)
2617 return [DOMRange _rangeWithImpl:makeRange(previous, next).get()];
2620 - (NSMutableDictionary *)dashboardRegions
2622 return m_frame->dashboardRegionsDictionary();
2627 @implementation WebCoreFrameBridge (WebCoreBridgeInternal)
2629 - (RootObject *)executionContextForView:(NSView *)aView
2631 MacFrame *frame = [self impl];
2632 RootObject *root = new RootObject(aView); // The root gets deleted by JavaScriptCore.
2633 root->setRootObjectImp(Window::retrieveWindow(frame));
2634 root->setInterpreter(frame->jScript()->interpreter());
2635 frame->addPluginRootObject(root);
2639 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point
2641 RenderObject *renderer = m_frame->renderer();
2643 RenderObject::NodeInfo nodeInfo(true, true);
2644 renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
2648 IntPoint widgetPoint(point);
2651 n = nodeInfo.innerNode();
2652 if (!n || !n->renderer() || !n->renderer()->isWidget())
2654 widget = static_cast<RenderWidget *>(n->renderer())->widget();
2655 if (!widget || !widget->isFrameView())
2657 Frame *kpart = static_cast<HTMLFrameElementImpl *>(n)->contentPart();
2658 if (!kpart || !static_cast<MacFrame *>(kpart)->renderer())
2661 n->renderer()->absolutePosition(absX, absY, true);
2662 FrameView *view = static_cast<FrameView *>(widget);
2663 widgetPoint.setX(widgetPoint.x() - absX + view->contentsX());
2664 widgetPoint.setY(widgetPoint.y() - absY + view->contentsY());
2666 RenderObject::NodeInfo widgetNodeInfo(true, true);
2667 static_cast<MacFrame *>(kpart)->renderer()->layer()->hitTest(widgetNodeInfo, widgetPoint.x(), widgetPoint.y());
2668 nodeInfo = widgetNodeInfo;
2676 @implementation WebCoreFrameBridge (WebCoreInternalUse)