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