2 * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #import "WebCoreBridge.h"
29 #import "dom2_eventsimpl.h"
30 #import "dom2_rangeimpl.h"
31 #import "dom2_viewsimpl.h"
32 #import "dom_docimpl.h"
34 #import "dom_nodeimpl.h"
35 #import "dom_position.h"
36 #import "html_documentimpl.h"
37 #import "html_formimpl.h"
38 #import "html_imageimpl.h"
40 #import "htmlediting.h"
42 #import "khtml_part.h"
45 #import "kjs_window.h"
47 #import "render_canvas.h"
48 #import "render_frames.h"
49 #import "render_image.h"
50 #import "render_object.h"
51 #import "render_replaced.h"
52 #import "render_style.h"
54 #import "visible_position.h"
56 #import <JavaScriptCore/npruntime.h>
57 #import <JavaScriptCore/jni_jsobject.h>
58 #import <JavaScriptCore/object.h>
59 #import <JavaScriptCore/runtime_root.h>
60 #import <JavaScriptCore/property_map.h>
62 #import "KWQAssertions.h"
63 #import "KWQCharsets.h"
64 #import "KWQClipboard.h"
65 #import "KWQDOMNode.h"
66 #import "KWQEditCommand.h"
68 #import "KWQFoundationExtras.h"
70 #import "KWQKHTMLPart.h"
72 #import "KWQPageState.h"
73 #import "KWQRenderTreeDebug.h"
75 #import "KWQPrinter.h"
76 #import "KWQAccObjectCache.h"
78 #import "DOMInternal.h"
79 #import "WebCoreImageRenderer.h"
80 #import "WebCoreTextRendererFactory.h"
81 #import "WebCoreViewFactory.h"
82 #import "WebCoreSettings.h"
86 using DOM::AtomicString;
87 using DOM::CSSStyleDeclarationImpl;
88 using DOM::DocumentFragmentImpl;
89 using DOM::DocumentImpl;
90 using DOM::DocumentTypeImpl;
93 using DOM::ElementImpl;
94 using DOM::HTMLElementImpl;
95 using DOM::HTMLFormElementImpl;
96 using DOM::HTMLGenericFormElementImpl;
97 using DOM::HTMLImageElementImpl;
98 using DOM::HTMLInputElementImpl;
104 using khtml::Decoder;
105 using khtml::DeleteSelectionCommand;
106 using khtml::EAffinity;
107 using khtml::EditCommandPtr;
108 using khtml::ETextGranularity;
109 using khtml::MoveSelectionCommand;
110 using khtml::parseURL;
111 using khtml::RenderCanvas;
112 using khtml::RenderImage;
113 using khtml::RenderObject;
114 using khtml::RenderPart;
115 using khtml::RenderStyle;
116 using khtml::RenderWidget;
117 using khtml::ReplaceSelectionCommand;
118 using khtml::Selection;
119 using khtml::TypingCommand;
120 using khtml::UPSTREAM;
121 using khtml::VisiblePosition;
123 using KJS::ExecState;
124 using KJS::ObjectImp;
125 using KJS::SavedProperties;
126 using KJS::SavedBuiltins;
129 using KParts::URLArgs;
131 using KJS::Bindings::RootObject;
133 NSString *WebCoreElementDOMNodeKey = @"WebElementDOMNode";
134 NSString *WebCoreElementFrameKey = @"WebElementFrame";
135 NSString *WebCoreElementImageAltStringKey = @"WebElementImageAltString";
136 NSString *WebCoreElementImageKey = @"WebElementImage";
137 NSString *WebCoreElementImageRectKey = @"WebElementImageRect";
138 NSString *WebCoreElementImageURLKey = @"WebElementImageURL";
139 NSString *WebCoreElementIsSelectedKey = @"WebElementIsSelected";
140 NSString *WebCoreElementLinkURLKey = @"WebElementLinkURL";
141 NSString *WebCoreElementLinkTargetFrameKey = @"WebElementTargetFrame";
142 NSString *WebCoreElementLinkLabelKey = @"WebElementLinkLabel";
143 NSString *WebCoreElementLinkTitleKey = @"WebElementLinkTitle";
144 NSString *WebCoreElementNameKey = @"WebElementName";
145 NSString *WebCoreElementTitleKey = @"WebCoreElementTitle"; // not in WebKit API for now, could be in API some day
147 NSString *WebCorePageCacheStateKey = @"WebCorePageCacheState";
149 @interface WebCoreBridge (WebCoreBridgePrivate)
150 - (RootObject *)executionContextForView:(NSView *)aView;
153 static RootObject *rootForView(void *v)
155 NSView *aView = (NSView *)v;
156 WebCoreBridge *aBridge = [[WebCoreViewFactory sharedFactory] bridgeForView:aView];
159 return [aBridge executionContextForView:aView];
164 static pthread_t mainThread = 0;
166 static void updateRenderingForBindings (ExecState *exec, ObjectImp *rootObject)
168 if (pthread_self() != mainThread)
174 Window *window = static_cast<Window*>(rootObject);
178 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->part()->document().handle());
180 doc->updateRendering();
184 @implementation WebCoreBridge
186 static bool initializedObjectCacheSize = FALSE;
187 static bool initializedKJS = FALSE;
189 + (WebCoreBridge *)bridgeForDOMDocument:(DOMDocument *)document
191 return ((KWQKHTMLPart *)[document _documentImpl]->part())->bridge();
198 _part = new KWQKHTMLPart;
199 _part->setBridge(self);
201 if (!initializedObjectCacheSize){
202 khtml::Cache::setSize([self getObjectCacheSize]);
203 initializedObjectCacheSize = TRUE;
206 if (!initializedKJS) {
207 mainThread = pthread_self();
209 RootObject::setFindRootObjectForNativeHandleFunction (rootForView);
211 KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
213 initializedKJS = TRUE;
216 _shouldCreateRenderers = YES;
221 - (void)initializeSettings: (WebCoreSettings *)settings
223 _part->setSettings ([settings settings]);
228 [self removeFromFrame];
231 _renderPart->deref(_renderPartArena);
233 _part->setBridge(nil);
241 // FIXME: This work really should not be done at deallocation time.
242 // We need to do it at some well-defined time instead.
244 [self removeFromFrame];
247 _renderPart->deref(_renderPartArena);
249 _part->setBridge(nil);
255 - (KWQKHTMLPart *)part
260 - (void)setRenderPart:(KHTMLRenderPart *)newPart;
262 RenderArena *arena = newPart->ref();
264 _renderPart->deref(_renderPartArena);
266 _renderPart = newPart;
267 _renderPartArena = arena;
270 - (KHTMLRenderPart *)renderPart
275 - (void)setParent:(WebCoreBridge *)parent
277 _part->setParent([parent part]);
280 - (void)provisionalLoadStarted
282 _part->provisionalLoadStarted();
285 - (void)openURL:(NSURL *)URL reload:(BOOL)reload contentType:(NSString *)contentType refresh:(NSString *)refresh lastModified:(NSDate *)lastModified pageCache:(NSDictionary *)pageCache
288 KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
289 _part->openURLFromPageCache(state);
295 URLArgs args(_part->browserExtension()->urlArgs());
296 args.reload = reload;
298 args.serviceType = QString::fromNSString(contentType);
300 _part->browserExtension()->setURLArgs(args);
303 if (_part->didOpenURL(URL)) {
304 // things we have to set up after calling didOpenURL
306 _part->addMetaData("http-refresh", QString::fromNSString(refresh));
309 NSString *modifiedString = [lastModified descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
310 _part->addMetaData("modified", QString::fromNSString(modifiedString));
315 - (void)setEncoding:(NSString *)encoding userChosen:(BOOL)userChosen
317 _part->setEncoding(QString::fromNSString(encoding), userChosen);
320 - (void)addData:(NSData *)data
322 DocumentImpl *doc = _part->xmlDocImpl();
324 // Document may be nil if the part is about to redirect
325 // as a result of JS executing during load, i.e. one frame
326 // changing another's location before the frame's document
329 doc->setShouldCreateRenderers([self shouldCreateRenderers]);
330 _part->addData((const char *)[data bytes], [data length]);
339 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache
341 _part->didNotOpenURL(KURL(URL).url());
343 // We might have made a page cache item, but now we're bailing out due to an error before we ever
344 // transitioned to the new page (before WebFrameState==commit). The goal here is to restore any state
345 // so that the existing view (that wenever got far enough to replace) can continue being used.
346 DocumentImpl *doc = _part->xmlDocImpl();
348 doc->setInPageCache(NO);
350 KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
354 - (void)saveDocumentState
356 DocumentImpl *doc = _part->xmlDocImpl();
358 QStringList list = doc->docState();
359 NSMutableArray *documentState = [[[NSMutableArray alloc] init] autorelease];
361 for (uint i = 0; i < list.count(); i++){
363 [documentState addObject: [NSString stringWithCharacters: (const unichar *)s.unicode() length: s.length()]];
365 [self saveDocumentState: documentState];
369 - (void)restoreDocumentState
371 DocumentImpl *doc = _part->xmlDocImpl();
374 NSArray *documentState = [self documentState];
377 for (uint i = 0; i < [documentState count]; i++){
378 NSString *string = [documentState objectAtIndex: i];
379 s.append(QString::fromNSString(string));
382 doc->setRestoreState(s);
386 - (void)scrollToAnchorWithURL:(NSURL *)URL
388 _part->scrollToAnchor(KURL(URL).url().latin1());
391 - (BOOL)scrollOverflowInDirection:(WebScrollDirection)direction granularity:(WebScrollGranularity)granularity
396 return _part->scrollOverflow((KWQScrollDirection)direction, (KWQScrollGranularity)granularity);
399 - (BOOL)scrollOverflowWithScrollWheelEvent:(NSEvent *)event
404 return _part->scrollOverflowWithScrollWheelEvent(event);
407 - (BOOL)saveDocumentToPageCache
409 DocumentImpl *doc = _part->xmlDocImpl();
417 _part->clearTimers();
419 SavedProperties *windowProperties = new SavedProperties;
420 _part->saveWindowProperties(windowProperties);
422 SavedProperties *locationProperties = new SavedProperties;
423 _part->saveLocationProperties(locationProperties);
425 SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
426 _part->saveInterpreterBuiltins(*interpreterBuiltins);
428 KWQPageState *pageState = [[[KWQPageState alloc] initWithDocument:doc
430 windowProperties:windowProperties
431 locationProperties:locationProperties
432 interpreterBuiltins:interpreterBuiltins] autorelease];
433 [pageState setPausedActions: _part->pauseActions((const void *)pageState)];
435 return [self saveDocumentToPageCache:pageState];
440 return _part->canCachePage();
448 - (void)createKHTMLViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
450 // If we own the view, delete the old one - otherwise the render _part will take care of deleting the view.
451 [self removeFromFrame];
453 KHTMLView *kview = new KHTMLView(_part, 0);
454 _part->setView(kview);
457 kview->setView(view);
459 kview->setMarginWidth(mw);
461 kview->setMarginHeight(mh);
464 - (void)scrollToAnchor:(NSString *)a
466 _part->gotoAnchor(QString::fromNSString(a));
469 - (BOOL)isSelectionEditable
471 // EDIT FIXME: This needs to consider the entire selected range
472 NodeImpl *startNode = _part->selection().start().node();
473 return startNode ? startNode->isContentEditable() : NO;
476 - (WebSelectionState)selectionState
478 switch (_part->selection().state()) {
479 case Selection::NONE:
480 return WebSelectionStateNone;
481 case Selection::CARET:
482 return WebSelectionStateCaret;
483 case Selection::RANGE:
484 return WebSelectionStateRange;
487 ASSERT_NOT_REACHED();
488 return WebSelectionStateNone;
491 - (NSString *)_documentTypeString
493 NSString *documentTypeString = nil;
494 DOM::DocumentImpl *doc = _part->xmlDocImpl();
496 DocumentTypeImpl *doctype = doc->doctype();
498 documentTypeString = doctype->toString().string().getNSString();
501 return documentTypeString;
504 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
506 NSString *documentTypeString = [self _documentTypeString];
507 if (documentTypeString && markupString) {
508 return [NSString stringWithFormat:@"%@%@", documentTypeString, markupString];
509 } else if (documentTypeString) {
510 return documentTypeString;
511 } else if (markupString) {
518 - (NSArray *)nodesFromList:(QPtrList<NodeImpl> *)nodeList
520 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
521 for (QPtrListIterator<NodeImpl> i(*nodeList); i.current(); ++i) {
522 [nodes addObject:[DOMNode _nodeWithImpl:i.current()]];
527 - (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
529 QPtrList<NodeImpl> *nodeList = NULL;
531 nodeList = new QPtrList<NodeImpl>;
533 NSString *markupString = [node _nodeImpl]->recursive_toHTML(false, nodeList).getNSString();
535 *nodes = [self nodesFromList:nodeList];
538 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
541 - (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
543 QPtrList<NodeImpl> *nodeList = NULL;
545 nodeList = new QPtrList<NodeImpl>;
547 NSString *markupString = [range _rangeImpl]->toHTML(nodeList).string().getNSString();
549 *nodes = [self nodesFromList:nodeList];
552 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
555 - (NSString *)selectedString
557 QString text = _part->selectedText();
558 text.replace('\\', _part->backslashAsCurrencySymbol());
559 return [[text.getNSString() copy] autorelease];
562 - (NSString *)stringForRange:(DOMRange *)range
564 QString text = _part->text([range _rangeImpl]);
565 text.replace('\\', _part->backslashAsCurrencySymbol());
566 return [[text.getNSString() copy] autorelease];
577 DocumentImpl *doc = _part->xmlDocImpl();
579 doc->setFocusNode(0);
585 _part->clearSelection();
590 return _part->isFrameSet();
593 - (NSString *)styleSheetForPrinting
595 if (!_part->settings()->shouldPrintBackgrounds()) {
596 return @"* { background-image: none !important; background-color: white !important;}";
601 - (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
603 _part->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
604 DocumentImpl *doc = _part->xmlDocImpl();
606 static QPaintDevice screen;
607 static QPrinter printer;
608 doc->setPaintDevice(deviceType == WebCoreDeviceScreen ? &screen : &printer);
609 if (deviceType != WebCoreDeviceScreen) {
610 doc->setPrintStyleSheet(QString::fromNSString([self styleSheetForPrinting]));
613 return _part->reparseConfiguration();
616 static BOOL nowPrinting(WebCoreBridge *self)
618 DocumentImpl *doc = self->_part->xmlDocImpl();
619 return doc && doc->paintDevice() && doc->paintDevice()->devType() == QInternal::Printer;
622 // Set or unset the printing mode in the view. We only toy with this if we're printing.
623 - (void)_setupRootForPrinting:(BOOL)onOrOff
625 if (nowPrinting(self)) {
626 RenderCanvas *root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
628 root->setPrintingMode(onOrOff);
633 - (void)forceLayoutAdjustingViewSize:(BOOL)flag
635 [self _setupRootForPrinting:YES];
636 _part->forceLayout();
638 [self adjustViewSize];
640 [self _setupRootForPrinting:NO];
643 - (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
645 [self _setupRootForPrinting:YES];
646 _part->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth);
648 [self adjustViewSize];
650 [self _setupRootForPrinting:NO];
653 - (void)sendResizeEvent
655 _part->sendResizeEvent();
658 - (void)sendScrollEvent
660 _part->sendScrollEvent();
663 - (void)drawRect:(NSRect)rect withPainter:(QPainter *)p
665 [self _setupRootForPrinting:YES];
666 _part->paint(p, QRect(rect));
667 [self _setupRootForPrinting:NO];
670 - (void)drawRect:(NSRect)rect
672 QPainter painter(nowPrinting(self));
673 bool displaysWithFocusAttributes = _part->displaysWithFocusAttributes();
674 painter.setUsesInactiveTextBackgroundColor(!displaysWithFocusAttributes);
675 painter.setDrawsFocusRing(displaysWithFocusAttributes);
676 [self drawRect:rect withPainter:&painter];
679 // Used by pagination code called from AppKit when a standalone web page is printed.
680 - (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
682 [self _setupRootForPrinting:YES];
683 NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
684 if (printWidthScaleFactor == 0 || printHeight == 0)
687 if (!_part || !_part->xmlDocImpl() || !_part->view()) return pages;
688 RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
689 if (!root) return pages;
691 KHTMLView* view = _part->view();
692 NSView* documentView = view->getDocumentView();
696 float currPageHeight = printHeight;
697 float docHeight = root->layer()->height();
698 float docWidth = root->layer()->width();
699 float printWidth = docWidth/printWidthScaleFactor;
701 // We need to give the part the opportunity to adjust the page height at each step.
702 for (float i = 0; i < docHeight; i += currPageHeight) {
703 float proposedBottom = kMin(docHeight, i + printHeight);
704 _part->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
705 currPageHeight = kMax(1.0f, proposedBottom - i);
706 for (float j = 0; j < docWidth; j += printWidth) {
707 NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
708 [pages addObject: val];
711 [self _setupRootForPrinting:NO];
716 // This is to support the case where a webview is embedded in the view that's being printed
717 - (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
719 [self _setupRootForPrinting:YES];
720 _part->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
721 [self _setupRootForPrinting:NO];
724 - (NSObject *)copyDOMNode:(NodeImpl *)node copier:(id <WebCoreDOMTreeCopier>)copier
726 NSMutableArray *children = [[NSMutableArray alloc] init];
727 for (NodeImpl *child = node->firstChild(); child; child = child->nextSibling()) {
728 [children addObject:[self copyDOMNode:child copier:copier]];
730 NSObject *copiedNode = [copier nodeWithName:node->nodeName().string().getNSString()
731 value:node->nodeValue().string().getNSString()
732 source:node->recursive_toHTML(true).getNSString()
738 - (NSObject *)copyDOMTree:(id <WebCoreDOMTreeCopier>)copier
740 DocumentImpl *doc = _part->xmlDocImpl();
744 return [self copyDOMNode:doc copier:copier];
747 - (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
749 NSMutableArray *children = [[NSMutableArray alloc] init];
750 for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
751 [children addObject:[self copyRenderNode:child copier:copier]];
754 NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
756 RenderPart *nodeRenderPart = dynamic_cast<RenderPart *>(node);
757 QWidget *widget = nodeRenderPart ? nodeRenderPart->widget() : 0;
758 NSView *view = widget ? widget->getView() : nil;
761 node->absolutePosition(nx,ny);
762 NSObject *copiedNode = [copier nodeWithName:name
763 position:NSMakePoint(nx,ny)
764 rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
774 - (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
776 RenderObject *renderer = _part->renderer();
780 return [self copyRenderNode:renderer copier:copier];
783 - (void)removeFromFrame
788 - (void)installInFrame:(NSView *)view
790 // If this isn't the main frame, it must have a render _part set, or it
791 // won't ever get installed in the view hierarchy.
792 ASSERT(self == [self mainFrame] || _renderPart != nil);
794 _part->view()->setView(view);
796 _renderPart->setWidget(_part->view());
797 // Now the render part owns the view, so we don't any more.
800 _part->view()->initScrollBars();
803 - (void)setActivationEventNumber:(int)num
805 _part->setActivationEventNumber(num);
808 - (void)mouseDown:(NSEvent *)event
810 _part->mouseDown(event);
813 - (void)mouseDragged:(NSEvent *)event
815 _part->mouseDragged(event);
818 - (void)mouseUp:(NSEvent *)event
820 _part->mouseUp(event);
823 - (void)mouseMoved:(NSEvent *)event
825 _part->mouseMoved(event);
828 - (BOOL)sendContextMenuEvent:(NSEvent *)event
830 return _part->sendContextMenuEvent(event);
833 - (DOMElement *)elementForView:(NSView *)view
835 // FIXME: implemented currently for only a subset of the KWQ widgets
836 if ([view conformsToProtocol:@protocol(KWQWidgetHolder)]) {
837 NSView <KWQWidgetHolder> *widgetHolder = view;
838 QWidget *widget = [widgetHolder widget];
840 NodeImpl *node = static_cast<const RenderWidget *>(widget->eventFilterObject())->element();
841 return [DOMElement _elementWithImpl:static_cast<ElementImpl *>(node)];
847 static NSView *viewForElement(ElementImpl *elementImpl)
849 RenderObject *renderer = elementImpl->renderer();
850 if (renderer && renderer->isWidget()) {
851 QWidget *widget = static_cast<const RenderWidget *>(renderer)->widget();
854 return widget->getView();
860 static HTMLInputElementImpl *inputElementFromDOMElement(DOMElement *element)
862 NodeImpl *node = [element _nodeImpl];
863 if (node && idFromNode(node) == ID_INPUT) {
864 return static_cast<HTMLInputElementImpl *>(node);
869 static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
871 NodeImpl *node = [element _nodeImpl];
872 if (node && idFromNode(node) == ID_FORM) {
873 return static_cast<HTMLFormElementImpl *>(node);
878 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
880 HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
882 QPtrList<HTMLGenericFormElementImpl> elements = formElement->formElements;
883 QString targetName = QString::fromNSString(name);
884 for (unsigned int i = 0; i < elements.count(); i++) {
885 HTMLGenericFormElementImpl *elt = elements.at(i);
886 // Skip option elements, other duds
887 if (elt->name() == targetName) {
888 return [DOMElement _elementWithImpl:elt];
895 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
897 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
898 return inputElement != nil
899 && inputElement->inputType() == HTMLInputElementImpl::TEXT
900 && inputElement->autoComplete();
903 - (BOOL)elementIsPassword:(DOMElement *)element
905 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
906 return inputElement != nil
907 && inputElement->inputType() == HTMLInputElementImpl::PASSWORD;
910 - (DOMElement *)formForElement:(DOMElement *)element;
912 HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
914 HTMLFormElementImpl *formElement = inputElement->form();
916 return [DOMElement _elementWithImpl:formElement];
922 - (DOMElement *)currentForm
924 HTMLFormElementImpl *formElement = _part->currentForm();
925 return formElement ? [DOMElement _elementWithImpl:formElement] : nil;
928 - (NSArray *)controlsInForm:(DOMElement *)form
930 NSMutableArray *results = nil;
931 HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
933 QPtrList<HTMLGenericFormElementImpl> elements = formElement->formElements;
934 for (unsigned int i = 0; i < elements.count(); i++) {
935 if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
936 NSView *view = viewForElement(elements.at(i));
939 results = [NSMutableArray arrayWithObject:view];
941 [results addObject:view];
950 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
952 return _part->searchForLabelsBeforeElement(labels, [element _elementImpl]);
955 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
957 return _part->matchLabelsAgainstElement(labels, [element _elementImpl]);
960 - (NSDictionary *)elementAtPoint:(NSPoint)point
962 RenderObject *renderer = _part->renderer();
966 RenderObject::NodeInfo nodeInfo(true, true);
967 renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
969 NSMutableDictionary *element = [NSMutableDictionary dictionary];
970 [element setObject:[NSNumber numberWithBool:_part->isPointInsideSelection((int)point.x, (int)point.y)]
971 forKey:WebCoreElementIsSelectedKey];
973 // Find the title in the nearest enclosing DOM node.
974 // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
975 for (NodeImpl *titleNode = nodeInfo.innerNode(); titleNode; titleNode = titleNode->parentNode()) {
976 if (titleNode->isElementNode()) {
977 const AtomicString& title = static_cast<ElementImpl *>(titleNode)->getAttribute(ATTR_TITLE);
978 if (!title.isNull()) {
979 // We found a node with a title.
980 QString titleText = title.string();
981 titleText.replace('\\', _part->backslashAsCurrencySymbol());
982 [element setObject:titleText.getNSString() forKey:WebCoreElementTitleKey];
988 NodeImpl *URLNode = nodeInfo.URLElement();
990 ElementImpl *e = static_cast<ElementImpl *>(URLNode);
992 const AtomicString& title = e->getAttribute(ATTR_TITLE);
993 if (!title.isEmpty()) {
994 QString titleText = title.string();
995 titleText.replace('\\', _part->backslashAsCurrencySymbol());
996 [element setObject:titleText.getNSString() forKey:WebCoreElementLinkTitleKey];
999 const AtomicString& link = e->getAttribute(ATTR_HREF);
1000 if (!link.isNull()) {
1001 if (e->firstChild()) {
1002 Range r(_part->document());
1003 r.setStartBefore(e->firstChild());
1004 r.setEndAfter(e->lastChild());
1005 QString t = _part->text(r);
1007 [element setObject:t.getNSString() forKey:WebCoreElementLinkLabelKey];
1010 QString URLString = parseURL(link).string();
1011 [element setObject:_part->xmlDocImpl()->completeURL(URLString).getNSString() forKey:WebCoreElementLinkURLKey];
1014 DOMString target = e->getAttribute(ATTR_TARGET);
1015 if (target.isEmpty() && _part->xmlDocImpl()) {
1016 target = _part->xmlDocImpl()->baseTarget();
1018 if (!target.isEmpty()) {
1019 [element setObject:target.string().getNSString() forKey:WebCoreElementLinkTargetFrameKey];
1023 NodeImpl *node = nodeInfo.innerNonSharedNode();
1025 [element setObject:[DOMNode _nodeWithImpl:node] forKey:WebCoreElementDOMNodeKey];
1027 if (node->renderer() && node->renderer()->isImage()) {
1028 RenderImage *r = static_cast<RenderImage *>(node->renderer());
1029 NSImage *image = r->pixmap().image();
1030 // Only return image information if there is an image.
1031 if (image && !r->isDisplayingError()) {
1032 [element setObject:r->pixmap().image() forKey:WebCoreElementImageKey];
1036 if (r->absolutePosition(x, y)) {
1037 NSValue *rect = [NSValue valueWithRect:NSMakeRect(x, y, r->contentWidth(), r->contentHeight())];
1038 [element setObject:rect forKey:WebCoreElementImageRectKey];
1041 ElementImpl *i = static_cast<ElementImpl*>(node);
1043 // FIXME: Code copied from RenderImage::updateFromElement; should share.
1045 if (idFromNode(i) == ID_OBJECT) {
1046 attr = i->getAttribute(ATTR_DATA);
1048 attr = i->getAttribute(ATTR_SRC);
1050 if (!attr.isEmpty()) {
1051 QString URLString = parseURL(attr).string();
1052 [element setObject:_part->xmlDocImpl()->completeURL(URLString).getNSString() forKey:WebCoreElementImageURLKey];
1055 // FIXME: Code copied from RenderImage::updateFromElement; should share.
1057 if (idFromNode(i) == ID_INPUT)
1058 alt = static_cast<HTMLInputElementImpl *>(i)->altText();
1059 else if (idFromNode(i) == ID_IMG)
1060 alt = static_cast<HTMLImageElementImpl *>(i)->altText();
1061 if (!alt.isNull()) {
1062 QString altText = alt.string();
1063 altText.replace('\\', _part->backslashAsCurrencySymbol());
1064 [element setObject:altText.getNSString() forKey:WebCoreElementImageAltStringKey];
1072 - (NSURL *)URLWithAttributeString:(NSString *)string
1074 DocumentImpl *doc = _part->xmlDocImpl();
1078 QString rel = parseURL(QString::fromNSString(string)).string();
1079 return KURL(doc->baseURL(), rel, doc->decoder() ? doc->decoder()->codec() : 0).getNSURL();
1082 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1084 return _part->findString(string, forward, caseFlag, wrapFlag);
1087 - (void)jumpToSelection
1089 _part->jumpToSelection();
1092 - (NSString *)advanceToNextMisspelling
1094 return _part->advanceToNextMisspelling().getNSString();
1097 - (NSString *)advanceToNextMisspellingStartingJustBeforeSelection
1099 return _part->advanceToNextMisspelling(true).getNSString();
1102 - (void)setTextSizeMultiplier:(float)multiplier
1104 int newZoomFactor = (int)rint(multiplier * 100);
1105 if (_part->zoomFactor() == newZoomFactor) {
1108 _part->setZoomFactor(newZoomFactor);
1111 - (CFStringEncoding)textEncoding
1113 return KWQCFStringEncodingFromIANACharsetName(_part->encoding().latin1());
1116 - (NSView *)nextKeyView
1118 DocumentImpl *doc = _part->xmlDocImpl();
1122 return _part->nextKeyView(doc->focusNode(), KWQSelectingNext);
1125 - (NSView *)previousKeyView
1127 DocumentImpl *doc = _part->xmlDocImpl();
1131 return _part->nextKeyView(doc->focusNode(), KWQSelectingPrevious);
1134 - (NSView *)nextKeyViewInsideWebFrameViews
1136 DocumentImpl *doc = _part->xmlDocImpl();
1141 return _part->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingNext);
1144 - (NSView *)previousKeyViewInsideWebFrameViews
1146 DocumentImpl *doc = _part->xmlDocImpl();
1151 return _part->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingPrevious);
1154 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
1156 _part->createEmptyDocument();
1157 return _part->executeScript(QString::fromNSString(string), true).asString().getNSString();
1160 - (WebScriptObject *)windowScriptObject
1162 return _part->windowScriptObject();
1165 - (NPObject *)windowScriptNPObject
1167 return _part->windowScriptNPObject();
1170 - (DOMDocument *)DOMDocument
1172 return [DOMDocument _documentWithImpl:_part->xmlDocImpl()];
1175 - (DOMHTMLElement *)frameElement
1177 return (DOMHTMLElement *)[[self DOMDocument] _ownerElement];
1180 - (NSAttributedString *)selectedAttributedString
1182 return _part->attributedString(_part->selectionStart(), _part->selectionStartOffset(), _part->selectionEnd(), _part->selectionEndOffset());
1185 - (NSAttributedString *)attributedStringFrom:(DOMNode *)start startOffset:(int)startOffset to:(DOMNode *)end endOffset:(int)endOffset
1187 DOMNode *startNode = start;
1188 DOMNode *endNode = end;
1189 return _part->attributedString([startNode _nodeImpl], startOffset, [endNode _nodeImpl], endOffset);
1192 - (NSRect)selectionRect
1194 return _part->selectionRect();
1197 - (NSRect)visibleSelectionRect
1199 return _part->visibleSelectionRect();
1202 - (void)centerSelectionInVisibleArea
1204 _part->centerSelectionInVisibleArea();
1207 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1209 return [node _nodeImpl]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1211 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1213 int extraWidthToEndOfLine = 0;
1214 QRect startCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range startOffset], UPSTREAM, &extraWidthToEndOfLine);
1215 QRect endCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range endOffset], UPSTREAM);
1217 if (startCaretRect.y() == endCaretRect.y()) {
1218 // start and end are on the same line
1219 return QRect(MIN(startCaretRect.x(), endCaretRect.x()),
1221 abs(endCaretRect.x() - startCaretRect.x()),
1222 MAX(startCaretRect.height(), endCaretRect.height()));
1225 // start and end aren't on the same line, so go from start to the end of its line
1226 return QRect(startCaretRect.x(),
1228 startCaretRect.width() + extraWidthToEndOfLine,
1229 startCaretRect.height());
1232 - (NSImage *)selectionImage
1234 return _part->selectionImage();
1237 - (void)setName:(NSString *)name
1239 _part->KHTMLPart::setName(QString::fromNSString(name));
1244 return _part->name().getNSString();
1249 return _part->url().getNSURL();
1252 - (NSString *)referrer
1254 return _part->referrer().getNSString();
1257 - (NSString *)domain
1259 DocumentImpl *doc = _part->xmlDocImpl();
1260 if (doc && doc->isHTMLDocument()) {
1261 return doc->domain().string().getNSString();
1266 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
1268 if (textEncoding == kCFStringEncodingInvalidId || textEncoding == kCFStringEncodingISOLatin1) {
1269 textEncoding = kCFStringEncodingWindowsLatin1;
1271 return QTextCodec(textEncoding).toUnicode((const char*)[data bytes], [data length]).getNSString();
1274 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1276 CFStringEncoding textEncoding = KWQCFStringEncodingFromIANACharsetName([textEncodingName lossyCString]);
1277 return [WebCoreBridge stringWithData:data textEncoding:textEncoding];
1282 RenderObject *renderer = _part->renderer();
1283 return renderer ? renderer->needsLayout() : false;
1286 - (void)setNeedsLayout
1288 RenderObject *renderer = _part->renderer();
1290 renderer->setNeedsLayout(true);
1293 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1295 return _part->keyEvent(event);
1298 - (NSString *)renderTreeAsExternalRepresentation
1300 return externalRepresentation(_part->renderer()).getNSString();
1303 - (void)setSelectionFromNone
1305 _part->setSelectionFromNone();
1308 - (void)setDisplaysWithFocusAttributes:(BOOL)flag
1310 _part->setDisplaysWithFocusAttributes(flag);
1313 - (void)setShouldCreateRenderers:(BOOL)f
1315 _shouldCreateRenderers = f;
1318 - (BOOL)shouldCreateRenderers
1320 return _shouldCreateRenderers;
1323 - (int)numPendingOrLoadingRequests
1325 DocumentImpl *doc = _part->xmlDocImpl();
1328 return KWQNumberOfPendingOrLoadingRequests (doc->docLoader());
1332 - (NSColor *)bodyBackgroundColor
1334 return _part->bodyBackgroundColor();
1337 - (NSColor *)selectionColor
1339 RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
1341 RenderStyle *pseudoStyle = root->getPseudoStyle(RenderStyle::SELECTION);
1342 if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) {
1343 return pseudoStyle->backgroundColor().getNSColor();
1346 return _part->displaysWithFocusAttributes() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1349 - (void)adjustViewSize
1351 KHTMLView *view = _part->view();
1353 view->adjustViewSize();
1356 -(id)accessibilityTree
1358 KWQAccObjectCache::enableAccessibility();
1359 if (!_part || !_part->xmlDocImpl()) return nil;
1360 RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
1361 if (!root) return nil;
1362 return _part->xmlDocImpl()->getOrCreateAccObjectCache()->accObject(root);
1365 - (void)setDrawsBackground:(BOOL)drawsBackground
1367 if (_part && _part->view())
1368 _part->view()->setTransparent(!drawsBackground);
1371 - (void)undoEditing:(id)arg
1373 ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1374 [arg command]->unapply();
1377 - (void)redoEditing:(id)arg
1379 ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1380 [arg command]->reapply();
1383 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebSelectionGranularity)granularity
1388 // NOTE: The enums *must* match the very similar ones declared in ktml_selection.h
1389 Selection selection(_part->selection());
1390 selection.expandUsingGranularity(static_cast<ETextGranularity>(granularity));
1391 return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1394 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
1399 // NOTE: The enums *must* match the very similar ones declared in ktml_selection.h
1400 Selection selection(_part->selection());
1401 selection.modify(static_cast<Selection::EAlter>(alteration),
1402 static_cast<Selection::EDirection>(direction),
1403 static_cast<ETextGranularity>(granularity));
1404 return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1407 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
1412 // NOTE: The enums *must* match the very similar ones declared in dom_selection.h
1413 Selection selection(_part->selection());
1414 selection.modify(static_cast<Selection::EAlter>(alteration),
1415 static_cast<Selection::EDirection>(direction),
1416 static_cast<ETextGranularity>(granularity));
1418 // save vertical navigation x position if necessary; many types of motion blow it away
1419 int xPos = KHTMLPart::NoXPosForVerticalArrowNavigation;
1420 switch (granularity) {
1421 case WebSelectByLine:
1422 case WebSelectByParagraph:
1423 xPos = _part->xPosForVerticalArrowNavigation();
1425 case WebSelectByCharacter:
1426 case WebSelectByWord:
1427 case WebSelectToLineBoundary:
1428 case WebSelectToParagraphBoundary:
1429 case WebSelectToDocumentBoundary:
1434 // setting the selection always clears saved vertical navigation x position
1435 _part->setSelection(selection);
1437 // restore vertical navigation x position if necessary
1438 if (xPos != KHTMLPart::NoXPosForVerticalArrowNavigation)
1439 _part->setXPosForVerticalArrowNavigation(xPos);
1441 [self ensureSelectionVisible];
1444 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1449 Selection selection(_part->selection());
1450 selection.modify(static_cast<Selection::EAlter>(alteration), static_cast<int>(verticalDistance));
1451 return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1454 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1459 Selection selection(_part->selection());
1460 selection.modify(static_cast<Selection::EAlter>(alteration), static_cast<int>(verticalDistance));
1462 // setting the selection always clears saved vertical navigation x position, so preserve it
1463 int xPos = _part->xPosForVerticalArrowNavigation();
1464 _part->setSelection(selection);
1465 _part->setXPosForVerticalArrowNavigation(xPos);
1467 [self ensureSelectionVisible];
1470 - (WebSelectionGranularity)selectionGranularity
1472 // NOTE: The enums *must* match the very similar ones declared in dom_selection.h
1473 return static_cast<WebSelectionGranularity>(_part->selectionGranularity());
1476 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
1478 NodeImpl *startContainer = [[range startContainer] _nodeImpl];
1479 NodeImpl *endContainer = [[range endContainer] _nodeImpl];
1480 ASSERT(startContainer);
1481 ASSERT(endContainer);
1482 ASSERT(startContainer->getDocument());
1483 ASSERT(startContainer->getDocument() == endContainer->getDocument());
1485 _part->xmlDocImpl()->updateLayout();
1487 // Work around bug where isRenderedContent returns false for <br> elements at the ends of lines.
1488 // If that bug wasn't an issue, we could just make the position from the range directly.
1489 Position start(startContainer, [range startOffset]);
1490 Position end(endContainer, [range endOffset]);
1491 start = VisiblePosition(start, UPSTREAM).deepEquivalent();
1493 Selection selection(start, end);
1494 selection.setAffinity(static_cast<EAffinity>(selectionAffinity));
1495 _part->setSelection(selection);
1498 - (DOMRange *)selectedDOMRange
1500 return [DOMRange _rangeWithImpl:_part->selection().toRange().handle()];
1503 - (NSSelectionAffinity)selectionAffinity
1505 return static_cast<NSSelectionAffinity>(_part->selection().affinity());
1508 - (void)setMarkDOMRange:(DOMRange *)range
1510 _part->setMark(Selection([range _rangeImpl]));
1513 - (DOMRange *)markDOMRange
1515 return [DOMRange _rangeWithImpl:_part->mark().toRange().handle()];
1518 - (void)setMarkedTextDOMRange:(DOMRange *)range
1520 _part->setMarkedTextRange([range _rangeImpl]);
1523 - (DOMRange *)markedTextDOMRange
1525 return [DOMRange _rangeWithImpl:_part->markedTextRange().handle()];
1528 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
1530 DOM::DocumentImpl *document = _part->xmlDocImpl();
1531 DOM::DocumentFragmentImpl *fragment = static_cast<HTMLElementImpl *>(document->documentElement())->createContextualFragment(markupString);
1534 if ([baseURLString length] > 0) {
1535 DOM::DOMString baseURL = baseURLString;
1536 if (baseURL != document->baseURL()) {
1537 fragment->recursive_completeURLs(baseURL.string());
1540 return [DOMDocumentFragment _documentFragmentWithImpl:fragment];
1543 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
1545 if (!_part || !_part->xmlDocImpl() || !text)
1548 return [DOMDocumentFragment _documentFragmentWithImpl:_part->documentFragmentWithText(text)];
1551 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1553 if (!_part || !_part->xmlDocImpl() || !fragment)
1556 EditCommandPtr(new ReplaceSelectionCommand(_part->xmlDocImpl(), [fragment _fragmentImpl], selectReplacement, smartReplace)).apply();
1557 [self ensureSelectionVisible];
1560 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1562 DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
1563 [fragment appendChild:node];
1564 [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace];
1567 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1569 DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1570 [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace];
1573 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1575 [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace];
1578 - (void)insertLineBreak
1580 if (!_part || !_part->xmlDocImpl())
1583 TypingCommand::insertLineBreak(_part->xmlDocImpl());
1584 [self ensureSelectionVisible];
1587 - (void)insertParagraphSeparator
1589 if (!_part || !_part->xmlDocImpl())
1592 TypingCommand::insertParagraphSeparator(_part->xmlDocImpl());
1593 [self ensureSelectionVisible];
1596 - (void)insertParagraphSeparatorInQuotedContent
1598 if (!_part || !_part->xmlDocImpl())
1601 Selection selection(_part->selection());
1602 if (selection.isNone())
1605 TypingCommand::insertParagraphSeparatorInQuotedContent(_part->xmlDocImpl());
1606 [self ensureSelectionVisible];
1609 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
1611 if (!_part || !_part->xmlDocImpl())
1614 TypingCommand::insertText(_part->xmlDocImpl(), text, selectInsertedText);
1615 [self ensureSelectionVisible];
1618 - (void)setSelectionToDragCaret
1620 _part->setSelection(_part->dragCaret());
1623 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
1625 Position base = _part->dragCaret().base();
1626 EditCommandPtr(new MoveSelectionCommand(_part->xmlDocImpl(), [selectionFragment _fragmentImpl], base, smartMove)).apply();
1629 - (Position)_positionForPoint:(NSPoint)point
1631 RenderObject *renderer = _part->renderer();
1636 RenderObject::NodeInfo nodeInfo(true, true);
1637 renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
1638 NodeImpl *node = nodeInfo.innerNode();
1639 if (!node->renderer())
1641 return node->renderer()->positionForCoordinates((int)point.x, (int)point.y);
1644 - (void)moveDragCaretToPoint:(NSPoint)point
1646 Selection dragCaret([self _positionForPoint:point]);
1647 _part->setDragCaret(dragCaret);
1650 - (void)removeDragCaret
1652 _part->setDragCaret(Selection());
1655 - (DOMRange *)dragCaretDOMRange
1657 return [DOMRange _rangeWithImpl:_part->dragCaret().toRange().handle()];
1660 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
1662 Position position = [self _positionForPoint:point];
1663 return position.isNull() ? nil : [DOMRange _rangeWithImpl:Selection(position).toRange().handle()];
1666 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
1668 if (!_part || !_part->xmlDocImpl())
1671 Selection selection(_part->selection());
1672 if (!selection.isRange())
1675 EditCommandPtr(new DeleteSelectionCommand(_part->xmlDocImpl(), smartDelete)).apply();
1678 - (void)deleteKeyPressed
1680 if (!_part || !_part->xmlDocImpl())
1683 TypingCommand::deleteKeyPressed(_part->xmlDocImpl());
1684 [self ensureSelectionVisible];
1687 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
1691 _part->applyStyle([style _styleDeclarationImpl]);
1694 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
1698 return _part->selectionStartHasStyle([style _styleDeclarationImpl]);
1701 - (void)applyEditingStyleToBodyElement
1705 _part->applyEditingStyleToBodyElement();
1708 - (void)removeEditingStyleFromBodyElement
1712 _part->removeEditingStyleFromBodyElement();
1715 - (void)applyEditingStyleToElement:(DOMElement *)element
1719 _part->applyEditingStyleToElement([element _elementImpl]);
1722 - (void)removeEditingStyleFromElement:(DOMElement *)element
1726 _part->removeEditingStyleFromElement([element _elementImpl]);
1729 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
1731 bool multipleFonts = false;
1734 font = _part->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
1735 if (hasMultipleFonts)
1736 *hasMultipleFonts = multipleFonts;
1740 - (NSDictionary *)fontAttributesForSelectionStart
1742 return _part ? _part->fontAttributesForSelectionStart() : nil;
1745 - (void)ensureSelectionVisible
1747 if (!_part || _part->selection().isNone())
1750 KHTMLView *v = _part->view();
1754 Position extent = _part->selection().extent();
1755 QRect extentRect = extent.node()->renderer()->caretRect(extent.offset(), _part->selection().affinity());
1756 if (!NSContainsRect([v->getDocumentView() visibleRect], NSRect(extentRect))) {
1757 v->ensureRectVisibleCentered(extentRect, true);
1761 // [info draggingLocation] is in window coords
1763 - (BOOL)eventMayStartDrag:(NSEvent *)event
1765 return _part ? _part->eventMayStartDrag(event) : NO;
1768 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
1770 NSDragOperation op = NSDragOperationNone;
1772 KHTMLView *v = _part->view();
1774 // Sending an event can result in the destruction of the view and part.
1777 KWQClipboard::AccessPolicy policy = _part->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
1778 KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
1780 NSDragOperation srcOp = [info draggingSourceOperationMask];
1781 clipboard->setSourceOperation(srcOp);
1783 if (v->updateDragAndDrop(QPoint([info draggingLocation]), clipboard)) {
1784 // *op unchanged if no source op was set
1785 if (!clipboard->destinationOperation(&op)) {
1786 // The element accepted but they didn't pick an operation, so we pick one for them
1788 if (srcOp & NSDragOperationCopy) {
1789 op = NSDragOperationCopy;
1790 } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
1791 op = NSDragOperationMove;
1792 } else if (srcOp & NSDragOperationLink) {
1793 op = NSDragOperationLink;
1795 op = NSDragOperationGeneric;
1797 } else if (!(op & srcOp)) {
1798 // make sure WC picked an op that was offered. Cocoa doesn't seem to enforce this,
1800 op = NSDragOperationNone;
1803 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
1813 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
1816 KHTMLView *v = _part->view();
1818 // Sending an event can result in the destruction of the view and part.
1821 KWQClipboard::AccessPolicy policy = _part->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
1822 KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
1824 clipboard->setSourceOperation([info draggingSourceOperationMask]);
1826 v->cancelDragAndDrop(QPoint([info draggingLocation]), clipboard);
1827 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
1835 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
1838 KHTMLView *v = _part->view();
1840 // Sending an event can result in the destruction of the view and part.
1843 KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], KWQClipboard::Readable);
1845 clipboard->setSourceOperation([info draggingSourceOperationMask]);
1847 BOOL result = v->performDragAndDrop(QPoint([info draggingLocation]), clipboard);
1848 clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
1859 - (void)dragSourceMovedTo:(NSPoint)windowLoc
1862 _part->dragSourceMovedTo(QPoint(windowLoc));
1866 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
1869 _part->dragSourceEndedAt(QPoint(windowLoc), operation);
1875 return _part->mayCut();
1878 - (BOOL)mayDHTMLCopy
1880 return _part->mayCopy();
1883 - (BOOL)mayDHTMLPaste
1885 return _part->mayPaste();
1890 return _part->tryCut();
1893 - (BOOL)tryDHTMLCopy
1895 return _part->tryCopy();
1898 - (BOOL)tryDHTMLPaste
1900 return _part->tryPaste();
1903 - (DOMRange *)rangeOfCharactersAroundCaret
1908 Selection selection(_part->selection());
1909 if (!selection.isCaret())
1912 VisiblePosition caret(selection.start());
1913 VisiblePosition next = caret.next();
1914 VisiblePosition previous = caret.previous();
1915 if (caret == next || caret == previous)
1918 return [DOMRange _rangeWithImpl:makeRange(previous, next).handle()];
1921 - (NSMutableDictionary *)dashboardRegions
1923 return _part->dashboardRegionsDictionary();
1928 @implementation WebCoreBridge (WebCoreBridgePrivate)
1930 - (RootObject *)executionContextForView:(NSView *)aView
1932 KWQKHTMLPart *part = [self part];
1933 RootObject *root = new RootObject(aView); // The root gets deleted by JavaScriptCore.
1934 root->setRootObjectImp(static_cast<ObjectImp *>(Window::retrieveWindow(part)));
1935 root->setInterpreter(KJSProxy::proxy(part)->interpreter());
1936 part->addPluginRootObject(root);