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