a67cde7400a1f251fad2f2435d1267bca7ec71b0
[WebKit-https.git] / WebKit / WebView.subproj / WebView.m
1 /*      
2     WebView.m
3     Copyright 2001, 2002 Apple, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebViewInternal.h>
7
8 #import <WebKit/DOM.h>
9 #import <WebKit/WebAssertions.h>
10 #import <WebKit/WebBackForwardList.h>
11 #import <WebKit/WebBaseNetscapePluginView.h>
12 #import <WebKit/WebBridge.h>
13 #import <WebKit/WebControllerSets.h>
14 #import <WebKit/WebDataProtocol.h>
15 #import <WebKit/WebDataSourcePrivate.h>
16 #import <WebKit/WebDefaultEditingDelegate.h>
17 #import <WebKit/WebDefaultFrameLoadDelegate.h>
18 #import <WebKit/WebDefaultPolicyDelegate.h>
19 #import <WebKit/WebDefaultResourceLoadDelegate.h>
20 #import <WebKit/WebDefaultUIDelegate.h>
21 #import <WebKit/WebDocument.h>
22 #import <WebKit/WebDocumentInternal.h>
23 #import <WebKit/WebDynamicScrollBarsView.h>
24 #import <WebKit/WebDownload.h>
25 #import <WebKit/WebException.h>
26 #import <WebKit/WebFormDelegatePrivate.h>
27 #import <WebKit/WebFrameInternal.h>
28 #import <WebKit/WebFrameViewPrivate.h>
29 #import <WebKit/WebHistoryItemPrivate.h>
30 #import <WebKit/WebHTMLView.h>
31 #import <WebKit/WebIconDatabase.h>
32 #import <WebKit/WebKitErrors.h>
33 #import <WebKit/WebKitLogging.h>
34 #import <WebKit/WebKitStatisticsPrivate.h>
35 #import <WebKit/WebNSPasteboardExtras.h>
36 #import "WebNSPrintOperationExtras.h"
37 #import <WebKit/WebNSURLExtras.h>
38 #import <WebKit/WebNSViewExtras.h>
39 #import <WebKit/WebPluginDatabase.h>
40 #import <WebKit/WebPolicyDelegate.h>
41 #import <WebKit/WebPreferencesPrivate.h>
42 #import <WebKit/WebResourceLoadDelegate.h>
43 #import <WebKit/WebTextView.h>
44 #import <WebKit/WebTextRepresentation.h>
45 #import <WebKit/WebTextRenderer.h>
46 #import <WebKit/WebUIDelegate.h>
47 #import <WebKit/WebUIDelegatePrivate.h>
48
49 #import <WebCore/WebCoreEncodings.h>
50 #import <WebCore/WebCoreSettings.h>
51
52 #import <Foundation/NSData_NSURLExtras.h>
53 #import <Foundation/NSDictionary_NSURLExtras.h>
54 #import <Foundation/NSString_NSURLExtras.h>
55 #import <Foundation/NSURLConnection.h>
56 #import <Foundation/NSURLDownloadPrivate.h>
57 #import <Foundation/NSURLFileTypeMappings.h>
58 #import <Foundation/NSURLRequestPrivate.h>
59 #import <Foundation/NSUserDefaults_NSURLExtras.h>
60
61 NSString *WebElementFrameKey =              @"WebElementFrame";
62 NSString *WebElementImageKey =              @"WebElementImage";
63 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
64 NSString *WebElementImageRectKey =          @"WebElementImageRect";
65 NSString *WebElementImageURLKey =           @"WebElementImageURL";
66 NSString *WebElementIsEditableKey =         @"WebElementIsEditable";
67 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
68 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
69 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
70 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
71 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
72
73 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
74 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
75 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
76
77 enum { WebViewVersion = 2 };
78
79
80 static NSMutableSet *schemesWithRepresentationsSet;
81
82 NSString *_WebCanGoBackKey =            @"canGoBack";
83 NSString *_WebCanGoForwardKey =         @"canGoForward";
84 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
85 NSString *_WebIsLoadingKey =            @"isLoading";
86 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
87 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
88 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
89
90 @interface WebProgressItem : NSObject
91 {
92 @public
93     long long bytesReceived;
94     long long estimatedLength;
95 }
96 @end
97
98 @implementation WebProgressItem
99 @end
100
101 @implementation WebViewPrivate
102
103 - init 
104 {
105     backForwardList = [[WebBackForwardList alloc] init];
106     textSizeMultiplier = 1;
107     progressNotificationInterval = 0.02;
108     progressNotificationTimeInterval = 0.1;
109     settings = [[WebCoreSettings alloc] init];
110
111     return self;
112 }
113
114 - (void)dealloc
115 {
116     ASSERT(!mainFrame);
117     
118     [backForwardList release];
119     [applicationNameForUserAgent release];
120     [userAgent release];
121     
122     [preferences release];
123     [settings release];
124     [hostWindow release];
125     
126     [policyDelegateForwarder release];
127     [resourceProgressDelegateForwarder release];
128     [UIDelegateForwarder release];
129     [frameLoadDelegateForwarder release];
130     [editingDelegateForwarder release];
131     
132     [progressItems release];
133     
134     [draggedTypes release];
135     
136     [super dealloc];
137 }
138
139 @end
140
141 @implementation WebView (WebPrivate)
142
143 + (NSArray *)_supportedMIMETypes
144 {
145     // Load the plug-in DB allowing plug-ins to install types.
146     [WebPluginDatabase installedPlugins];
147     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
148 }
149
150 + (NSArray *)_supportedFileExtensions
151 {
152     NSMutableSet *extensions = [[NSMutableSet alloc] init];
153     NSArray *MIMETypes = [self _supportedMIMETypes];
154     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
155     NSString *MIMEType;
156     NSURLFileTypeMappings *mappings = [NSURLFileTypeMappings sharedMappings];
157     while ((MIMEType = [enumerator nextObject]) != nil) {
158         NSArray *extensionsForType = [mappings extensionsForMIMEType:MIMEType];
159         if (extensionsForType) {
160             [extensions addObjectsFromArray:extensionsForType];
161         }
162     }
163     NSArray *uniqueExtensions = [extensions allObjects];
164     [extensions release];
165     return uniqueExtensions;
166 }
167
168 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
169 {
170     MIMEType = [MIMEType lowercaseString];
171     Class viewClass;
172     Class repClass;
173     
174     // Simple optimization that avoids loading the plug-in DB and image types for the HTML case.
175     if ([self canShowMIMETypeAsHTML:MIMEType]) {
176         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _web_objectForMIMEType:MIMEType];
177         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _web_objectForMIMEType:MIMEType];
178         if (viewClass && repClass) {
179             if (vClass) {
180                 *vClass = viewClass;
181             }
182             if (rClass) {
183                 *rClass = repClass;
184             }
185             return YES;
186         }
187     }
188     
189     // Load the plug-in DB allowing plug-ins to install types.
190     [[WebPluginDatabase installedPlugins] loadPluginIfNeededForMIMEType:MIMEType];
191     
192     // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
193     viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _web_objectForMIMEType:MIMEType];
194     repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _web_objectForMIMEType:MIMEType];
195     if (viewClass && repClass) {
196         // Special-case WebTextView for text types that shouldn't be shown.
197         if (viewClass == [WebTextView class] &&
198             repClass == [WebTextRepresentation class] &&
199             [[WebTextView unsupportedTextMIMETypes] containsObject:MIMEType]) {
200             return NO;
201         }
202         if (vClass) {
203             *vClass = viewClass;
204         }
205         if (rClass) {
206             *rClass = repClass;
207         }
208         return YES;
209     }
210     
211     return NO;
212 }
213
214 + (void)_setAlwaysUseATSU:(BOOL)f
215 {
216     [WebTextRenderer _setAlwaysUseATSU:f];
217 }
218
219 + (BOOL)canShowFile:(NSString *)path
220 {
221     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
222 }
223
224 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
225 {
226     return [[NSURLFileTypeMappings sharedMappings] preferredExtensionForMIMEType:type];
227 }
228
229 - (void)_close
230 {
231     if (_private->setName != nil) {
232         [WebViewSets removeWebView:self fromSetNamed:_private->setName];
233         [_private->setName release];
234         _private->setName = nil;
235     }
236
237     [_private->mainFrame _detachFromParent];
238     [_private->mainFrame release];
239     _private->mainFrame = nil;
240     
241     // Clear the page cache so we call destroy on all the plug-ins in the page cache to break any retain cycles.
242     // See comment in [WebHistoryItem _releaseAllPendingPageCaches] for more information.
243     [_private->backForwardList _clearPageCache];
244 }
245
246 - (WebFrame *)_createFrameNamed:(NSString *)fname inParent:(WebFrame *)parent allowsScrolling:(BOOL)allowsScrolling
247 {
248     WebFrameView *childView = [[WebFrameView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
249
250     [childView _setWebView:self];
251     [childView setAllowsScrolling:allowsScrolling];
252     
253     WebFrame *newFrame = [[WebFrame alloc] initWithName:fname webFrameView:childView webView:self];
254
255     [childView release];
256
257     [parent _addChild:newFrame];
258     
259     [newFrame release];
260         
261     return newFrame;
262 }
263
264 - (void)_finishedLoadingResourceFromDataSource: (WebDataSource *)dataSource
265 {
266     WebFrame *frame = [dataSource webFrame];
267     
268     ASSERT(dataSource != nil);
269     
270     // This resource has completed, so check if the load is complete for all frames.
271     if (frame != nil) {
272         [frame _transitionToLayoutAcceptable];
273         [frame _checkLoadComplete];
274     }
275 }
276
277 - (void)_mainReceivedBytesSoFar: (unsigned)bytesSoFar fromDataSource: (WebDataSource *)dataSource complete: (BOOL)isComplete
278 {
279     WebFrame *frame = [dataSource webFrame];
280     
281     ASSERT(dataSource != nil);
282
283     // The frame may be nil if a previously cancelled load is still making progress callbacks.
284     if (frame == nil)
285         return;
286         
287     // This resource has completed, so check if the load is complete for all frames.
288     if (isComplete){
289         // If the load is complete, mark the primary load as done.  The primary load is the load
290         // of the main document.  Other resources may still be arriving.
291         [dataSource _setPrimaryLoadComplete: YES];
292         [frame _checkLoadComplete];
293     }
294     else {
295         // If the frame isn't complete it might be ready for a layout.  Perform that check here.
296         // Note that transitioning a frame to this state doesn't guarantee a layout, rather it
297         // just indicates that an early layout can be performed.
298         int timedLayoutSize = [[WebPreferences standardPreferences] _initialTimedLayoutSize];
299         if ((int)bytesSoFar > timedLayoutSize)
300             [frame _transitionToLayoutAcceptable];
301     }
302 }
303
304 - (void)_receivedError: (NSError *)error fromDataSource: (WebDataSource *)dataSource
305 {
306     WebFrame *frame = [dataSource webFrame];
307
308     [frame _checkLoadComplete];
309 }
310
311
312 - (void)_mainReceivedError:(NSError *)error fromDataSource:(WebDataSource *)dataSource complete:(BOOL)isComplete
313 {
314     ASSERT(dataSource);
315 #ifndef NDEBUG
316     ASSERT([dataSource webFrame]);
317 #endif
318     
319     [dataSource _setMainDocumentError: error];
320
321     if (isComplete) {
322         [dataSource _setPrimaryLoadComplete:YES];
323         [[dataSource webFrame] _checkLoadComplete];
324     }
325 }
326
327 + (NSString *)_MIMETypeForFile:(NSString *)path
328 {
329     NSString *extension = [path pathExtension];
330     NSString *MIMEType = nil;
331
332     // FIXME: This is a workaround to make web archive files work with Foundations that
333     // are too old to know about web archive files. We should remove this before we ship.
334     if ([extension  _web_isCaseInsensitiveEqualToString:@"webarchive"]) {
335         return @"application/x-webarchive";
336     }
337     
338     // Get the MIME type from the extension.
339     if ([extension length] != 0) {
340         MIMEType = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:extension];
341     }
342
343     // If we can't get a known MIME type from the extension, sniff.
344     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
345         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
346         NSData *data = [handle readDataOfLength:GUESS_MIME_TYPE_PEEK_LENGTH];
347         [handle closeFile];
348         if ([data length] != 0) {
349             MIMEType = [data _web_guessedMIMEType];
350         }
351         if ([MIMEType length] == 0) {
352             MIMEType = @"application/octet-stream";
353         }
354     }
355
356     return MIMEType;
357 }
358
359 - (void)_downloadURL:(NSURL *)URL
360 {
361     [self _downloadURL:URL toDirectory:nil];
362 }
363
364 - (void)_downloadURL:(NSURL *)URL toDirectory:(NSString *)directory
365 {
366     ASSERT(URL);
367     
368     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
369     [WebDownload _downloadWithRequest:request
370                              delegate:_private->downloadDelegate
371                             directory:[directory isAbsolutePath] ? directory : nil];
372     [request release];
373 }
374
375 - (BOOL)defersCallbacks
376 {
377     return _private->defersCallbacks;
378 }
379
380 - (void)setDefersCallbacks:(BOOL)defers
381 {
382     if (defers == _private->defersCallbacks) {
383         return;
384     }
385
386     _private->defersCallbacks = defers;
387     [_private->mainFrame _defersCallbacksChanged];
388 }
389
390 - (void)_setTopLevelFrameName:(NSString *)name
391 {
392     [[self mainFrame] _setName:name];
393 }
394
395 - (WebFrame *)_findFrameInThisWindowNamed: (NSString *)name
396 {
397     return [[self mainFrame] _descendantFrameNamed:name];
398 }
399
400 - (WebFrame *)_findFrameNamed:(NSString *)name
401 {
402     // Try this WebView first.
403     WebFrame *frame = [self _findFrameInThisWindowNamed:name];
404
405     if (frame != nil) {
406         return frame;
407     }
408
409     // Try other WebViews in the same set
410     if (_private->setName != nil) {
411         NSEnumerator *enumerator = [WebViewSets webViewsInSetNamed:_private->setName];
412         WebView *webView;
413         while ((webView = [enumerator nextObject]) != nil && frame == nil) {
414             frame = [webView _findFrameInThisWindowNamed:name];
415         }
416     }
417
418     return frame;
419 }
420
421 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
422 {
423     id wd = [self UIDelegate];
424     WebView *newWindowWebView = nil;
425     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
426         newWindowWebView = [wd webView:self createWebViewWithRequest:request];
427     else {
428         newWindowWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:self createWebViewWithRequest: request];
429     }
430
431     [[newWindowWebView _UIDelegateForwarder] webViewShow: newWindowWebView];
432
433     return newWindowWebView;
434 }
435
436 - (NSMenu *)_menuForElement:(NSDictionary *)element
437 {
438     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate]
439           webView:self contextMenuItemsForElement:element defaultMenuItems:nil];
440     NSArray *menuItems = defaultMenuItems;
441     NSMenu *menu = nil;
442     unsigned i;
443
444     if (_private->UIDelegate) {
445         id cd = _private->UIDelegate;
446         
447         if ([cd respondsToSelector:@selector(webView:contextMenuItemsForElement:defaultMenuItems:)])
448             menuItems = [cd webView:self contextMenuItemsForElement:element defaultMenuItems:defaultMenuItems];
449     } 
450
451     if (menuItems && [menuItems count] > 0) {
452         menu = [[[NSMenu alloc] init] autorelease];
453
454         for (i=0; i<[menuItems count]; i++) {
455             [menu addItem:[menuItems objectAtIndex:i]];
456         }
457     }
458
459     return menu;
460 }
461
462 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(unsigned)modifierFlags
463 {
464     // When the mouse isn't over this view at all, we'll get called with a dictionary of nil over
465     // and over again. So it's a good idea to catch that here and not send multiple calls to the delegate
466     // for that case.
467     
468     if (dictionary && _private->lastElementWasNonNil) {
469         [[self _UIDelegateForwarder] webView:self mouseDidMoveOverElement:dictionary modifierFlags:modifierFlags];
470     }
471     _private->lastElementWasNonNil = dictionary != nil;
472 }
473
474 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)type
475 {
476     // We never go back/forward on a per-frame basis, so the target must be the main frame
477     //ASSERT([item target] == nil || [self _findFrameNamed:[item target]] == [self mainFrame]);
478
479     // abort any current load if we're going back/forward
480     [[self mainFrame] stopLoading];
481     [[self mainFrame] _goToItem:item withLoadType:type];
482 }
483
484 // Not used now, but could be if we ever store frames in bookmarks or history
485 - (void)_loadItem:(WebHistoryItem *)item
486 {
487     WebHistoryItem *newItem = [item copy];      // Makes a deep copy, happily
488     [[self backForwardList] addItem:newItem];
489     [self _goToItem:newItem withLoadType:WebFrameLoadTypeIndexedBackForward];
490 }
491
492 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
493 {
494     // It turns out the right combination of behavior is done with the back/forward load
495     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
496     // in the back forward list, and go to the current one.
497
498     WebBackForwardList *bfList = [self backForwardList];
499     ASSERT(![bfList currentItem]);      // destination list should be empty
500
501     WebBackForwardList *otherBFList = [otherView backForwardList];
502     if (![otherBFList currentItem]) {
503         return;         // empty back forward list, bail
504     }
505
506     WebHistoryItem *newItemToGoTo = nil;
507     int lastItemIndex = [otherBFList forwardListCount];
508     int i;
509     for (i = -[otherBFList backListCount]; i <= lastItemIndex; i++) {
510         if (i == 0) {
511             // If this item is showing , save away its current scroll and form state,
512             // since that might have changed since loading and it is normally not saved
513             // until we leave that page.
514             [[otherView mainFrame] _saveDocumentAndScrollState];
515         }
516         WebHistoryItem *newItem = [[otherBFList itemAtIndex:i] copy];
517         [bfList addItem:newItem];
518         if (i == 0) {
519             newItemToGoTo = newItem;
520         }
521     }
522     
523     [self _goToItem:newItemToGoTo withLoadType:WebFrameLoadTypeIndexedBackForward];
524 }
525
526 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
527 {
528     _private->formDelegate = delegate;
529 }
530
531 - (id<WebFormDelegate>)_formDelegate
532 {
533     if (!_private->formDelegate) {
534         // create lazily, to give the client a chance to set one before we bother to alloc the shared one
535         _private->formDelegate = [WebFormDelegate _sharedWebFormDelegate];
536     }
537     return _private->formDelegate;
538 }
539
540 - (WebCoreSettings *)_settings
541 {
542     return _private->settings;
543 }
544
545 - (void)_updateWebCoreSettingsFromPreferences: (WebPreferences *)preferences
546 {
547     [_private->settings setCursiveFontFamily:[preferences cursiveFontFamily]];
548     [_private->settings setDefaultFixedFontSize:[preferences defaultFixedFontSize]];
549     [_private->settings setDefaultFontSize:[preferences defaultFontSize]];
550     [_private->settings setDefaultTextEncoding:[preferences defaultTextEncodingName]];
551     [_private->settings setFantasyFontFamily:[preferences fantasyFontFamily]];
552     [_private->settings setFixedFontFamily:[preferences fixedFontFamily]];
553     [_private->settings setJavaEnabled:[preferences isJavaEnabled]];
554     [_private->settings setJavaScriptEnabled:[preferences isJavaScriptEnabled]];
555     [_private->settings setJavaScriptCanOpenWindowsAutomatically:[preferences javaScriptCanOpenWindowsAutomatically]];
556     [_private->settings setMinimumFontSize:[preferences minimumFontSize]];
557     [_private->settings setMinimumLogicalFontSize:[preferences minimumLogicalFontSize]];
558     [_private->settings setPluginsEnabled:[preferences arePlugInsEnabled]];
559     [_private->settings setSansSerifFontFamily:[preferences sansSerifFontFamily]];
560     [_private->settings setSerifFontFamily:[preferences serifFontFamily]];
561     [_private->settings setStandardFontFamily:[preferences standardFontFamily]];
562     [_private->settings setWillLoadImagesAutomatically:[preferences loadsImagesAutomatically]];
563
564     if ([preferences userStyleSheetEnabled]) {
565         [_private->settings setUserStyleSheetLocation:[[preferences userStyleSheetLocation] _web_originalDataAsString]];
566     } else {
567         [_private->settings setUserStyleSheetLocation:@""];
568     }
569     [_private->settings setShouldPrintBackgrounds:[preferences shouldPrintBackgrounds]];
570 }
571
572 - (void)_preferencesChangedNotification: (NSNotification *)notification
573 {
574     WebPreferences *preferences = (WebPreferences *)[notification object];
575     
576     ASSERT(preferences == [self preferences]);
577     if (!_private->userAgentOverridden) {
578         [_private->userAgent release];
579         _private->userAgent = nil;
580     }
581     [self _updateWebCoreSettingsFromPreferences: preferences];
582 }
583
584 - _frameLoadDelegateForwarder
585 {
586     if (!_private->frameLoadDelegateForwarder)
587         _private->frameLoadDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self frameLoadDelegate]  defaultTarget: [WebDefaultFrameLoadDelegate sharedFrameLoadDelegate] templateClass: [WebDefaultFrameLoadDelegate class]];
588     return _private->frameLoadDelegateForwarder;
589 }
590
591 - _resourceLoadDelegateForwarder
592 {
593     if (!_private->resourceProgressDelegateForwarder)
594         _private->resourceProgressDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self resourceLoadDelegate] defaultTarget: [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] templateClass: [WebDefaultResourceLoadDelegate class]];
595     return _private->resourceProgressDelegateForwarder;
596 }
597
598 - (void)_cacheResourceLoadDelegateImplementations
599 {
600     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:)])
601         _private->resourceLoadDelegateImplementations.delegateImplementsDidCancelAuthenticationChallenge = YES;
602
603     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)])
604         _private->resourceLoadDelegateImplementations.delegateImplementsDidReceiveAuthenticationChallenge = YES;
605
606     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:didFinishLoadingFromDataSource:)])
607         _private->resourceLoadDelegateImplementations.delegateImplementsDidFinishLoadingFromDataSource = YES;
608     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:didReceiveContentLength:fromDataSource:)])
609         _private->resourceLoadDelegateImplementations.delegateImplementsDidReceiveContentLength = YES;
610     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:didReceiveResponse:fromDataSource:)])
611         _private->resourceLoadDelegateImplementations.delegateImplementsDidReceiveResponse = YES;
612     if ([[self resourceLoadDelegate] respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)])
613         _private->resourceLoadDelegateImplementations.delegateImplementsWillSendRequest = YES;
614     if ([[self resourceLoadDelegate] respondsToSelector: @selector(webView:identifierForInitialRequest:fromDataSource:)])
615         _private->resourceLoadDelegateImplementations.delegateImplementsIdentifierForRequest = YES;
616 }
617
618 - (WebResourceDelegateImplementationCache)_resourceLoadDelegateImplementations
619 {
620     return _private->resourceLoadDelegateImplementations;
621 }
622
623 - _policyDelegateForwarder
624 {
625     if (!_private->policyDelegateForwarder)
626         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self policyDelegate] defaultTarget: [WebDefaultPolicyDelegate sharedPolicyDelegate] templateClass: [WebDefaultPolicyDelegate class]];
627     return _private->policyDelegateForwarder;
628 }
629
630 - _UIDelegateForwarder
631 {
632     if (!_private->UIDelegateForwarder)
633         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self UIDelegate] defaultTarget: [WebDefaultUIDelegate sharedUIDelegate] templateClass: [WebDefaultUIDelegate class]];
634     return _private->UIDelegateForwarder;
635 }
636
637 - _editingDelegateForwarder
638 {
639     if (!_private->editingDelegateForwarder)
640         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self editingDelegate] defaultTarget: [WebDefaultEditingDelegate sharedEditingDelegate] templateClass: [WebDefaultEditingDelegate class]];
641     return _private->editingDelegateForwarder;
642 }
643
644
645 - (WebFrame *)_frameForDataSource: (WebDataSource *)dataSource fromFrame: (WebFrame *)frame
646 {
647     NSArray *frames;
648     int i, count;
649     WebFrame *result, *aFrame;
650
651     if ([frame dataSource] == dataSource)
652         return frame;
653
654     if ([frame provisionalDataSource] == dataSource)
655         return frame;
656
657     frames = [frame childFrames];
658     count = [frames count];
659     for (i = 0; i < count; i++){
660         aFrame = [frames objectAtIndex: i];
661         result = [self _frameForDataSource: dataSource fromFrame: aFrame];
662         if (result)
663             return result;
664     }
665
666     return nil;
667 }
668
669
670 - (WebFrame *)_frameForDataSource: (WebDataSource *)dataSource
671 {
672     WebFrame *frame = [self mainFrame];
673
674     return [self _frameForDataSource: dataSource fromFrame: frame];
675 }
676
677
678 - (WebFrame *)_frameForView: (WebFrameView *)aView fromFrame: (WebFrame *)frame
679 {
680     NSArray *frames;
681     int i, count;
682     WebFrame *result, *aFrame;
683
684     if ([frame frameView] == aView)
685         return frame;
686
687     frames = [frame childFrames];
688     count = [frames count];
689     for (i = 0; i < count; i++){
690         aFrame = [frames objectAtIndex: i];
691         result = [self _frameForView: aView fromFrame: aFrame];
692         if (result)
693             return result;
694     }
695
696     return nil;
697 }
698
699 - (WebFrame *)_frameForView: (WebFrameView *)aView
700 {
701     WebFrame *frame = [self mainFrame];
702
703     return [self _frameForView: aView fromFrame: frame];
704 }
705
706 - (void)_setDraggedTypes:(NSArray *)draggedTypes
707 {
708     [draggedTypes retain];
709     [_private->draggedTypes release];
710     _private->draggedTypes = draggedTypes;
711 }
712
713 - (void)unregisterDraggedTypes
714 {
715     [self _setDraggedTypes:nil];
716     [super unregisterDraggedTypes];
717 }
718
719 - (void)registerForDraggedTypes:(NSArray *)draggedTypes
720 {
721     [self _setDraggedTypes:draggedTypes];
722     [super registerForDraggedTypes:draggedTypes];
723 }
724
725 - (void)_registerDraggedTypes
726 {
727     [self registerForDraggedTypes:[NSPasteboard _web_dragTypesForURL]];
728 }
729
730 - (void)_closeWindow
731 {
732     [[self _UIDelegateForwarder] webViewClose:self];
733 }
734
735 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
736 {
737     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
738     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
739 }
740
741 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
742 {
743     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
744     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
745
746     // This is used to make _representationExistsForURLScheme faster.
747     // Without this set, we'd have to create the MIME type each time.
748     if (schemesWithRepresentationsSet == nil) {
749         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
750     }
751     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
752 }
753
754 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
755 {
756     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
757 }
758
759 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
760 {
761     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
762 }
763
764 + (BOOL)_canHandleRequest:(NSURLRequest *)request
765 {
766     if ([NSURLConnection canHandleRequest:request]) {
767         return YES;
768     }
769     
770     // We're always willing to load alternate content for unreachable URLs
771     if ([request _webDataRequestUnreachableURL]) {
772         return YES;
773     }
774
775     return [self _representationExistsForURLScheme:[[request URL] scheme]];
776 }
777
778 + (NSString *)_decodeData:(NSData *)data
779 {
780     return [WebCoreEncodings decodeData:data];
781 }
782
783 - (void)_pushPerformingProgrammaticFocus
784 {
785     _private->programmaticFocusCount++;
786 }
787
788 - (void)_popPerformingProgrammaticFocus
789 {
790     _private->programmaticFocusCount--;
791 }
792
793 - (BOOL)_isPerformingProgrammaticFocus
794 {
795     return _private->programmaticFocusCount != 0;
796 }
797
798 #define UnknownTotalBytes -1
799 #define WebProgressItemDefaultEstimatedLength 1024*16
800
801 - (void)_didChangeValueForKey: (NSString *)key
802 {
803     LOG (Bindings, "calling didChangeValueForKey: %@", key);
804     [self didChangeValueForKey: key];
805 }
806
807 - (void)_willChangeValueForKey: (NSString *)key
808 {
809     LOG (Bindings, "calling willChangeValueForKey: %@", key);
810     [self willChangeValueForKey: key];
811 }
812
813 // Always start progress at INITIAL_PROGRESS_VALUE so it appears progress indicators
814 // will immediately show some progress.  This helps provide feedback as soon as a load
815 // starts.
816 #define INITIAL_PROGRESS_VALUE 0.1
817
818 - (void)_resetProgress
819 {
820     [_private->progressItems release];
821     _private->progressItems = nil;
822     _private->totalPageAndResourceBytesToLoad = 0;
823     _private->totalBytesReceived = 0;
824     _private->progressValue = 0;
825     _private->lastNotifiedProgressValue = 0;
826     _private->lastNotifiedProgressTime = 0;
827     _private->finalProgressChangedSent = NO;
828     _private->numProgressTrackedFrames = 0;
829     [_private->orginatingProgressFrame release];
830     _private->orginatingProgressFrame = nil;
831 }
832 - (void)_progressStarted:(WebFrame *)frame
833 {
834     LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
835     [self _willChangeValueForKey: @"estimatedProgress"];
836     if (_private->numProgressTrackedFrames == 0 || _private->orginatingProgressFrame == frame){
837         [self _resetProgress];
838         _private->progressValue = INITIAL_PROGRESS_VALUE;
839         _private->orginatingProgressFrame = [frame retain];
840         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:self];
841     }
842     _private->numProgressTrackedFrames++;
843     [self _didChangeValueForKey: @"estimatedProgress"];
844 }
845
846 - (void)_finalProgressComplete
847 {
848     LOG (Progress, "");
849
850     // Before resetting progress value be sure to send client a least one notification
851     // with final progress value.
852     if (!_private->finalProgressChangedSent) {
853         _private->progressValue = 1;
854         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
855     }
856     
857     [self _resetProgress];
858     
859     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:self];
860 }
861
862 - (void)_progressCompleted:(WebFrame *)frame
863 {    
864     LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
865
866     if (_private->numProgressTrackedFrames <= 0)
867         return;
868
869     [self _willChangeValueForKey: @"estimatedProgress"];
870
871     _private->numProgressTrackedFrames--;
872     if (_private->numProgressTrackedFrames == 0 ||
873         (frame == _private->orginatingProgressFrame && _private->numProgressTrackedFrames != 0)){
874         [self _finalProgressComplete];
875     }
876     [self _didChangeValueForKey: @"estimatedProgress"];
877 }
878
879 - (void)_incrementProgressForConnectionDelegate:(id)connectionDelegate response:(NSURLResponse *)response;
880 {
881     if (!connectionDelegate)
882         return;
883
884     LOG (Progress, "_private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
885     
886     if (_private->numProgressTrackedFrames <= 0)
887         return;
888         
889     WebProgressItem *item = [[WebProgressItem alloc] init];
890
891     if (!item)
892         return;
893
894     long long length = [response expectedContentLength];
895     if (length < 0){
896         length = WebProgressItemDefaultEstimatedLength;
897     }
898     item->estimatedLength = length;
899     _private->totalPageAndResourceBytesToLoad += length;
900     
901     if (!_private->progressItems)
902         _private->progressItems = [[NSMutableDictionary alloc] init];
903         
904     [_private->progressItems _web_setObject:item forUncopiedKey:connectionDelegate];
905     [item release];
906 }
907
908 - (void)_incrementProgressForConnectionDelegate:(id)connectionDelegate data:(NSData *)data
909 {
910     if (!connectionDelegate)
911         return;
912
913     WebProgressItem *item = [_private->progressItems objectForKey:connectionDelegate];
914
915     if (!item)
916         return;
917
918     [self _willChangeValueForKey: @"estimatedProgress"];
919
920     unsigned bytesReceived = [data length];
921     double increment = 0, percentOfRemainingBytes;
922     long long remainingBytes, estimatedBytesForPendingRequests;
923
924     item->bytesReceived += bytesReceived;
925     if (item->bytesReceived > item->estimatedLength){
926         _private->totalPageAndResourceBytesToLoad += ((item->bytesReceived*2) - item->estimatedLength);
927         item->estimatedLength = item->bytesReceived*2;
928     }
929     
930     int numPendingOrLoadingRequests = [[self mainFrame] _numPendingOrLoadingRequests:YES];
931     estimatedBytesForPendingRequests = WebProgressItemDefaultEstimatedLength * numPendingOrLoadingRequests;
932     remainingBytes = ((_private->totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - _private->totalBytesReceived);
933     percentOfRemainingBytes = (double)bytesReceived / (double)remainingBytes;
934     increment = (1.0 - _private->progressValue) * percentOfRemainingBytes;
935     
936     _private->totalBytesReceived += bytesReceived;
937     
938     _private->progressValue += increment;
939
940     if (_private->progressValue < 0.0)
941         _private->progressValue = 0.0;
942
943     if (_private->progressValue > 1.0)
944         _private->progressValue = 1.0;
945
946     double now = CFAbsoluteTimeGetCurrent();
947     double notifiedProgressTimeDelta = CFAbsoluteTimeGetCurrent() - _private->lastNotifiedProgressTime;
948     _private->lastNotifiedProgressTime = now;
949     
950     LOG (Progress, "_private->progressValue %g, _private->numProgressTrackedFrames %d", _private->progressValue, _private->numProgressTrackedFrames);
951     double notificationProgressDelta = _private->progressValue - _private->lastNotifiedProgressValue;
952     if ((notificationProgressDelta >= _private->progressNotificationInterval ||
953             notifiedProgressTimeDelta >= _private->progressNotificationTimeInterval) &&
954             _private->numProgressTrackedFrames > 0) {
955         if (!_private->finalProgressChangedSent) {
956             if (_private->progressValue == 1)
957                 _private->finalProgressChangedSent = YES;
958             [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
959             _private->lastNotifiedProgressValue = _private->progressValue;
960         }
961     }
962
963     [self _didChangeValueForKey: @"estimatedProgress"];
964 }
965
966 - (void)_completeProgressForConnectionDelegate:(id)connectionDelegate
967 {
968     WebProgressItem *item = [_private->progressItems objectForKey:connectionDelegate];
969
970     if (!item)
971         return;
972         
973     // Adjust the total expected bytes to account for any overage/underage.
974     long long delta = item->bytesReceived - item->estimatedLength;
975     _private->totalPageAndResourceBytesToLoad += delta;
976     item->estimatedLength = item->bytesReceived;
977 }
978
979 // Required to prevent automatic observer notifications.
980 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
981     return NO;
982 }
983
984 - (NSArray *)_declaredKeys {
985     static NSArray *declaredKeys = nil;
986     
987     if (!declaredKeys) {
988         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, nil];
989     }
990
991     return declaredKeys;
992 }
993
994 - (void)setObservationInfo:(void *)info
995 {
996     _private->observationInfo = info;
997 }
998
999 - (void *)observationInfo
1000 {
1001     return _private->observationInfo;
1002 }
1003
1004 - (void)_willChangeBackForwardKeys
1005 {
1006     [self _willChangeValueForKey: _WebCanGoBackKey];
1007     [self _willChangeValueForKey: _WebCanGoForwardKey];
1008 }
1009
1010 - (void)_didChangeBackForwardKeys
1011 {
1012     [self _didChangeValueForKey: _WebCanGoBackKey];
1013     [self _didChangeValueForKey: _WebCanGoForwardKey];
1014 }
1015
1016 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1017 {
1018     [self _willChangeBackForwardKeys];
1019     if (frame == [self mainFrame]){
1020         // Force an observer update by sending a will/did.
1021         [self _willChangeValueForKey: _WebIsLoadingKey];
1022         [self _didChangeValueForKey: _WebIsLoadingKey];
1023
1024         [self _willChangeValueForKey: _WebMainFrameURLKey];
1025     }
1026     [NSApp setWindowsNeedUpdate:YES];
1027 }
1028
1029 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1030 {
1031     if (frame == [self mainFrame]){
1032         [self _didChangeValueForKey: _WebMainFrameURLKey];
1033     }
1034     [NSApp setWindowsNeedUpdate:YES];
1035 }
1036
1037 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1038 {
1039     [self _didChangeBackForwardKeys];
1040     if (frame == [self mainFrame]){
1041         // Force an observer update by sending a will/did.
1042         [self _willChangeValueForKey: _WebIsLoadingKey];
1043         [self _didChangeValueForKey: _WebIsLoadingKey];
1044     }
1045     [NSApp setWindowsNeedUpdate:YES];
1046 }
1047
1048 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1049 {
1050     [self _didChangeBackForwardKeys];
1051     if (frame == [self mainFrame]){
1052         // Force an observer update by sending a will/did.
1053         [self _willChangeValueForKey: _WebIsLoadingKey];
1054         [self _didChangeValueForKey: _WebIsLoadingKey];
1055     }
1056     [NSApp setWindowsNeedUpdate:YES];
1057 }
1058
1059 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1060 {
1061     [self _didChangeBackForwardKeys];
1062     if (frame == [self mainFrame]){
1063         // Force an observer update by sending a will/did.
1064         [self _willChangeValueForKey: _WebIsLoadingKey];
1065         [self _didChangeValueForKey: _WebIsLoadingKey];
1066         
1067         [self _didChangeValueForKey: _WebMainFrameURLKey];
1068     }
1069     [NSApp setWindowsNeedUpdate:YES];
1070 }
1071
1072 - (void)_reloadForPluginChanges
1073 {
1074     [[self mainFrame] _reloadForPluginChanges];
1075 }
1076
1077 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1078 {
1079     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1080     [request setHTTPUserAgent:[self userAgentForURL:URL]];
1081     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1082     [request release];
1083     return cachedResponse;
1084 }
1085
1086 @end
1087
1088
1089 @implementation _WebSafeForwarder
1090
1091 - initWithTarget: t defaultTarget: dt templateClass: (Class)aClass
1092 {
1093     [super init];
1094     target = t;         // Non retained.
1095     defaultTarget = dt;
1096     templateClass = aClass;
1097     return self;
1098 }
1099
1100
1101 // Used to send messages to delegates that implement informal protocols.
1102 + safeForwarderWithTarget: t defaultTarget: dt templateClass: (Class)aClass;
1103 {
1104     return [[[_WebSafeForwarder alloc] initWithTarget: t defaultTarget: dt templateClass: aClass] autorelease];
1105 }
1106
1107 #ifndef NDEBUG
1108 NSMutableDictionary *countInvocations;
1109 #endif
1110
1111 - (void)forwardInvocation:(NSInvocation *)anInvocation
1112 {
1113 #ifndef NDEBUG
1114     if (!countInvocations){
1115         countInvocations = [[NSMutableDictionary alloc] init];
1116     }
1117     NSNumber *count = [countInvocations objectForKey: NSStringFromSelector([anInvocation selector])];
1118     if (!count)
1119         count = [NSNumber numberWithInt: 1];
1120     else
1121         count = [NSNumber numberWithInt: [count intValue] + 1];
1122     [countInvocations setObject: count forKey: NSStringFromSelector([anInvocation selector])];
1123 #endif
1124     if ([target respondsToSelector: [anInvocation selector]])
1125         [anInvocation invokeWithTarget: target];
1126     else if ([defaultTarget respondsToSelector: [anInvocation selector]])
1127         [anInvocation invokeWithTarget: defaultTarget];
1128     // Do nothing quietly if method not implemented.
1129 }
1130
1131 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
1132 {
1133     return [templateClass instanceMethodSignatureForSelector: aSelector];
1134 }
1135
1136 @end
1137
1138 @interface WebView (WebInternal)
1139 - (BOOL)_isLoading;
1140 @end
1141
1142 @implementation WebView
1143
1144 + (BOOL)canShowMIMEType:(NSString *)MIMEType
1145 {
1146     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
1147 }
1148
1149 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
1150 {
1151     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
1152 }
1153
1154 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
1155 {
1156     _private->drawsBackground = YES;
1157
1158     NSRect f = [self frame];
1159     WebFrameView *wv = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
1160     [wv setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
1161     [self addSubview: wv];
1162     [wv release];
1163
1164     _private->mainFrame = [[WebFrame alloc] initWithName: frameName webFrameView: wv  webView: self];
1165     [self setGroupName:groupName];
1166     
1167     // If there's already a next key view (e.g., from a nib), wire it up to our
1168     // contained frame view. In any case, wire our next key view up to the our
1169     // contained frame view. This works together with our becomeFirstResponder 
1170     // and setNextKeyView overrides.
1171     NSView *nextKeyView = [self nextKeyView];
1172     if (nextKeyView != nil && nextKeyView != wv) {
1173         [wv setNextKeyView:nextKeyView];
1174     }
1175     [super setNextKeyView:wv];
1176
1177     ++WebViewCount;
1178
1179     [self _registerDraggedTypes];
1180
1181     // Update WebCore with preferences.  These values will either come from an archived WebPreferences,
1182     // or from the standard preferences, depending on whether this method was called from initWithCoder:
1183     // or initWithFrame, respectively.
1184     [self _updateWebCoreSettingsFromPreferences: [self preferences]];
1185     
1186     // Register to receive notifications whenever preference values change.
1187     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1188                                                  name:WebPreferencesChangedNotification object:[self preferences]];
1189 }
1190
1191 - init
1192 {
1193     return [self initWithFrame: NSZeroRect frameName: nil groupName: nil];
1194 }
1195
1196 - initWithFrame: (NSRect)f
1197 {
1198     [self initWithFrame: f frameName:nil groupName:nil];
1199     return self;
1200 }
1201
1202 - initWithFrame: (NSRect)f frameName: (NSString *)frameName groupName: (NSString *)groupName;
1203 {
1204     [super initWithFrame: f];
1205     _private = [[WebViewPrivate alloc] init];
1206     [self _commonInitializationWithFrameName:frameName groupName:groupName];
1207     [self setMaintainsBackForwardList: YES];
1208     return self;
1209 }
1210
1211 - (id)initWithCoder:(NSCoder *)decoder
1212 {
1213     WebView *result = nil;
1214
1215 NS_DURING
1216
1217     NSString *frameName;
1218     NSString *groupName;
1219     
1220     result = [super initWithCoder:decoder];
1221     result->_private = [[WebViewPrivate alloc] init];
1222     
1223     // We don't want any of the archived subviews.  The subviews will always
1224     // be created in _commonInitializationFrameName:groupName:.
1225     [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
1226     
1227     if ([decoder allowsKeyedCoding]){
1228         frameName = [decoder decodeObjectForKey:@"FrameName"];
1229         groupName = [decoder decodeObjectForKey:@"GroupName"];
1230                 
1231         [result setPreferences: [decoder decodeObjectForKey:@"Preferences"]];
1232         result->_private->useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
1233
1234         LOG (Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)_private->useBackForwardList);
1235     }
1236     else {
1237         int version;
1238     
1239         [decoder decodeValueOfObjCType:@encode(int) at:&version];
1240         frameName = [decoder decodeObject];
1241         groupName = [decoder decodeObject];
1242         [result setPreferences: [decoder decodeObject]];
1243         if (version > 1)
1244             [decoder decodeValuesOfObjCTypes:"c",&result->_private->useBackForwardList];
1245     }
1246     [result _commonInitializationWithFrameName:frameName groupName:groupName];
1247     
1248 NS_HANDLER
1249
1250     result = nil;
1251     [self release];
1252
1253 NS_ENDHANDLER
1254
1255     return result;
1256 }
1257
1258 - (void)encodeWithCoder:(NSCoder *)encoder
1259 {
1260     [super encodeWithCoder:encoder];
1261
1262     if ([encoder allowsKeyedCoding]){
1263         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
1264         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
1265         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
1266         [encoder encodeBool:_private->useBackForwardList forKey:@"UseBackForwardList"];
1267
1268         LOG (Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)_private->useBackForwardList);
1269     }
1270     else {
1271         int version = WebViewVersion;
1272         [encoder encodeValueOfObjCType:@encode(int) at:&version];
1273         [encoder encodeObject:[[self mainFrame] name]];
1274         [encoder encodeObject:[self groupName]];
1275         [encoder encodeObject:[self preferences]];
1276         [encoder encodeValuesOfObjCTypes:"c",&_private->useBackForwardList];
1277     }
1278 }
1279
1280 - (void)dealloc
1281 {
1282     [self _close];
1283     
1284     --WebViewCount;
1285     
1286     [[NSNotificationCenter defaultCenter] removeObserver:self];
1287     
1288     [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
1289     
1290     [_private release];
1291     // [super dealloc] can end up dispatching against _private (3466082)
1292     _private = nil;
1293
1294     [super dealloc];
1295 }
1296
1297 - (void)setPreferences: (WebPreferences *)prefs
1298 {
1299     if (_private->preferences != prefs){
1300         [[NSNotificationCenter defaultCenter] removeObserver: self name: WebPreferencesChangedNotification object: [self preferences]];
1301         [WebPreferences _removeReferenceForIdentifier: [_private->preferences identifier]];
1302         [_private->preferences release];
1303         _private->preferences = [prefs retain];
1304         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1305                                                     name:WebPreferencesChangedNotification object:[self preferences]];
1306     }
1307 }
1308
1309 - (WebPreferences *)preferences
1310 {
1311     return _private->preferences ? _private->preferences : [WebPreferences standardPreferences];
1312 }
1313
1314 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
1315 {
1316     if (![anIdentifier isEqual: [[self preferences] identifier]]){
1317         [self setPreferences: [[WebPreferences alloc] initWithIdentifier:anIdentifier]];
1318     }
1319 }
1320
1321 - (NSString *)preferencesIdentifier
1322 {
1323     return [[self preferences] identifier];
1324 }
1325
1326
1327 - (void)setUIDelegate:delegate
1328 {
1329     _private->UIDelegate = delegate;
1330     [_private->UIDelegateForwarder release];
1331     _private->UIDelegateForwarder = nil;
1332 }
1333
1334 - UIDelegate
1335 {
1336     return _private->UIDelegate;
1337 }
1338
1339 - (void)setResourceLoadDelegate: delegate
1340 {
1341     _private->resourceProgressDelegate = delegate;
1342     [_private->resourceProgressDelegateForwarder release];
1343     _private->resourceProgressDelegateForwarder = nil;
1344     [self _cacheResourceLoadDelegateImplementations];
1345 }
1346
1347
1348 - resourceLoadDelegate
1349 {
1350     return _private->resourceProgressDelegate;
1351 }
1352
1353
1354 - (void)setDownloadDelegate: delegate
1355 {
1356     _private->downloadDelegate = delegate;
1357 }
1358
1359
1360 - downloadDelegate
1361 {
1362     return _private->downloadDelegate;
1363 }
1364
1365 - (void)setPolicyDelegate:delegate
1366 {
1367     _private->policyDelegate = delegate;
1368     [_private->policyDelegateForwarder release];
1369     _private->policyDelegateForwarder = nil;
1370 }
1371
1372 - policyDelegate
1373 {
1374     return _private->policyDelegate;
1375 }
1376
1377 - (void)setFrameLoadDelegate:delegate
1378 {
1379     _private->frameLoadDelegate = delegate;
1380     [_private->frameLoadDelegateForwarder release];
1381     _private->frameLoadDelegateForwarder = nil;
1382 }
1383
1384 - frameLoadDelegate
1385 {
1386     return _private->frameLoadDelegate;
1387 }
1388
1389 - (WebFrame *)mainFrame
1390 {
1391     // This can be called in initialization, before _private has been set up (3465613)
1392     if (_private != nil) {
1393         return _private->mainFrame;
1394     }
1395     return nil;
1396 }
1397
1398 - (WebBackForwardList *)backForwardList
1399 {
1400     if (_private->useBackForwardList)
1401         return _private->backForwardList;
1402     return nil;
1403 }
1404
1405 - (void)setMaintainsBackForwardList: (BOOL)flag
1406 {
1407     _private->useBackForwardList = flag;
1408 }
1409
1410 - (BOOL)goBack
1411 {
1412     WebHistoryItem *item = [[self backForwardList] backItem];
1413     
1414     if (item){
1415         [self _goToItem: item withLoadType: WebFrameLoadTypeBack];
1416         return YES;
1417     }
1418     return NO;
1419 }
1420
1421 - (BOOL)goForward
1422 {
1423     WebHistoryItem *item = [[self backForwardList] forwardItem];
1424     
1425     if (item){
1426         [self _goToItem: item withLoadType: WebFrameLoadTypeForward];
1427         return YES;
1428     }
1429     return NO;
1430 }
1431
1432 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
1433 {
1434     [self _goToItem: item withLoadType: WebFrameLoadTypeIndexedBackForward];
1435     return YES;
1436 }
1437
1438 - (void)setTextSizeMultiplier:(float)m
1439 {
1440     if (_private->textSizeMultiplier == m) {
1441         return;
1442     }
1443     _private->textSizeMultiplier = m;
1444     [[self mainFrame] _textSizeMultiplierChanged];
1445 }
1446
1447 - (float)textSizeMultiplier
1448 {
1449     return _private->textSizeMultiplier;
1450 }
1451
1452 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
1453 {
1454     NSString *name = [applicationName copy];
1455     [_private->applicationNameForUserAgent release];
1456     _private->applicationNameForUserAgent = name;
1457     if (!_private->userAgentOverridden) {
1458         [_private->userAgent release];
1459         _private->userAgent = nil;
1460     }
1461 }
1462
1463 - (NSString *)applicationNameForUserAgent
1464 {
1465     return [[_private->applicationNameForUserAgent retain] autorelease];
1466 }
1467
1468 - (void)setCustomUserAgent:(NSString *)userAgentString
1469 {
1470     NSString *override = [userAgentString copy];
1471     [_private->userAgent release];
1472     _private->userAgent = override;
1473     _private->userAgentOverridden = override != nil;
1474 }
1475
1476 - (NSString *)customUserAgent
1477 {
1478     return _private->userAgentOverridden ? [[_private->userAgent retain] autorelease] : nil;
1479 }
1480
1481 - (BOOL)supportsTextEncoding
1482 {
1483     id documentView = [[[self mainFrame] frameView] documentView];
1484     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
1485         && [documentView supportsTextEncoding];
1486 }
1487
1488 - (void)setCustomTextEncodingName:(NSString *)encoding
1489 {
1490     NSString *oldEncoding = [self customTextEncodingName];
1491     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) {
1492         return;
1493     }
1494     [[self mainFrame] _reloadAllowingStaleDataWithOverrideEncoding:encoding];
1495 }
1496
1497 - (NSString *)_mainFrameOverrideEncoding
1498 {
1499     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
1500     if (dataSource == nil) {
1501         dataSource = [[self mainFrame] dataSource];
1502     }
1503     if (dataSource == nil) {
1504         return nil;
1505     }
1506     return [dataSource _overrideEncoding];
1507 }
1508
1509 - (NSString *)customTextEncodingName
1510 {
1511     return [self _mainFrameOverrideEncoding];
1512 }
1513
1514 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
1515 {
1516     return [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
1517 }
1518
1519 // Get the appropriate user-agent string for a particular URL.
1520 // Since we no longer automatically spoof, this no longer requires looking at the URL.
1521 - (NSString *)userAgentForURL:(NSURL *)URL
1522 {
1523     NSString *userAgent = _private->userAgent;
1524     if (userAgent) {
1525         return [[userAgent retain] autorelease];
1526     }
1527     
1528     // FIXME: Some day we will start reporting the actual CPU here instead of hardcoding PPC.
1529
1530     NSString *language = [NSUserDefaults _web_preferredLanguageCode];
1531     id sourceVersion = [[NSBundle bundleForClass:[WebView class]]
1532         objectForInfoDictionaryKey:(id)kCFBundleVersionKey];
1533     NSString *applicationName = _private->applicationNameForUserAgent;
1534
1535     if ([applicationName length]) {
1536         userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@",
1537             language, sourceVersion, applicationName];
1538     } else {
1539         userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)",
1540             language, sourceVersion];
1541     }
1542
1543     _private->userAgent = [userAgent retain];
1544     return userAgent;
1545 }
1546
1547 - (void)setHostWindow:(NSWindow *)hostWindow
1548 {
1549     if (hostWindow != _private->hostWindow) {
1550         [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
1551         [_private->hostWindow release];
1552         _private->hostWindow = [hostWindow retain];
1553         [[self mainFrame] _viewDidMoveToHostWindow];
1554     }
1555 }
1556
1557 - (NSWindow *)hostWindow
1558 {
1559     return _private->hostWindow;
1560 }
1561
1562 - (NSDragOperation)_dragOperationForDraggingInfo:(id <NSDraggingInfo>)sender
1563 {
1564     // Even though we may not be registered for any drag types, we may still get drag messages forwarded from WebHTMLView,
1565     // so compare the types on the pasteboard against the types we're currently registered for.
1566     if ([_private->draggedTypes count] > 0 && [[sender draggingPasteboard] availableTypeFromArray:_private->draggedTypes] != nil) {
1567         return  [self _web_dragOperationForDraggingInfo:sender];
1568     }
1569     return NSDragOperationNone;
1570 }
1571
1572 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1573 {
1574     return [self _dragOperationForDraggingInfo:sender];
1575 }
1576
1577 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1578 {
1579     NSPoint point = [[self superview] convertPoint:[sender draggingLocation] toView:nil];
1580     if ([[self hitTest:point] isKindOfClass:[WebBaseNetscapePluginView class]]) {
1581         return NSDragOperationNone;
1582     }
1583     return [self _dragOperationForDraggingInfo:sender];
1584 }
1585
1586 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1587 {
1588     return YES;
1589 }
1590
1591 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1592 {
1593     return YES;
1594 }
1595
1596 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
1597 {
1598     if ([self _dragOperationForDraggingInfo:sender] != NSDragOperationNone) {
1599         NSURL *URL = [[sender draggingPasteboard] _web_bestURL];
1600         if (URL) {
1601             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1602             [[self mainFrame] loadRequest:request];
1603             [request release];
1604         }
1605     }
1606 }
1607
1608 - (BOOL)acceptsFirstResponder
1609 {
1610     return [[[self mainFrame] frameView] acceptsFirstResponder];
1611 }
1612
1613 - (BOOL)becomeFirstResponder
1614 {
1615     // This works together with setNextKeyView to splice the WebView into
1616     // the key loop similar to the way NSScrollView does this. Note that
1617     // WebFrameView has very similar code.
1618     NSWindow *window = [self window];
1619     WebFrameView *mainFrameView = [[self mainFrame] frameView];
1620     
1621     if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
1622         NSView *previousValidKeyView = [self previousValidKeyView];
1623         if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
1624             [window makeFirstResponder:previousValidKeyView];
1625             return YES;
1626         } else {
1627             return NO;
1628         }
1629     }
1630     
1631     if ([mainFrameView acceptsFirstResponder]) {
1632         [window makeFirstResponder:mainFrameView];
1633         return YES;
1634     } 
1635     
1636     return NO;
1637 }
1638
1639 - (void)setNextKeyView:(NSView *)aView
1640 {
1641     // This works together with becomeFirstResponder to splice the WebView into
1642     // the key loop similar to the way NSScrollView does this. Note that
1643     // WebFrameView has very similar code.
1644     WebFrameView *mainFrameView = [[self mainFrame] frameView];
1645     if (mainFrameView != nil) {
1646         [mainFrameView setNextKeyView:aView];
1647     } else {
1648         [super setNextKeyView:aView];
1649     }
1650 }
1651
1652 // Return the frame holding first responder
1653 - (WebFrame *)_currentFrame
1654 {
1655     // Find the frame holding the first responder, or holding the first form in the doc
1656     NSResponder *resp = [[self window] firstResponder];
1657     if (!resp || ![resp isKindOfClass:[NSView class]] || ![(NSView *)resp isDescendantOf:self]) {
1658         return nil;     // first responder outside our view tree
1659     } else {
1660         WebFrameView *frameView = (WebFrameView *)[(NSView *)resp _web_superviewOfClass:[WebFrameView class]];
1661         return [frameView webFrame];
1662     }
1663 }
1664
1665 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
1666 {
1667     return forward ? [curr _nextFrameWithWrap:wrapFlag]
1668                    : [curr _previousFrameWithWrap:wrapFlag];
1669 }
1670
1671 // Search from the end of the currently selected location, or from the beginning of the
1672 // document if nothing is selected.  Deals with subframes.
1673 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1674 {
1675     // Get the frame holding the selection, or start with the main frame
1676     WebFrame *startFrame = [self _currentFrame];
1677     if (!startFrame) {
1678         startFrame = [self mainFrame];
1679     }
1680
1681     // Search the first frame, then all the other frames, in order
1682     NSView <WebDocumentSearching> *startSearchView = nil;
1683     BOOL startHasSelection = NO;
1684     WebFrame *frame = startFrame;
1685     do {
1686         id <WebDocumentView> view = [[frame frameView] documentView];
1687         if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
1688             NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
1689
1690             // first time through
1691             if (frame == startFrame) {
1692                 // Remember if start even has a selection, to know if we need to search more later
1693                 if ([searchView isKindOfClass:[WebHTMLView class]]) {
1694                     // optimization for the common case, to avoid making giant string for selection
1695                     startHasSelection = [[startFrame _bridge] selectionStart] != nil;
1696                 } else if ([searchView conformsToProtocol:@protocol(WebDocumentText)]) {
1697                     startHasSelection = [(id <WebDocumentText>)searchView selectedString] != nil;
1698                 }
1699                 startSearchView = searchView;
1700             }
1701             
1702             // Note at this point we are assuming the search will be done top-to-bottom,
1703             // not starting at any selection that exists.  See 3228554.
1704             BOOL success = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:NO];
1705             if (success) {
1706                 [[self window] makeFirstResponder:searchView];
1707                 return YES;
1708             }
1709         }
1710         frame = incrementFrame(frame, forward, wrapFlag);
1711     } while (frame != nil && frame != startFrame);
1712
1713     // Search contents of startFrame, on the other side of the selection that we did earlier.
1714     // We cheat a bit and just research with wrap on
1715     if (wrapFlag && startHasSelection && startSearchView) {
1716         BOOL success = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
1717         if (success) {
1718             [[self window] makeFirstResponder:startSearchView];
1719             return YES;
1720         }
1721     }
1722     return NO;
1723 }
1724
1725 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
1726 {
1727     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
1728     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
1729 }
1730
1731 - (void)setGroupName:(NSString *)groupName
1732 {
1733     if (groupName != _private->setName){
1734         [_private->setName release];
1735         _private->setName = [groupName copy];
1736         [WebViewSets addWebView:self toSetNamed:_private->setName];
1737     }
1738 }
1739
1740 - (NSString *)groupName
1741 {
1742     return _private->setName;
1743 }
1744
1745 - (double)estimatedProgress
1746 {
1747     return _private->progressValue;
1748 }
1749
1750 @end
1751
1752 @implementation WebView (WebIBActions)
1753
1754 - (IBAction)takeStringURLFrom: sender
1755 {
1756     NSString *URLString = [sender stringValue];
1757     
1758     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
1759 }
1760
1761 - (BOOL)canGoBack
1762 {
1763     return [[self backForwardList] backItem] != nil;
1764 }
1765
1766 - (BOOL)canGoForward
1767 {
1768     return [[self backForwardList] forwardItem] != nil;
1769 }
1770
1771 - (IBAction)goBack:(id)sender
1772 {
1773     [self goBack];
1774 }
1775
1776 - (IBAction)goForward:(id)sender
1777 {
1778     [self goForward];
1779 }
1780
1781 - (IBAction)stopLoading:(id)sender
1782 {
1783     [[self mainFrame] stopLoading];
1784 }
1785
1786 - (IBAction)reload:(id)sender
1787 {
1788     [[self mainFrame] reload];
1789 }
1790
1791 #define MinimumTextSizeMultiplier       0.5
1792 #define MaximumTextSizeMultiplier       3.0
1793 #define TextSizeMultiplierRatio         1.2
1794
1795 - (BOOL)canMakeTextSmaller
1796 {
1797     if ([[self mainFrame] dataSource] == nil) {
1798         return NO;
1799     }
1800     // FIXME: This will prevent text sizing in subframes if the main frame doesn't support it
1801     if (![[[[self mainFrame] frameView] documentView] conformsToProtocol:@protocol(_web_WebDocumentTextSizing)]) {
1802         return NO;
1803     }
1804     if ([self textSizeMultiplier]/TextSizeMultiplierRatio < MinimumTextSizeMultiplier) {
1805         return NO;
1806     }
1807     return YES;
1808 }
1809
1810 - (BOOL)canMakeTextLarger
1811 {
1812     if ([[self mainFrame] dataSource] == nil) {
1813         return NO;
1814     }
1815     // FIXME: This will prevent text sizing in subframes if the main frame doesn't support it
1816     if (![[[[self mainFrame] frameView] documentView] conformsToProtocol:@protocol(_web_WebDocumentTextSizing)]) {
1817         return NO;
1818     }
1819     if ([self textSizeMultiplier]*TextSizeMultiplierRatio > MaximumTextSizeMultiplier) {
1820         return NO;
1821     }
1822     return YES;
1823 }
1824
1825 - (IBAction)makeTextSmaller:(id)sender
1826 {
1827     if (![self canMakeTextSmaller]) {
1828         return;
1829     }
1830     [self setTextSizeMultiplier:[self textSizeMultiplier]/TextSizeMultiplierRatio];
1831 }
1832
1833 - (IBAction)makeTextLarger:(id)sender
1834 {
1835     if (![self canMakeTextLarger]) {
1836         return;
1837     }
1838     [self setTextSizeMultiplier:[self textSizeMultiplier]*TextSizeMultiplierRatio];
1839 }
1840
1841 - (BOOL)_isLoading
1842 {
1843     WebFrame *mainFrame = [self mainFrame];
1844     return [[mainFrame dataSource] isLoading]
1845         || [[mainFrame provisionalDataSource] isLoading];
1846 }
1847
1848 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
1849 {
1850     SEL action = [item action];
1851
1852     if (action == @selector(goBack:)) {
1853         return [self canGoBack];
1854     } else if (action == @selector(goForward:)) {
1855         return [self canGoForward];
1856     } else if (action == @selector(makeTextLarger:)) {
1857         return [self canMakeTextLarger];
1858     } else if (action == @selector(makeTextSmaller:)) {
1859         return [self canMakeTextSmaller];
1860     } else if (action == @selector(reload:)) {
1861         return [[self mainFrame] dataSource] != nil;
1862     } else if (action == @selector(stopLoading:)) {
1863         return [self _isLoading];
1864     }
1865
1866     return YES;
1867 }
1868
1869
1870 @end
1871
1872
1873 @implementation WebView (WebPendingPublic)
1874
1875 - (void)setMainFrameURL:(NSString *)URLString
1876 {
1877     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
1878 }
1879
1880 - (NSString *)mainFrameURL
1881 {
1882     WebDataSource *ds;
1883     ds = [[self mainFrame] provisionalDataSource];
1884     if (!ds)
1885         ds = [[self mainFrame] dataSource];
1886     return [[[ds request] URL] _web_originalDataAsString];
1887 }
1888
1889 - (BOOL)isLoading
1890 {
1891     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
1892     return [self _isLoading];
1893 }
1894
1895 - (NSString *)mainFrameTitle
1896 {
1897     NSString *mainFrameTitle = [[[self mainFrame] dataSource] pageTitle];
1898     return (mainFrameTitle != nil) ? mainFrameTitle : @"";
1899 }
1900
1901 - (NSImage *)mainFrameIcon
1902 {
1903     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
1904 }
1905
1906 - (void)setDrawsBackground:(BOOL)drawsBackground
1907 {
1908     if (_private->drawsBackground == drawsBackground)
1909         return;
1910     _private->drawsBackground = drawsBackground;
1911     [[self mainFrame] _updateDrawsBackground];
1912 }
1913
1914 - (BOOL)drawsBackground
1915 {
1916     return _private->drawsBackground;
1917 }
1918
1919 @end
1920
1921 @implementation WebView (WebViewPrintingPrivate)
1922
1923 - (float)_headerHeight
1924 {
1925     if ([[self UIDelegate] respondsToSelector:@selector(webViewHeaderHeight:)]) {
1926         return [[self UIDelegate] webViewHeaderHeight:self];
1927     }
1928     
1929 #ifdef DEBUG_HEADER_AND_FOOTER
1930     return 25;
1931 #else
1932     return 0;
1933 #endif
1934 }
1935
1936 - (float)_footerHeight
1937 {
1938     if ([[self UIDelegate] respondsToSelector:@selector(webViewFooterHeight:)]) {
1939         return [[self UIDelegate] webViewFooterHeight:self];
1940     }
1941     
1942 #ifdef DEBUG_HEADER_AND_FOOTER
1943     return 50;
1944 #else
1945     return 0;
1946 #endif
1947 }
1948
1949 - (void)_drawHeaderInRect:(NSRect)rect
1950 {
1951 #ifdef DEBUG_HEADER_AND_FOOTER
1952     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
1953     [currentContext saveGraphicsState];
1954     [[NSColor yellowColor] set];
1955     NSRectFill(rect);
1956     [currentContext restoreGraphicsState];
1957 #endif
1958     
1959     if ([[self UIDelegate] respondsToSelector:@selector(webView:drawHeaderInRect:)]) {
1960         NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
1961         [currentContext saveGraphicsState];
1962         NSRectClip(rect);
1963         [[self UIDelegate] webView:self drawHeaderInRect:rect]; 
1964         [currentContext restoreGraphicsState];
1965     }
1966 }
1967
1968 - (void)_drawFooterInRect:(NSRect)rect
1969 {
1970 #ifdef DEBUG_HEADER_AND_FOOTER
1971     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
1972     [currentContext saveGraphicsState];
1973     [[NSColor cyanColor] set];
1974     NSRectFill(rect);
1975     [currentContext restoreGraphicsState];
1976 #endif
1977     
1978     if ([[self UIDelegate] respondsToSelector:@selector(webView:drawFooterInRect:)]) {
1979         NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
1980         [currentContext saveGraphicsState];
1981         NSRectClip(rect);
1982         [[self UIDelegate] webView:self drawFooterInRect:rect];
1983         [currentContext restoreGraphicsState];
1984     }
1985 }
1986
1987 - (void)_adjustPrintingMarginsForHeaderAndFooter
1988 {
1989     NSPrintOperation *op = [NSPrintOperation currentOperation];
1990     NSPrintInfo *info = [op printInfo];
1991     float scale = [op _web_pageSetupScaleFactor];
1992     [info setTopMargin:[info topMargin] + [self _headerHeight]*scale];
1993     [info setBottomMargin:[info bottomMargin] + [self _footerHeight]*scale];
1994 }
1995
1996 - (void)_drawHeaderAndFooter
1997 {
1998     // The header and footer rect height scales with the page, but the width is always
1999     // all the way across the printed page (inset by printing margins).
2000     NSPrintOperation *op = [NSPrintOperation currentOperation];
2001     float scale = [op _web_pageSetupScaleFactor];
2002     NSPrintInfo *printInfo = [op printInfo];
2003     NSSize paperSize = [printInfo paperSize];
2004     float headerFooterLeft = [printInfo leftMargin]/scale;
2005     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
2006     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 
2007                                    headerFooterWidth, [self _footerHeight]);
2008     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 
2009                                    headerFooterWidth, [self _headerHeight]);
2010     
2011     [self _drawHeaderInRect:headerRect];
2012     [self _drawFooterInRect:footerRect];
2013 }
2014 @end
2015
2016 @implementation WebView (WebDebugBinding)
2017
2018 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
2019 {
2020     LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
2021     [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
2022 }
2023
2024 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
2025 {
2026     LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
2027     [super removeObserver:anObserver forKeyPath:keyPath];
2028 }
2029
2030 @end
2031
2032 //==========================================================================================
2033 // Editing
2034
2035 @interface WebView (WebViewEditingInternal)
2036
2037 - (void)_alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity;
2038 - (WebBridge *)_bridgeForCurrentSelection;
2039 - (BOOL)_currentSelectionIsEditable;
2040
2041 @end
2042
2043 @implementation WebView (WebViewEditingInternal)
2044
2045 - (void)_alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
2046 {
2047     WebBridge *bridge = [self _bridgeForCurrentSelection];
2048     DOMRange *proposedRange = [bridge rangeByAlteringCurrentSelection:alteration direction:direction granularity:granularity];
2049     if ([[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:[self selectedDOMRange] toDOMRange:proposedRange stillSelecting:NO]) {
2050         [bridge alterCurrentSelection:alteration direction:direction granularity:granularity];
2051     }
2052 }
2053
2054 - (WebBridge *)_bridgeForCurrentSelection
2055 {
2056     // FIXME: This needs to be changed to deal properly with subframes.
2057     return [[self mainFrame] _bridge];
2058 }
2059
2060 - (BOOL)_currentSelectionIsEditable
2061 {
2062     return [[self _bridgeForCurrentSelection] isSelectionEditable];
2063 }
2064
2065 @end
2066
2067 @implementation WebView (WebViewCSS)
2068
2069 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
2070 {
2071     ERROR("unimplemented");
2072     return nil;
2073 }
2074
2075 @end
2076
2077 @implementation WebView (WebViewEditing)
2078
2079 - (void)_editingKeyDown:(NSEvent *)event
2080 {
2081     [self interpretKeyEvents:[NSArray arrayWithObject:event]];
2082 }
2083
2084 - (void)setSelectedDOMRange:(DOMRange *)range
2085 {
2086     [[self _bridgeForCurrentSelection] setSelectedDOMRange:range];
2087 }
2088
2089 - (DOMRange *)selectedDOMRange
2090 {
2091     return [[self _bridgeForCurrentSelection] selectedDOMRange];
2092 }
2093
2094 - (void)setEditable:(BOOL)flag
2095 {
2096     _private->editable = flag;
2097 }
2098
2099 - (BOOL)isEditable
2100 {
2101     return _private->editable;
2102 }
2103
2104 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
2105 {
2106     ERROR("unimplemented");
2107 }
2108
2109 - (DOMCSSStyleDeclaration *)typingStyle
2110 {
2111     ERROR("unimplemented");
2112     return nil;
2113 }
2114
2115 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
2116 {
2117     ERROR("unimplemented");
2118 }
2119
2120 - (BOOL)smartInsertDeleteEnabled
2121 {
2122     ERROR("unimplemented");
2123     return NO;
2124 }
2125
2126 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
2127 {
2128     ERROR("unimplemented");
2129 }
2130
2131 - (BOOL)isContinuousSpellCheckingEnabled
2132 {
2133     ERROR("unimplemented");
2134     return NO;
2135 }
2136
2137 - (int)spellCheckerDocumentTag
2138 {
2139     ERROR("unimplemented");
2140     return 0;
2141 }
2142
2143 - (NSUndoManager *)undoManager
2144 {
2145     NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
2146     if (undoManager) {
2147         return undoManager;
2148     }
2149     return [super undoManager];
2150 }
2151
2152 - (void)setEditingDelegate:(id)delegate
2153 {
2154     _private->editingDelegate = delegate;
2155     [_private->editingDelegateForwarder release];
2156     _private->editingDelegateForwarder = nil;
2157 }
2158
2159 - (id)editingDelegate
2160 {
2161     return _private->editingDelegate;
2162 }
2163
2164 @end
2165
2166 @implementation WebView (WebViewUndoableEditing)
2167
2168 - (void)insertNode:(DOMNode *)node replacingDOMRange:(DOMRange *)range
2169 {
2170     if (!range)
2171         return;
2172         
2173     WebBridge *bridge = [self _bridgeForCurrentSelection];
2174     [bridge setSelectedDOMRange:range];
2175     [bridge replaceSelectionWithNode:node];
2176 }    
2177
2178 - (void)insertText:(NSString *)text replacingDOMRange:(DOMRange *)range
2179 {
2180     if (!range)
2181         return;
2182
2183     WebBridge *bridge = [self _bridgeForCurrentSelection];
2184     [bridge setSelectedDOMRange:range];
2185     [bridge replaceSelectionWithText:text];
2186 }
2187
2188 - (void)insertMarkupString:(NSString *)markupString replacingDOMRange:(DOMRange *)range
2189 {
2190     if (!range)
2191         return;
2192
2193     WebBridge *bridge = [self _bridgeForCurrentSelection];
2194     [bridge setSelectedDOMRange:range];
2195     [bridge replaceSelectionWithMarkupString:markupString];
2196 }
2197
2198 - (void)insertWebArchive:(WebArchive *)webArchive replacingDOMRange:(DOMRange *)range
2199 {
2200     if (!range)
2201         return;
2202
2203     WebBridge *bridge = [self _bridgeForCurrentSelection];
2204     [bridge setSelectedDOMRange:range];
2205     [bridge replaceSelectionWithWebArchive:webArchive];
2206 }
2207
2208 - (void)deleteDOMRange:(DOMRange *)range
2209 {
2210     if (!range)
2211         return;
2212
2213     WebBridge *bridge = [self _bridgeForCurrentSelection];
2214     [bridge setSelectedDOMRange:range];
2215     [bridge deleteSelection];
2216 }
2217     
2218 - (void)applyStyle:(DOMCSSStyleDeclaration *)style toElementsInDOMRange:(DOMRange *)range
2219 {
2220     if (!range)
2221         return;
2222
2223     WebBridge *bridge = [self _bridgeForCurrentSelection];
2224     [bridge setSelectedDOMRange:range];
2225     [bridge applyStyle:style toElementsInDOMRange:range];
2226 }
2227
2228 @end
2229
2230
2231 /*!
2232     @implementation WebView (WebViewEditingActions)
2233 */
2234 @implementation WebView (WebViewEditingActions)
2235
2236 - (void)centerSelectionInVisibleArea:(id)sender
2237 {
2238     if ([self _currentSelectionIsEditable]) {
2239         ERROR("unimplemented");
2240         return;
2241     }
2242     [[self nextResponder] tryToPerform:@selector(centerSelectionInVisibleArea:) with:sender];
2243 }
2244
2245 - (void)moveBackward:(id)sender
2246 {
2247     if ([self _currentSelectionIsEditable]) {
2248         ERROR("unimplemented");
2249         return;
2250     }
2251     [[self nextResponder] tryToPerform:@selector(moveBackward:) with:sender];
2252 }
2253
2254 - (void)moveBackwardAndModifySelection:(id)sender
2255 {
2256     if ([self _currentSelectionIsEditable]) {
2257         ERROR("unimplemented");
2258         return;
2259     }
2260     [[self nextResponder] tryToPerform:@selector(moveBackwardAndModifySelection:) with:sender];
2261 }
2262
2263 - (void)moveDown:(id)sender
2264 {
2265     if ([self _currentSelectionIsEditable]) {
2266         ERROR("unimplemented");
2267         return;
2268     }
2269     [[self nextResponder] tryToPerform:@selector(moveDown:) with:sender];
2270 }
2271
2272 - (void)moveDownAndModifySelection:(id)sender
2273 {
2274     if ([self _currentSelectionIsEditable]) {
2275         ERROR("unimplemented");
2276         return;
2277     }
2278     [[self nextResponder] tryToPerform:@selector(moveDownAndModifySelection:) with:sender];
2279 }
2280
2281 - (void)moveForward:(id)sender
2282 {
2283     if ([self _currentSelectionIsEditable]) {
2284         ERROR("unimplemented");
2285         return;
2286     }
2287     [[self nextResponder] tryToPerform:@selector(moveForward:) with:sender];
2288 }
2289
2290 - (void)moveForwardAndModifySelection:(id)sender
2291 {
2292     if ([self _currentSelectionIsEditable]) {
2293         ERROR("unimplemented");
2294         return;
2295     }
2296     [[self nextResponder] tryToPerform:@selector(moveForwardAndModifySelection:) with:sender];
2297 }
2298
2299 - (void)moveLeft:(id)sender
2300 {
2301     if ([self _currentSelectionIsEditable]) {
2302         [self _alterCurrentSelection:WebSelectByMoving direction:WebSelectLeft granularity:WebSelectByCharacter];
2303         return;
2304     }
2305     [[self nextResponder] tryToPerform:@selector(moveLeft:) with:sender];
2306 }
2307
2308 - (void)moveLeftAndModifySelection:(id)sender
2309 {
2310     if ([self _currentSelectionIsEditable]) {
2311         [self _alterCurrentSelection:WebSelectByExtending direction:WebSelectLeft granularity:WebSelectByCharacter];
2312         return;
2313     }
2314     [[self nextResponder] tryToPerform:@selector(moveLeftAndModifySelection:) with:sender];
2315 }
2316
2317 - (void)moveRight:(id)sender
2318 {
2319     if ([self _currentSelectionIsEditable]) {
2320         [self _alterCurrentSelection:WebSelectByMoving direction:WebSelectRight granularity:WebSelectByCharacter];
2321         return;
2322     }
2323     [[self nextResponder] tryToPerform:@selector(moveRight:) with:sender];
2324 }
2325
2326 - (void)moveRightAndModifySelection:(id)sender
2327 {
2328     if ([self _currentSelectionIsEditable]) {
2329         [self _alterCurrentSelection:WebSelectByExtending direction:WebSelectRight granularity:WebSelectByCharacter];
2330         return;
2331     }
2332     [[self nextResponder] tryToPerform:@selector(moveRightAndModifySelection:) with:sender];
2333 }
2334
2335 - (void)moveToBeginningOfDocument:(id)sender
2336 {
2337     if ([self _currentSelectionIsEditable]) {
2338         ERROR("unimplemented");
2339         return;
2340     }
2341     [[self nextResponder] tryToPerform:@selector(moveToBeginningOfDocument:) with:sender];
2342 }
2343
2344 - (void)moveToBeginningOfLine:(id)sender
2345 {
2346     if ([self _currentSelectionIsEditable]) {
2347         ERROR("unimplemented");
2348         return;
2349     }
2350     [[self nextResponder] tryToPerform:@selector(moveToBeginningOfLine:) with:sender];
2351 }
2352
2353 - (void)moveToBeginningOfParagraph:(id)sender
2354 {
2355     if ([self _currentSelectionIsEditable]) {
2356         ERROR("unimplemented");
2357         return;
2358     }
2359     [[self nextResponder] tryToPerform:@selector(moveToBeginningOfParagraph:) with:sender];
2360 }
2361
2362 - (void)moveToEndOfDocument:(id)sender
2363 {
2364     if ([self _currentSelectionIsEditable]) {
2365         ERROR("unimplemented");
2366         return;
2367     }
2368     [[self nextResponder] tryToPerform:@selector(moveToEndOfDocument:) with:sender];
2369 }
2370
2371 - (void)moveToEndOfLine:(id)sender
2372 {
2373     if ([self _currentSelectionIsEditable]) {
2374         ERROR("unimplemented");
2375         return;
2376     }
2377     [[self nextResponder] tryToPerform:@selector(moveToEndOfLine:) with:sender];
2378 }
2379
2380 - (void)moveToEndOfParagraph:(id)sender
2381 {
2382     if ([self _currentSelectionIsEditable]) {
2383         ERROR("unimplemented");
2384         return;
2385     }
2386     [[self nextResponder] tryToPerform:@selector(moveToEndOfParagraph:) with:sender];
2387 }
2388
2389 - (void)moveUp:(id)sender
2390 {
2391     if ([self _currentSelectionIsEditable]) {
2392         ERROR("unimplemented");
2393         return;
2394     }
2395     [[self nextResponder] tryToPerform:@selector(moveUp:) with:sender];
2396 }
2397
2398 - (void)moveUpAndModifySelection:(id)sender
2399 {
2400     if ([self _currentSelectionIsEditable]) {
2401         ERROR("unimplemented");
2402         return;
2403     }
2404     [[self nextResponder] tryToPerform:@selector(moveUpAndModifySelection:) with:sender];
2405 }
2406
2407 - (void)moveWordBackward:(id)sender
2408 {
2409     if ([self _currentSelectionIsEditable]) {
2410         ERROR("unimplemented");
2411         return;
2412     }
2413     [[self nextResponder] tryToPerform:@selector(moveWordBackward:) with:sender];
2414 }
2415
2416 - (void)moveWordBackwardAndModifySelection:(id)sender
2417 {
2418     if ([self _currentSelectionIsEditable]) {
2419         ERROR("unimplemented");
2420         return;
2421     }
2422     [[self nextResponder] tryToPerform:@selector(moveWordBackwardAndModifySelection:) with:sender];
2423 }
2424
2425 - (void)moveWordForward:(id)sender
2426 {
2427     if ([self _currentSelectionIsEditable]) {
2428         ERROR("unimplemented");
2429         return;
2430     }
2431     [[self nextResponder] tryToPerform:@selector(moveWordForward:) with:sender];
2432 }
2433
2434 - (void)moveWordForwardAndModifySelection:(id)sender
2435 {
2436     if ([self _currentSelectionIsEditable]) {
2437         ERROR("unimplemented");
2438         return;
2439     }
2440     [[self nextResponder] tryToPerform:@selector(moveWordForwardAndModifySelection:) with:sender];
2441 }
2442
2443 - (void)moveWordLeft:(id)sender
2444 {
2445     if ([self _currentSelectionIsEditable]) {
2446         ERROR("unimplemented");
2447         return;
2448     }
2449     [[self nextResponder] tryToPerform:@selector(moveWordLeft:) with:sender];
2450 }
2451
2452 - (void)moveWordLeftAndModifySelection:(id)sender
2453 {
2454     if ([self _currentSelectionIsEditable]) {
2455         ERROR("unimplemented");
2456         return;
2457     }
2458     [[self nextResponder] tryToPerform:@selector(moveWordLeftAndModifySelection:) with:sender];
2459 }
2460
2461 - (void)moveWordRight:(id)sender
2462 {
2463     if ([self _currentSelectionIsEditable]) {
2464         ERROR("unimplemented");
2465         return;
2466     }
2467     [[self nextResponder] tryToPerform:@selector(moveWordRight:) with:sender];
2468 }
2469
2470 - (void)moveWordRightAndModifySelection:(id)sender
2471 {
2472     if ([self _currentSelectionIsEditable]) {
2473         ERROR("unimplemented");
2474         return;
2475     }
2476     [[self nextResponder] tryToPerform:@selector(moveWordRightAndModifySelection:) with:sender];
2477 }
2478
2479 - (void)pageDown:(id)sender
2480 {
2481     if ([self _currentSelectionIsEditable]) {
2482         ERROR("unimplemented");
2483         return;
2484     }
2485     [[self nextResponder] tryToPerform:@selector(pageDown:) with:sender];
2486 }
2487
2488 - (void)pageUp:(id)sender
2489 {
2490     if ([self _currentSelectionIsEditable]) {
2491         ERROR("unimplemented");
2492         return;
2493     }
2494     [[self nextResponder] tryToPerform:@selector(pageUp:) with:sender];
2495 }
2496
2497 - (void)scrollLineDown:(id)sender
2498 {
2499     if ([self _currentSelectionIsEditable]) {
2500         ERROR("unimplemented");
2501         return;
2502     }
2503     [[self nextResponder] tryToPerform:@selector(scrollLineDown:) with:sender];
2504 }
2505
2506 - (void)scrollLineUp:(id)sender
2507 {
2508     if ([self _currentSelectionIsEditable]) {
2509         ERROR("unimplemented");
2510         return;
2511     }
2512     [[self nextResponder] tryToPerform:@selector(scrollLineUp:) with:sender];
2513 }
2514
2515 - (void)scrollPageDown:(id)sender
2516 {
2517     if ([self _currentSelectionIsEditable]) {
2518         ERROR("unimplemented");
2519         return;
2520     }
2521     [[self nextResponder] tryToPerform:@selector(scrollPageDown:) with:sender];
2522 }
2523
2524 - (void)scrollPageUp:(id)sender
2525 {
2526     if ([self _currentSelectionIsEditable]) {
2527         ERROR("unimplemented");
2528         return;
2529     }
2530     [[self nextResponder] tryToPerform:@selector(scrollPageUp:) with:sender];
2531 }
2532
2533
2534     /* Selections */
2535
2536 - (void)selectAll:(id)sender
2537 {
2538     if ([self _currentSelectionIsEditable]) {
2539         ERROR("unimplemented");
2540         return;
2541     }
2542     [[self nextResponder] tryToPerform:@selector(selectAll:) with:sender];
2543 }
2544
2545 - (void)selectParagraph:(id)sender
2546 {
2547     if ([self _currentSelectionIsEditable]) {
2548         ERROR("unimplemented");
2549         return;
2550     }
2551     [[self nextResponder] tryToPerform:@selector(selectParagraph:) with:sender];
2552 }
2553
2554 - (void)selectLine:(id)sender
2555 {
2556     if ([self _currentSelectionIsEditable]) {
2557         ERROR("unimplemented");
2558         return;
2559     }
2560     [[self nextResponder] tryToPerform:@selector(selectLine:) with:sender];
2561 }
2562
2563 - (void)selectWord:(id)sender
2564 {
2565     if ([self _currentSelectionIsEditable]) {
2566         ERROR("unimplemented");
2567         return;
2568     }
2569     [[self nextResponder] tryToPerform:@selector(selectWord:) with:sender];
2570 }
2571
2572
2573     /* "Edit menu" actions */
2574
2575 - (void)copy:(id)sender
2576 {
2577     if ([self _currentSelectionIsEditable]) {
2578         ERROR("unimplemented");
2579         return;
2580     }
2581     [[self nextResponder] tryToPerform:@selector(copy:) with:sender];
2582 }
2583
2584 - (void)cut:(id)sender
2585 {
2586     if ([self _currentSelectionIsEditable]) {
2587         ERROR("unimplemented");
2588         return;
2589     }
2590     [[self nextResponder] tryToPerform:@selector(cut:) with:sender];
2591 }
2592
2593 - (void)paste:(id)sender
2594 {
2595     if ([self _currentSelectionIsEditable]) {
2596         ERROR("unimplemented");
2597         return;
2598     }
2599     [[self nextResponder] tryToPerform:@selector(paste:) with:sender];
2600 }
2601
2602 - (void)copyFont:(id)sender
2603 {
2604     if ([self _currentSelectionIsEditable]) {
2605         ERROR("unimplemented");
2606         return;
2607     }
2608     [[self nextResponder] tryToPerform:@selector(copyFont:) with:sender];
2609 }
2610
2611 - (void)pasteFont:(id)sender
2612 {
2613     if ([self _currentSelectionIsEditable]) {
2614         ERROR("unimplemented");
2615         return;
2616     }
2617     [[self nextResponder] tryToPerform:@selector(pasteFont:) with:sender];
2618 }
2619
2620 - (void)delete:(id)sender
2621 {
2622     if ([self _currentSelectionIsEditable]) {
2623         ERROR("unimplemented");
2624         return;
2625     }
2626     [[self nextResponder] tryToPerform:@selector(delete:) with:sender];
2627 }
2628
2629 - (void)pasteAsPlainText:(id)sender
2630 {
2631     if ([self _currentSelectionIsEditable]) {
2632         ERROR("unimplemented");
2633         return;
2634     }
2635     [[self nextResponder] tryToPerform:@selector(pasteAsPlainText:) with:sender];
2636 }
2637
2638 - (void)pasteAsRichText:(id)sender
2639 {
2640     if ([self _currentSelectionIsEditable]) {
2641         ERROR("unimplemented");
2642         return;
2643     }
2644     [[self nextResponder] tryToPerform:@selector(pasteAsRichText:) with:sender];
2645 }
2646
2647
2648     /* Fonts */
2649
2650 - (void)changeFont:(id)sender
2651 {
2652     if ([self _currentSelectionIsEditable]) {
2653         ERROR("unimplemented");
2654         return;
2655     }
2656     [[self nextResponder] tryToPerform:@selector(changeFont:) with:sender];
2657 }
2658
2659 - (void)changeAttributes:(id)sender
2660 {
2661     if ([self _currentSelectionIsEditable]) {
2662         ERROR("unimplemented");
2663         return;
2664     }
2665     [[self nextResponder] tryToPerform:@selector(changeAttributes:) with:sender];
2666 }
2667
2668 - (void)changeDocumentBackgroundColor:(id)sender
2669 {
2670     if ([self _currentSelectionIsEditable]) {
2671         ERROR("unimplemented");
2672         return;
2673     }
2674     [[self nextResponder] tryToPerform:@selector(changeDocumentBackgroundColor:) with:sender];
2675 }
2676
2677
2678     /* Colors */
2679
2680 - (void)changeColor:(id)sender
2681 {
2682     if ([self _currentSelectionIsEditable]) {
2683         ERROR("unimplemented");
2684         return;
2685     }
2686     [[self nextResponder] tryToPerform:@selector(changeColor:) with:sender];
2687 }
2688
2689
2690         /* Alignment */
2691
2692 - (void)alignCenter:(id)sender
2693 {
2694     if ([self _currentSelectionIsEditable]) {
2695         ERROR("unimplemented");
2696         return;
2697     }
2698     [[self nextResponder] tryToPerform:@selector(alignCenter:) with:sender];
2699 }
2700
2701 - (void)alignJustified:(id)sender
2702 {
2703     if ([self _currentSelectionIsEditable]) {
2704         ERROR("unimplemented");
2705         return;
2706     }
2707     [[self nextResponder] tryToPerform:@selector(alignJustified:) with:sender];
2708 }
2709
2710 - (void)alignLeft:(id)sender
2711 {
2712     if ([self _currentSelectionIsEditable]) {
2713         ERROR("unimplemented");
2714         return;
2715     }
2716     [[self nextResponder] tryToPerform:@selector(alignLeft:) with:sender];
2717 }
2718
2719 - (void)alignRight:(id)sender
2720 {
2721     if ([self _currentSelectionIsEditable]) {
2722         ERROR("unimplemented");
2723         return;
2724     }
2725     [[self nextResponder] tryToPerform:@selector(alignRight:) with:sender];
2726 }
2727
2728
2729     /* Insertions and Indentations */
2730
2731 - (void)indent:(id)sender
2732 {
2733     if ([self _currentSelectionIsEditable]) {
2734         ERROR("unimplemented");
2735         return;
2736     }
2737     [[self nextResponder] tryToPerform:@selector(indent:) with:sender];
2738 }
2739
2740 - (void)insertTab:(id)sender
2741 {
2742     if ([self _currentSelectionIsEditable]) {
2743         ERROR("unimplemented");
2744         return;
2745     }
2746     [[self nextResponder] tryToPerform:@selector(insertTab:) with:sender];
2747 }
2748
2749 - (void)insertBacktab:(id)sender
2750 {
2751     if ([self _currentSelectionIsEditable]) {
2752         ERROR("unimplemented");
2753         return;
2754     }
2755     [[self nextResponder] tryToPerform:@selector(insertBacktab:) with:sender];
2756 }
2757
2758 - (void)insertNewline:(id)sender
2759 {
2760     if ([self _currentSelectionIsEditable]) {
2761         [[self _bridgeForCurrentSelection] replaceSelectionWithNewline];
2762         return;
2763     }
2764     [[self nextResponder] tryToPerform:@selector(insertNewline:) with:sender];
2765 }
2766
2767 - (void)insertParagraphSeparator:(id)sender
2768 {
2769     if ([self _currentSelectionIsEditable]) {
2770         ERROR("unimplemented");
2771         return;
2772     }
2773     [[self nextResponder] tryToPerform:@selector(insertParagraphSeparator:) with:sender];
2774 }
2775
2776
2777     /* Case changes */
2778
2779 - (void)changeCaseOfLetter:(id)sender
2780 {
2781     if ([self _currentSelectionIsEditable]) {
2782         ERROR("unimplemented");
2783         return;
2784     }
2785     [[self nextResponder] tryToPerform:@selector(changeCaseOfLetter:) with:sender];
2786 }
2787
2788 - (void)uppercaseWord:(id)sender
2789 {
2790     if ([self _currentSelectionIsEditable]) {
2791         ERROR("unimplemented");
2792         return;
2793     }
2794     [[self nextResponder] tryToPerform:@selector(uppercaseWord:) with:sender];
2795 }
2796
2797 - (void)lowercaseWord:(id)sender
2798 {
2799     if ([self _currentSelectionIsEditable]) {
2800         ERROR("unimplemented");
2801         return;
2802     }
2803     [[self nextResponder] tryToPerform:@selector(lowercaseWord:) with:sender];
2804 }
2805
2806 - (void)capitalizeWord:(id)sender
2807 {
2808     if ([self _currentSelectionIsEditable]) {
2809         ERROR("unimplemented");
2810         return;
2811     }
2812     [[self nextResponder] tryToPerform:@selector(capitalizeWord:) with:sender];
2813 }
2814
2815
2816     /* Deletions */
2817
2818 - (void)deleteForward:(id)sender
2819 {
2820     if ([self _currentSelectionIsEditable]) {
2821         ERROR("unimplemented");
2822         return;
2823     }
2824     [[self nextResponder] tryToPerform:@selector(deleteForward:) with:sender];
2825 }
2826
2827 - (void)deleteBackward:(id)sender
2828 {
2829     if ([self _currentSelectionIsEditable]) {
2830         [[self _bridgeForCurrentSelection] deleteKeyPressed];
2831         return;
2832     }
2833     [[self nextResponder] tryToPerform:@selector(deleteBackward:) with:sender];
2834 }
2835
2836 - (void)deleteBackwardByDecomposingPreviousCharacter:(id)sender
2837 {
2838     if ([self _currentSelectionIsEditable]) {
2839         ERROR("unimplemented");
2840         return;
2841     }
2842     [[self nextResponder] tryToPerform:@selector(deleteBackwardByDecomposingPreviousCharacter:) with:sender];
2843 }
2844
2845 - (void)deleteWordForward:(id)sender
2846 {
2847     if ([self _currentSelectionIsEditable]) {
2848         ERROR("unimplemented");
2849         return;
2850     }
2851     [[self nextResponder] tryToPerform:@selector(deleteWordForward:) with:sender];
2852 }
2853
2854 - (void)deleteWordBackward:(id)sender
2855 {
2856     if ([self _currentSelectionIsEditable]) {
2857         ERROR("unimplemented");
2858         return;
2859     }
2860     [[self nextResponder] tryToPerform:@selector(deleteWordBackward:) with:sender];
2861 }
2862
2863 - (void)deleteToBeginningOfLine:(id)sender
2864 {
2865     if ([self _currentSelectionIsEditable]) {
2866         ERROR("unimplemented");
2867         return;
2868     }
2869     [[self nextResponder] tryToPerform:@selector(deleteToBeginningOfLine:) with:sender];
2870 }
2871
2872 - (void)deleteToEndOfLine:(id)sender
2873 {
2874     if ([self _currentSelectionIsEditable]) {
2875         ERROR("unimplemented");
2876         return;
2877     }
2878     [[self nextResponder] tryToPerform:@selector(deleteToEndOfLine:) with:sender];
2879 }
2880
2881 - (void)deleteToBeginningOfParagraph:(id)sender
2882 {
2883     if ([self _currentSelectionIsEditable]) {
2884         ERROR("unimplemented");
2885         return;
2886     }
2887     [[self nextResponder] tryToPerform:@selector(deleteToBeginningOfParagraph:) with:sender];
2888 }
2889
2890 - (void)deleteToEndOfParagraph:(id)sender
2891 {
2892     if ([self _currentSelectionIsEditable]) {
2893         ERROR("unimplemented");
2894         return;
2895     }
2896     [[self nextResponder] tryToPerform:@selector(deleteToEndOfParagraph:) with:sender];
2897 }
2898
2899
2900     /* Completion */
2901
2902 - (void)complete:(id)sender
2903 {
2904     if ([self _currentSelectionIsEditable]) {
2905         ERROR("unimplemented");
2906         return;
2907     }
2908     [[self nextResponder] tryToPerform:@selector(complete:) with:sender];
2909 }
2910
2911
2912     /* Spelling */
2913
2914 - (void)checkSpelling:(id)sender
2915 {
2916     if ([self _currentSelectionIsEditable]) {
2917         ERROR("unimplemented");
2918         return;
2919     }
2920     [[self nextResponder] tryToPerform:@selector(checkSpelling:) with:sender];
2921 }
2922
2923 - (void)showGuessPanel:(id)sender
2924 {
2925     if ([self _currentSelectionIsEditable]) {
2926         ERROR("unimplemented");
2927         return;
2928     }
2929     [[self nextResponder] tryToPerform:@selector(showGuessPanel:) with:sender];
2930 }
2931
2932
2933     /* Finding */
2934     
2935 - (void)performFindPanelAction:(id)sender
2936 {
2937     if ([self _currentSelectionIsEditable]) {
2938         ERROR("unimplemented");
2939         return;
2940     }
2941     [[self nextResponder] tryToPerform:@selector(performFindPanelAction:) with:sender];
2942 }
2943
2944
2945         /* Speech */
2946
2947 - (void)startSpeaking:(id)sender
2948 {
2949     if ([self _currentSelectionIsEditable]) {
2950         ERROR("unimplemented");
2951         return;
2952     }
2953     [[self nextResponder] tryToPerform:@selector(startSpeaking:) with:sender];
2954 }
2955
2956 - (void)stopSpeaking:(id)sender
2957 {
2958     if ([self _currentSelectionIsEditable]) {
2959         ERROR("unimplemented");
2960         return;
2961     }
2962     [[self nextResponder] tryToPerform:@selector(stopSpeaking:) with:sender];
2963 }
2964
2965         /* Text input */
2966
2967 - (void)insertText:(NSString *)text
2968 {
2969     if ([self _currentSelectionIsEditable]) {
2970         [[self _bridgeForCurrentSelection] replaceSelectionWithText:text];
2971         return;
2972     }
2973     [[self nextResponder] tryToPerform:@selector(insertText:) with:text];
2974 }
2975
2976 @end
2977