d5d20b3e67a8e248fcd2b4425b863fbbe00402b1
[WebKit-https.git] / WebKit / win / WebView.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "WebView.h"
29
30 #include "DOMCoreClasses.h"
31 #include "IWebNotification.h"
32 #include "WebDebugProgram.h"
33 #include "WebDocumentLoader.h"
34 #include "WebEditorClient.h"
35 #include "WebElementPropertyBag.h"
36 #include "WebFrame.h"
37 #include "WebBackForwardList.h"
38 #include "WebChromeClient.h"
39 #include "WebContextMenuClient.h"
40 #include "WebDragClient.h"
41 #include "WebInspectorClient.h"
42 #include "WebKit.h"
43 #include "WebKitStatisticsPrivate.h"
44 #include "WebMutableURLRequest.h"
45 #include "WebNotificationCenter.h"
46 #include "WebPreferences.h"
47 #pragma warning( push, 0 )
48 #include <CoreGraphics/CGContext.h>
49 #include <CFNetwork/CFHTTPCookiesPriv.h>
50 #include <WebCore/BString.h>
51 #include <WebCore/Cache.h>
52 #include <WebCore/CommandByName.h>
53 #include <WebCore/ContextMenu.h>
54 #include <WebCore/ContextMenuController.h>
55 #include <WebCore/CString.h>
56 #include <WebCore/Cursor.h>
57 #include <WebCore/Document.h>
58 #include <WebCore/DragController.h>
59 #include <WebCore/DragData.h>
60 #include <WebCore/Editor.h>
61 #include <WebCore/EventHandler.h>
62 #include <WebCore/FocusController.h>
63 #include <WebCore/FrameLoader.h>
64 #include <WebCore/FrameTree.h>
65 #include <WebCore/FrameView.h>
66 #include <WebCore/FrameWin.h>
67 #include <WebCore/GDIObjectCounter.h>
68 #include <WebCore/GraphicsContext.h>
69 #include <WebCore/HistoryItem.h>
70 #include <WebCore/HitTestResult.h>
71 #include <WebCore/IntRect.h>
72 #include <WebCore/KeyboardEvent.h>
73 #include <WebCore/MIMETypeRegistry.h>
74 #include <WebCore/NotImplemented.h>
75 #include <WebCore/Page.h>
76 #include <WebCore/PageCache.h>
77 #include <WebCore/PlatformKeyboardEvent.h>
78 #include <WebCore/PlatformMouseEvent.h>
79 #include <WebCore/PlatformWheelEvent.h>
80 #include <WebCore/PluginDatabaseWin.h>
81 #include <WebCore/PlugInInfoStore.h>
82 #include <WebCore/ProgressTracker.h>
83 #include <WebCore/ResourceHandle.h>
84 #include <WebCore/ResourceHandleClient.h>
85 #include <WebCore/SelectionController.h>
86 #include <WebCore/Settings.h>
87 #include <WebCore/TypingCommand.h>
88 #pragma warning(pop)
89 #include <JavaScriptCore/collector.h>
90 #include <JavaScriptCore/value.h>
91 #include <CFNetwork/CFURLProtocolPriv.h>
92 #include <tchar.h>
93 #include <dimm.h>
94 #include <windowsx.h>
95 #include <ShlObj.h>
96
97 using namespace WebCore;
98 using KJS::JSLock;
99 using std::min;
100
101 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
102
103 const int WM_XP_THEMECHANGED = 0x031A;
104 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
105
106 static const int maxToolTipWidth = 250;
107
108 static ATOM registerWebView();
109 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
110
111 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
112
113 static bool continuousSpellCheckingEnabled;
114 static bool grammarCheckingEnabled;
115
116 // WebView ----------------------------------------------------------------
117
118 bool WebView::s_allowSiteSpecificHacks = false;
119
120 WebView::WebView()
121 : m_refCount(0)
122 , m_hostWindow(0)
123 , m_viewWindow(0)
124 , m_mainFrame(0)
125 , m_page(0)
126 , m_backingStoreBitmap(0)
127 , m_backingStoreDirtyRegion(0)
128 , m_useBackForwardList(true)
129 , m_userAgentOverridden(false)
130 , m_textSizeMultiplier(1)
131 , m_mouseActivated(false)
132 , m_dragData(0)
133 , m_currentCharacterCode(0)
134 , m_isBeingDestroyed(false)
135 , m_paintCount(0)
136 , m_hasSpellCheckerDocumentTag(false)
137 , m_smartInsertDeleteEnabled(false)
138 , m_didClose(false)
139 , m_inIMEComposition(0)
140 , m_toolTipHwnd(0)
141 {
142     KJS::Collector::registerAsMainThread();
143
144     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
145
146     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
147
148     COMPtr<IWebPreferences> prefs;
149     if (SUCCEEDED(preferences(&prefs))) {
150         BOOL enabled;
151         if (SUCCEEDED(prefs->continuousSpellCheckingEnabled(&enabled)))
152             continuousSpellCheckingEnabled = !!enabled;
153         if (SUCCEEDED(prefs->grammarCheckingEnabled(&enabled)))
154             grammarCheckingEnabled = !!enabled;
155     }
156
157     WebDebugProgram::viewAdded(this);
158     WebViewCount++;
159     gClassCount++;
160 }
161
162 WebView::~WebView()
163 {
164     deleteBackingStore();
165
166     // <rdar://4958382> m_viewWindow will be destroyed when m_hostWindow is destroyed, but if
167     // setHostWindow was never called we will leak our HWND. If we still have a valid HWND at
168     // this point, we should just destroy it ourselves.
169     if (::IsWindow(m_viewWindow))
170         ::DestroyWindow(m_viewWindow);
171
172     delete m_page;
173
174     WebDebugProgram::viewRemoved(this);
175     WebViewCount--;
176     gClassCount--;
177 }
178
179 WebView* WebView::createInstance()
180 {
181     WebView* instance = new WebView();
182     instance->AddRef();
183     return instance;
184 }
185
186 void WebView::close()
187 {
188     if (m_didClose)
189         return;
190
191     m_didClose = true;
192
193     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
194     COMPtr<IWebPreferences> prefs;
195     if (SUCCEEDED(preferences(&prefs)))
196         notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), prefs.get());
197     prefs = 0;  // make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
198     if (m_preferences) {
199         BSTR identifier = 0;
200         if (SUCCEEDED(m_preferences->identifier(&identifier)))
201             WebPreferences::removeReferenceForIdentifier(identifier);
202         if (identifier)
203             SysFreeString(identifier);
204         m_preferences = 0;
205     }
206
207     setHostWindow(0);
208     setFrameLoadDelegate(0);
209     setFrameLoadDelegatePrivate(0);
210     setUIDelegate(0);
211     setFormDelegate(0);
212     setPolicyDelegate(0);
213
214     Frame* frame = NULL;
215     frame = m_page->mainFrame();
216     if (frame)
217         frame->loader()->detachFromParent();
218
219     delete m_page;
220     m_page = 0;
221
222     deleteBackingStore();
223 }
224
225 void WebView::deleteBackingStore()
226 {
227     if (m_backingStoreBitmap) {
228         ::DeleteObject(m_backingStoreBitmap);
229         m_backingStoreBitmap = 0;
230     }
231
232     if (m_backingStoreDirtyRegion) {
233         ::DeleteObject(m_backingStoreDirtyRegion);
234         m_backingStoreDirtyRegion = 0;
235     }
236
237     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
238 }
239
240 bool WebView::ensureBackingStore()
241 {
242     RECT windowRect;
243     ::GetClientRect(m_viewWindow, &windowRect);
244     LONG width = windowRect.right - windowRect.left;
245     LONG height = windowRect.bottom - windowRect.top;
246     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
247         deleteBackingStore();
248
249         m_backingStoreSize.cx = width;
250         m_backingStoreSize.cy = height;
251         BITMAPINFO bitmapInfo;
252         bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
253         bitmapInfo.bmiHeader.biWidth         = width; 
254         bitmapInfo.bmiHeader.biHeight        = -height;
255         bitmapInfo.bmiHeader.biPlanes        = 1;
256         bitmapInfo.bmiHeader.biBitCount      = 32;
257         bitmapInfo.bmiHeader.biCompression   = BI_RGB;
258         bitmapInfo.bmiHeader.biSizeImage     = 0;
259         bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
260         bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
261         bitmapInfo.bmiHeader.biClrUsed       = 0;
262         bitmapInfo.bmiHeader.biClrImportant  = 0;
263
264         void* pixels = NULL;
265         m_backingStoreBitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, NULL, 0);
266         return true;
267     }
268
269     return false;
270 }
271
272 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
273 {
274     HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
275                                      dirtyRect.right(), dirtyRect.bottom());
276     addToDirtyRegion(newRegion);
277 }
278
279 void WebView::addToDirtyRegion(HRGN newRegion)
280 {
281     LOCAL_GDI_COUNTER(0, __FUNCTION__);
282
283     if (m_backingStoreDirtyRegion) {
284         HRGN combinedRegion = ::CreateRectRgn(0,0,0,0);
285         ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion, newRegion, RGN_OR);
286         ::DeleteObject(m_backingStoreDirtyRegion);
287         ::DeleteObject(newRegion);
288         m_backingStoreDirtyRegion = combinedRegion;
289     } else
290         m_backingStoreDirtyRegion = newRegion;
291 }
292
293 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
294 {
295     LOCAL_GDI_COUNTER(0, __FUNCTION__);
296
297     // If there's no backing store we don't need to update it
298     if (!m_backingStoreBitmap) {
299         if (m_uiDelegatePrivate)
300             m_uiDelegatePrivate->webViewScrolled(this);
301
302         return;
303     }
304
305     // Make a region to hold the invalidated scroll area.
306     HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0);
307
308     // Collect our device context info and select the bitmap to scroll.
309     HDC windowDC = ::GetDC(m_viewWindow);
310     HDC bitmapDC = ::CreateCompatibleDC(windowDC);
311     ::SelectObject(bitmapDC, m_backingStoreBitmap);
312     
313     // Scroll the bitmap.
314     RECT scrollRectWin(scrollViewRect);
315     RECT clipRectWin(clipRect);
316     ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0);
317     RECT regionBox;
318     ::GetRgnBox(updateRegion, &regionBox);
319
320     // Flush.
321     GdiFlush();
322
323     // Add the dirty region to the backing store's dirty region.
324     addToDirtyRegion(updateRegion);
325
326     if (m_uiDelegatePrivate)
327         m_uiDelegatePrivate->webViewScrolled(this);
328
329     // Update the backing store.
330     updateBackingStore(frameView, bitmapDC, false);
331
332     // Clean up.
333     ::DeleteDC(bitmapDC);
334     ::ReleaseDC(m_viewWindow, windowDC);
335
336 }
337
338 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty)
339 {
340     LOCAL_GDI_COUNTER(0, __FUNCTION__);
341
342     HDC windowDC = 0;
343     HDC bitmapDC = dc;
344     if (!dc) {
345         windowDC = ::GetDC(m_viewWindow);
346         bitmapDC = ::CreateCompatibleDC(windowDC);
347         ::SelectObject(bitmapDC, m_backingStoreBitmap);
348     }
349
350     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
351         // Do a layout first so that everything we render to the backing store is always current.
352         m_mainFrame->layoutIfNeededRecursive(0);
353
354         // This emulates the Mac smarts for painting rects intelligently.  This is
355         // very important for us, since we double buffer based off dirty rects.
356         bool useRegionBox = true;
357         const int cRectThreshold = 10;
358         const float cWastedSpaceThreshold = 0.75f;
359         RECT regionBox;
360         if (!backingStoreCompletelyDirty) {
361             ::GetRgnBox(m_backingStoreDirtyRegion, &regionBox);
362             DWORD regionDataSize = GetRegionData(m_backingStoreDirtyRegion, sizeof(RGNDATA), NULL);
363             if (regionDataSize) {
364                 RGNDATA* regionData = (RGNDATA*)malloc(regionDataSize);
365                 GetRegionData(m_backingStoreDirtyRegion, regionDataSize, regionData);
366                 if (regionData->rdh.nCount <= cRectThreshold) {
367                     double unionPixels = (regionBox.right - regionBox.left) * (regionBox.bottom - regionBox.top);
368                     double singlePixels = 0;
369                     
370                     unsigned i;
371                     RECT* rect;
372                     for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
373                         singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
374                     double wastedSpace = 1.0 - (singlePixels / unionPixels);
375                     if (wastedSpace > cWastedSpaceThreshold) {
376                         // Paint individual rects.
377                         useRegionBox = false;
378                         for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
379                             paintIntoBackingStore(frameView, bitmapDC, rect);
380                     }
381                 }
382                 free(regionData);
383             }
384         } else
385             ::GetClientRect(m_viewWindow, &regionBox);
386
387         if (useRegionBox)
388             paintIntoBackingStore(frameView, bitmapDC, &regionBox);
389
390         if (m_backingStoreDirtyRegion) {
391             ::DeleteObject(m_backingStoreDirtyRegion);
392             m_backingStoreDirtyRegion = 0;
393         }
394     }
395
396     if (!dc) {
397         ::DeleteDC(bitmapDC);
398         ::ReleaseDC(m_viewWindow, windowDC);
399     }
400
401     GdiFlush();
402 }
403
404 void WebView::paint(HDC dc, LPARAM options)
405 {
406     LOCAL_GDI_COUNTER(0, __FUNCTION__);
407
408     Frame* coreFrame = core(m_mainFrame);
409     if (!coreFrame)
410         return;
411     FrameView* frameView = coreFrame->view();
412
413     m_paintCount++;
414
415     RECT rcPaint;
416     HDC hdc;
417     HRGN region = 0;
418     int regionType = NULLREGION;
419     PAINTSTRUCT ps;
420     if (!dc) {
421         region = CreateRectRgn(0,0,0,0);
422         regionType = GetUpdateRgn(m_viewWindow, region, false);
423         hdc = BeginPaint(m_viewWindow, &ps);
424         rcPaint = ps.rcPaint;
425     } else {
426         hdc = dc;
427         ::GetClientRect(m_viewWindow, &rcPaint);
428         if (options & PRF_ERASEBKGND)
429             ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
430     }
431
432     HDC bitmapDC = ::CreateCompatibleDC(hdc);
433     bool backingStoreCompletelyDirty = ensureBackingStore();
434     ::SelectObject(bitmapDC, m_backingStoreBitmap);
435
436     // Update our backing store if needed.
437     updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty);
438
439     // Now we blit the updated backing store
440     IntRect windowDirtyRect = rcPaint;
441     
442     // Apply the same heuristic for this update region too.
443     bool useWindowDirtyRect = true;
444     if (region && regionType == COMPLEXREGION) {
445         LOCAL_GDI_COUNTER(1, __FUNCTION__" (COMPLEXREGION)");
446
447         const int cRectThreshold = 10;
448         const float cWastedSpaceThreshold = 0.75f;
449         DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
450         if (regionDataSize) {
451             RGNDATA* regionData = (RGNDATA*)malloc(regionDataSize);
452             GetRegionData(region, regionDataSize, regionData);
453             if (regionData->rdh.nCount <= cRectThreshold) {
454                 double unionPixels = windowDirtyRect.width() * windowDirtyRect.height();
455                 double singlePixels = 0;
456                 
457                 unsigned i;
458                 RECT* rect;
459                 for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
460                     singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
461                 double wastedSpace = 1.0 - (singlePixels / unionPixels);
462                 if (wastedSpace > cWastedSpaceThreshold) {
463                     // Paint individual rects.
464                     useWindowDirtyRect = false;
465                     for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
466                         paintIntoWindow(bitmapDC, hdc, rect);
467                 }
468             }
469             free(regionData);
470         }
471     }
472     
473     ::DeleteObject(region);
474
475     if (useWindowDirtyRect)
476         paintIntoWindow(bitmapDC, hdc, &rcPaint);
477
478     ::DeleteDC(bitmapDC);
479
480     // Paint the gripper.
481     COMPtr<IWebUIDelegate> ui;
482     if (SUCCEEDED(uiDelegate(&ui))) {
483         COMPtr<IWebUIDelegatePrivate> uiPrivate;
484         if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
485             RECT r;
486             if (SUCCEEDED(uiPrivate->webViewResizerRect(this, &r))) {
487                 LOCAL_GDI_COUNTER(2, __FUNCTION__" webViewDrawResizer delegate call");
488                 uiPrivate->webViewDrawResizer(this, hdc, (frameView->resizerOverlapsContent() ? true : false), &r);
489             }
490         }
491     }
492
493     if (!dc)
494         EndPaint(m_viewWindow, &ps);
495
496     m_paintCount--;
497 }
498
499 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, LPRECT dirtyRect)
500 {
501     LOCAL_GDI_COUNTER(0, __FUNCTION__);
502
503 #if FLASH_BACKING_STORE_REDRAW
504     HDC dc = ::GetDC(m_viewWindow);
505     HBRUSH yellowBrush = CreateSolidBrush(RGB(255, 255, 0));
506     FillRect(dc, dirtyRect, yellowBrush);
507     DeleteObject(yellowBrush);
508     GdiFlush();
509     Sleep(50);
510     paintIntoWindow(bitmapDC, dc, dirtyRect);
511     ::ReleaseDC(m_viewWindow, dc);
512 #endif
513
514     FillRect(bitmapDC, dirtyRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
515     if (frameView && frameView->frame() && frameView->frame()->renderer()) {
516         GraphicsContext gc(bitmapDC);
517         gc.save();
518         gc.clip(IntRect(*dirtyRect));
519         frameView->paint(&gc, IntRect(*dirtyRect));
520         gc.restore();
521     }
522 }
523
524 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, LPRECT dirtyRect)
525 {
526     LOCAL_GDI_COUNTER(0, __FUNCTION__);
527 #if FLASH_WINDOW_REDRAW
528     HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0));
529     FillRect(windowDC, dirtyRect, greenBrush);
530     DeleteObject(greenBrush);
531     GdiFlush();
532     Sleep(50);
533 #endif
534
535     // Blit the dirty rect from the backing store into the same position
536     // in the destination DC.
537     BitBlt(windowDC, dirtyRect->left, dirtyRect->top, dirtyRect->right - dirtyRect->left, dirtyRect->bottom - dirtyRect->top, bitmapDC,
538            dirtyRect->left, dirtyRect->top, SRCCOPY);
539 }
540
541 void WebView::frameRect(RECT* rect)
542 {
543     ::GetWindowRect(m_viewWindow, rect);
544 }
545
546 void WebView::closeWindow()
547 {
548     if (m_hasSpellCheckerDocumentTag) {
549         if (m_editingDelegate)
550             m_editingDelegate->closeSpellDocument(this);
551         m_hasSpellCheckerDocumentTag = false;
552     }
553
554     COMPtr<IWebUIDelegate> ui;
555     if (SUCCEEDED(uiDelegate(&ui)))
556         ui->webViewClose(this);
557 }
558
559 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
560 {
561     // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
562     if (equalIgnoringCase(String(request.url().protocol()), "about"))
563         return true;
564
565     if (CFURLProtocolCanHandleRequest(request.cfURLRequest()))
566         return true;
567
568     // FIXME: Mac WebKit calls _representationExistsForURLScheme here
569     return false;
570 }
571
572 Page* WebView::page()
573 {
574     return m_page;
575 }
576
577 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
578 {
579     static const int contextMenuMargin = 1;
580
581     // Translate the screen coordinates into window coordinates
582     POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
583     if (coords.x == -1 || coords.y == -1) {
584         FrameView* view = m_page->mainFrame()->view();
585         if (!view)
586             return false;
587
588         int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
589         IntPoint location;
590
591         // The context menu event was generated from the keyboard, so show the context menu by the current selection.
592         Position start = m_page->mainFrame()->selectionController()->selection().start();
593         Position end = m_page->mainFrame()->selectionController()->selection().end();
594
595         if (!start.node() || !end.node())
596             location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
597         else {
598             RenderObject* renderer = start.node()->renderer();
599             if (!renderer)
600                 return false;
601
602             // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:]).
603             int extraWidthToEndOfLine = 0;
604             IntRect startCaretRect = renderer->caretRect(start.offset(), DOWNSTREAM, &extraWidthToEndOfLine);
605             IntRect endCaretRect = renderer->caretRect(end.offset(), UPSTREAM);
606
607             IntRect firstRect;
608             if (startCaretRect.y() == endCaretRect.y())
609                 firstRect = IntRect(min(startCaretRect.x(), endCaretRect.x()), startCaretRect.y(), abs(endCaretRect.x() - startCaretRect.x()), max(startCaretRect.height(), endCaretRect.height()));
610             else
611                 firstRect = IntRect(startCaretRect.x(), startCaretRect.y(), startCaretRect.width() + extraWidthToEndOfLine, startCaretRect.height());
612
613             location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
614         }
615
616         location = view->contentsToWindow(location);
617         // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
618         // Ideally we'd have the position of a context menu event be separate from its target node.
619         coords = location + IntSize(0, -1);
620     } else {
621         if (!::ScreenToClient(m_viewWindow, &coords))
622             return false;
623     }
624
625     lParam = MAKELPARAM(coords.x, coords.y);
626
627     // The contextMenuController() holds onto the last context menu that was popped up on the
628     // page until a new one is created. We need to clear this menu before propagating the event
629     // through the DOM so that we can detect if we create a new menu for this event, since we
630     // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
631     // not run.
632     m_page->contextMenuController()->clearContextMenu();
633
634     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
635     focusedFrame->view()->setCursor(pointerCursor());
636     PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
637     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(mouseEvent);
638     if (!handledEvent)
639         return false;
640
641     // Show the menu
642     ContextMenu* coreMenu = m_page->contextMenuController()->contextMenu();
643     if (!coreMenu)
644         return false;
645
646     Node* node = coreMenu->hitTestResult().innerNonSharedNode();
647     if (!node)
648         return false;
649
650     Frame* frame = node->document()->frame();
651     if (!frame)
652         return false;
653
654     FrameView* view = frame->view();
655     if (!view)
656         return false;
657
658     POINT point(view->contentsToWindow(coreMenu->hitTestResult().point()));
659
660     // Translate the point to screen coordinates
661     if (!::ClientToScreen(view->containingWindow(), &point))
662         return false;
663
664     BOOL hasCustomMenus = false;
665     if (m_uiDelegate)
666         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
667
668     if (hasCustomMenus)
669         m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->platformDescription(), &point);
670     else {
671         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
672         UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
673             | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
674         ::TrackPopupMenuEx(coreMenu->platformDescription(), flags, point.x, point.y, view->containingWindow(), 0);
675     }
676
677     return true;
678 }
679
680 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
681 {
682     if (!m_uiDelegate)
683         return false;
684
685     BOOL hasCustomMenus = false;
686     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
687     if (!hasCustomMenus)
688         return false;
689
690     m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
691     return true;
692 }
693
694 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
695 {
696     if (!m_uiDelegate)
697         return false;
698
699     BOOL hasCustomMenus = false;
700     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
701     if (!hasCustomMenus)
702         return false;
703
704     m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
705     return true;
706 }
707
708 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
709 {
710     if (!m_uiDelegate)
711         return false;
712
713     HMENU menu = (HMENU)wParam;
714     if (!menu)
715         return false;
716
717     BOOL hasCustomMenus = false;
718     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
719     if (!hasCustomMenus)
720         return false;
721
722     m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
723     return true;
724 }
725
726 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
727 {
728     if (!m_uiDelegate)
729         return false;
730
731     HMENU menu = (HMENU)wParam;
732     if (!menu)
733         return false;
734
735     BOOL hasCustomMenus = false;
736     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
737     if (!hasCustomMenus)
738         return false;
739
740     m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
741     return true;
742 }
743
744 void WebView::performContextMenuAction(WPARAM wParam, LPARAM /*lParam*/)
745 {
746     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
747     ASSERT(menu);
748
749     ContextMenuItem* item = menu->itemWithAction((ContextMenuAction)wParam);
750     m_page->contextMenuController()->contextMenuItemSelected(item);
751     delete item;
752 }
753
754 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
755 {
756     static LONG globalClickCount;
757     static IntPoint globalPrevPoint;
758     static MouseButton globalPrevButton;
759     static LONG globalPrevMouseDownTime;
760
761     // Create our event.
762     PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, lParam, m_mouseActivated);
763    
764     bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
765                            abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
766     LONG messageTime = ::GetMessageTime();
767     
768     bool handled = false;
769     if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
770         // FIXME: I'm not sure if this is the "right" way to do this
771         // but without this call, we never become focused since we don't allow
772         // the default handling of mouse events.
773         SetFocus(m_viewWindow);
774
775         // Always start capturing events when the mouse goes down in our HWND.
776         ::SetCapture(m_viewWindow);
777
778         if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) && 
779             insideThreshold &&
780             mouseEvent.button() == globalPrevButton)
781             globalClickCount++;
782         else
783             // Reset the click count.
784             globalClickCount = 1;
785         globalPrevMouseDownTime = messageTime;
786         globalPrevButton = mouseEvent.button();
787         globalPrevPoint = mouseEvent.pos();
788         
789         mouseEvent.setClickCount(globalClickCount);
790         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
791     } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
792         globalClickCount++;
793         mouseEvent.setClickCount(globalClickCount);
794         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
795     } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
796         // Record the global position and the button of the up.
797         globalPrevButton = mouseEvent.button();
798         globalPrevPoint = mouseEvent.pos();
799         mouseEvent.setClickCount(globalClickCount);
800         m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
801         ::ReleaseCapture();
802     } else if (message == WM_MOUSEMOVE) {
803         if (!insideThreshold)
804             globalClickCount = 0;
805         mouseEvent.setClickCount(globalClickCount);
806         handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
807     }
808     setMouseActivated(false);
809     return handled;
810 }
811
812 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isHorizontal)
813 {
814     // Ctrl+Mouse wheel doesn't ever go into WebCore.  It is used to
815     // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
816     // own local zoom modes for Ctrl+wheel).
817     if (wParam & MK_CONTROL) {
818         short delta = short(HIWORD(wParam));
819         if (delta < 0)
820             makeTextLarger(0);
821         else
822             makeTextSmaller(0);
823         return true;
824     }
825
826     PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isHorizontal);
827     Frame* coreFrame = core(m_mainFrame);
828     if (!coreFrame)
829         return false;
830
831     return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
832 }
833
834 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
835 {
836     Frame* frame = m_page->focusController()->focusedOrMainFrame();
837     bool handled = false;
838     switch (LOWORD(wParam)) {
839     case SelectAll:
840         handled = frame->editor()->execCommand("SelectAll");
841         break;
842     case Undo:
843         handled = frame->editor()->execCommand("Undo");
844         break;
845     case Redo:
846         handled = frame->editor()->execCommand("Redo");
847         break;
848     default:
849         break;
850     }
851     return handled;
852 }
853
854 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData)
855 {
856     // Don't send key events for shift, ctrl, and capslock keys when they're by themselves
857     if (virtualKeyCode == VK_SHIFT || virtualKeyCode == VK_CONTROL || virtualKeyCode == VK_CAPITAL) {
858         return false;
859     }
860
861     // Don't process keyDown events during IME composition
862     if (m_inIMEComposition)
863         return false;
864
865     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, m_currentCharacterCode);
866     Frame* frame = m_page->focusController()->focusedOrMainFrame();
867     m_currentCharacterCode = 0;
868
869     return frame->eventHandler()->keyEvent(keyEvent);
870 }
871
872 static const unsigned CtrlKey = 1 << 0;
873 static const unsigned AltKey = 1 << 1;
874 static const unsigned ShiftKey = 1 << 2;
875
876
877 struct KeyEntry {
878     unsigned virtualKey;
879     unsigned modifiers;
880     const char* name;
881 };
882
883 static const KeyEntry keyEntries[] = {
884     { VK_LEFT,   0,                  "MoveLeft"                                    },
885     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
886     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
887     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
888     { VK_RIGHT,  0,                  "MoveRight"                                   },
889     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
890     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
891     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
892     { VK_UP,     0,                  "MoveUp"                                      },
893     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
894     { VK_PRIOR,  ShiftKey,           "MoveUpAndModifySelection"                    },
895     { VK_DOWN,   0,                  "MoveDown"                                    },
896     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
897     { VK_NEXT,   ShiftKey,           "MoveDownAndModifySelection"                  },
898     { VK_PRIOR,  0,                  "MoveUpByPageAndModifyCaret"                  },
899     { VK_NEXT,   0,                  "MoveDownByPageAndModifyCaret"                },
900     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
901     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
902     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
903     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
904
905     { VK_END,    0,                  "MoveToEndOfLine"                             },
906     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
907     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
908     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
909
910     { VK_BACK,   0,                  "BackwardDelete"                              },
911     { VK_BACK,   ShiftKey,           "BackwardDelete"                              },
912     { VK_DELETE, 0,                  "ForwardDelete"                               },
913     { VK_DELETE, ShiftKey,           "ForwardDelete"                               },
914     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
915     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
916     
917     { 'B',       CtrlKey,            "ToggleBold"                                  },
918     { 'I',       CtrlKey,            "ToggleItalic"                                },
919
920     { VK_ESCAPE, 0,                  "Cancel"                                      },
921     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
922     { VK_TAB,    0,                  "InsertTab"                                   },
923     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
924     { VK_RETURN, 0,                  "InsertNewline"                               },
925     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
926     { VK_RETURN, AltKey,             "InsertNewline"                               },
927     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
928
929     { 'C',       CtrlKey,            "Copy"                                        },
930     { 'V',       CtrlKey,            "Paste"                                       },
931     { 'X',       CtrlKey,            "Cut"                                         },
932 };
933
934 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
935 {
936     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
937     if (!keyEvent)
938         return "";
939
940     static HashMap<int, const char*>* commandsMap = 0;
941
942     if (!commandsMap) {
943         commandsMap = new HashMap<int, const char*>;
944
945         for (unsigned i = 0; i < _countof(keyEntries); i++)
946             commandsMap->set(keyEntries[i].modifiers << 16 | keyEntries[i].virtualKey, keyEntries[i].name);
947     }
948
949     unsigned modifiers = 0;
950     if (keyEvent->shiftKey())
951         modifiers |= ShiftKey;
952     if (keyEvent->altKey())
953         modifiers |= AltKey;
954     if (keyEvent->ctrlKey())
955         modifiers |= CtrlKey;
956
957     return commandsMap->get(modifiers << 16 | keyEvent->WindowsKeyCode());
958 }
959
960 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
961 {
962     String command(interpretKeyEvent(evt));
963
964     Node* node = evt->target()->toNode();
965     ASSERT(node);
966     Frame* frame = node->document()->frame();
967     ASSERT(frame);
968
969     if (!command.isEmpty())
970         if (frame->editor()->execCommand(command, evt))
971             return true;
972
973     if (evt->keyEvent())
974         if (frame->editor()->insertText(evt->keyEvent()->text(), evt))
975             return true;
976
977     return false;
978 }
979
980 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData)
981 {
982     MSG msg;
983     // If the next message is a WM_CHAR message, then take it out of the queue, and use
984     // the message parameters to get the character code to construct the PlatformKeyboardEvent.
985     if (::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE)) 
986         m_currentCharacterCode = (UChar)msg.wParam;
987
988     // FIXME: We need to check WM_UNICHAR to support supplementary characters.
989     // FIXME: We may need to handle other messages for international text.
990
991     // Don't send key events for shift, ctrl, and capslock keys when they're by themselves
992     if (virtualKeyCode == VK_SHIFT || virtualKeyCode == VK_CONTROL || virtualKeyCode == VK_CAPITAL)
993         return false;
994
995     // Don't process keyDown events during IME composition
996     if (m_inIMEComposition)
997         return false;
998
999     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, m_currentCharacterCode);
1000     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1001
1002     if (frame->eventHandler()->keyEvent(keyEvent))
1003         return true;
1004
1005     // We need to handle back/forward using either Backspace(+Shift) or Ctrl+Left/Right Arrow keys.
1006     int windowsKeyCode = keyEvent.WindowsKeyCode();
1007     if ((windowsKeyCode == VK_BACK && keyEvent.shiftKey()) || (windowsKeyCode == VK_RIGHT && keyEvent.ctrlKey()))
1008         m_page->goForward();
1009     else if (windowsKeyCode == VK_BACK || (windowsKeyCode == VK_LEFT && keyEvent.ctrlKey()))
1010         m_page->goBack();
1011     
1012     // Need to scroll the page if the arrow keys, space(shift), pgup/dn, or home/end are hit.
1013     ScrollDirection direction;
1014     ScrollGranularity granularity;
1015     switch (windowsKeyCode) {
1016         case VK_LEFT:
1017             granularity = ScrollByLine;
1018             direction = ScrollLeft;
1019             break;
1020         case VK_RIGHT:
1021             granularity = ScrollByLine;
1022             direction = ScrollRight;
1023             break;
1024         case VK_UP:
1025             granularity = ScrollByLine;
1026             direction = ScrollUp;
1027             break;
1028         case VK_DOWN:
1029             granularity = ScrollByLine;
1030             direction = ScrollDown;
1031             break;
1032         case VK_HOME:
1033             granularity = ScrollByDocument;
1034             direction = ScrollUp;
1035             break;
1036         case VK_END:
1037             granularity = ScrollByDocument;
1038             direction = ScrollDown;
1039             break;
1040         case VK_SPACE:
1041             granularity = ScrollByPage;
1042             direction = (GetKeyState(VK_SHIFT) & 0x8000) ? ScrollUp : ScrollDown;
1043             break;
1044         case VK_PRIOR:
1045             granularity = ScrollByPage;
1046             direction = ScrollUp;
1047             break;
1048         case VK_NEXT:
1049             granularity = ScrollByPage;
1050             direction = ScrollDown;
1051             break;
1052         default:
1053             // We return true here so the WM_CHAR handler won't pick up unhandled messages.
1054             return true;
1055     }
1056
1057     frame->view()->scroll(direction, granularity);
1058
1059     return true;
1060 }
1061
1062 bool WebView::inResizer(LPARAM lParam)
1063 {
1064     if (!m_uiDelegatePrivate)
1065         return false;
1066
1067     RECT r;
1068     if (FAILED(m_uiDelegatePrivate->webViewResizerRect(this, &r)))
1069         return false;
1070
1071     POINT pt;
1072     pt.x = LOWORD(lParam);
1073     pt.y = HIWORD(lParam);
1074     return !!PtInRect(&r, pt);
1075 }
1076
1077 void WebView::initializeCacheSizesIfNecessary()
1078 {
1079     static bool didInitialize;
1080     if (didInitialize)
1081         return;
1082
1083     COMPtr<IWebPreferences> prefs;
1084     if (FAILED(preferences(&prefs)))
1085         return;
1086
1087    UINT pageCacheSize;
1088    if (SUCCEEDED(prefs->pageCacheSize(&pageCacheSize)))
1089         pageCache()->setCapacity(pageCacheSize);
1090
1091    UINT objectCacheSize;
1092    if (SUCCEEDED(prefs->objectCacheSize(&objectCacheSize)))
1093         cache()->setMaximumSize(objectCacheSize);
1094
1095     didInitialize = true;
1096 }
1097
1098 static ATOM registerWebViewWindowClass()
1099 {
1100     static bool haveRegisteredWindowClass = false;
1101     if (haveRegisteredWindowClass)
1102         return true;
1103
1104     WNDCLASSEX wcex;
1105
1106     wcex.cbSize = sizeof(WNDCLASSEX);
1107
1108     wcex.style          = CS_DBLCLKS;
1109     wcex.lpfnWndProc    = WebViewWndProc;
1110     wcex.cbClsExtra     = 0;
1111     wcex.cbWndExtra     = 4; // 4 bytes for the IWebView pointer
1112     wcex.hInstance      = gInstance;
1113     wcex.hIcon          = 0;
1114     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
1115     wcex.hbrBackground  = 0;
1116     wcex.lpszMenuName   = 0;
1117     wcex.lpszClassName  = kWebViewWindowClassName;
1118     wcex.hIconSm        = 0;
1119
1120     return RegisterClassEx(&wcex);
1121 }
1122
1123 namespace WebCore {
1124     extern HCURSOR lastSetCursor;
1125 }
1126
1127 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1128 {
1129     LRESULT lResult = 0;
1130     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
1131     WebView* webView = reinterpret_cast<WebView*>(longPtr);
1132     WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
1133     if (!mainFrameImpl)
1134         return DefWindowProc(hWnd, message, wParam, lParam);
1135
1136     ASSERT(webView);
1137
1138     bool handled = true;
1139
1140     switch (message) {
1141         case WM_PAINT: {
1142             COMPtr<IWebDataSource> dataSource;
1143             mainFrameImpl->dataSource(&dataSource);
1144             Frame* coreFrame = core(mainFrameImpl);
1145             if (!webView->isPainting() && (!dataSource || coreFrame && coreFrame->view()->didFirstLayout()))
1146                 webView->paint(0, 0);
1147             else
1148                 ValidateRect(hWnd, 0);
1149             break;
1150         }
1151         case WM_PRINTCLIENT:
1152             webView->paint((HDC)wParam, lParam);
1153             break;
1154         case WM_DESTROY:
1155             webView->close();
1156             webView->setIsBeingDestroyed();
1157             webView->revokeDragDrop();
1158             break;
1159         case WM_MOUSEMOVE:
1160             if (webView->inResizer(lParam))
1161                 SetCursor(LoadCursor(0, IDC_SIZENWSE));
1162             // fall through
1163         case WM_LBUTTONDOWN:
1164         case WM_MBUTTONDOWN:
1165         case WM_RBUTTONDOWN:
1166         case WM_LBUTTONDBLCLK:
1167         case WM_MBUTTONDBLCLK:
1168         case WM_RBUTTONDBLCLK:
1169         case WM_LBUTTONUP:
1170         case WM_MBUTTONUP:
1171         case WM_RBUTTONUP:
1172             if (Frame* coreFrame = core(mainFrameImpl))
1173                 if (coreFrame->view()->didFirstLayout())
1174                     handled = webView->handleMouseEvent(message, wParam, lParam);
1175             break;
1176         case WM_MOUSEWHEEL:
1177         case WM_VISTA_MOUSEHWHEEL:
1178             if (Frame* coreFrame = core(mainFrameImpl))
1179                 if (coreFrame->view()->didFirstLayout())
1180                     handled = webView->mouseWheel(wParam, lParam, (wParam & MK_SHIFT) || message == WM_VISTA_MOUSEHWHEEL);
1181             break;
1182         case WM_KEYDOWN:
1183             handled = webView->keyDown(wParam, lParam);
1184             break;
1185         case WM_KEYUP:
1186             handled = webView->keyUp(wParam, lParam);
1187             break;
1188         case WM_SIZE:
1189             if (webView->isBeingDestroyed())
1190                 // If someone has sent us this message while we're being destroyed, we should bail out so we don't crash.
1191                 break;
1192
1193             if (lParam != 0) {
1194                 webView->deleteBackingStore();
1195                 if (Frame* coreFrame = core(mainFrameImpl)) {
1196                     coreFrame->view()->resize(LOWORD(lParam), HIWORD(lParam));
1197
1198                     if (!coreFrame->loader()->isLoading())
1199                         coreFrame->sendResizeEvent();
1200                 }
1201             }
1202             break;
1203         case WM_SHOWWINDOW:
1204             lResult = DefWindowProc(hWnd, message, wParam, lParam);
1205             if (wParam == 0)
1206                 // The window is being hidden (e.g., because we switched tabs.
1207                 // Null out our backing store.
1208                 webView->deleteBackingStore();
1209             break;
1210         case WM_SETFOCUS: {
1211             COMPtr<IWebUIDelegate> uiDelegate;
1212             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1213             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1214                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1215                 uiDelegatePrivate->webViewReceivedFocus(webView);
1216             // FIXME: Merge this logic with updateActiveState, and switch this over to use updateActiveState
1217
1218             // It's ok to just always do setWindowHasFocus, since we won't fire the focus event on the DOM
1219             // window unless the value changes.  It's also ok to do setIsActive inside focus,
1220             // because Windows has no concept of having to update control tints (e.g., graphite vs. aqua)
1221             // and therefore only needs to update the selection (which is limited to the focused frame).
1222             FocusController* focusController = webView->page()->focusController();
1223             if (Frame* frame = focusController->focusedFrame()) {
1224                 frame->setIsActive(true);
1225
1226                 // If the previously focused window is a child of ours (for example a plugin), don't send any
1227                 // focus events.
1228                 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
1229                     frame->setWindowHasFocus(true);
1230             } else
1231                 focusController->setFocusedFrame(webView->page()->mainFrame());
1232             break;
1233         }
1234         case WM_KILLFOCUS: {
1235             COMPtr<IWebUIDelegate> uiDelegate;
1236             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1237             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1238                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1239                 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)wParam);
1240             // FIXME: Merge this logic with updateActiveState, and switch this over to use updateActiveState
1241
1242             // However here we have to be careful.  If we are losing focus because of a deactivate,
1243             // then we need to remember our focused target for restoration later.  
1244             // If we are losing focus to another part of our window, then we are no longer focused for real
1245             // and we need to clear out the focused target.
1246             FocusController* focusController = webView->page()->focusController();
1247             webView->resetIME(focusController->focusedOrMainFrame());
1248             if (GetAncestor(hWnd, GA_ROOT) != GetFocus()) {
1249                 if (Frame* frame = focusController->focusedFrame()) {
1250                     frame->setIsActive(false);
1251
1252                     // If we're losing focus to a child of ours, don't send blur events.
1253                     if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
1254                         frame->setWindowHasFocus(false);
1255                 }
1256             } else
1257                 focusController->setFocusedFrame(0);
1258             break;
1259         }
1260         case WM_CUT:
1261             webView->cut(0);
1262             break;
1263         case WM_COPY:
1264             webView->copy(0);
1265             break;
1266         case WM_PASTE:
1267             webView->paste(0);
1268             break;
1269         case WM_CLEAR:
1270             webView->delete_(0);
1271             break;
1272         case WM_COMMAND:
1273             if (HIWORD(wParam))
1274                 handled = webView->execCommand(wParam, lParam);
1275             else // If the high word of wParam is 0, the message is from a menu
1276                 webView->performContextMenuAction(wParam, lParam);
1277             break;
1278         case WM_CONTEXTMENU:
1279             handled = webView->handleContextMenuEvent(wParam, lParam);
1280             break;
1281         case WM_INITMENUPOPUP:
1282             handled = webView->onInitMenuPopup(wParam, lParam);
1283             break;
1284         case WM_MEASUREITEM:
1285             handled = webView->onMeasureItem(wParam, lParam);
1286             break;
1287         case WM_DRAWITEM:
1288             handled = webView->onDrawItem(wParam, lParam);
1289             break;
1290         case WM_UNINITMENUPOPUP:
1291             handled = webView->onUninitMenuPopup(wParam, lParam);
1292             break;
1293         case WM_XP_THEMECHANGED:
1294             if (Frame* coreFrame = core(mainFrameImpl)) {
1295                 webView->deleteBackingStore();
1296                 coreFrame->view()->themeChanged();
1297             }
1298             break;
1299         case WM_MOUSEACTIVATE:
1300             webView->setMouseActivated(true);
1301             break;
1302         case WM_GETDLGCODE: {
1303             COMPtr<IWebUIDelegate> uiDelegate;
1304             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1305             LONG_PTR dlgCode = 0;
1306             UINT keyCode = 0;
1307             if (lParam) {
1308                 LPMSG lpMsg = (LPMSG)lParam;
1309                 if (lpMsg->message == WM_KEYDOWN)
1310                     keyCode = (UINT) lpMsg->wParam;
1311             }
1312             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1313                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate &&
1314                 SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
1315                 return dlgCode;
1316             handled = false;
1317             break;
1318         }
1319
1320         case WM_IME_STARTCOMPOSITION:
1321             handled = webView->onIMEStartComposition();
1322             break;
1323         case WM_IME_REQUEST:
1324             webView->onIMERequest(wParam, lParam, &lResult);
1325             break;
1326         case WM_IME_COMPOSITION:
1327             handled = webView->onIMEComposition(lParam);
1328             break;
1329         case WM_IME_ENDCOMPOSITION:
1330             handled = webView->onIMEEndComposition();
1331             break;
1332         case WM_IME_CHAR:
1333             handled = webView->onIMEChar(wParam, lParam);
1334             break;
1335         case WM_IME_NOTIFY:
1336             handled = webView->onIMENotify(wParam, lParam, &lResult);
1337             break;
1338         case WM_IME_SELECT:
1339             handled = webView->onIMESelect(wParam, lParam);
1340             break;
1341         case WM_IME_SETCONTEXT:
1342             handled = webView->onIMESetContext(wParam, lParam);
1343             break;
1344         case WM_SETCURSOR:
1345             if (lastSetCursor) {
1346                 SetCursor(lastSetCursor);
1347                 break;
1348             }
1349             __fallthrough;
1350         default:
1351             handled = false;
1352             break;
1353     }
1354
1355     if (!handled)
1356         lResult = DefWindowProc(hWnd, message, wParam, lParam);
1357     
1358     return lResult;
1359 }
1360
1361 HRESULT WebView::updateWebCoreSettingsFromPreferences(IWebPreferences* preferences)
1362 {
1363     HRESULT hr;
1364     BSTR str;
1365     int size;
1366     BOOL enabled;
1367     
1368     Settings* settings = m_page->settings();
1369
1370     hr = preferences->cursiveFontFamily(&str);
1371     if (FAILED(hr))
1372         return hr;
1373     settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str)));
1374     SysFreeString(str);
1375
1376     hr = preferences->defaultFixedFontSize(&size);
1377     if (FAILED(hr))
1378         return hr;
1379     settings->setDefaultFixedFontSize(size);
1380
1381     hr = preferences->defaultFontSize(&size);
1382     if (FAILED(hr))
1383         return hr;
1384     settings->setDefaultFontSize(size);
1385     
1386     hr = preferences->defaultTextEncodingName(&str);
1387     if (FAILED(hr))
1388         return hr;
1389     settings->setDefaultTextEncodingName(String(str, SysStringLen(str)));
1390     SysFreeString(str);
1391
1392     hr = preferences->fantasyFontFamily(&str);
1393     if (FAILED(hr))
1394         return hr;
1395     settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str)));
1396     SysFreeString(str);
1397
1398     hr = preferences->fixedFontFamily(&str);
1399     if (FAILED(hr))
1400         return hr;
1401     settings->setFixedFontFamily(AtomicString(str, SysStringLen(str)));
1402     SysFreeString(str);
1403
1404     hr = preferences->isJavaEnabled(&enabled);
1405     if (FAILED(hr))
1406         return hr;
1407     settings->setJavaEnabled(!!enabled);
1408
1409     hr = preferences->isJavaScriptEnabled(&enabled);
1410     if (FAILED(hr))
1411         return hr;
1412     settings->setJavaScriptEnabled(!!enabled);
1413
1414     hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled);
1415     if (FAILED(hr))
1416         return hr;
1417     settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled);
1418
1419     hr = preferences->minimumFontSize(&size);
1420     if (FAILED(hr))
1421         return hr;
1422     settings->setMinimumFontSize(size);
1423
1424     hr = preferences->minimumLogicalFontSize(&size);
1425     if (FAILED(hr))
1426         return hr;
1427     settings->setMinimumLogicalFontSize(size);
1428
1429     hr = preferences->arePlugInsEnabled(&enabled);
1430     if (FAILED(hr))
1431         return hr;
1432     settings->setPluginsEnabled(!!enabled);
1433
1434     hr = preferences->privateBrowsingEnabled(&enabled);
1435     if (FAILED(hr))
1436         return hr;
1437     settings->setPrivateBrowsingEnabled(!!enabled);
1438
1439     hr = preferences->sansSerifFontFamily(&str);
1440     if (FAILED(hr))
1441         return hr;
1442     settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str)));
1443     SysFreeString(str);
1444
1445     hr = preferences->serifFontFamily(&str);
1446     if (FAILED(hr))
1447         return hr;
1448     settings->setSerifFontFamily(AtomicString(str, SysStringLen(str)));
1449     SysFreeString(str);
1450
1451     hr = preferences->standardFontFamily(&str);
1452     if (FAILED(hr))
1453         return hr;
1454     settings->setStandardFontFamily(AtomicString(str, SysStringLen(str)));
1455     SysFreeString(str);
1456
1457     hr = preferences->loadsImagesAutomatically(&enabled);
1458     if (FAILED(hr))
1459         return hr;
1460     settings->setLoadsImagesAutomatically(!!enabled);
1461
1462     hr = preferences->userStyleSheetEnabled(&enabled);
1463     if (FAILED(hr))
1464         return hr;
1465     if (enabled) {
1466         hr = preferences->userStyleSheetLocation(&str);
1467         if (FAILED(hr))
1468             return hr;
1469         settings->setUserStyleSheetLocation(KURL(DeprecatedString((DeprecatedChar*)str, SysStringLen(str))));
1470         SysFreeString(str);
1471     } else {
1472         settings->setUserStyleSheetLocation(KURL(DeprecatedString("")));
1473     }
1474
1475     hr = preferences->shouldPrintBackgrounds(&enabled);
1476     if (FAILED(hr))
1477         return hr;
1478     settings->setShouldPrintBackgrounds(!!enabled);
1479
1480     hr = preferences->textAreasAreResizable(&enabled);
1481     if (FAILED(hr))
1482         return hr;
1483     settings->setTextAreasAreResizable(!!enabled);
1484
1485     WebKitEditableLinkBehavior behavior;
1486     hr = preferences->editableLinkBehavior(&behavior);
1487     if (FAILED(hr))
1488         return hr;
1489     settings->setEditableLinkBehavior((EditableLinkBehavior)behavior);
1490
1491     WebKitCookieStorageAcceptPolicy acceptPolicy;
1492     hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy);
1493     if (FAILED(hr))
1494         return hr;
1495
1496     hr = preferences->usesPageCache(&enabled);
1497     if (FAILED(hr))
1498         return hr;
1499     settings->setUsesPageCache(!!enabled);
1500
1501     hr = preferences->isDOMPasteAllowed(&enabled);
1502     if (FAILED(hr))
1503         return hr;
1504     settings->setDOMPasteAllowed(!!enabled);
1505
1506     ResourceHandle::setCookieStorageAcceptPolicy(acceptPolicy);
1507
1508     settings->setShowsURLsInToolTips(false);
1509
1510     settings->setForceFTPDirectoryListings(true);
1511
1512     // FIXME: make this read a preference like the Mac's WebKitDeveloperExtras
1513     // or when Safari's IncludeDebugMenu is set
1514     settings->setDeveloperExtrasEnabled(true);
1515
1516     m_mainFrame->invalidate(); // FIXME
1517
1518     return S_OK;
1519 }
1520
1521 static String osVersion()
1522 {
1523     String osVersion;
1524     OSVERSIONINFO versionInfo = {0};
1525     versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
1526     GetVersionEx(&versionInfo);
1527
1528     if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
1529         if (versionInfo.dwMajorVersion == 4) {
1530             if (versionInfo.dwMinorVersion == 0)
1531                 osVersion = "Windows 95";
1532             else if (versionInfo.dwMinorVersion == 10)
1533                 osVersion = "Windows 98";
1534             else if (versionInfo.dwMinorVersion == 90)
1535                 osVersion = "Windows 98; Win 9x 4.90";
1536         }
1537     } else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1538         osVersion = String::format("Windows NT %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
1539
1540     if (!osVersion.length())
1541         osVersion = String::format("Windows %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
1542
1543     return osVersion;
1544 }
1545
1546 static String language()
1547 {
1548     TCHAR languageName[256];
1549     if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, languageName, ARRAYSIZE(languageName)))
1550         return "en";
1551     else
1552         return String(languageName, (unsigned int)_tcslen(languageName));
1553 }
1554
1555 static String webKitVersion()
1556 {
1557     String versionStr = "420+";
1558     void* data = 0;
1559
1560     struct LANGANDCODEPAGE {
1561         WORD wLanguage;
1562         WORD wCodePage;
1563     } *lpTranslate;
1564
1565     TCHAR path[MAX_PATH];
1566     GetModuleFileName(gInstance, path, ARRAYSIZE(path));
1567     DWORD handle;
1568     DWORD versionSize = GetFileVersionInfoSize(path, &handle);
1569     if (!versionSize)
1570         goto exit;
1571     data = malloc(versionSize);
1572     if (!data)
1573         goto exit;
1574     if (!GetFileVersionInfo(path, 0, versionSize, data))
1575         goto exit;
1576     UINT cbTranslate;
1577     if (!VerQueryValue(data, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
1578         goto exit;
1579     TCHAR key[256];
1580     _stprintf_s(key, ARRAYSIZE(key), TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"), lpTranslate[0].wLanguage, lpTranslate[0].wCodePage);
1581     LPCTSTR productVersion;
1582     UINT productVersionLength;
1583     if (!VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&productVersion, &productVersionLength))
1584         goto exit;
1585     versionStr = String(productVersion, productVersionLength);
1586
1587 exit:
1588     if (data)
1589         free(data);
1590     return versionStr;
1591 }
1592
1593 const String& WebView::userAgentForKURL(const KURL& url)
1594 {
1595     if (m_userAgentOverridden)
1596         return m_userAgentCustom;
1597
1598     static const DeprecatedString uaCustomHosts[] = {
1599         "flickr.com",                       // <rdar://problem/5081617> flickr does not recognize post-2.0.4 versions of Safari
1600         "volvocars.us",                     // <rdar://problem/5246665> Drop down lists are not drawn on volvocars.us
1601         "investing.schwab.com"              // <rdar://problem/5213266> schwab.com menu is ridiculously big.
1602     };
1603     static const DeprecatedString uaCustomURLs[] = {
1604         "http://www.adobe.com/shockwave/download/"  // <rdar://problem/5243655> Flash download page doesn't recognize Boomer
1605     };
1606     static const String uaCustomValuesForHosts[] = {
1607         "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3",
1608         "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/522.7 (KHTML, like Gecko) Version/3.0 Safari/522.7",
1609         "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3",
1610     };
1611     static const String uaCustomValuesForURLs[] = {
1612         "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3",
1613     };
1614
1615     if (allowSiteSpecificHacks()) {
1616         for (int i = 0; i < ARRAYSIZE(uaCustomHosts); i++) {
1617             if (url.host().endsWith(uaCustomHosts[i]))
1618                 return uaCustomValuesForHosts[i];
1619         }
1620         for (int i = 0; i < ARRAYSIZE(uaCustomURLs); i++) {
1621             if (url.url().startsWith(uaCustomURLs[i]))
1622                 return uaCustomValuesForURLs[i];
1623         }
1624     }
1625
1626     if (!m_userAgentStandard.length())
1627         m_userAgentStandard = String::format("Mozilla/5.0 (Windows; U; %s; %s) AppleWebKit/%s (KHTML, like Gecko)%s%s", osVersion().latin1().data(), language().latin1().data(), webKitVersion().latin1().data(), (m_applicationName.length() ? " " : ""), m_applicationName.latin1().data());
1628     return m_userAgentStandard;
1629 }
1630
1631 // IUnknown -------------------------------------------------------------------
1632
1633 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
1634 {
1635     *ppvObject = 0;
1636     if (IsEqualGUID(riid, CLSID_WebView))
1637         *ppvObject = this;
1638     else if (IsEqualGUID(riid, IID_IUnknown))
1639         *ppvObject = static_cast<IWebView*>(this);
1640     else if (IsEqualGUID(riid, IID_IWebView))
1641         *ppvObject = static_cast<IWebView*>(this);
1642     else if (IsEqualGUID(riid, IID_IWebViewPrivate))
1643         *ppvObject = static_cast<IWebViewPrivate*>(this);
1644     else if (IsEqualGUID(riid, IID_IWebIBActions))
1645         *ppvObject = static_cast<IWebIBActions*>(this);
1646     else if (IsEqualGUID(riid, IID_IWebViewCSS))
1647         *ppvObject = static_cast<IWebViewCSS*>(this);
1648     else if (IsEqualGUID(riid, IID_IWebViewEditing))
1649         *ppvObject = static_cast<IWebViewEditing*>(this);
1650     else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
1651         *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
1652     else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
1653         *ppvObject = static_cast<IWebViewEditingActions*>(this);
1654     else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
1655         *ppvObject = static_cast<IWebNotificationObserver*>(this);
1656     else if (IsEqualGUID(riid, IID_IDropTarget))
1657         *ppvObject = static_cast<IDropTarget*>(this);
1658     else
1659         return E_NOINTERFACE;
1660
1661     AddRef();
1662     return S_OK;
1663 }
1664
1665 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
1666 {
1667     return ++m_refCount;
1668 }
1669
1670 ULONG STDMETHODCALLTYPE WebView::Release(void)
1671 {
1672     ULONG newRef = --m_refCount;
1673     if (!newRef)
1674         delete(this);
1675
1676     return newRef;
1677 }
1678
1679 // IWebView --------------------------------------------------------------------
1680
1681 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType( 
1682     /* [in] */ BSTR mimeType,
1683     /* [retval][out] */ BOOL* canShow)
1684 {
1685     String mimeTypeStr(mimeType, SysStringLen(mimeType));
1686
1687     if (!canShow)
1688         return E_POINTER;
1689
1690     *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) ||
1691         MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) ||
1692         PlugInInfoStore::supportsMIMEType(mimeTypeStr);
1693     
1694     return S_OK;
1695 }
1696
1697 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML( 
1698     /* [in] */ BSTR /*mimeType*/,
1699     /* [retval][out] */ BOOL* canShow)
1700 {
1701     // FIXME
1702     *canShow = TRUE;
1703     return S_OK;
1704 }
1705
1706 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML( 
1707     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
1708 {
1709     ASSERT_NOT_REACHED();
1710     return E_NOTIMPL;
1711 }
1712
1713 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML( 
1714         /* [size_is][in] */ BSTR* /*mimeTypes*/,
1715         /* [in] */ int /*cMimeTypes*/)
1716 {
1717     ASSERT_NOT_REACHED();
1718     return E_NOTIMPL;
1719 }
1720
1721 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard( 
1722     /* [in] */ IDataObject* /*pasteboard*/,
1723     /* [retval][out] */ BSTR* /*url*/)
1724 {
1725     ASSERT_NOT_REACHED();
1726     return E_NOTIMPL;
1727 }
1728
1729 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard( 
1730     /* [in] */ IDataObject* /*pasteboard*/,
1731     /* [retval][out] */ BSTR* /*urlTitle*/)
1732 {
1733     ASSERT_NOT_REACHED();
1734     return E_NOTIMPL;
1735 }
1736
1737 HRESULT STDMETHODCALLTYPE WebView::initWithFrame( 
1738     /* [in] */ RECT frame,
1739     /* [in] */ BSTR frameName,
1740     /* [in] */ BSTR groupName)
1741 {
1742     HRESULT hr = S_OK;
1743
1744     if (m_viewWindow)
1745         return E_FAIL;
1746
1747     registerWebViewWindowClass();
1748
1749     if (!::IsWindow(m_hostWindow)) {
1750         ASSERT_NOT_REACHED();
1751         return E_FAIL;
1752     }
1753
1754     m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPCHILDREN,
1755         frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow, 0, gInstance, 0);
1756     ASSERT(::IsWindow(m_viewWindow));
1757
1758     hr = registerDragDrop();
1759     if (FAILED(hr))
1760         return hr;
1761
1762     m_groupName = String(groupName, SysStringLen(groupName));
1763
1764     m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this));
1765     // FIXME: 4931464 - When we do cache pages on Windows this needs to be removed so the "should I cache this page?" check
1766     // in FrameLoader::provisionalLoadStarted() doesn't always fail
1767     m_page->settings()->setUsesPageCache(false);
1768
1769     // Try to set the FTP Directory template path in WebCore when the first WebView is initialized
1770     static bool setFTPDirectoryTemplatePathOnce = false;
1771
1772     if (!setFTPDirectoryTemplatePathOnce && m_uiDelegate) {
1773         COMPtr<IWebUIDelegate2> uiDelegate2;
1774         if (SUCCEEDED(m_uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2))) {
1775             BSTR path;
1776             if (SUCCEEDED(uiDelegate2->ftpDirectoryTemplatePath(this, &path))) {
1777                 m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path)));
1778                 SysFreeString(path);
1779                 setFTPDirectoryTemplatePathOnce = true;
1780             }
1781         }
1782     }
1783
1784     WebFrame* webFrame = WebFrame::createInstance();
1785     webFrame->initWithWebFrameView(0 /*FIXME*/, this, m_page, 0);
1786     m_mainFrame = webFrame;
1787     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
1788
1789
1790     m_page->mainFrame()->tree()->setName(String(frameName, SysStringLen(frameName)));
1791     m_page->mainFrame()->init();
1792     m_page->setGroupName(m_groupName);
1793
1794     #pragma warning(suppress: 4244)
1795     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
1796     ShowWindow(m_viewWindow, SW_SHOW);
1797
1798     initializeCacheSizesIfNecessary();
1799     initializeToolTipWindow();
1800
1801     // Update WebCore with preferences.  These values will either come from an archived WebPreferences,
1802     // or from the standard preferences, depending on whether this method was called from initWithCoder:
1803     // or initWithFrame, respectively.
1804     //[self _updateWebCoreSettingsFromPreferences: [self preferences]];
1805     COMPtr<IWebPreferences> prefs;
1806     if (FAILED(preferences(&prefs)))
1807         return hr;
1808     hr = updateWebCoreSettingsFromPreferences(prefs.get());
1809     if (FAILED(hr))
1810         return hr;
1811
1812     // Use default cookie storage
1813     RetainPtr<CFHTTPCookieStorageRef> cookies(AdoptCF, CFHTTPCookieStorageCreateFromFile(kCFAllocatorDefault, 0, 0));
1814     ResourceHandle::setCookieStorage(cookies.get());
1815
1816     // Register to receive notifications whenever preference values change.
1817     //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1818     //                                             name:WebPreferencesChangedNotification object:[self preferences]];
1819     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
1820     if (!WebPreferences::webPreferencesChangedNotification())
1821         return E_OUTOFMEMORY;
1822     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), prefs.get());
1823
1824     setSmartInsertDeleteEnabled(TRUE);
1825     return hr;
1826 }
1827
1828 static bool initCommonControls()
1829 {
1830     static bool haveInitialized = false;
1831     if (haveInitialized)
1832         return true;
1833
1834     INITCOMMONCONTROLSEX init;
1835     init.dwSize = sizeof(init);
1836     init.dwICC = ICC_TREEVIEW_CLASSES;
1837     haveInitialized = !!::InitCommonControlsEx(&init);
1838     return haveInitialized;
1839 }
1840
1841 void WebView::initializeToolTipWindow()
1842 {
1843     if (!initCommonControls())
1844         return;
1845
1846     m_toolTipHwnd = CreateWindowEx(0, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
1847                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1848                                    m_viewWindow, 0, 0, 0);
1849     if (!m_toolTipHwnd)
1850         return;
1851
1852     TOOLINFO info = {0};
1853     info.cbSize = sizeof(info);
1854     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
1855     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
1856
1857     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
1858     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
1859
1860     ::SetWindowPos(m_toolTipHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1861 }
1862
1863 void WebView::setToolTip(const String& toolTip)
1864 {
1865     if (!m_toolTipHwnd)
1866         return;
1867
1868     if (toolTip == m_toolTip)
1869         return;
1870
1871     m_toolTip = toolTip;
1872
1873     if (!m_toolTip.isEmpty()) {
1874         TOOLINFO info = {0};
1875         info.cbSize = sizeof(info);
1876         info.uFlags = TTF_IDISHWND;
1877         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
1878         info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination());
1879         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
1880     }
1881
1882     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
1883 }
1884
1885 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate( 
1886     /* [in] */ IWebUIDelegate* d)
1887 {
1888     m_uiDelegate = d;
1889
1890     if (m_uiDelegatePrivate)
1891         m_uiDelegatePrivate = 0;
1892
1893     if (d) {
1894         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
1895             m_uiDelegatePrivate = 0;
1896     }
1897
1898     return S_OK;
1899 }
1900
1901 HRESULT STDMETHODCALLTYPE WebView::uiDelegate( 
1902     /* [out][retval] */ IWebUIDelegate** d)
1903 {
1904     if (!m_uiDelegate)
1905         return E_FAIL;
1906
1907     return m_uiDelegate.copyRefTo(d);
1908 }
1909
1910 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate( 
1911     /* [in] */ IWebResourceLoadDelegate* d)
1912 {
1913     m_resourceLoadDelegate = d;
1914     return S_OK;
1915 }
1916
1917 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate( 
1918     /* [out][retval] */ IWebResourceLoadDelegate** d)
1919 {
1920     if (!m_resourceLoadDelegate)
1921         return E_FAIL;
1922
1923     return m_resourceLoadDelegate.copyRefTo(d);
1924 }
1925
1926 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate( 
1927     /* [in] */ IWebDownloadDelegate* d)
1928 {
1929     m_downloadDelegate = d;
1930     return S_OK;
1931 }
1932
1933 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate( 
1934     /* [out][retval] */ IWebDownloadDelegate** d)
1935 {
1936     if (!m_downloadDelegate)
1937         return E_FAIL;
1938
1939     return m_downloadDelegate.copyRefTo(d);
1940 }
1941
1942 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate( 
1943     /* [in] */ IWebFrameLoadDelegate* d)
1944 {
1945     m_frameLoadDelegate = d;
1946     return S_OK;
1947 }
1948
1949 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate( 
1950     /* [out][retval] */ IWebFrameLoadDelegate** d)
1951 {
1952     if (!m_frameLoadDelegate)
1953         return E_FAIL;
1954
1955     return m_frameLoadDelegate.copyRefTo(d);
1956 }
1957
1958 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate( 
1959     /* [in] */ IWebPolicyDelegate* d)
1960 {
1961     m_policyDelegate = d;
1962     return S_OK;
1963 }
1964
1965 HRESULT STDMETHODCALLTYPE WebView::policyDelegate( 
1966     /* [out][retval] */ IWebPolicyDelegate** d)
1967 {
1968     if (!m_policyDelegate)
1969         return E_FAIL;
1970     return m_policyDelegate.copyRefTo(d);
1971 }
1972
1973 HRESULT STDMETHODCALLTYPE WebView::mainFrame( 
1974     /* [out][retval] */ IWebFrame** frame)
1975 {
1976     if (!frame) {
1977         ASSERT_NOT_REACHED();
1978         return E_POINTER;
1979     }
1980
1981     *frame = m_mainFrame;
1982     if (!m_mainFrame)
1983         return E_FAIL;
1984
1985     m_mainFrame->AddRef();
1986     return S_OK;
1987 }
1988
1989 HRESULT STDMETHODCALLTYPE WebView::focusedFrame( 
1990     /* [out][retval] */ IWebFrame** frame)
1991 {
1992     if (!frame) {
1993         ASSERT_NOT_REACHED();
1994         return E_POINTER;
1995     }
1996
1997     *frame = 0;
1998     Frame* f = m_page->focusController()->focusedFrame();
1999     if (!f)
2000         return E_FAIL;
2001
2002     WebFrame* webFrame = kit(f);
2003     if (!webFrame)
2004         return E_FAIL;
2005
2006     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
2007 }
2008 HRESULT STDMETHODCALLTYPE WebView::backForwardList( 
2009     /* [out][retval] */ IWebBackForwardList** list)
2010 {
2011     if (!m_useBackForwardList)
2012         return E_FAIL;
2013  
2014     *list = WebBackForwardList::createInstance(m_page->backForwardList());
2015
2016     return S_OK;
2017 }
2018
2019 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList( 
2020     /* [in] */ BOOL flag)
2021 {
2022     m_useBackForwardList = !!flag;
2023     return S_OK;
2024 }
2025
2026 HRESULT STDMETHODCALLTYPE WebView::goBack( 
2027     /* [retval][out] */ BOOL* succeeded)
2028 {
2029     *succeeded = m_page->goBack();
2030     return S_OK;
2031 }
2032
2033 HRESULT STDMETHODCALLTYPE WebView::goForward( 
2034     /* [retval][out] */ BOOL* succeeded)
2035 {
2036     *succeeded = m_page->goForward();
2037     return S_OK;
2038 }
2039
2040 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem( 
2041     /* [in] */ IWebHistoryItem* item,
2042     /* [retval][out] */ BOOL* succeeded)
2043 {
2044     *succeeded = FALSE;
2045
2046     COMPtr<WebHistoryItem> webHistoryItem;
2047     HRESULT hr = item->QueryInterface(CLSID_WebHistoryItem, (void**)&webHistoryItem);
2048     if (FAILED(hr))
2049         return hr;
2050
2051     m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward);
2052     *succeeded = TRUE;
2053
2054     return S_OK;
2055 }
2056
2057 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier( 
2058     /* [in] */ float multiplier)
2059 {
2060     if (m_textSizeMultiplier != multiplier)
2061         m_textSizeMultiplier = multiplier;
2062     
2063     if (!m_mainFrame)
2064         return E_FAIL;
2065
2066     m_mainFrame->setTextSizeMultiplier(multiplier);
2067     return S_OK;
2068 }
2069
2070 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier( 
2071     /* [retval][out] */ float* multiplier)
2072 {
2073     *multiplier = m_textSizeMultiplier;
2074     return S_OK;
2075 }
2076
2077 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent( 
2078     /* [in] */ BSTR applicationName)
2079 {
2080     m_applicationName = String(applicationName, SysStringLen(applicationName));
2081     m_userAgentStandard = String();
2082     return S_OK;
2083 }
2084
2085 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent( 
2086     /* [retval][out] */ BSTR* applicationName)
2087 {
2088     *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length());
2089     if (!*applicationName && m_applicationName.length())
2090         return E_OUTOFMEMORY;
2091     return S_OK;
2092 }
2093
2094 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent( 
2095     /* [in] */ BSTR userAgentString)
2096 {
2097     m_userAgentOverridden = true;
2098     m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString));
2099     return S_OK;
2100 }
2101
2102 HRESULT STDMETHODCALLTYPE WebView::customUserAgent( 
2103     /* [retval][out] */ BSTR* userAgentString)
2104 {
2105     *userAgentString = 0;
2106     if (!m_userAgentOverridden)
2107         return S_OK;
2108     *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length());
2109     if (!*userAgentString && m_userAgentCustom.length())
2110         return E_OUTOFMEMORY;
2111     return S_OK;
2112 }
2113
2114 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL( 
2115     /* [in] */ BSTR url,
2116     /* [retval][out] */ BSTR* userAgent)
2117 {
2118     DeprecatedString urlStr((DeprecatedChar*)url, SysStringLen(url));
2119     String userAgentString = this->userAgentForKURL(KURL(urlStr));
2120     *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length());
2121     if (!*userAgent && userAgentString.length())
2122         return E_OUTOFMEMORY;
2123     return S_OK;
2124 }
2125
2126 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding( 
2127     /* [retval][out] */ BOOL* supports)
2128 {
2129     *supports = TRUE;
2130     return S_OK;
2131 }
2132
2133 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName( 
2134     /* [in] */ BSTR encodingName)
2135 {
2136     if (!m_mainFrame)
2137         return E_FAIL;
2138
2139     HRESULT hr;
2140     BSTR oldEncoding;
2141     hr = customTextEncodingName(&oldEncoding);
2142     if (FAILED(hr))
2143         return hr;
2144
2145     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || _tcscmp(oldEncoding, encodingName))) {
2146         if (Frame* coreFrame = core(m_mainFrame))
2147             coreFrame->loader()->reloadAllowingStaleData(String(encodingName, SysStringLen(encodingName)));
2148     }
2149
2150     return S_OK;
2151 }
2152
2153 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName( 
2154     /* [retval][out] */ BSTR* encodingName)
2155 {
2156     HRESULT hr = S_OK;
2157     COMPtr<IWebDataSource> dataSource;
2158     COMPtr<WebDataSource> dataSourceImpl;
2159     *encodingName = 0;
2160
2161     if (!m_mainFrame)
2162         return E_FAIL;
2163
2164     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
2165         hr = m_mainFrame->dataSource(&dataSource);
2166         if (FAILED(hr) || !dataSource)
2167             return hr;
2168     }
2169
2170     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
2171     if (FAILED(hr))
2172         return hr;
2173
2174     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
2175     if (FAILED(hr))
2176         return hr;
2177
2178     if (!*encodingName)
2179         *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length());
2180
2181     if (!*encodingName && m_overrideEncoding.length())
2182         return E_OUTOFMEMORY;
2183
2184     return S_OK;
2185 }
2186
2187 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle( 
2188     /* [in] */ BSTR /*media*/)
2189 {
2190     ASSERT_NOT_REACHED();
2191     return E_NOTIMPL;
2192 }
2193
2194 HRESULT STDMETHODCALLTYPE WebView::mediaStyle( 
2195     /* [retval][out] */ BSTR* /*media*/)
2196 {
2197     ASSERT_NOT_REACHED();
2198     return E_NOTIMPL;
2199 }
2200
2201 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString( 
2202     /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
2203     /* [retval][out] */ BSTR* result)
2204 {
2205     if (!result) {
2206         ASSERT_NOT_REACHED();
2207         return E_POINTER;
2208     }
2209
2210     *result = 0;
2211
2212     Frame* coreFrame = core(m_mainFrame);
2213     if (!coreFrame)
2214         return E_FAIL;
2215
2216     KJS::JSValue* scriptExecutionResult = coreFrame->loader()->executeScript(WebCore::String(script), true);
2217     if(!scriptExecutionResult)
2218         return E_FAIL;
2219     else if (scriptExecutionResult->isString()) {
2220         JSLock lock;
2221         *result = BString(String(scriptExecutionResult->getString()));
2222     }
2223
2224     return S_OK;
2225 }
2226
2227 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject( 
2228     /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
2229 {
2230     ASSERT_NOT_REACHED();
2231     return E_NOTIMPL;
2232 }
2233
2234 HRESULT STDMETHODCALLTYPE WebView::setPreferences( 
2235     /* [in] */ IWebPreferences* prefs)
2236 {
2237     if (m_preferences == prefs)
2238         return S_OK;
2239
2240     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2241     COMPtr<IWebPreferences> oldPrefs;
2242     if (SUCCEEDED(preferences(&oldPrefs)) && oldPrefs) {
2243         nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), oldPrefs.get());
2244         BSTR identifier = 0;
2245         HRESULT hr = oldPrefs->identifier(&identifier);
2246         oldPrefs = 0;   // make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
2247         if (SUCCEEDED(hr))
2248             WebPreferences::removeReferenceForIdentifier(identifier);
2249         if (identifier)
2250             SysFreeString(identifier);
2251     }
2252     m_preferences = prefs;
2253     COMPtr<IWebPreferences> newPrefs;
2254     if (SUCCEEDED(preferences(&newPrefs)))
2255         nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), newPrefs.get());
2256     HRESULT hr = nc->postNotificationName(WebPreferences::webPreferencesChangedNotification(), newPrefs.get(), 0);
2257     if (FAILED(hr))
2258         return hr;
2259
2260     return S_OK;
2261 }
2262
2263 HRESULT STDMETHODCALLTYPE WebView::preferences( 
2264     /* [retval][out] */ IWebPreferences** prefs)
2265 {
2266     HRESULT hr = S_OK;
2267
2268     if (!m_preferences) {
2269         WebPreferences* instance = WebPreferences::createInstance();
2270         if (!instance)
2271             return E_FAIL;
2272         hr = instance->standardPreferences(&m_preferences);
2273         instance->Release();
2274     }
2275
2276     m_preferences.copyRefTo(prefs);
2277     return hr;
2278 }
2279
2280 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier( 
2281     /* [in] */ BSTR /*anIdentifier*/)
2282 {
2283     ASSERT_NOT_REACHED();
2284     return E_NOTIMPL;
2285 }
2286
2287 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier( 
2288     /* [retval][out] */ BSTR* /*anIdentifier*/)
2289 {
2290     ASSERT_NOT_REACHED();
2291     return E_NOTIMPL;
2292 }
2293
2294 HRESULT STDMETHODCALLTYPE WebView::setHostWindow( 
2295     /* [in] */ OLE_HANDLE oleWindow)
2296 {
2297     HWND window = (HWND)(ULONG64)oleWindow;
2298     if (m_viewWindow && window)
2299         SetParent(m_viewWindow, window);
2300
2301     m_hostWindow = window;
2302
2303     return S_OK;
2304 }
2305
2306 HRESULT STDMETHODCALLTYPE WebView::hostWindow( 
2307     /* [retval][out] */ OLE_HANDLE* window)
2308 {
2309     *window = (OLE_HANDLE)(ULONG64)m_hostWindow;
2310     return S_OK;
2311 }
2312
2313
2314 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
2315 {
2316     return forward
2317         ? curr->tree()->traverseNextWithWrap(wrapFlag)
2318         : curr->tree()->traversePreviousWithWrap(wrapFlag);
2319 }
2320
2321 HRESULT STDMETHODCALLTYPE WebView::searchFor( 
2322     /* [in] */ BSTR str,
2323     /* [in] */ BOOL forward,
2324     /* [in] */ BOOL caseFlag,
2325     /* [in] */ BOOL wrapFlag,
2326     /* [retval][out] */ BOOL* found)
2327 {
2328     if (!found)
2329         return E_INVALIDARG;
2330     
2331     if (!m_page || !m_page->mainFrame())
2332         return E_UNEXPECTED;
2333
2334     if (!str || !SysStringLen(str))
2335         return E_INVALIDARG;
2336
2337     String search(str, SysStringLen(str));
2338
2339
2340     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2341     WebCore::Frame* startFrame = frame;
2342     do {
2343         *found = frame->findString(search, !!forward, !!caseFlag, false, true);
2344         if (*found) {
2345             if (frame != startFrame)
2346                 startFrame->selectionController()->clear();
2347             m_page->focusController()->setFocusedFrame(frame);
2348             return S_OK;
2349         }
2350         frame = incrementFrame(frame, !!forward, !!wrapFlag);
2351     } while (frame && frame != startFrame);
2352
2353     // Search contents of startFrame, on the other side of the selection that we did earlier.
2354     // We cheat a bit and just research with wrap on
2355     if (wrapFlag && !startFrame->selectionController()->isNone()) {
2356         *found = startFrame->findString(search, !!forward, !!caseFlag, true, true);
2357         m_page->focusController()->setFocusedFrame(frame);
2358     }
2359
2360     return S_OK;
2361 }
2362
2363 HRESULT STDMETHODCALLTYPE WebView::updateActiveState()
2364 {
2365     Frame* frame = m_page->mainFrame();
2366
2367     HWND window = ::GetAncestor(m_viewWindow, GA_ROOT);
2368     HWND activeWindow = ::GetActiveWindow();
2369     bool windowIsKey = window == activeWindow;
2370     activeWindow = ::GetAncestor(activeWindow, GA_ROOTOWNER);
2371
2372     bool windowOrSheetIsKey = windowIsKey || (window == activeWindow);
2373
2374     frame->setIsActive(windowIsKey);            
2375
2376     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
2377     frame->setWindowHasFocus(frame == focusedFrame && windowOrSheetIsKey);
2378
2379     return S_OK;
2380 }
2381
2382 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
2383     BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
2384 {
2385     if (!matches)
2386         return E_INVALIDARG;
2387
2388     if (!m_page || !m_page->mainFrame())
2389         return E_UNEXPECTED;
2390
2391     if (!str || !SysStringLen(str))
2392         return E_INVALIDARG;
2393
2394     String search(str, SysStringLen(str));
2395     *matches = 0;
2396
2397     WebCore::Frame* frame = m_page->mainFrame();
2398     do {
2399         frame->setMarkedTextMatchesAreHighlighted(!!highlight);
2400         *matches += frame->markAllMatchesForText(search, !!caseSensitive, (limit == 0)? 0 : (limit - *matches));
2401         frame = incrementFrame(frame, true, false);
2402     } while (frame);
2403
2404     return S_OK;
2405
2406 }
2407
2408 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
2409 {
2410     if (!m_page || !m_page->mainFrame())
2411         return E_UNEXPECTED;
2412
2413     WebCore::Frame* frame = m_page->mainFrame();
2414     do {
2415         if (Document* document = frame->document())
2416             document->removeMarkers(DocumentMarker::TextMatch);
2417         frame = incrementFrame(frame, true, false);
2418     } while (frame);
2419
2420
2421     return S_OK;
2422 }
2423
2424 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
2425     IEnumTextMatches** pmatches)
2426 {
2427     Vector<IntRect> allRects;
2428     WebCore::Frame* frame = m_page->mainFrame();
2429     do {
2430         if (Document* document = frame->document()) {
2431             Vector<IntRect> frameRects = document->renderedRectsForMarkers(DocumentMarker::TextMatch);
2432             IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
2433             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
2434
2435             Vector<IntRect>::iterator end = frameRects.end();
2436             for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
2437                 it->move(frameOffset.x(), frameOffset.y());
2438                 allRects.append(*it);
2439             }
2440         }
2441         frame = incrementFrame(frame, true, false);
2442     } while (frame);
2443
2444     return createMatchEnumerator(&allRects, pmatches);
2445 }
2446
2447 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap)
2448 {
2449     *hBitmap = 0;
2450
2451     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2452
2453     if (frame) {
2454         HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE);
2455         *hBitmap = (OLE_HANDLE)(ULONG64)bitmap;
2456     }
2457
2458     return S_OK;
2459 }
2460
2461 HRESULT STDMETHODCALLTYPE WebView::selectionImageRect(RECT* rc)
2462 {
2463     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2464
2465     if (frame) {
2466         IntRect ir = enclosingIntRect(frame->selectionRect());
2467         ir = frame->view()->convertToContainingWindow(ir);
2468         ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
2469         rc->left = ir.x();
2470         rc->top = ir.y();
2471         rc->bottom = rc->top + ir.height();
2472         rc->right = rc->left + ir.width();
2473     }
2474
2475     return S_OK;
2476 }
2477
2478 HRESULT STDMETHODCALLTYPE WebView::registerViewClass( 
2479     /* [in] */ IWebDocumentView* /*view*/,
2480     /* [in] */ IWebDocumentRepresentation* /*representation*/,
2481     /* [in] */ BSTR /*forMIMEType*/)
2482 {
2483     ASSERT_NOT_REACHED();
2484     return E_NOTIMPL;
2485 }
2486
2487 HRESULT STDMETHODCALLTYPE WebView::setGroupName( 
2488         /* [in] */ BSTR groupName)
2489 {
2490     m_groupName = String(groupName, SysStringLen(groupName));
2491     return S_OK;
2492 }
2493     
2494 HRESULT STDMETHODCALLTYPE WebView::groupName( 
2495         /* [retval][out] */ BSTR* groupName)
2496 {
2497     *groupName = SysAllocStringLen(m_groupName.characters(), m_groupName.length());
2498     if (!*groupName && m_groupName.length())
2499         return E_OUTOFMEMORY;
2500     return S_OK;
2501 }
2502     
2503 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress( 
2504         /* [retval][out] */ double* estimatedProgress)
2505 {
2506     *estimatedProgress = m_page->progress()->estimatedProgress();
2507     return S_OK;
2508 }
2509     
2510 HRESULT STDMETHODCALLTYPE WebView::isLoading( 
2511         /* [retval][out] */ BOOL* isLoading)
2512 {
2513     COMPtr<IWebDataSource> dataSource;
2514     COMPtr<IWebDataSource> provisionalDataSource;
2515
2516     if (!isLoading)
2517         return E_POINTER;
2518
2519     *isLoading = FALSE;
2520
2521     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
2522         dataSource->isLoading(isLoading);
2523
2524     if (*isLoading)
2525         return S_OK;
2526
2527     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
2528         provisionalDataSource->isLoading(isLoading);
2529     return S_OK;
2530 }
2531     
2532 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint( 
2533         /* [in] */ LPPOINT point,
2534         /* [retval][out] */ IPropertyBag** elementDictionary)
2535 {
2536     if (!elementDictionary) {
2537         ASSERT_NOT_REACHED();
2538         return E_POINTER;
2539     }
2540
2541     *elementDictionary = 0;
2542
2543     Frame* frame = core(m_mainFrame);
2544     if (!frame)
2545         return E_FAIL;
2546
2547     IntPoint webCorePoint = IntPoint(point->x, point->y);
2548     HitTestResult result = HitTestResult(webCorePoint);
2549     if (frame->renderer())
2550         result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false);
2551     *elementDictionary = WebElementPropertyBag::createInstance(result);
2552     return S_OK;
2553 }
2554     
2555 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection( 
2556     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2557 {
2558     ASSERT_NOT_REACHED();
2559     return E_NOTIMPL;
2560 }
2561     
2562 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes( 
2563         /* [size_is][in] */ BSTR* /*types*/,
2564         /* [in] */ int /*cTypes*/,
2565         /* [in] */ IDataObject* /*pasteboard*/)
2566 {
2567     ASSERT_NOT_REACHED();
2568     return E_NOTIMPL;
2569 }
2570     
2571 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement( 
2572     /* [in] */ IPropertyBag* /*elementDictionary*/,
2573     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2574 {
2575     ASSERT_NOT_REACHED();
2576     return E_NOTIMPL;
2577 }
2578     
2579 HRESULT STDMETHODCALLTYPE WebView::writeElement( 
2580         /* [in] */ IPropertyBag* /*elementDictionary*/,
2581         /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
2582         /* [in] */ int /*cWithPasteboardTypes*/,
2583         /* [in] */ IDataObject* /*pasteboard*/)
2584 {
2585     ASSERT_NOT_REACHED();
2586     return E_NOTIMPL;
2587 }
2588     
2589 HRESULT STDMETHODCALLTYPE WebView::selectedText(
2590         /* [out, retval] */ BSTR* text)
2591 {
2592     if (!text) {
2593         ASSERT_NOT_REACHED();
2594         return E_POINTER;
2595     }
2596
2597     *text = 0;
2598
2599     Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0;
2600     if (!focusedFrame)
2601         return E_FAIL;
2602
2603     String frameSelectedText = focusedFrame->selectedText();
2604     *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length());
2605     if (!*text && frameSelectedText.length())
2606         return E_OUTOFMEMORY;
2607     return S_OK;
2608 }
2609
2610 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
2611         /* [in] */ IUnknown* /* sender */)
2612 {
2613     Frame* coreFrame = core(m_mainFrame);
2614     if (!coreFrame)
2615         return E_FAIL;
2616
2617     coreFrame->revealSelection(RenderLayer::gAlignCenterAlways);
2618     return S_OK;
2619 }
2620
2621
2622 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint( 
2623         /* [in] */ LPPOINT /*point*/)
2624 {
2625     ASSERT_NOT_REACHED();
2626     return E_NOTIMPL;
2627 }
2628     
2629 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
2630 {
2631     ASSERT_NOT_REACHED();
2632     return E_NOTIMPL;
2633 }
2634     
2635 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground( 
2636         /* [in] */ BOOL /*drawsBackground*/)
2637 {
2638     ASSERT_NOT_REACHED();
2639     return E_NOTIMPL;
2640 }
2641     
2642 HRESULT STDMETHODCALLTYPE WebView::drawsBackground( 
2643         /* [retval][out] */ BOOL* /*drawsBackground*/)
2644 {
2645     ASSERT_NOT_REACHED();
2646     return E_NOTIMPL;
2647 }
2648     
2649 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL( 
2650         /* [in] */ BSTR /*urlString*/)
2651 {
2652     ASSERT_NOT_REACHED();
2653     return E_NOTIMPL;
2654 }
2655     
2656 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL( 
2657         /* [retval][out] */ BSTR* /*urlString*/)
2658 {
2659     ASSERT_NOT_REACHED();
2660     return E_NOTIMPL;
2661 }
2662     
2663 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument( 
2664         /* [retval][out] */ IDOMDocument** document)
2665 {
2666     if (document)
2667         *document = 0;
2668     if (!m_mainFrame)
2669         return E_FAIL;
2670     return m_mainFrame->DOMDocument(document);
2671 }
2672     
2673 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle( 
2674         /* [retval][out] */ BSTR* /*title*/)
2675 {
2676     ASSERT_NOT_REACHED();
2677     return E_NOTIMPL;
2678 }
2679     
2680 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon( 
2681         /* [retval][out] */ OLE_HANDLE* /*hBitmap*/)
2682 {
2683     ASSERT_NOT_REACHED();
2684     return E_NOTIMPL;
2685 }
2686
2687 // IWebIBActions ---------------------------------------------------------------
2688
2689 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom( 
2690         /* [in] */ IUnknown* /*sender*/)
2691 {
2692     ASSERT_NOT_REACHED();
2693     return E_NOTIMPL;
2694 }
2695     
2696 HRESULT STDMETHODCALLTYPE WebView::stopLoading( 
2697         /* [in] */ IUnknown* /*sender*/)
2698 {
2699     if (!m_mainFrame)
2700         return E_FAIL;
2701
2702     return m_mainFrame->stopLoading();
2703 }
2704     
2705 HRESULT STDMETHODCALLTYPE WebView::reload( 
2706         /* [in] */ IUnknown* /*sender*/)
2707 {
2708     if (!m_mainFrame)
2709         return E_FAIL;
2710
2711     return m_mainFrame->reload();
2712 }
2713     
2714 HRESULT STDMETHODCALLTYPE WebView::canGoBack( 
2715         /* [in] */ IUnknown* /*sender*/,
2716         /* [retval][out] */ BOOL* result)
2717 {
2718     *result = !!m_page->backForwardList()->backItem();
2719     return S_OK;
2720 }
2721     
2722 HRESULT STDMETHODCALLTYPE WebView::goBack( 
2723         /* [in] */ IUnknown* /*sender*/)
2724 {
2725     ASSERT_NOT_REACHED();
2726     return E_NOTIMPL;
2727 }
2728     
2729 HRESULT STDMETHODCALLTYPE WebView::canGoForward( 
2730         /* [in] */ IUnknown* /*sender*/,
2731         /* [retval][out] */ BOOL* result)
2732 {
2733     *result = !!m_page->backForwardList()->forwardItem();
2734     return S_OK;
2735 }
2736     
2737 HRESULT STDMETHODCALLTYPE WebView::goForward( 
2738         /* [in] */ IUnknown* /*sender*/)
2739 {
2740     ASSERT_NOT_REACHED();
2741     return E_NOTIMPL;
2742 }
2743
2744 #define MinimumTextSizeMultiplier   0.5f
2745 #define MaximumTextSizeMultiplier   3.0f
2746 #define TextSizeMultiplierRatio     1.2f
2747
2748 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger( 
2749         /* [in] */ IUnknown* /*sender*/,
2750         /* [retval][out] */ BOOL* result)
2751 {
2752     bool canGrowMore = m_textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
2753     *result = canGrowMore ? TRUE : FALSE;
2754     return S_OK;
2755 }
2756     
2757 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger( 
2758         /* [in] */ IUnknown* /*sender*/)
2759 {
2760     float newScale = m_textSizeMultiplier*TextSizeMultiplierRatio;
2761     bool canGrowMore = newScale < MaximumTextSizeMultiplier;
2762     if (!canGrowMore)
2763         return E_FAIL;
2764     return setTextSizeMultiplier(newScale);
2765
2766 }
2767     
2768 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller( 
2769         /* [in] */ IUnknown* /*sender*/,
2770         /* [retval][out] */ BOOL* result)
2771 {
2772     bool canShrinkMore = m_textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
2773     *result = canShrinkMore ? TRUE : FALSE;
2774     return S_OK;
2775 }
2776
2777 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller( 
2778         /* [in] */ IUnknown* /*sender*/)
2779 {
2780     float newScale = m_textSizeMultiplier/TextSizeMultiplierRatio;
2781     bool canShrinkMore = newScale > MinimumTextSizeMultiplier;
2782     if (!canShrinkMore)
2783         return E_FAIL;
2784     return setTextSizeMultiplier(newScale);
2785 }
2786
2787 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize( 
2788     /* [in] */ IUnknown* /*sender*/,
2789     /* [retval][out] */ BOOL* result)
2790 {
2791     bool notAlreadyStandard = m_textSizeMultiplier != 1.0f;
2792     *result = notAlreadyStandard ? TRUE : FALSE;
2793     return S_OK;
2794 }
2795
2796 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize( 
2797     /* [in] */ IUnknown* /*sender*/)
2798 {
2799     bool notAlreadyStandard = m_textSizeMultiplier != 1.0f;
2800     if (notAlreadyStandard)
2801         return setTextSizeMultiplier(1.0f);
2802     return S_OK;
2803 }
2804
2805 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking( 
2806     /* [in] */ IUnknown* /*sender*/)
2807 {
2808     HRESULT hr;
2809     BOOL enabled;
2810     if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
2811         return hr;
2812     return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
2813 }
2814
2815 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete( 
2816     /* [in] */ IUnknown* /*sender*/)
2817 {
2818     BOOL enabled = FALSE;
2819     HRESULT hr = smartInsertDeleteEnabled(&enabled);
2820     if (FAILED(hr))
2821         return hr;
2822
2823     return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
2824 }
2825
2826 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking( 
2827     /* [in] */ IUnknown* /*sender*/)
2828 {
2829     BOOL enabled;
2830     HRESULT hr = isGrammarCheckingEnabled(&enabled);
2831     if (FAILED(hr))
2832         return hr;
2833
2834     return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
2835 }
2836
2837 // IWebViewCSS -----------------------------------------------------------------
2838
2839 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement( 
2840         /* [in] */ IDOMElement* /*element*/,
2841         /* [in] */ BSTR /*pseudoElement*/,
2842         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
2843 {
2844     ASSERT_NOT_REACHED();
2845     return E_NOTIMPL;
2846 }
2847
2848 // IWebViewEditing -------------------------------------------------------------
2849
2850 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint( 
2851         /* [in] */ LPPOINT /*point*/,
2852         /* [retval][out] */ IDOMRange** /*range*/)
2853 {
2854     ASSERT_NOT_REACHED();
2855     return E_NOTIMPL;
2856 }
2857     
2858 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange( 
2859         /* [in] */ IDOMRange* /*range*/,
2860         /* [in] */ WebSelectionAffinity /*affinity*/)
2861 {
2862     ASSERT_NOT_REACHED();
2863     return E_NOTIMPL;
2864 }
2865     
2866 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange( 
2867         /* [retval][out] */ IDOMRange** /*range*/)
2868 {
2869     ASSERT_NOT_REACHED();
2870     return E_NOTIMPL;
2871 }
2872     
2873 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity( 
2874         /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
2875 {
2876     ASSERT_NOT_REACHED();
2877     return E_NOTIMPL;
2878 }
2879     
2880 HRESULT STDMETHODCALLTYPE WebView::setEditable( 
2881         /* [in] */ BOOL /*flag*/)
2882 {
2883     ASSERT_NOT_REACHED();
2884     return E_NOTIMPL;
2885 }
2886     
2887 HRESULT STDMETHODCALLTYPE WebView::isEditable( 
2888         /* [retval][out] */ BOOL* /*isEditable*/)
2889 {
2890     ASSERT_NOT_REACHED();
2891     return E_NOTIMPL;
2892 }
2893     
2894 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle( 
2895         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
2896 {
2897     ASSERT_NOT_REACHED();
2898     return E_NOTIMPL;
2899 }
2900     
2901 HRESULT STDMETHODCALLTYPE WebView::typingStyle( 
2902         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
2903 {
2904     ASSERT_NOT_REACHED();
2905     return E_NOTIMPL;
2906 }
2907     
2908 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled( 
2909         /* [in] */ BOOL flag)
2910 {
2911     m_smartInsertDeleteEnabled = !!flag;
2912     return S_OK;
2913 }
2914     
2915 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled( 
2916         /* [retval][out] */ BOOL* enabled)
2917 {
2918     *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE;
2919     return S_OK;
2920 }
2921     
2922 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled( 
2923         /* [in] */ BOOL flag)
2924 {
2925     if (continuousSpellCheckingEnabled != !!flag) {
2926         continuousSpellCheckingEnabled = !!flag;
2927         COMPtr<IWebPreferences> prefs;
2928         if (SUCCEEDED(preferences(&prefs)))
2929             prefs->setContinuousSpellCheckingEnabled(flag);
2930     }
2931     
2932     BOOL spellCheckingEnabled;
2933     if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
2934         preflightSpellChecker();
2935     else
2936         m_mainFrame->unmarkAllMisspellings();
2937
2938     return S_OK;
2939 }
2940     
2941 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled( 
2942         /* [retval][out] */ BOOL* enabled)
2943 {
2944     *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
2945     return S_OK;
2946 }
2947     
2948 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag( 
2949         /* [retval][out] */ int* tag)
2950 {
2951     // we just use this as a flag to indicate that we've spell checked the document
2952     // and need to close the spell checker out when the view closes.
2953     *tag = 0;
2954     m_hasSpellCheckerDocumentTag = true;
2955     return S_OK;
2956 }
2957
2958 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
2959
2960 static void preflightSpellCheckerNow()
2961 {
2962     spellingDelegateForTimer->preflightChosenSpellServer();
2963     spellingDelegateForTimer = 0;
2964 }
2965
2966 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
2967 {
2968     ::KillTimer(0, id);
2969     preflightSpellCheckerNow();
2970 }
2971
2972 void WebView::preflightSpellChecker()
2973 {
2974     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
2975     if (!m_editingDelegate)
2976         return;
2977
2978     BOOL exists;
2979     spellingDelegateForTimer = m_editingDelegate;
2980     if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists)
2981         preflightSpellCheckerNow();
2982     else
2983         ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback);
2984 }
2985
2986 bool WebView::continuousCheckingAllowed()
2987 {
2988     static bool allowContinuousSpellChecking = true;
2989     static bool readAllowContinuousSpellCheckingDefault = false;
2990     if (!readAllowContinuousSpellCheckingDefault) {
2991         COMPtr<IWebPreferences> prefs;
2992         if (SUCCEEDED(preferences(&prefs))) {
2993             BOOL allowed;
2994             prefs->allowContinuousSpellChecking(&allowed);
2995             allowContinuousSpellChecking = !!allowed;
2996         }
2997         readAllowContinuousSpellCheckingDefault = true;
2998     }
2999     return allowContinuousSpellChecking;
3000 }
3001
3002 HRESULT STDMETHODCALLTYPE WebView::undoManager( 
3003         /* [retval][out] */ IWebUndoManager** /*manager*/)
3004 {
3005     ASSERT_NOT_REACHED();
3006     return E_NOTIMPL;
3007 }
3008     
3009 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate( 
3010         /* [in] */ IWebEditingDelegate* d)
3011 {
3012     m_editingDelegate = d;
3013     return S_OK;
3014 }
3015     
3016 HRESULT STDMETHODCALLTYPE WebView::editingDelegate( 
3017         /* [retval][out] */ IWebEditingDelegate** d)
3018 {
3019     if (!d) {
3020         ASSERT_NOT_REACHED();
3021         return E_POINTER;
3022     }
3023
3024     *d = m_editingDelegate.get();
3025     if (!*d)
3026         return E_FAIL;
3027
3028     (*d)->AddRef();
3029     return S_OK;
3030 }
3031     
3032 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText( 
3033         /* [in] */ BSTR /*text*/,
3034         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
3035 {
3036     ASSERT_NOT_REACHED();
3037     return E_NOTIMPL;
3038 }
3039     
3040 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange( 
3041         /* [retval][out] */ BOOL* hasSelectedRange)
3042 {
3043     *hasSelectedRange = m_page->mainFrame()->selectionController()->isRange();
3044     return S_OK;
3045 }
3046     
3047 HRESULT STDMETHODCALLTYPE WebView::cutEnabled( 
3048         /* [retval][out] */ BOOL* enabled)
3049 {
3050     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3051     *enabled = editor->canCut() || editor->canDHTMLCut();
3052     return S_OK;
3053 }
3054     
3055 HRESULT STDMETHODCALLTYPE WebView::copyEnabled( 
3056         /* [retval][out] */ BOOL* enabled)
3057 {
3058     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3059     *enabled = editor->canCopy() || editor->canDHTMLCopy();
3060     return S_OK;
3061 }
3062     
3063 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled( 
3064         /* [retval][out] */ BOOL* enabled)
3065 {
3066     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3067     *enabled = editor->canPaste() || editor->canDHTMLPaste();
3068     return S_OK;
3069 }
3070     
3071 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled( 
3072         /* [retval][out] */ BOOL* enabled)
3073 {
3074     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete();
3075     return S_OK;
3076 }
3077     
3078 HRESULT STDMETHODCALLTYPE WebView::editingEnabled( 
3079         /* [retval][out] */ BOOL* enabled)
3080 {
3081     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit();
3082     return S_OK;
3083 }
3084
3085 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled( 
3086     /* [retval][out] */ BOOL* enabled)
3087 {
3088     *enabled = grammarCheckingEnabled ? TRUE : FALSE;
3089     return S_OK;
3090 }
3091
3092 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled( 
3093     BOOL enabled)
3094 {
3095     if (grammarCheckingEnabled == !!enabled)
3096         return S_OK;
3097     
3098     grammarCheckingEnabled = !!enabled;
3099     COMPtr<IWebPreferences> prefs;
3100     if (SUCCEEDED(preferences(&prefs)))
3101         prefs->setGrammarCheckingEnabled(enabled);
3102     
3103     m_editingDelegate->updateGrammar();
3104
3105     // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
3106     // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
3107     
3108     BOOL grammarEnabled;
3109     if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled)
3110         m_mainFrame->unmarkAllBadGrammar();
3111
3112     return S_OK;
3113 }
3114
3115 // IWebViewUndoableEditing -----------------------------------------------------
3116
3117 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode( 
3118         /* [in] */ IDOMNode* /*node*/)
3119 {
3120     ASSERT_NOT_REACHED();
3121     return E_NOTIMPL;
3122 }
3123     
3124 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText( 
3125         /* [in] */ BSTR text)
3126 {
3127     String textString(text, ::SysStringLen(text));
3128     Position start = m_page->mainFrame()->selectionController()->selection().start();
3129     m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0);
3130     m_page->mainFrame()->selectionController()->setBase(start);
3131     return S_OK;
3132 }
3133     
3134 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString( 
3135         /* [in] */ BSTR /*markupString*/)
3136 {
3137     ASSERT_NOT_REACHED();
3138     return E_NOTIMPL;
3139 }
3140     
3141 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive( 
3142         /* [in] */ IWebArchive* /*archive*/)
3143 {
3144     ASSERT_NOT_REACHED();
3145     return E_NOTIMPL;
3146 }
3147     
3148 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void)
3149 {
3150     m_page->focusController()->focusedOrMainFrame()->editor()->deleteSelectionWithSmartDelete();
3151     return S_OK;
3152 }
3153
3154 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void)
3155 {
3156     m_page->focusController()->focusedOrMainFrame()->selectionController()->clear();
3157     return S_OK;
3158 }
3159     
3160 HRESULT STDMETHODCALLTYPE WebView::applyStyle( 
3161         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
3162 {
3163     ASSERT_NOT_REACHED();
3164     return E_NOTIMPL;
3165 }
3166
3167 // IWebViewEditingActions ------------------------------------------------------
3168
3169 HRESULT STDMETHODCALLTYPE WebView::copy( 
3170         /* [in] */ IUnknown* /*sender*/)
3171 {
3172     m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Copy");
3173     return S_OK;
3174 }
3175
3176 HRESULT STDMETHODCALLTYPE WebView::cut( 
3177         /* [in] */ IUnknown* /*sender*/)
3178 {
3179     m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Cut");
3180     return S_OK;
3181 }
3182
3183 HRESULT STDMETHODCALLTYPE WebView::paste( 
3184         /* [in] */ IUnknown* /*sender*/)
3185 {
3186     m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Paste");
3187     return S_OK;
3188 }
3189
3190 HRESULT STDMETHODCALLTYPE WebView::copyURL( 
3191         /* [in] */ BSTR url)
3192 {
3193     String temp(url, SysStringLen(url));
3194     m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(KURL(temp.deprecatedString()), "");
3195     return S_OK;
3196 }
3197
3198
3199 HRESULT STDMETHODCALLTYPE WebView::copyFont( 
3200         /* [in] */ IUnknown* /*sender*/)
3201 {
3202     ASSERT_NOT_REACHED();
3203     return E_NOTIMPL;
3204 }
3205     
3206 HRESULT STDMETHODCALLTYPE WebView::pasteFont( 
3207         /* [in] */ IUnknown* /*sender*/)
3208 {
3209     ASSERT_NOT_REACHED();
3210     return E_NOTIMPL;
3211 }
3212     
3213 HRESULT STDMETHODCALLTYPE WebView::delete_( 
3214         /* [in] */ IUnknown* /*sender*/)
3215 {
3216     m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Delete");
3217     return S_OK;
3218 }
3219     
3220 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText( 
3221         /* [in] */ IUnknown* /*sender*/)
3222 {
3223     ASSERT_NOT_REACHED();
3224     return E_NOTIMPL;
3225 }
3226     
3227 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText( 
3228         /* [in] */ IUnknown* /*sender*/)
3229 {
3230     ASSERT_NOT_REACHED();
3231     return E_NOTIMPL;
3232 }
3233     
3234 HRESULT STDMETHODCALLTYPE WebView::changeFont( 
3235         /* [in] */ IUnknown* /*sender*/)
3236 {
3237     ASSERT_NOT_REACHED();
3238     return E_NOTIMPL;
3239 }
3240     
3241 HRESULT STDMETHODCALLTYPE WebView::changeAttributes( 
3242         /* [in] */ IUnknown* /*sender*/)
3243 {
3244     ASSERT_NOT_REACHED();
3245     return E_NOTIMPL;
3246 }
3247     
3248 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor( 
3249         /* [in] */ IUnknown* /*sender*/)
3250 {
3251     ASSERT_NOT_REACHED();
3252     return E_NOTIMPL;
3253 }
3254     
3255 HRESULT STDMETHODCALLTYPE WebView::changeColor( 
3256         /* [in] */ IUnknown* /*sender*/)
3257 {
3258     ASSERT_NOT_REACHED();
3259     return E_NOTIMPL;
3260 }
3261     
3262 HRESULT STDMETHODCALLTYPE WebView::alignCenter( 
3263         /* [in] */ IUnknown* /*sender*/)
3264 {
3265     ASSERT_NOT_REACHED();
3266     return E_NOTIMPL;
3267 }
3268     
3269 HRESULT STDMETHODCALLTYPE WebView::alignJustified( 
3270         /* [in] */ IUnknown* /*sender*/)
3271 {
3272     ASSERT_NOT_REACHED();
3273     return E_NOTIMPL;
3274 }
3275     
3276 HRESULT STDMETHODCALLTYPE WebView::alignLeft( 
3277         /* [in] */ IUnknown* /*sender*/)
3278 {
3279     ASSERT_NOT_REACHED();
3280     return E_NOTIMPL;
3281 }
3282     
3283 HRESULT STDMETHODCALLTYPE WebView::alignRight( 
3284         /* [in] */ IUnknown* /*sender*/)
3285 {
3286     ASSERT_NOT_REACHED();
3287     return E_NOTIMPL;
3288 }
3289     
3290 HRESULT STDMETHODCALLTYPE WebView::checkSpelling( 
3291         /* [in] */ IUnknown* /*sender*/)
3292 {
3293     if (!m_editingDelegate) {
3294         LOG_ERROR("No NSSpellChecker");
3295         return E_FAIL;
3296     }
3297     
3298     core(m_mainFrame)->editor()->advanceToNextMisspelling();
3299     return S_OK;
3300 }
3301     
3302 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel( 
3303         /* [in] */ IUnknown* /*sender*/)
3304 {
3305     if (!m_editingDelegate) {
3306         LOG_ERROR("No NSSpellChecker");
3307         return E_FAIL;
3308     }
3309     
3310     // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
3311     // to match rest of OS X.
3312     BOOL showing;
3313     if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) {
3314         m_editingDelegate->showSpellingUI(FALSE);
3315     }
3316     
3317     core(m_mainFrame)->editor()->advanceToNextMisspelling(true);
3318     m_editingDelegate->showSpellingUI(TRUE);
3319     return S_OK;
3320 }
3321     
3322 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction( 
3323         /* [in] */ IUnknown* /*sender*/)
3324 {
3325     ASSERT_NOT_REACHED();
3326     return E_NOTIMPL;
3327 }
3328     
3329 HRESULT STDMETHODCALLTYPE WebView::startSpeaking( 
3330         /* [in] */ IUnknown* /*sender*/)
3331 {
3332     ASSERT_NOT_REACHED();
3333     return E_NOTIMPL;
3334 }
3335     
3336 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking( 
3337         /* [in] */ IUnknown* /*sender*/)
3338 {
3339     ASSERT_NOT_REACHED();
3340     return E_NOTIMPL;
3341 }
3342
3343 // IWebNotificationObserver -----------------------------------------------------------------
3344
3345 HRESULT STDMETHODCALLTYPE WebView::onNotify( 
3346     /* [in] */ IWebNotification* notification)
3347 {
3348     COMPtr<IUnknown> unkPrefs;
3349     HRESULT hr = notification->getObject(&unkPrefs);
3350     if (FAILED(hr))
3351         return hr;
3352
3353     COMPtr<IWebPreferences> preferences;
3354     hr = unkPrefs->QueryInterface(IID_IWebPreferences, (void**)&preferences);
3355     if (FAILED(hr))
3356         return hr;
3357
3358     hr = updateWebCoreSettingsFromPreferences(preferences.get());
3359
3360     return hr;
3361 }
3362
3363 // IWebViewPrivate ------------------------------------------------------------
3364
3365 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode( 
3366         /* [in] */ BOOL flag)
3367 {
3368     if (!m_mainFrame)
3369         return E_FAIL;
3370
3371     return m_mainFrame->setInViewSourceMode(flag);
3372 }
3373     
3374 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode( 
3375         /* [retval][out] */ BOOL* flag)
3376 {
3377     if (!m_mainFrame)
3378         return E_FAIL;
3379
3380     return m_mainFrame->inViewSourceMode(flag);
3381 }
3382
3383 HRESULT STDMETHODCALLTYPE WebView::viewWindow( 
3384         /* [retval][out] */ OLE_HANDLE *window)
3385 {
3386     *window = (OLE_HANDLE)(ULONG64)m_viewWindow;
3387     return S_OK;
3388 }
3389
3390 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate( 
3391     /* [in] */ IWebFormDelegate *formDelegate)
3392 {
3393     m_formDelegate = formDelegate;
3394     return S_OK;
3395 }
3396
3397 HRESULT STDMETHODCALLTYPE WebView::formDelegate( 
3398     /* [retval][out] */ IWebFormDelegate **formDelegate)
3399 {
3400     if (!m_formDelegate)
3401         return E_FAIL;
3402
3403     return m_formDelegate.copyRefTo(formDelegate);
3404 }
3405
3406 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate( 
3407     /* [in] */ IWebFrameLoadDelegatePrivate* d)
3408 {
3409     m_frameLoadDelegatePrivate = d;
3410     return S_OK;
3411 }
3412
3413 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate( 
3414     /* [out][retval] */ IWebFrameLoadDelegatePrivate** d)
3415 {
3416     if (!m_frameLoadDelegatePrivate)
3417         return E_FAIL;
3418         
3419     return m_frameLoadDelegatePrivate.copyRefTo(d);
3420 }
3421
3422 HRESULT STDMETHODCALLTYPE WebView::scrollOffset( 
3423     /* [retval][out] */ LPPOINT offset)
3424 {
3425     if (!offset)
3426         return E_POINTER;
3427     IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset();
3428     offset->x = offsetIntSize.width();
3429     offset->y = offsetIntSize.height();
3430     return S_OK;
3431 }
3432
3433 HRESULT STDMETHODCALLTYPE WebView::scrollBy( 
3434     /* [in] */ LPPOINT offset)
3435 {
3436     if (!offset)
3437         return E_POINTER;
3438     m_page->mainFrame()->view()->scrollBy(offset->x, offset->y);
3439     return S_OK;
3440 }
3441
3442 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect( 
3443     /* [retval][out] */ LPRECT rect)
3444 {
3445     if (!rect)
3446         return E_POINTER;
3447     FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect();
3448     rect->left = (LONG) visibleContent.x();
3449     rect->top = (LONG) visibleContent.y();
3450     rect->right = (LONG) visibleContent.right();
3451     rect->bottom = (LONG) visibleContent.bottom();
3452     return S_OK;
3453 }
3454
3455 static DWORD dragOperationToDragCursor(DragOperation op) {
3456     DWORD res = DROPEFFECT_NONE;
3457     if (op & DragOperationCopy) 
3458         res = DROPEFFECT_COPY;
3459     else if (op & DragOperationLink) 
3460         res = DROPEFFECT_LINK;
3461     else if (op & DragOperationMove) 
3462         res = DROPEFFECT_MOVE;
3463     else if (op & DragOperationGeneric) 
3464         res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour
3465     return res;
3466 }
3467
3468 static DragOperation keyStateToDragOperation(DWORD) {
3469     //FIXME: This is currently very simple, it may need to actually
3470     //work out an appropriate DragOperation in future -- however this
3471     //behaviour appears to match FireFox
3472     return (DragOperation)(DragOperationCopy | DragOperationLink);
3473 }
3474
3475 HRESULT STDMETHODCALLTYPE WebView::DragEnter(
3476         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3477 {
3478     m_dragData = 0;
3479
3480     if (m_dropTargetHelper)
3481         m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect);
3482
3483     POINTL localpt = pt;
3484     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3485     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 
3486         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3487     *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data));
3488
3489     m_dragData = pDataObject;
3490
3491     return S_OK;
3492 }
3493
3494 HRESULT STDMETHODCALLTYPE WebView::DragOver(
3495         DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3496 {
3497     if (m_dropTargetHelper)
3498         m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
3499
3500     if (m_dragData) {
3501         POINTL localpt = pt;
3502         ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3503         DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), 
3504             IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3505         *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data));
3506     } else
3507         *pdwEffect = DROPEFFECT_NONE;
3508
3509     return S_OK;
3510 }
3511
3512 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
3513 {
3514     if (m_dropTargetHelper)
3515         m_dropTargetHelper->DragLeave();
3516
3517     if (m_dragData) {
3518         DragData data(m_dragData.get(), IntPoint(), IntPoint(), 
3519             DragOperationNone);
3520         m_page->dragController()->dragExited(&data);
3521         m_dragData = 0;
3522     }
3523     return S_OK;
3524 }
3525
3526 HRESULT STDMETHODCALLTYPE WebView::Drop(
3527         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3528 {
3529     if (m_dropTargetHelper)
3530         m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
3531
3532     m_dragData = 0;
3533     *pdwEffect = DROPEFFECT_NONE;
3534     POINTL localpt = pt;
3535     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3536     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 
3537         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3538     m_page->dragController()->performDrag(&data);
3539     return S_OK;
3540 }
3541
3542 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest( 
3543     IWebURLRequest *request,
3544     BOOL *result)
3545 {
3546     COMPtr<WebMutableURLRequest> requestImpl;
3547
3548     HRESULT hr = request->QueryInterface(CLSID_WebMutableURLRequest, (void**)&requestImpl);
3549     if (FAILED(hr))
3550         return hr;
3551
3552     *result = !!canHandleRequest(requestImpl->resourceRequest());
3553     return S_OK;
3554 }
3555
3556 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode()
3557 {
3558     if (m_page && m_page->focusController())
3559         m_page->focusController()->setFocusedNode(0, 0);
3560     return S_OK;
3561 }
3562
3563 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements( 
3564     /* [in] */ BOOL cycles)
3565 {
3566     if (m_page)
3567         m_page->setTabKeyCyclesThroughElements(!!cycles);
3568
3569     return S_OK;
3570 }
3571
3572 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements( 
3573     /* [retval][out] */ BOOL* result)
3574 {
3575     if (!result) {
3576         ASSERT_NOT_REACHED();
3577         return E_POINTER;
3578     }
3579
3580     *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE;
3581     return S_OK;
3582 }
3583
3584 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks(
3585     /* [in] */ BOOL allow)
3586 {
3587     s_allowSiteSpecificHacks = !!allow;
3588     return S_OK;
3589 }
3590
3591 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginPath( 
3592         /* [in] */ BSTR path)
3593 {
3594     PluginDatabaseWin::installedPlugins()->addExtraPluginPath(String(path, SysStringLen(path)));
3595     return S_OK;
3596 }
3597
3598 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView( 
3599     /* [in] */ IWebView* otherView)
3600 {
3601     if (!m_page)
3602         return E_FAIL;
3603     
3604     // It turns out the right combination of behavior is done with the back/forward load
3605     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
3606     // in the back forward list, and go to the current one.
3607     BackForwardList* backForwardList = m_page->backForwardList();
3608     ASSERT(!backForwardList->currentItem()); // destination list should be empty
3609
3610     COMPtr<WebView> otherWebView;
3611     if (FAILED(otherView->QueryInterface(CLSID_WebView, (void**)&otherWebView)))
3612         return E_FAIL;
3613     BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList();
3614     if (!otherBackForwardList->currentItem())
3615         return S_OK; // empty back forward list, bail
3616     
3617     HistoryItem* newItemToGoTo = 0;
3618
3619     int lastItemIndex = otherBackForwardList->forwardListCount();
3620     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
3621         if (!i) {
3622             // If this item is showing , save away its current scroll and form state,
3623             // since that might have changed since loading and it is normally not saved
3624             // until we leave that page.
3625             otherWebView->m_page->mainFrame()->loader()->saveDocumentAndScrollState();
3626         }
3627         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
3628         if (!i) 
3629             newItemToGoTo = newItem.get();
3630         backForwardList->addItem(newItem.release());
3631     }
3632     
3633     ASSERT(newItemToGoTo);
3634     m_page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
3635     return S_OK;
3636 }
3637
3638 HRESULT WebView::registerDragDrop()
3639 {
3640     ASSERT(::IsWindow(m_viewWindow));
3641     return ::RegisterDragDrop(m_viewWindow, this);
3642 }
3643
3644 HRESULT WebView::revokeDragDrop()
3645 {
3646     ASSERT(::IsWindow(m_viewWindow));
3647     return ::RevokeDragDrop(m_viewWindow);
3648 }
3649
3650 void WebView::setProhibitsMainFrameScrolling(bool b)
3651 {
3652     m_page->mainFrame()->setProhibitsScrolling(b);
3653 }
3654
3655 class IMMDict {
3656     typedef HIMC (CALLBACK *getContextPtr)(HWND);
3657     typedef BOOL (CALLBACK *releaseContextPtr)(HWND, HIMC);
3658     typedef LONG (CALLBACK *getCompositionStringPtr)(HIMC, DWORD, LPVOID, DWORD);
3659     typedef BOOL (CALLBACK *setCandidateWindowPtr)(HIMC, LPCANDIDATEFORM);
3660     typedef BOOL (CALLBACK *setOpenStatusPtr)(HIMC, BOOL);
3661     typedef BOOL (CALLBACK *notifyIMEPtr)(HIMC, DWORD, DWORD, DWORD);
3662
3663 public:
3664     getContextPtr getContext;
3665     releaseContextPtr releaseContext;
3666     getCompositionStringPtr getCompositionString;
3667     setCandidateWindowPtr setCandidateWindow;
3668     setOpenStatusPtr setOpenStatus;
3669     notifyIMEPtr notifyIME;
3670     static const IMMDict& dict();
3671 private:
3672     IMMDict();
3673     HMODULE m_instance;
3674 };
3675
3676 const IMMDict& IMMDict::dict()
3677 {
3678     static IMMDict instance;
3679     return instance;
3680 }
3681
3682 IMMDict::IMMDict()
3683 {
3684     m_instance = ::LoadLibrary(TEXT("IMM32.DLL"));
3685     getContext = reinterpret_cast<getContextPtr>(::GetProcAddress(m_instance, "ImmGetContext"));
3686     ASSERT(getContext);
3687     releaseContext = reinterpret_cast<releaseContextPtr>(::GetProcAddress(m_instance, "ImmReleaseContext"));
3688     ASSERT(releaseContext);
3689     getCompositionString = reinterpret_cast<getCompositionStringPtr>(::GetProcAddress(m_instance, "ImmGetCompositionStringW"));
3690     ASSERT(getCompositionString);
3691     setCandidateWindow = reinterpret_cast<setCandidateWindowPtr>(::GetProcAddress(m_instance, "ImmSetCandidateWindow"));
3692     ASSERT(setCandidateWindow);
3693     setOpenStatus = reinterpret_cast<setOpenStatusPtr>(::GetProcAddress(m_instance, "ImmSetOpenStatus"));
3694     ASSERT(setOpenStatus);
3695     notifyIME = reinterpret_cast<notifyIMEPtr>(::GetProcAddress(m_instance, "ImmNotifyIME"));
3696     ASSERT(notifyIME);
3697 }
3698
3699 HIMC WebView::getIMMContext() 
3700 {
3701     HIMC context = IMMDict::dict().getContext(m_viewWindow);
3702     return context;
3703 }
3704
3705 void WebView::releaseIMMContext(HIMC hIMC)
3706 {
3707     if (!hIMC)
3708         return;
3709     IMMDict::dict().releaseContext(m_viewWindow, hIMC);
3710 }
3711
3712 void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext) 
3713 {
3714     IntRect caret;
3715     if (RefPtr<Range> range = targetFrame->selectionController()->selection().toRange()) {
3716         ExceptionCode ec = 0;
3717         RefPtr<Range> tempRange = range->cloneRange(ec);
3718         caret = targetFrame->firstRectForRange(tempRange.get());
3719     }
3720     caret = targetFrame->view()->contentsToWindow(caret);
3721     CANDIDATEFORM form;
3722     form.dwIndex = 0;
3723     form.dwStyle = CFS_EXCLUDE;
3724     form.ptCurrentPos.x = caret.x();
3725     form.ptCurrentPos.y = caret.y() + caret.height();
3726     form.rcArea.top = caret.y();
3727     form.rcArea.bottom = caret.bottom();
3728     form.rcArea.left = caret.x();
3729     form.rcArea.right = caret.right();
3730     IMMDict::dict().setCandidateWindow(hInputContext, &form);
3731 }
3732
3733 static bool markedTextContainsSelection(Range* markedTextRange, Range* selection)
3734 {
3735     ExceptionCode ec = 0;
3736
3737     ASSERT(markedTextRange->startContainer(ec) == markedTextRange->endContainer(ec));
3738
3739     if (selection->startContainer(ec) != markedTextRange->startContainer(ec))
3740         return false;
3741
3742     if (selection->endContainer(ec) != markedTextRange->endContainer(ec))
3743         return false;
3744
3745     if (selection->startOffset(ec) < markedTextRange->startOffset(ec))
3746         return false;
3747
3748     if (selection->endOffset(ec) > markedTextRange->endOffset(ec))
3749         return false;
3750
3751     return true;
3752 }
3753
3754 static void setSelectionToEndOfRange(Frame* targetFrame, Range* sourceRange)
3755 {
3756     ExceptionCode ec = 0;
3757     Node* caretContainer = sourceRange->endContainer(ec);
3758     unsigned caretOffset = sourceRange->endOffset(ec);
3759     RefPtr<Range> range = targetFrame->document()->createRange();
3760     range->setStart(caretContainer, caretOffset, ec);
3761     range->setEnd(caretContainer, caretOffset, ec);
3762     targetFrame->editor()->unmarkText();
3763     targetFrame->selectionController()->setSelectedRange(range.get(), WebCore::DOWNSTREAM, true, ec);
3764 }
3765
3766 void WebView::resetIME(Frame* targetFrame)
3767 {
3768     if (targetFrame)
3769         targetFrame->editor()->unmarkText();
3770
3771     if (HIMC hInputContext = getIMMContext()) {
3772         IMMDict::dict().notifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
3773         releaseIMMContext(hInputContext);
3774     }
3775 }
3776
3777 void WebView::updateSelectionForIME()
3778 {
3779     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
3780     if (!targetFrame || !targetFrame->markedTextRange())
3781         return;
3782     
3783     if (targetFrame->editor()->ignoreMarkedTextSelectionChange())
3784         return;
3785
3786     RefPtr<Range> selectionRange = targetFrame->selectionController()->selection().toRange();
3787     if (!selectionRange || !markedTextContainsSelection(targetFrame->markedTextRange(), selectionRange.get()))
3788         resetIME(targetFrame);
3789 }
3790
3791 void WebView::selectionChanged()
3792 {
3793     updateSelectionForIME();
3794 }
3795
3796 bool WebView::onIMEStartComposition()
3797 {
3798     m_inIMEComposition++;
3799     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
3800     if (!targetFrame)
3801         return true;
3802
3803     //Tidy up in case the last IME composition was not correctly terminated
3804     targetFrame->editor()->unmarkText();
3805
3806     HIMC hInputContext = getIMMContext();
3807     prepareCandidateWindow(targetFrame, hInputContext);
3808     releaseIMMContext(hInputContext);
3809     return true;
3810 }
3811
3812 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
3813 {
3814     int compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, 0, 0);
3815     if (compositionLength <= 0)
3816         return false;
3817     Vector<UChar> compositionBuffer(compositionLength / 2);
3818     compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, (LPVOID)compositionBuffer.data(), compositionLength);
3819     result = String(compositionBuffer, compositionLength / 2);
3820     ASSERT(!compositionLength || compositionBuffer[0]);
3821     ASSERT(!compositionLength || compositionBuffer[compositionLength / 2 - 1]);
3822     return true;
3823 }
3824
3825 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, 
3826                                     unsigned startOffset, Vector<MarkedTextUnderline>& underlines)
3827 {
3828     if (!clauses.size())
3829         return;
3830   
3831     const size_t numBoundaries = clauses.size() - 1;
3832     underlines.resize(numBoundaries);
3833     for (unsigned i = 0; i < numBoundaries; i++) {
3834         underlines[i].startOffset = startOffset + clauses[i];
3835         underlines[i].endOffset = startOffset + clauses[i + 1];
3836         BYTE attribute = attributes[clauses[i]];
3837         underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
3838         underlines[i].color = Color(0,0,0);
3839     }
3840 }
3841
3842 bool WebView::onIMEComposition(LPARAM lparam)
3843 {
3844     HIMC hInputContext = getIMMContext();
3845     if (!hInputContext)
3846         return true;
3847
3848     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
3849     if (!targetFrame || !targetFrame->editor()->canEdit())
3850         return true;
3851
3852     prepareCandidateWindow(targetFrame, hInputContext);
3853     targetFrame->editor()->setIgnoreMarkedTextSelectionChange(true);
3854
3855     // if we had marked text already, we need to make sure to replace
3856     // that, instead of the selection/caret
3857     targetFrame->editor()->selectMarkedText();
3858
3859     if (lparam & GCS_RESULTSTR || !lparam) {
3860         String compositionString;
3861         if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
3862             goto cleanup;
3863         
3864         targetFrame->editor()->replaceMarkedText(compositionString);
3865         RefPtr<Range> sourceRange = targetFrame->selectionController()->selection().toRange();
3866         setSelectionToEndOfRange(targetFrame, sourceRange.get());
3867     } else if (lparam) {
3868         String compositionString;
3869         if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
3870             goto cleanup;
3871         
3872         targetFrame->editor()->replaceMarkedText(compositionString);
3873
3874         ExceptionCode ec = 0;
3875         RefPtr<Range> sourceRange = targetFrame->selectionController()->selection().toRange();
3876         if (!sourceRange)
3877             goto cleanup;
3878
3879         Node* startContainer = sourceRange->startContainer(ec);
3880         const String& str = startContainer->textContent();
3881         for (unsigned i = 0; i < str.length(); i++)
3882             ASSERT(str[i]);
3883
3884         unsigned startOffset = sourceRange->startOffset(ec);
3885         RefPtr<Range> range = targetFrame->document()->createRange();
3886         range->setStart(startContainer, startOffset, ec);
3887         range->setEnd(startContainer, startOffset + compositionString.length(), ec);
3888
3889         // Composition string attributes
3890         int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0);
3891         Vector<BYTE> attributes(numAttributes);
3892         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
3893
3894         // Get clauses
3895         int numClauses = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, 0, 0);
3896         Vector<DWORD> clauses(numClauses / sizeof(DWORD));
3897         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses);
3898         Vector<MarkedTextUnderline> underlines;
3899         compositionToUnderlines(clauses, attributes, startOffset, underlines);
3900         targetFrame->setMarkedTextRange(range.get(), underlines);
3901         if (targetFrame->markedTextRange())
3902             targetFrame->selectRangeInMarkedText(LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0)), 0);
3903     }
3904 cleanup:
3905     targetFrame->editor()->setIgnoreMarkedTextSelectionChange(false);
3906     return true;
3907 }
3908
3909 bool WebView::onIMEEndComposition()
3910 {
3911     if (m_inIMEComposition) 
3912         m_inIMEComposition--;
3913     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
3914     if (!targetFrame)
3915         return true;
3916     targetFrame->editor()->unmarkText();
3917     return true;
3918 }
3919
3920 bool WebView::onIMEChar(WPARAM, LPARAM)
3921 {
3922     return true;
3923 }
3924
3925 bool WebView::onIMENotify(WPARAM, LPARAM, LRESULT*)
3926 {
3927     return false;
3928 }
3929
3930 bool WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* charPos, LRESULT* result)
3931 {
3932     IntRect caret;
3933     ASSERT(charPos->dwCharPos == 0 || targetFrame->markedTextRange());
3934     if (RefPtr<Range> range = targetFrame->markedTextRange() ? targetFrame->markedTextRange() : targetFrame->selectionController()->selection().toRange()) {
3935         ExceptionCode ec = 0;
3936         RefPtr<Range> tempRange = range->cloneRange(ec);
3937         tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec);
3938         caret = targetFrame->firstRectForRange(tempRange.get());
3939     }
3940     caret = targetFrame->view()->contentsToWindow(caret);
3941     charPos->pt.x = caret.x();
3942     charPos->pt.y = caret.y();
3943     ::ClientToScreen(m_viewWindow, &charPos->pt);
3944     charPos->cLineHeight = caret.height();
3945     ::GetWindowRect(m_viewWindow, &charPos->rcDocument);
3946     *result = TRUE;
3947     return true;
3948 }
3949
3950 bool WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString, LRESULT* result)
3951 {
3952     RefPtr<Range> selectedRange = targetFrame->selectionController()->toRange();
3953     String text = selectedRange->text();
3954     if (!reconvertString) {
3955         *result = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
3956         return true;
3957     }
3958
3959     unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
3960     *result = totalSize;
3961     if (totalSize > reconvertString->dwSize) {
3962         *result = 0;
3963         return false;
3964     }
3965     reconvertString->dwCompStrLen = text.length();
3966     reconvertString->dwStrLen = text.length();
3967     reconvertString->dwTargetStrLen = text.length();
3968     reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
3969     memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
3970     return true;
3971 }
3972
3973 bool WebView::onIMERequest(WPARAM request, LPARAM data, LRESULT* result)
3974 {
3975     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
3976     if (!targetFrame || !targetFrame->editor()->canEdit())
3977         return true;
3978
3979     switch (request) {
3980         case IMR_RECONVERTSTRING:
3981             return onIMERequestReconvertString(targetFrame, (RECONVERTSTRING*)data, result);
3982
3983         case IMR_QUERYCHARPOSITION:
3984             return onIMERequestCharPosition(targetFrame, (IMECHARPOSITION*)data, result);
3985     }
3986     return false;
3987 }
3988
3989 bool WebView::onIMESelect(WPARAM, LPARAM)
3990 {
3991     return false;
3992 }
3993
3994 bool WebView::onIMESetContext(WPARAM, LPARAM)
3995 {
3996     return false;
3997 }
3998
3999 class EnumTextMatches : public IEnumTextMatches
4000 {
4001     long m_ref;
4002     UINT m_index;
4003     Vector<IntRect> m_rects;
4004 public:
4005     EnumTextMatches(Vector<IntRect>* rects) : m_index(0), m_ref(1)
4006     {
4007         m_rects = *rects;
4008     }
4009
4010     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
4011     {
4012         if (riid == IID_IUnknown || riid == IID_IEnumTextMatches) {
4013             *ppv = this;
4014             AddRef();
4015         }
4016
4017         return *ppv?S_OK:E_NOINTERFACE;
4018     }
4019
4020     virtual ULONG STDMETHODCALLTYPE AddRef()
4021     {
4022         return m_ref++;
4023     }
4024     
4025     virtual ULONG STDMETHODCALLTYPE Release()
4026     {
4027         if (m_ref == 1) {
4028             delete this;
4029             return 0;
4030         }
4031         else
4032             return m_ref--;
4033     }
4034
4035     virtual HRESULT STDMETHODCALLTYPE Next(ULONG, RECT* rect, ULONG* pceltFetched)
4036     {
4037         if (m_index < m_rects.size()) {
4038             if (pceltFetched)
4039                 *pceltFetched = 1;
4040             *rect = m_rects[m_index];
4041             m_index++;
4042             return S_OK;
4043         }
4044
4045         if (pceltFetched)
4046             *pceltFetched = 0;
4047
4048         return S_FALSE;
4049     }
4050     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
4051     {
4052         m_index += celt;
4053         return S_OK;
4054     }
4055     virtual HRESULT STDMETHODCALLTYPE Reset(void)
4056     {
4057         m_index = 0;
4058         return S_OK;
4059     }
4060     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumTextMatches**)
4061     {
4062         return E_NOTIMPL;
4063     }
4064 };
4065
4066 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches)
4067 {
4068     *matches = new EnumTextMatches(rects);
4069     return (*matches)?S_OK:E_OUTOFMEMORY;
4070 }
4071
4072 Page* core(IWebView* iWebView)
4073 {
4074     Page* page = 0;
4075
4076     WebView* webView = 0;
4077     if (SUCCEEDED(iWebView->QueryInterface(CLSID_WebView, (void**)&webView)) && webView) {
4078         page = webView->page();
4079         webView->Release();
4080     }
4081
4082     return page;
4083 }