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