WebCore:
[WebKit-https.git] / WebCore / kwq / WebCoreBridge.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #import "WebCoreBridge.h"
27
28 #import "csshelper.h"
29 #import "dom2_eventsimpl.h"
30 #import "dom2_rangeimpl.h"
31 #import "dom2_viewsimpl.h"
32 #import "dom_docimpl.h"
33 #import "dom_node.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"
39 #import "htmlattrs.h"
40 #import "htmlediting.h"
41 #import "htmltags.h"
42 #import "khtml_part.h"
43 #import "khtmlview.h"
44 #import "kjs_proxy.h"
45 #import "kjs_window.h"
46 #import "loader.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"
53 #import "selection.h"
54 #import "visible_position.h"
55
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>
61
62 #import "KWQAssertions.h"
63 #import "KWQCharsets.h"
64 #import "KWQClipboard.h"
65 #import "KWQDOMNode.h"
66 #import "KWQEditCommand.h"
67 #import "KWQFont.h"
68 #import "KWQFoundationExtras.h"
69 #import "KWQFrame.h"
70 #import "KWQKHTMLPart.h"
71 #import "KWQLoader.h"
72 #import "KWQPageState.h"
73 #import "KWQRenderTreeDebug.h"
74 #import "KWQView.h"
75 #import "KWQPrinter.h"
76 #import "KWQAccObjectCache.h"
77
78 #import "DOMInternal.h"
79 #import "WebCoreImageRenderer.h"
80 #import "WebCoreTextRendererFactory.h"
81 #import "WebCoreViewFactory.h"
82 #import "WebCoreSettings.h"
83
84 @class NSView;
85
86 using DOM::AtomicString;
87 using DOM::DocumentFragmentImpl;
88 using DOM::DocumentImpl;
89 using DOM::DocumentTypeImpl;
90 using DOM::DOMString;
91 using DOM::Element;
92 using DOM::ElementImpl;
93 using DOM::HTMLElementImpl;
94 using DOM::HTMLFormElementImpl;
95 using DOM::HTMLGenericFormElementImpl;
96 using DOM::HTMLImageElementImpl;
97 using DOM::HTMLInputElementImpl;
98 using DOM::Node;
99 using DOM::NodeImpl;
100 using DOM::Position;
101 using DOM::Range;
102
103 using khtml::Decoder;
104 using khtml::DeleteSelectionCommand;
105 using khtml::EditCommandPtr;
106 using khtml::EditCommand;
107 using khtml::ETextGranularity;
108 using khtml::MoveSelectionCommand;
109 using khtml::parseURL;
110 using khtml::RenderCanvas;
111 using khtml::RenderImage;
112 using khtml::RenderObject;
113 using khtml::RenderPart;
114 using khtml::RenderStyle;
115 using khtml::RenderWidget;
116 using khtml::ReplaceSelectionCommand;
117 using khtml::Selection;
118 using khtml::TypingCommand;
119 using khtml::UPSTREAM;
120 using khtml::VisiblePosition;
121
122 using KJS::ExecState;
123 using KJS::ObjectImp;
124 using KJS::SavedProperties;
125 using KJS::SavedBuiltins;
126 using KJS::Window;
127
128 using KParts::URLArgs;
129
130 using KJS::Bindings::RootObject;
131
132 NSString *WebCoreElementDOMNodeKey =            @"WebElementDOMNode";
133 NSString *WebCoreElementFrameKey =              @"WebElementFrame";
134 NSString *WebCoreElementImageAltStringKey =     @"WebElementImageAltString";
135 NSString *WebCoreElementImageKey =              @"WebElementImage";
136 NSString *WebCoreElementImageRectKey =          @"WebElementImageRect";
137 NSString *WebCoreElementImageURLKey =           @"WebElementImageURL";
138 NSString *WebCoreElementIsSelectedKey =         @"WebElementIsSelected";
139 NSString *WebCoreElementLinkURLKey =            @"WebElementLinkURL";
140 NSString *WebCoreElementLinkTargetFrameKey =    @"WebElementTargetFrame";
141 NSString *WebCoreElementLinkLabelKey =          @"WebElementLinkLabel";
142 NSString *WebCoreElementLinkTitleKey =          @"WebElementLinkTitle";
143 NSString *WebCoreElementNameKey =               @"WebElementName";
144 NSString *WebCoreElementTitleKey =              @"WebCoreElementTitle"; // not in WebKit API for now, could be in API some day
145
146 NSString *WebCorePageCacheStateKey =            @"WebCorePageCacheState";
147
148 @interface WebCoreBridge (WebCoreBridgePrivate)
149 - (RootObject *)executionContextForView:(NSView *)aView;
150 @end
151
152 static RootObject *rootForView(void *v)
153 {
154     NSView *aView = (NSView *)v;
155     WebCoreBridge *aBridge = [[WebCoreViewFactory sharedFactory] bridgeForView:aView];
156
157     if (aBridge)
158         return [aBridge executionContextForView:aView];
159
160     return 0;
161 }
162
163 static pthread_t mainThread = 0;
164
165 static void updateRenderingForBindings (ExecState *exec, ObjectImp *rootObject)
166 {
167     if (pthread_self() != mainThread)
168         return;
169         
170     if (!rootObject)
171         return;
172         
173     Window *window = static_cast<Window*>(rootObject);
174     if (!window)
175         return;
176         
177     DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->part()->document().handle());
178     if (doc)
179         doc->updateRendering();
180 }
181
182
183 @implementation WebCoreBridge
184
185 static bool initializedObjectCacheSize = FALSE;
186 static bool initializedKJS = FALSE;
187
188 + (WebCoreBridge *)bridgeForDOMDocument:(DOMDocument *)document
189 {
190     return ((KWQKHTMLPart *)[document _documentImpl]->part())->bridge();
191 }
192
193 - init
194 {
195     [super init];
196     
197     _part = new KWQKHTMLPart;
198     _part->setBridge(self);
199
200     if (!initializedObjectCacheSize){
201         khtml::Cache::setSize([self getObjectCacheSize]);
202         initializedObjectCacheSize = TRUE;
203     }
204     
205     if (!initializedKJS) {
206         mainThread = pthread_self();
207         
208         RootObject::setFindRootObjectForNativeHandleFunction (rootForView);
209         
210         KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
211         
212         initializedKJS = TRUE;
213     }
214     
215     _shouldCreateRenderers = YES;
216     
217     return self;
218 }
219
220 - (void)initializeSettings: (WebCoreSettings *)settings
221 {
222     _part->setSettings ([settings settings]);
223 }
224
225 - (void)dealloc
226 {
227     [self removeFromFrame];
228     
229     if (_renderPart) {
230         _renderPart->deref(_renderPartArena);
231     }
232     _part->setBridge(nil);
233     _part->deref();
234         
235     [super dealloc];
236 }
237
238 - (void)finalize
239 {
240     // FIXME: This work really should not be done at deallocation time.
241     // We need to do it at some well-defined time instead.
242
243     [self removeFromFrame];
244     
245     if (_renderPart) {
246         _renderPart->deref(_renderPartArena);
247     }
248     _part->setBridge(nil);
249     _part->deref();
250         
251     [super finalize];
252 }
253
254 - (KWQKHTMLPart *)part
255 {
256     return _part;
257 }
258
259 - (void)setRenderPart:(KHTMLRenderPart *)newPart;
260 {
261     RenderArena *arena = newPart->ref();
262     if (_renderPart) {
263         _renderPart->deref(_renderPartArena);
264     }
265     _renderPart = newPart;
266     _renderPartArena = arena;
267 }
268
269 - (KHTMLRenderPart *)renderPart
270 {
271     return _renderPart;
272 }
273
274 - (void)setParent:(WebCoreBridge *)parent
275 {
276     _part->setParent([parent part]);
277 }
278
279 - (void)provisionalLoadStarted
280 {
281     _part->provisionalLoadStarted();
282 }
283
284 - (void)openURL:(NSURL *)URL reload:(BOOL)reload contentType:(NSString *)contentType refresh:(NSString *)refresh lastModified:(NSDate *)lastModified pageCache:(NSDictionary *)pageCache
285 {
286     if (pageCache) {
287         KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
288         _part->openURLFromPageCache(state);
289         [state invalidate];
290         return;
291     }
292         
293     // arguments
294     URLArgs args(_part->browserExtension()->urlArgs());
295     args.reload = reload;
296     if (contentType) {
297         args.serviceType = QString::fromNSString(contentType);
298     }
299     _part->browserExtension()->setURLArgs(args);
300
301     // opening the URL
302     if (_part->didOpenURL(URL)) {
303         // things we have to set up after calling didOpenURL
304         if (refresh) {
305             _part->addMetaData("http-refresh", QString::fromNSString(refresh));
306         }
307         if (lastModified) {
308             NSString *modifiedString = [lastModified descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
309             _part->addMetaData("modified", QString::fromNSString(modifiedString));
310         }
311     }
312 }
313
314 - (void)setEncoding:(NSString *)encoding userChosen:(BOOL)userChosen
315 {
316     _part->setEncoding(QString::fromNSString(encoding), userChosen);
317 }
318
319 - (void)addData:(NSData *)data
320 {
321     DocumentImpl *doc = _part->xmlDocImpl();
322     
323     // Document may be nil if the part is about to redirect
324     // as a result of JS executing during load, i.e. one frame
325     // changing another's location before the frame's document
326     // has been created. 
327     if (doc){
328         doc->setShouldCreateRenderers([self shouldCreateRenderers]);
329         _part->addData((const char *)[data bytes], [data length]);
330     }
331 }
332
333 - (void)closeURL
334 {
335     _part->closeURL();
336 }
337
338 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache
339 {
340     _part->didNotOpenURL(KURL(URL).url());
341
342     // We might have made a page cache item, but now we're bailing out due to an error before we ever
343     // transitioned to the new page (before WebFrameState==commit).  The goal here is to restore any state
344     // so that the existing view (that wenever got far enough to replace) can continue being used.
345     DocumentImpl *doc = _part->xmlDocImpl();
346     if (doc) {
347         doc->setInPageCache(NO);
348     }
349     KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
350     [state invalidate];
351 }
352
353 - (void)saveDocumentState
354 {
355     DocumentImpl *doc = _part->xmlDocImpl();
356     if (doc != 0){
357         QStringList list = doc->docState();
358         NSMutableArray *documentState = [[[NSMutableArray alloc] init] autorelease];
359         
360         for (uint i = 0; i < list.count(); i++){
361             QString s = list[i];
362             [documentState addObject: [NSString stringWithCharacters: (const unichar *)s.unicode() length: s.length()]];
363         }
364         [self saveDocumentState: documentState];
365     }
366 }
367
368 - (void)restoreDocumentState
369 {
370     DocumentImpl *doc = _part->xmlDocImpl();
371     
372     if (doc != 0){
373         NSArray *documentState = [self documentState];
374         
375         QStringList s;
376         for (uint i = 0; i < [documentState count]; i++){
377             NSString *string = [documentState objectAtIndex: i];
378             s.append(QString::fromNSString(string));
379         }
380             
381         doc->setRestoreState(s);
382     }
383 }
384
385 - (void)scrollToAnchorWithURL:(NSURL *)URL
386 {
387     _part->scrollToAnchor(KURL(URL).url().latin1());
388 }
389
390 - (BOOL)saveDocumentToPageCache
391 {
392     DocumentImpl *doc = _part->xmlDocImpl();
393     if (!doc) {
394         return NO;
395     }
396     
397     if (!doc->view()) {
398         return NO;
399     }
400     _part->clearTimers();
401
402     SavedProperties *windowProperties = new SavedProperties;
403     _part->saveWindowProperties(windowProperties);
404
405     SavedProperties *locationProperties = new SavedProperties;
406     _part->saveLocationProperties(locationProperties);
407     
408     SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
409     _part->saveInterpreterBuiltins(*interpreterBuiltins);
410
411     KWQPageState *pageState = [[[KWQPageState alloc] initWithDocument:doc
412                                                                   URL:_part->m_url
413                                                      windowProperties:windowProperties
414                                                    locationProperties:locationProperties
415                                                   interpreterBuiltins:interpreterBuiltins] autorelease];
416     [pageState setPausedActions: _part->pauseActions((const void *)pageState)];
417
418     return [self saveDocumentToPageCache:pageState];
419 }
420
421 - (BOOL)canCachePage
422 {
423     return _part->canCachePage();
424 }
425
426 - (void)end
427 {
428     _part->end();
429 }
430
431 - (void)createKHTMLViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
432 {
433     // If we own the view, delete the old one - otherwise the render _part will take care of deleting the view.
434     [self removeFromFrame];
435
436     KHTMLView *kview = new KHTMLView(_part, 0);
437     _part->setView(kview);
438     kview->deref();
439
440     kview->setView(view);
441     if (mw >= 0)
442         kview->setMarginWidth(mw);
443     if (mh >= 0)
444         kview->setMarginHeight(mh);
445 }
446
447 - (void)scrollToAnchor:(NSString *)a
448 {
449     _part->gotoAnchor(QString::fromNSString(a));
450 }
451
452 - (BOOL)isSelectionEditable
453 {
454     // EDIT FIXME: This needs to consider the entire selected range
455     NodeImpl *startNode = _part->selection().start().node();
456     return startNode ? startNode->isContentEditable() : NO;
457 }
458
459 - (WebSelectionState)selectionState
460 {
461     switch (_part->selection().state()) {
462         case Selection::NONE:
463             return WebSelectionStateNone;
464         case Selection::CARET:
465             return WebSelectionStateCaret;
466         case Selection::RANGE:
467             return WebSelectionStateRange;
468     }
469     
470     ASSERT_NOT_REACHED();
471     return WebSelectionStateNone;
472 }
473
474 - (NSString *)_documentTypeString
475 {
476     NSString *documentTypeString = nil;
477     DOM::DocumentImpl *doc = _part->xmlDocImpl();
478     if (doc) {
479         DocumentTypeImpl *doctype = doc->doctype();
480         if (doctype) {
481             documentTypeString = doctype->toString().string().getNSString();
482         }
483     }
484     return documentTypeString;
485 }
486
487 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
488 {
489     NSString *documentTypeString = [self _documentTypeString];
490     if (documentTypeString && markupString) {
491         return [NSString stringWithFormat:@"%@%@", documentTypeString, markupString];
492     } else if (documentTypeString) {
493         return documentTypeString;
494     } else if (markupString) {
495         return markupString;
496     } else {
497         return @"";
498     }
499 }
500
501 - (NSArray *)nodesFromList:(QPtrList<NodeImpl> *)nodeList
502 {
503     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
504     for (QPtrListIterator<NodeImpl> i(*nodeList); i.current(); ++i) {
505         [nodes addObject:[DOMNode _nodeWithImpl:i.current()]];
506     }
507     return nodes;
508 }
509
510 - (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
511 {
512     QPtrList<NodeImpl> *nodeList = NULL;
513     if (nodes) {
514         nodeList = new QPtrList<NodeImpl>;
515     }
516     NSString *markupString = [node _nodeImpl]->recursive_toHTML(false, nodeList).getNSString();
517     if (nodes) {
518         *nodes = [self nodesFromList:nodeList];
519         delete nodeList;
520     }
521     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
522 }
523
524 - (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
525 {
526     QPtrList<NodeImpl> *nodeList = NULL;
527     if (nodes) {
528         nodeList = new QPtrList<NodeImpl>;
529     }
530     NSString *markupString = [range _rangeImpl]->toHTML(nodeList).string().getNSString();
531     if (nodes) {
532         *nodes = [self nodesFromList:nodeList];
533         delete nodeList;
534     }
535     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
536 }
537
538 - (NSString *)selectedString
539 {
540     QString text = _part->selectedText();
541     text.replace('\\', _part->backslashAsCurrencySymbol());
542     return [[text.getNSString() copy] autorelease];
543 }
544
545 - (NSString *)stringForRange:(DOMRange *)range
546 {
547     QString text = _part->text([range _rangeImpl]);
548     text.replace('\\', _part->backslashAsCurrencySymbol());
549     return [[text.getNSString() copy] autorelease];
550 }
551
552 - (void)selectAll
553 {
554     _part->selectAll();
555 }
556
557 - (void)deselectAll
558 {
559     [self deselectText];
560     DocumentImpl *doc = _part->xmlDocImpl();
561     if (doc) {
562         doc->setFocusNode(0);
563     }
564 }
565
566 - (void)deselectText
567 {
568     _part->clearSelection();
569 }
570
571 - (BOOL)isFrameSet
572 {
573     return _part->isFrameSet();
574 }
575
576 - (NSString *)styleSheetForPrinting
577 {
578     if (!_part->settings()->shouldPrintBackgrounds()) {
579         return @"* { background-image: none !important; background-color: white !important;}";
580     }
581     return nil;
582 }
583
584 - (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
585 {
586     _part->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
587     DocumentImpl *doc = _part->xmlDocImpl();
588     if (doc) {
589         static QPaintDevice screen;
590         static QPrinter printer;
591         doc->setPaintDevice(deviceType == WebCoreDeviceScreen ? &screen : &printer);
592         if (deviceType != WebCoreDeviceScreen) {
593             doc->setPrintStyleSheet(QString::fromNSString([self styleSheetForPrinting]));
594         }
595     }
596     return _part->reparseConfiguration();
597 }
598
599 static BOOL nowPrinting(WebCoreBridge *self)
600 {
601     DocumentImpl *doc = self->_part->xmlDocImpl();
602     return doc && doc->paintDevice() && doc->paintDevice()->devType() == QInternal::Printer;
603 }
604
605 // Set or unset the printing mode in the view.  We only toy with this if we're printing.
606 - (void)_setupRootForPrinting:(BOOL)onOrOff
607 {
608     if (nowPrinting(self)) {
609         RenderCanvas *root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
610         if (root) {
611             root->setPrintingMode(onOrOff);
612         }
613     }
614 }
615
616 - (void)forceLayoutAdjustingViewSize:(BOOL)flag
617 {
618     [self _setupRootForPrinting:YES];
619     _part->forceLayout();
620     if (flag) {
621         [self adjustViewSize];
622     }
623     [self _setupRootForPrinting:NO];
624 }
625
626 - (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
627 {
628     [self _setupRootForPrinting:YES];
629     _part->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth);
630     if (flag) {
631         [self adjustViewSize];
632     }
633     [self _setupRootForPrinting:NO];
634 }
635
636 - (void)sendResizeEvent
637 {
638     _part->sendResizeEvent();
639 }
640
641 - (void)sendScrollEvent
642 {
643     _part->sendScrollEvent();
644 }
645
646 - (void)drawRect:(NSRect)rect withPainter:(QPainter *)p
647 {
648     [self _setupRootForPrinting:YES];
649     _part->paint(p, QRect(rect));
650     [self _setupRootForPrinting:NO];
651 }
652
653 - (void)drawRect:(NSRect)rect
654 {
655     QPainter painter(nowPrinting(self));
656     bool displaysWithFocusAttributes = _part->displaysWithFocusAttributes();
657     painter.setUsesInactiveTextBackgroundColor(!displaysWithFocusAttributes);
658     painter.setDrawsFocusRing(displaysWithFocusAttributes);
659     [self drawRect:rect withPainter:&painter];
660 }
661
662 // Used by pagination code called from AppKit when a standalone web page is printed.
663 - (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
664 {
665     [self _setupRootForPrinting:YES];
666     NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
667     if (printWidthScaleFactor == 0 || printHeight == 0)
668         return pages;
669         
670     if (!_part || !_part->xmlDocImpl() || !_part->view()) return pages;
671     RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
672     if (!root) return pages;
673     
674     KHTMLView* view = _part->view();
675     NSView* documentView = view->getDocumentView();
676     if (!documentView)
677         return pages;
678         
679     float currPageHeight = printHeight;
680     float docHeight = root->layer()->height();
681     float docWidth = root->layer()->width();
682     float printWidth = docWidth/printWidthScaleFactor;
683     
684     // We need to give the part the opportunity to adjust the page height at each step.
685     for (float i = 0; i < docHeight; i += currPageHeight) {
686         float proposedBottom = kMin(docHeight, i + printHeight);
687         _part->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
688         currPageHeight = kMax(1.0f, proposedBottom - i);
689         for (float j = 0; j < docWidth; j += printWidth) {
690             NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
691             [pages addObject: val];
692         }
693     }
694     [self _setupRootForPrinting:NO];
695     
696     return pages;
697 }
698
699 // This is to support the case where a webview is embedded in the view that's being printed
700 - (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
701 {
702     [self _setupRootForPrinting:YES];
703     _part->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
704     [self _setupRootForPrinting:NO];
705 }
706
707 - (NSObject *)copyDOMNode:(NodeImpl *)node copier:(id <WebCoreDOMTreeCopier>)copier
708 {
709     NSMutableArray *children = [[NSMutableArray alloc] init];
710     for (NodeImpl *child = node->firstChild(); child; child = child->nextSibling()) {
711         [children addObject:[self copyDOMNode:child copier:copier]];
712     }
713     NSObject *copiedNode = [copier nodeWithName:node->nodeName().string().getNSString()
714                                           value:node->nodeValue().string().getNSString()
715                                          source:node->recursive_toHTML(true).getNSString()
716                                        children:children];
717     [children release];
718     return copiedNode;
719 }
720
721 - (NSObject *)copyDOMTree:(id <WebCoreDOMTreeCopier>)copier
722 {
723     DocumentImpl *doc = _part->xmlDocImpl();
724     if (!doc) {
725         return nil;
726     }
727     return [self copyDOMNode:doc copier:copier];
728 }
729
730 - (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
731 {
732     NSMutableArray *children = [[NSMutableArray alloc] init];
733     for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
734         [children addObject:[self copyRenderNode:child copier:copier]];
735     }
736           
737     NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
738     
739     RenderPart *nodeRenderPart = dynamic_cast<RenderPart *>(node);
740     QWidget *widget = nodeRenderPart ? nodeRenderPart->widget() : 0;
741     NSView *view = widget ? widget->getView() : nil;
742     
743     int nx, ny;
744     node->absolutePosition(nx,ny);
745     NSObject *copiedNode = [copier nodeWithName:name
746                                        position:NSMakePoint(nx,ny)
747                                            rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
748                                            view:view
749                                        children:children];
750     
751     [name release];
752     [children release];
753     
754     return copiedNode;
755 }
756
757 - (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
758 {
759     RenderObject *renderer = _part->renderer();
760     if (!renderer) {
761         return nil;
762     }
763     return [self copyRenderNode:renderer copier:copier];
764 }
765
766 - (void)removeFromFrame
767 {
768     _part->setView(0);
769 }
770
771 - (void)installInFrame:(NSView *)view
772 {
773     // If this isn't the main frame, it must have a render _part set, or it
774     // won't ever get installed in the view hierarchy.
775     ASSERT(self == [self mainFrame] || _renderPart != nil);
776
777     _part->view()->setView(view);
778     if (_renderPart) {
779         _renderPart->setWidget(_part->view());
780         // Now the render part owns the view, so we don't any more.
781     }
782
783     _part->view()->initScrollBars();
784 }
785
786 - (void)setActivationEventNumber:(int)num
787 {
788     _part->setActivationEventNumber(num);
789 }
790
791 - (void)mouseDown:(NSEvent *)event
792 {
793     _part->mouseDown(event);
794 }
795
796 - (void)mouseDragged:(NSEvent *)event
797 {
798     _part->mouseDragged(event);
799 }
800
801 - (void)mouseUp:(NSEvent *)event
802 {
803     _part->mouseUp(event);
804 }
805
806 - (void)mouseMoved:(NSEvent *)event
807 {
808     _part->mouseMoved(event);
809 }
810
811 - (BOOL)sendContextMenuEvent:(NSEvent *)event
812 {
813     return _part->sendContextMenuEvent(event);
814 }
815
816 - (DOMElement *)elementForView:(NSView *)view
817 {
818     // FIXME: implemented currently for only a subset of the KWQ widgets
819     if ([view conformsToProtocol:@protocol(KWQWidgetHolder)]) {
820         NSView <KWQWidgetHolder> *widgetHolder = view;
821         QWidget *widget = [widgetHolder widget];
822         if (widget != nil) {
823             NodeImpl *node = static_cast<const RenderWidget *>(widget->eventFilterObject())->element();
824             return [DOMElement _elementWithImpl:static_cast<ElementImpl *>(node)];
825         }
826     }
827     return nil;
828 }
829
830 static NSView *viewForElement(ElementImpl *elementImpl)
831 {
832     RenderObject *renderer = elementImpl->renderer();
833     if (renderer && renderer->isWidget()) {
834         QWidget *widget = static_cast<const RenderWidget *>(renderer)->widget();
835         if (widget) {
836             widget->populate();
837             return widget->getView();
838         }
839     }
840     return nil;
841 }
842
843 static HTMLInputElementImpl *inputElementFromDOMElement(DOMElement *element)
844 {
845     NodeImpl *node = [element _nodeImpl];
846     if (node && idFromNode(node) == ID_INPUT) {
847         return static_cast<HTMLInputElementImpl *>(node);
848     }
849     return nil;
850 }
851
852 static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
853 {
854     NodeImpl *node = [element _nodeImpl];
855     if (node && idFromNode(node) == ID_FORM) {
856         return static_cast<HTMLFormElementImpl *>(node);
857     }
858     return nil;
859 }
860
861 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
862 {
863     HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
864     if (formElement) {
865         QPtrList<HTMLGenericFormElementImpl> elements = formElement->formElements;
866         QString targetName = QString::fromNSString(name);
867         for (unsigned int i = 0; i < elements.count(); i++) {
868             HTMLGenericFormElementImpl *elt = elements.at(i);
869             // Skip option elements, other duds
870             if (elt->name() == targetName) {
871                 return [DOMElement _elementWithImpl:elt];
872             }
873         }
874     }
875     return nil;
876 }
877
878 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
879 {
880     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
881     return inputElement != nil
882         && inputElement->inputType() == HTMLInputElementImpl::TEXT
883         && inputElement->autoComplete();
884 }
885
886 - (BOOL)elementIsPassword:(DOMElement *)element
887 {
888     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
889     return inputElement != nil
890         && inputElement->inputType() == HTMLInputElementImpl::PASSWORD;
891 }
892
893 - (DOMElement *)formForElement:(DOMElement *)element;
894 {
895     HTMLInputElementImpl *inputElement = inputElementFromDOMElement(element);
896     if (inputElement) {
897         HTMLFormElementImpl *formElement = inputElement->form();
898         if (formElement) {
899             return [DOMElement _elementWithImpl:formElement];
900         }
901     }
902     return nil;
903 }
904
905 - (DOMElement *)currentForm
906 {
907     HTMLFormElementImpl *formElement = _part->currentForm();
908     return formElement ? [DOMElement _elementWithImpl:formElement] : nil;
909 }
910
911 - (NSArray *)controlsInForm:(DOMElement *)form
912 {
913     NSMutableArray *results = nil;
914     HTMLFormElementImpl *formElement = formElementFromDOMElement(form);
915     if (formElement) {
916         QPtrList<HTMLGenericFormElementImpl> elements = formElement->formElements;
917         for (unsigned int i = 0; i < elements.count(); i++) {
918             if (elements.at(i)->isEnumeratable()) {             // Skip option elements, other duds
919                 NSView *view = viewForElement(elements.at(i));
920                 if (view) {
921                     if (!results) {
922                         results = [NSMutableArray arrayWithObject:view];
923                     } else {
924                         [results addObject:view];
925                     }
926                 }
927             }
928         }
929     }
930     return results;
931 }
932
933 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
934 {
935     return _part->searchForLabelsBeforeElement(labels, [element _elementImpl]);
936 }
937
938 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
939 {
940     return _part->matchLabelsAgainstElement(labels, [element _elementImpl]);
941 }
942
943 - (NSDictionary *)elementAtPoint:(NSPoint)point
944 {
945     RenderObject *renderer = _part->renderer();
946     if (!renderer) {
947         return nil;
948     }
949     RenderObject::NodeInfo nodeInfo(true, true);
950     renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
951     
952     NSMutableDictionary *element = [NSMutableDictionary dictionary];
953     [element setObject:[NSNumber numberWithBool:_part->isPointInsideSelection((int)point.x, (int)point.y)]
954                 forKey:WebCoreElementIsSelectedKey];
955     
956     // Find the title in the nearest enclosing DOM node.
957     // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
958     for (NodeImpl *titleNode = nodeInfo.innerNode(); titleNode; titleNode = titleNode->parentNode()) {
959         if (titleNode->isElementNode()) {
960             const AtomicString& title = static_cast<ElementImpl *>(titleNode)->getAttribute(ATTR_TITLE);
961             if (!title.isNull()) {
962                 // We found a node with a title.
963                 QString titleText = title.string();
964                 titleText.replace('\\', _part->backslashAsCurrencySymbol());
965                 [element setObject:titleText.getNSString() forKey:WebCoreElementTitleKey];
966                 break;
967             }
968         }
969     }
970
971     NodeImpl *URLNode = nodeInfo.URLElement();
972     if (URLNode) {
973         ElementImpl *e = static_cast<ElementImpl *>(URLNode);
974         
975         const AtomicString& title = e->getAttribute(ATTR_TITLE);
976         if (!title.isEmpty()) {
977             QString titleText = title.string();
978             titleText.replace('\\', _part->backslashAsCurrencySymbol());
979             [element setObject:titleText.getNSString() forKey:WebCoreElementLinkTitleKey];
980         }
981         
982         const AtomicString& link = e->getAttribute(ATTR_HREF);
983         if (!link.isNull()) {
984             if (e->firstChild()) {
985                 Range r(_part->document());
986                 r.setStartBefore(e->firstChild());
987                 r.setEndAfter(e->lastChild());
988                 QString t = _part->text(r);
989                 if (!t.isEmpty()) {
990                     [element setObject:t.getNSString() forKey:WebCoreElementLinkLabelKey];
991                 }
992             }
993             QString URLString = parseURL(link).string();
994             [element setObject:_part->xmlDocImpl()->completeURL(URLString).getNSString() forKey:WebCoreElementLinkURLKey];
995         }
996         
997         DOMString target = e->getAttribute(ATTR_TARGET);
998         if (target.isEmpty() && _part->xmlDocImpl()) {
999             target = _part->xmlDocImpl()->baseTarget();
1000         }
1001         if (!target.isEmpty()) {
1002             [element setObject:target.string().getNSString() forKey:WebCoreElementLinkTargetFrameKey];
1003         }
1004     }
1005
1006     NodeImpl *node = nodeInfo.innerNonSharedNode();
1007     if (node) {
1008         [element setObject:[DOMNode _nodeWithImpl:node] forKey:WebCoreElementDOMNodeKey];
1009     
1010         if (node->renderer() && node->renderer()->isImage()) {
1011             RenderImage *r = static_cast<RenderImage *>(node->renderer());
1012             NSImage *image = r->pixmap().image();
1013             // Only return image information if there is an image.
1014             if (image && !r->isDisplayingError()) {
1015                 [element setObject:r->pixmap().image() forKey:WebCoreElementImageKey];
1016             }
1017                 
1018             int x, y;
1019             if (r->absolutePosition(x, y)) {
1020                 NSValue *rect = [NSValue valueWithRect:NSMakeRect(x, y, r->contentWidth(), r->contentHeight())];
1021                 [element setObject:rect forKey:WebCoreElementImageRectKey];
1022             }
1023                 
1024             ElementImpl *i = static_cast<ElementImpl*>(node);
1025     
1026             // FIXME: Code copied from RenderImage::updateFromElement; should share.
1027             DOMString attr;
1028             if (idFromNode(i) == ID_OBJECT) {
1029                 attr = i->getAttribute(ATTR_DATA);
1030             } else {
1031                 attr = i->getAttribute(ATTR_SRC);
1032             }
1033             if (!attr.isEmpty()) {
1034                 QString URLString = parseURL(attr).string();
1035                 [element setObject:_part->xmlDocImpl()->completeURL(URLString).getNSString() forKey:WebCoreElementImageURLKey];
1036             }
1037             
1038             // FIXME: Code copied from RenderImage::updateFromElement; should share.
1039             DOMString alt;
1040             if (idFromNode(i) == ID_INPUT)
1041                 alt = static_cast<HTMLInputElementImpl *>(i)->altText();
1042             else if (idFromNode(i) == ID_IMG)
1043                 alt = static_cast<HTMLImageElementImpl *>(i)->altText();
1044             if (!alt.isNull()) {
1045                 QString altText = alt.string();
1046                 altText.replace('\\', _part->backslashAsCurrencySymbol());
1047                 [element setObject:altText.getNSString() forKey:WebCoreElementImageAltStringKey];
1048             }
1049         }
1050     }
1051     
1052     return element;
1053 }
1054
1055 - (NSURL *)URLWithAttributeString:(NSString *)string
1056 {
1057     DocumentImpl *doc = _part->xmlDocImpl();
1058     if (!doc) {
1059         return nil;
1060     }
1061     QString rel = parseURL(QString::fromNSString(string)).string();
1062     return KURL(doc->baseURL(), rel, doc->decoder() ? doc->decoder()->codec() : 0).getNSURL();
1063 }
1064
1065 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1066 {
1067     return _part->findString(string, forward, caseFlag, wrapFlag);
1068 }
1069
1070 - (void)jumpToSelection
1071 {
1072     _part->jumpToSelection();
1073 }
1074
1075 - (NSString *)advanceToNextMisspelling
1076 {
1077     return _part->advanceToNextMisspelling().getNSString();
1078 }
1079
1080 - (NSString *)advanceToNextMisspellingStartingJustBeforeSelection
1081 {
1082     return _part->advanceToNextMisspelling(true).getNSString();
1083 }
1084
1085 - (void)setTextSizeMultiplier:(float)multiplier
1086 {
1087     int newZoomFactor = (int)rint(multiplier * 100);
1088     if (_part->zoomFactor() == newZoomFactor) {
1089         return;
1090     }
1091     _part->setZoomFactor(newZoomFactor);
1092 }
1093
1094 - (CFStringEncoding)textEncoding
1095 {
1096     return KWQCFStringEncodingFromIANACharsetName(_part->encoding().latin1());
1097 }
1098
1099 - (NSView *)nextKeyView
1100 {
1101     DocumentImpl *doc = _part->xmlDocImpl();
1102     if (!doc) {
1103         return nil;
1104     }
1105     return _part->nextKeyView(doc->focusNode(), KWQSelectingNext);
1106 }
1107
1108 - (NSView *)previousKeyView
1109 {
1110     DocumentImpl *doc = _part->xmlDocImpl();
1111     if (!doc) {
1112         return nil;
1113     }
1114     return _part->nextKeyView(doc->focusNode(), KWQSelectingPrevious);
1115 }
1116
1117 - (NSView *)nextKeyViewInsideWebFrameViews
1118 {
1119     DocumentImpl *doc = _part->xmlDocImpl();
1120     if (!doc) {
1121         return nil;
1122     }
1123     
1124     return _part->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingNext);
1125 }
1126
1127 - (NSView *)previousKeyViewInsideWebFrameViews
1128 {
1129     DocumentImpl *doc = _part->xmlDocImpl();
1130     if (!doc) {
1131         return nil;
1132     }
1133
1134     return _part->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingPrevious);
1135 }
1136
1137 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
1138 {
1139     _part->createEmptyDocument();
1140     return _part->executeScript(QString::fromNSString(string), true).asString().getNSString();
1141 }
1142
1143 - (WebScriptObject *)windowScriptObject
1144 {
1145     return _part->windowScriptObject();
1146 }
1147
1148 - (NPObject *)windowScriptNPObject
1149 {
1150     return _part->windowScriptNPObject();
1151 }
1152
1153 - (DOMDocument *)DOMDocument
1154 {
1155     return [DOMDocument _documentWithImpl:_part->xmlDocImpl()];
1156 }
1157
1158 - (DOMHTMLElement *)frameElement
1159 {
1160     return (DOMHTMLElement *)[[self DOMDocument] _ownerElement];
1161 }
1162
1163 - (NSAttributedString *)selectedAttributedString
1164 {
1165     return _part->attributedString(_part->selectionStart(), _part->selectionStartOffset(), _part->selectionEnd(), _part->selectionEndOffset());
1166 }
1167
1168 - (NSAttributedString *)attributedStringFrom:(DOMNode *)start startOffset:(int)startOffset to:(DOMNode *)end endOffset:(int)endOffset
1169 {
1170     DOMNode *startNode = start;
1171     DOMNode *endNode = end;
1172     return _part->attributedString([startNode _nodeImpl], startOffset, [endNode _nodeImpl], endOffset);
1173 }
1174
1175 - (NSRect)selectionRect
1176 {
1177     return _part->selectionRect(); 
1178 }
1179
1180 - (NSRect)visibleSelectionRect
1181 {
1182     return _part->visibleSelectionRect(); 
1183 }
1184
1185 - (void)centerSelectionInVisibleArea
1186 {
1187     _part->centerSelectionInVisibleArea(); 
1188 }
1189
1190 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset
1191 {
1192     return [node _nodeImpl]->renderer()->caretRect(offset, true);
1193 }
1194
1195 - (NSImage *)selectionImage
1196 {
1197     return _part->selectionImage();
1198 }
1199
1200 - (void)setName:(NSString *)name
1201 {
1202     _part->KHTMLPart::setName(QString::fromNSString(name));
1203 }
1204
1205 - (NSString *)name
1206 {
1207     return _part->name().getNSString();
1208 }
1209
1210 - (NSURL *)URL
1211 {
1212     return _part->url().getNSURL();
1213 }
1214
1215 - (NSString *)referrer
1216 {
1217     return _part->referrer().getNSString();
1218 }
1219
1220 - (NSString *)domain
1221 {
1222     DocumentImpl *doc = _part->xmlDocImpl();
1223     if (doc && doc->isHTMLDocument()) {
1224         return doc->domain().string().getNSString();
1225     }
1226     return nil;
1227 }
1228
1229 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
1230 {
1231     if (textEncoding == kCFStringEncodingInvalidId || textEncoding == kCFStringEncodingISOLatin1) {
1232         textEncoding = kCFStringEncodingWindowsLatin1;
1233     }
1234     return QTextCodec(textEncoding).toUnicode((const char*)[data bytes], [data length]).getNSString();
1235 }
1236
1237 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1238 {
1239     CFStringEncoding textEncoding = KWQCFStringEncodingFromIANACharsetName([textEncodingName lossyCString]);
1240     return [WebCoreBridge stringWithData:data textEncoding:textEncoding];
1241 }
1242
1243 - (BOOL)needsLayout
1244 {
1245     RenderObject *renderer = _part->renderer();
1246     return renderer ? renderer->needsLayout() : false;
1247 }
1248
1249 - (void)setNeedsLayout
1250 {
1251     RenderObject *renderer = _part->renderer();
1252     if (renderer)
1253         renderer->setNeedsLayout(true);
1254 }
1255
1256 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1257 {
1258     return _part->keyEvent(event);
1259 }
1260
1261 - (NSString *)renderTreeAsExternalRepresentation
1262 {
1263     return externalRepresentation(_part->renderer()).getNSString();
1264 }
1265
1266 - (void)setSelectionFromNone
1267 {
1268     _part->setSelectionFromNone();
1269 }
1270
1271 - (void)setDisplaysWithFocusAttributes:(BOOL)flag
1272 {
1273     _part->setDisplaysWithFocusAttributes(flag);
1274 }
1275
1276 - (void)setShouldCreateRenderers:(BOOL)f
1277 {
1278     _shouldCreateRenderers = f;
1279 }
1280
1281 - (BOOL)shouldCreateRenderers
1282 {
1283     return _shouldCreateRenderers;
1284 }
1285
1286 - (int)numPendingOrLoadingRequests
1287 {
1288     DocumentImpl *doc = _part->xmlDocImpl();
1289     
1290     if (doc)
1291         return KWQNumberOfPendingOrLoadingRequests (doc->docLoader());
1292     return 0;
1293 }
1294
1295 - (NSColor *)bodyBackgroundColor
1296 {
1297     return _part->bodyBackgroundColor();
1298 }
1299
1300 - (NSColor *)selectionColor
1301 {
1302     RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
1303     if (root) {
1304         RenderStyle *pseudoStyle = root->getPseudoStyle(RenderStyle::SELECTION);
1305         if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) {
1306             return pseudoStyle->backgroundColor().getNSColor();
1307         }
1308     }
1309     return _part->displaysWithFocusAttributes() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1310 }
1311
1312 - (void)adjustViewSize
1313 {
1314     KHTMLView *view = _part->view();
1315     if (view)
1316         view->adjustViewSize();
1317 }
1318
1319 -(id)accessibilityTree
1320 {
1321     KWQAccObjectCache::enableAccessibility();
1322     if (!_part || !_part->xmlDocImpl()) return nil;
1323     RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
1324     if (!root) return nil;
1325     return _part->xmlDocImpl()->getOrCreateAccObjectCache()->accObject(root);
1326 }
1327
1328 - (void)setDrawsBackground:(BOOL)drawsBackground
1329 {
1330     if (_part && _part->view())
1331         _part->view()->setTransparent(!drawsBackground);
1332 }
1333
1334 - (void)undoEditing:(id)arg
1335 {
1336     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1337     
1338     EditCommandPtr cmd([arg impl]);
1339     cmd.unapply();
1340 }
1341
1342 - (void)redoEditing:(id)arg
1343 {
1344     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1345     
1346     EditCommandPtr cmd([arg impl]);
1347     cmd.reapply();
1348 }
1349
1350 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebSelectionGranularity)granularity
1351 {
1352     if (!_part)
1353         return nil;
1354         
1355     // NOTE: The enums *must* match the very similar ones declared in ktml_selection.h
1356     Selection selection(_part->selection());
1357     selection.expandUsingGranularity(static_cast<ETextGranularity>(granularity));
1358     return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1359 }
1360
1361 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
1362 {
1363     if (!_part)
1364         return nil;
1365         
1366     // NOTE: The enums *must* match the very similar ones declared in ktml_selection.h
1367     Selection selection(_part->selection());
1368     selection.modify(static_cast<Selection::EAlter>(alteration), 
1369                      static_cast<Selection::EDirection>(direction), 
1370                      static_cast<ETextGranularity>(granularity));
1371     return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1372 }
1373
1374 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
1375 {
1376     if (!_part)
1377         return;
1378         
1379     // NOTE: The enums *must* match the very similar ones declared in dom_selection.h
1380     Selection selection(_part->selection());
1381     selection.modify(static_cast<Selection::EAlter>(alteration), 
1382                      static_cast<Selection::EDirection>(direction), 
1383                      static_cast<ETextGranularity>(granularity));
1384
1385     // save vertical navigation x position if necessary; many types of motion blow it away
1386     int xPos = KHTMLPart::NoXPosForVerticalArrowNavigation;
1387     switch (granularity) {
1388         case WebSelectByLine:
1389         case WebSelectByParagraph:
1390             xPos = _part->xPosForVerticalArrowNavigation();
1391             break;
1392         case WebSelectByCharacter:
1393         case WebSelectByWord:
1394         case WebSelectToLineBoundary:
1395         case WebSelectToParagraphBoundary:
1396         case WebSelectToDocumentBoundary:
1397             break;
1398     }
1399
1400     
1401     // setting the selection always clears saved vertical navigation x position
1402     _part->setSelection(selection);
1403     
1404     // restore vertical navigation x position if necessary
1405     if (xPos != KHTMLPart::NoXPosForVerticalArrowNavigation)
1406         _part->setXPosForVerticalArrowNavigation(xPos);
1407
1408     [self ensureCaretVisible];
1409 }
1410
1411 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1412 {
1413     if (!_part)
1414         return nil;
1415         
1416     Selection selection(_part->selection());
1417     selection.modify(static_cast<Selection::EAlter>(alteration), static_cast<int>(verticalDistance));
1418     return [DOMRange _rangeWithImpl:selection.toRange().handle()];
1419 }
1420
1421 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1422 {
1423     if (!_part)
1424         return;
1425         
1426     Selection selection(_part->selection());
1427     selection.modify(static_cast<Selection::EAlter>(alteration), static_cast<int>(verticalDistance));
1428
1429     // setting the selection always clears saved vertical navigation x position, so preserve it
1430     int xPos = _part->xPosForVerticalArrowNavigation();
1431     _part->setSelection(selection);
1432     _part->setXPosForVerticalArrowNavigation(xPos);
1433
1434     [self ensureCaretVisible];
1435 }
1436
1437 - (WebSelectionGranularity)selectionGranularity
1438 {
1439     // NOTE: The enums *must* match the very similar ones declared in dom_selection.h
1440     return static_cast<WebSelectionGranularity>(_part->selectionGranularity());
1441 }
1442
1443 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
1444 {
1445     NodeImpl *startContainer = [[range startContainer] _nodeImpl];
1446     NodeImpl *endContainer = [[range endContainer] _nodeImpl];
1447     ASSERT(startContainer);
1448     ASSERT(endContainer);
1449     ASSERT(startContainer->getDocument());
1450     ASSERT(startContainer->getDocument() == endContainer->getDocument());
1451     
1452     _part->xmlDocImpl()->updateLayout();
1453
1454     // Work around bug where isRenderedContent returns false for <br> elements at the ends of lines.
1455     // If that bug wasn't an issue, we could just make the position from the range directly.
1456     Position start(startContainer, [range startOffset]);
1457     Position end(endContainer, [range endOffset]);
1458     start = VisiblePosition(start, UPSTREAM).deepEquivalent();
1459
1460     Selection selection(start, end);
1461     selection.setAffinity(static_cast<khtml::EAffinity>(selectionAffinity));
1462     _part->setSelection(selection);
1463 }
1464
1465 - (DOMRange *)selectedDOMRange
1466 {
1467     return [DOMRange _rangeWithImpl:_part->selection().toRange().handle()];
1468 }
1469
1470 - (NSSelectionAffinity)selectionAffinity
1471 {
1472     return static_cast<NSSelectionAffinity>(_part->selection().affinity());
1473 }
1474
1475 - (void)setMarkDOMRange:(DOMRange *)range
1476 {
1477     _part->setMark(Selection([range _rangeImpl]));
1478 }
1479
1480 - (DOMRange *)markDOMRange
1481 {
1482     return [DOMRange _rangeWithImpl:_part->mark().toRange().handle()];
1483 }
1484
1485 - (void)setMarkedTextDOMRange:(DOMRange *)range
1486 {
1487     _part->setMarkedTextRange([range _rangeImpl]);
1488 }
1489
1490 - (DOMRange *)markedTextDOMRange
1491 {
1492     return [DOMRange _rangeWithImpl:_part->markedTextRange().handle()];
1493 }
1494
1495 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
1496 {
1497     DOM::DocumentImpl *document = _part->xmlDocImpl();
1498     DOM::DocumentFragmentImpl *fragment = static_cast<HTMLElementImpl *>(document->documentElement())->createContextualFragment(markupString);
1499     ASSERT(fragment);
1500     
1501     if ([baseURLString length] > 0) {
1502         DOM::DOMString baseURL = baseURLString;
1503         if (baseURL != document->baseURL()) {
1504             fragment->recursive_completeURLs(baseURL.string());
1505         }
1506     }
1507     return [DOMDocumentFragment _documentFragmentWithImpl:fragment];
1508 }
1509
1510 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
1511 {
1512     if (!_part || !_part->xmlDocImpl() || !text)
1513         return 0;
1514
1515     return [DOMDocumentFragment _documentFragmentWithImpl:_part->documentFragmentWithText(text)];
1516 }
1517
1518 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1519 {
1520     if (!_part || !_part->xmlDocImpl() || !fragment)
1521         return;
1522     
1523     EditCommandPtr cmd(new ReplaceSelectionCommand(_part->xmlDocImpl(), [fragment _fragmentImpl], selectReplacement, smartReplace));
1524     cmd.apply();
1525     [self ensureCaretVisible];
1526 }
1527
1528 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1529 {
1530     DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
1531     [fragment appendChild:node];
1532     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace];
1533 }
1534
1535 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1536 {
1537     DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1538     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace];
1539 }
1540
1541 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1542 {
1543     [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace];
1544 }
1545
1546 - (void)insertNewline
1547 {
1548     if (!_part || !_part->xmlDocImpl())
1549         return;
1550     
1551     TypingCommand::insertNewline(_part->xmlDocImpl());
1552     [self ensureCaretVisible];
1553 }
1554
1555 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
1556 {
1557     if (!_part || !_part->xmlDocImpl())
1558         return;
1559     
1560     TypingCommand::insertText(_part->xmlDocImpl(), text, selectInsertedText);
1561     [self ensureCaretVisible];
1562 }
1563
1564 - (void)setSelectionToDragCaret
1565 {
1566     _part->setSelection(_part->dragCaret());
1567 }
1568
1569 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
1570 {
1571     Position base = _part->dragCaret().base();
1572     EditCommandPtr cmd(new MoveSelectionCommand(_part->xmlDocImpl(), [selectionFragment _fragmentImpl], base, smartMove));
1573     cmd.apply();
1574 }
1575
1576 - (Position)_positionForPoint:(NSPoint)point
1577 {
1578     RenderObject *renderer = _part->renderer();
1579     if (!renderer) {
1580         return Position();
1581     }
1582     
1583     RenderObject::NodeInfo nodeInfo(true, true);
1584     renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
1585     NodeImpl *node = nodeInfo.innerNode();
1586     return node->positionForCoordinates((int)point.x, (int)point.y);
1587 }
1588
1589 - (void)moveDragCaretToPoint:(NSPoint)point
1590 {    
1591     Selection dragCaret([self _positionForPoint:point]);
1592     _part->setDragCaret(dragCaret);
1593 }
1594
1595 - (void)removeDragCaret
1596 {
1597     _part->setDragCaret(Selection());
1598 }
1599
1600 - (DOMRange *)dragCaretDOMRange
1601 {
1602     return [DOMRange _rangeWithImpl:_part->dragCaret().toRange().handle()];
1603 }
1604
1605 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
1606 {
1607     Position position = [self _positionForPoint:point];
1608     return position.isNull() ? nil : [DOMRange _rangeWithImpl:Selection(position).toRange().handle()];
1609 }
1610
1611 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
1612 {
1613     if (!_part || !_part->xmlDocImpl())
1614         return;
1615     
1616     Selection selection(_part->selection());
1617     if (!selection.isRange())
1618         return;
1619     
1620     EditCommandPtr cmd(new DeleteSelectionCommand(_part->xmlDocImpl(), smartDelete));
1621     cmd.apply();
1622 }
1623
1624 - (void)deleteKeyPressed
1625 {
1626     if (!_part || !_part->xmlDocImpl())
1627         return;
1628     
1629     TypingCommand::deleteKeyPressed(_part->xmlDocImpl());
1630     [self ensureCaretVisible];
1631 }
1632
1633 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
1634 {
1635     if (!_part)
1636         return;
1637     _part->applyStyle([style _styleDeclarationImpl]);
1638 }
1639
1640 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
1641 {
1642     if (!_part)
1643         return NO;
1644     return _part->selectionStartHasStyle([style _styleDeclarationImpl]);
1645 }
1646
1647 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
1648 {
1649     bool multipleFonts = false;
1650     NSFont *font = nil;
1651     if (_part)
1652         font = _part->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
1653     if (hasMultipleFonts)
1654         *hasMultipleFonts = multipleFonts;
1655     return font;
1656 }
1657
1658 - (void)ensureCaretVisible
1659 {
1660     if (!_part || !_part->selection().isCaret())
1661         return;
1662     
1663     KHTMLView *v = _part->view();
1664     if (!v)
1665         return;
1666
1667     QRect r(_part->selection().caretRect());
1668     v->ensureVisible(r.right(), r.bottom());
1669     v->ensureVisible(r.left(), r.top());
1670 }
1671
1672 // [info draggingLocation] is in window coords
1673
1674 - (BOOL)eventMayStartDrag:(NSEvent *)event
1675 {
1676     return _part ? _part->eventMayStartDrag(event) : NO;
1677 }
1678
1679 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
1680 {
1681     NSDragOperation op = NSDragOperationNone;
1682     if (_part) {
1683         KHTMLView *v = _part->view();
1684         if (v) {
1685             // Sending an event can result in the destruction of the view and part.
1686             v->ref();
1687             
1688             KWQClipboard::AccessPolicy policy = _part->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
1689             KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
1690             clipboard->ref();
1691             NSDragOperation srcOp = [info draggingSourceOperationMask];
1692             clipboard->setSourceOperation(srcOp);
1693
1694             if (v->updateDragAndDrop(QPoint([info draggingLocation]), clipboard)) {
1695                 // *op unchanged if no source op was set
1696                 if (!clipboard->destinationOperation(&op)) {
1697                     // The element accepted but they didn't pick an operation, so we pick one for them
1698                     // (as does WinIE).
1699                     if (srcOp & NSDragOperationCopy) {
1700                         op = NSDragOperationCopy;
1701                     } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
1702                         op = NSDragOperationMove;
1703                     } else if (srcOp & NSDragOperationLink) {
1704                         op = NSDragOperationLink;
1705                     } else {
1706                         op = NSDragOperationGeneric;
1707                     }
1708                 } else if (!(op & srcOp)) {
1709                     // make sure WC picked an op that was offered.  Cocoa doesn't seem to enforce this,
1710                     // but IE does.
1711                     op = NSDragOperationNone;
1712                 }
1713             }
1714             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
1715
1716             clipboard->deref();
1717             v->deref();
1718             return op;
1719         }
1720     }
1721     return op;
1722 }
1723
1724 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
1725 {
1726     if (_part) {
1727         KHTMLView *v = _part->view();
1728         if (v) {
1729             // Sending an event can result in the destruction of the view and part.
1730             v->ref();
1731
1732             KWQClipboard::AccessPolicy policy = _part->baseURL().isLocalFile() ? KWQClipboard::Readable : KWQClipboard::TypesReadable;
1733             KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], policy);
1734             clipboard->ref();
1735             clipboard->setSourceOperation([info draggingSourceOperationMask]);
1736             
1737             v->cancelDragAndDrop(QPoint([info draggingLocation]), clipboard);
1738             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
1739
1740             clipboard->deref();
1741             v->deref();
1742         }
1743     }
1744 }
1745
1746 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
1747 {
1748     if (_part) {
1749         KHTMLView *v = _part->view();
1750         if (v) {
1751             // Sending an event can result in the destruction of the view and part.
1752             v->ref();
1753
1754             KWQClipboard *clipboard = new KWQClipboard(true, [info draggingPasteboard], KWQClipboard::Readable);
1755             clipboard->ref();
1756             clipboard->setSourceOperation([info draggingSourceOperationMask]);
1757
1758             BOOL result = v->performDragAndDrop(QPoint([info draggingLocation]), clipboard);
1759             clipboard->setAccessPolicy(KWQClipboard::Numb);    // invalidate clipboard here for security
1760
1761             clipboard->deref();
1762             v->deref();
1763
1764             return result;
1765         }
1766     }
1767     return NO;
1768 }
1769
1770 - (void)dragSourceMovedTo:(NSPoint)windowLoc
1771 {
1772     if (_part) {
1773         _part->dragSourceMovedTo(QPoint(windowLoc));
1774     }
1775 }
1776
1777 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
1778 {
1779     if (_part) {
1780         _part->dragSourceEndedAt(QPoint(windowLoc), operation);
1781     }
1782 }
1783
1784 - (BOOL)mayDHTMLCut
1785 {
1786     return _part->mayCut();
1787 }
1788
1789 - (BOOL)mayDHTMLCopy
1790 {
1791     return _part->mayCopy();
1792 }
1793
1794 - (BOOL)mayDHTMLPaste
1795 {
1796     return _part->mayPaste();
1797 }
1798
1799 - (BOOL)tryDHTMLCut
1800 {
1801     return _part->tryCut();
1802 }
1803
1804 - (BOOL)tryDHTMLCopy
1805 {
1806     return _part->tryCopy();
1807 }
1808
1809 - (BOOL)tryDHTMLPaste
1810 {
1811     return _part->tryPaste();
1812 }
1813
1814 - (DOMRange *)rangeOfCharactersAroundCaret
1815 {
1816     if (!_part)
1817         return nil;
1818         
1819     Selection selection(_part->selection());
1820     if (!selection.isCaret())
1821         return nil;
1822
1823     VisiblePosition caret(selection.start());
1824     VisiblePosition next = caret.next();
1825     VisiblePosition previous = caret.previous();
1826     if (caret == next || caret == previous)
1827         return nil;
1828
1829     return [DOMRange _rangeWithImpl:makeRange(previous, next).handle()];
1830 }
1831
1832 - (NSMutableDictionary *)dashboardRegions
1833 {
1834     return _part->dashboardRegionsDictionary();
1835 }
1836
1837 @end
1838
1839 @implementation WebCoreBridge (WebCoreBridgePrivate)
1840
1841 - (RootObject *)executionContextForView:(NSView *)aView
1842 {
1843     KWQKHTMLPart *part = [self part];
1844     RootObject *root = new RootObject(aView);    // The root gets deleted by JavaScriptCore.
1845     root->setRootObjectImp(static_cast<ObjectImp *>(Window::retrieveWindow(part)));
1846     root->setInterpreter(KJSProxy::proxy(part)->interpreter());
1847     part->addPluginRootObject(root);
1848     return root;
1849 }
1850 @end