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