590 lines
14 KiB
C
590 lines
14 KiB
C
#include <glib.h>
|
|
#include <gconf/gconf-client.h>
|
|
#include "gm-color-table.h"
|
|
#include <string.h>
|
|
#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;
|
|
|
|
/*const GdkColor
|
|
terminal_palette_linux[TERMINAL_PALETTE_SIZE] =
|
|
{
|
|
{ 0, 0x0000, 0x0000, 0x0000 },
|
|
{ 0, 0xaaaa, 0x0000, 0x0000 },
|
|
{ 0, 0x0000, 0xaaaa, 0x0000 },
|
|
{ 0, 0xaaaa, 0x5555, 0x0000 },
|
|
{ 0, 0x0000, 0x0000, 0xaaaa },
|
|
{ 0, 0xaaaa, 0x0000, 0xaaaa },
|
|
{ 0, 0x0000, 0xaaaa, 0xaaaa },
|
|
{ 0, 0xaaaa, 0xaaaa, 0xaaaa },
|
|
{ 0, 0x5555, 0x5555, 0x5555 },
|
|
{ 0, 0xffff, 0x5555, 0x5555 },
|
|
{ 0, 0x5555, 0xffff, 0x5555 },
|
|
{ 0, 0xffff, 0xffff, 0x5555 },
|
|
{ 0, 0x5555, 0x5555, 0xffff },
|
|
{ 0, 0xffff, 0x5555, 0xffff },
|
|
{ 0, 0x5555, 0xffff, 0xffff },
|
|
{ 0, 0xffff, 0xffff, 0xffff }
|
|
};*/
|
|
|
|
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_default[] = {
|
|
{"fg_default", "#000000"},
|
|
{"fg_black", "#000000"},
|
|
{"fg_red", "#663822"},
|
|
{"fg_green", "#445632"},
|
|
{"fg_yellow", "#D1940C"},
|
|
{"fg_blue", "#314E6C"},
|
|
{"fg_purple", "#494066"},
|
|
{"fg_cyan", "#0000FFFFFFFF"},
|
|
{"fg_white", "#BAB5AB"},
|
|
|
|
{"fg_default_h", "#565248"},
|
|
{"fg_black_h", "#565248"},
|
|
{"fg_red_h", "#990000"},
|
|
{"fg_green_h", "#267726"},
|
|
{"fg_yellow_h", "#EED680"},
|
|
{"fg_blue_h", "#9DB8D2"},
|
|
{"fg_purple_h", "#ADA7C8"},
|
|
{"fg_cyan_h", "#86EEFFFFFFFF"},
|
|
{"fg_white_h", "#807D74"},
|
|
|
|
{"bg_default", "#FFFFFF"},
|
|
{"bg_black", "#000000"},
|
|
{"bg_red", "#663822"},
|
|
{"bg_green", "#445632"},
|
|
{"bg_yellow", "#D1940C"},
|
|
{"bg_blue", "#314E6C"},
|
|
{"bg_purple", "#494066"},
|
|
{"bg_cyan", "#0000FFFFFFFF"},
|
|
{"bg_white", "#FFFFFFFFFFFF"},
|
|
{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}
|
|
};
|
|
|
|
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_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_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);
|
|
}
|
|
}
|
|
|