302 lines
8.3 KiB
C
302 lines
8.3 KiB
C
|
#ifdef HAVE_CONFIG_H
|
||
|
#include <config.h>
|
||
|
#endif
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#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;
|
||
|
}
|