#include #include #include "gm-color-table.h" #include #include "gm-ansi.h" #include "gm-debug.h" #define GM_COLOR_TABLE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GM_TYPE_COLOR_TABLE, GmColorTablePrivate)) static void gm_color_table_item_free(gpointer item); typedef struct _GmColorTableItem GmColorTableItem; struct _GmColorTableItem { gchar *hex; GdkColor color; }; typedef struct _GmColorTableSchemeItem { const gchar *name; const gchar *hex; } GmColorTableSchemeItem; static const GmColorTableSchemeItem scheme_default[] = { {"fg_default", "#000000"}, {"fg_black", "#000000"}, {"fg_red", "#aa0000"}, {"fg_green", "#00aa00"}, {"fg_yellow", "#aa5500"}, {"fg_blue", "#0000aa"}, {"fg_purple", "#aa00aa"}, {"fg_cyan", "#00aaaa"}, {"fg_white", "#aaaaaa"}, {"fg_default_h", "#555555"}, {"fg_black_h", "#555555"}, {"fg_red_h", "#ff5555"}, {"fg_green_h", "#55ff55"}, {"fg_yellow_h", "#ffff55"}, {"fg_blue_h", "#5555ff"}, {"fg_purple_h", "#ff55ff"}, {"fg_cyan_h", "#55ffff"}, {"fg_white_h", "#ffffff"}, {"bg_default", "#ffffff"}, {"bg_black", "#222222"}, {"bg_red", "#770000"}, {"bg_green", "#007700"}, {"bg_yellow", "#ddaa33"}, {"bg_blue", "#000077"}, {"bg_purple", "#770077"}, {"bg_cyan", "#007777"}, {"bg_white", "#777777"}, {NULL, NULL} }; static const GmColorTableSchemeItem scheme_white_on_black[] = { {"fg_default", "#D6B5D6B5D6B5"}, {"fg_black", "#2D6B2D6B2D6B"}, {"fg_red", "#FFFF00000000"}, {"fg_green", "#0000FFFF0000"}, {"fg_yellow", "#FFFFD0450000"}, {"fg_blue", "#3EF73EF7BFFF"}, {"fg_purple", "#A0A02020F0F0"}, {"fg_cyan", "#0000FFFFFFFF"}, {"fg_white", "#D8C5D8C5D8C5"}, {"fg_default_h", "#FFFFFFFFFFFF"}, {"fg_black_h", "#529452945294"}, {"fg_red_h", "#FFFF785F785F"}, {"fg_green_h", "#66ADFFFF66AD"}, {"fg_yellow_h", "#FFFFFFFF58C6"}, {"fg_blue_h", "#86318631FFFF"}, {"fg_purple_h", "#C6576A18FFFF"}, {"fg_cyan_h", "#86EEFFFFFFFF"}, {"fg_white_h", "#FFFFFFFFFFFF"}, {"bg_default", "#000000000000"}, {"bg_black", "#2B5B2B5B2B5B"}, {"bg_red", "#FFFF00000000"}, {"bg_green", "#000080000000"}, {"bg_yellow", "#C047C0470000"}, {"bg_blue", "#00000000FFFF"}, {"bg_purple", "#A0A02020F0F0"}, {"bg_cyan", "#0000B74CB74C"}, {"bg_white", "#FFFFFFFFFFFF"}, {NULL, NULL} }; static const GmColorTableSchemeItem scheme_xterm[] = { {"fg_default", "#E5E2E5E2E5E2"}, {"fg_black", "#000000000000"}, {"fg_red", "#CDCB00000000"}, {"fg_green", "#0000CDCB0000"}, {"fg_yellow", "#CDCBCDCB0000"}, {"fg_blue", "#1E1A908FFFFF"}, {"fg_purple", "#CDCB0000CDCB"}, {"fg_cyan", "#0000CDCBCDCB"}, {"fg_white", "#E5E2E5E2E5E2"}, {"fg_default_h", "#FFFFFFFFFFFF"}, {"fg_black_h", "#4CCCC4CCCC4CCCC"}, {"fg_red_h", "#FFFF00000000"}, {"fg_green_h", "#0000FFFF0000"}, {"fg_yellow_h", "#FFFFFFFF0000"}, {"fg_blue_h", "#46458281B4AE"}, {"fg_purple_h", "#FFFF0000FFFF"}, {"fg_cyan_h", "#0000FFFFFFFF"}, {"fg_white_h", "#FFFFFFFFFFFF"}, {"bg_default", "#000000000000"}, {"bg_black", "#000000000000"}, {"bg_red", "#CDCB00000000"}, {"bg_green", "#0000CDCB0000"}, {"bg_yellow", "#CDCBCDCB0000"}, {"bg_blue", "#1E1A908FFFFF"}, {"bg_purple", "#CDCB0000CDCB"}, {"bg_cyan", "#0000CDCBCDCB"}, {"bg_white", "#E5E2E5E2E5E2"}, {NULL, NULL} }; static const GmColorTableSchemeItem scheme_rxvt[] = { {"fg_default", "#FAFAEBEBD7D7"}, {"fg_black", "#000000000000"}, {"fg_red", "#CDCD00000000"}, {"fg_green", "#0000CDCD0000"}, {"fg_yellow", "#CDCDCDCD0000"}, {"fg_blue", "#00000000CDCD"}, {"fg_purple", "#CDCD0000CDCD"}, {"fg_cyan", "#0000CDCDCDCD"}, {"fg_white", "#FAFAEBEBD7D7"}, {"fg_default_h", "#FFFFFFFFFFFF"}, {"fg_black_h", "#404040404040"}, {"fg_red_h", "#FFFF00000000"}, {"fg_green_h", "#0000FFFF0000"}, {"fg_yellow_h", "#FFFFFFFF0000"}, {"fg_blue_h", "#00000000FFFF"}, {"fg_purple_h", "#FFFF0000FFFF"}, {"fg_cyan_h", "#0000FFFFFFFF"}, {"fg_white_h", "#FFFFFFFFFFFF"}, {"bg_default", "#000000000000"}, {"bg_black", "#000000000000"}, {"bg_red", "#CDCD00000000"}, {"bg_green", "#0000CDCD0000"}, {"bg_yellow", "#CDCDCDCD0000"}, {"bg_blue", "#00000000CDCD"}, {"bg_purple", "#CDCD0000CDCD"}, {"bg_cyan", "#0000CDCDCDCD"}, {"bg_white", "#FAFAEBEBD7D7"}, {NULL, NULL} }; static const GmColorTableSchemeItem scheme_linux[] = { {"fg_default", "#AAAAAAAAAAAA"}, {"fg_black", "#000000000000"}, {"fg_red", "#AAAA00000000"}, {"fg_green", "#0000AAAA0000"}, {"fg_yellow", "#AAAA55550000"}, {"fg_blue", "#00000000AAAA"}, {"fg_purple", "#AAAA0000AAAA"}, {"fg_cyan", "#0000AAAAAAAA"}, {"fg_white", "#AAAAAAAAAAAA"}, {"fg_default_h", "#FFFFFFFFFFFF"}, {"fg_black_h", "#555555555555"}, {"fg_red_h", "#FFFF55555555"}, {"fg_green_h", "#5555FFFF5555"}, {"fg_yellow_h", "#FFFFFFFF5555"}, {"fg_blue_h", "#55555555FFFF"}, {"fg_purple_h", "#FFFF5555FFFF"}, {"fg_cyan_h", "#5555FFFFFFFF"}, {"fg_white_h", "#FFFFFFFFFFFF"}, {"bg_default", "#000000000000"}, {"bg_black", "#000000000000"}, {"bg_red", "#AAAA00000000"}, {"bg_green", "#0000AAAA0000"}, {"bg_yellow", "#AAAA55550000"}, {"bg_blue", "#00000000AAAA"}, {"bg_purple", "#AAAA0000AAAA"}, {"bg_cyan", "#0000AAAAAAAA"}, {"bg_white", "#AAAAAAAAAAAA"}, {NULL, NULL} }; typedef struct _GmColorScheme { GmColorTableScheme scheme; const gchar *name; const GmColorTableSchemeItem *values; } GmColorScheme; static const GmColorScheme scheme_names[] = { {SCHEME_NONE, "none", NULL}, {SCHEME_DEFAULT, "default", scheme_default}, {SCHEME_WHITE_ON_BLACK, "white_on_black", scheme_white_on_black}, {SCHEME_RXVT, "rxvt", scheme_rxvt}, {SCHEME_XTERM, "xterm", scheme_xterm}, {SCHEME_LINUX, "linux", scheme_linux}, {SCHEME_USER, "user", NULL}, {SCHEME_NONE, NULL, NULL} }; struct _GmColorTablePrivate { GHashTable *colors; gchar *font_description; gboolean use_system_font; GmOptions *options; GmColorTableScheme scheme; guint gconf_connection_id; }; static void on_gm_color_table_monospace_font_change_notify(GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data); static void gm_color_table_disconnect_font_changed(GmColorTable *table); #define MONOSPACE_FONT_DIR "/desktop/gnome/interface" #define MONOSPACE_FONT_KEY MONOSPACE_FONT_DIR "/monospace_font_name" /* Signals */ enum { COLOR_CHANGED, FONT_CHANGED, NUM_SIGNALS }; static guint color_table_signals[NUM_SIGNALS] = {0}; G_DEFINE_TYPE(GmColorTable, gm_color_table, G_TYPE_OBJECT) static void gm_color_table_finalize(GObject *object) { GmColorTable *table = GM_COLOR_TABLE(object); gm_color_table_disconnect_font_changed(table); G_OBJECT_CLASS(gm_color_table_parent_class)->finalize(object); } static void gm_color_table_class_init(GmColorTableClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = gm_color_table_finalize; color_table_signals[COLOR_CHANGED] = g_signal_new("color_changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmColorTableClass, color_changed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); color_table_signals[FONT_CHANGED] = g_signal_new("font_changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmColorTableClass, font_changed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private(object_class, sizeof(GmColorTablePrivate)); } static void gm_color_table_init(GmColorTable *table) { table->priv = GM_COLOR_TABLE_GET_PRIVATE(table); table->priv->colors = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, gm_color_table_item_free); table->priv->scheme = SCHEME_NONE; } /* Private functions */ static void gm_color_table_item_free(gpointer item) { GmColorTableItem *i = (GmColorTableItem *)(item); g_free(i->hex); g_free(i); } static void gm_color_table_set_value(GmColorTable *table, gchar const *name, gchar const *hex) { GmColorTableItem *item; item = g_hash_table_lookup(table->priv->colors, name); if (!item) { item = g_new0(GmColorTableItem, 1); g_hash_table_insert(table->priv->colors, g_strdup(name), item); } if (item->hex == NULL || strcmp(hex, item->hex) != 0) { g_free(item->hex); item->hex = g_strdup(hex); gdk_color_parse(item->hex, &(item->color)); g_signal_emit(table, color_table_signals[COLOR_CHANGED], 0, name); } } static gchar * gm_color_table_default_font(GmColorTable *table) { GConfClient *conf = gconf_client_get_default(); gchar *name = gconf_client_get_string(conf, MONOSPACE_FONT_KEY, NULL); g_object_unref(G_OBJECT(conf)); if (name) { return name; } else { return g_strdup("Monospace 10"); } } static void gm_color_table_fill_from_options(GmColorTable *table) { gchar const *value; gint vint; gchar *font; GmOptions *options = table->priv->options; // New, color schemes value = gm_options_get(options, "color_scheme"); gm_color_table_set_from_scheme_name(table, value); value = gm_options_get(options, "use_system_font"); vint = gm_options_get_int(options, "use_system_font"); if (!value || vint) { gm_color_table_set_use_system_font(table, TRUE); } else { value = gm_options_get(options, "font_family"); if (!value || *value == '\0') { font = gm_color_table_default_font(table); gm_options_set(options, "font_family", font); g_free(font); value = gm_options_get(options, "font_family"); } gm_color_table_set_font_description(table, value); } } static void gm_color_table_disconnect_font_changed(GmColorTable *table) { GConfClient *conf; if (table->priv->gconf_connection_id) { conf = gconf_client_get_default(); gconf_client_notify_remove(conf, table->priv->gconf_connection_id); gconf_client_remove_dir(conf, MONOSPACE_FONT_DIR, NULL); table->priv->gconf_connection_id = 0; g_object_unref(G_OBJECT(conf)); } } static void gm_color_table_connect_font_changed(GmColorTable *table) { GError *err; GConfClient *conf; guint connection_id; conf = gconf_client_get_default (); err = NULL; gconf_client_add_dir(conf, MONOSPACE_FONT_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, &err); if (err) { gm_debug_msg(DEBUG_DEFAULT, "There was an error loading config from " "%s. (%s)\n", MONOSPACE_FONT_DIR, err->message); g_error_free(err); } err = NULL; connection_id = gconf_client_notify_add(conf, MONOSPACE_FONT_DIR, on_gm_color_table_monospace_font_change_notify, table, NULL, &err); g_object_unref (conf); if (err) { gm_debug_msg(DEBUG_DEFAULT, "There was an error subscribing to " "notification of monospace font changes. (%s)\n", err->message); g_error_free(err); } else { table->priv->gconf_connection_id = connection_id; } } /* Public functions */ GmColorTable * gm_color_table_new(void) { GmColorTable *table = GM_COLOR_TABLE(g_object_new(GM_TYPE_COLOR_TABLE, NULL)); gm_color_table_load_scheme(table, SCHEME_DEFAULT); gm_color_table_set_use_system_font(table, TRUE); return table; } GmColorTable * gm_color_table_new_from_options(gchar *filename) { GmColorTable *table = GM_COLOR_TABLE(g_object_new(GM_TYPE_COLOR_TABLE, NULL)); table->priv->options = gm_options_new(); gm_options_set(table->priv->options, "color_scheme", "default"); _gm_options_check_old_options(filename); gm_options_load(table->priv->options, filename); gm_color_table_fill_from_options(table); return table; } void gm_color_table_save(GmColorTable *table) { if (table->priv->options) { gm_options_save(table->priv->options); } } void gm_color_table_set(GmColorTable *table, gchar const *name, gchar const *hex) { GmColorTableSchemeItem const *item; GmColorTableItem *it; if (table->priv->scheme != SCHEME_USER) { table->priv->scheme = SCHEME_USER; if (table->priv->options) { gm_options_set(table->priv->options, "color_scheme", scheme_names[SCHEME_USER].name); // Store all current values in the options for (item = scheme_default; item->name != NULL; ++item) { it = g_hash_table_lookup(table->priv->colors, item->name); gm_options_set(table->priv->options, item->name, it->hex); } } } if (table->priv->options) { // Store value in the options, set value in the table gm_options_set(table->priv->options, name, hex); } gm_color_table_set_value(table, name, hex); } gboolean gm_color_table_get(GmColorTable *table, gchar const *name, GdkColor *color) { GmColorTableItem *item; item = g_hash_table_lookup(table->priv->colors, name); if (item != NULL) { *color = item->color; return TRUE; } else { return FALSE; } } const gchar * gm_color_table_get_hex(GmColorTable *table, const gchar *name) { GmColorTableItem *item; item = g_hash_table_lookup(table->priv->colors, name); if (item != NULL) { return item->hex; } else { return FALSE; } } void gm_color_table_set_font_description(GmColorTable *table, gchar const *font_description) { gchar *fd; if (font_description == NULL) { fd = gm_color_table_default_font(table); } else if (table->priv->use_system_font) { return; } else { fd = g_strdup(font_description); } if (table->priv->options) { gm_options_set(table->priv->options, "font_family", fd); } if (table->priv->font_description == NULL || strcmp(table->priv->font_description, fd) != 0) { g_free(table->priv->font_description); table->priv->font_description = g_strdup(fd); g_signal_emit(table, color_table_signals[FONT_CHANGED], 0, table->priv->font_description); } g_free(fd); } void gm_color_table_set_use_system_font(GmColorTable *table, gboolean use_system_font) { if (table->priv->use_system_font == use_system_font) { return; } table->priv->use_system_font = use_system_font; if (use_system_font) { gm_color_table_connect_font_changed(table); gm_color_table_set_font_description(table, NULL); if (table->priv->options) { gm_options_set(table->priv->options, "use_system_font", "1"); } } else { gm_color_table_disconnect_font_changed(table); if (table->priv->options) { gm_options_set(table->priv->options, "use_system_font", "0"); } } } gboolean gm_color_table_get_use_system_font(GmColorTable *table) { return table->priv->use_system_font; } const gchar * gm_color_table_font_description(GmColorTable *table) { return table->priv->font_description; } void gm_color_table_load_scheme(GmColorTable *table, GmColorTableScheme scheme) { guint i = 0; GmColorTableSchemeItem const *values; GmOptions *options = table->priv->options; gchar const *value; if (scheme == SCHEME_USER && options) { values = scheme_names[SCHEME_DEFAULT].values; while (values[i].name != NULL) { value = gm_options_get(options, values[i].name); if (value != NULL) { gm_color_table_set_value(table, values[i].name, value); } else { gm_options_set(options, values[i].name, values[i].hex); gm_color_table_set_value(table, values[i].name, values[i].hex); } ++i; } } else if (scheme != SCHEME_USER) { values = scheme_names[scheme].values; while (values[i].name != NULL) { gm_color_table_set_value(table, values[i].name, values[i].hex); ++i; } } table->priv->scheme = scheme; } void gm_color_table_set_from_scheme_name(GmColorTable *table, gchar const *scheme) { gint i = 0; while (scheme_names[i].name) { if (strcasecmp(scheme_names[i].name, scheme) == 0) { gm_color_table_load_scheme(table, scheme_names[i].scheme); break; } ++i; } if (scheme_names[i].name == NULL) { gm_color_table_load_scheme(table, SCHEME_DEFAULT); if (table->priv->options) { gm_options_set(table->priv->options, "color_scheme", "default"); } } else if (table->priv->options) { gm_options_set(table->priv->options, "color_scheme", scheme_names[i].name); } } gchar const * gm_color_table_get_scheme_name(GmColorTable *table) { gint i = 0; while (scheme_names[i].name) { if (scheme_names[i].scheme == table->priv->scheme) { return scheme_names[i].name; } ++i; } return NULL; } /* Callbacks */ static void on_gm_color_table_monospace_font_change_notify(GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) { GmColorTable *table = GM_COLOR_TABLE(user_data); if (strcmp(entry->key, MONOSPACE_FONT_KEY) == 0) { gm_color_table_set_font_description(table, NULL); } }