/*
* Copyright © 2000 Nate Case
* Copyright © 2000-2004 Marco Pesenti Gritti
* Copyright © 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id$
*/
#include "mozilla-config.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib/gi18n.h>
#include <gdk/gdkx.h>
#include <gtk/gtksettings.h>
#include <nsCOMPtr.h>
#include <nsIPrefService.h>
#include <nsIServiceManager.h>
#include <nsMemory.h>
#include <nsServiceManagerUtils.h>
#include "eel-gconf-extensions.h"
#include "ephy-debug.h"
#include "ephy-embed-prefs.h"
#include "ephy-embed-shell.h"
#include "ephy-encodings.h"
#include "ephy-langs.h"
#include "ephy-node.h"
#include "ephy-prefs.h"
#include "mozilla-notifiers.h"
/* define to migrate epiphany 1.0 font preferences */
#define MIGRATE_PIXEL_SIZE
#define MAX_FONT_SIZE 128
/* Keeps the list of the notifiers we installed for mozilla prefs */
/* to be able to remove them when exiting */
static GList *notifiers = NULL;
static nsIPrefBranch *gPrefBranch;
typedef struct
{
char *gconf_key;
char *mozilla_pref;
PrefValueTransformFunc func;
gpointer user_data;
guint cnxn_id;
} PrefData;
static void
free_pref_data (PrefData *data)
{
g_free (data->gconf_key);
g_free (data->mozilla_pref);
g_slice_free (PrefData, data);
}
static gboolean
transform_accept_languages_list (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
GArray *array;
GSList *languages, *l;
char **langs;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_LIST ||
gconf_value_get_list_type (gcvalue) != GCONF_VALUE_STRING) return FALSE;
languages = gconf_value_get_list (gcvalue);
array = g_array_new (TRUE, FALSE, sizeof (char *));
for (l = languages; l != NULL; l = l->next)
{
const char *lang;
lang = gconf_value_get_string ((GConfValue *) l->data);
if (lang != NULL && strcmp (lang, "system") == 0)
{
ephy_langs_append_languages (array);
}
else if (lang != NULL && lang[0] != '\0')
{
char *str;
str = g_ascii_strdown (lang, -1);
g_array_append_val (array, str);
}
}
ephy_langs_sanitise (array);
langs = (char **) g_array_free (array, FALSE);
g_value_init (value, G_TYPE_STRING);
g_value_take_string (value, g_strjoinv (",", langs));
g_strfreev (langs);
return TRUE;
}
static gboolean
transform_cache_size (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_INT) return FALSE;
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, gconf_value_get_int (gcvalue) * 1024);
return TRUE;
}
static gboolean
transform_cookies_accept_mode (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
const char *mode;
int mozilla_mode = 0;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING) return FALSE;
mode = gconf_value_get_string (gcvalue);
if (mode == NULL) return FALSE;
if (strcmp (mode, "anywhere") == 0)
{
mozilla_mode = 0;
}
else if (strcmp (mode, "current site") == 0)
{
mozilla_mode = 1;
}
else if (strcmp (mode, "nowhere") == 0)
{
mozilla_mode = 2;
}
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, mozilla_mode);
return TRUE;
}
static gboolean
transform_encoding (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
EphyEncodings *encodings;
EphyNode *node;
const char *code;
gboolean is_autodetector;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING) return FALSE;
code = gconf_value_get_string (gcvalue);
if (code == NULL) return FALSE;
encodings = EPHY_ENCODINGS (ephy_embed_shell_get_encodings (embed_shell));
node = ephy_encodings_get_node (encodings, code, FALSE);
if (node == NULL) return FALSE;
is_autodetector = ephy_node_get_property_boolean (node, EPHY_NODE_ENCODING_PROP_IS_AUTODETECTOR);
if (is_autodetector != GPOINTER_TO_INT (user_data)) return FALSE;
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, code);
return TRUE;
}
static gboolean
transform_image_animation_mode (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
const char *mode;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING) return FALSE;
mode = gconf_value_get_string (gcvalue);
if (mode == NULL) return FALSE;
if (strcmp (mode, "disabled") == 0)
{
mode = "none";
}
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, mode);
return TRUE;
}
static gboolean
transform_proxy_ignore_list (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
GArray *array;
GSList *hosts, *l;
char **strings;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_LIST ||
gconf_value_get_list_type (gcvalue) != GCONF_VALUE_STRING) return FALSE;
hosts = gconf_value_get_list (gcvalue);
array = g_array_new (TRUE, FALSE, sizeof (char *));
for (l = hosts; l != NULL; l = l->next)
{
const char *host;
host = gconf_value_get_string ((GConfValue *) l->data);
if (host != NULL && host[0] != '\0')
{
g_array_append_val (array, host);
}
}
strings = (char **) g_array_free (array, FALSE);
g_value_init (value, G_TYPE_STRING);
g_value_take_string (value, g_strjoinv (",", strings));
/* the strings themselves are const */
g_free (strings);
return TRUE;
}
static gboolean
transform_proxy_mode (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
const char *mode;
int mozilla_mode = 0;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING) return FALSE;
mode = gconf_value_get_string (gcvalue);
if (mode == NULL) return FALSE;
if (strcmp (mode, "manual") == 0)
{
mozilla_mode = 1;
}
else if (strcmp (mode, "auto") == 0)
{
mozilla_mode = 2;
}
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, mozilla_mode);
return TRUE;
}
static gboolean
transform_use_own_fonts (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, gconf_value_get_bool (gcvalue) ? 0 : 1);
return TRUE;
}
extern "C" gboolean
mozilla_notifier_transform_bool (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, gconf_value_get_bool (gcvalue));
return TRUE;
}
extern "C" gboolean
mozilla_notifier_transform_bool_invert (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, !gconf_value_get_bool (gcvalue));
return TRUE;
}
extern "C" gboolean
mozilla_notifier_transform_int (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_INT) return FALSE;
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, gconf_value_get_int (gcvalue));
return TRUE;
}
extern "C" gboolean
mozilla_notifier_transform_string (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
GConfValue *gcvalue;
const char *str;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING) return FALSE;
str = gconf_value_get_string (gcvalue);
if (str == NULL) return FALSE;
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
return TRUE;
}
static const PrefData notifier_entries[] =
{
{ CONF_BROWSE_WITH_CARET,
"accessibility.browsewithcaret",
mozilla_notifier_transform_bool },
{ CONF_NETWORK_CACHE_SIZE,
"browser.cache.disk.capacity",
transform_cache_size },
{ CONF_RENDERING_USE_OWN_COLORS,
"browser.display.use_document_colors",
mozilla_notifier_transform_bool_invert },
{ CONF_RENDERING_USE_OWN_FONTS,
"browser.display.use_document_fonts",
transform_use_own_fonts },
{ CONF_SECURITY_ALLOW_POPUPS,
"dom.disable_open_during_load",
mozilla_notifier_transform_bool_invert },
{ CONF_DISPLAY_SMOOTHSCROLL,
"general.smoothScroll",
mozilla_notifier_transform_bool },
{ CONF_IMAGE_ANIMATION_MODE,
"image.animation_mode",
transform_image_animation_mode },
{ CONF_RENDERING_LANGUAGE,
"intl.accept_languages",
transform_accept_languages_list },
{ CONF_LANGUAGE_DEFAULT_ENCODING,
"intl.charset.default",
transform_encoding,
GINT_TO_POINTER (FALSE) },
{ CONF_LANGUAGE_AUTODETECT_ENCODING,
"intl.charset.detector",
transform_encoding,
GINT_TO_POINTER (TRUE) },
{ CONF_SECURITY_JAVA_ENABLED,
"security.enable_java",
mozilla_notifier_transform_bool },
{ CONF_SECURITY_JAVASCRIPT_ENABLED,
"javascript.enabled",
mozilla_notifier_transform_bool },
{ CONF_NETWORK_PROXY_AUTO_URL,
"network.proxy.autoconfig_url",
mozilla_notifier_transform_string },
{ CONF_NETWORK_HTTP_PROXY,
"network.proxy.http",
mozilla_notifier_transform_string },
{ CONF_NETWORK_HTTP_PROXY_PORT,
"network.proxy.http_port",
mozilla_notifier_transform_int },
{ CONF_NETWORK_FTP_PROXY,
"network.proxy.ftp",
mozilla_notifier_transform_string },
{ CONF_NETWORK_FTP_PROXY_PORT,
"network.proxy.ftp_port",
mozilla_notifier_transform_int },
{ CONF_NETWORK_SSL_PROXY,
"network.proxy.ssl",
mozilla_notifier_transform_string },
{ CONF_NETWORK_SSL_PROXY_PORT,
"network.proxy.ssl_port",
mozilla_notifier_transform_int },
{ CONF_NETWORK_SOCKS_PROXY,
"network.proxy.socks",
mozilla_notifier_transform_string },
{ CONF_NETWORK_SOCKS_PROXY_PORT,
"network.proxy.socks_port",
mozilla_notifier_transform_int },
{ CONF_NETWORK_PROXY_IGNORE_HOSTS,
"network.proxy.no_proxies_on",
transform_proxy_ignore_list },
{ CONF_NETWORK_PROXY_MODE,
"network.proxy.type",
transform_proxy_mode },
{ CONF_SECURITY_COOKIES_ACCEPT,
"network.cookie.cookieBehavior",
transform_cookies_accept_mode },
{ CONF_PRIVACY_REMEMBER_PASSWORDS,
"signon.rememberSignons",
mozilla_notifier_transform_bool }
};
gboolean
mozilla_pref_set (const char *pref,
const GValue *value)
{
NS_ENSURE_TRUE (gPrefBranch, FALSE);
g_return_val_if_fail (pref != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
nsresult rv;
PRInt32 prefType;
rv = gPrefBranch->GetPrefType (pref, &prefType);
if (NS_FAILED (rv))
{
/* probably just an unset pref */
prefType = nsIPrefBranch::PREF_INVALID;
rv = NS_OK;
}
switch (G_VALUE_TYPE (value))
{
case G_TYPE_INT:
{
if (prefType != nsIPrefBranch::PREF_INT &&
prefType != nsIPrefBranch::PREF_INVALID)
break;
PRInt32 old_value = 0;
PRInt32 new_value = g_value_get_int (value);
rv = gPrefBranch->GetIntPref (pref, &old_value);
if (NS_FAILED (rv) || old_value != new_value)
{
rv = gPrefBranch->SetIntPref (pref, new_value);
}
break;
}
case G_TYPE_BOOLEAN:
{
if (prefType != nsIPrefBranch::PREF_BOOL &&
prefType != nsIPrefBranch::PREF_INVALID)
break;
PRBool old_value = PR_FALSE;
PRBool new_value = g_value_get_boolean (value);
rv = gPrefBranch->GetBoolPref (pref, &old_value);
if (NS_FAILED (rv) || old_value != new_value)
{
rv = gPrefBranch->SetBoolPref (pref, new_value);
}
break;
}
case G_TYPE_STRING:
{
if (prefType != nsIPrefBranch::PREF_STRING &&
prefType != nsIPrefBranch::PREF_INVALID)
break;
const char *new_value = g_value_get_string (value);
if (new_value == NULL)
{
rv = gPrefBranch->ClearUserPref (pref);
}
else
{
char *old_value = nsnull;
rv = gPrefBranch->GetCharPref (pref, &old_value);
if (NS_FAILED (rv) ||
old_value == nsnull ||
strcmp (old_value, new_value) != 0)
{
rv = gPrefBranch->SetCharPref (pref, new_value);
}
if (old_value)
{
nsMemory::Free (old_value);
}
}
break;
}
default:
g_return_val_if_reached (FALSE);
rv = NS_ERROR_FAILURE;
break;
}
return NS_SUCCEEDED (rv) != PR_FALSE;
}
static void
notify_cb (GConfClient *client,
guint cnxn_id,
GConfEntry *gcentry,
PrefData *data)
{
GValue value = { 0, };
g_return_if_fail (gcentry != NULL);
g_assert (data != NULL);
if (data->func (gcentry, &value, data->user_data))
{
mozilla_pref_set (data->mozilla_pref, &value);
g_value_unset (&value);
}
else
{
/* Reset the pref */
NS_ENSURE_TRUE (gPrefBranch, );
gPrefBranch->ClearUserPref (data->mozilla_pref);
}
}
extern "C" guint
mozilla_notifier_add (const char *gconf_key,
const char *mozilla_pref,
PrefValueTransformFunc func,
gpointer user_data)
{
GConfClient *client;
PrefData *data;
GError *error = NULL;
guint cnxn_id;
g_return_val_if_fail (gconf_key != NULL, 0);
g_return_val_if_fail (mozilla_pref != NULL, 0);
g_return_val_if_fail (func, 0);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, 0);
data = g_slice_new (PrefData);
data->gconf_key = g_strdup (gconf_key);
data->mozilla_pref = g_strdup (mozilla_pref);
data->func = func;
data->user_data = user_data;
cnxn_id = gconf_client_notify_add (client, gconf_key,
(GConfClientNotifyFunc) notify_cb,
data, (GFreeFunc) free_pref_data,
&error);
if (eel_gconf_handle_error (&error))
{
if (cnxn_id != EEL_GCONF_UNDEFINED_CONNECTION)
{
gconf_client_notify_remove (client, cnxn_id);
}
return 0;
}
data->cnxn_id = cnxn_id;
notifiers = g_list_prepend (notifiers, data);
gconf_client_notify (client, gconf_key);
return cnxn_id;
}
static int
find_data (const PrefData *a,
gconstpointer idptr)
{
return a->cnxn_id != GPOINTER_TO_UINT (idptr);
}
extern "C" void
mozilla_notifier_remove (guint id)
{
GList *l;
g_return_if_fail (id != 0);
l = g_list_find_custom (notifiers, GUINT_TO_POINTER (id),
(GCompareFunc) find_data);
g_return_if_fail (l != NULL);
notifiers = g_list_delete_link (notifiers, l);
eel_gconf_notification_remove (id);
}
#ifdef MIGRATE_PIXEL_SIZE
#define INT_ROUND(a) gint((a) + 0.5f)
/**
* This function gets the dpi in the same way that mozilla gets the dpi,
* this allows us to convert from pixels to points easily
*/
static gint
mozilla_get_dpi ()
{
GtkSettings* settings = gtk_settings_get_default ();
gint dpi = 0;
/* Use the gdk-xft-dpi setting if it is set */
if (g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (settings)),
"gtk-xft-dpi"))
{
g_object_get (G_OBJECT (settings), "gtk-xft-dpi", &dpi, (char *) NULL);
if (dpi) return INT_ROUND (dpi / PANGO_SCALE);
}
/* Fall back to what xft thinks it is */
char *val = XGetDefault (GDK_DISPLAY (), "Xft", "dpi");
if (val)
{
char *e;
double d = strtod(val, &e);
if (e != val) return INT_ROUND (d);
}
/* Fall back to calculating manually from the gdk screen settings */
float screenWidthIn = float (gdk_screen_width_mm()) / 25.4f;
return INT_ROUND (gdk_screen_width() / screenWidthIn);
}
static void
migrate_font_gconf_key (const char *pixel_key,
const char *point_key)
{
int size;
size = eel_gconf_get_integer (pixel_key);
if (size > 0)
{
/* Use doubles to get more accurate arithmetic */
double dpi = (double) mozilla_get_dpi ();
double value = (double) eel_gconf_get_integer (pixel_key);
gint point = INT_ROUND ((value * 72) / dpi);
eel_gconf_set_integer (point_key, point);
}
}
#endif
static gboolean
parse_pango_font (const char *font,
char **name,
int *size)
{
PangoFontMask mask = (PangoFontMask) (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
PangoFontDescription *desc = pango_font_description_from_string (font);
if (desc == NULL) return FALSE;
if ((pango_font_description_get_set_fields (desc) & mask) != mask)
{
pango_font_description_free (desc);
return FALSE;
}
*size = PANGO_PIXELS (pango_font_description_get_size (desc));
*name = g_strdup (pango_font_description_get_family (desc));
pango_font_description_free (desc);
LOG ("Parsed pango font description '%s' -> name:%s, size:%d",
font, *name ? *name : "-", *size);
return *name != NULL && *size > 0;
}
typedef struct
{
guint cnxn_id;
char **font_name_prefs;
char **font_size_prefs;
char *font_name;
int font_size;
} DesktopFontData;
static gboolean
transform_font_name (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
DesktopFontData *data = (DesktopFontData *) user_data;
GConfValue *gcvalue;
const char *font_name;
gcvalue = gconf_entry_get_value (gcentry);
if (gconf_entry_get_is_default (gcentry) ||
gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_STRING)
{
font_name = data->font_name;
}
else
{
font_name = gconf_value_get_string (gcvalue);
if ((font_name == NULL || font_name[0] == '\0'))
{
font_name = data->font_name;
}
}
LOG ("%s value for key '%s'",
gconf_entry_get_is_default (gcentry) ? "default" : "NON-default",
gconf_entry_get_key (gcentry));
if (font_name == NULL) return FALSE;
LOG ("Inferred font name '%s' for key '%s'",
font_name, gconf_entry_get_key (gcentry));
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, font_name);
return TRUE;
}
static gboolean
transform_font_size (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
DesktopFontData *data = (DesktopFontData *) user_data;
GConfValue *gcvalue;
int size = 0;
gcvalue = gconf_entry_get_value (gcentry);
if (gconf_entry_get_is_default (gcentry) ||
gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_INT)
{
size = data->font_size;
}
else
{
size = gconf_value_get_int (gcvalue);
}
if (size <= 0 || size > MAX_FONT_SIZE) return FALSE;
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, size);
return TRUE;
}
static void
notify_desktop_font_cb (GConfClient *client,
guint cnxn_id,
GConfEntry *gcentry,
DesktopFontData *data)
{
GConfValue *gcvalue;
char *name = NULL;
int size = 0, i;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue != NULL &&
gcvalue->type == GCONF_VALUE_STRING &&
parse_pango_font (gconf_value_get_string (gcvalue), &name, &size))
{
LOG ("Desktop font %s -> name=%s, size=%d",
gconf_entry_get_key (gcentry), name, size);
g_free (data->font_name);
data->font_name = name;
data->font_size = size;
}
else
{
g_free (name);
g_free (data->font_name);
data->font_name = NULL;
data->font_size = 0;
}
for (i = 0; data->font_name_prefs[i] != NULL; ++i)
{
gconf_client_notify (client, data->font_name_prefs[i]);
}
for (i = 0; data->font_size_prefs[i] != NULL; ++i)
{
gconf_client_notify (client, data->font_size_prefs[i]);
}
}
typedef struct
{
guint cnxn_id;
char **prefs;
int size;
} MinimumFontSizeData;
static gboolean
transform_minimum_font_size (GConfEntry *gcentry,
GValue *value,
gpointer user_data)
{
MinimumFontSizeData *data = (MinimumFontSizeData *) user_data;
GConfValue *gcvalue;
int size = 0;
gcvalue = gconf_entry_get_value (gcentry);
if (gcvalue == NULL ||
gcvalue->type != GCONF_VALUE_INT)
{
size = data->size;
}
else
{
size = MAX (gconf_value_get_int (gcvalue),
data->size);
}
if (size <= 0) return FALSE;
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, size);
return TRUE;
}
static void
notify_minimum_size_cb (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
MinimumFontSizeData *data)
{
GConfValue *gcvalue;
int i;
data->size = 0;
gcvalue = gconf_entry_get_value (entry);
/* happens on initial notify if the key doesn't exist */
if (gcvalue != NULL &&
gcvalue->type == GCONF_VALUE_INT)
{
data->size = gconf_value_get_int (gcvalue);
data->size = MAX (data->size, 0);
}
LOG ("Minimum font size now %d", data->size);
for (i = 0; data->prefs[i] != NULL; ++i)
{
gconf_client_notify (client, data->prefs[i]);
}
}
static DesktopFontData *desktop_font_data;
static MinimumFontSizeData *minimum_font_size_data;
static void
mozilla_font_notifiers_init (void)
{
static const char *types [] = { "variable", "monospace" };
const EphyFontsLanguageInfo *font_languages;
guint n_font_languages, i;
eel_gconf_monitor_add ("/desktop/gnome/interface");
font_languages = ephy_font_languages ();
n_font_languages = ephy_font_n_languages ();
desktop_font_data = g_new0 (DesktopFontData, 2);
desktop_font_data[0].font_name_prefs = g_new0 (char*, n_font_languages + 1);
desktop_font_data[0].font_size_prefs = g_new0 (char*, n_font_languages + 1);
desktop_font_data[1].font_name_prefs = g_new0 (char*, n_font_languages + 1);
desktop_font_data[1].font_size_prefs = g_new0 (char*, n_font_languages + 1);
desktop_font_data[0].cnxn_id =
eel_gconf_notification_add (CONF_DESKTOP_FONT_VARIABLE,
(GConfClientNotifyFunc) notify_desktop_font_cb,
&desktop_font_data[0]);
eel_gconf_notify (CONF_DESKTOP_FONT_VARIABLE);
desktop_font_data[1].cnxn_id =
eel_gconf_notification_add (CONF_DESKTOP_FONT_MONOSPACE,
(GConfClientNotifyFunc) notify_desktop_font_cb,
&desktop_font_data[1]);
eel_gconf_notify (CONF_DESKTOP_FONT_MONOSPACE);
minimum_font_size_data = g_new0 (MinimumFontSizeData, 1);
minimum_font_size_data->prefs = g_new0 (char*, n_font_languages + 1);
minimum_font_size_data->cnxn_id =
eel_gconf_notification_add (CONF_RENDERING_FONT_MIN_SIZE,
(GConfClientNotifyFunc) notify_minimum_size_cb,
minimum_font_size_data);
eel_gconf_notify (CONF_RENDERING_FONT_MIN_SIZE);
#ifdef MIGRATE_PIXEL_SIZE
gboolean migrate_size;
migrate_size = (eel_gconf_get_integer (CONF_SCHEMA_VERSION)
< EPIPHANY_SCHEMA_VERSION);
if (migrate_size)
{
eel_gconf_set_integer (CONF_SCHEMA_VERSION, EPIPHANY_SCHEMA_VERSION);
}
#endif
for (i=0; i < n_font_languages; i++)
{
const char *code = font_languages[i].code;
guint k;
char key[255], pref[255];
#ifdef MIGRATE_PIXEL_SIZE
char old_key[255];
#endif
for (k = 0; k < G_N_ELEMENTS (types); k++)
{
g_snprintf (key, sizeof (key), "%s_%s_%s",
CONF_RENDERING_FONT, types[k], code);
g_snprintf (pref, sizeof (pref), "font.name.%s.%s",
types[k], code);
desktop_font_data[k].font_name_prefs[i] = g_strdup (key);
mozilla_notifier_add (key, pref,
transform_font_name,
&desktop_font_data[k]);
}
#ifdef MIGRATE_PIXEL_SIZE
if (migrate_size)
{
char *type;
type = eel_gconf_get_string (CONF_RENDERING_FONT_TYPE_OLD);
if (type && (strcmp (type, "serif") == 0 ||
strcmp (type, "sans-serif") == 0))
{
char *family;
g_snprintf (old_key, sizeof (old_key), "%s_%s_%s",
CONF_RENDERING_FONT, type, code);
g_snprintf (key, sizeof (key), "%s_%s_%s",
CONF_RENDERING_FONT, "variable", code);
family = eel_gconf_get_string (old_key);
if (family)
{
eel_gconf_set_string (key, family);
g_free (family);
}
}
g_free (type);
}
#endif
/* FIXME is it "minimum-size" or "min-size" !!? */
g_snprintf (key, sizeof (key), "%s_%s",
CONF_RENDERING_FONT_MIN_SIZE, code);
g_snprintf (pref, sizeof (pref), "font.minimum-size.%s", code);
minimum_font_size_data->prefs[i] = g_strdup (key);
mozilla_notifier_add (key, pref, transform_minimum_font_size,
minimum_font_size_data);
#ifdef MIGRATE_PIXEL_SIZE
if (migrate_size)
{
g_snprintf (old_key, sizeof (key), "%s_%s",
CONF_RENDERING_FONT_MIN_SIZE_OLD, code);
migrate_font_gconf_key (old_key, key);
}
#endif
g_snprintf (key, sizeof (key), "%s_%s",
CONF_RENDERING_FONT_FIXED_SIZE, code);
g_snprintf (pref, sizeof (pref), "font.size.fixed.%s", code);
desktop_font_data[1].font_size_prefs[i] = g_strdup (key);
mozilla_notifier_add (key, pref, transform_font_size,
&desktop_font_data[1]);
#ifdef MIGRATE_PIXEL_SIZE
if (migrate_size)
{
g_snprintf (old_key, sizeof (old_key), "%s_%s",
CONF_RENDERING_FONT_FIXED_SIZE_OLD, code);
migrate_font_gconf_key (old_key, key);
}
#endif
g_snprintf (key, sizeof (key), "%s_%s",
CONF_RENDERING_FONT_VAR_SIZE, code);
g_snprintf (pref, sizeof (pref), "font.size.variable.%s", code);
desktop_font_data[0].font_size_prefs[i] = g_strdup (key);
mozilla_notifier_add (key, pref, transform_font_size,
&desktop_font_data[0]);
#ifdef MIGRATE_PIXEL_SIZE
if (migrate_size)
{
g_snprintf (old_key, sizeof (old_key), "%s_%s",
CONF_RENDERING_FONT_VAR_SIZE_OLD, code);
migrate_font_gconf_key (old_key, key);
}
#endif
}
}
static void
mozilla_font_notifiers_shutdown (void)
{
eel_gconf_monitor_remove ("/desktop/gnome/interface");
eel_gconf_notification_remove (desktop_font_data[0].cnxn_id);
eel_gconf_notification_remove (desktop_font_data[1].cnxn_id);
eel_gconf_notification_remove (minimum_font_size_data->cnxn_id);
g_free (desktop_font_data[0].font_name);
g_free (desktop_font_data[1].font_name);
g_strfreev (desktop_font_data[0].font_name_prefs);
g_strfreev (desktop_font_data[0].font_size_prefs);
g_strfreev (desktop_font_data[1].font_name_prefs);
g_strfreev (desktop_font_data[1].font_size_prefs);
g_strfreev (minimum_font_size_data->prefs);
g_free (desktop_font_data);
g_free (minimum_font_size_data);
}
#if 0
static void
notify_generic_cb (GConfClient *client,
guint cnxn_id,
GConfEntry *gcentry,
gpointer data)
{
GConfValue *gcvalue;
const char *key, *pref;
static const gsize len = strlen ("/apps/epiphany/web/gecko_prefs/");
GValue value = { 0, };
key = gconf_entry_get_key (gcentry);
if (!key || strlen (key) <= len) return;
pref = key + len;
gcvalue = gconf_entry_get_value (gcentry);
if (!gcvalue) return;
switch (gcvalue->type)
{
case GCONF_VALUE_STRING:
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, gconf_value_get_string (gcvalue));
break;
case GCONF_VALUE_INT:
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, gconf_value_get_int (gcvalue));
break;
case GCONF_VALUE_BOOL:
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, gconf_value_get_bool (gcvalue));
break;
/* case GCONF_VALUE_INVALID: */
/* case GCONF_VALUE_FLOAT: */
/* case GCONF_VALUE_SCHEMA: */
/* case GCONF_VALUE_LIST: */
/* case GCONF_VALUE_PAIR: */
default:
g_warning ("Unsupported value type for key '%s'\n", key);
return;
}
g_assert (G_IS_VALUE (&value));
mozilla_pref_set (pref, &value);
g_value_unset (&value);
}
static void
mozilla_generic_notifier_init (void)
{
GConfClient *client;
GError *error = NULL;
guint cnxn_id;
PrefData *data;
GSList *list, *l;
client = eel_gconf_client_get_global ();
cnxn_id = gconf_client_notify_add (client, "/apps/epiphany/web/gecko_prefs",
(GConfClientNotifyFunc) notify_generic_cb,
NULL, NULL, &error);
if (eel_gconf_handle_error (&error))
{
if (cnxn_id != EEL_GCONF_UNDEFINED_CONNECTION)
{
gconf_client_notify_remove (client, cnxn_id);
}
return;
}
data = g_slice_new0 (PrefData);
data->cnxn_id = cnxn_id;
notifiers = g_list_prepend (notifiers, data);
list = gconf_client_all_entries (client, "/apps/epiphany/web/gecko_prefs", NULL);
for (l = list; l != NULL; l = l->next)
{
GConfEntry *gcentry = (GConfEntry *) l->data;
notify_generic_cb (client, cnxn_id, gcentry, NULL);
gconf_entry_unref (gcentry);
}
g_slist_free (list);
}
#endif
extern "C" gboolean
mozilla_notifiers_init (void)
{
guint i;
eel_gconf_monitor_add ("/apps/epiphany/web");
eel_gconf_monitor_add ("/system/proxy");
eel_gconf_monitor_add ("/system/http_proxy");
/* the pref service conveniently implements the root pref branch */
gPrefBranch = nsnull;
nsresult rv = CallGetService (NS_PREFSERVICE_CONTRACTID, &gPrefBranch);
if (NS_FAILED (rv) || !gPrefBranch)
{
g_warning ("Failed to get the pref service!\n");
return FALSE;
}
#if 0
/* First init the generic notifier, so our regular prefs override prefs set there */
mozilla_generic_notifier_init ();
#endif
for (i = 0; i < G_N_ELEMENTS (notifier_entries); i++)
{
mozilla_notifier_add (notifier_entries[i].gconf_key,
notifier_entries[i].mozilla_pref,
notifier_entries[i].func,
notifier_entries[i].user_data);
}
mozilla_font_notifiers_init ();
return TRUE;
}
static void
remove_notification (PrefData *data)
{
eel_gconf_notification_remove (data->cnxn_id);
}
extern "C" void
mozilla_notifiers_shutdown (void)
{
NS_IF_RELEASE (gPrefBranch);
gPrefBranch = nsnull;
mozilla_font_notifiers_shutdown ();
eel_gconf_monitor_remove ("/apps/epiphany/web");
eel_gconf_monitor_remove ("/system/proxy");
eel_gconf_monitor_remove ("/system/http_proxy");
g_list_foreach (notifiers, (GFunc) remove_notification, NULL);
g_list_free (notifiers);
}