2007-12-22 Alp Toker <alp@atoker.com>
[WebKit-https.git] / WebKit / gtk / WebView / webkitwebview.cpp
1 /*
2  *  Copyright (C) 2007 Holger Hans Peter Freyther
3  *  Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
4  *  Copyright (C) 2007 Xan Lopez <xan@gnome.org>
5  *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "config.h"
23
24 #include "webkitwebview.h"
25 #include "webkit-marshal.h"
26 #include "webkitprivate.h"
27
28 #include "NotImplemented.h"
29 #include "CString.h"
30 #include "ChromeClientGtk.h"
31 #include "ContextMenuClientGtk.h"
32 #include "DragClientGtk.h"
33 #include "Editor.h"
34 #include "EditorClientGtk.h"
35 #include "EventHandler.h"
36 #include "FocusController.h"
37 #include "HitTestRequest.h"
38 #include "HitTestResult.h"
39 #include "GraphicsContext.h"
40 #include "InspectorClientGtk.h"
41 #include "FrameLoader.h"
42 #include "FrameView.h"
43 #include "Editor.h"
44 #include "PasteboardHelper.h"
45 #include "PlatformKeyboardEvent.h"
46 #include "PlatformWheelEvent.h"
47 #include "SubstituteData.h"
48
49 #include <gdk/gdkkeysyms.h>
50
51 using namespace WebKit;
52 using namespace WebCore;
53
54 extern "C" {
55
56 enum {
57     /* normal signals */
58     NAVIGATION_REQUESTED,
59     WINDOW_OBJECT_CLEARED,
60     LOAD_STARTED,
61     LOAD_COMMITTED,
62     LOAD_PROGRESS_CHANGED,
63     LOAD_FINISHED,
64     TITLE_CHANGED,
65     HOVERING_OVER_LINK,
66     STATUS_BAR_TEXT_CHANGED,
67     ICOND_LOADED,
68     SELECTION_CHANGED,
69     CONSOLE_MESSAGE,
70     SCRIPT_ALERT,
71     SCRIPT_CONFIRM,
72     SCRIPT_PROMPT,
73     SELECT_ALL,
74     COPY_CLIPBOARD,
75     PASTE_CLIPBOARD,
76     CUT_CLIPBOARD,
77     LAST_SIGNAL
78 };
79
80 enum {
81     PROP_0,
82
83     PROP_COPY_TARGET_LIST,
84     PROP_PASTE_TARGET_LIST
85 };
86
87 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
88
89 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
90
91 static void webkit_web_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
92     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
93
94     switch(prop_id) {
95     case PROP_COPY_TARGET_LIST:
96         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
97         break;
98     case PROP_PASTE_TARGET_LIST:
99         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
100         break;
101     default:
102         break;
103     }
104 }
105
106 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
107 {
108     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
109     GdkRectangle clip;
110     gdk_region_get_clipbox(event->region, &clip);
111     cairo_t* cr = gdk_cairo_create(event->window);
112     GraphicsContext ctx(cr);
113     ctx.setGdkExposeEvent(event);
114     if (frame->renderer()) {
115         frame->view()->layoutIfNeededRecursive();
116         frame->view()->paint(&ctx, clip);
117     }
118     cairo_destroy(cr);
119
120     return FALSE;
121 }
122
123 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
124 {
125     Frame* frame = core(WEBKIT_WEB_VIEW(widget))->focusController()->focusedOrMainFrame();
126     PlatformKeyboardEvent keyboardEvent(event);
127
128     if (frame->eventHandler()->keyEvent(keyboardEvent))
129         return TRUE;
130
131     FrameView* view = frame->view();
132     SelectionController::EAlteration alteration;
133     if (event->state & GDK_SHIFT_MASK)
134         alteration = SelectionController::EXTEND;
135     else
136         alteration = SelectionController::MOVE;
137
138     // TODO: We probably want to use GTK+ key bindings here and perhaps take an
139     // approach more like the Win and Mac ports for key handling.
140     switch (event->keyval) {
141     case GDK_Down:
142         view->scrollBy(0, LINE_STEP);
143         return TRUE;
144     case GDK_Up:
145         view->scrollBy(0, -LINE_STEP);
146         return TRUE;
147     case GDK_Right:
148         view->scrollBy(LINE_STEP, 0);
149         return TRUE;
150     case GDK_Left:
151         view->scrollBy(-LINE_STEP, 0);
152         return TRUE;
153     case GDK_Home:
154         frame->selectionController()->modify(alteration, SelectionController::BACKWARD, DocumentBoundary, true);
155         return TRUE;
156     case GDK_End:
157         frame->selectionController()->modify(alteration, SelectionController::FORWARD, DocumentBoundary, true);
158         return TRUE;
159     }
160
161     /* Chain up to our parent class for binding activation */
162     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
163 }
164
165 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
166 {
167     Frame* frame = core(WEBKIT_WEB_VIEW(widget))->focusController()->focusedOrMainFrame();
168     PlatformKeyboardEvent keyboardEvent(event);
169
170     if (frame->eventHandler()->keyEvent(keyboardEvent))
171         return TRUE;
172
173     /* Chain up to our parent class for binding activation */
174     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
175 }
176
177 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
178 {
179     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
180
181     // FIXME: need to keep track of subframe focus for key events
182     gtk_widget_grab_focus(GTK_WIDGET(widget));
183     return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
184 }
185
186 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
187 {
188     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
189
190     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
191     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(web_view);
192     Frame* focusedFrame = webViewData->corePage->focusController()->focusedFrame();
193
194     if (focusedFrame->editor()->canEdit()) {
195         GdkWindow* window = gtk_widget_get_parent_window(widget);
196         gtk_im_context_set_client_window(webViewData->imContext, window);
197 #ifdef MAEMO_CHANGES
198         hildon_gtk_im_context_filter_event(webViewData->imContext, (GdkEvent*)event);
199         hildon_gtk_im_context_show(webViewData->imContext);
200 #endif
201     }
202
203     return frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
204 }
205
206 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
207 {
208     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
209     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
210 }
211
212 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
213 {
214     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
215     PlatformWheelEvent wheelEvent(event);
216     return frame->eventHandler()->handleWheelEvent(wheelEvent);
217 }
218
219 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
220 {
221     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
222
223     Frame* frame = core(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(widget)));
224     frame->view()->resize(allocation->width, allocation->height);
225     frame->forceLayout();
226     frame->view()->adjustViewSize();
227 }
228
229 static void webkit_web_view_realize(GtkWidget* widget)
230 {
231     GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
232
233     GdkWindowAttr attributes;
234     attributes.window_type = GDK_WINDOW_CHILD;
235     attributes.x = widget->allocation.x;
236     attributes.y = widget->allocation.y;
237     attributes.width = widget->allocation.width;
238     attributes.height = widget->allocation.height;
239     attributes.wclass = GDK_INPUT_OUTPUT;
240     attributes.visual = gtk_widget_get_visual (widget);
241     attributes.colormap = gtk_widget_get_colormap (widget);
242     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
243                             | GDK_EXPOSURE_MASK
244                             | GDK_BUTTON_PRESS_MASK
245                             | GDK_BUTTON_RELEASE_MASK
246                             | GDK_POINTER_MOTION_MASK
247                             | GDK_KEY_PRESS_MASK
248                             | GDK_KEY_RELEASE_MASK
249                             | GDK_BUTTON_MOTION_MASK
250                             | GDK_BUTTON1_MOTION_MASK
251                             | GDK_BUTTON2_MOTION_MASK
252                             | GDK_BUTTON3_MOTION_MASK;
253
254     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
255     widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
256     gdk_window_set_user_data(widget->window, widget);
257 }
258
259 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
260 {
261     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
262     view->setGtkAdjustments(hadj, vadj);
263 }
264
265 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
266 {
267     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
268     WebKitWebViewPrivate* private_data = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
269
270     private_data->children.add(widget);
271     if (GTK_WIDGET_REALIZED(container))
272         gtk_widget_set_parent_window(widget, GTK_WIDGET(webView)->window);
273     gtk_widget_set_parent(widget, GTK_WIDGET(container));
274 }
275
276 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
277 {
278     WebKitWebViewPrivate* private_data = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(container));
279
280     if (private_data->children.contains(widget)) {
281         gtk_widget_unparent(widget);
282         private_data->children.remove(widget);
283     }
284 }
285
286 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
287 {
288     WebKitWebViewPrivate* privateData = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(container));
289
290     HashSet<GtkWidget*> children = privateData->children;
291     HashSet<GtkWidget*>::const_iterator end = children.end();
292     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
293         (*callback)(*current, callbackData);
294 }
295
296 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*)
297 {
298     notImplemented();
299     return 0;
300 }
301
302 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame* frame, WebKitNetworkRequest*)
303 {
304     notImplemented();
305     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
306 }
307
308 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
309 {
310     notImplemented();
311 }
312
313 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
314 {
315     notImplemented();
316     return g_strdup(old_name);
317 }
318
319 typedef enum {
320     WEBKIT_SCRIPT_DIALOG_ALERT,
321     WEBKIT_SCRIPT_DIALOG_CONFIRM,
322     WEBKIT_SCRIPT_DIALOG_PROMPT
323  } WebKitScriptDialogType;
324
325 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
326 {
327     GtkMessageType messageType;
328     GtkButtonsType buttons;
329     gint defaultResponse;
330     GtkWidget* window;
331     GtkWidget* dialog;
332     GtkWidget* entry = 0;
333     gboolean didConfirm = FALSE;
334
335     switch (type) {
336     case WEBKIT_SCRIPT_DIALOG_ALERT:
337         messageType = GTK_MESSAGE_WARNING;
338         buttons = GTK_BUTTONS_CLOSE;
339         defaultResponse = GTK_RESPONSE_CLOSE;
340         break;
341     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
342         messageType = GTK_MESSAGE_QUESTION;
343         buttons = GTK_BUTTONS_YES_NO;
344         defaultResponse = GTK_RESPONSE_YES;
345         break;
346     case WEBKIT_SCRIPT_DIALOG_PROMPT:
347         messageType = GTK_MESSAGE_QUESTION;
348         buttons = GTK_BUTTONS_OK_CANCEL;
349         defaultResponse = GTK_RESPONSE_OK;
350         break;
351     default:
352         g_warning("Unknown value for WebKitScriptDialogType.");
353         return FALSE;
354     }
355
356     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
357     dialog = gtk_message_dialog_new(GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
358     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
359     gtk_window_set_title(GTK_WINDOW(dialog), title);
360     g_free(title);
361
362     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
363         entry = gtk_entry_new();
364         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
365         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
366         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
367         gtk_widget_show(entry);
368     }
369
370     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
371     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
372
373     switch (response) {
374     case GTK_RESPONSE_YES:
375         didConfirm = TRUE;
376         break;
377     case GTK_RESPONSE_OK:
378         didConfirm = TRUE;
379         if (entry)
380             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
381         else
382             *value = 0;
383         break;
384     case GTK_RESPONSE_NO:
385     case GTK_RESPONSE_CANCEL:
386         didConfirm = FALSE;
387         break;
388
389     }
390     gtk_widget_destroy(GTK_WIDGET(dialog));
391     return didConfirm;
392 }
393
394 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
395 {
396     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
397     return TRUE;
398 }
399
400 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
401 {
402     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
403     return TRUE;
404 }
405
406 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
407 {
408     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
409         *value = NULL;
410     return TRUE;
411 }
412
413 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
414 {
415     g_print("console message: %s @%d: %s\n", sourceId, line, message);
416     return TRUE;
417 }
418
419 static void webkit_web_view_real_select_all(WebKitWebView* webView)
420 {
421     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
422     frame->editor()->command("SelectAll").execute();
423 }
424
425 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
426 {
427     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
428     frame->editor()->command("Cut").execute();
429 }
430
431 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
432 {
433     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
434     frame->editor()->command("Copy").execute();
435 }
436
437 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
438 {
439     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
440     frame->editor()->command("Paste").execute();
441 }
442
443 static void webkit_web_view_finalize(GObject* object)
444 {
445     webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
446
447     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(object));
448     delete webViewData->corePage;
449     delete webViewData->settings;
450     g_object_unref(webViewData->mainFrame);
451     g_object_unref(webViewData->imContext);
452     gtk_target_list_unref(webViewData->copy_target_list);
453     gtk_target_list_unref(webViewData->paste_target_list);
454     delete webViewData->userAgent;
455
456     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
457 }
458
459 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
460 {
461     GtkBindingSet* binding_set;
462
463     webkit_init();
464
465     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
466
467     /*
468      * Signals
469      */
470
471     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
472             G_TYPE_FROM_CLASS(webViewClass),
473             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
474             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
475             NULL,
476             NULL,
477             webkit_marshal_INT__OBJECT_OBJECT,
478             G_TYPE_INT, 2,
479             G_TYPE_OBJECT,
480             G_TYPE_OBJECT);
481
482     /**
483      * WebKitWebView::window-object-cleared:
484      * @web_view: the object on which the signal is emitted
485      * @frame: the #WebKitWebFrame to which @window_object belongs
486      * @context: the #JSGlobalContextRef holding the global object and other
487      * execution state; equivalent to the return value of
488      * webkit_web_frame_get_global_context(@frame)
489      *
490      * @window_object: the #JSObjectRef representing the frame's JavaScript
491      * window object
492      *
493      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
494      * cleared in preparation for a new load. This is the preferred place to
495      * set custom properties on the window object using the JavaScriptCore API.
496      */
497     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
498             G_TYPE_FROM_CLASS(webViewClass),
499             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
500             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
501             NULL,
502             NULL,
503             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
504             G_TYPE_NONE, 3,
505             WEBKIT_TYPE_WEB_FRAME,
506             G_TYPE_POINTER,
507             G_TYPE_POINTER);
508
509     /**
510      * WebKitWebView::load-started:
511      * @web_view: the object on which the signal is emitted
512      * @frame: the frame going to do the load
513      *
514      * When a #WebKitWebFrame begins to load this signal is emitted.
515      */
516     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
517             G_TYPE_FROM_CLASS(webViewClass),
518             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
519             0,
520             NULL,
521             NULL,
522             g_cclosure_marshal_VOID__OBJECT,
523             G_TYPE_NONE, 1,
524             WEBKIT_TYPE_WEB_FRAME);
525
526     /**
527      * WebKitWebView::load-committed:
528      * @web_view: the object on which the signal is emitted
529      * @frame: the main frame that received the first data
530      *
531      * When a #WebKitWebFrame loaded the first data this signal is emitted.
532      */
533     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
534             G_TYPE_FROM_CLASS(webViewClass),
535             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
536             0,
537             NULL,
538             NULL,
539             g_cclosure_marshal_VOID__OBJECT,
540             G_TYPE_NONE, 1,
541             WEBKIT_TYPE_WEB_FRAME);
542
543
544     /**
545      * WebKitWebView::load-progress-changed:
546      * @web_view: the #WebKitWebView
547      * @progress: the global progress
548      */
549     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
550             G_TYPE_FROM_CLASS(webViewClass),
551             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
552             0,
553             NULL,
554             NULL,
555             g_cclosure_marshal_VOID__INT,
556             G_TYPE_NONE, 1,
557             G_TYPE_INT);
558
559     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
560             G_TYPE_FROM_CLASS(webViewClass),
561             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
562             0,
563             NULL,
564             NULL,
565             g_cclosure_marshal_VOID__OBJECT,
566             G_TYPE_NONE, 1,
567             WEBKIT_TYPE_WEB_FRAME);
568
569     /**
570      * WebKitWebView::title-changed:
571      * @web_view: the object on which the signal is emitted
572      * @frame: the main frame
573      * @title: the new title
574      *
575      * When a #WebKitWebFrame changes the document title this signal is emitted.
576      */
577     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
578             G_TYPE_FROM_CLASS(webViewClass),
579             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
580             0,
581             NULL,
582             NULL,
583             webkit_marshal_VOID__OBJECT_STRING,
584             G_TYPE_NONE, 2,
585             WEBKIT_TYPE_WEB_FRAME,
586             G_TYPE_STRING);
587
588     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
589             G_TYPE_FROM_CLASS(webViewClass),
590             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
591             0,
592             NULL,
593             NULL,
594             webkit_marshal_VOID__STRING_STRING,
595             G_TYPE_NONE, 2,
596             G_TYPE_STRING,
597             G_TYPE_STRING);
598
599     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
600             G_TYPE_FROM_CLASS(webViewClass),
601             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
602             0,
603             NULL,
604             NULL,
605             g_cclosure_marshal_VOID__STRING,
606             G_TYPE_NONE, 1,
607             G_TYPE_STRING);
608
609     webkit_web_view_signals[ICOND_LOADED] = g_signal_new("icon-loaded",
610             G_TYPE_FROM_CLASS(webViewClass),
611             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
612             0,
613             NULL,
614             NULL,
615             g_cclosure_marshal_VOID__VOID,
616             G_TYPE_NONE, 0);
617
618     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
619             G_TYPE_FROM_CLASS(webViewClass),
620             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
621             0,
622             NULL,
623             NULL,
624             g_cclosure_marshal_VOID__VOID,
625             G_TYPE_NONE, 0);
626
627     /**
628      * WebKitWebView::console-message:
629      * @web_view: the object on which the signal is emitted
630      * @message: the message text
631      * @line: the line where the error occured
632      * @source_id: the source id
633      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
634      *
635      * A JavaScript console message was created.
636      */
637     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
638             G_TYPE_FROM_CLASS(webViewClass),
639             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
640             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
641             g_signal_accumulator_true_handled,
642             NULL,
643             webkit_marshal_BOOLEAN__STRING_INT_STRING,
644             G_TYPE_BOOLEAN, 3,
645             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
646
647     /**
648      * WebKitWebView::script-alert:
649      * @web_view: the object on which the signal is emitted
650      * @frame: the relevant frame
651      * @message: the message text
652      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
653      *
654      * A JavaScript alert dialog was created.
655      */
656     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
657             G_TYPE_FROM_CLASS(webViewClass),
658             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
659             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
660             g_signal_accumulator_true_handled,
661             NULL,
662             webkit_marshal_BOOLEAN__OBJECT_STRING,
663             G_TYPE_BOOLEAN, 2,
664             G_TYPE_OBJECT, G_TYPE_STRING);
665
666     /**
667      * WebKitWebView::script-confirm:
668      * @web_view: the object on which the signal is emitted
669      * @frame: the relevant frame
670      * @message: the message text
671      * @confirmed: whether the dialog has been confirmed
672      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
673      *
674      * A JavaScript confirm dialog was created, providing Yes and No buttons.
675      */
676     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
677             G_TYPE_FROM_CLASS(webViewClass),
678             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
679             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
680             g_signal_accumulator_true_handled,
681             NULL,
682             webkit_marshal_BOOLEAN__OBJECT_STRING_BOOLEAN,
683             G_TYPE_BOOLEAN, 3,
684             G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_BOOLEAN);
685
686     /**
687      * WebKitWebView::script-prompt:
688      * @web_view: the object on which the signal is emitted
689      * @frame: the relevant frame
690      * @message: the message text
691      * @default: the default value
692      * @text: To be filled with the return value or NULL if the dialog was cancelled.
693      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
694      *
695      * A JavaScript prompt dialog was created, providing an entry to input text.
696      */
697     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
698             G_TYPE_FROM_CLASS(webViewClass),
699             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
700             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
701             g_signal_accumulator_true_handled,
702             NULL,
703             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
704             G_TYPE_BOOLEAN, 4,
705             G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
706
707     /**
708      * WebKitWebView::select-all:
709      * @web_view: the object which received the signal
710      *
711      * The ::select-all signal is a keybinding signal which gets emitted to
712      * select the complete contents of the text view.
713      *
714      * The default bindings for this signal is Ctrl-a.
715      */
716     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
717             G_TYPE_FROM_CLASS(webViewClass),
718             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
719             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
720             NULL, NULL,
721             g_cclosure_marshal_VOID__VOID,
722             G_TYPE_NONE, 0);
723
724     /**
725      * WebKitWebView::cut-clipboard:
726      * @web_view: the object which received the signal
727      *
728      * The ::cut-clipboard signal is a keybinding signal which gets emitted to
729      * cut the selection to the clipboard.
730      *
731      * The default bindings for this signal are Ctrl-x and Shift-Delete.
732      */
733     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
734             G_TYPE_FROM_CLASS(webViewClass),
735             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
736             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
737             NULL, NULL,
738             g_cclosure_marshal_VOID__VOID,
739             G_TYPE_NONE, 0);
740
741     /**
742      * WebKitWebView::copy-clipboard:
743      * @web_view: the object which received the signal
744      *
745      * The ::copy-clipboard signal is a keybinding signal which gets emitted to
746      * copy the selection to the clipboard.
747      *
748      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
749      */
750     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
751             G_TYPE_FROM_CLASS(webViewClass),
752             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
753             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
754             NULL, NULL,
755             g_cclosure_marshal_VOID__VOID,
756             G_TYPE_NONE, 0);
757
758     /**
759      * WebKitWebView::paste-clipboard:
760      * @web_view: the object which received the signal
761      *
762      * The ::paste-clipboard signal is a keybinding signal which gets emitted to
763      * paste the contents of the clipboard into the Web view.
764      *
765      * The default bindings for this signal are Ctrl-v and Shift-Insert.
766      */
767     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
768             G_TYPE_FROM_CLASS(webViewClass),
769             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
770             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
771             NULL, NULL,
772             g_cclosure_marshal_VOID__VOID,
773             G_TYPE_NONE, 0);
774
775     /*
776      * implementations of virtual methods
777      */
778     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
779     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
780     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
781     webViewClass->choose_file = webkit_web_view_real_choose_file;
782     webViewClass->script_alert = webkit_web_view_real_script_alert;
783     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
784     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
785     webViewClass->console_message = webkit_web_view_real_console_message;
786     webViewClass->select_all = webkit_web_view_real_select_all;
787     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
788     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
789     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
790
791     G_OBJECT_CLASS(webViewClass)->finalize = webkit_web_view_finalize;
792
793     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
794     objectClass->get_property = webkit_web_view_get_property;
795
796     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
797     widgetClass->realize = webkit_web_view_realize;
798     widgetClass->expose_event = webkit_web_view_expose_event;
799     widgetClass->key_press_event = webkit_web_view_key_press_event;
800     widgetClass->key_release_event = webkit_web_view_key_release_event;
801     widgetClass->button_press_event = webkit_web_view_button_press_event;
802     widgetClass->button_release_event = webkit_web_view_button_release_event;
803     widgetClass->motion_notify_event = webkit_web_view_motion_event;
804     widgetClass->scroll_event = webkit_web_view_scroll_event;
805     widgetClass->size_allocate = webkit_web_view_size_allocate;
806
807     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
808     containerClass->add = webkit_web_view_container_add;
809     containerClass->remove = webkit_web_view_container_remove;
810     containerClass->forall = webkit_web_view_container_forall;
811
812     /*
813      * make us scrollable (e.g. addable to a GtkScrolledWindow)
814      */
815     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
816     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
817             G_TYPE_FROM_CLASS(webViewClass),
818             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
819             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
820             NULL, NULL,
821             webkit_marshal_VOID__OBJECT_OBJECT,
822             G_TYPE_NONE, 2,
823             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
824
825     /*
826      * Key bindings
827      */
828
829     binding_set = gtk_binding_set_by_class(webViewClass);
830
831     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
832                                  "select_all", 0);
833
834     /* Cut/copy/paste */
835
836     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
837                                  "cut_clipboard", 0);
838     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
839                                  "copy_clipboard", 0);
840     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
841                                  "paste_clipboard", 0);
842
843     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
844                                  "cut_clipboard", 0);
845     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
846                                  "copy_clipboard", 0);
847     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
848                                  "paste_clipboard", 0);
849
850     /* Properties */
851     GParamFlags flags = (GParamFlags)(G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
852     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
853                                     g_param_spec_boxed("copy-target-list",
854                                                        "Target list",
855                                                        "The list of targets this Web view supports for copying to the clipboard",
856                                                        GTK_TYPE_TARGET_LIST,
857                                                        flags));
858
859     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
860                                     g_param_spec_boxed("paste-target-list",
861                                                        "Target list",
862                                                        "The list of targets this Web view supports for pasting to the clipboard",
863                                                        GTK_TYPE_TARGET_LIST,
864                                                        flags));
865 }
866
867 static void webkit_web_view_init(WebKitWebView* webView)
868 {
869     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(webView));
870     webViewData->imContext = gtk_im_multicontext_new();
871     webViewData->corePage = new Page(new WebKit::ChromeClient(webView), new WebKit::ContextMenuClient, new WebKit::EditorClient(webView), new WebKit::DragClient, new WebKit::InspectorClient);
872
873     Settings* settings = webViewData->corePage->settings();
874     settings->setLoadsImagesAutomatically(true);
875     settings->setMinimumFontSize(5);
876     settings->setDOMPasteAllowed(true);
877     settings->setMinimumLogicalFontSize(5);
878     settings->setShouldPrintBackgrounds(true);
879     settings->setJavaScriptEnabled(true);
880     settings->setDefaultFixedFontSize(14);
881     settings->setDefaultFontSize(14);
882     settings->setSerifFontFamily("Times New Roman");
883     settings->setSansSerifFontFamily("Arial");
884     settings->setFixedFontFamily("Courier New");
885     settings->setStandardFontFamily("Arial");
886
887     GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS);
888     webViewData->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
889     webViewData->editable = false;
890
891 #if GTK_CHECK_VERSION(2,10,0)
892     GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
893 #else
894     GdkAtom textHtml = gdk_atom_intern("text/html", false);
895 #endif
896     /* Targets for copy */
897     webViewData->copy_target_list = gtk_target_list_new(NULL, 0);
898     gtk_target_list_add(webViewData->copy_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
899     gtk_target_list_add_text_targets(webViewData->copy_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
900
901     /* Targets for pasting */
902     webViewData->paste_target_list = gtk_target_list_new(NULL, 0);
903     gtk_target_list_add(webViewData->paste_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
904     gtk_target_list_add_text_targets(webViewData->paste_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
905
906 }
907
908 GtkWidget* webkit_web_view_new(void)
909 {
910     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
911
912     return GTK_WIDGET(webView);
913 }
914
915 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settings)
916 {
917     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
918     g_return_if_fail(settings);
919
920     notImplemented();
921 }
922
923 WebKitSettings* webkit_web_view_get_settings(WebKitWebView* webView)
924 {
925     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
926
927     notImplemented();
928     return NULL;
929 }
930
931 void webkit_web_view_go_backward(WebKitWebView* webView)
932 {
933     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
934
935     Frame* frame = core(webkit_web_view_get_main_frame(webView));
936     frame->loader()->goBackOrForward(-1);
937 }
938
939 void webkit_web_view_go_forward(WebKitWebView* webView)
940 {
941     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
942
943     Frame* frame = core(webkit_web_view_get_main_frame(webView));
944     frame->loader()->goBackOrForward(1);
945 }
946
947 gboolean webkit_web_view_can_go_backward(WebKitWebView* webView)
948 {
949     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
950
951     Frame* frame = core(webkit_web_view_get_main_frame(webView));
952     return frame->loader()->canGoBackOrForward(-1);
953 }
954
955 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
956 {
957     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
958
959     Frame* frame = core(webkit_web_view_get_main_frame(webView));
960     return frame->loader()->canGoBackOrForward(1);
961 }
962
963 void webkit_web_view_open(WebKitWebView* webView, const gchar* uri)
964 {
965     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
966
967     Frame* frame = core(webkit_web_view_get_main_frame(webView));
968     DeprecatedString string = DeprecatedString::fromUtf8(uri);
969     frame->loader()->load(ResourceRequest(KURL(string)));
970 }
971
972 void webkit_web_view_reload(WebKitWebView* webView)
973 {
974     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
975
976     Frame* frame = core(webkit_web_view_get_main_frame(webView));
977     frame->loader()->reload();
978 }
979
980 void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri)
981 {
982     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
983
984     Frame* frame = core(webkit_web_view_get_main_frame(webView));
985
986     KURL url(DeprecatedString::fromUtf8(baseUri));
987     RefPtr<SharedBuffer> sharedBuffer = new SharedBuffer(strdup(content), strlen(content));
988     SubstituteData substituteData(sharedBuffer.release(), String(contentMimeType), String(contentEncoding), KURL("about:blank"), url);
989
990     frame->loader()->load(ResourceRequest(url), substituteData);
991 }
992
993 void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUrl)
994 {
995     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
996
997     webkit_web_view_load_string(webView, content, "text/html", "UTF-8", baseUrl);
998 }
999
1000 void webkit_web_view_stop_loading(WebKitWebView* webView)
1001 {
1002     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1003
1004     Frame* frame = core(webkit_web_view_get_main_frame(webView));
1005
1006     if (FrameLoader* loader = frame->loader())
1007         loader->stopAllLoaders();
1008 }
1009
1010 /**
1011  * webkit_web_view_search_text:
1012  * @web_view: a #WebKitWebView
1013  * @text: a string to look for
1014  * @forward: whether to find forward or not
1015  * @case_sensitive: whether to respect the case of text
1016  * @wrap: whether to continue looking at the beginning after reaching the end
1017  *
1018  * Looks for a specified string inside #web_view.
1019  *
1020  * Return value: %TRUE on success or %FALSE on failure
1021  */
1022 gboolean webkit_web_view_search_text(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, gboolean forward, gboolean shouldWrap)
1023 {
1024     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1025     g_return_val_if_fail(string, FALSE);
1026
1027     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
1028     FindDirection direction = forward ? FindDirectionForward : FindDirectionBackward;
1029
1030     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1031     return webViewData->corePage->findString(String::fromUTF8(string), caseSensitivity, direction, shouldWrap);
1032 }
1033
1034 /**
1035  * webkit_web_view_mark_text_matches:
1036  * @web_view: a #WebKitWebView
1037  * @string: a string to look for
1038  * @case_sensitive: whether to respect the case of text
1039  * @limit: the maximum number of strings to look for or %0 for all
1040  *
1041  * Attempts to highlight all occurances of #string inside #web_view.
1042  *
1043  * Return value: the number of strings highlighted
1044  */
1045 guint webkit_web_view_mark_text_matches(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, guint limit)
1046 {
1047     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1048     g_return_val_if_fail(string, 0);
1049
1050     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
1051
1052     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1053     return webViewData->corePage->markAllMatchesForText(String::fromUTF8(string), caseSensitivity, false, limit);
1054 }
1055
1056 /**
1057  * webkit_web_view_set_highlight_text_matches:
1058  * @web_view: a #WebKitWebView
1059  * @highlight: whether to highlight text matches
1060  *
1061  * Highlights text matches previously marked by webkit_web_view_mark_text_matches.
1062  */
1063 void webkit_web_view_set_highlight_text_matches(WebKitWebView* webView, gboolean shouldHighlight)
1064 {
1065     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1066
1067     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1068     WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(webViewData->mainFrame);
1069     frameData->frame->setMarkedTextMatchesAreHighlighted(shouldHighlight);
1070 }
1071
1072 /**
1073  * webkit_web_view_unmark_text_matches:
1074  * @web_view: a #WebKitWebView
1075  *
1076  * Removes highlighting previously set by webkit_web_view_mark_text_matches.
1077  */
1078 void webkit_web_view_unmark_text_matches(WebKitWebView* webView)
1079 {
1080     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1081
1082     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1083     return webViewData->corePage->unmarkAllTextMatches();
1084 }
1085
1086 WebKitWebFrame* webkit_web_view_get_main_frame(WebKitWebView* webView)
1087 {
1088     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1089
1090     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1091     return webViewData->mainFrame;
1092 }
1093
1094 void webkit_web_view_execute_script(WebKitWebView* webView, const gchar* script)
1095 {
1096     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1097     g_return_if_fail(script);
1098
1099     Frame* frame = core(webkit_web_view_get_main_frame(webView));
1100     if (FrameLoader* loader = frame->loader())
1101         loader->executeScript(String::fromUTF8(script), true);
1102 }
1103
1104 /**
1105  * webkit_web_view_cut_clipboard:
1106  * @web_view: a #WebKitWebView
1107  *
1108  * Determines whether or not it is currently possible to cut to the clipboard.
1109  *
1110  * Return value: %TRUE if a selection can be cut, %FALSE if not
1111  */
1112 gboolean webkit_web_view_can_cut_clipboard(WebKitWebView* webView)
1113 {
1114     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1115
1116     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1117     return frame->editor()->canCut() || frame->editor()->canDHTMLCut();
1118 }
1119
1120 /**
1121  * webkit_web_view_copy_clipboard:
1122  * @web_view: a #WebKitWebView
1123  *
1124  * Determines whether or not it is currently possible to copy to the clipboard.
1125  *
1126  * Return value: %TRUE if a selection can be copied, %FALSE if not
1127  */
1128 gboolean webkit_web_view_can_copy_clipboard(WebKitWebView* webView)
1129 {
1130     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1131
1132     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1133     return frame->editor()->canCopy() || frame->editor()->canDHTMLCopy();
1134 }
1135
1136 /**
1137  * webkit_web_view_paste_clipboard:
1138  * @web_view: a #WebKitWebView
1139  *
1140  * Determines whether or not it is currently possible to paste from the clipboard.
1141  *
1142  * Return value: %TRUE if a selection can be pasted, %FALSE if not
1143  */
1144 gboolean webkit_web_view_can_paste_clipboard(WebKitWebView* webView)
1145 {
1146     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1147
1148     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1149     return frame->editor()->canPaste() || frame->editor()->canDHTMLPaste();
1150 }
1151
1152 /**
1153  * webkit_web_view_cut_clipboard:
1154  * @web_view: a #WebKitWebView
1155  *
1156  * Cuts the current selection inside the @web_view to the clipboard.
1157  */
1158 void webkit_web_view_cut_clipboard(WebKitWebView* webView)
1159 {
1160     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1161
1162     if (webkit_web_view_can_cut_clipboard(webView))
1163         g_signal_emit(webView, webkit_web_view_signals[CUT_CLIPBOARD], 0);
1164 }
1165
1166 /**
1167  * webkit_web_view_copy_clipboard:
1168  * @web_view: a #WebKitWebView
1169  *
1170  * Copies the current selection inside the @web_view to the clipboard.
1171  */
1172 void webkit_web_view_copy_clipboard(WebKitWebView* webView)
1173 {
1174     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1175
1176     if (webkit_web_view_can_copy_clipboard(webView))
1177         g_signal_emit(webView, webkit_web_view_signals[COPY_CLIPBOARD], 0);
1178 }
1179
1180 /**
1181  * webkit_web_view_paste_clipboard:
1182  * @web_view: a #WebKitWebView
1183  *
1184  * Pastes the current contents of the clipboard to the @web_view.
1185  */
1186 void webkit_web_view_paste_clipboard(WebKitWebView* webView)
1187 {
1188     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1189
1190     if (webkit_web_view_can_paste_clipboard(webView))
1191         g_signal_emit(webView, webkit_web_view_signals[PASTE_CLIPBOARD], 0);
1192 }
1193
1194 /**
1195  * webkit_web_view_delete_selection:
1196  * @web_view: a #WebKitWebView
1197  *
1198  * Deletes the current selection inside the @web_view.
1199  */
1200 void webkit_web_view_delete_selection(WebKitWebView* webView)
1201 {
1202     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1203
1204     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1205     frame->editor()->performDelete();
1206 }
1207
1208 /**
1209  * webkit_web_view_has_selection:
1210  * @web_view: a #WebKitWebView
1211  *
1212  * Determines whether text was selected.
1213  *
1214  * Return value: %TRUE if there is selected text, %FALSE if not
1215  */
1216 gboolean webkit_web_view_has_selection(WebKitWebView* webView)
1217 {
1218     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1219
1220     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1221     return webViewData->corePage->selection().isNone() ? TRUE : FALSE;
1222 }
1223
1224 /**
1225  * webkit_web_view_get_selected_text:
1226  * @web_view: a #WebKitWebView
1227  *
1228  * Retrieves the selected text if any.
1229  *
1230  * Return value: a newly allocated string with the selection or %NULL
1231  */
1232 gchar* webkit_web_view_get_selected_text(WebKitWebView* webView)
1233 {
1234     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1235
1236     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1237     return g_strdup(frame->selectedText().utf8().data());
1238 }
1239
1240 /**
1241  * webkit_web_view_select_all:
1242  * @web_view: a #WebKitWebView
1243  *
1244  * Attempts to select everything inside the @web_view.
1245  */
1246 void webkit_web_view_select_all(WebKitWebView* webView)
1247 {
1248     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1249
1250     g_signal_emit(webView, webkit_web_view_signals[SELECT_ALL], 0);
1251 }
1252
1253 /**
1254  * webkit_web_view_get_editable:
1255  * @web_view: a #WebKitWebView
1256  *
1257  * Returns whether the user is allowed to edit the document.
1258  *
1259  * Returns %TRUE if @web_view allows the user to edit the HTML document, %FALSE if
1260  * it doesn't. You can change @web_view's document programmatically regardless of
1261  * this setting.
1262  *
1263  * Return value: a #gboolean indicating the editable state
1264  */
1265 gboolean webkit_web_view_get_editable(WebKitWebView* webView)
1266 {
1267     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1268
1269     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1270     ASSERT(webViewData);
1271
1272     return webViewData->editable;
1273 }
1274
1275 /**
1276  * webkit_web_view_set_editable:
1277  * @web_view: a #WebKitWebView
1278  * @flag: a #gboolean indicating the editable state
1279  *
1280  * Sets whether @web_view allows the user to edit its HTML document.
1281  *
1282  * If @flag is %TRUE, @web_view allows the user to edit the document. If @flag is
1283  * %FALSE, an element in @web_view's document can only be edited if the
1284  * CONTENTEDITABLE attribute has been set on the element or one of its parent
1285  * elements. You can change @web_view's document programmatically regardless of
1286  * this setting. By default a #WebKitWebView is not editable.
1287
1288  * Normally, an HTML document is not editable unless the elements within the
1289  * document are editable. This function provides a low-level way to make the
1290  * contents of a #WebKitWebView editable without altering the document or DOM
1291  * structure.
1292  */
1293 void webkit_web_view_set_editable(WebKitWebView* webView, gboolean flag)
1294 {
1295     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1296     flag = flag != FALSE;
1297
1298     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1299     ASSERT(webViewData);
1300
1301     Frame* mainFrame = core(webViewData->mainFrame);
1302     g_return_if_fail(mainFrame);
1303
1304     // TODO: What happens when the frame is replaced?
1305     if (flag == webViewData->editable)
1306         return;
1307
1308     webViewData->editable = flag;
1309
1310     if (flag) {
1311         mainFrame->applyEditingStyleToBodyElement();
1312         // TODO: If the WebKitWebView is made editable and the selection is empty, set it to something.
1313         //if (!webkit_web_view_get_selected_dom_range(webView))
1314         //    mainFrame->setSelectionFromNone();
1315     } else
1316         mainFrame->removeEditingStyleFromBodyElement();
1317 }
1318
1319 /**
1320  * webkit_web_view_get_copy_target_list:
1321  * @web_view: a #WebKitWebView
1322  *
1323  * This function returns the list of targets this #WebKitWebView can
1324  * provide for clipboard copying and as DND source. The targets in the list are
1325  * added with %info values from the #WebKitWebViewTargetInfo enum,
1326  * using gtk_target_list_add() and
1327  * gtk_target_list_add_text_targets().
1328  *
1329  * Return value: the #GtkTargetList
1330  **/
1331 GtkTargetList* webkit_web_view_get_copy_target_list(WebKitWebView* webView)
1332 {
1333     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1334
1335     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1336     return webViewData->copy_target_list;
1337 }
1338
1339 /**
1340  * webkit_web_view_get_paste_target_list:
1341  * @web_view: a #WebKitWebView
1342  *
1343  * This function returns the list of targets this #WebKitWebView can
1344  * provide for clipboard pasting and as DND destination. The targets in the list are
1345  * added with %info values from the #WebKitWebViewTargetInfo enum,
1346  * using gtk_target_list_add() and
1347  * gtk_target_list_add_text_targets().
1348  *
1349  * Return value: the #GtkTargetList
1350  **/
1351 GtkTargetList* webkit_web_view_get_paste_target_list(WebKitWebView* webView)
1352 {
1353     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1354
1355     WebKitWebViewPrivate* webViewData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1356     return webViewData->paste_target_list;
1357 }
1358
1359 }