diff --git a/src/widgets/gm-world-text-view.c b/src/widgets/gm-world-text-view.c index c43de67..9824f5d 100644 --- a/src/widgets/gm-world-text-view.c +++ b/src/widgets/gm-world-text-view.c @@ -2,12 +2,11 @@ #include #include "gm-world-text-view.h" -#include "gm-color-table.h" -#include "gm-marshal.h" - -#include "ansi.h" -#include "debug.h" -//#include "gm-support.h" +#include "../gm-color-table.h" +#include "../gm-marshal.h" +#include "../ansi.h" +#include "../debug.h" +#include "../gm-support.h" /* Callback definitions */ void on_gm_world_text_view_style_set(GmWorldTextView *view, @@ -23,7 +22,7 @@ void on_gm_world_text_view_color_table_color_changed(GmColorTable *table, gchar *name, GmWorldTextView *view); void on_gm_world_text_view_color_table_font_changed(GmColorTable *table, gchar *font_description, GmWorldTextView *view); - + void gm_world_text_view_create_tags(GmWorldTextView *view); void gm_world_text_view_init_tags(GmWorldTextView *view); void gm_world_text_view_update_font(GmWorldTextView *view); @@ -191,6 +190,14 @@ gm_world_text_view_create_tags(GmWorldTextView *view) { GtkTextTag *tag; GtkTextBuffer *buf = GM_WORLD_TEXT_VIEW_BUFFER(view); GdkColor col; + + /* Url tag */ + tag = gtk_text_buffer_create_tag(buf, "url", "foreground", "steelblue", + "underline", PANGO_UNDERLINE_SINGLE, NULL); + g_signal_connect(tag, "event", G_CALLBACK(on_gm_world_text_view_url_event), + view); + g_signal_connect(view, "event", G_CALLBACK(on_gm_world_text_view_event), + tag); for (i = 0; i < (int)(sizeof(ansi_colors) / sizeof(ansinamepair)); i++) { tag = gtk_text_buffer_create_tag(buf, ansi_colors[i].name, NULL); @@ -207,29 +214,35 @@ gm_world_text_view_create_tags(GmWorldTextView *view) { gm_color_table_get(view->priv->color_table, "bg_default", &col); } - gtk_text_buffer_create_tag(buf, "inverse_fg", "background-gdk", &col, NULL); + gtk_text_buffer_create_tag(buf, "inverse_fg", "background-gdk", &col, NULL); for (i = 0; i < (int)(sizeof(ansi_styles) / sizeof(ansinamepair)); i++) { tag = gtk_text_buffer_create_tag(buf, ansi_styles[i].name, NULL); switch (ansi_styles[i].code) { case A_BOLD: - g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_ULTRABOLD, NULL); + g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_ULTRABOLD, + NULL); break; case A_BOLD_OFF: - g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_NORMAL, NULL); + g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_NORMAL, + NULL); break; case A_FAINT: - g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_ULTRALIGHT, NULL); + g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_ULTRALIGHT, + NULL); break; case A_UNDERLINE: - g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_SINGLE, NULL); + g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_SINGLE, + NULL); break; case A_DOUBLE_UNDERLINE: - g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_DOUBLE, NULL); + g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_DOUBLE, + NULL); break; case A_UNDERLINE_OFF: - g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_NONE, NULL); + g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_NONE, + NULL); break; case A_CROSSOUT: g_object_set(G_OBJECT(tag), "strikethrough", TRUE, NULL); @@ -253,17 +266,11 @@ gm_world_text_view_create_tags(GmWorldTextView *view) { g_object_set(G_OBJECT(tag), "wrap-mode", GTK_WRAP_NONE, NULL); break; default: - gtk_text_tag_table_remove(gtk_text_buffer_get_tag_table(buf), tag); + gtk_text_tag_table_remove(gtk_text_buffer_get_tag_table(buf), + tag); break; } } - - /* Url tag */ - tag = gtk_text_buffer_create_tag(buf, "url", "foreground", "steelblue", - "underline", PANGO_UNDERLINE_SINGLE, NULL); - - g_signal_connect(tag, "event", G_CALLBACK(on_gm_world_text_view_url_event), view); - g_signal_connect(view, "event", G_CALLBACK(on_gm_world_text_view_event), tag); } void @@ -327,7 +334,8 @@ g_utf8_toint(gchar *str, guint *result) { } void -gm_world_text_view_insert_text(GmWorldTextView *view, const gchar *text, GList *tags) { +gm_world_text_view_insert_text(GmWorldTextView *view, const gchar *text, + GList *tags) { GtkTextIter end_iter, start_iter; GtkTextBuffer *tb = GM_WORLD_TEXT_VIEW_BUFFER(view); gint start_offset; @@ -336,19 +344,19 @@ gm_world_text_view_insert_text(GmWorldTextView *view, const gchar *text, GList * gtk_text_buffer_get_end_iter(tb, &end_iter); start_offset = gtk_text_iter_get_offset(&end_iter); - gtk_text_buffer_insert(tb, &end_iter, text, g_utf8_strlen(text, -1)); + gtk_text_buffer_insert(tb, &end_iter, text, -1); - if (tags) { - gtk_text_buffer_get_iter_at_offset(tb, &start_iter, start_offset); - gtk_text_buffer_get_end_iter(tb, &end_iter); + if (tags) { + gtk_text_buffer_get_iter_at_offset(tb, &start_iter, start_offset); + gtk_text_buffer_get_end_iter(tb, &end_iter); - for (; tags; tags = tags->next) { - g_object_get(GTK_TEXT_TAG(tags->data), "name", &name, NULL); - g_free(name); - gtk_text_buffer_apply_tag(tb, GTK_TEXT_TAG(tags->data), &start_iter, - &end_iter); - } - } + for (; tags; tags = tags->next) { + g_object_get(GTK_TEXT_TAG(tags->data), "name", &name, NULL); + g_free(name); + gtk_text_buffer_apply_tag(tb, GTK_TEXT_TAG(tags->data), &start_iter, + &end_iter); + } + } } const gchar * @@ -640,6 +648,41 @@ gm_world_text_view_color_table(GmWorldTextView *view) { return view->priv->color_table; } +void +gm_world_text_view_tag_urls(GmWorldTextView *view, gchar *text, + GtkTextIter *started, GtkTextIter *ended) { + gint num_matches, i; + GArray *start, *end; + gint s = 0, e = 0; + GtkTextBuffer *buffer = GM_WORLD_TEXT_VIEW_BUFFER(view); + GtkTextTag *url_tag = gtk_text_tag_table_lookup( + gtk_text_buffer_get_tag_table(buffer), "url"); + GtkTextIter urlstart, urlend; + + start = g_array_new(FALSE, FALSE, sizeof(gint)); + end = g_array_new(FALSE, FALSE, sizeof(gint)); + + num_matches = gm_url_regex_match(text, strlen(text), start, end); + + for (i = 0; i < num_matches; i++) { + urlstart = *started; + urlend = *started; + + s = g_array_index(start, gint, i); + e = g_array_index(end, gint, i); + + gtk_text_iter_forward_cursor_positions(&urlstart, + g_utf8_pointer_to_offset(text, text + s)); + gtk_text_iter_forward_cursor_positions(&urlend, + g_utf8_pointer_to_offset(text, text + e)); + + gtk_text_buffer_apply_tag(buffer, url_tag, &urlstart, &urlend); + } + + g_array_free(start, TRUE); + g_array_free(end, TRUE); +} + gchar * gm_world_text_view_insert(GmWorldTextView *view, const gchar *text) { gchar *ptr, *ansi_start, *ansi_stop, **ansis; @@ -686,7 +729,8 @@ gm_world_text_view_insert(GmWorldTextView *view, const gchar *text) { i = g_utf8_pointer_to_offset(new_line->str, ansi_start); if (i != 0) { - ptr = g_strndup(new_line->str, i); + ptr = g_strndup(new_line->str, ansi_start - new_line->str); + gm_world_text_view_insert_text(view, ptr, info->tags); g_free(ptr); } @@ -760,10 +804,9 @@ gm_world_text_view_insert(GmWorldTextView *view, const gchar *text) { } g_strfreev(ansis); - g_string_erase(new_line, 0, - g_utf8_pointer_to_offset(new_line->str, ansi_stop) + 1); + g_string_erase(new_line, 0, (ansi_stop - new_line->str) + 1); } else { - info->text = ansi_start; + info->text = g_strdup(ansi_start); g_string_free(new_line, TRUE); new_line = NULL; } @@ -772,14 +815,21 @@ gm_world_text_view_insert(GmWorldTextView *view, const gchar *text) { if (new_line && new_line->len != 0) { gm_world_text_view_insert_text(view, new_line->str, info->tags); } - - g_string_free(new_line, TRUE); + + if (new_line) { + g_string_free(new_line, TRUE); + } + gm_world_text_view_check_buffer_size(view); gtk_text_buffer_get_iter_at_mark(buffer, &started, start_mark); gtk_text_buffer_get_end_iter(buffer, &ended); gtk_text_buffer_delete_mark(buffer, start_mark); - return gtk_text_buffer_get_text(buffer, &started, &ended, FALSE); + + ptr = gtk_text_buffer_get_text(buffer, &started, &ended, FALSE); + gm_world_text_view_tag_urls(view, ptr, &started, &ended); + + return ptr; } /* Callbacks */