Hiroyuki Ikezoe
ikezo****@users*****
Tue Mar 20 13:04:11 JST 2007
Index: kazehakase/module/embed/gecko/kz-gecko-embed.cpp diff -u /dev/null kazehakase/module/embed/gecko/kz-gecko-embed.cpp:1.1 --- /dev/null Tue Mar 20 13:04:11 2007 +++ kazehakase/module/embed/gecko/kz-gecko-embed.cpp Tue Mar 20 13:04:11 2007 @@ -0,0 +1,3206 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2007 Hiroyuki Ikezoe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "kz-embed.h" +#include "kz-gecko-embed.h" + +#include "kz-gecko-single.h" + +#define KZ_REGRESSION_BUG4474 1 + +#include <string.h> +#include <math.h> +#include <gtkmozembed.h> +#include <gtkmozembed_internal.h> +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <sys/stat.h> + +#include "kazehakase.h" +#include "kz-window.h" +#include "kz-mozwrapper.h" +#include "kz-mozprogresslistener.h" +#include "kz-mozthumbnailcreator.h" +#include "kz-mozutils.h" +#include "mozilla.h" +#include "mozilla-prefs.h" +#include "bookmarks/kz-bookmark.h" +#if USE_MIGEMO +#include "kz-migemo.h" +#endif +#include "utils.h" + +#include "kz-search.h" + +#include <nsCOMPtr.h> +#include <nsIDOMDocument.h> +#include <nsIDocumentViewer.h> +#include <nsIWebBrowser.h> +#include <nsIDOMMouseEvent.h> +#include <dom/nsIDOMKeyEvent.h> +#include <dom/nsIDOMNSHTMLElement.h> +#include <nsIDOMHTMLElement.h> +#include <nsIDOMHTMLDocument.h> +#include <nsIDOMHTMLTextAreaElement.h> +#include <nsIDOMNamedNodeMap.h> +#include <nsIDOMDocumentRange.h> +#include <nsIDOMDocumentFragment.h> +#include <nsIDOMSerializer.h> +#include <nsIDOMText.h> +#include <webbrowserpersist/nsIWebBrowserPersist.h> +#include <nsIWebBrowserFind.h> +#include <nsIFind.h> +#include <dom/nsIDOMNSDocument.h> +#include <dom/nsIDOMNSEvent.h> +#include <nsIDOMNodeList.h> +#include <nsIDOMWindow.h> +#include <nsISelection.h> +#include <nsIDOMRange.h> +#include <nsIDOMWindow.h> +#include <nsISelection.h> +#include <nsISHistory.h> +#include <nsIHistoryEntry.h> +#include <nsISHEntry.h> +#include <nsISHistoryInternal.h> +#include <nsIWebNavigation.h> +#include <nsCWebBrowserPersist.h> +#include <widget/nsIBaseWindow.h> +#include <nsIWebPageDescriptor.h> +#include <nsICommandManager.h> +#include <nsTime.h> +#include <nsRect.h> +#define MOZILLA_STRICT_API +#include <nsEmbedString.h> +#undef MOZILLA_STRICT_API +#include <nsIServiceManager.h> +#include <nsIInterfaceRequestorUtils.h> +#include <nsMemory.h> +#include <nsILocalFile.h> +#include <nsIDOM3Node.h> + +typedef struct _KzGeckoEmbedPrivate KzGeckoEmbedPrivate; +struct _KzGeckoEmbedPrivate +{ + KzMozWrapper *wrapper; + gint size_inited; + gint cur_requests; + gint total_requests; + + /* location and title */ + gchar *location; + gchar *title; + + gint load_started; /* count of currently active connections */ + gint load_percent; + gint bytes_loaded; + gint max_bytes_loaded; + gboolean is_loading; + const gchar *load_status_message; + + gboolean lock; + + /* for navigation link */ + GList *nav_links[KZ_EMBED_LINK_GUARD]; + +#ifdef USE_MIGEMO + gchar *migemo_keyword; +#endif + gchar *last_highlight; + gchar *first_url; +}; + +typedef struct _KzGeckoEmbedClass KzGeckoEmbedClass; +struct _KzGeckoEmbedClass +{ + GtkMozEmbedClass parent_class; +}; + +#define KZ_GECKO_EMBED_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), KZ_TYPE_GECKO_EMBED, KzGeckoEmbedPrivate)) + +#define KZ_GECKO_EMBED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KZ_TYPE_GECKO_EMBED, KzGeckoEmbedClass)) +#define KZ_IS_GECKO_EMBED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KZ_TYPE_GECKO_EMBED)) +#define KZ_GECKO_EMBED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KZ_TYPE_GECKO_EMBED, KzGeckoEmbedClass)) + +/* for module */ +void kz_embed_module_init (GTypeModule *module); +void kz_embed_module_exit (void); +GtkWidget *kz_embed_module_create (const gchar *url); + +/* for interface */ +static void kz_gecko_embed_iface_init (KzEmbedIFace *iface); + +static void kz_gecko_embed_navigation_link_free(KzGeckoEmbed *kzembed); +static glong kz_gecko_embed_get_key_event_info (KzGeckoEmbed *kzembed, + gpointer event, + KzEmbedEventKey **info_ret); +static glong kz_gecko_embed_get_mouse_event_info(KzGeckoEmbed *kzembed, + gpointer event, + KzEmbedEventMouse **info_ret); +static glong kz_gecko_embed_set_event_context (KzGeckoEmbed *kzembed, + nsIDOMEventTarget *target, + KzEmbedEvent *info); +static gchar *kz_gecko_embed_store_history_file (KzGeckoEmbed *kzembed); + +static void kz_gecko_embed_load_url (KzEmbed *kzembed, + const gchar *url); +static void kz_gecko_embed_view_source (KzEmbed *kzembed, + const gchar *url); + +static gboolean kz_gecko_embed_is_loading (KzEmbed *kzembed); + +static const gchar *kz_gecko_embed_get_title (KzEmbed *kzembed); +static const gchar *kz_gecko_embed_get_location (KzEmbed *kzembed); +static gchar *kz_gecko_embed_ensure_title (KzEmbed *kzembed); +static gchar *kz_gecko_embed_get_link_message (KzEmbed *kzembed); + +static gdouble kz_gecko_embed_get_progress (KzEmbed *kzembed); + +static gboolean kz_gecko_embed_can_cut_selection (KzEmbed *kzembed); +static gboolean kz_gecko_embed_can_copy_selection (KzEmbed *kzembed); +static gboolean kz_gecko_embed_can_paste (KzEmbed *kzembed); +static void kz_gecko_embed_cut_selection (KzEmbed *kzembed); +static void kz_gecko_embed_copy_selection (KzEmbed *kzembed); +static void kz_gecko_embed_paste (KzEmbed *kzembed); +static void kz_gecko_embed_select_all (KzEmbed *kzembed); + +static gchar *kz_gecko_embed_get_selection_string (KzEmbed *kzembed); + +static gboolean kz_gecko_embed_find (KzEmbed *kzembed, + const char *keyword, + gboolean backward); +static gboolean kz_gecko_embed_incremental_search (KzEmbed *kzembed, + const char *keyword, + gboolean backward); + +static gboolean kz_gecko_embed_selection_is_collapsed(KzEmbed *kzembed); + +static gboolean kz_gecko_embed_get_links (KzEmbed *kzembed, + GList **list, + gboolean selected_only); + +static gboolean kz_gecko_embed_get_dest_anchors (KzEmbed *kzembed, + GList **list); + +static void kz_gecko_embed_copy_page (KzEmbed *kzembed, + KzEmbed *dkzembed, + KzEmbedCopyType type); +static gboolean kz_gecko_embed_shistory_copy (KzEmbed *source, + KzEmbed *dest, + gboolean back_history, + gboolean forward_history, + gboolean set_current); +static gboolean kz_gecko_embed_shistory_get_pos (KzEmbed *kzembed, + int *pos, + int *count); +static void kz_gecko_embed_shistory_get_nth (KzEmbed *kzembed, + int nth, + gboolean is_relative, + char **aUrl, + char **aTitle); + +static void kz_gecko_embed_reload (KzEmbed *kzembed, + KzEmbedReloadFlag flags); +static void kz_gecko_embed_stop_load (KzEmbed *kzembed); +static void kz_gecko_embed_go_back (KzEmbed *kzembed); +static void kz_gecko_embed_go_forward (KzEmbed *kzembed); + +static gboolean kz_gecko_embed_can_go_back (KzEmbed *kzembed); +static gboolean kz_gecko_embed_can_go_forward (KzEmbed *kzembed); +static gboolean kz_gecko_embed_can_go_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link); +static void kz_gecko_embed_go_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link); +static void kz_gecko_embed_append_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + KzNavi *navi); +static void kz_gecko_embed_set_nth_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + KzNavi *navi, + guint n); +static KzNavi *kz_gecko_embed_get_nth_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + guint n); +static GList *kz_gecko_embed_get_nav_links (KzEmbed *kzembed, + KzEmbedNavLink link); +static void kz_gecko_embed_go_history_index (KzEmbed *kzembed, + gint index); + +static void kz_gecko_embed_do_command (KzEmbed *kzembed, + const char *command); +static gboolean kz_gecko_embed_can_do_command (KzEmbed *kzembed, + const char *command); + +static gboolean kz_gecko_embed_get_lock (KzEmbed *kzembed); +static void kz_gecko_embed_set_lock (KzEmbed *kzembed, + gboolean lock); + +static gchar *kz_gecko_embed_get_body_text (KzEmbed *kzembed); +#if 0 +static gchar *kz_gecko_embed_get_selection_source (KzEmbed *kzembed); +#endif +static void kz_gecko_embed_set_encoding (KzEmbed *kzembed, + const char *encoding); +static void kz_gecko_embed_get_encoding (KzEmbed *kzembed, + char **encoding, + gboolean *forced); +static void kz_gecko_embed_print (KzEmbed *kzembed); +static void kz_gecko_embed_print_preview (KzEmbed *kzembed); +static GList *kz_gecko_embed_get_printer_list (KzEmbed *kzembed); +static void kz_gecko_embed_create_thumbnail (KzEmbed *kzembed); + + +static gboolean kz_gecko_embed_save_with_content (KzEmbed *kzembed, + const char *rawfilename); + +static gboolean kz_gecko_embed_set_text_into_textarea(KzEmbed *kzembed, + gpointer element, + const gchar *text); +static gchar *kz_gecko_embed_get_text_from_textarea(KzEmbed *kzembed, + gpointer element); + + +static void kz_gecko_embed_zoom_set (KzEmbed *kzembed, + int zoom, + gboolean reflow); +static int kz_gecko_embed_zoom_get (KzEmbed *kzembed); +static void kz_gecko_embed_set_text_size (KzEmbed *kzembed, + int zoom, + gboolean reflow); +static int kz_gecko_embed_get_text_size (KzEmbed *kzembed); + +static gchar *kz_gecko_embed_get_html_with_contents(KzEmbed *kzembed, + const gchar *storedir); + +static void kz_gecko_embed_set_history (KzEmbed *kzembed, + KzBookmark *history); +static void kz_gecko_embed_get_history (KzEmbed *kzembed, + KzBookmark *history); +static guint kz_gecko_embed_get_last_modified (KzEmbed *kzembed); + + +#if 0 +static void kz_gecko_embed_set_edit_mode (KzEmbed *kzembed); +static void kz_gecko_embed_set_view_mode (KzEmbed *kzembed); +#endif +static void kz_gecko_embed_fine_scroll (KzEmbed *kzembed, + int horiz, + int vert); +static void kz_gecko_embed_page_up (KzEmbed *kzembed); +static void kz_gecko_embed_page_down (KzEmbed *kzembed); + +static gboolean kz_gecko_embed_get_allow_javascript (KzEmbed *kzembed); +static void kz_gecko_embed_set_allow_javascript (KzEmbed *kzembed, + gboolean allow); +static gboolean kz_gecko_embed_get_allow_images (KzEmbed *kzembed); +static void kz_gecko_embed_set_allow_images (KzEmbed *kzembed, + gboolean allow); +static void kz_gecko_embed_show_page_certificate (KzEmbed *kzembed); + +/* KzGeckoEmbed Class */ +static void kz_gecko_embed_class_init (KzGeckoEmbedClass *klass); +static void kz_gecko_embed_init (KzGeckoEmbed *embed); + +static GtkMozEmbedClass *kz_gecko_embed_parent_class; +static GType kz_gecko_embed_type = 0; + +static void +kz_gecko_embed_register_type (GTypeModule *module) +{ + static const GTypeInfo kz_gecko_embed_info = + { + sizeof (KzGeckoEmbedClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) kz_gecko_embed_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (KzGeckoEmbed), + 0, /* n_preallocs */ + (GInstanceInitFunc) kz_gecko_embed_init, + }; + + const GInterfaceInfo kz_embed_info = + { + (GInterfaceInitFunc) kz_gecko_embed_iface_init, + NULL, + NULL + }; + + kz_gecko_embed_type = g_type_module_register_type(module, + GTK_TYPE_MOZ_EMBED, + "KzGeckoEmbed", + &kz_gecko_embed_info, (GTypeFlags)0); + + g_type_module_add_interface(module, + KZ_TYPE_GECKO_EMBED, + KZ_TYPE_EMBED, + &kz_embed_info); +} + +G_MODULE_EXPORT void +kz_embed_module_init (GTypeModule *module) +{ + kz_gecko_embed_register_type(module); +} + +G_MODULE_EXPORT void +kz_embed_module_exit (void) +{ +} + +G_MODULE_EXPORT GtkWidget * +kz_embed_module_create (const gchar *url) +{ + return kz_gecko_embed_new(url); +} + +GType +kz_gecko_embed_get_type (void) +{ + return kz_gecko_embed_type; +} + +static void +kz_gecko_embed_iface_init (KzEmbedIFace *iface) +{ + iface->load_url = kz_gecko_embed_load_url; + iface->view_source = kz_gecko_embed_view_source; + iface->is_loading = kz_gecko_embed_is_loading; + iface->get_title = kz_gecko_embed_get_title; + iface->get_location = kz_gecko_embed_get_location; + iface->ensure_title = kz_gecko_embed_ensure_title; + iface->get_link_message = kz_gecko_embed_get_link_message; + iface->get_progress = kz_gecko_embed_get_progress; + iface->can_cut_selection = kz_gecko_embed_can_cut_selection; + iface->can_copy_selection = kz_gecko_embed_can_copy_selection; + iface->can_paste = kz_gecko_embed_can_paste; + iface->cut_selection = kz_gecko_embed_cut_selection; + iface->copy_selection = kz_gecko_embed_copy_selection; + iface->paste = kz_gecko_embed_paste; + iface->select_all = kz_gecko_embed_select_all; + iface->get_selection_string = kz_gecko_embed_get_selection_string; + iface->find = kz_gecko_embed_find; + iface->incremental_search = kz_gecko_embed_incremental_search; + iface->selection_is_collapsed = kz_gecko_embed_selection_is_collapsed; + iface->get_links = kz_gecko_embed_get_links; + iface->get_dest_anchors = kz_gecko_embed_get_dest_anchors; + iface->copy_page = kz_gecko_embed_copy_page; + iface->shistory_copy = kz_gecko_embed_shistory_copy; + iface->shistory_get_pos = kz_gecko_embed_shistory_get_pos; + iface->shistory_get_nth = kz_gecko_embed_shistory_get_nth; + iface->reload = kz_gecko_embed_reload; + iface->stop_load = kz_gecko_embed_stop_load; + iface->go_back = kz_gecko_embed_go_back; + iface->go_forward = kz_gecko_embed_go_forward; + iface->can_go_back = kz_gecko_embed_can_go_back; + iface->can_go_forward = kz_gecko_embed_can_go_forward; + iface->can_go_nav_link = kz_gecko_embed_can_go_nav_link; + iface->go_nav_link = kz_gecko_embed_go_nav_link; + iface->append_nav_link = kz_gecko_embed_append_nav_link; + iface->set_nav_link = NULL; + iface->set_nth_nav_link = kz_gecko_embed_set_nth_nav_link; + iface->get_nav_link = NULL; + iface->get_nth_nav_link = kz_gecko_embed_get_nth_nav_link; + iface->get_nav_links = kz_gecko_embed_get_nav_links; + iface->go_history_index = kz_gecko_embed_go_history_index; + iface->do_command = kz_gecko_embed_do_command; + iface->can_do_command = kz_gecko_embed_can_do_command; + iface->get_lock = kz_gecko_embed_get_lock; + iface->set_lock = kz_gecko_embed_set_lock; + iface->get_body_text = kz_gecko_embed_get_body_text; +#if 0 + iface->get_selection_source = kz_gecko_embed_get_selection_source; +#endif + iface->set_encoding = kz_gecko_embed_set_encoding; + iface->get_encoding = kz_gecko_embed_get_encoding; + iface->print = kz_gecko_embed_print; + iface->print_preview = kz_gecko_embed_print_preview; + iface->get_printer_list = kz_gecko_embed_get_printer_list; + iface->create_thumbnail = kz_gecko_embed_create_thumbnail; + iface->save_with_content = kz_gecko_embed_save_with_content; + iface->set_text_into_textarea = kz_gecko_embed_set_text_into_textarea; + iface->get_text_from_textarea = kz_gecko_embed_get_text_from_textarea; + iface->zoom_set = kz_gecko_embed_zoom_set; + iface->zoom_get = kz_gecko_embed_zoom_get; + iface->set_text_size = kz_gecko_embed_set_text_size; + iface->get_text_size = kz_gecko_embed_get_text_size; + iface->get_html_with_contents = kz_gecko_embed_get_html_with_contents; + iface->set_history = kz_gecko_embed_set_history; + iface->get_history = kz_gecko_embed_get_history; + iface->get_last_modified = kz_gecko_embed_get_last_modified; + iface->fine_scroll = kz_gecko_embed_fine_scroll; + iface->page_up = kz_gecko_embed_page_up; + iface->page_down = kz_gecko_embed_page_down; + iface->get_allow_javascript = kz_gecko_embed_get_allow_javascript; + iface->set_allow_javascript = kz_gecko_embed_set_allow_javascript; + iface->get_allow_images = kz_gecko_embed_get_allow_images; + iface->set_allow_images = kz_gecko_embed_set_allow_images; + iface->show_page_certificate = kz_gecko_embed_show_page_certificate; + + +#if 0 + iface->set_edit_mode = set_edit_mode; + iface->set_view_mode = set_view_mode; +#endif + iface->link_message = NULL; + iface->js_status = NULL; + iface->location = NULL; + iface->title = NULL; + iface->progress = NULL; + iface->net_start = NULL; + iface->net_stop = NULL; + iface->new_window = NULL; + iface->open_uri = NULL; + iface->size_to = NULL; + iface->dom_key_down = NULL; + iface->dom_key_press = NULL; + iface->dom_key_up = NULL; + iface->dom_mouse_down = NULL; + iface->dom_mouse_up = NULL; + iface->dom_mouse_click = NULL; + iface->dom_mouse_dbl_click = NULL; + iface->dom_mouse_over = NULL; + iface->dom_mouse_out = NULL; + iface->security_change = NULL; + iface->status_change = NULL; +} + +static void +kz_gecko_embed_class_init (KzGeckoEmbedClass *klass) +{ + GObjectClass *object_class; + + kz_gecko_embed_parent_class = (GtkMozEmbedClass *)g_type_class_peek_parent (klass); + object_class = (GObjectClass *) klass; + + g_type_class_add_private (object_class, sizeof(KzGeckoEmbedPrivate)); +} + +static void +kz_gecko_embed_init (KzGeckoEmbed *kzembed) +{ + gint i; + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + priv->location = NULL; + priv->title = NULL; + priv->load_started = 0; + priv->load_percent = 0; + priv->bytes_loaded = 0; + priv->max_bytes_loaded = 0; + priv->is_loading = FALSE; + priv->load_status_message = NULL; + priv->wrapper = NULL; + priv->size_inited = FALSE; + priv->total_requests = 0; + priv->cur_requests = 0; + + for (i = 0; i < KZ_EMBED_LINK_GUARD; i++) + { + priv->nav_links[i] = NULL; + } +#ifdef USE_MIGEMO + priv->migemo_keyword = NULL; +#endif + priv->last_highlight = NULL; + priv->first_url = NULL; + +#ifndef KZ_REGRESSION_BUG4474 +#ifndef HAVE_GECKO_1_8 + kz_moz_embed_load_url(KZ_EMBED(kzembed), "about:blank"); +#endif +#endif +} + +static void +kz_gecko_embed_load_url (KzEmbed *kzembed, const gchar *url) +{ + gchar *start_page = NULL; + + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (url && *url) + { + start_page = g_strdup(url); + } + else + { + start_page = g_strdup("about:blank"); + } + + if (!priv->first_url && + kz_gecko_embed_get_lock(kzembed)) + { + GtkMozEmbed *newembed = NULL; + g_signal_emit_by_name(kzembed, + "new-window", + &newembed, 0); + gtk_moz_embed_load_url(newembed, start_page); + return; + } + else + { + gtk_moz_embed_load_url(GTK_MOZ_EMBED(kzembed), start_page); + } + if (priv->location) + g_free(priv->location); + priv->location = start_page; +} + + +static void +kz_gecko_embed_view_source (KzEmbed *kzembed, const gchar *url) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzMozWrapper *wrapper = priv->wrapper; + nsresult rv; + + nsCOMPtr<nsISupports> pageDescriptor; + rv = wrapper->GetPageDescriptor(getter_AddRefs(pageDescriptor)); + if (!pageDescriptor || NS_FAILED(rv)) return; + + rv = wrapper->LoadDocument(pageDescriptor, + nsIWebPageDescriptor::DISPLAY_AS_SOURCE); + if (NS_FAILED(rv)) return; + + // set history explicitly + nsCOMPtr<nsISHistory> sHistory; + rv = wrapper->GetSHistory(getter_AddRefs(sHistory)); + if (NS_FAILED(rv) || !sHistory) return; + + nsCOMPtr<nsISHistoryInternal> sHistoryInternal; + sHistoryInternal = do_QueryInterface(sHistory); + + gchar *uri = g_strdup_printf("view-source:%s", url); + + nsCOMPtr<nsISHEntry> entry; + entry = do_CreateInstance(NS_SHENTRY_CONTRACTID); + + nsCOMPtr<nsIURI> aURI; + NewURI(getter_AddRefs(aURI), uri); + /* FIXME! set correct contentType */ + nsEmbedCString contentType; + entry->SetURI(aURI); + sHistoryInternal->AddEntry(entry, PR_TRUE); + g_free(uri); +} + + +static gboolean +kz_gecko_embed_is_loading (KzEmbed *kzembed) +{ + return KZ_IS_GECKO_EMBED(kzembed) + ? KZ_GECKO_EMBED_GET_PRIVATE(kzembed)->is_loading + : FALSE; +} + + +static const gchar * +kz_gecko_embed_get_title (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + return KZ_GECKO_EMBED_GET_PRIVATE(kzembed)->title; +} + +static gchar * +kz_gecko_embed_ensure_title (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (priv->title && *priv->title) + return g_strdup(priv->title); + + if (priv->location && *priv->location) + { + if (kz_gecko_embed_is_loading(kzembed)) + { + return g_strdup_printf(_("Loading %s ..."), + priv->location); + } + else + { + return g_strdup(priv->location); + } + } + else + { + if (kz_gecko_embed_is_loading(kzembed)) + return g_strdup(_("Loading...")); + } + + return g_strdup(_("No title")); +} + +static gchar * +kz_gecko_embed_get_link_message (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_GECKO_EMBED(kzembed), NULL); + + gchar *message; + + message = gtk_moz_embed_get_link_message(GTK_MOZ_EMBED(kzembed)); + + return message; +} + + +static gdouble +kz_gecko_embed_get_progress (KzEmbed *kzembed) +{ + gdouble progress; + + g_return_val_if_fail(KZ_GECKO_EMBED(kzembed), 0.0); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (priv->total_requests <= 0 || + priv->cur_requests <= 0) + { + return 0.0; + } + + progress = (gdouble) priv->cur_requests + / (gdouble) priv->total_requests; + + if (progress > 1.0) + return 1.0; + + return progress; +} + + +static const gchar * +kz_gecko_embed_get_location (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (priv->location != NULL && + !strncmp(priv->location, "about:blank", 11)) + { + return ""; + } + + return priv->location; +} + +static void +kz_gecko_embed_destroy_brsr (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + gtk_widget_destroy(GTK_WIDGET(embed)); +} + + +static void +kz_gecko_embed_link_message (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + g_signal_emit_by_name(embed, "kz-link-message"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->link_message) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->link_message(embed); +} + +static void +kz_gecko_embed_js_status (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + g_signal_emit_by_name(embed, "kz-js-status"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->js_status) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->js_status(embed); +} + +static void +kz_gecko_embed_title (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE(embed); + + g_free(priv->title); + + priv->title = gtk_moz_embed_get_title(embed); + + g_signal_emit_by_name(embed, "kz-title"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->title) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->title(embed); +} + +static void +kz_gecko_embed_location (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE(embed); + +#ifndef KZ_REGRESSION_BUG4474 + if (priv->first_url) + { + gchar *tmp = g_strdup(priv->first_url); + g_free(priv->first_url); + priv->first_url = NULL; + + kz_gecko_embed_load_url(KZ_EMBED(embed), tmp); + g_free(tmp); + + return; + } +#endif + if (priv->location) + g_free(priv->location); + priv->location = gtk_moz_embed_get_location(embed); + + g_signal_emit_by_name(embed, "kz-location"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->location) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->location(embed); +} + + +static void +kz_gecko_embed_net_start (GtkMozEmbed *embed) +{ + KzGeckoEmbed *kzembed = KZ_GECKO_EMBED(embed); + + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (priv->first_url) + return; + + priv->is_loading = TRUE; + + /* First free previous link */ + kz_gecko_embed_navigation_link_free(kzembed); + + g_signal_emit_by_name(embed, "kz-net-start"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_start) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_start(embed); +} + +static void +net_stop_proccess (KzGeckoEmbed *kzembed) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + gboolean create_thumbnail = FALSE, store_cache = TRUE; + KZ_CONF_GET("Global", "create_thumbnail", create_thumbnail, BOOL); + KZ_CONF_GET("History", "store_cache", store_cache, BOOL); + + gchar *cache = g_strconcat("file://", g_get_home_dir(), + HISTORY_DIR, NULL); + const gchar *location = kz_gecko_embed_get_location(KZ_EMBED(kzembed)); + if (location && + (g_str_has_prefix(location, "http:") || + g_str_has_prefix(location, "https:") || + g_str_has_prefix(location, "history-search:") || + g_str_has_prefix(location, "file:")) && + !g_str_has_prefix(location, cache)) + { + //get the last modification time + nsCOMPtr<nsIDOMDocument> domDoc; + priv->wrapper->GetMainDomDocument(getter_AddRefs(domDoc)); + nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(domDoc); + nsEmbedString value; + doc->GetLastModified(value); + + nsEmbedCString cValue; + NS_UTF16ToCString(value, + NS_CSTRING_ENCODING_UTF8, cValue); + nsTime lm (cValue.get(), PR_TRUE); + GTime last_modified; + LL_DIV(last_modified, + NS_STATIC_CAST(PRTime, lm), PR_USEC_PER_SEC); + + nsCOMPtr<nsIURI> inURI; + nsEmbedCString sURI; + nsresult rv; + + rv = priv->wrapper->GetDocumentUrl(sURI); + const gchar *uri = sURI.get(); + rv = NewURI(getter_AddRefs(inURI), uri); + + if (create_thumbnail && + (!last_modified || (thumbnail_get_last_modified(uri) < last_modified))) + { + kz_gecko_embed_create_thumbnail(KZ_EMBED(kzembed)); + } + + if ((!last_modified || (history_get_last_modified(uri) < last_modified)) && + !g_str_has_prefix(location, "history-search:")) + { + if (store_cache) + { + gchar *filename; + filename = kz_gecko_embed_store_history_file(kzembed); + if (filename) + g_free(filename); + } + + if (KZ_GET_SEARCH) + { + const gchar *title = kz_gecko_embed_get_title(KZ_EMBED(kzembed)); + + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(domDoc); + nsCOMPtr<nsIDOMSerializer> serializer; + serializer = do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv); + if (serializer) + { + serializer->SerializeToString(node, value); + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue); + } + kz_search_register_document(KZ_GET_SEARCH, uri, title, cValue.get(), last_modified); +#ifdef WITH_ANTHY_TRAINER + KzSearch *search = kz_search_new("anthy-trainer"); + if (search) + { + kz_search_register_document(search, uri, title, cValue.get(), last_modified); + g_object_unref(search); + } +#endif + } + } + } + + g_free(cache); +} + +static void +kz_gecko_embed_net_stop (GtkMozEmbed *embed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(embed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (embed); + priv->is_loading = FALSE; + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_stop) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_stop(embed); + + net_stop_proccess(KZ_GECKO_EMBED(embed)); + + g_signal_emit_by_name(embed, "kz-net-stop"); +} + +static void +kz_gecko_embed_net_state_all (GtkMozEmbed *embed, const char *aURI, + gint state, guint status) +{ + KzGeckoEmbed *kzembed = KZ_GECKO_EMBED(embed); + + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK) + { + priv->total_requests = 0; + priv->cur_requests = 0; +#if 0 + if (state & GTK_MOZ_EMBED_FLAG_START) + { + } + else if (state & EMBED_STATE_STOP) + { + priv->total_requests = 0; + priv->cur_requests = 0; + } +#endif + } + if (state & GTK_MOZ_EMBED_FLAG_IS_REQUEST) + { + if (state & GTK_MOZ_EMBED_FLAG_START) + priv->total_requests ++; + else if (state & GTK_MOZ_EMBED_FLAG_STOP) + priv->cur_requests ++; + } + + g_signal_emit_by_name(embed, "kz-progress"); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_state_all) + ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->net_state_all(embed, aURI, state, status); +} + +static void +cb_embed_destroy_browser (GtkMozEmbed *embed, GtkWidget *transient_window) +{ + gtk_widget_destroy(GTK_WIDGET(transient_window)); +} + +static void +kz_gecko_embed_new_window (GtkMozEmbed *embed, GtkMozEmbed **newEmbed, + guint chromemask) +{ + if ((chromemask & GTK_MOZ_EMBED_FLAG_OPENASCHROME) != 0) + { + /* FIXME! this is ad hoc. */ + GtkWidget *newWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_window_set_transient_for(GTK_WINDOW(newWindow), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(embed)))); + *newEmbed = GTK_MOZ_EMBED(kz_gecko_embed_new(NULL)); + g_signal_connect(*newEmbed,"destroy", + G_CALLBACK(cb_embed_destroy_browser), + newWindow); + gtk_container_add(GTK_CONTAINER(newWindow), + GTK_WIDGET(*newEmbed)); + } + else + { + g_signal_emit_by_name(embed, "kz-new-window", newEmbed); + } +} + +static gint +kz_gecko_embed_open_uri (GtkMozEmbed *embed, const char *uri) +{ + gint ret = FALSE; + + g_signal_emit_by_name(embed, "kz-open-uri", uri, &ret); + + if (((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->open_uri) + ret = ((GtkMozEmbedClass*)kz_gecko_embed_parent_class)->open_uri(embed, uri); + +#if 0 + if (!strncmp(uri, "mailto:", 7)) + { + return TRUE; + } +#endif + + return ret; +} + +static void +kz_gecko_embed_size_to (GtkMozEmbed *embed, gint width, gint height) +{ + gtk_widget_set_size_request(GTK_WIDGET(embed), width, height); + gtk_widget_queue_resize(GTK_WIDGET(embed)); + + g_signal_emit_by_name(embed, "kz-size-to", width, height); +} + +static gint +kz_gecko_embed_dom_key_down (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventKey *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_key_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-key-down", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_key_up (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventKey *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_key_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-key-up", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_key_press (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventKey *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_key_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-key-press", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_mouse_down (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventMouse *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_mouse_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + + g_signal_emit_by_name(embed, "kz-dom-mouse-down", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_mouse_up (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventMouse *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_mouse_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-mouse-up", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_mouse_click (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventMouse *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_mouse_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-mouse-click", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static gint +kz_gecko_embed_dom_mouse_dbl_click (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventMouse *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_mouse_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-mouse-dbl-click", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static +gint kz_gecko_embed_dom_mouse_over (GtkMozEmbed *embed, gpointer event) +{ + KzEmbedEventMouse *kzevent; + gint ret = FALSE; + + kz_gecko_embed_get_mouse_event_info(KZ_GECKO_EMBED(embed), event, &kzevent); + g_signal_emit_by_name(embed, "kz-dom-mouse-over", + kzevent, &ret); + kz_embed_event_free((KzEmbedEvent *) kzevent); + + return ret; +} + +static void +kz_gecko_embed_visibility (GtkMozEmbed *embed, gboolean visibility) +{ + GtkWidget *parent = NULL; + + parent = gtk_widget_get_parent(GTK_WIDGET(embed)); + g_return_if_fail(parent != NULL); + + g_object_set(embed, "visible", visibility, NULL); + g_object_set(parent, "visible", visibility, NULL); +} + +#if 0 +static void +kz_gecko_embed_security_change (GtkMozEmbed *embed, + gpointer request, + guint state) +{ + if (kz_gecko_embed_parent_class->security_change) + kz_gecko_embed_parent_class->security_change(embed, request, state); +} +#endif + +static gboolean +kz_gecko_embed_can_cut_selection (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return TRUE; + + PRBool retval; + nsresult rv = priv->wrapper->CanCutSelection(&retval); + + if (NS_FAILED(rv)) return FALSE; + + return retval; +} + +static gboolean +kz_gecko_embed_can_copy_selection (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return TRUE; + + PRBool retval; + nsresult rv = priv->wrapper->CanCopySelection(&retval); + + if (NS_FAILED(rv)) return FALSE; + + return retval; +} + +static gboolean +kz_gecko_embed_can_paste (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return TRUE; + + PRBool retval; + nsresult rv = priv->wrapper->CanPaste(&retval); + + if (NS_FAILED(rv)) return FALSE; + + return retval; +} + +static void +kz_gecko_embed_cut_selection (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + + priv->wrapper->CutSelection(); +} + +static void +kz_gecko_embed_copy_selection (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + + priv->wrapper->CopySelection(); +} + +static void +kz_gecko_embed_paste (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + + priv->wrapper->Paste(); +} + +static void +kz_gecko_embed_select_all (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + + priv->wrapper->SelectAll(); +} + +static gchar * +kz_gecko_embed_get_selection_string(KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return NULL; + + nsresult rv; + + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (!selection) return NULL; + + PRUnichar *string; + rv = selection->ToString(&string); + + nsEmbedCString str; + NS_UTF16ToCString(nsEmbedString(string), + NS_CSTRING_ENCODING_UTF8, str); + + return g_strdup (str.get()); +} + +static gchar * +kz_gecko_embed_get_html_with_contents (KzEmbed *kzembed, const gchar *storedir) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return NULL; + + nsresult rv; + + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (!selection) return NULL; + + nsEmbedString string; + rv = priv->wrapper->GetHtmlWithContents(selection, + storedir, + string); + if (NS_FAILED(rv)) return NULL; + + nsEmbedCString str; + NS_UTF16ToCString(nsEmbedString(string), + NS_CSTRING_ENCODING_UTF8, str); + return g_strdup(str.get()); +} +#if 0 +static gchar * +kz_gecko_embed_get_selection_source(KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + if (!priv->wrapper) return NULL; + + nsresult rv; + + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (!selection) return NULL; + + nsAutoString string; + rv = priv->wrapper->GetSelectionSource(selection, PR_TRUE, string); + if (NS_FAILED(rv)) return NULL; + + return g_strdup(NS_ConvertUCS2toUTF8(string).get()); +} +#endif + +#if USE_MIGEMO +static gboolean +kz_gecko_embed_get_body_string(KzGeckoEmbed *mozembed, gchar **body_string, + gboolean backward, gboolean whole) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (mozembed); + nsEmbedString text; + nsresult rv; + + if (whole) + rv = priv->wrapper->GetBodyString(text); + else + rv = priv->wrapper->GetStringSelection(text, backward); + if (NS_FAILED(rv)) + return FALSE; + + nsEmbedCString str; + NS_UTF16ToCString(text, + NS_CSTRING_ENCODING_UTF8, str); + *body_string = g_strdup(str.get()); + return TRUE; +} + +static void +set_migemo_keyword(KzGeckoEmbed *mozembed, const char *keyword, + gchar *body_string, gboolean backward) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (mozembed); + g_free(priv->migemo_keyword); + priv->migemo_keyword = + kz_migemo_get_matched_text(KZ_GET_MIGEMO, body_string, + keyword, backward); +} +#endif + +static gboolean +kz_gecko_embed_unhighlight_word (KzEmbed *kzembed, const char *word) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return FALSE; + + KzMozWrapper *wrapper = priv->wrapper; + + nsresult rv; + nsCOMPtr<nsIFind> finder; + finder = do_CreateInstance("@mozilla.org/embedcomp/rangefind;1", &rv); + + if (NS_FAILED(rv)) return FALSE; + + nsEmbedString string; + NS_CStringToUTF16(nsEmbedCString(word), + NS_CSTRING_ENCODING_UTF8, string); + const PRUnichar *u_word; + NS_StringGetData(string, &u_word); + + nsCOMPtr<nsIDOMDocument> domDoc; + rv = wrapper->GetMainDomDocument(getter_AddRefs(domDoc)); + if (NS_FAILED(rv) || !domDoc) return FALSE; + + nsCOMPtr<nsIDOMDocumentRange> docRange = do_QueryInterface(domDoc); + if (!docRange) return FALSE; + + nsCOMPtr<nsIDOMRange> searchRange; + nsCOMPtr<nsIDOMRange> startRange; + nsCOMPtr<nsIDOMRange> endRange; + rv = wrapper->SetHighlightRange(getter_AddRefs(searchRange), + getter_AddRefs(startRange), + getter_AddRefs(endRange)); + nsCOMPtr<nsIDOMRange> retRange; + + while (finder->Find(u_word, searchRange, startRange, endRange, getter_AddRefs(retRange)) == NS_OK) + { + if (!retRange) break; + + nsCOMPtr<nsIDOMNode> startContainer; + retRange->GetStartContainer(getter_AddRefs(startContainer)); + + nsCOMPtr<nsIDOMNode> elm; + startContainer->GetParentNode(getter_AddRefs(elm)); + + char *attr = NULL; + wrapper->GetAttributeFromNode(elm, "id", &attr); + if (elm && attr && !g_ascii_strcasecmp(attr, "kazehakase-search")) + { + nsCOMPtr<nsIDOMDocumentFragment> flag; + nsCOMPtr<nsIDOMNode> next; + nsCOMPtr<nsIDOMNode> parent; + + domDoc->CreateDocumentFragment(getter_AddRefs(flag)); + nsCOMPtr<nsIDOMNode> flagNode; + flagNode = do_QueryInterface(flag); + + elm->GetNextSibling(getter_AddRefs(next)); + elm->GetParentNode(getter_AddRefs(parent)); + + nsCOMPtr<nsIDOMNode> child; + while (elm->GetFirstChild(getter_AddRefs(child)) == NS_OK) + { + if (!child) break; + nsCOMPtr<nsIDOMNode> newNode; + flagNode->AppendChild(child, getter_AddRefs(newNode)); + } + + docRange->CreateRange(getter_AddRefs(startRange)); + startRange->SetStartAfter(elm); + + nsCOMPtr<nsIDOMNode> tmp; + parent->RemoveChild(elm, getter_AddRefs(tmp)); + parent->InsertBefore(flagNode, next, getter_AddRefs(tmp)); + } + else + { + nsCOMPtr<nsIDOMNode> endContainer; + retRange->GetEndContainer(getter_AddRefs(endContainer)); + PRInt32 endOffset; + retRange->GetEndOffset(&endOffset); + docRange->CreateRange(getter_AddRefs(startRange)); + startRange->SetStart(endContainer, endOffset); + } + startRange->Collapse(PR_TRUE); + } + + return TRUE; +} + + +// this function is drawn upon +// toolkit/components/typeaheadfind/content/findBar.js in firefox-1.0+. +static gboolean +kz_gecko_embed_highlight_word (KzEmbed *kzembed, const char *word) +{ + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (priv->last_highlight) + { + if (!strcmp(priv->last_highlight, word)) + return TRUE; + kz_gecko_embed_unhighlight_word (kzembed, priv->last_highlight); + g_free(priv->last_highlight); + } + + priv->last_highlight = g_strdup(word); + + nsresult rv; + nsCOMPtr<nsIFind> finder; + finder = do_CreateInstance("@mozilla.org/embedcomp/rangefind;1", &rv); + + if (NS_FAILED(rv)) return FALSE; + + nsEmbedString string; + NS_CStringToUTF16(nsEmbedCString(word), + NS_CSTRING_ENCODING_UTF8, string); + const PRUnichar *u_word; + NS_StringGetData(string, &u_word); + + nsCOMPtr<nsIDOMDocument> domDoc; + rv = priv->wrapper->GetMainDomDocument(getter_AddRefs(domDoc)); + if (NS_FAILED(rv) || !domDoc) return FALSE; + + + nsCOMPtr<nsIDOMRange> searchRange; + nsCOMPtr<nsIDOMRange> startRange; + nsCOMPtr<nsIDOMRange> endRange; + rv = priv->wrapper->SetHighlightRange(getter_AddRefs(searchRange), + getter_AddRefs(startRange), + getter_AddRefs(endRange)); + + const PRUnichar span[] = { 's', 'p', 'a', 'n' ,'\0' }; + const PRUnichar style[] = { 's', 't', 'y', 'l' ,'e', '\0' }; + const PRUnichar u_color[] = { 's', 'p', 'a', 'n' ,'\0' }; + const PRUnichar id[] = { 'i', 'd', '\0' }; + const PRUnichar sc[] = { ';', '\0' }; + const PRUnichar bg_color[] = { 'b', 'a', 'c', 'k' ,'g', 'r', + 'o', 'u', 'n', 'd', '-', 'c', + 'o', 'l', 'o', 'r', ':', '\0' }; + const PRUnichar kazehakase_id[] = { 'k', 'a', 'z', 'e' ,'h', 'a', + 'k', 'a', 's', 'e', '-', 's', + 'e', 'a', 'r', 'c', 'h', '\0' }; + + nsEmbedCString cColor("#ffff00"); + nsEmbedString uColor; + NS_CStringToUTF16(cColor, NS_CSTRING_ENCODING_UTF8, uColor); + nsEmbedString color(bg_color); + color += uColor; + color += sc; + nsCOMPtr<nsIDOMElement> baseElm; + domDoc->CreateElement(nsEmbedString(span), getter_AddRefs(baseElm)); + baseElm->SetAttribute(nsEmbedString(style), color); + baseElm->SetAttribute(nsEmbedString(id), nsEmbedString(kazehakase_id)); + nsCOMPtr<nsIDOMNode> baseNode = do_QueryInterface(baseElm); + + nsCOMPtr<nsIDOMRange> retRange; + + while (finder->Find(u_word, searchRange, startRange, endRange, getter_AddRefs(retRange)) == NS_OK) + { + if (!retRange) break; + + nsCOMPtr<nsIDOMNode> node; + baseNode->CloneNode(PR_TRUE, getter_AddRefs(node)); + + nsCOMPtr<nsIDOMNode> startContainer; + retRange->GetStartContainer(getter_AddRefs(startContainer)); + + PRInt32 startOffset, endOffset; + retRange->GetStartOffset(&startOffset); + retRange->GetEndOffset(&endOffset); + + nsCOMPtr<nsIDOMDocumentFragment> flag; + retRange->ExtractContents(getter_AddRefs(flag)); + if (!flag) continue; + + nsCOMPtr<nsIDOMNode> flagNode; + flagNode = do_QueryInterface(flag); + + nsCOMPtr<nsIDOMText> text; + text = do_QueryInterface(startContainer); + + nsCOMPtr<nsIDOMText> before; + text->SplitText(startOffset, getter_AddRefs(before)); + nsCOMPtr<nsIDOMNode> beforeNode; + beforeNode = do_QueryInterface(before); + + nsCOMPtr<nsIDOMNode> parent; + beforeNode->GetParentNode(getter_AddRefs(parent)); + + nsCOMPtr<nsIDOMNode> newNode; + node->AppendChild(flagNode, getter_AddRefs(newNode)); + nsCOMPtr<nsIDOMNode> newParent; + parent->InsertBefore(node, beforeNode, getter_AddRefs(newParent)); + + nsCOMPtr<nsIDOMDocument> doc; + node->GetOwnerDocument(getter_AddRefs(doc)); + nsCOMPtr<nsIDOMDocumentRange> range; + range = do_QueryInterface(doc); + + range->CreateRange(getter_AddRefs(startRange)); + + nsCOMPtr<nsIDOMNodeList> list; + node->GetChildNodes(getter_AddRefs(list)); + + PRUint32 length; + list->GetLength(&length); + startRange->SetStart(node, length); + startRange->SetEnd(node, length); + } + + return TRUE; +} + + +static gboolean +kz_gecko_embed_find (KzEmbed *kzembed, const char *keyword, + gboolean backward) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + g_return_val_if_fail(keyword, FALSE); + + nsCOMPtr<nsIWebBrowser> web; + gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(kzembed), + getter_AddRefs(web)); + if (!web) return FALSE; + + + nsresult rv; + nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(web)); +#if USE_MIGEMO + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + gboolean use_migemo; + KZ_CONF_GET("Global", "use_migemo", use_migemo, BOOL); + + nsEmbedString str; + if (use_migemo) + { + gchar *body_string; + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!kz_gecko_embed_get_body_string(mozembed, &body_string, + backward, FALSE)) + goto START_SEARCH; + set_migemo_keyword(mozembed, keyword, body_string, backward); + + if (!priv->migemo_keyword) + { + g_free(body_string); + if (!kz_gecko_embed_get_body_string(mozembed, + &body_string, + backward, + TRUE)) + goto START_SEARCH; + set_migemo_keyword(mozembed, keyword, + body_string, backward); + } + + if (priv->migemo_keyword) + { + NS_CStringToUTF16(nsEmbedCString(priv->migemo_keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + else + { + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + g_free(body_string); + } + else + { + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + finder->SetSearchString(str.get()); +START_SEARCH: +#else + nsEmbedString str; + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + finder->SetSearchString(str.get()); +#endif + finder->SetFindBackwards(backward); + finder->SetWrapFind(TRUE); + finder->SetEntireWord(TRUE); + finder->SetSearchFrames(TRUE); + finder->SetMatchCase(FALSE); + PRBool did_find; + rv = finder->FindNext(&did_find); + + return NS_SUCCEEDED(rv) && did_find ? TRUE : FALSE; +} + +static gboolean +kz_gecko_embed_incremental_search (KzEmbed *kzembed, const char *keyword, + gboolean backward) +{ + nsresult rv; + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + g_return_val_if_fail(keyword, FALSE); + + if (strlen(keyword) == 0) + return FALSE; + + nsCOMPtr<nsIWebBrowser> web; + gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(kzembed), + getter_AddRefs(web)); + if (!web) return FALSE; + + nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(web)); +#if USE_MIGEMO + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + gboolean use_migemo; + KZ_CONF_GET("Global", "use_migemo", use_migemo, BOOL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (!selection) return FALSE; + + selection->RemoveAllRanges(); + + nsEmbedString str; + if (use_migemo) + { + gchar *body_string; + + if (!kz_gecko_embed_get_body_string(mozembed, &body_string, + backward, TRUE)) + goto START_SEARCH; + set_migemo_keyword(mozembed, keyword, body_string, backward); + + if (priv->migemo_keyword) + { + NS_CStringToUTF16(nsEmbedCString(priv->migemo_keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + else + { + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + g_free(body_string); + } + else + { + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + } + finder->SetSearchString(str.get()); +START_SEARCH: +#else + nsEmbedString str; + NS_CStringToUTF16(nsEmbedCString(keyword), + NS_CSTRING_ENCODING_UTF8, str); + finder->SetSearchString(str.get()); +#endif + finder->SetFindBackwards(backward); + finder->SetWrapFind(TRUE); + finder->SetEntireWord(TRUE); + finder->SetSearchFrames(TRUE); + finder->SetMatchCase(FALSE); + PRBool did_find; + rv = finder->FindNext(&did_find); + + // highlight search word + + gboolean use_highlight = FALSE; + KZ_CONF_GET("Global", "use_highlight", use_highlight, BOOL); + if (use_highlight) + { + if (NS_SUCCEEDED(rv)) + { + nsEmbedCString c_str; + NS_UTF16ToCString(str, NS_CSTRING_ENCODING_UTF8, c_str); + kz_gecko_embed_highlight_word(kzembed, c_str.get()); + } + } + + return NS_SUCCEEDED(rv) && did_find ? TRUE : FALSE; +} + +static gboolean +kz_gecko_embed_selection_is_collapsed (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), TRUE); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return TRUE; + + nsresult rv; + + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (!selection) return TRUE; + + PRBool collapsed; + rv = selection->GetIsCollapsed(&collapsed); + if (NS_FAILED(rv)) return TRUE; + + return collapsed; +} + + +static gboolean +kz_gecko_embed_get_links (KzEmbed *kzembed, GList **list, + gboolean selected_only) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_val_if_fail(priv->wrapper, FALSE); + g_return_val_if_fail(list, FALSE); + + // get selection + nsresult rv; + nsCOMPtr<nsISelection> selection; + rv = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv)) return FALSE; + + // get all anchor nodes in the document. + nsCOMPtr<nsIDOMDocument> mainDoc; + rv = priv->wrapper->GetMainDomDocument(getter_AddRefs(mainDoc)); + if (NS_FAILED(rv) || !mainDoc) return FALSE; + + // get main DOMWindow + nsCOMPtr<nsIDOMWindow> mainDOMWindow; + rv = priv->wrapper->GetDOMWindow(getter_AddRefs(mainDOMWindow)); + if (NS_FAILED(rv)) return FALSE; + + rv = priv->wrapper->GetLinksFromWindow(mainDOMWindow, + list, + selection, + selected_only); + + return NS_FAILED(rv) ? FALSE : TRUE; +} + + +static gboolean +kz_gecko_embed_get_dest_anchors (KzEmbed *kzembed, GList **list) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_val_if_fail(priv->wrapper, FALSE); + g_return_val_if_fail(list, FALSE); + + // get all anchor nodes in the document. + nsCOMPtr<nsIDOMDocument> mainDoc; + nsresult rv = priv->wrapper->GetMainDomDocument(getter_AddRefs(mainDoc)); + if (NS_FAILED(rv) || !mainDoc) return FALSE; + + // get main DOMWindow + nsCOMPtr<nsIDOMWindow> mainDOMWindow; + rv = priv->wrapper->GetDOMWindow(getter_AddRefs(mainDOMWindow)); + if (NS_FAILED(rv)) return FALSE; + + rv = priv->wrapper->GetDestAnchorsFromWindow(mainDOMWindow, + list); + + return NS_FAILED(rv) ? FALSE : TRUE; +} + + +glong +kz_gecko_embed_get_key_event_info(KzGeckoEmbed *kzembed, gpointer event, + KzEmbedEventKey **info_ret) +{ + KzEmbedEventKey *info; + info = (KzEmbedEventKey *) kz_embed_event_new(KZ_EMBED_EVENT_KEY); + *info_ret = info; + + nsresult result; + + nsIDOMKeyEvent *aKeyEvent = (nsIDOMKeyEvent*) event; + + nsCOMPtr<nsIDOMEventTarget> OriginalTarget; + + nsCOMPtr<nsIDOMNSEvent> aEvent = do_QueryInterface(aKeyEvent); + if (!aEvent) return KZ_CONTEXT_NONE; + + PRUint32 code; + aKeyEvent->GetKeyCode(&code); + info->key = code; + + aKeyEvent->GetCharCode(&code); + info->char_code = code; + + PRBool mod_key; + info->modifier = 0; + aKeyEvent->GetAltKey(&mod_key); + if (mod_key) info->modifier |= KZ_ALT_KEY; + + aKeyEvent->GetShiftKey(&mod_key); + if (mod_key) info->modifier |= KZ_SHIFT_KEY; + + aKeyEvent->GetMetaKey(&mod_key); + if (mod_key) info->modifier |= KZ_META_KEY; + + aKeyEvent->GetCtrlKey(&mod_key); + if (mod_key) info->modifier |= KZ_CTRL_KEY; + + result = aEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget)); + + if (NS_FAILED(result) || !OriginalTarget) return KZ_CONTEXT_NONE; + + nsCOMPtr<nsIDOMNode> OriginalNode = do_QueryInterface(OriginalTarget); + if (!OriginalNode) return KZ_CONTEXT_NONE; + + nsEmbedString nodename; + OriginalNode->GetNodeName(nodename); + + nsEmbedCString cNodename; + NS_UTF16ToCString(nodename, NS_CSTRING_ENCODING_UTF8, cNodename); + + if (!g_ascii_strcasecmp(cNodename.get(), "xul:thumb") || + !g_ascii_strcasecmp(cNodename.get(), "xul:slider")) + { + return KZ_CONTEXT_NONE; + } + + nsCOMPtr<nsIDOMEventTarget> target; + result = aKeyEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(result) || !target) return KZ_CONTEXT_NONE; + + return kz_gecko_embed_set_event_context(kzembed, target, (KzEmbedEvent *) info); +} + + +glong +kz_gecko_embed_get_mouse_event_info(KzGeckoEmbed *kzembed, gpointer event, + KzEmbedEventMouse **info_ret) +{ + KzEmbedEventMouse *info; + info = (KzEmbedEventMouse *) kz_embed_event_new(KZ_EMBED_EVENT_MOUSE); + *info_ret = info; + + nsresult result; + + nsIDOMMouseEvent *aMouseEvent = (nsIDOMMouseEvent*)event; + + nsCOMPtr<nsIDOMEventTarget> OriginalTarget; + + nsCOMPtr<nsIDOMNSEvent> aEvent = do_QueryInterface(aMouseEvent); + if (!aEvent) return KZ_CONTEXT_NONE; + + PRUint16 button; + aMouseEvent->GetButton(&button); + info->button = button; + + PRBool mod_key; + info->modifier = 0; + aMouseEvent->GetAltKey(&mod_key); + if (mod_key) info->modifier |= KZ_ALT_KEY; + + aMouseEvent->GetShiftKey(&mod_key); + if (mod_key) info->modifier |= KZ_SHIFT_KEY; + + aMouseEvent->GetMetaKey(&mod_key); + if (mod_key) info->modifier |= KZ_META_KEY; + + aMouseEvent->GetCtrlKey(&mod_key); + if (mod_key) info->modifier |= KZ_CTRL_KEY; + + PRInt32 pos; + aMouseEvent->GetClientX(&pos); + info->x = pos; + aMouseEvent->GetClientY(&pos); + info->y = pos; + + result = aEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget)); + + if (NS_FAILED(result) || !OriginalTarget) return KZ_CONTEXT_NONE; + + nsCOMPtr<nsIDOMNode> OriginalNode = do_QueryInterface(OriginalTarget); + if (!OriginalNode) return KZ_CONTEXT_NONE; + + nsEmbedString nodename; + OriginalNode->GetNodeName(nodename); + + nsEmbedCString cNodename; + NS_UTF16ToCString(nodename, NS_CSTRING_ENCODING_UTF8, cNodename); + + if (!g_ascii_strcasecmp(cNodename.get(), "xul:thumb") || + !g_ascii_strcasecmp(cNodename.get(), "xul:slider")) + { + return KZ_CONTEXT_NONE; + } + + nsCOMPtr<nsIDOMEventTarget> target; + result = aMouseEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(result) || !target) return KZ_CONTEXT_NONE; + + return kz_gecko_embed_set_event_context(kzembed, target, (KzEmbedEvent *) info); +} + + +static glong +mozilla_set_event_context (KzGeckoEmbed *kzembed, + nsIDOMEventTarget *target, + KzEmbedEvent *info) +{ + nsresult result; + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzMozWrapper *wrapper = priv->wrapper; + + g_return_val_if_fail(priv->wrapper, KZ_CONTEXT_NONE); + + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target); + if (!node) return KZ_CONTEXT_NONE; + + nsCOMPtr<nsIDOMDocument> domDoc; + result = node->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!NS_SUCCEEDED (result) || !domDoc) return KZ_CONTEXT_NONE; + + nsCOMPtr<nsIDOM3Node> domnode = do_QueryInterface(domDoc); + if(!domnode) return KZ_CONTEXT_NONE; + + nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(domDoc); + if (!nsDoc) return KZ_CONTEXT_NONE; + + nsEmbedString spec; + domnode->GetBaseURI(spec); + + nsEmbedCString cSpec; + NS_UTF16ToCString(spec, + NS_CSTRING_ENCODING_UTF8, cSpec); + + nsCOMPtr<nsIURI> baseURI; + NewURI(getter_AddRefs(baseURI), cSpec.get()); + if (!baseURI) return KZ_CONTEXT_NONE; + + nsEmbedString mime; + nsDoc->GetContentType(mime); + + nsEmbedCString cMime; + NS_UTF16ToCString(mime, NS_CSTRING_ENCODING_UTF8, cMime); + if (!g_ascii_strcasecmp(cMime.get(), "text/xul")) return KZ_CONTEXT_NONE; + + PRUint32 flags = KZ_CONTEXT_NONE; + + // check framed page + nsCOMPtr<nsIDOMDocument> mainDocument; + result = priv->wrapper->GetMainDomDocument (getter_AddRefs(mainDocument)); + if (domDoc != mainDocument) + { + flags |= KZ_CONTEXT_FRAME; + nsEmbedCString url; + baseURI->GetSpec(url); + info->frame_src = g_strdup(url.get()); + } + + // check whether the node is in the selection or not + nsCOMPtr<nsISelection> selection; + result = priv->wrapper->GetSelection(getter_AddRefs(selection)); + if (selection) + { + PRBool contains; + selection->ContainsNode(node, PR_TRUE, &contains); + if (contains) + flags |= KZ_CONTEXT_SELECTION; + } + + // Get other context + nsCOMPtr<nsIDOMHTMLElement> element; + + do { + PRUint16 type; + node->GetNodeType(&type); + + element = do_QueryInterface(node); + if (element) + { + nsEmbedString uTag; + element->GetLocalName(uTag); + + nsEmbedCString utf8_tag; + NS_UTF16ToCString(uTag, NS_CSTRING_ENCODING_UTF8, utf8_tag); + + if (!g_ascii_strcasecmp(utf8_tag.get(), "input")) + { + flags |= KZ_CONTEXT_INPUT; + } + else if (!g_ascii_strcasecmp(utf8_tag.get(), "textarea")) + { + flags |= KZ_CONTEXT_INPUT | KZ_CONTEXT_TEXTAREA; + info->element = (void*)element; + } + else if (!g_ascii_strcasecmp(utf8_tag.get(), "img")) + { + flags |= KZ_CONTEXT_IMAGE; + + char *src = NULL; + wrapper->GetAttributeFromNode(node, "src", &src); + if (!src) return KZ_CONTEXT_NONE; + + nsEmbedCString srca; + srca = nsEmbedCString(src); + + nsEmbedCString srcc,imgc; + + srcc = nsEmbedCString(src); + + result = baseURI->Resolve(srcc, imgc); + g_free(src); + + info->img = g_strdup(imgc.get()); + + if (!info->img) return KZ_CONTEXT_NONE; + } + else + { + flags |= KZ_CONTEXT_OTHER; + } + + nsCOMPtr<nsIDOMNamedNodeMap> attributes; + node->GetAttributes(getter_AddRefs(attributes)); + if (attributes) + { + nsCOMPtr<nsIDOMNode> hrefNode; + nsEmbedString href; + + NS_CStringToUTF16(nsEmbedCString("href"), + NS_CSTRING_ENCODING_UTF8, + href); + attributes->GetNamedItem(href, getter_AddRefs(hrefNode)); + if (hrefNode) + { + gchar *link; + flags |= KZ_CONTEXT_LINK; + + wrapper->GetLinkAndTitleFromNode(domDoc, + node, + &link, + &info->linktext); + if (!link) + { + g_free(info->linktext); + return KZ_CONTEXT_NONE; + } + if (!strncasecmp(link, "mailto:", 7)) + info->link = g_strdup(link+7); + else + info->link = g_strdup(link); + g_free(link); + break; + } + } + } + + nsCOMPtr<nsIDOMNode> parentNode; + node->GetParentNode(getter_AddRefs(parentNode)); + + if (!parentNode) + { + node = nsnull; + flags |= KZ_CONTEXT_DOCUMENT; + break; + } + node = parentNode; + } while (node); + + info->context = flags; + + return flags; +} + +static gchar * +kz_gecko_embed_get_up_location(KzGeckoEmbed *kzembed) +{ + const gchar *location; + gchar *up_location = NULL; + gchar *pos, *dummy; + int len; + + location = kz_gecko_embed_get_location(KZ_EMBED(kzembed)); + if (!location) + return NULL; + + len = strlen(location); + if (location[len - 1] == '/') + dummy = g_strndup(location, len - 1); + else + dummy = g_strndup(location, len); + pos = strrchr(dummy, '/'); + if (pos) + up_location = g_strndup(dummy, pos - dummy + 1); + g_free(dummy); + return up_location; +} + +static void +kz_gecko_embed_reload (KzEmbed *kzembed, KzEmbedReloadFlag flags) +{ + gint32 moz_flags; + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + switch (flags) { + case KZ_EMBED_RELOAD_NORMAL: + moz_flags = GTK_MOZ_EMBED_FLAG_RELOADNORMAL; + break; + case KZ_EMBED_RELOAD_BYPASS_CACHE: + moz_flags = GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE; + break; + case KZ_EMBED_RELOAD_BYPASS_PROXY: + moz_flags = GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXY; + break; + case KZ_EMBED_RELOAD_BYPASS_PROXY_AND_CACHE: + moz_flags = GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE; + break; + case KZ_EMBED_RELOAD_CHARSET_CHANGE: + moz_flags = GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE; + break; + } + + gtk_moz_embed_reload(GTK_MOZ_EMBED(kzembed), moz_flags); +} + + +static void +kz_gecko_embed_stop_load (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + gtk_moz_embed_stop_load(GTK_MOZ_EMBED(kzembed)); +} + + +static void +kz_gecko_embed_go_back (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + gtk_moz_embed_go_back(GTK_MOZ_EMBED(kzembed)); +} + + +static void +kz_gecko_embed_go_up (KzEmbed *kzembed) +{ + gchar *location; + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + location = kz_gecko_embed_get_up_location(KZ_GECKO_EMBED(kzembed)); + kz_gecko_embed_load_url(kzembed, location); + g_free(location); +} + +static void +kz_gecko_embed_go_forward (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + gtk_moz_embed_go_forward(GTK_MOZ_EMBED(kzembed)); +} + + +static gboolean +kz_gecko_embed_can_go_back (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + return gtk_moz_embed_can_go_back(GTK_MOZ_EMBED(kzembed)); +} + +static gboolean +kz_gecko_embed_can_go_forward (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + return gtk_moz_embed_can_go_forward(GTK_MOZ_EMBED(kzembed)); +} + +static gboolean +kz_gecko_embed_can_go_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzNavi *navi = KZ_NAVI(g_list_nth_data(priv->nav_links[link], 0)); + return (navi && navi->uri) ? TRUE : FALSE; +} + +static void +kz_gecko_embed_go_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzNavi *navi = KZ_NAVI(g_list_nth_data(priv->nav_links[link], 0)); + g_return_if_fail(navi); + + kz_gecko_embed_load_url(kzembed, navi->uri); +} + + +static void +kz_gecko_embed_append_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + KzNavi *navi) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + g_return_if_fail(link < KZ_EMBED_LINK_GUARD); + g_return_if_fail(navi); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + priv->nav_links[link] = g_list_append(priv->nav_links[link], + g_object_ref(navi)); +} + +static void +kz_gecko_embed_set_nth_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + KzNavi *navi, + guint n) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + g_return_if_fail(link < KZ_EMBED_LINK_GUARD); + g_return_if_fail(navi); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + guint len = g_list_length(priv->nav_links[link]); + GList *nth_nav_link; + + if (n >= len) + { + int i; + for (i = len; i < n; i++) + { + priv->nav_links[link] = + g_list_append(priv->nav_links[link], NULL); + } + } + + nth_nav_link = g_list_nth(priv->nav_links[link], n); + if (nth_nav_link->data) + g_object_unref(nth_nav_link->data); + nth_nav_link->data = g_object_ref(navi); +} + + +static KzNavi * +kz_gecko_embed_get_nth_nav_link (KzEmbed *kzembed, + KzEmbedNavLink link, + guint n) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE(kzembed); + + return KZ_NAVI(g_list_nth_data(priv->nav_links[link], n)); +} + + +static GList * +kz_gecko_embed_get_nav_links (KzEmbed *kzembed, + KzEmbedNavLink link) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE(kzembed); + + return priv->nav_links[link]; +} + + +static void +kz_gecko_embed_go_history_index (KzEmbed *kzembed, gint index) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + + priv->wrapper->GoHistoryIndex(index); +} + +static void +kz_gecko_embed_copy_page (KzEmbed *kzembed, KzEmbed *dkzembed, + KzEmbedCopyType type) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + g_return_if_fail(KZ_IS_GECKO_EMBED(dkzembed)); + + KzMozWrapper *dWrapper = KZ_GECKO_EMBED_GET_PRIVATE(dkzembed)->wrapper;; + KzMozWrapper *sWrapper = KZ_GECKO_EMBED_GET_PRIVATE(kzembed)->wrapper;; + + nsresult rv; + + nsCOMPtr<nsISupports> pageDescriptor; + rv = sWrapper->GetPageDescriptor(getter_AddRefs(pageDescriptor)); + if (!pageDescriptor || NS_FAILED(rv)) return; + + PRUint32 aDisplayType = nsIWebPageDescriptor::DISPLAY_NORMAL; + switch (type) { + case KZ_EMBED_COPY_NORMAL: + aDisplayType = nsIWebPageDescriptor::DISPLAY_NORMAL; + break; + case KZ_EMBED_COPY_SOURCE: + aDisplayType = nsIWebPageDescriptor::DISPLAY_AS_SOURCE; + break; + } + rv = dWrapper->LoadDocument(pageDescriptor, aDisplayType); +} + + +static gboolean +kz_gecko_embed_shistory_copy (KzEmbed *source, + KzEmbed *dest, + gboolean back_history, + gboolean forward_history, + gboolean set_current) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(source), FALSE); + g_return_val_if_fail(KZ_IS_GECKO_EMBED(dest), FALSE); + + nsresult rv; + KzMozWrapper *d_wrapper = KZ_GECKO_EMBED_GET_PRIVATE(dest)->wrapper;; + KzMozWrapper *s_wrapper = KZ_GECKO_EMBED_GET_PRIVATE(source)->wrapper;; + rv = s_wrapper->CopyHistoryTo (d_wrapper, back_history, forward_history, set_current); + + return NS_SUCCEEDED(rv) ? TRUE : FALSE; +} + + +/* picked from galeon-1.3.11a */ +static gboolean +kz_gecko_embed_shistory_get_pos (KzEmbed *kzembed, + int *pos, int *count) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + nsresult rv; + int total, index; + + rv = priv->wrapper->GetSHInfo (&total, &index); + + *pos = index; + *count = total; + + return NS_SUCCEEDED(rv) ? TRUE : FALSE; +} + +/* picked from galeon-1.3.11a */ +static void +kz_gecko_embed_shistory_get_nth (KzEmbed *kzembed, + int nth, + gboolean is_relative, + char **aUrl, + char **aTitle) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzMozWrapper *wrapper = priv->wrapper; + nsresult rv; + + if (is_relative) + { + int pos, count; + if (kz_gecko_embed_shistory_get_pos(kzembed, &pos, &count)) + pos += nth; + else + return; + nth = pos; + } + + nsEmbedCString url; + rv = wrapper->GetSHUrlAtIndex(nth, url); + + *aUrl = (NS_SUCCEEDED (rv) && url.Length()) ? g_strdup(url.get()) : NULL; + + PRUnichar *title; + rv = wrapper->GetSHTitleAtIndex(nth, &title); + + nsEmbedCString str; + NS_UTF16ToCString(nsEmbedString(title), + NS_CSTRING_ENCODING_UTF8, str); + *aTitle = g_strdup (str.get()); + nsMemory::Free(title); +} + + +static gboolean +kz_gecko_embed_get_lock (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + return priv->lock; +} + + +static void +kz_gecko_embed_set_lock (KzEmbed *kzembed, gboolean lock) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + priv->lock = lock; +} + + +static gchar * +kz_gecko_embed_get_body_text(KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + nsEmbedString text; + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_val_if_fail(priv->wrapper, FALSE); + priv->wrapper->GetBodyString(text); + + nsEmbedCString cText; + NS_UTF16ToCString(text, + NS_CSTRING_ENCODING_UTF8, cText); + return g_strdup(cText.get()); +} + + +static void +kz_gecko_embed_set_encoding (KzEmbed *kzembed, const char *encoding) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + priv->wrapper->ForceEncoding(encoding); +} + +static void +kz_gecko_embed_get_encoding (KzEmbed *kzembed, char **encoding, gboolean *forced) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail(priv->wrapper); + priv->wrapper->GetEncoding(encoding, *forced); +} + +static gboolean +kz_gecko_embed_save_with_content (KzEmbed *kzembed, const char *rawfilename) +{ + nsresult rv; + KzMozWrapper *wrapper = NULL; + PRUint32 persistFlags = 0; + + nsCOMPtr<nsIWebBrowserPersist> bpersist = + do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID); + if (!bpersist) return FALSE; + + nsCOMPtr<nsIURI> linkURI; + linkURI = nsnull; + + nsEmbedCString filename(rawfilename); + nsCOMPtr<nsILocalFile> file; + NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file)); + if (!file) return FALSE; + + nsCOMPtr<nsILocalFile> path; + char *datapath; + datapath = g_strconcat (rawfilename, ".content", NULL); + + nsEmbedString DataPath; + NS_CStringToUTF16(nsEmbedCString(datapath), + NS_CSTRING_ENCODING_UTF8, DataPath); + NS_NewLocalFile(DataPath, PR_TRUE, getter_AddRefs(path)); + g_free (datapath); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + wrapper = priv->wrapper; + g_return_val_if_fail (wrapper != NULL, FALSE); + + persistFlags = nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES; + + size_t len = strlen(rawfilename); + if((rawfilename[len-1] == 'z' && rawfilename[len-2] == 'g') || + (rawfilename[len-1] == 'Z' && rawfilename[len-2] == 'G')) + { + persistFlags |= nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION; + } + + persistFlags |= nsIWebBrowserPersist::PERSIST_FLAGS_BYPASS_CACHE; + bpersist->SetPersistFlags (persistFlags); + + nsCOMPtr<nsIDOMDocument> DOMDocument; + + rv = wrapper->GetMainDomDocument (getter_AddRefs(DOMDocument)); + if (NS_FAILED(rv) || !DOMDocument) return FALSE; + + nsCOMPtr<nsIURI> inURI; + nsEmbedCString sURI; + + rv = wrapper->GetDocumentUrl(sURI); + rv = NewURI(getter_AddRefs(inURI), sURI.get()); + + // FIXME! Use ProgressListener. + // KzMozProgressListener *aProgress = new KzMozProgressListener (); + // aProgress->Init(inURI, path, + // nsnull, nsnull, 0, bpersist); + + rv = bpersist->SaveDocument (DOMDocument, file, path, nsnull, 0, 0); + if (NS_FAILED(rv)) return FALSE; + + return TRUE; +} + + +static void +kz_gecko_embed_print (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail (priv->wrapper != NULL); + + priv->wrapper->Print(); +} + + +static void +kz_gecko_embed_print_preview (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_if_fail (priv->wrapper != NULL); + + priv->wrapper->PrintPreview(); +} + + +static GList * +kz_gecko_embed_get_printer_list (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + g_return_val_if_fail (priv->wrapper != NULL, NULL); + + GList *list = NULL; + priv->wrapper->GetPrinterList(&list); + + return list; +} + + +static gchar * +kz_gecko_embed_get_text_from_textarea (KzEmbed *kzembed, + gpointer element) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + + nsIDOMHTMLElement *htmlElement = (nsIDOMHTMLElement*)element; + + nsCOMPtr<nsIDOMHTMLTextAreaElement> tElement = do_QueryInterface(htmlElement); + + g_return_val_if_fail(tElement, NULL); + + nsEmbedString string; + tElement->GetValue(string); + + nsEmbedCString cString; + NS_UTF16ToCString(string, + NS_CSTRING_ENCODING_UTF8, cString); + + return g_strdup(cString.get()); +} + + +static gboolean +kz_gecko_embed_set_text_into_textarea (KzEmbed *kzembed, + gpointer element, + const gchar *text) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + nsIDOMHTMLElement *htmlElement = (nsIDOMHTMLElement*)element; + + nsCOMPtr<nsIDOMHTMLTextAreaElement> tElement = do_QueryInterface(htmlElement); + + if (!tElement) return FALSE; + + nsEmbedString string; + NS_CStringToUTF16(nsEmbedCString(text), + NS_CSTRING_ENCODING_UTF8, string); + tElement->SetValue(string); + + return TRUE; +} + + +static gchar * +kz_gecko_embed_store_history_file(KzGeckoEmbed *kzembed) +{ + nsresult rv; + + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), NULL); + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + KzMozWrapper *wrapper = priv->wrapper; + g_return_val_if_fail (wrapper != NULL, NULL); + + PRUint32 persistFlags = 0; + + nsCOMPtr<nsIWebBrowserPersist> bpersist = + do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID); + if (!bpersist) return NULL; + + persistFlags = nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES; + + persistFlags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; + bpersist->SetPersistFlags (persistFlags); + + nsCOMPtr<nsIURI> inURI; + nsEmbedCString sURI; + + rv = wrapper->GetDocumentUrl(sURI); + rv = NewURI(getter_AddRefs(inURI), sURI.get()); + + gchar *dir, *filename; + + filename = create_filename_with_path_from_uri(sURI.get()); + + dir = g_build_filename(g_get_home_dir(), + HISTORY_DIR, + filename, + NULL); + g_free(filename); + + nsCOMPtr<nsILocalFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); + rv = localFile->InitWithNativePath(nsEmbedCString(dir)); + + if (NS_FAILED(rv)) + return NULL; + + PRBool exists; + localFile->Exists(&exists); + if (!exists) + { + rv = localFile->Create(nsIFile::NORMAL_FILE_TYPE, 0600); + if (NS_FAILED(rv)) + return NULL; + } + + nsCOMPtr<nsISupports> pageDescriptor; + + wrapper->GetPageDescriptor(getter_AddRefs(pageDescriptor)); + + rv = bpersist->SaveURI (inURI, pageDescriptor, nsnull, + nsnull, nsnull, localFile); + + // update timestamp file + gchar *timestamp_file = g_build_filename(g_get_home_dir(), + HISTORY_DIR, + "timestamp", + NULL); + + struct stat st; + g_stat(dir, &st); + // Hmm, rounding st_mtime causes some problem I think. Is it OK? + gchar *time = g_strdup_printf("%d", (int)st.st_mtime); + + GIOChannel *io = g_io_channel_new_file(timestamp_file, "a+", NULL); + g_io_channel_set_encoding(io, NULL, NULL); + g_io_channel_write_chars(io, time, strlen(time), + NULL, NULL); + g_io_channel_write_chars(io, ",", 1, NULL, NULL); + g_io_channel_write_chars(io, dir, strlen(dir), + NULL, NULL); + g_io_channel_write_chars(io, "\n", 1, NULL, NULL); + g_io_channel_shutdown(io, TRUE, NULL); + g_io_channel_unref(io); + + g_free(time); + g_free(timestamp_file); + + return dir; +} + + +#ifndef MOZ_NSICANVASRENDERINGCONTEXTINTERNAL_HAVE_GETINPUTSTREAM_ +static KzMozThumbnailCreator * +kz_window_create_thumbnail_creator (KzWindow *kz) +{ + KzMozThumbnailCreator *creator; + + creator = KZ_MOZ_THUMBNAIL_CREATOR(g_object_get_data(G_OBJECT(kz), + "KzGeckoEmbed::ThumbnailCreator")); + if (!creator) + { + creator = kz_moz_thumbnail_creator_new(); + gtk_widget_set_size_request(GTK_WIDGET(creator), 0, 0); + gtk_widget_show(GTK_WIDGET(creator)); + + gtk_box_pack_start(GTK_BOX(kz->statusbar), + GTK_WIDGET(creator), + FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(kz), + "KzGeckoEmbed::ThumbnailCreator", + creator); + } + + return creator; +} +#endif + +static void +kz_gecko_embed_create_thumbnail (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + gboolean create_thumbnail = FALSE; + KZ_CONF_GET("Global", "create_thumbnail", create_thumbnail, BOOL); + if (!create_thumbnail) return; + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + KzMozWrapper *wrapper = priv->wrapper; + g_return_if_fail (wrapper != NULL); + +#ifdef MOZ_NSICANVASRENDERINGCONTEXTINTERNAL_HAVE_GETINPUTSTREAM_ + wrapper->CreateThumbnail(); +#else + nsresult rv; + int total, index; + rv = wrapper->GetSHInfo (&total, &index); + + nsCOMPtr<nsIHistoryEntry> he; + rv = wrapper->GetHistoryEntry(index, getter_AddRefs(he)); + if (NS_FAILED(rv)) return; + + GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(kzembed)); + + if (!KZ_IS_WINDOW(window)) return; + + KzWindow *kz = KZ_WINDOW(window); + + KzMozThumbnailCreator *creator; + creator = kz_window_create_thumbnail_creator(kz); + kz_moz_thumbnail_creator_append_queue(creator, he); +#endif +} + + +void +kz_gecko_embed_do_command (KzEmbed *kzembed, const char *command) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + nsCOMPtr<nsICommandManager> commandManager; + commandManager = do_GetInterface(priv->wrapper->mWebBrowser); + if (!commandManager) return; + + commandManager->DoCommand(command, nsnull, nsnull); + +} + +static gboolean +kz_gecko_embed_can_do_command (KzEmbed *kzembed, const char *command) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + nsCOMPtr<nsICommandManager> commandManager; + commandManager = do_GetInterface(priv->wrapper->mWebBrowser); + if (!commandManager) return FALSE; + + PRBool enabled; + commandManager->IsCommandEnabled(command, nsnull, &enabled); + + return (enabled == PR_TRUE); +} + +static void +kz_gecko_embed_zoom_set (KzEmbed *kzembed, int zoom, gboolean reflow) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + priv->wrapper->SetImageZoom ((float)(zoom) / 100); + + kz_gecko_embed_set_text_size(kzembed, zoom, reflow); +} + +static int +kz_gecko_embed_zoom_get (KzEmbed *kzembed) +{ + return kz_gecko_embed_get_text_size(kzembed); +} + + +static void +kz_gecko_embed_set_text_size (KzEmbed *kzembed, int zoom, gboolean reflow) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + priv->wrapper->SetZoom ((float)(zoom) / 100, reflow); +} + +static int +kz_gecko_embed_get_text_size (KzEmbed *kzembed) +{ + float f; + int zoom; + + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), 100); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return 100; + + nsresult result = priv->wrapper->GetZoom (&f); + if (NS_FAILED (result)) return 100; + + zoom = (int) rint (f * 100); + + return zoom; +} + +static void +kz_gecko_embed_set_history (KzEmbed *kzembed, KzBookmark *history) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + g_return_if_fail(KZ_IS_BOOKMARK(history)); + + if (!kz_bookmark_is_folder(history)) return; + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return; + + nsCOMPtr<nsISHistory> sHistory; + nsresult rv = priv->wrapper->GetSHistory(getter_AddRefs(sHistory)); + if (NS_FAILED(rv) || !sHistory) return; + + nsCOMPtr<nsISHistoryInternal> sHistoryInternal; + sHistoryInternal = do_QueryInterface(sHistory); + + PRInt32 n; + sHistory->GetCount(&n); + sHistory->PurgeHistory(n); + + GList *children, *node; + children = kz_bookmark_get_children(history); + for (node = children; node; node = g_list_next (node)) + { + KzBookmark *child = KZ_BOOKMARK(node->data); + const gchar *title, *uri; + + title = kz_bookmark_get_title(child); + uri = kz_bookmark_get_link(child); + + nsCOMPtr<nsISHEntry> entry; + entry = do_CreateInstance(NS_SHENTRY_CONTRACTID); + + nsCOMPtr<nsIURI> aURI; + NewURI(getter_AddRefs(aURI), uri); + /* FIXME! set correct contentType */ + nsEmbedCString contentType; + entry->SetURI(aURI); + sHistoryInternal->AddEntry(entry, PR_TRUE); + } + g_list_free(children); + + /* set current */ + gint cur = kz_bookmark_get_current(history); + kz_gecko_embed_go_history_index(kzembed, cur); +} + +static void +kz_gecko_embed_get_history (KzEmbed *kzembed, KzBookmark *history) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + g_return_if_fail(KZ_IS_BOOKMARK(history)); + + if (!kz_bookmark_is_folder(history)) return; + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + if (!priv->wrapper) return; + + nsCOMPtr<nsISHistory> sHistory; + nsresult rv = priv->wrapper->GetSHistory(getter_AddRefs(sHistory)); + + if (NS_FAILED(rv) || !sHistory) return; + + GList *children, *tab; + children = kz_bookmark_get_children(history); + tab = children; + + PRInt32 count; + sHistory->GetCount(&count); + + PRInt32 index; + sHistory->GetIndex(&index); + for (PRInt32 i = 0; i < count; i++) + { + gchar *title = NULL, *uri = NULL; + KzBookmark *bookmark = NULL; + + kz_gecko_embed_shistory_get_nth (kzembed, + i, FALSE, + &uri, + &title); + if (tab) + { + bookmark = KZ_BOOKMARK(tab->data); + tab = g_list_next(tab); + } + + /* if there's no children of bookmarks, create a new bookmark */ + if (!bookmark) + { + bookmark = kz_bookmark_new_with_attrs(title, uri, NULL); + kz_bookmark_append(history, bookmark); + g_object_unref(bookmark); + } + else if (uri && !strcmp(uri, kz_bookmark_get_link(bookmark))) + { + g_free(uri); + continue; + } + else + { + kz_bookmark_set_link(bookmark, uri); + kz_bookmark_set_title(bookmark, title); + kz_bookmark_set_last_visited(bookmark, 0); + } + + if (title) + g_free(title); + if (uri) + g_free(uri); + } + + if (tab) + tab = g_list_last(tab); + GList *prev; + + while (tab) + { + KzBookmark *child = KZ_BOOKMARK(tab->data); + prev = g_list_previous(tab); + kz_bookmark_remove (history, child); + tab = prev; + } + + if (children) + g_list_free(children); + + kz_bookmark_set_current(history, (gint)index); +} + + +static guint +kz_gecko_embed_get_last_modified (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), 0); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return 0; + + nsresult result; + + nsCOMPtr<nsIDOMDocument> DOMDocument; + + result = priv->wrapper->GetDocument (getter_AddRefs(DOMDocument)); + if (NS_FAILED(result) || !DOMDocument) return 0; + + nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(DOMDocument); + if(!doc) return 0; + + nsEmbedString value; + + doc->GetLastModified(value); + + guint mod_time = 0; + nsEmbedCString cValue; + NS_UTF16ToCString(value, + NS_CSTRING_ENCODING_UTF8, cValue); + nsTime last_modified (cValue.get(), PR_TRUE); + LL_DIV (mod_time, + NS_STATIC_CAST(PRTime, last_modified), PR_USEC_PER_SEC); + return mod_time; +} + + +#if 0 +static void +kz_gecko_embed_set_edit_mode (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + + nsCOMPtr<nsIDOMWindow> domWindow; + priv->wrapper->GetDOMWindow(getter_AddRefs(domWindow)); + + nsCOMPtr<nsIEditingSession> edit; + edit = do_GetInterface(priv->wrapper->mWebBrowser); + if (edit) + { + edit->MakeWindowEditable(domWindow, "html", PR_FALSE); + } +} + +static void +kz_gecko_embed_set_view_mode (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbed *mozembed = KZ_GECKO_EMBED(kzembed); + + nsCOMPtr<nsIDOMWindow> domWindow; + priv->wrapper->GetDOMWindow(getter_AddRefs(domWindow)); + + nsCOMPtr<nsIEditingSession> edit; + edit = do_GetInterface(priv->wrapper->mWebBrowser); + if (edit) + { + edit->TearDownEditorOnWindow(domWindow); + } +} +#endif + +static void +kz_gecko_embed_fine_scroll (KzEmbed *kzembed, + int horiz, int vert) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->FineScroll (horiz, vert); +} + +static void +kz_gecko_embed_page_up (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->PageUp(); +} + +static void +kz_gecko_embed_page_down (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->PageDown(); +} + +static gboolean +kz_gecko_embed_get_allow_javascript (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return FALSE; + + PRBool allow; + priv->wrapper->GetAllowJavascript(&allow); + + return allow ? TRUE : FALSE; +} + +static void +kz_gecko_embed_set_allow_javascript (KzEmbed *kzembed, gboolean allow) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->SetAllowJavascript(allow); +} + +static gboolean +kz_gecko_embed_get_allow_images (KzEmbed *kzembed) +{ + g_return_val_if_fail(KZ_IS_GECKO_EMBED(kzembed), FALSE); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return FALSE; + + PRBool allow; + priv->wrapper->GetAllowImages(&allow); + + return allow ? TRUE : FALSE; +} + +static void +kz_gecko_embed_set_allow_images (KzEmbed *kzembed, gboolean allow) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->SetAllowImages(allow); +} + +static void +kz_gecko_embed_show_page_certificate (KzEmbed *kzembed) +{ + g_return_if_fail(KZ_IS_GECKO_EMBED(kzembed)); + + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE (kzembed); + + if (!priv->wrapper) return; + + priv->wrapper->ShowPageCertificate(); + +} + +static void +nav_link_elem_free(gpointer object, gpointer unused) +{ + if (object) + g_object_unref(G_OBJECT(object)); +} + +static void +kz_gecko_embed_navigation_link_free(KzGeckoEmbed *kzembed) +{ + gint i; + KzGeckoEmbedPrivate *priv = KZ_GECKO_EMBED_GET_PRIVATE(kzembed); + + for (i = 0; i < KZ_EMBED_LINK_GUARD; i++) + { + if (priv->nav_links[i]) + { + g_list_foreach(priv->nav_links[i], nav_link_elem_free, NULL); + g_list_free(priv->nav_links[i]); + priv->nav_links[i] = NULL; + } + } +#ifdef USE_MIGEMO + if (priv->migemo_keyword) + g_free(priv->migemo_keyword); + priv->migemo_keyword =NULL; +#endif + if (priv->last_highlight) + g_free(priv->last_highlight); + priv->last_highlight = NULL; +} +