#ifdef HAVE_CONFIG_H #include #endif #include #include "gm-source-style-scheme.h" #include "gm-color-table.h" #include "gm-app.h" #include "gm-support.h" #include "gm-debug.h" #define GM_TYPE_SOURCE_STYLE_SCHEME (gm_source_style_scheme_get_type ()) #define GM_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleScheme)) #define GM_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleSchemeClass)) #define GM_IS_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GM_TYPE_SOURCE_STYLE_SCHEME)) #define GM_IS_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GM_TYPE_SOURCE_STYLE_SCHEME)) #define GM_SOURCE_STYLE_SCHEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleSchemeClass)) typedef struct _GmSourceStyleScheme GmSourceStyleScheme; typedef struct _GmSourceStyleSchemeClass GmSourceStyleSchemeClass; struct _GmSourceStyleScheme { GObject parent_instance; GHashTable *mapping; GHashTable *styles; }; struct _GmSourceStyleSchemeClass { GObjectClass parent_class; }; static GObjectClass *parent_class = NULL; static GType gm_source_style_scheme_get_type (void); static void gm_source_style_scheme_class_init(GmSourceStyleSchemeClass *klass); static void gm_source_style_scheme_IFace_init(GtkSourceStyleSchemeClass *iface); static void gm_source_style_scheme_init(GmSourceStyleScheme *scheme); static void gm_source_style_scheme_finalize(GObject *object); static GtkSourceTagStyle *gm_source_style_scheme_get_tag_style( GtkSourceStyleScheme *scheme, const gchar *style_name); static const gchar *gm_source_style_scheme_get_name(GtkSourceStyleScheme *scheme); static GSList *gm_source_style_scheme_get_style_names(GtkSourceStyleScheme *scheme); static GType gm_source_style_scheme_get_type (void) { static GType type = 0; if (!type) { static const GTypeInfo info = { sizeof (GmSourceStyleSchemeClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gm_source_style_scheme_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GmSourceStyleScheme), 0, /* n_preallocs */ (GInstanceInitFunc) gm_source_style_scheme_init, }; static const GInterfaceInfo iface_info = { (GInterfaceInitFunc) gm_source_style_scheme_IFace_init, /* interface_init */ NULL, /* interface_finalize */ NULL /* interface_data */ }; type = g_type_register_static (G_TYPE_OBJECT, "GmSourceStyleScheme", &info, 0); g_type_add_interface_static (type, GTK_TYPE_SOURCE_STYLE_SCHEME, &iface_info); } return type; } static void gm_source_style_scheme_class_init(GmSourceStyleSchemeClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent(klass); gobject_class->finalize = gm_source_style_scheme_finalize; } static void gm_source_style_scheme_IFace_init(GtkSourceStyleSchemeClass *iface) { iface->get_tag_style = gm_source_style_scheme_get_tag_style; iface->get_name = gm_source_style_scheme_get_name; iface->get_style_names = gm_source_style_scheme_get_style_names; } static GtkSourceTagStyle * new_tag_style(gchar const * foreground, gchar const * background, gboolean bold, gboolean italic) { GtkSourceTagStyle *ts; ts = gtk_source_tag_style_new(); gdk_color_parse(foreground, &ts->foreground); ts->mask |= GTK_SOURCE_TAG_STYLE_USE_FOREGROUND; if (background != NULL) { gdk_color_parse (background, &ts->background); ts->mask |= GTK_SOURCE_TAG_STYLE_USE_BACKGROUND; } ts->italic = italic; ts->bold = bold; ts->is_default = TRUE; return ts; } typedef struct _GmSourceStyleEntry { gchar const *name; gchar const *color_name; gboolean bold; gboolean italic; } GmSourceStyleEntry; static GmSourceStyleEntry entries[] = { {"Base-N Integer", "fg_purple_h"}, {"Character", "fg_purple_h"}, {"Comment", "fg_blue_h"}, {"Data Type", "fg_cyan", TRUE}, {"Function", "fg_green"}, {"Decimal", "fg_purple_h"}, {"Floating Point", "fg_purple_h"}, {"Keyword", "fg_red", TRUE}, {"String", "fg_purple_h"}, {NULL, NULL} }; static GmKeyValuePair mapping[] = { {"fg_purple_h", "Object@32@Number String"}, {"fg_cyan", "Builtin@32@Variables Types S-Ref Error"}, {"fg_green", "Builtin@32@Functions"}, {"fg_blue_h", "Line@32@Comment"}, {"fg_red", "Keywords"}, {NULL, NULL} }; static void gm_source_style_scheme_init_mapping(GmSourceStyleScheme *scheme) { GmKeyValuePair *entry; scheme->mapping = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_strfreev); for (entry = mapping; entry->key; ++entry) { g_hash_table_insert(scheme->mapping, g_strdup(entry->key), g_strsplit(entry->value, " ", 0)); } } static void gm_source_style_scheme_init(GmSourceStyleScheme *scheme) { GtkSourceTagStyle *ts; GmColorTable *table = gm_app_color_table(gm_app_instance()); GmSourceStyleEntry *entry; scheme->styles = g_hash_table_new_full((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)gtk_source_tag_style_free); for (entry = entries; entry->name; ++entry) { ts = new_tag_style(gm_color_table_get_hex(table, entry->color_name), NULL, entry->bold, entry->italic); g_hash_table_insert(scheme->styles, g_strdup(entry->name), ts); } gm_source_style_scheme_init_mapping(scheme); } static void gm_source_style_scheme_finalize(GObject *object) { GmSourceStyleScheme *scheme = GM_SOURCE_STYLE_SCHEME(object); g_hash_table_destroy(scheme->styles); g_hash_table_destroy(scheme->mapping); G_OBJECT_CLASS(parent_class)->finalize (object); } static GtkSourceTagStyle * gm_source_style_scheme_get_tag_style(GtkSourceStyleScheme *scheme, const gchar *style_name) { GmSourceStyleScheme *ds; const gpointer *style; g_return_val_if_fail(GM_IS_SOURCE_STYLE_SCHEME(scheme), NULL); g_return_val_if_fail(style_name != NULL, NULL); ds = GM_SOURCE_STYLE_SCHEME(scheme); style = g_hash_table_lookup(ds->styles, style_name); return (style != NULL) ? gtk_source_tag_style_copy((GtkSourceTagStyle *)style) : NULL; } static const gchar * gm_source_style_scheme_get_name(GtkSourceStyleScheme *scheme) { g_return_val_if_fail(GTK_IS_SOURCE_STYLE_SCHEME(scheme), NULL); return _("Gnoemoe"); } static void add_style_name(gpointer key, gpointer value, gpointer user_data) { GSList **l = user_data; *l = g_slist_append(*l, g_strdup(key)); } static GSList * gm_source_style_scheme_get_style_names(GtkSourceStyleScheme *scheme) { GmSourceStyleScheme *ds; GSList *l = NULL; g_return_val_if_fail(GTK_IS_SOURCE_STYLE_SCHEME(scheme), NULL); ds = GM_SOURCE_STYLE_SCHEME(scheme); g_hash_table_foreach(ds->styles, add_style_name, &l); return l; } /* Default style scheme */ static GtkSourceStyleScheme *gm_style_scheme = NULL; static void on_gm_source_style_scheme_color_changed(GmColorTable *table, gchar const *color) { gchar **ids; gchar const *hex = gm_color_table_get_hex(table, color); GmSourceStyleEntry *entry; GtkSourceTagStyle *style; for (entry = entries; entry->name; ++entry) { if (strcmp(entry->color_name, color) == 0) { style = g_hash_table_lookup( GM_SOURCE_STYLE_SCHEME(gm_style_scheme)->styles, entry->name); if (style != NULL) { gdk_color_parse(hex, &(style->foreground)); } } } ids = g_hash_table_lookup(GM_SOURCE_STYLE_SCHEME(gm_style_scheme)->mapping, color); if (ids) { for (; *ids; ++ids) { g_signal_emit_by_name(gm_style_scheme, "style_changed", *ids); } } } void gm_source_style_weak_destroy(gpointer data, GObject *object) { g_signal_handlers_disconnect_by_func(gm_app_color_table(gm_app_instance()), on_gm_source_style_scheme_color_changed, NULL); gm_style_scheme = NULL; } GtkSourceStyleScheme * gm_source_style_scheme_get_default(void) { if (gm_style_scheme == NULL) { gm_style_scheme = g_object_new(GM_TYPE_SOURCE_STYLE_SCHEME, NULL); g_object_weak_ref(G_OBJECT(gm_style_scheme), gm_source_style_weak_destroy, NULL); g_signal_connect(gm_app_color_table(gm_app_instance()), "color-changed", G_CALLBACK(on_gm_source_style_scheme_color_changed), NULL); } else { g_object_ref(gm_style_scheme); } return gm_style_scheme; }