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