diff options
author | Christian Persch <chpe@cvs.gnome.org> | 2003-10-18 06:40:17 +0800 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2003-10-18 06:40:17 +0800 |
commit | 0e078cd9825b89e128d0501d4a7b5885670c2347 (patch) | |
tree | 932814c057bd8d2c6cdee449dc6b267091cef6c5 | |
parent | 4d9d732ba340aae6430bd687f0cf3252bff2217d (diff) | |
download | gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar.gz gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar.bz2 gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar.lz gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar.xz gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.tar.zst gsoc2013-epiphany-0e078cd9825b89e128d0501d4a7b5885670c2347.zip |
Encoding menu improvements, Part 4: The Rewrite.
2003-10-18 Christian Persch <chpe@cvs.gnome.org>
Encoding menu improvements, Part 4:
The Rewrite.
* data/glade/epiphany.glade:
* data/ui/epiphany-ui.xml:
* data/ui/nautilus-epiphany-view.xml.in:
* embed/Makefile.am:
* embed/ephy-embed-shell.c: (ephy_embed_shell_init),
(ephy_embed_shell_finalize), (ephy_embed_shell_new),
(ephy_embed_shell_get_encodings):
* embed/ephy-embed-shell.h:
* embed/ephy-embed-utils.c: (ephy_embed_utils_save):
* embed/ephy-embed-utils.h:
* embed/ephy-embed.c: (ephy_embed_get_encoding_info):
* embed/ephy-embed.h:
* embed/ephy-encodings.c: (ephy_encodings_get_type),
(ephy_encodings_finalize), (ephy_encodings_class_init),
(ephy_encodings_get_node), (ephy_encodings_get_encodings),
(ephy_encodings_get_detectors), (ephy_encodings_get_all),
(ephy_encodings_get_categories), (ephy_encodings_add_recent),
(ephy_encodings_get_recent), (ephy_encodings_init),
(ephy_encoding_info_free), (ephy_encodings_new):
* embed/ephy-encodings.h:
* embed/mozilla/EphyWrapper.cpp:
* embed/mozilla/EphyWrapper.h:
* embed/mozilla/Makefile.am:
* embed/mozilla/mozilla-embed.cpp:
* embed/mozilla/mozilla-notifiers.cpp:
* lib/Makefile.am:
* lib/ephy-encodings.c:
* lib/ephy-encodings.h:
* lib/ephy-langs.c: (ephy_font_languages), (ephy_font_n_languages):
* lib/ephy-langs.h:
* src/Makefile.am:
* src/ephy-encoding-dialog.c: (ephy_encoding_dialog_get_type),
(setup_filter), (sync_embed_cb), (sync_active_tab),
(ephy_encoding_dialog_set_window), (activate_choice),
(activate_automatic), (ephy_encoding_dialog_response_cb),
(category_node_selected_cb), (view_node_selected_cb),
(view_node_activated_cb), (ephy_encoding_dialog_init),
(ephy_encoding_dialog_finalize),
(ephy_encoding_dialog_set_property),
(ephy_encoding_dialog_get_property),
(ephy_encoding_dialog_class_init), (ephy_encoding_dialog_new):
* src/ephy-encoding-dialog.h:
* src/ephy-encoding-menu.c: (ephy_encoding_menu_init),
(sort_encodings), (add_menu_item), (update_encoding_menu_cb),
(encoding_activate_cb), (add_action),
(ephy_encoding_menu_view_dialog_cb),
(ephy_encoding_menu_automatic_cb), (ephy_encoding_menu_set_window),
(ephy_encoding_menu_finalize), (ephy_encoding_menu_class_init),
(ephy_encoding_menu_new):
* src/ephy-nautilus-view.c: (gnv_bonobo_control_activate_cb),
(gnv_cmd_select_encoding), (gnv_cmd_edit_find):
* src/ephy-window.c: (ephy_window_set_active_tab),
(setup_notebook), (ephy_window_set_property),
(ephy_window_get_property), (ephy_window_class_init):
* src/language-editor.h:
* src/pdm-dialog.c: (setup_passwords_treeview),
(setup_cookies_treeview):
* src/prefs-dialog.c: (prefs_dialog_finalize),
(get_current_language_code), (fonts_language_info_cmp),
(create_fonts_language_menu), (find_encoding_in_list_cmp),
(sort_encodings), (create_optionmenu), (prefs_dialog_init):
Made encodings menu dynamic, containing recently used items + items
related to the currently active encoding. Split encodings out as a
embed shell service, port all users over to that. Harvest all encoding
info we can get from mozilla.
32 files changed, 2131 insertions, 875 deletions
@@ -1,3 +1,75 @@ +2003-10-18 Christian Persch <chpe@cvs.gnome.org> + + Encoding menu improvements, Part 4: + The Rewrite. + + * data/glade/epiphany.glade: + * data/ui/epiphany-ui.xml: + * data/ui/nautilus-epiphany-view.xml.in: + * embed/Makefile.am: + * embed/ephy-embed-shell.c: (ephy_embed_shell_init), + (ephy_embed_shell_finalize), (ephy_embed_shell_new), + (ephy_embed_shell_get_encodings): + * embed/ephy-embed-shell.h: + * embed/ephy-embed-utils.c: (ephy_embed_utils_save): + * embed/ephy-embed-utils.h: + * embed/ephy-embed.c: (ephy_embed_get_encoding_info): + * embed/ephy-embed.h: + * embed/ephy-encodings.c: (ephy_encodings_get_type), + (ephy_encodings_finalize), (ephy_encodings_class_init), + (ephy_encodings_get_node), (ephy_encodings_get_encodings), + (ephy_encodings_get_detectors), (ephy_encodings_get_all), + (ephy_encodings_get_categories), (ephy_encodings_add_recent), + (ephy_encodings_get_recent), (ephy_encodings_init), + (ephy_encoding_info_free), (ephy_encodings_new): + * embed/ephy-encodings.h: + * embed/mozilla/EphyWrapper.cpp: + * embed/mozilla/EphyWrapper.h: + * embed/mozilla/Makefile.am: + * embed/mozilla/mozilla-embed.cpp: + * embed/mozilla/mozilla-notifiers.cpp: + * lib/Makefile.am: + * lib/ephy-encodings.c: + * lib/ephy-encodings.h: + * lib/ephy-langs.c: (ephy_font_languages), (ephy_font_n_languages): + * lib/ephy-langs.h: + * src/Makefile.am: + * src/ephy-encoding-dialog.c: (ephy_encoding_dialog_get_type), + (setup_filter), (sync_embed_cb), (sync_active_tab), + (ephy_encoding_dialog_set_window), (activate_choice), + (activate_automatic), (ephy_encoding_dialog_response_cb), + (category_node_selected_cb), (view_node_selected_cb), + (view_node_activated_cb), (ephy_encoding_dialog_init), + (ephy_encoding_dialog_finalize), + (ephy_encoding_dialog_set_property), + (ephy_encoding_dialog_get_property), + (ephy_encoding_dialog_class_init), (ephy_encoding_dialog_new): + * src/ephy-encoding-dialog.h: + * src/ephy-encoding-menu.c: (ephy_encoding_menu_init), + (sort_encodings), (add_menu_item), (update_encoding_menu_cb), + (encoding_activate_cb), (add_action), + (ephy_encoding_menu_view_dialog_cb), + (ephy_encoding_menu_automatic_cb), (ephy_encoding_menu_set_window), + (ephy_encoding_menu_finalize), (ephy_encoding_menu_class_init), + (ephy_encoding_menu_new): + * src/ephy-nautilus-view.c: (gnv_bonobo_control_activate_cb), + (gnv_cmd_select_encoding), (gnv_cmd_edit_find): + * src/ephy-window.c: (ephy_window_set_active_tab), + (setup_notebook), (ephy_window_set_property), + (ephy_window_get_property), (ephy_window_class_init): + * src/language-editor.h: + * src/pdm-dialog.c: (setup_passwords_treeview), + (setup_cookies_treeview): + * src/prefs-dialog.c: (prefs_dialog_finalize), + (get_current_language_code), (fonts_language_info_cmp), + (create_fonts_language_menu), (find_encoding_in_list_cmp), + (sort_encodings), (create_optionmenu), (prefs_dialog_init): + + Made encodings menu dynamic, containing recently used items + items + related to the currently active encoding. Split encodings out as a + embed shell service, port all users over to that. Harvest all encoding + info we can get from mozilla. + 2003-10-17 Marco Pesenti Gritti <marco@gnome.org> * src/bookmarks/ephy-bookmarks-editor.c: diff --git a/data/glade/epiphany.glade b/data/glade/epiphany.glade index 23e014551..a443fc3a2 100644 --- a/data/glade/epiphany.glade +++ b/data/glade/epiphany.glade @@ -912,4 +912,141 @@ It's not possible to view this file type directly in the browser:</property> </child> </widget> +<widget class="GtkDialog" id="encoding_dialog"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Text Encoding</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">400</property> + <property name="default_height">380</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">False</property> + <signal name="response" handler="ephy_encoding_dialog_response_cb" last_modification_time="Thu, 16 Oct 2003 17:19:06 GMT"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox30"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area30"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-5</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="automatic_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Automatic</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-11</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox147"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHPaned" id="hpaned1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">128</property> + + <child> + <widget class="GtkScrolledWindow" id="categories_scroller"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="list_scroller"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + </glade-interface> diff --git a/data/ui/epiphany-ui.xml b/data/ui/epiphany-ui.xml index d4fbb636a..f331c7e71 100644 --- a/data/ui/epiphany-ui.xml +++ b/data/ui/epiphany-ui.xml @@ -39,7 +39,9 @@ <menuitem name="ViewZoomOutMenu" action="ViewZoomOut"/> <menuitem name="ViewZoomNormalMenu" action="ViewZoomNormal"/> <separator name="ViewSep2"/> - <placeholder name="ViewEncodingsPlaceholder"/> + <menu name="ViewEncodingMenu" action="ViewEncoding"> + <placeholder name="ViewEncodingPlaceholder"/> + </menu> <menuitem name="ViewPageSourceMenu" action="ViewPageSource"/> <separator name="ViewSep3"/> <menuitem name="ViewStopMenu" action="ViewStop"/> diff --git a/data/ui/nautilus-epiphany-view.xml.in b/data/ui/nautilus-epiphany-view.xml.in index 09c0e57ba..4858abd3f 100644 --- a/data/ui/nautilus-epiphany-view.xml.in +++ b/data/ui/nautilus-epiphany-view.xml.in @@ -78,7 +78,7 @@ <menuitem name="EditFind" verb="" _label="_Find..."/> </submenu> <submenu name="View"> - <placeholder name="Encoding"/> + <menuitem name="ViewEncoding" verb="" _label="Text _Encoding..."/> </submenu> </menu> diff --git a/embed/Makefile.am b/embed/Makefile.am index e2d94f622..35d86aea8 100644 --- a/embed/Makefile.am +++ b/embed/Makefile.am @@ -36,6 +36,7 @@ INST_H_FILES = \ ephy-embed-single.h \ ephy-embed-shell.h \ ephy-embed-types.h \ + ephy-encodings.h \ ephy-history.h libephyembed_la_SOURCES = \ @@ -49,6 +50,7 @@ libephyembed_la_SOURCES = \ ephy-embed-single.c \ ephy-embed-shell.c \ ephy-embed-utils.c \ + ephy-encodings.c \ ephy-favicon-cache.c \ ephy-history.c \ find-dialog.c \ diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c index bcf9c0d00..0a0dbeb04 100644 --- a/embed/ephy-embed-shell.c +++ b/embed/ephy-embed-shell.c @@ -25,6 +25,7 @@ #include "ephy-favicon-cache.h" #include "mozilla-embed-single.h" #include "downloader-view.h" +#include "ephy-encodings.h" #include "ephy-debug.h" #include <string.h> @@ -37,6 +38,7 @@ struct EphyEmbedShellPrivate DownloaderView *downloader_view; EphyFaviconCache *favicon_cache; EphyEmbedSingle *embed_single; + EphyEncodings *encodings; }; static void @@ -109,6 +111,7 @@ ephy_embed_shell_init (EphyEmbedShell *ges) ges->priv->global_history = NULL; ges->priv->downloader_view = NULL; ges->priv->favicon_cache = NULL; + ges->priv->encodings = NULL; } static void @@ -137,6 +140,12 @@ ephy_embed_shell_finalize (GObject *object) g_object_unref (G_OBJECT (ges->priv->favicon_cache)); } + LOG ("Unref encodings") + if (ges->priv->encodings) + { + g_object_unref (G_OBJECT (ges->priv->encodings)); + } + LOG ("Unref embed single") if (ges->priv->embed_single) { @@ -149,14 +158,7 @@ ephy_embed_shell_finalize (GObject *object) EphyEmbedShell * ephy_embed_shell_new (const char *type) { - if (strcmp (type, "mozilla") == 0) - { - return EPHY_EMBED_SHELL (g_object_new - (EPHY_TYPE_EMBED_SHELL, NULL)); - } - - g_assert_not_reached (); - return NULL; + return g_object_new (EPHY_TYPE_EMBED_SHELL, NULL); } /** @@ -243,3 +245,13 @@ impl_get_downloader_view (EphyEmbedShell *shell) return G_OBJECT (shell->priv->downloader_view); } +GObject * +ephy_embed_shell_get_encodings (EphyEmbedShell *shell) +{ + if (shell->priv->encodings == NULL) + { + shell->priv->encodings = ephy_encodings_new (); + } + + return G_OBJECT (shell->priv->encodings); +} diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h index ec0b26215..610123eb0 100644 --- a/embed/ephy-embed-shell.h +++ b/embed/ephy-embed-shell.h @@ -69,6 +69,8 @@ EphyHistory *ephy_embed_shell_get_global_history (EphyEmbedShell *shell); GObject *ephy_embed_shell_get_downloader_view (EphyEmbedShell *shell); +GObject *ephy_embed_shell_get_encodings (EphyEmbedShell *shell); + EphyEmbedSingle *ephy_embed_shell_get_embed_single (EphyEmbedShell *shell); G_END_DECLS diff --git a/embed/ephy-embed-utils.c b/embed/ephy-embed-utils.c index c6e113042..0bcd6bb52 100644 --- a/embed/ephy-embed-utils.c +++ b/embed/ephy-embed-utils.c @@ -29,7 +29,6 @@ #include "ephy-gui.h" #include "ephy-debug.h" #include "ephy-langs.h" -#include "ephy-encodings.h" #include <gtk/gtkdialog.h> #include <gtk/gtkmessagedialog.h> @@ -189,86 +188,6 @@ ephy_embed_utils_save (GtkWidget *window, } /** - * ephy_embed_utils_build_encodings_submenu: - * @ui_component: the parent #BonoboUIComponent - * @path: the bonoboui path where to create the submenu. - * It's recommended to use a <placeholder/> - * @fn: callback to report the selected encodings - * @data: the data passed to the callback - * - * Create a encoding submenu using bonobo ui. - **/ -void -ephy_embed_utils_build_encodings_submenu (BonoboUIComponent *ui_component, - const char *path, - BonoboUIVerbFn fn, - gpointer view) -{ - gchar *tmp, *verb; - GString *xml_string; - GList *groups, *gl, *encodings, *l; - GList *verbs = NULL; - - START_PROFILER ("Encodings menu") - - xml_string = g_string_new (NULL); - g_string_append (xml_string, "<submenu name=\"Encoding\" _label=\"_Encoding\">"); - - groups = ephy_lang_get_group_list (); - for (gl = groups; gl != NULL; gl = gl->next) - { - const EphyLanguageGroupInfo *lang_info = (EphyLanguageGroupInfo *) gl->data; - - tmp = g_strdup_printf ("<submenu label=\"%s\" name=\"EncodingGroup%d\">\n", - lang_info->title, lang_info->group); - xml_string = g_string_append (xml_string, tmp); - g_free (tmp); - - encodings = ephy_encodings_get_list (lang_info->group, FALSE); - for (l = encodings; l != NULL; l = l->next) - { - const EphyEncodingInfo *info = (EphyEncodingInfo *) l->data; - - verb = g_strdup_printf ("Encoding%s", info->encoding); - tmp = g_strdup_printf ("<menuitem label=\"%s\" name=\"%s\" verb=\"%s\"/>\n", - info->title, verb, verb); - xml_string = g_string_append (xml_string, tmp); - - verbs = g_list_prepend (verbs, verb); - - g_free (tmp); - } - - g_list_foreach (encodings, (GFunc) ephy_encoding_info_free, NULL); - g_list_free (encodings); - - g_string_append (xml_string, "</submenu>"); - } - - g_list_foreach (groups, (GFunc) ephy_lang_group_info_free, NULL); - g_list_free (groups); - - g_string_append (xml_string, "</submenu>"); - - bonobo_ui_component_set_translate (ui_component, path, - xml_string->str, NULL); - - for (l = verbs; l != NULL; l = l->next) - { - bonobo_ui_component_add_verb (ui_component, - (const char *) l->data, - fn, view); - } - - g_list_foreach (verbs, (GFunc) g_free, NULL); - g_list_free (verbs); - - g_string_free (xml_string, TRUE); - - STOP_PROFILER ("Encodings menu") -} - -/** * ephy_embed_utils_handlernotfound_dialog_run: * @parent: the dialog parent window * diff --git a/embed/ephy-embed-utils.h b/embed/ephy-embed-utils.h index 8a0a52591..312e51026 100644 --- a/embed/ephy-embed-utils.h +++ b/embed/ephy-embed-utils.h @@ -32,11 +32,6 @@ void ephy_embed_utils_save (GtkWidget *window, gboolean ask_dest, EphyEmbedPersist *persist); -void ephy_embed_utils_build_encodings_submenu (BonoboUIComponent *ui_component, - const char *path, - BonoboUIVerbFn fn, - gpointer view); - void ephy_embed_utils_nohandler_dialog_run (GtkWidget *parent); G_END_DECLS diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c index 145498665..4bc9de42e 100644 --- a/embed/ephy-embed.c +++ b/embed/ephy-embed.c @@ -575,11 +575,11 @@ ephy_embed_set_encoding (EphyEmbed *embed, } gresult -ephy_embed_get_encoding (EphyEmbed *embed, - char **encoding) +ephy_embed_get_encoding_info (EphyEmbed *embed, + EphyEncodingInfo **info) { EphyEmbedClass *klass = EPHY_EMBED_GET_CLASS (embed); - return klass->get_encoding (embed, encoding); + return klass->get_encoding_info (embed, info); } gresult diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h index 5bcac1ae1..811fa91e6 100644 --- a/embed/ephy-embed.h +++ b/embed/ephy-embed.h @@ -21,6 +21,7 @@ #include "ephy-embed-types.h" #include "ephy-embed-event.h" +#include "ephy-encodings.h" #include <glib-object.h> #include <glib.h> @@ -270,8 +271,8 @@ struct EphyEmbedClass gint pageNum); gresult (* set_encoding) (EphyEmbed *embed, const char *encoding); - gresult (* get_encoding) (EphyEmbed *embed, - char **encoding); + gresult (* get_encoding_info) (EphyEmbed *embed, + EphyEncodingInfo **info); }; GType ephy_embed_get_type (void); @@ -392,8 +393,8 @@ gresult ephy_embed_find_next (EphyEmbed *embed, gresult ephy_embed_set_encoding (EphyEmbed *embed, const char *encoding); -gresult ephy_embed_get_encoding (EphyEmbed *embed, - char **encoding); +gresult ephy_embed_get_encoding_info (EphyEmbed *embed, + EphyEncodingInfo **info); gresult ephy_embed_activate (EphyEmbed *embed); diff --git a/embed/ephy-encodings.c b/embed/ephy-encodings.c new file mode 100644 index 000000000..1105207df --- /dev/null +++ b/embed/ephy-encodings.c @@ -0,0 +1,545 @@ +/* + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persch + * + * 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. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ephy-encodings.h" +#include "ephy-string.h" +#include "ephy-node-db.h" +#include "ephy-file-helpers.h" +#include "eel-gconf-extensions.h" +#include "ephy-debug.h" + +#include <bonobo/bonobo-i18n.h> +#include <string.h> + +#define EPHY_ENCODINGS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ENCODINGS, EphyEncodingsPrivate)) + +struct EphyEncodingsPrivate +{ + EphyNodeDb *db; + EphyNode *root; + EphyNode *encodings; + EphyNode *detectors; + EphyNode *categories; + GHashTable *hash; + GSList *recent; +}; + +/** + * translatable encodings titles + * NOTE: if you add/remove/change encodings, please also update the schema in + * epiphany.schemas.in + */ +static const +struct +{ + char *title; + char *code; + EphyLanguageGroup groups; + gboolean is_autodetector; +} +encoding_entries [] = +{ + { N_("Arabic (_IBM-864)"), "IBM864", LG_ARABIC, FALSE }, + { N_("Arabic (ISO-_8859-6)"), "ISO-8859-6", LG_ARABIC, FALSE }, + { N_("Arabic (_MacArabic)"), "x-mac-arabic", LG_ARABIC, FALSE }, + { N_("Arabic (_Windows-1256)"), "windows-1256", LG_ARABIC, FALSE }, + { N_("Baltic (_ISO-8859-13)"), "ISO-8859-13", LG_BALTIC, FALSE }, + { N_("Baltic (I_SO-8859-4)"), "ISO-8859-4", LG_BALTIC, FALSE }, + { N_("Baltic (_Windows-1257)"), "windows-1257", LG_BALTIC, FALSE }, + { N_("_Armenian (ARMSCII-8)"), "armscii-8", LG_CAUCASIAN, FALSE }, + { N_("_Georgian (GEOSTD8)"), "geostd8", LG_CAUCASIAN, FALSE }, + { N_("Central European (_IBM-852)"), "IBM852", LG_C_EUROPEAN, FALSE }, + { N_("Central European (I_SO-8859-2)"), "ISO-8859-2", LG_C_EUROPEAN, FALSE }, + { N_("Central European (_MacCE)"), "x-mac-ce", LG_C_EUROPEAN, FALSE }, + { N_("Central European (_Windows-1250)"), "windows-1250", LG_C_EUROPEAN, FALSE }, + { N_("Chinese Simplified (_GB18030)"), "gb18030", LG_CHINESE_SIMP, FALSE }, + { N_("Chinese Simplified (G_B2312)"), "GB2312", LG_CHINESE_SIMP, FALSE }, + { N_("Chinese Simplified (GB_K)"), "x-gbk", LG_CHINESE_SIMP, FALSE }, + { N_("Chinese Simplified (_HZ)"), "HZ-GB-2312", LG_CHINESE_SIMP, FALSE }, + { N_("Chinese Simplified (_ISO-2022-CN)"), "ISO-2022-CN", LG_CHINESE_SIMP, FALSE }, + { N_("Chinese Traditional (Big_5)"), "Big5", LG_CHINESE_TRAD, FALSE }, + { N_("Chinese Traditional (Big5-HK_SCS)"), "Big5-HKSCS", LG_CHINESE_TRAD, FALSE }, + { N_("Chinese Traditional (_EUC-TW)"), "x-euc-tw", LG_CHINESE_TRAD, FALSE }, + { N_("Cyrillic (_IBM-855)"), "IBM855", LG_CYRILLIC, FALSE }, + { N_("Cyrillic (I_SO-8859-5)"), "ISO-8859-5", LG_CYRILLIC, FALSE }, + { N_("Cyrillic (IS_O-IR-111)"), "ISO-IR-111", LG_CYRILLIC, FALSE }, + { N_("Cyrillic (_KOI8-R)"), "KOI8-R", LG_CYRILLIC, FALSE }, + { N_("Cyrillic (_MacCyrillic)"), "x-mac-cyrillic", LG_CYRILLIC, FALSE }, + { N_("Cyrillic (_Windows-1251)"), "windows-1251", LG_CYRILLIC, FALSE }, + { N_("Cyrillic/_Russian (IBM-866)"), "IBM866", LG_CYRILLIC, FALSE }, + { N_("Greek (_ISO-8859-7)"), "ISO-8859-7", LG_GREEK, FALSE }, + { N_("Greek (_MacGreek)"), "x-mac-greek", LG_GREEK, FALSE }, + { N_("Greek (_Windows-1253)"), "windows-1253", LG_GREEK, FALSE }, + { N_("Gujarati (_MacGujarati)"), "x-mac-gujarati", LG_INDIAN, FALSE }, + { N_("Gurmukhi (Mac_Gurmukhi)"), "x-mac-gurmukhi", LG_INDIAN, FALSE }, + { N_("Hindi (Mac_Devanagari)"), "x-mac-devanagari", LG_INDIAN, FALSE }, + { N_("Hebrew (_IBM-862)"), "IBM862", LG_HEBREW, FALSE }, + { N_("Hebrew (IS_O-8859-8-I)"), "ISO-8859-8-I", LG_HEBREW, FALSE }, + { N_("Hebrew (_MacHebrew)"), "x-mac-hebrew", LG_HEBREW, FALSE }, + { N_("Hebrew (_Windows-1255)"), "windows-1255", LG_HEBREW, FALSE }, + { N_("_Visual Hebrew (ISO-8859-8)"), "ISO-8859-8", LG_HEBREW, FALSE }, + { N_("Japanese (_EUC-JP)"), "EUC-JP", LG_JAPANESE, FALSE }, + { N_("Japanese (_ISO-2022-JP)"), "ISO-2022-JP", LG_JAPANESE, FALSE }, + { N_("Japanese (_Shift-JIS)"), "Shift_JIS", LG_JAPANESE, FALSE }, + { N_("Korean (_EUC-KR)"), "EUC-KR", LG_KOREAN, FALSE }, + { N_("Korean (_ISO-2022-KR)"), "ISO-2022-KR", LG_KOREAN, FALSE }, + { N_("Korean (_JOHAB)"), "x-johab", LG_KOREAN, FALSE }, + { N_("Korean (_UHC)"), "x-windows-949", LG_KOREAN, FALSE }, + { N_("_Celtic (ISO-8859-14)"), "ISO-8859-14", LG_NORDIC, FALSE }, + { N_("_Icelandic (MacIcelandic)"), "x-mac-icelandic", LG_NORDIC, FALSE }, + { N_("_Nordic (ISO-8859-10)"), "ISO-8859-10", LG_NORDIC, FALSE }, + { N_("_Persian (MacFarsi)"), "x-mac-farsi", LG_PERSIAN, FALSE }, + { N_("Croatian (Mac_Croatian)"), "x-mac-croatian", LG_SE_EUROPEAN, FALSE }, + { N_("_Romanian (MacRomanian)"), "x-mac-romanian", LG_SE_EUROPEAN, FALSE }, + { N_("R_omanian (ISO-8859-16)"), "ISO-8859-16", LG_SE_EUROPEAN, FALSE }, + { N_("South _European (ISO-8859-3)"), "ISO-8859-3", LG_SE_EUROPEAN, FALSE }, + { N_("Thai (TIS-_620)"), "TIS-620", LG_THAI, FALSE }, +#if MOZILLA_SNAPSHOT >= 10 + { N_("Thai (IS_O-8859-11)"), "iso-8859-11", LG_THAI, FALSE }, + { N_("_Thai (Windows-874)"), "windows-874", LG_THAI, FALSE }, +#endif + { N_("Turkish (_IBM-857)"), "IBM857", LG_TURKISH, FALSE }, + { N_("Turkish (I_SO-8859-9)"), "ISO-8859-9", LG_TURKISH, FALSE }, + { N_("Turkish (_MacTurkish)"), "x-mac-turkish", LG_TURKISH, FALSE }, + { N_("Turkish (_Windows-1254)"), "windows-1254", LG_TURKISH, FALSE }, + { N_("Unicode (UTF-_8)"), "UTF-8", LG_UNICODE, FALSE }, + { N_("Unicode (UTF-_7)"), "UTF-7", LG_UNICODE, FALSE }, + { N_("Cyrillic/Ukrainian (_KOI8-U)"), "KOI8-U", LG_UKRAINIAN, FALSE }, + { N_("Cyrillic/Ukrainian (Mac_Ukrainian)"), "x-mac-ukrainian", LG_UKRAINIAN, FALSE }, + { N_("Vietnamese (_TCVN)"), "x-viet-tcvn5712", LG_VIETNAMESE, FALSE }, + { N_("Vietnamese (_VISCII)"), "VISCII", LG_VIETNAMESE, FALSE }, + { N_("Vietnamese (V_PS)"), "x-viet-vps", LG_VIETNAMESE, FALSE }, + { N_("Vietnamese (_Windows-1258)"), "windows-1258", LG_VIETNAMESE, FALSE }, + { N_("Western (_IBM-850)"), "IBM850", LG_WESTERN, FALSE }, + { N_("Western (_ISO-8859-1)"), "ISO-8859-1", LG_WESTERN, FALSE }, + { N_("Western (IS_O-8859-15)"), "ISO-8859-15", LG_WESTERN, FALSE }, + { N_("Western (_MacRoman)"), "x-mac-roman", LG_WESTERN, FALSE }, + { N_("Western (_Windows-1252)"), "windows-1252", LG_WESTERN, FALSE }, + + { N_("Off"), "", LG_NONE, TRUE }, + { N_("Chinese"), "zh_parallel_state_machine", LG_CHINESE_TRAD | LG_CHINESE_SIMP, TRUE }, + { N_("Chinese Simplified"), "zhcn_parallel_state_machine", LG_CHINESE_SIMP, TRUE }, + { N_("Chinese Traditional"), "zhtw_parallel_state_machine", LG_CHINESE_TRAD, TRUE }, + { N_("East Asian"), "cjk_parallel_state_machine", LG_CHINESE_TRAD | LG_CHINESE_SIMP | LG_JAPANESE | LG_KOREAN, TRUE }, + { N_("Japanese"), "ja_parallel_state_machine", LG_JAPANESE, TRUE }, + { N_("Korean"), "ko_parallel_state_machine", LG_KOREAN, TRUE }, + { N_("Russian"), "ruprob", LG_CYRILLIC | LG_UKRAINIAN, TRUE }, + { N_("Universal"), "universal_charset_detector", LG_ALL, TRUE }, + { N_("Ukrainian"), "ukprob", LG_UKRAINIAN, TRUE } +}; +static const guint n_encoding_entries = G_N_ELEMENTS (encoding_entries); + +/* make sure this covers all LG_* groups ! */ +/* FIXME: those categories are pretty bad :( */ +static const struct +{ + char *title; + EphyLanguageGroup groups; +} +geo_entries [] = +{ + { N_("Universal"), LG_UNICODE }, + { N_("Eastern Asia"), LG_CHINESE_SIMP | LG_CHINESE_TRAD | LG_JAPANESE | LG_KOREAN | LG_VIETNAMESE | LG_THAI }, + { N_("Western Asia"), LG_CAUCASIAN | LG_TURKISH | LG_INDIAN }, + { N_("Eastern European"), LG_BALTIC | LG_CYRILLIC | LG_UKRAINIAN | LG_C_EUROPEAN }, + { N_("Western European"), LG_WESTERN | LG_GREEK | LG_NORDIC | LG_SE_EUROPEAN }, + { N_("Middle Eastern"), LG_ARABIC | LG_PERSIAN | LG_HEBREW } +}; +static const guint n_geo_entries = G_N_ELEMENTS (geo_entries); + +enum +{ + ALL_NODE_ID = 2, + ENCODINGS_NODE_ID = 3, + DETECTORS_NODE_ID = 5, + CATEGORIES_NODE_ID = 7 +}; + +#define RECENT_KEY "/apps/epiphany/general/recent_encodings" +#define RECENT_MAX 4 + +static void ephy_encodings_class_init (EphyEncodingsClass *klass); +static void ephy_encodings_init (EphyEncodings *ma); + +static GObjectClass *parent_class = NULL; + +GType +ephy_encodings_get_type (void) +{ + static GType ephy_encodings_type = 0; + + if (ephy_encodings_type == 0) + { + static const GTypeInfo our_info = + { + sizeof (EphyEncodingsClass), + NULL, + NULL, + (GClassInitFunc) ephy_encodings_class_init, + NULL, + NULL, + sizeof (EphyEncodings), + 0, + (GInstanceInitFunc) ephy_encodings_init + }; + + ephy_encodings_type = g_type_register_static (G_TYPE_OBJECT, + "EphyEncodings", + &our_info, 0); + } + + return ephy_encodings_type; +} + +static void +ephy_encodings_finalize (GObject *object) +{ + EphyEncodings *encodings = EPHY_ENCODINGS (object); + + g_hash_table_destroy (encodings->priv->hash); + + ephy_node_unref (encodings->priv->encodings); + ephy_node_unref (encodings->priv->detectors); + ephy_node_unref (encodings->priv->categories); + ephy_node_unref (encodings->priv->root); + + g_slist_foreach (encodings->priv->recent, (GFunc) g_free, NULL); + g_slist_free (encodings->priv->recent); + + g_object_unref (encodings->priv->db); + + LOG ("EphyEncodings finalised") + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +ephy_encodings_class_init (EphyEncodingsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = ephy_encodings_finalize; + + g_type_class_add_private (object_class, sizeof (EphyEncodingsPrivate)); +} + +EphyNode * +ephy_encodings_get_node (EphyEncodings *encodings, + const char *code) +{ + g_return_val_if_fail (EPHY_IS_ENCODINGS (encodings), NULL); + + return g_hash_table_lookup (encodings->priv->hash, code); +} + +GList * +ephy_encodings_get_encodings (EphyEncodings *encodings, + EphyLanguageGroup group_mask) +{ + GList *list = NULL; + GPtrArray *children; + int i, n_items; + + children = ephy_node_get_children (encodings->priv->encodings); + n_items = children->len; + for (i = 0; i < n_items; i++) + { + EphyNode *kid; + EphyLanguageGroup group; + + kid = g_ptr_array_index (children, i); + group = ephy_node_get_property_int + (kid, EPHY_NODE_ENCODING_PROP_LANGUAGE_GROUPS); + + if ((group & group_mask) != 0) + { + list = g_list_prepend (list, kid); + } + } + ephy_node_thaw (encodings->priv->encodings); + + return list; +} + +GList * +ephy_encodings_get_detectors (EphyEncodings *encodings) +{ + GList *list = NULL; + GPtrArray *children; + int i, n_items; + + children = ephy_node_get_children (encodings->priv->detectors); + n_items = children->len; + for (i = 0; i < n_items; i++) + { + EphyNode *kid; + + kid = g_ptr_array_index (children, i); + + list = g_list_prepend (list, kid); + } + ephy_node_thaw (encodings->priv->detectors); + + return list; +} + +EphyNode * +ephy_encodings_get_all (EphyEncodings *encodings) +{ + g_return_val_if_fail (EPHY_IS_ENCODINGS (encodings), NULL); + + return encodings->priv->encodings; +} + +EphyNode * +ephy_encodings_get_categories (EphyEncodings *encodings) +{ + g_return_val_if_fail (EPHY_IS_ENCODINGS (encodings), NULL); + + return encodings->priv->categories; +} + +void +ephy_encodings_add_recent (EphyEncodings *encodings, + const char *code) +{ + GSList *element; + + g_return_if_fail (EPHY_IS_ENCODINGS (encodings)); + g_return_if_fail (code != NULL); + g_return_if_fail (ephy_encodings_get_node (encodings, code) != NULL); + + /* keep the list elements unique */ + element = g_slist_find_custom (encodings->priv->recent, code, + (GCompareFunc) strcmp); + if (element != NULL) + { + encodings->priv->recent = + g_slist_remove_link (encodings->priv->recent, element); + } + + /* add the new code upfront */ + encodings->priv->recent = + g_slist_prepend (encodings->priv->recent, g_strdup (code)); + + /* truncate the list if necessary; it's at most 1 element too much */ + if (g_slist_length (encodings->priv->recent) > RECENT_MAX) + { + GSList *tail; + + tail = g_slist_last (encodings->priv->recent); + g_free (tail->data); + encodings->priv->recent = + g_slist_remove_link (encodings->priv->recent, tail); + } + + /* persist the list */ + eel_gconf_set_string_list (RECENT_KEY, encodings->priv->recent); +} + +GList * +ephy_encodings_get_recent (EphyEncodings *encodings) +{ + GSList *l; + GList *list = NULL; + + for (l = encodings->priv->recent; l != NULL; l = l->next) + { + EphyNode *node; + + node = ephy_encodings_get_node (encodings, (char *) l->data); + g_return_val_if_fail (EPHY_IS_NODE (node), NULL); + + list = g_list_prepend (list, node); + } + + return list; +} + +static void +ephy_encodings_init (EphyEncodings *encodings) +{ + EphyNodeDb *db; + GSList *list, *l; + guint i; + + encodings->priv = EPHY_ENCODINGS_GET_PRIVATE (encodings); + + LOG ("EphyEncodings initialising") + + db = ephy_node_db_new ("EncodingsDB"); + encodings->priv->db = db; + + encodings->priv->hash = g_hash_table_new (g_str_hash, g_str_equal); + + encodings->priv->root = ephy_node_new_with_id (db, ALL_NODE_ID); + encodings->priv->encodings = ephy_node_new_with_id (db, ENCODINGS_NODE_ID); + encodings->priv->detectors = ephy_node_new_with_id (db, DETECTORS_NODE_ID); + encodings->priv->categories = ephy_node_new_with_id (db, CATEGORIES_NODE_ID); + + ephy_node_ref (encodings->priv->root); + ephy_node_ref (encodings->priv->encodings); + ephy_node_ref (encodings->priv->detectors); + ephy_node_ref (encodings->priv->categories); + + /* now fill the db */ + for (i = 0; i < n_encoding_entries; i++) + { + EphyNode *node; + char *elided, *normalised; + GValue value = { 0, }; + + node = ephy_node_new (db); + ephy_node_add_child (encodings->priv->root, node); + g_hash_table_insert (encodings->priv->hash, encoding_entries[i].code, node); + + if (encoding_entries[i].is_autodetector) + { + ephy_node_add_child (encodings->priv->detectors, node); + } + else + { + ephy_node_add_child (encodings->priv->encodings, node); + } + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, _(encoding_entries[i].title)); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_TITLE, &value); + g_value_unset (&value); + + elided = ephy_string_elide_underscores (_(encoding_entries[i].title)); + normalised = g_utf8_normalize (elided, -1, G_NORMALIZE_DEFAULT); + + g_value_init (&value, G_TYPE_STRING); + g_value_take_string (&value, g_utf8_collate_key (normalised, -1)); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_COLLATION_KEY, &value); + g_value_unset (&value); + + g_free (normalised); + + g_value_init (&value, G_TYPE_STRING); + g_value_take_string (&value, elided); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_TITLE_ELIDED, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, encoding_entries[i].code); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_ENCODING, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, encoding_entries[i].groups); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_LANGUAGE_GROUPS, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, encoding_entries[i].is_autodetector); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_IS_AUTODETECTOR, &value); + g_value_unset (&value); + } + + /* setup list of categories for 2-pane view in ephy-encoding-dialog */ + for (i=0; i < n_geo_entries; i++) + { + EphyNode *node; + GValue value = { 0, }; + GList *list, *l; + + node = ephy_node_new (db); + ephy_node_add_child (encodings->priv->categories, node); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, _(geo_entries[i].title)); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_TITLE, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_STRING); + g_value_take_string (&value, g_utf8_collate_key (_(geo_entries[i].title), -1)); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_COLLATION_KEY, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, encoding_entries[i].groups); + ephy_node_set_property (node, EPHY_NODE_ENCODING_PROP_LANGUAGE_GROUPS, &value); + g_value_unset (&value); + + /* add the encodings to the category */ + list = ephy_encodings_get_encodings (encodings, geo_entries[i].groups); + for (l = list; l != NULL; l = l->next) + { + ephy_node_add_child (node, (EphyNode *) l->data); + } + g_list_free (list); + + } + + /* get the list of recently used encodings */ + list = eel_gconf_get_string_list (RECENT_KEY); + + /* make sure the list has no duplicates (GtkUIManager goes + * crazy otherwise), and only valid entries + */ + encodings->priv->recent = NULL; + for (l = list; l != NULL; l = l->next) + { + if (g_slist_find (encodings->priv->recent, l->data) == NULL + && g_slist_length (encodings->priv->recent) < RECENT_MAX + && ephy_encodings_get_node (encodings, l->data) != NULL) + { + encodings->priv->recent = + g_slist_prepend (encodings->priv->recent, + l->data); + } + else + { + g_free (l->data); + } + } + encodings->priv->recent = g_slist_reverse (encodings->priv->recent); + g_slist_free (list); +} + +void +ephy_encoding_info_free (EphyEncodingInfo *info) +{ + if (info) + { + g_free (info->encoding); + g_free (info->hint_encoding); + g_free (info->parent_encoding); + g_free (info->prev_doc_encoding); + g_free (info->forced_encoding); + g_free (info->default_encoding); + g_free (info); + } +} + +EphyEncodings * +ephy_encodings_new (void) +{ + return g_object_new (EPHY_TYPE_ENCODINGS, NULL); +} diff --git a/embed/ephy-encodings.h b/embed/ephy-encodings.h new file mode 100644 index 000000000..29034e13a --- /dev/null +++ b/embed/ephy-encodings.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2003 Christian Persch + * + * 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. + * + * $Id$ + */ + +#ifndef EPHY_ENCODINGS_H +#define EPHY_ENCODINGS_H + +#include <glib-object.h> +#include <glib.h> + +#include "ephy-node.h" + +G_BEGIN_DECLS + +#define EPHY_TYPE_ENCODINGS (ephy_encodings_get_type ()) +#define EPHY_ENCODINGS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_ENCODINGS, EphyEncodings)) +#define EPHY_ENCODINGS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EPHY_TYPE_ENCODINGS, EphyEncodingsClass)) +#define EPHY_IS_ENCODINGS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_ENCODINGS)) +#define EPHY_IS_ENCODINGS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_ENCODINGS)) +#define EPHY_ENCODINGS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_ENCODINGS, EphyEncodingsClass)) + +typedef struct EphyEncodingsPrivate EphyEncodingsPrivate; + +typedef enum +{ + LG_NONE = 0, + LG_ARABIC = 1 << 0, + LG_BALTIC = 1 << 1, + LG_CAUCASIAN = 1 << 2, + LG_C_EUROPEAN = 1 << 3, + LG_CHINESE_TRAD = 1 << 4, + LG_CHINESE_SIMP = 1 << 5, + LG_CYRILLIC = 1 << 6, + LG_GREEK = 1 << 7, + LG_HEBREW = 1 << 8, + LG_INDIAN = 1 << 9, + LG_JAPANESE = 1 << 10, + LG_KOREAN = 1 << 12, + LG_NORDIC = 1 << 13, + LG_PERSIAN = 1 << 14, + LG_SE_EUROPEAN = 1 << 15, + LG_THAI = 1 << 16, + LG_TURKISH = 1 << 17, + LG_UKRAINIAN = 1 << 18, + LG_UNICODE = 1 << 19, + LG_VIETNAMESE = 1 << 20, + LG_WESTERN = 1 << 21, + LG_ALL = 0x3fffff, +} +EphyLanguageGroup; + +/* from htmlparser/nsIParser.h */ +/* note: the value order defines the priority */ +typedef enum +{ + EMBED_ENCODING_UNINITIALISED = 0, + EMBED_ENCODING_WEAK_DOCTYPE_DEFAULT = 1, + EMBED_ENCODING_USER_DEFAULT = 2, + EMBED_ENCODING_DOCTYPE_DEFAULT = 3, + EMBED_ENCODING_CACHE = 4, + EMBED_ENCODING_PARENT_FRAME = 5, + EMBED_ENCODING_BOOKMARKS = 6, + EMBED_ENCODING_AUTODETECTION = 7, + EMBED_ENCODING_HINT_PREV_DOC = 8, + EMBED_ENCODING_META_TAG = 9, + EMBED_ENCODING_BOM = 10, + EMBED_ENCODING_CHANNEL = 11, + EMBED_ENCODING_PARENT_FORCED = 12, + EMBED_ENCODING_USER_FORCED = 13, + EMBED_ENCODING_OTHER_COMPONENT = 14, + EMBED_ENCODING_PREV_LOADING = 15 +} +EphyEncodingSource; + +typedef struct +{ + char *encoding; + char *default_encoding; + char *hint_encoding; + char *prev_doc_encoding; + char *forced_encoding; + char *parent_encoding; + EphyEncodingSource encoding_source; + EphyEncodingSource hint_encoding_source; + EphyEncodingSource parent_encoding_source; +} +EphyEncodingInfo; + +enum +{ + EPHY_NODE_ENCODING_PROP_TITLE = 1, + EPHY_NODE_ENCODING_PROP_TITLE_ELIDED = 2, + EPHY_NODE_ENCODING_PROP_COLLATION_KEY = 3, + EPHY_NODE_ENCODING_PROP_ENCODING = 4, + EPHY_NODE_ENCODING_PROP_LANGUAGE_GROUPS = 5, + EPHY_NODE_ENCODING_PROP_IS_AUTODETECTOR = 6 +}; + +typedef struct +{ + GObject parent; + EphyEncodingsPrivate *priv; +} EphyEncodings; + +typedef struct +{ + GObjectClass parent_class; +} EphyEncodingsClass; + +GType ephy_encodings_get_type (void); + +EphyEncodings *ephy_encodings_new (void); + +EphyNode *ephy_encodings_get_node (EphyEncodings *encodings, + const char *code); + +GList *ephy_encodings_get_encodings (EphyEncodings *encodings, + EphyLanguageGroup group_mask); + +EphyNode *ephy_encodings_get_all (EphyEncodings *encodings); + +EphyNode *ephy_encodings_get_categories (EphyEncodings *encodings); + +GList *ephy_encodings_get_detectors (EphyEncodings *encodings); + +void ephy_encodings_add_recent (EphyEncodings *encodings, + const char *code); + +GList *ephy_encodings_get_recent (EphyEncodings *encodings); + +void ephy_encoding_info_free (EphyEncodingInfo *info); + +G_END_DECLS + +#endif diff --git a/embed/mozilla/EphyWrapper.cpp b/embed/mozilla/EphyWrapper.cpp index 71194438f..371e87134 100644 --- a/embed/mozilla/EphyWrapper.cpp +++ b/embed/mozilla/EphyWrapper.cpp @@ -72,6 +72,8 @@ #include "nsIDOMHTMLElement.h" #include "nsIDeviceContext.h" #include "nsIPresContext.h" +#include "nsIAtom.h" +#include "nsIDocumentCharsetInfo.h" #include "ContentHandler.h" #include "EphyEventListener.h" @@ -756,9 +758,10 @@ nsresult EphyWrapper::PopTargetDocument () return NS_OK; } -nsresult EphyWrapper::GetEncoding (char **aEncoding) +nsresult EphyWrapper::GetEncodingInfo (EphyEncodingInfo **infoptr) { nsresult result; + EphyEncodingInfo *info; nsCOMPtr<nsIDOMDocument> domDoc; result = GetDOMDocument (getter_AddRefs(domDoc)); @@ -767,19 +770,104 @@ nsresult EphyWrapper::GetEncoding (char **aEncoding) nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc, &result); if (NS_FAILED (result) || !doc) return NS_ERROR_FAILURE; + info = g_new0 (EphyEncodingInfo, 1); + *infoptr = info; + #if MOZILLA_SNAPSHOT >= 10 nsCAutoString enc; result = doc->GetDocumentCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; - *aEncoding = g_strdup (enc.get()); + info->encoding = g_strdup (enc.get()); #else nsAutoString enc; result = doc->GetDocumentCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; - *aEncoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); + info->encoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); +#endif + + PRInt32 source; + result = doc->GetDocumentCharacterSetSource (&source); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->encoding_source = (EphyEncodingSource) source; + + nsCOMPtr<nsIDocShell> ds; + result = GetDocShell (getter_AddRefs(ds)); + if (NS_FAILED(result) || !ds) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDocumentCharsetInfo> ci; + result = ds->GetDocumentCharsetInfo (getter_AddRefs (ci)); + if (NS_FAILED(result) || !ci) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIAtom> atom; + result = ci->GetForcedCharset (getter_AddRefs (atom)); + if (NS_FAILED(result)) return NS_ERROR_FAILURE; + if (atom) + { + nsCAutoString atomstr; + atom->ToUTF8String (atomstr); + info->forced_encoding = g_strdup (atomstr.get()); + } + + result = ci->GetParentCharset (getter_AddRefs (atom)); + if (NS_FAILED(result)) return NS_ERROR_FAILURE; + if (atom) + { + nsCAutoString atomstr; + atom->ToUTF8String (atomstr); + info->parent_encoding = g_strdup (atomstr.get()); + } + + result = ci->GetParentCharsetSource (&source); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->parent_encoding_source = (EphyEncodingSource) source; + + nsCOMPtr<nsIContentViewer> contentViewer; + result = ds->GetContentViewer (getter_AddRefs(contentViewer)); + if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer, + &result); + if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE; + +#if MOZILLA_SNAPSHOT >= 10 + result = mdv->GetDefaultCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->default_encoding = g_strdup (enc.get()); + + result = mdv->GetForceCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->forced_encoding = g_strdup (enc.get()); + + result = mdv->GetHintCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->hint_encoding = g_strdup (enc.get()); + + result = mdv->GetPrevDocCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->prev_doc_encoding = g_strdup (enc.get()); +#else + result = mdv->GetDefaultCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->default_encoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); + + result = mdv->GetForceCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->forced_encoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); + + result = mdv->GetHintCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->hint_encoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); + + result = mdv->GetPrevDocCharacterSet (enc); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->prev_doc__encoding = g_strdup (NS_ConvertUCS2toUTF8(enc).get()); #endif + mdv->GetHintCharacterSetSource (&source); + if (NS_FAILED (result)) return NS_ERROR_FAILURE; + info->hint_encoding_source = (EphyEncodingSource) source; + return NS_OK; } diff --git a/embed/mozilla/EphyWrapper.h b/embed/mozilla/EphyWrapper.h index cfedf6ccc..5f5ed7bf3 100644 --- a/embed/mozilla/EphyWrapper.h +++ b/embed/mozilla/EphyWrapper.h @@ -21,6 +21,8 @@ #ifndef EPHY_WRAPPER_H #define EPHY_WRAPPER_H +#include "ephy-encodings.h" + #include "nsIDocShell.h" //#include "ProgressListener.h" #include "nsIWebNavigation.h" @@ -78,7 +80,7 @@ public: nsresult ForceEncoding (const char *encoding); - nsresult GetEncoding (char **aEncoding); + nsresult GetEncodingInfo (EphyEncodingInfo **infoptr); nsresult CanCutSelection(PRBool *result); diff --git a/embed/mozilla/Makefile.am b/embed/mozilla/Makefile.am index 22ef72829..12922c1e7 100644 --- a/embed/mozilla/Makefile.am +++ b/embed/mozilla/Makefile.am @@ -6,6 +6,7 @@ INCLUDES = \ $(WARN_CXXFLAGS) \ $(MOZILLA_COMPONENT_CFLAGS) \ -I$(MOZILLA_INCLUDE_ROOT)/appcomps \ + -I$(MOZILLA_INCLUDE_ROOT)/chardet \ -I$(MOZILLA_INCLUDE_ROOT)/chrome \ -I$(MOZILLA_INCLUDE_ROOT)/content \ -I$(MOZILLA_INCLUDE_ROOT)/cookie \ diff --git a/embed/mozilla/mozilla-embed.cpp b/embed/mozilla/mozilla-embed.cpp index de87457e3..e00738e4f 100644 --- a/embed/mozilla/mozilla-embed.cpp +++ b/embed/mozilla/mozilla-embed.cpp @@ -148,8 +148,8 @@ static gresult impl_set_encoding (EphyEmbed *embed, const char *encoding); static gresult -impl_get_encoding (EphyEmbed *embed, - char **encoding); +impl_get_encoding_info (EphyEmbed *embed, + EphyEncodingInfo **info); static gresult impl_print (EphyEmbed *embed, EmbedPrintInfo *info); @@ -380,7 +380,7 @@ ephy_embed_init (EphyEmbedClass *embed_class) embed_class->activate = impl_activate; embed_class->find_set_properties = impl_find_set_properties; embed_class->set_encoding = impl_set_encoding; - embed_class->get_encoding = impl_get_encoding; + embed_class->get_encoding_info = impl_get_encoding_info; embed_class->select_all = impl_select_all; embed_class->print = impl_print; embed_class->print_preview_close = impl_print_preview_close; @@ -1192,19 +1192,21 @@ impl_set_encoding (EphyEmbed *embed, } static gresult -impl_get_encoding (EphyEmbed *embed, - char **encoding) +impl_get_encoding_info (EphyEmbed *embed, + EphyEncodingInfo **info) { nsresult result; EphyWrapper *wrapper; - g_return_val_if_fail (encoding != NULL, G_FAILED); - *encoding = NULL; + g_return_val_if_fail (info != NULL, G_FAILED); + *info = NULL; wrapper = MOZILLA_EMBED(embed)->priv->wrapper; - g_return_val_if_fail (wrapper != NULL, G_FAILED); + // we want to use get_encoding_info on newly opened tabs too :/ + //g_return_val_if_fail (wrapper != NULL, G_FAILED); + if (wrapper == NULL) return G_FAILED; - result = wrapper->GetEncoding (encoding); + result = wrapper->GetEncodingInfo (info); return NS_SUCCEEDED(result) ? G_OK : G_FAILED; } diff --git a/embed/mozilla/mozilla-notifiers.cpp b/embed/mozilla/mozilla-notifiers.cpp index 0b170b555..7dde69462 100644 --- a/embed/mozilla/mozilla-notifiers.cpp +++ b/embed/mozilla/mozilla-notifiers.cpp @@ -387,7 +387,8 @@ mozilla_notifiers_init(EphyEmbedSingle *single) { GConfClient *client = eel_gconf_client_get_global (); guint i; - GList *codes, *l; + const EphyFontsLanguageInfo *font_languages; + guint n_font_languages; for (i = 0; conversion_table[i].gconf_key != NULL; i++) { @@ -425,10 +426,12 @@ mozilla_notifiers_init(EphyEmbedSingle *single) } /* fonts notifiers */ - codes = ephy_font_langs_get_codes_list (); - for (l = codes; l != NULL; l = l->next) + font_languages = ephy_font_languages (); + n_font_languages = ephy_font_n_languages (); + + for (i=0; i < n_font_languages; i++) { - const char *code = (char*) l->data; + const char *code = font_languages[i].code; guint k; char *types [] = { "variable", "monospace" }; char key[255]; @@ -467,7 +470,6 @@ mozilla_notifiers_init(EphyEmbedSingle *single) info); font_infos = g_list_prepend (font_infos, info); } - g_list_free (codes); } void diff --git a/lib/Makefile.am b/lib/Makefile.am index 64c469144..7caefb55d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -35,7 +35,6 @@ NOINST_H_FILES = \ INST_H_FILES = \ ephy-dialog.h \ ephy-langs.h \ - ephy-encodings.h \ ephy-node.h \ ephy-node-db.h \ ephy-types.h @@ -51,7 +50,6 @@ libephy_la_SOURCES = \ ephy-dialog.h \ ephy-dnd.c \ ephy-dnd.h \ - ephy-encodings.c \ ephy-file-helpers.c \ ephy-file-helpers.h \ ephy-glade.c \ diff --git a/lib/ephy-encodings.c b/lib/ephy-encodings.c deleted file mode 100644 index c02705c72..000000000 --- a/lib/ephy-encodings.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2003 Marco Pesenti Gritti - * Copyright (C) 2003 Christian Persch - * - * 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. - * - * $Id$ - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "ephy-encodings.h" -#include "ephy-string.h" -#include <bonobo/bonobo-i18n.h> -#include <string.h> - -/** - * translatable encodings titles - * NOTE: if you add /change encodings, please also update the schema file - * epiphany.schemas.in - */ -static const -struct -{ - char *title; - char *name; - EphyLanguageGroup group; -} -encodings[] = -{ - /* translators: access keys need only be unique within the same LG_group */ - { N_("Arabic (_IBM-864)"), "IBM864", LG_ARABIC }, - { N_("Arabic (ISO-_8859-6)"), "ISO-8859-6", LG_ARABIC }, - { N_("Arabic (_MacArabic)"), "x-mac-arabic", LG_ARABIC }, - { N_("Arabic (_Windows-1256)"), "windows-1256", LG_ARABIC }, - { N_("Baltic (_ISO-8859-13)"), "ISO-8859-13", LG_BALTIC }, - { N_("Baltic (I_SO-8859-4)"), "ISO-8859-4", LG_BALTIC }, - { N_("Baltic (_Windows-1257)"), "windows-1257", LG_BALTIC }, - { N_("Central European (_IBM-852)"), "IBM852", LG_CENTRAL_EUROPEAN }, - { N_("Central European (I_SO-8859-2)"), "ISO-8859-2", LG_CENTRAL_EUROPEAN }, - { N_("Central European (_MacCE)"), "x-mac-ce", LG_CENTRAL_EUROPEAN }, - { N_("Central European (_Windows-1250)"), "windows-1250", LG_CENTRAL_EUROPEAN }, - { N_("Croatian (Mac_Croatian)"), "x-mac-croatian", LG_CENTRAL_EUROPEAN }, - { N_("Chinese Simplified (_GB18030)"), "gb18030", LG_CHINESE }, - { N_("Chinese Simplified (G_B2312)"), "GB2312", LG_CHINESE }, - { N_("Chinese Simplified (GB_K)"), "x-gbk", LG_CHINESE }, - { N_("Chinese Simplified (_HZ)"), "HZ-GB-2312", LG_CHINESE }, - { N_("Chinese Simplified (_ISO-2022-CN)"), "ISO-2022-CN", LG_CHINESE }, - { N_("Chinese Traditional (Big_5)"), "Big5", LG_CHINESE }, - { N_("Chinese Traditional (Big5-HK_SCS)"), "Big5-HKSCS", LG_CHINESE }, - { N_("Chinese Traditional (_EUC-TW)"), "x-euc-tw", LG_CHINESE }, - { N_("Cyrillic (_IBM-855)"), "IBM855", LG_CYRILLIC }, - { N_("Cyrillic (I_SO-8859-5)"), "ISO-8859-5", LG_CYRILLIC }, - { N_("Cyrillic (IS_O-IR-111)"), "ISO-IR-111", LG_CYRILLIC }, - { N_("Cyrillic (_KOI8-R)"), "KOI8-R", LG_CYRILLIC }, - { N_("Cyrillic (_MacCyrillic)"), "x-mac-cyrillic", LG_CYRILLIC }, - { N_("Cyrillic (_Windows-1251)"), "windows-1251", LG_CYRILLIC }, - { N_("Cyrillic/Russian (_CP-866)"), "IBM866", LG_CYRILLIC }, - { N_("Cyrillic/Ukrainian (_KOI8-U)"), "KOI8-U", LG_CYRILLIC }, - { N_("Cyrillic/Ukrainian (Mac_Ukrainian)"), "x-mac-ukrainian", LG_CYRILLIC }, - { N_("Greek (_ISO-8859-7)"), "ISO-8859-7", LG_GREEK }, - { N_("Greek (_MacGreek)"), "x-mac-greek", LG_GREEK }, - { N_("Greek (_Windows-1253)"), "windows-1253", LG_GREEK }, - { N_("Gujarati (_MacGujarati)"), "x-mac-gujarati", LG_INDIAN }, - { N_("Gurmukhi (Mac_Gurmukhi)"), "x-mac-gurmukhi", LG_INDIAN }, - { N_("Hindi (Mac_Devanagari)"), "x-mac-devanagari", LG_INDIAN }, - { N_("Hebrew (_IBM-862)"), "IBM862", LG_HEBREW }, - { N_("Hebrew (IS_O-8859-8-I)"), "ISO-8859-8-I", LG_HEBREW }, - { N_("Hebrew (_MacHebrew)"), "x-mac-hebrew", LG_HEBREW }, - { N_("Hebrew (_Windows-1255)"), "windows-1255", LG_HEBREW }, - { N_("_Visual Hebrew (ISO-8859-8)"), "ISO-8859-8", LG_HEBREW }, - { N_("Japanese (_EUC-JP)"), "EUC-JP", LG_JAPANESE }, - { N_("Japanese (_ISO-2022-JP)"), "ISO-2022-JP", LG_JAPANESE }, - { N_("Japanese (_Shift-JIS)"), "Shift_JIS", LG_JAPANESE }, - { N_("Korean (_EUC-KR)"), "EUC-KR", LG_KOREAN }, - { N_("Korean (_ISO-2022-KR)"), "ISO-2022-KR", LG_KOREAN }, - { N_("Korean (_JOHAB)"), "x-johab", LG_KOREAN }, - { N_("Korean (_UHC)"), "x-windows-949", LG_KOREAN }, - { N_("Turkish (_IBM-857)"), "IBM857", LG_TURKISH }, - { N_("Turkish (I_SO-8859-9)"), "ISO-8859-9", LG_TURKISH }, - { N_("Turkish (_MacTurkish)"), "x-mac-turkish", LG_TURKISH }, - { N_("Turkish (_Windows-1254)"), "windows-1254", LG_TURKISH }, - { N_("Unicode (UTF-_7)"), "UTF-7", LG_UNICODE }, - { N_("Unicode (UTF-_8)"), "UTF-8", LG_UNICODE }, - { N_("Vietnamese (_TCVN)"), "x-viet-tcvn5712", LG_VIETNAMESE }, - { N_("Vietnamese (_VISCII)"), "VISCII", LG_VIETNAMESE }, - { N_("Vietnamese (V_PS)"), "x-viet-vps", LG_VIETNAMESE }, - { N_("Vietnamese (_Windows-1258)"), "windows-1258", LG_VIETNAMESE }, - { N_("Western (_IBM-850)"), "IBM850", LG_WESTERN }, - { N_("Western (I_SO-8859-1)"), "ISO-8859-1", LG_WESTERN }, - { N_("Western (IS_O-8859-15)"), "ISO-8859-15", LG_WESTERN }, - { N_("Western (_MacRoman)"), "x-mac-roman", LG_WESTERN }, - { N_("Western (_Windows-1252)"), "windows-1252", LG_WESTERN }, - { N_("_Armenian (ARMSCII-8)"), "armscii-8", LG_OTHER }, - { N_("_Celtic (ISO-8859-14)"), "ISO-8859-14", LG_OTHER }, - { N_("_Farsi (MacFarsi)"), "x-mac-farsi", LG_OTHER }, - { N_("_Georgian (GEOSTD8)"), "geostd8", LG_OTHER }, - { N_("_Icelandic (MacIcelandic)"), "x-mac-icelandic", LG_OTHER }, - { N_("_Nordic (ISO-8859-10)"), "ISO-8859-10", LG_OTHER }, - { N_("_Romanian (MacRomanian)"), "x-mac-romanian", LG_OTHER }, - { N_("R_omanian (ISO-8859-16)"), "ISO-8859-16", LG_OTHER }, - { N_("South _European (ISO-8859-3)"), "ISO-8859-3", LG_OTHER }, - { N_("Thai (TIS-_620)"), "TIS-620", LG_OTHER }, -#if MOZILLA_SNAPSHOT >= 10 - { N_("Thai (IS_O-8859-11)"), "iso-8859-11", LG_OTHER }, - { N_("_Thai (Windows-874)"), "windows-874", LG_OTHER }, -#endif - { N_("_User Defined"), "x-user-defined", LG_OTHER }, -}; -static const guint n_encodings = G_N_ELEMENTS (encodings); - -void -ephy_encoding_info_free (EphyEncodingInfo *info) -{ - g_return_if_fail (info != NULL); - - g_free (info->title); - g_free (info->key); - g_free (info->encoding); - - g_free (info); -} - -static int -encodings_info_cmp (const EphyEncodingInfo *i1, const EphyEncodingInfo *i2) -{ - return strcmp (i1->key, i2->key); -} - -GList * -ephy_encodings_get_list (EphyLanguageGroup group, gboolean elide_underscores) -{ - GList *list = NULL; - guint i; - - for (i = 0; i < n_encodings; i++) - { - if (group == LG_ALL || group == encodings[i].group) - { - EphyEncodingInfo *info; - char *elided = NULL; - - info = g_new0 (EphyEncodingInfo, 1); - - info->group = encodings[i].group; - info->encoding = g_strdup (encodings[i].name); - - elided = ephy_string_elide_underscores (_(encodings[i].title)); - - /* collate without underscores */ - info->key = g_utf8_collate_key (elided, -1); - - if (elide_underscores) - { - info->title = elided; - } - else - { - g_free (elided); - - info->title = g_strdup (_(encodings[i].title)); - } - - list = g_list_prepend (list, info); - } - } - - return g_list_sort (list, (GCompareFunc) encodings_info_cmp); -} diff --git a/lib/ephy-encodings.h b/lib/ephy-encodings.h deleted file mode 100644 index 59f14393e..000000000 --- a/lib/ephy-encodings.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2003 Marco Pesenti Gritti - * Copyright (C) 2003 Christian Persch - * - * 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. - * - * $Id$ - */ - -#ifndef EPHY_ENCODINGS_H -#define EPHY_ENCODINGS_H - -#include <glib.h> -#include "ephy-langs.h" - -G_BEGIN_DECLS - -typedef struct -{ - char *encoding; - EphyLanguageGroup group; - char *title; - char *key; -} EphyEncodingInfo; - -GList *ephy_encodings_get_list (EphyLanguageGroup group, - gboolean elide_underscores); - -void ephy_encoding_info_free (EphyEncodingInfo *info); - -G_END_DECLS - -#endif diff --git a/lib/ephy-langs.c b/lib/ephy-langs.c index dee178846..5669253e0 100644 --- a/lib/ephy-langs.c +++ b/lib/ephy-langs.c @@ -23,11 +23,10 @@ #endif #include "ephy-langs.h" -#include "ephy-string.h" + #include <bonobo/bonobo-i18n.h> -#include <string.h> -static const FontsLanguageInfo font_languages[] = +static const EphyFontsLanguageInfo font_languages [] = { { N_("Arabic"), "ar" }, { N_("Baltic"), "x-baltic" }, @@ -51,112 +50,14 @@ static const FontsLanguageInfo font_languages[] = }; static const guint n_font_languages = G_N_ELEMENTS (font_languages); -static const -struct -{ - EphyLanguageGroup group; - char *title; -} -lang_group_names[] = -{ - { LG_ARABIC, N_("_Arabic") }, - { LG_BALTIC, N_("_Baltic") }, - { LG_CENTRAL_EUROPEAN, N_("Central _European") }, - { LG_CHINESE, N_("Chi_nese") }, - { LG_CYRILLIC, N_("_Cyrillic") }, - { LG_GREEK, N_("_Greek") }, - { LG_HEBREW, N_("_Hebrew") }, - { LG_INDIAN, N_("_Indian") }, - { LG_JAPANESE, N_("_Japanese") }, - { LG_KOREAN, N_("_Korean") }, - { LG_TURKISH, N_("_Turkish") }, - { LG_UNICODE, N_("_Unicode") }, - { LG_VIETNAMESE, N_("_Vietnamese") }, - { LG_WESTERN, N_("_Western") }, - { LG_OTHER, N_("_Other") } -}; -static const guint n_lang_group_names = G_N_ELEMENTS (lang_group_names); - -void -ephy_lang_group_info_free (EphyLanguageGroupInfo *info) -{ - g_return_if_fail (info != NULL); - - g_free (info->title); - g_free (info->key); - - g_free (info); -} - -static gint -lang_group_info_cmp (const EphyLanguageGroupInfo *i1, const EphyLanguageGroupInfo *i2) -{ - return strcmp (i1->key, i2->key); -} - -GList * -ephy_lang_get_group_list (void) -{ - GList *list = NULL; - guint i; - - for (i = 0; i < n_lang_group_names; i++) - { - EphyLanguageGroupInfo *info; - char *elided = NULL; - - info = g_new0 (EphyLanguageGroupInfo, 1); - - info->title = g_strdup (_(lang_group_names[i].title)); - info->group = lang_group_names[i].group; - - /* collate without underscores */ - elided = ephy_string_elide_underscores (info->title); - info->key = g_utf8_collate_key (elided, -1); - g_free (elided); - - list = g_list_prepend (list, info); - } - - return g_list_sort (list, (GCompareFunc) lang_group_info_cmp); -} - -static int -fonts_language_info_cmp (const FontsLanguageInfo *i1, const FontsLanguageInfo *i2) -{ - return g_utf8_collate (i1->title, i2->title); -} - -GList * -ephy_font_langs_get_codes_list (void) +const EphyFontsLanguageInfo * +ephy_font_languages (void) { - guint i; - GList *list = NULL; - - for (i=0; i < n_font_languages; i++) - { - list = g_list_prepend (list, font_languages[i].code); - } - - return list; + return font_languages; } -GList * -ephy_font_langs_get_list (void) +guint +ephy_font_n_languages (void) { - GList *list = NULL; - guint i; - - for (i = 0; i < n_font_languages; i++) - { - FontsLanguageInfo *info; - - info = g_new0 (FontsLanguageInfo, 1); - info->title = _(font_languages[i].title); - info->code = font_languages[i].code; - - list = g_list_prepend (list, info); - } - - return g_list_sort (list, (GCompareFunc) fonts_language_info_cmp); + return n_font_languages; } diff --git a/lib/ephy-langs.h b/lib/ephy-langs.h index c4007dd73..4715801f4 100644 --- a/lib/ephy-langs.h +++ b/lib/ephy-langs.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2000 Marco Pesenti Gritti + * Copyright (C) 2000, 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persc * * 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 @@ -14,60 +15,26 @@ * 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. + * + * $Id$ */ #ifndef EPHY_LANGS_H #define EPHY_LANGS_H -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <glib.h> G_BEGIN_DECLS -/* language groups */ -typedef enum -{ - LG_ARABIC, - LG_BALTIC, - LG_CENTRAL_EUROPEAN, - LG_CHINESE, - LG_CYRILLIC, - LG_GREEK, - LG_HEBREW, - LG_INDIAN, - LG_JAPANESE, - LG_KOREAN, - LG_TURKISH, - LG_UNICODE, - LG_VIETNAMESE, - LG_WESTERN, - LG_OTHER, - LG_ALL -} EphyLanguageGroup; - -typedef struct -{ - EphyLanguageGroup group; - char *title; - char *key; -} EphyLanguageGroupInfo; - typedef struct { char *title; char *code; -} FontsLanguageInfo; - -GList *ephy_font_langs_get_list (void); - -GList *ephy_font_langs_get_codes_list (void); +} EphyFontsLanguageInfo; -GList *ephy_lang_get_group_list (void); +const EphyFontsLanguageInfo *ephy_font_languages (void); -void ephy_lang_group_info_free (EphyLanguageGroupInfo *info); +guint ephy_font_n_languages (void); G_END_DECLS diff --git a/src/Makefile.am b/src/Makefile.am index f1cc2ad3a..7703b6b4c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,6 +50,7 @@ header_DATA = $(INST_H_FILES) NOINST_H_FILES = \ ephy-automation.h \ + ephy-encoding-dialog.h \ ephy-encoding-menu.h \ ephy-favicon-action.h \ ephy-favorites-menu.h \ @@ -83,6 +84,7 @@ epiphany_bin_SOURCES = \ ephy-automation.c \ ephy-completion-model.c \ ephy-completion-model.h \ + ephy-encoding-dialog.c \ ephy-encoding-menu.c \ ephy-favicon-action.c \ ephy-favorites-menu.c \ diff --git a/src/ephy-encoding-dialog.c b/src/ephy-encoding-dialog.c new file mode 100644 index 000000000..5f7e653a1 --- /dev/null +++ b/src/ephy-encoding-dialog.c @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persch + * + * 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. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ephy-encoding-dialog.h" +#include "ephy-encodings.h" +#include "ephy-embed.h" +#include "ephy-embed-shell.h" +#include "ephy-shell.h" +#include "ephy-gui.h" +#include "ephy-node.h" +#include "ephy-node-view.h" +#include "ephy-debug.h" + +#include <gtk/gtklabel.h> +#include <gtk/gtkbutton.h> +#include <gtk/gtktreeview.h> +#include <gtk/gtktreeselection.h> +#include <bonobo/bonobo-i18n.h> +#include <string.h> + +enum +{ + CATEGORIES_SCROLLER_PROP, + LIST_SCROLLER_PROP +}; + +static const +EphyDialogProperty properties [] = +{ + { CATEGORIES_SCROLLER_PROP, "categories_scroller", NULL, PT_NORMAL, NULL }, + { LIST_SCROLLER_PROP, "list_scroller", NULL, PT_NORMAL, NULL }, + + { -1, NULL, NULL } +}; + +#define EPHY_ENCODING_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ENCODING_DIALOG, EphyEncodingDialogPrivate)) + +struct EphyEncodingDialogPrivate +{ + EphyEncodings *encodings; + EphyWindow *window; + EphyEmbed *embed; + GtkWidget *cat_view; + GtkWidget *enc_view; + EphyNodeFilter *filter; + EphyNode *selected_node; + gboolean update_tag; +}; + +static void ephy_encoding_dialog_class_init (EphyEncodingDialogClass *klass); +static void ephy_encoding_dialog_init (EphyEncodingDialog *ge); +void ephy_encoding_dialog_response_cb (GtkWidget *widget, + gint response, + EphyEncodingDialog *dialog); + +enum +{ + PROP_0, + PROP_WINDOW +}; + +static GObjectClass *parent_class = NULL; + +GType +ephy_encoding_dialog_get_type (void) +{ + static GType ephy_type_encoding_dialog = 0; + + if (ephy_type_encoding_dialog == 0) + { + static const GTypeInfo our_info = + { + sizeof (EphyEncodingDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) ephy_encoding_dialog_class_init, + NULL, + NULL, /* class_data */ + sizeof (EphyEncodingDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) ephy_encoding_dialog_init + }; + + ephy_type_encoding_dialog = g_type_register_static (EPHY_TYPE_EMBED_DIALOG, + "EphyEncodingDialog", + &our_info, 0); + } + + return ephy_type_encoding_dialog; +} + +static void +setup_filter (EphyEncodingDialog *dialog, EphyNode *category) +{ + ephy_node_filter_empty (dialog->priv->filter); + + ephy_node_filter_add_expression (dialog->priv->filter, + ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_HAS_PARENT, + category), + 0); + + ephy_node_filter_done_changing (dialog->priv->filter); +} + +static void +sync_embed_cb (EphyEncodingDialog *dialog, GParamSpec *pspec, gpointer dummy) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + EphyNode *node, *categories; + gresult result; + GtkTreeSelection *selection; + GtkTreeModel *model; + GList *rows; + GPtrArray *children; + int i; + + dialog->priv->update_tag = TRUE; + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + node = ephy_encodings_get_node (dialog->priv->encodings, info->encoding); + g_return_if_fail (EPHY_IS_NODE (node)); + + /* select the correct category in the left pane ... */ + categories = ephy_encodings_get_categories (dialog->priv->encodings); + + children = ephy_node_get_children (categories); + for (i = 0; i < children->len; i++) + { + EphyNode *kid; + + kid = g_ptr_array_index (children, i); + if (ephy_node_has_child (kid, node)) + { + ephy_node_view_select_node (EPHY_NODE_VIEW (dialog->priv->cat_view), + kid); + break; + } + } + ephy_node_thaw (categories); + + /* ... and the active encoding in the right pane */ + ephy_node_view_select_node (EPHY_NODE_VIEW (dialog->priv->enc_view), + node); + + /* scroll the view so the active encoding is visible */ + selection = gtk_tree_view_get_selection + (GTK_TREE_VIEW (dialog->priv->enc_view)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->enc_view)); + rows = gtk_tree_selection_get_selected_rows (selection, &model); + if (rows != NULL) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->priv->enc_view), + (GtkTreePath *)rows->data, + NULL, FALSE); + g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL); + g_list_free (rows); + } + + ephy_encoding_info_free (info); + + dialog->priv->update_tag = FALSE; +} + +static void +sync_active_tab (EphyWindow *window, GParamSpec *pspec, EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + + embed = ephy_window_get_active_embed (dialog->priv->window); + + g_object_set (G_OBJECT (dialog), "embed", embed, NULL); +} + +static void +ephy_encoding_dialog_set_window (EphyEncodingDialog *dialog, EphyWindow *window) +{ + g_return_if_fail (EPHY_IS_WINDOW (window)); + + dialog->priv->window = window; + + sync_active_tab (window, NULL, dialog); + g_signal_connect (G_OBJECT (window), "notify::active-tab", + G_CALLBACK (sync_active_tab), dialog); +} + +static void +activate_choice (EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + gresult result; + + LOG ("going manual") + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + if (dialog->priv->selected_node != NULL) + { + const char *code; + + code = ephy_node_get_property_string (dialog->priv->selected_node, + EPHY_NODE_ENCODING_PROP_ENCODING); + + /* only force it if it's different from active */ + if (info->encoding && strcmp (info->encoding, code) != 0) + { + ephy_embed_set_encoding (embed, code); + + ephy_encodings_add_recent (dialog->priv->encodings, code); + } + } + + ephy_encoding_info_free (info); +} + +static void +activate_automatic (EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + gresult result; + + LOG ("going automatic") + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + if ((info->forced_encoding != NULL && info->forced_encoding[0] != '\0') + || info->encoding_source >= EMBED_ENCODING_PARENT_FORCED) + { + /* clear forced encoding */ + ephy_embed_set_encoding (embed, ""); + } + + ephy_encoding_info_free (info); +} + +void +ephy_encoding_dialog_response_cb (GtkWidget *widget, + gint response, + EphyEncodingDialog *dialog) +{ + switch (response) + { + case GTK_RESPONSE_OK: + activate_choice (dialog); + break; + case -11: /* Automatic */ + activate_automatic (dialog); + break; + default: + break; + } + + g_object_unref (dialog); +} + +static void +category_node_selected_cb (EphyNodeView *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + setup_filter (dialog, node); +} + +static void +view_node_selected_cb (EphyNodeView *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + dialog->priv->selected_node = node; +} + +static void +view_node_activated_cb (GtkWidget *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + dialog->priv->selected_node = node; + + if (dialog->priv->update_tag == FALSE) + { + activate_choice (dialog); + + g_object_unref (dialog); + } +} + +static void +ephy_encoding_dialog_init (EphyEncodingDialog *dialog) +{ + GtkWidget *treeview, *scroller; + GtkTreeSelection *selection; + EphyNode *node; + + dialog->priv = EPHY_ENCODING_DIALOG_GET_PRIVATE (dialog); + + dialog->priv->encodings = + EPHY_ENCODINGS (ephy_embed_shell_get_encodings + (EPHY_EMBED_SHELL (ephy_shell))); + + dialog->priv->update_tag = FALSE; + dialog->priv->selected_node = NULL; + + ephy_dialog_construct (EPHY_DIALOG (dialog), + properties, + "epiphany.glade", + "encoding_dialog"); + + node = ephy_encodings_get_categories (dialog->priv->encodings); + treeview = ephy_node_view_new (node, dialog->priv->filter); + + ephy_node_view_add_column (EPHY_NODE_VIEW (treeview), _("Location"), + G_TYPE_STRING, + EPHY_NODE_ENCODING_PROP_TITLE, + -1, + EPHY_NODE_VIEW_AUTO_SORT | + EPHY_NODE_VIEW_SEARCHABLE, + NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + g_signal_connect (G_OBJECT (treeview), + "node_selected", + G_CALLBACK (category_node_selected_cb), + dialog); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); + gtk_widget_show (treeview); + + scroller = ephy_dialog_get_control + (EPHY_DIALOG (dialog), CATEGORIES_SCROLLER_PROP); + gtk_container_add (GTK_CONTAINER (scroller), treeview); + + dialog->priv->cat_view = treeview; + + dialog->priv->filter = ephy_node_filter_new (); + + node = ephy_encodings_get_all (dialog->priv->encodings); + treeview = ephy_node_view_new (node, dialog->priv->filter); + + ephy_node_view_add_column (EPHY_NODE_VIEW (treeview), _("Encodings"), + G_TYPE_STRING, + EPHY_NODE_ENCODING_PROP_TITLE_ELIDED, + -1, + EPHY_NODE_VIEW_AUTO_SORT | + EPHY_NODE_VIEW_SEARCHABLE, + NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); + + g_signal_connect (G_OBJECT (treeview), + "node_selected", + G_CALLBACK (view_node_selected_cb), + dialog); + g_signal_connect (G_OBJECT (treeview), + "node_activated", + G_CALLBACK (view_node_activated_cb), + dialog); + + gtk_widget_show (treeview); + + scroller = ephy_dialog_get_control + (EPHY_DIALOG (dialog), LIST_SCROLLER_PROP); + gtk_container_add (GTK_CONTAINER (scroller), treeview); + + dialog->priv->enc_view = treeview; + + g_signal_connect (G_OBJECT (dialog), "notify::embed", + G_CALLBACK (sync_embed_cb), NULL); +} + +static void +ephy_encoding_dialog_finalize (GObject *object) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + if (dialog->priv->window != NULL) + { + g_signal_handlers_disconnect_by_func (dialog->priv->window, + G_CALLBACK (sync_active_tab), + dialog); + } + + g_object_unref (dialog->priv->filter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +ephy_encoding_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + switch (prop_id) + { + case PROP_WINDOW: + ephy_encoding_dialog_set_window (dialog, g_value_get_object (value)); + break; + } +} + +static void +ephy_encoding_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + switch (prop_id) + { + case PROP_WINDOW: + g_value_set_object (value, dialog->priv->window); + break; + } +} + +static void +ephy_encoding_dialog_class_init (EphyEncodingDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = ephy_encoding_dialog_finalize; + object_class->get_property = ephy_encoding_dialog_get_property; + object_class->set_property = ephy_encoding_dialog_set_property; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "Parent window", + EPHY_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof(EphyEncodingDialogPrivate)); +} + +EphyEncodingDialog * +ephy_encoding_dialog_new (EphyWindow *parent) +{ + return g_object_new (EPHY_TYPE_ENCODING_DIALOG, + "window", parent, + NULL); +} diff --git a/src/ephy-encoding-dialog.h b/src/ephy-encoding-dialog.h new file mode 100644 index 000000000..b95b783a3 --- /dev/null +++ b/src/ephy-encoding-dialog.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persch + * + * 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. + * + * $Id$ + */ + +#ifndef EPHY_ENCODING_DIALOG_H +#define EPHY_ENCODING_DIALOG_H + +#include "ephy-embed-dialog.h" +#include "ephy-window.h" + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define EPHY_TYPE_ENCODING_DIALOG (ephy_encoding_dialog_get_type ()) +#define EPHY_ENCODING_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_ENCODING_DIALOG, EphyEncodingDialog)) +#define EPHY_ENCODING_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_ENCODING_DIALOG, EphyEncodingDialogClass)) +#define EPHY_IS_ENCODING_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_ENCODING_DIALOG)) +#define EPHY_IS_ENCODING_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_ENCODING_DIALOG)) +#define EPHY_ENCODING_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_ENCODING_DIALOG, EphyEncodingDialogClass)) + +typedef struct EphyEncodingDialog EphyEncodingDialog; +typedef struct EphyEncodingDialogClass EphyEncodingDialogClass; +typedef struct EphyEncodingDialogPrivate EphyEncodingDialogPrivate; + +struct EphyEncodingDialog +{ + EphyEmbedDialog parent; + EphyEncodingDialogPrivate *priv; +}; + +struct EphyEncodingDialogClass +{ + EphyEmbedDialogClass parent_class; +}; + +GType ephy_encoding_dialog_get_type (void); + +EphyEncodingDialog *ephy_encoding_dialog_new (EphyWindow *window); + +G_END_DECLS + +#endif diff --git a/src/ephy-encoding-menu.c b/src/ephy-encoding-menu.c index 0773a9fc5..312ba5a2f 100644 --- a/src/ephy-encoding-menu.c +++ b/src/ephy-encoding-menu.c @@ -25,35 +25,39 @@ #endif #include "ephy-encoding-menu.h" -#include "ephy-langs.h" +#include "ephy-encoding-dialog.h" #include "ephy-encodings.h" +#include "ephy-embed.h" +#include "ephy-embed-shell.h" +#include "ephy-shell.h" #include "ephy-string.h" #include "ephy-debug.h" -#include <bonobo/bonobo-i18n.h> #include <gtk/gtkaction.h> #include <gtk/gtktoggleaction.h> #include <gtk/gtkradioaction.h> #include <gtk/gtkuimanager.h> +#include <bonobo/bonobo-i18n.h> #include <string.h> #define EPHY_ENCODING_MENU_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ENCODING_MENU, EphyEncodingMenuPrivate)) struct _EphyEncodingMenuPrivate { + EphyEncodings *encodings; EphyWindow *window; GtkUIManager *manager; GtkActionGroup *action_group; gboolean update_tag; guint merge_id; + GSList *encodings_radio_group; + EphyEncodingDialog *dialog; }; -#define ENCODING_PLACEHOLDER_PATH "/menubar/ViewMenu/ViewEncodingsPlaceholder" -#define ENCODING_MENU_PATH "/menubar/ViewMenu/ViewEncodingsPlaceholder/ViewEncodingMenu" +#define ENCODING_PLACEHOLDER_PATH "/menubar/ViewMenu/ViewEncodingMenu/ViewEncodingPlaceholder" -static void ephy_encoding_menu_class_init (EphyEncodingMenuClass *klass); -static void ephy_encoding_menu_init (EphyEncodingMenu *menu); -static void ephy_encoding_menu_rebuild (EphyEncodingMenu *menu); +static void ephy_encoding_menu_class_init (EphyEncodingMenuClass *klass); +static void ephy_encoding_menu_init (EphyEncodingMenu *menu); enum { @@ -92,93 +96,314 @@ ephy_encoding_menu_get_type (void) } static void -ephy_encoding_menu_verb_cb (GtkAction *action, - EphyEncodingMenu *menu) +ephy_encoding_menu_init (EphyEncodingMenu *menu) +{ + menu->priv = EPHY_ENCODING_MENU_GET_PRIVATE (menu); + + menu->priv->encodings = + EPHY_ENCODINGS (ephy_embed_shell_get_encodings + (EPHY_EMBED_SHELL (ephy_shell))); + + menu->priv->update_tag = FALSE; + menu->priv->action_group = NULL; + menu->priv->merge_id = 0; + menu->priv->encodings_radio_group = NULL; + menu->priv->dialog = NULL; +} + +static int +sort_encodings (gconstpointer a, gconstpointer b) +{ + EphyNode *node1 = (EphyNode *) a; + EphyNode *node2 = (EphyNode *) b; + const char *key1, *key2; + + key1 = ephy_node_get_property_string + (node1, EPHY_NODE_ENCODING_PROP_COLLATION_KEY); + key2 = ephy_node_get_property_string + (node2, EPHY_NODE_ENCODING_PROP_COLLATION_KEY); + + return strcmp (key1, key2); +} + +static void +add_menu_item (EphyNode *node, EphyEncodingMenu *menu) +{ + const char *code; + char action[128], name[128]; + + code = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_ENCODING); + + g_snprintf (action, sizeof (action), "Encoding%s", code); + g_snprintf (name, sizeof (name), "%sItem", action); + + gtk_ui_manager_add_ui (menu->priv->manager, menu->priv->merge_id, + ENCODING_PLACEHOLDER_PATH, + name, action, + GTK_UI_MANAGER_MENUITEM, FALSE); +} + +static void +update_encoding_menu_cb (GtkAction *dummy, EphyEncodingMenu *menu) { + EphyEncodingMenuPrivate *p = menu->priv; EphyEmbed *embed; + GtkAction *action; + EphyEncodingInfo *info = NULL; + char name[128]; const char *encoding; - const char *action_name; + EphyNode *enc_node; + GList *recent, *related = NULL, *l; + EphyLanguageGroup groups; + gboolean is_automatic; + gresult result; - /* do nothing if this action was _de_activated, or if we're updating - * the menu, i.e. setting the active encoding from the document + START_PROFILER ("Rebuilding encoding menu") + + /* FIXME: block the "activate" signal on the actions instead; needs to + * wait until g_signal_handlers_block_matched supports blocking + * by signal id alone. */ - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) == FALSE - || menu->priv->update_tag) + menu->priv->update_tag = TRUE; + + /* get most recently used encodings */ + recent = ephy_encodings_get_recent (p->encodings); + + embed = ephy_window_get_active_embed (p->window); + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) goto build_menu; + + LOG ("encoding information\n enc='%s' default='%s' hint='%s' " + "prev_doc='%s' forced='%s' parent='%s' source=%d " + "hint_source=%d parent_source=%d", info->encoding, + info->default_encoding, info->hint_encoding, + info->prev_doc_encoding, info->forced_encoding, + info->parent_encoding, info->encoding_source, + info->hint_encoding_source, info->parent_encoding_source) + + encoding = info->encoding; + + enc_node = ephy_encodings_get_node (p->encodings, encoding); + if (!EPHY_IS_NODE (enc_node)) { - return; + g_warning ("Encountered unknown encoding '%s'" + ". Please file a bug at http://bugzilla.gnome.o" + "rg/enter_bug.cgi?product=epiphany\n", + encoding); + + goto build_menu; } - embed = ephy_window_get_active_embed (menu->priv->window); - g_return_if_fail (embed != NULL); + /* set the encodings group's active member */ + g_snprintf (name, sizeof (name), "Encoding%s", encoding); + action = gtk_action_group_get_action (p->action_group, name); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + + /* check if encoding was overridden */ + is_automatic = (info->encoding_source < EMBED_ENCODING_PARENT_FORCED); - action_name = gtk_action_get_name (action); + action = gtk_action_group_get_action (p->action_group, + "ViewEncodingAutomatic"); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_automatic); + g_object_set (G_OBJECT (action), "sensitive", !is_automatic, NULL); - if (strncmp (action_name, "Encoding", 8) == 0) + /* get encodings related to the current encoding */ + groups = ephy_node_get_property_int + (enc_node, EPHY_NODE_ENCODING_PROP_LANGUAGE_GROUPS); + + related = ephy_encodings_get_encodings (p->encodings, groups); + related = g_list_sort (related, (GCompareFunc) sort_encodings); + + /* add the current encoding to the list of + * things to display, making sure we don't add it more than once + */ + if (g_list_find (related, enc_node) == NULL + && g_list_find (recent, enc_node) == NULL) + { + recent = g_list_prepend (recent, enc_node); + } + + /* make sure related and recent are disjoint so we don't display twice */ + for (l = related; l != NULL; l = l->next) { - encoding = action_name + 8; + recent = g_list_remove (recent, l->data); + } - LOG ("Switching to encoding %s", encoding) + recent = g_list_sort (recent, (GCompareFunc) sort_encodings); - ephy_embed_set_encoding (embed, encoding); +build_menu: + /* clear the menu */ + if (p->merge_id > 0) + { + gtk_ui_manager_remove_ui (p->manager, p->merge_id); + gtk_ui_manager_ensure_update (p->manager); } -} -static void -ephy_encoding_menu_init (EphyEncodingMenu *menu) -{ - menu->priv = EPHY_ENCODING_MENU_GET_PRIVATE (menu); + /* build the new menu */ + p->merge_id = gtk_ui_manager_new_merge_id (p->manager); + + gtk_ui_manager_add_ui (p->manager, p->merge_id, + ENCODING_PLACEHOLDER_PATH, + "ViewEncodingAutomaticItem", + "ViewEncodingAutomatic", + GTK_UI_MANAGER_MENUITEM, FALSE); + + gtk_ui_manager_add_ui (p->manager, p->merge_id, + ENCODING_PLACEHOLDER_PATH, + "Sep1Item", "Sep1", + GTK_UI_MANAGER_SEPARATOR, FALSE); + + g_list_foreach (recent, (GFunc) add_menu_item, menu); + + gtk_ui_manager_add_ui (p->manager, p->merge_id, + ENCODING_PLACEHOLDER_PATH, + "Sep2Item", "Sep2", + GTK_UI_MANAGER_SEPARATOR, FALSE); + + g_list_foreach (related, (GFunc) add_menu_item, menu); + + gtk_ui_manager_add_ui (p->manager, p->merge_id, + ENCODING_PLACEHOLDER_PATH, + "Sep3Item", "Sep3", + GTK_UI_MANAGER_SEPARATOR, FALSE); + + gtk_ui_manager_add_ui (p->manager, p->merge_id, + ENCODING_PLACEHOLDER_PATH, + "ViewEncodingOtherItem", + "ViewEncodingOther", + GTK_UI_MANAGER_MENUITEM, FALSE); + + /* cleanup */ + g_list_free (related); + g_list_free (recent); + + ephy_encoding_info_free (info); menu->priv->update_tag = FALSE; - menu->priv->action_group = NULL; - menu->priv->merge_id = 0; + + STOP_PROFILER ("Rebuilding encoding menu") } static void -update_encoding_menu_cb (GtkAction *dummy, EphyEncodingMenu *menu) +encoding_activate_cb (GtkAction *action, EphyEncodingMenu *menu) { EphyEmbed *embed; - GtkAction *action = NULL; - char *encoding; + EphyEncodingInfo *info; + const char *name, *encoding; + gresult result; + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) == FALSE + || menu->priv->update_tag) + { + return; + } + + name = gtk_action_get_name (GTK_ACTION (action)); + encoding = name + strlen("Encoding"); embed = ephy_window_get_active_embed (menu->priv->window); - g_return_if_fail (embed != NULL); - ephy_embed_get_encoding (embed, &encoding); + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; - if (encoding != NULL) + /* Force only when different from current encoding */ + if (info->encoding && strcmp (info->encoding, encoding) != 0) { - char name[32]; - - g_snprintf (name, 32, "Encoding%s", encoding); - action = gtk_action_group_get_action (menu->priv->action_group, - name); + ephy_embed_set_encoding (embed, encoding); } - if (action != NULL) + ephy_encoding_info_free (info); + + ephy_encodings_add_recent (menu->priv->encodings, encoding); +} + +static void +add_action (EphyNode *node, EphyEncodingMenu *menu) +{ + GtkAction *action; + char name[128]; + const char *encoding, *title; + + encoding = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_ENCODING); + title = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_TITLE); + + g_snprintf (name, sizeof (name), "Encoding%s", encoding); + + action = g_object_new (GTK_TYPE_RADIO_ACTION, + "name", name, + "label", title, + NULL); + + gtk_radio_action_set_group (GTK_RADIO_ACTION (action), + menu->priv->encodings_radio_group); + menu->priv->encodings_radio_group = gtk_radio_action_get_group + (GTK_RADIO_ACTION (action)); + + g_signal_connect (action, "activate", + G_CALLBACK (encoding_activate_cb), + menu); + + gtk_action_group_add_action (menu->priv->action_group, action); + g_object_unref (action); +} + +static void +ephy_encoding_menu_view_dialog_cb (GtkAction *action, EphyEncodingMenu *menu) +{ + if (menu->priv->dialog == NULL) { - /* FIXME: block the "activate" signal instead; needs to wait - * until g_signal_handlers_block_matched supports blocking - * by signal id alone. - */ - menu->priv->update_tag = TRUE; - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); - menu->priv->update_tag = FALSE; + menu->priv->dialog = ephy_encoding_dialog_new + (menu->priv->window); + + g_object_add_weak_pointer(G_OBJECT (menu->priv->dialog), + (gpointer *) &menu->priv->dialog); } - else + + ephy_dialog_show (EPHY_DIALOG (menu->priv->dialog)); +} + +static void +ephy_encoding_menu_automatic_cb (GtkAction *action, EphyEncodingMenu *menu) +{ + EphyEmbed *embed; + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) == FALSE + || menu->priv->update_tag) { - g_warning ("Could not find action for encoding '%s'!\n", encoding); + return; } - g_free (encoding); + embed = ephy_window_get_active_embed (menu->priv->window); + + /* setting "" will clear the forced encoding */ + ephy_embed_set_encoding (embed, ""); } +static GtkActionEntry menu_entries [] = +{ + { "ViewEncodingOther", NULL, N_("_Other..."), NULL, + N_("Other encodings"), + G_CALLBACK (ephy_encoding_menu_view_dialog_cb) } +}; +static guint n_menu_entries = G_N_ELEMENTS (menu_entries); + +static GtkToggleActionEntry toggle_menu_entries [] = +{ + { "ViewEncodingAutomatic", NULL, N_("_Automatic"), NULL, + N_("Use the encoding specified by the document"), + G_CALLBACK (ephy_encoding_menu_automatic_cb), FALSE } +}; +static const guint n_toggle_menu_entries = G_N_ELEMENTS (toggle_menu_entries); + static void ephy_encoding_menu_set_window (EphyEncodingMenu *menu, EphyWindow *window) { GtkActionGroup *action_group; GtkAction *action; - GList *encodings, *groups, *l; - GSList *radio_group = NULL; + GList *encodings; g_return_if_fail (EPHY_IS_WINDOW (window)); @@ -186,52 +411,17 @@ ephy_encoding_menu_set_window (EphyEncodingMenu *menu, EphyWindow *window) menu->priv->manager = GTK_UI_MANAGER (window->ui_merge); action_group = gtk_action_group_new ("EncodingActions"); + gtk_action_group_set_translation_domain (action_group, NULL); menu->priv->action_group = action_group; - encodings = ephy_encodings_get_list (LG_ALL, FALSE); - for (l = encodings; l != NULL; l = l->next) - { - const EphyEncodingInfo *info = (EphyEncodingInfo *) l->data; - char name[32]; - - g_snprintf (name, 32, "Encoding%s", info->encoding); - action = g_object_new (GTK_TYPE_RADIO_ACTION, - "name", name, - "label", info->title, - NULL); - - gtk_radio_action_set_group (GTK_RADIO_ACTION (action), radio_group); - radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action)); - - g_signal_connect (action, "activate", - G_CALLBACK (ephy_encoding_menu_verb_cb), - menu); - - gtk_action_group_add_action (menu->priv->action_group, action); - g_object_unref (action); - } - - g_list_foreach (encodings, (GFunc) ephy_encoding_info_free, NULL); - g_list_free (encodings); + gtk_action_group_add_actions (action_group, menu_entries, + n_menu_entries, menu); + gtk_action_group_add_toggle_actions (action_group, toggle_menu_entries, + n_toggle_menu_entries, menu); - groups = ephy_lang_get_group_list (); - for (l = groups; l != NULL; l = l->next) - { - const EphyLanguageGroupInfo *info = (EphyLanguageGroupInfo *) l->data; - char name[32]; - - g_snprintf (name, 32, "EncodingGroup%d", info->group); - - action = g_object_new (GTK_TYPE_ACTION, - "name", name, - "label", info->title, - NULL); - gtk_action_group_add_action (menu->priv->action_group, action); - g_object_unref (action); - } - - g_list_foreach (groups, (GFunc) ephy_lang_group_info_free, NULL); - g_list_free (groups); + encodings = ephy_encodings_get_encodings (menu->priv->encodings, LG_ALL); + g_list_foreach (encodings, (GFunc) add_action, menu); + g_list_free (encodings); gtk_ui_manager_insert_action_group (menu->priv->manager, action_group, 0); @@ -239,14 +429,9 @@ ephy_encoding_menu_set_window (EphyEncodingMenu *menu, EphyWindow *window) action = gtk_ui_manager_get_action (menu->priv->manager, "/menubar/ViewMenu"); - if (action != NULL) - { - g_signal_connect_object (action, "activate", - G_CALLBACK (update_encoding_menu_cb), - menu, 0); - } - - ephy_encoding_menu_rebuild (menu); + g_signal_connect_object (action, "activate", + G_CALLBACK (update_encoding_menu_cb), + menu, 0); } static void @@ -282,12 +467,26 @@ ephy_encoding_menu_get_property (GObject *object, } static void +ephy_encoding_menu_finalize (GObject *object) +{ + EphyEncodingMenu *menu = EPHY_ENCODING_MENU (object); + + if (menu->priv->dialog) + { + g_object_unref (menu->priv->dialog); + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void ephy_encoding_menu_class_init (EphyEncodingMenuClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); + object_class->finalize = ephy_encoding_menu_finalize; object_class->set_property = ephy_encoding_menu_set_property; object_class->get_property = ephy_encoding_menu_get_property; @@ -310,58 +509,3 @@ ephy_encoding_menu_new (EphyWindow *window) "window", window, NULL); } - -static void -ephy_encoding_menu_rebuild (EphyEncodingMenu *menu) -{ - EphyEncodingMenuPrivate *p = menu->priv; - GList *groups, *l; - - if (p->merge_id > 0) - { - gtk_ui_manager_remove_ui (p->manager, p->merge_id); - gtk_ui_manager_ensure_update (p->manager); - } - - p->merge_id = gtk_ui_manager_new_merge_id (p->manager); - - gtk_ui_manager_add_ui (p->manager, p->merge_id, ENCODING_PLACEHOLDER_PATH, - "ViewEncodingMenu", "ViewEncoding", - GTK_UI_MANAGER_MENU, FALSE); - - groups = ephy_lang_get_group_list (); - for (l = groups; l != NULL; l = l->next) - { - const EphyLanguageGroupInfo *info = (EphyLanguageGroupInfo *) l->data; - char name[32], action[36], path[128]; - GList *encodings, *enc; - - g_snprintf (action, 32, "EncodingGroup%d", info->group); - g_snprintf (name, 36, "%sMenu", action); - g_snprintf (path, 128, "%s/%s", ENCODING_MENU_PATH, name); - - gtk_ui_manager_add_ui (p->manager, p->merge_id, - ENCODING_MENU_PATH, - name, action, - GTK_UI_MANAGER_MENU, FALSE); - - encodings = ephy_encodings_get_list (info->group, FALSE); - for (enc = encodings; enc != NULL; enc = enc->next) - { - const EphyEncodingInfo *info = (EphyEncodingInfo *) enc->data; - - g_snprintf (action, 32, "Encoding%s", info->encoding); - g_snprintf (name, 36, "%sItem", action); - - gtk_ui_manager_add_ui (p->manager, p->merge_id, path, - name, action, - GTK_UI_MANAGER_MENUITEM, FALSE); - } - - g_list_foreach (encodings, (GFunc) ephy_encoding_info_free, NULL); - g_list_free (encodings); - } - - g_list_foreach (groups, (GFunc) ephy_lang_group_info_free, NULL); - g_list_free (groups); -} diff --git a/src/ephy-nautilus-view.c b/src/ephy-nautilus-view.c index 6c60be01a..fd2ec0a2d 100644 --- a/src/ephy-nautilus-view.c +++ b/src/ephy-nautilus-view.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2001, 2002 Ricardo Fernández Pascual + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persch * * 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 @@ -31,6 +33,7 @@ #include "ephy-embed-utils.h" #include "find-dialog.h" #include "print-dialog.h" +#include "ephy-encoding-dialog.h" #include "ephy-zoom.h" #include "ephy-debug.h" @@ -79,16 +82,15 @@ static void gnv_zoomable_zoom_to_fit_cb (BonoboZoomable *zoomable, static void gnv_zoomable_zoom_to_default_cb (BonoboZoomable *zoomable, EphyNautilusView *view); /* commands */ -static void gnv_cmd_set_encoding (BonoboUIComponent *uic, - EphyNautilusView *view, - const char* verbname); static void gnv_cmd_file_print (BonoboUIComponent *uic, EphyNautilusView *view, const char* verbname); static void gnv_cmd_edit_find (BonoboUIComponent *uic, EphyNautilusView *view, const char* verbname); - +static void gnv_cmd_select_encoding (BonoboUIComponent *uic, + EphyNautilusView *view, + const char* verbname); /* popups */ static EphyNautilusView *gnv_view_from_popup (EphyEmbedPopupControl*popup); @@ -131,12 +133,10 @@ static BonoboUIVerb ephy_popup_verbs [] = { BonoboUIVerb ephy_verbs [] = { BONOBO_UI_VERB ("FilePrint", (BonoboUIVerbFn) gnv_cmd_file_print), BONOBO_UI_VERB ("EditFind", (BonoboUIVerbFn) gnv_cmd_edit_find), + BONOBO_UI_VERB ("ViewEncoding", (BonoboUIVerbFn) gnv_cmd_select_encoding), BONOBO_UI_VERB_END }; -#define ENCODING_MENU_PATH "/menu/View/Encoding" - - BONOBO_CLASS_BOILERPLATE (EphyNautilusView, ephy_nautilus_view, NautilusView, NAUTILUS_TYPE_VIEW) @@ -434,11 +434,6 @@ gnv_bonobo_control_activate_cb (BonoboControl *control, gboolean state, EphyNaut p->ui = nautilus_view_set_up_ui (NAUTILUS_VIEW (view), SHARE_DIR, "nautilus-epiphany-view.xml", "EphyNautilusView"); g_return_if_fail (BONOBO_IS_UI_COMPONENT (p->ui)); - - ephy_embed_utils_build_encodings_submenu (p->ui, - ENCODING_MENU_PATH, - (BonoboUIVerbFn) gnv_cmd_set_encoding, - view); bonobo_ui_component_add_verb_list_with_data (p->ui, ephy_verbs, view); } @@ -509,23 +504,19 @@ gnv_popup_cmd_frame_in_new_window (BonoboUIComponent *uic, g_free (location); } -void -gnv_cmd_set_encoding (BonoboUIComponent *uic, - EphyNautilusView *view, - const char* verbname) +static void +gnv_cmd_select_encoding (BonoboUIComponent *uic, + EphyNautilusView *view, + const char* verbname) { - const char *encoding; - - g_return_if_fail (EPHY_IS_NAUTILUS_VIEW (view)); - - if (strncmp (verbname, "Encoding", 8) == 0) - { - encoding = verbname + 8; - - LOG ("Set encoding %s", encoding) + EphyDialog *dialog; + + dialog = EPHY_DIALOG (g_object_new (EPHY_TYPE_ENCODING_DIALOG, + "embed", view->priv->embed, + NULL)); - ephy_embed_set_encoding (view->priv->embed, encoding); - } + ephy_dialog_set_modal (dialog, TRUE); + ephy_dialog_show (dialog); } static void @@ -558,7 +549,6 @@ gnv_cmd_edit_find (BonoboUIComponent *uic, ephy_dialog_show (p->find_dialog); } - /* zoomable */ static void gnv_zoomable_set_zoom_level_cb (BonoboZoomable *zoomable, diff --git a/src/ephy-window.c b/src/ephy-window.c index 5462ae72e..c36a1c541 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti + * Copyright (C) 2000, 2001, 2002, 2003 Marco Pesenti Gritti * * 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 @@ -19,7 +19,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #include "ephy-window.h" @@ -139,7 +139,9 @@ static GtkActionEntry ephy_menu_entries [] = { { "ViewZoomNormal", GTK_STOCK_ZOOM_100, N_("_Normal Size"), NULL, N_("Use the normal text size"), G_CALLBACK (window_cmd_view_zoom_normal) }, - { "ViewEncoding", NULL, N_("_Encoding") }, + { "ViewEncoding", NULL, N_("Text _Encoding"), NULL, + N_("Change the text encoding"), + NULL }, { "ViewPageSource", EPHY_STOCK_VIEWSOURCE, N_("_Page Source"), "<control>U", N_("View the source code of the page"), G_CALLBACK (window_cmd_view_page_source) }, @@ -304,6 +306,12 @@ ephy_window_notebook_switch_page_cb (GtkNotebook *notebook, guint page_num, EphyWindow *window); +enum +{ + PROP_0, + PROP_ACTIVE_TAB +}; + static GObjectClass *parent_class = NULL; GType @@ -368,24 +376,6 @@ ephy_window_destroy (GtkObject *gtkobject) } static void -ephy_window_class_init (EphyWindowClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = ephy_window_finalize; - - widget_class->show = ephy_window_show; - - gtkobject_class->destroy = ephy_window_destroy; - - g_type_class_add_private (object_class, sizeof(EphyWindowPrivate)); -} - -static void ephy_window_selection_received_cb (GtkWidget *widget, GtkSelectionData *selection_data, guint time, EphyWindow *window) @@ -1184,6 +1174,8 @@ ephy_window_set_active_tab (EphyWindow *window, EphyTab *new_tab) action = GTK_TOGGLE_ACTION (ephy_tab_get_action (new_tab)); gtk_toggle_action_set_active (action, TRUE); + + g_object_notify (G_OBJECT (window), "active-tab"); } } @@ -1312,6 +1304,66 @@ setup_notebook (EphyWindow *window) } static void +ephy_window_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyWindow *window = EPHY_WINDOW (object); + + switch (prop_id) + { + case PROP_ACTIVE_TAB: + ephy_window_set_active_tab (window, g_value_get_object (value)); + break; + } +} + +static void +ephy_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyWindow *window = EPHY_WINDOW (object); + + switch (prop_id) + { + case PROP_ACTIVE_TAB: + g_value_set_object (value, window->priv->active_tab); + break; + } +} + +static void +ephy_window_class_init (EphyWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = ephy_window_finalize; + object_class->get_property = ephy_window_get_property; + object_class->set_property = ephy_window_set_property; + + gtkobject_class->destroy = ephy_window_destroy; + + widget_class->show = ephy_window_show; + + g_object_class_install_property (object_class, + PROP_ACTIVE_TAB, + g_param_spec_object ("active-tab", + "active-tab", + "Active tab", + EPHY_TYPE_TAB, + G_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof(EphyWindowPrivate)); +} + +static void ephy_window_init (EphyWindow *window) { Session *session; diff --git a/src/language-editor.h b/src/language-editor.h index 536d16eb8..61e22347a 100644 --- a/src/language-editor.h +++ b/src/language-editor.h @@ -20,7 +20,6 @@ #define LANGUAGE_EDITOR_H #include "ephy-dialog.h" -#include "language-editor.h" #include <gtk/gtkwidget.h> #include <glib-object.h> diff --git a/src/pdm-dialog.c b/src/pdm-dialog.c index b57cde4d4..3becb2d84 100755 --- a/src/pdm-dialog.c +++ b/src/pdm-dialog.c @@ -249,6 +249,7 @@ setup_passwords_treeview (PdmDialog *dialog) gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore), COL_PASSWORDS_HOST, GTK_SORT_ASCENDING); + g_object_unref (liststore); renderer = gtk_cell_renderer_text_new (); @@ -305,6 +306,7 @@ setup_cookies_treeview (PdmDialog *dialog) gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore), COL_COOKIES_HOST, GTK_SORT_ASCENDING); + g_object_unref (liststore); g_signal_connect (selection, "changed", G_CALLBACK(cookies_treeview_selection_changed_cb), diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c index 1b0999956..0b297374f 100644 --- a/src/prefs-dialog.c +++ b/src/prefs-dialog.c @@ -25,6 +25,8 @@ #include "prefs-dialog.h" #include "ephy-dialog.h" #include "ephy-prefs.h" +#include "ephy-embed-shell.h" +#include "ephy-shell.h" #include "ephy-embed-prefs.h" #include "ephy-embed-single.h" #include "ephy-shell.h" @@ -33,6 +35,7 @@ #include "language-editor.h" #include "ephy-langs.h" #include "ephy-encodings.h" +#include "ephy-debug.h" #include <bonobo/bonobo-i18n.h> #include <gtk/gtkframe.h> @@ -148,27 +151,6 @@ languages [] = }; static guint n_languages = G_N_ELEMENTS (languages); -typedef struct -{ - gchar *title; - gchar *name; -} EncodingAutodetectorInfo; - -static EncodingAutodetectorInfo encoding_autodetector[] = -{ - { N_("Off"), "" }, - { N_("Chinese"), "zh_parallel_state_machine" }, - { N_("East Asian"), "cjk_parallel_state_machine" }, - { N_("Japanese"), "ja_parallel_state_machine" }, - { N_("Korean"), "ko_parallel_state_machine" }, - { N_("Russian"), "ruprob" }, - { N_("Simplified Chinese"), "zhcn_parallel_state_machine" }, - { N_("Traditional Chinese"), "zhtw_parallel_state_machine" }, - { N_("Universal"), "universal_charset_detector" }, - { N_("Ukrainian"), "ukprob" } -}; -static guint n_encoding_autodetectors = G_N_ELEMENTS (encoding_autodetector); - static const char *cookies_accept_enum [] = { @@ -267,8 +249,8 @@ EphyDialogProperty properties [] = { DISK_CACHE_PROP, "disk_cache_spin", CONF_NETWORK_CACHE_SIZE, PT_AUTOAPPLY, NULL }, /* Languages */ - { AUTO_ENCODING_PROP, "auto_encoding_optionmenu", NULL, PT_NORMAL, NULL }, - { DEFAULT_ENCODING_PROP, "default_encoding_optionmenu", NULL, PT_NORMAL, NULL }, + { AUTO_ENCODING_PROP, "auto_encoding_optionmenu", CONF_LANGUAGE_AUTODETECT_ENCODING, PT_AUTOAPPLY, NULL }, + { DEFAULT_ENCODING_PROP, "default_encoding_optionmenu", CONF_LANGUAGE_DEFAULT_ENCODING, PT_AUTOAPPLY, NULL }, { LANGUAGE_PROP, "language_optionmenu", NULL, PT_NORMAL, NULL }, { LANGUAGE_LABEL_PROP, "language_label", NULL, PT_NORMAL, NULL }, { DEFAULT_ENCODING_LABEL_PROP, "default_encoding_label", NULL, PT_NORMAL, NULL }, @@ -301,8 +283,6 @@ struct PrefsDialogPrivate GtkWidget *window; GList *langs; - GList *encodings; - GList *autodetectors; GList *fonts_languages; guint language; @@ -383,12 +363,6 @@ prefs_dialog_finalize (GObject *object) g_list_foreach (pd->priv->langs, (GFunc) free_lang_item, NULL); g_list_free (pd->priv->langs); - g_list_foreach (pd->priv->encodings, (GFunc) ephy_encoding_info_free, NULL); - g_list_free (pd->priv->encodings); - - g_list_foreach (pd->priv->autodetectors, (GFunc) g_free, NULL); - g_list_free (pd->priv->autodetectors); - g_list_foreach (pd->priv->fonts_languages, (GFunc) g_free, NULL); g_list_free (pd->priv->fonts_languages); @@ -415,15 +389,15 @@ prefs_dialog_show_help (PrefsDialog *pd) ephy_gui_help (GTK_WINDOW (pd->priv->window), "epiphany", help_preferences[id]); } -static const gchar * +static const char * get_current_language_code (PrefsDialog *dialog) { GList *lang; - const FontsLanguageInfo *info; + const EphyFontsLanguageInfo *info; lang = g_list_nth (dialog->priv->fonts_languages, dialog->priv->language); g_assert (lang != NULL); - info = (FontsLanguageInfo *) lang->data; + info = (EphyFontsLanguageInfo *) lang->data; return info->code; } @@ -648,24 +622,47 @@ setup_fonts (PrefsDialog *dialog) dialog->priv->switching = FALSE; } +static int +fonts_language_info_cmp (const EphyFontsLanguageInfo *i1, + const EphyFontsLanguageInfo *i2) +{ + return g_utf8_collate (i1->title, i2->title); +} + static void create_fonts_language_menu (PrefsDialog *dialog) { GtkWidget *optionmenu, *menu; - GList *l = NULL; - guint n_fonts_languages, i = 0; + GList *list = NULL, *l; + guint n_fonts_languages, i; char **lang_codes; + const EphyFontsLanguageInfo *fonts_languages; optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog), FONTS_LANGUAGE_PROP); menu = gtk_menu_new (); - dialog->priv->fonts_languages = ephy_font_langs_get_list (); - n_fonts_languages = g_list_length (dialog->priv->fonts_languages); + fonts_languages = ephy_font_languages (); + n_fonts_languages = ephy_font_n_languages (); + + for (i = 0; i < n_fonts_languages; i++) + { + EphyFontsLanguageInfo *info; + + info = g_new0 (EphyFontsLanguageInfo, 1); + info->title = _(fonts_languages[i].title); + info->code = fonts_languages[i].code; + + list = g_list_prepend (list, info); + } + + dialog->priv->fonts_languages = + g_list_sort (list, (GCompareFunc) fonts_language_info_cmp); + for (l = dialog->priv->fonts_languages; l != NULL; l = l->next) { - FontsLanguageInfo *info = (FontsLanguageInfo *) l->data; + EphyFontsLanguageInfo *info = (EphyFontsLanguageInfo *) l->data; GtkWidget *item; item = gtk_menu_item_new_with_label (info->title); @@ -676,12 +673,12 @@ create_fonts_language_menu (PrefsDialog *dialog) gtk_option_menu_set_menu (GTK_OPTION_MENU(optionmenu), menu); lang_codes = g_new0 (char *, n_fonts_languages); - for (l = dialog->priv->fonts_languages; l != NULL; l = l->next) + for (l = dialog->priv->fonts_languages, i=0; l != NULL; l = l->next) { - FontsLanguageInfo *info = (FontsLanguageInfo *) l->data; + EphyFontsLanguageInfo *info = (EphyFontsLanguageInfo *) l->data; lang_codes[i] = info->code; - + i++; } ephy_dialog_add_enum (EPHY_DIALOG (dialog), FONTS_LANGUAGE_PROP, @@ -697,160 +694,97 @@ create_fonts_language_menu (PrefsDialog *dialog) dialog); } -static void -default_encoding_menu_changed_cb (GtkOptionMenu *option_menu, - PrefsDialog *dialog) +static int +find_encoding_in_list_cmp (gconstpointer info, const char *encoding) { - GList *encoding; - gint i; - const EphyEncodingInfo *info; + EphyNode *node = (EphyNode *) info; + const char *code; - i = gtk_option_menu_get_history (option_menu); - encoding = g_list_nth (dialog->priv->encodings, i); - g_assert (encoding != NULL); + code = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_ENCODING); - info = (EphyEncodingInfo *) encoding->data; - eel_gconf_set_string (CONF_LANGUAGE_DEFAULT_ENCODING, info->encoding); + return strcmp (code, encoding); } -static gint -find_encoding_in_list_cmp (const EphyEncodingInfo *info, const char *encoding) +static int +sort_encodings (gconstpointer a, gconstpointer b) { - return strcmp (info->encoding, encoding); + EphyNode *node1 = (EphyNode *) a; + EphyNode *node2 = (EphyNode *) b; + const char *key1, *key2; + + key1 = ephy_node_get_property_string + (node1, EPHY_NODE_ENCODING_PROP_COLLATION_KEY); + key2 = ephy_node_get_property_string + (node2, EPHY_NODE_ENCODING_PROP_COLLATION_KEY); + + return strcmp (key1, key2); } static void -create_default_encoding_menu (PrefsDialog *dialog) +create_optionmenu (PrefsDialog *dialog, + int property, + GList *list, + const char *key, + const char *default_value) { - GList *l; + GList *element, *l; GtkWidget *menu, *optionmenu; - gchar *encoding; + char *value; + char **codes; + guint pos, i, num; menu = gtk_menu_new (); optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog), - DEFAULT_ENCODING_PROP); - - dialog->priv->encodings = ephy_encodings_get_list (LG_ALL, TRUE); - for (l = dialog->priv->encodings; l != NULL; l = l->next) - { - const EphyEncodingInfo *info = (EphyEncodingInfo *) l->data; - GtkWidget *item; - - item = gtk_menu_item_new_with_label (info->title); - gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); - gtk_widget_show (item); - } + property); - gtk_option_menu_set_menu (GTK_OPTION_MENU(optionmenu), menu); + list = g_list_sort (list, (GCompareFunc) sort_encodings); - /* init value */ - encoding = eel_gconf_get_string (CONF_LANGUAGE_DEFAULT_ENCODING); - /* fallback */ - if (encoding == NULL) encoding = g_strdup ("ISO-8859-1"); + num = g_list_length (list); + codes = g_new0 (char *, num); - l = g_list_find_custom (dialog->priv->encodings, encoding, - (GCompareFunc) find_encoding_in_list_cmp); - gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu), - g_list_position (dialog->priv->encodings, l)); - g_free (encoding); - - g_signal_connect (optionmenu, "changed", - G_CALLBACK (default_encoding_menu_changed_cb), - dialog); -} - -static void -autodetect_encoding_menu_changed_cb (GtkOptionMenu *option_menu, gpointer data) -{ - GList *l; - guint i; - EncodingAutodetectorInfo *info; - - g_return_if_fail (EPHY_IS_PREFS_DIALOG (data)); - - i = gtk_option_menu_get_history (option_menu); - - l = g_list_nth (EPHY_PREFS_DIALOG (data)->priv->autodetectors, i); - - if (l) - { - info = (EncodingAutodetectorInfo *) l->data; - - eel_gconf_set_string (CONF_LANGUAGE_AUTODETECT_ENCODING, info->name); - } -} - -static gint -autodetector_info_cmp (const EncodingAutodetectorInfo *i1, const EncodingAutodetectorInfo *i2) -{ - return g_utf8_collate (i1->title, i2->title); -} - -static gint -find_autodetector_info (const EncodingAutodetectorInfo *info, const gchar *name) -{ - return strcmp (info->name, name); -} - -static void -create_encoding_autodetectors_menu (PrefsDialog *dialog) -{ - GtkWidget *optionmenu, *menu, *item; - gint i, position = 0; - GList *l, *list = NULL; - gchar *detector = NULL; - EncodingAutodetectorInfo *info; - - optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog), - AUTO_ENCODING_PROP); - - for (i = 0; i < n_encoding_autodetectors; i++) + for (l = list, i=0; l != NULL; l = l->next, i++) { - info = g_new0 (EncodingAutodetectorInfo, 1); - - info->title = _(encoding_autodetector[i].title); - info->name = encoding_autodetector[i].name; - - list = g_list_prepend (list, info); - } - - list = g_list_sort (list, (GCompareFunc) autodetector_info_cmp); - dialog->priv->autodetectors = list; - - menu = gtk_menu_new (); + EphyNode *node = (EphyNode *) l->data; + const char *title, *code; + GtkWidget *item; - for (l = list; l != NULL; l = l->next) - { - info = (EncodingAutodetectorInfo *) l->data; + title = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_TITLE_ELIDED); - item = gtk_menu_item_new_with_label (info->title); + item = gtk_menu_item_new_with_label (title); gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); gtk_widget_show (item); - g_object_set_data (G_OBJECT (item), "desc", info->title); + + code = ephy_node_get_property_string + (node, EPHY_NODE_ENCODING_PROP_ENCODING); + codes[i] = (char *) code; } gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu); /* init value */ - detector = eel_gconf_get_string (CONF_LANGUAGE_AUTODETECT_ENCODING); - if (detector == NULL) detector = g_strdup (""); - - l = g_list_find_custom (list, detector, - (GCompareFunc) find_autodetector_info); - - g_free (detector); - - if (l) + value = eel_gconf_get_string (key); + /* fallback */ + if (value == NULL || value[0] == '\0') { - position = g_list_position (list, l); + g_free (value); + value = g_strdup (default_value); } - gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu), position); + element = g_list_find_custom (list, value, + (GCompareFunc) find_encoding_in_list_cmp); + g_free (value); + pos = g_list_position (list, element); - g_signal_connect (optionmenu, "changed", - G_CALLBACK (autodetect_encoding_menu_changed_cb), - dialog); + ephy_dialog_add_enum (EPHY_DIALOG (dialog), property, + num, (const char **) codes); + + gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu), pos); + + /* the entries themselves are const, so we don't use g_strfreev here */ + g_free (codes); } static gint @@ -1033,7 +967,9 @@ static void prefs_dialog_init (PrefsDialog *pd) { EphyDialog *dialog = EPHY_DIALOG (pd); + EphyEncodings *encodings; GdkPixbuf *icon; + GList *list; pd->priv = EPHY_PREFS_DIALOG_GET_PRIVATE (pd); @@ -1051,8 +987,6 @@ prefs_dialog_init (PrefsDialog *pd) pd->priv->window = ephy_dialog_get_control (dialog, WINDOW_PROP); pd->priv->notebook = ephy_dialog_get_control (dialog, NOTEBOOK_PROP); pd->priv->langs = NULL; - pd->priv->encodings = NULL; - pd->priv->autodetectors = NULL; pd->priv->fonts_languages = NULL; icon = gtk_widget_render_icon (pd->priv->window, @@ -1067,8 +1001,20 @@ prefs_dialog_init (PrefsDialog *pd) attach_fonts_signals (pd); attach_size_controls_signals (pd); create_languages_list (pd); - create_default_encoding_menu (pd); - create_encoding_autodetectors_menu (pd); + + encodings = EPHY_ENCODINGS (ephy_embed_shell_get_encodings + (EPHY_EMBED_SHELL (ephy_shell))); + + list = ephy_encodings_get_encodings (encodings, LG_ALL); + create_optionmenu (pd, DEFAULT_ENCODING_PROP, list, + CONF_LANGUAGE_DEFAULT_ENCODING, "ISO-8859-1"); + g_list_free (list); + + list = ephy_encodings_get_detectors (encodings); + create_optionmenu (pd, AUTO_ENCODING_PROP, list, + CONF_LANGUAGE_AUTODETECT_ENCODING, ""); + g_list_free (list); + create_language_menu (pd); } |