using Gtk; public class TextViewUrl : Gtk.TextView { protected static string browser = "E:\\Firefox\\firefox.exe"; protected Gtk.TextTag url_tag; construct { Gdk.Color blue; blue.red = 1300; blue.green = 1200; blue.blue = 60000; Gtk.TextTagTable tagTbl = this.buffer.get_tag_table (); this.url_tag = new Gtk.TextTag ("url_tag"); this.url_tag.underline = Pango.Underline.SINGLE; this.url_tag.underline_set = true; this.url_tag.foreground_gdk = &blue; this.url_tag.event += TextViewUrl.event; tagTbl.add (this.url_tag); } [Callback] private static bool event (Gtk.TextTag sender, GLib.Object event_object, Gdk.Event event, Gtk.TextIter iter) { bool ret = false; if (event.type == Gdk.EventType.BUTTON_RELEASE) { weak Gdk.EventButton event_btn = (Gdk.EventButton)event; if (event_btn.button == 1) { ret = TextViewUrl.url_activate (sender, iter); } } return ret; } private static bool url_activate (Gtk.TextTag sender, Gtk.TextIter iter) { bool ret = false; Gtk.TextIter start, end; string link; if (iter.toggles_tag (sender) == false) { // Go backward until this tag begins start = iter; while (start.begins_tag (sender) == false) { start.backward_char (); } // Go backward until this tag ends end = iter; while (end.ends_tag(sender) == false) { end.forward_char(); } link = start.get_text (end); if (link != null) { try { string[] argv = new string[3]; argv[0] = TextViewUrl.browser; argv[1] = link; argv[2] = null; GLib.Process.spawn_async (null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null, null); ret = true; } catch (GLib.Error e) { GLib.critical (e.message); } } } return ret; } public void insert_url (Gtk.TextIter iter, string! url) { Gtk.TextIter start, end; Gtk.TextMark startOfURL; this.buffer.get_end_iter (out start); startOfURL = this.buffer.create_mark ("url_mark", start, true); this.buffer.insert (iter, url, -1); this.buffer.get_end_iter (out end); this.buffer.get_iter_at_mark (out start, startOfURL); this.buffer.apply_tag (this.url_tag, start, end); this.buffer.delete_mark (startOfURL); } }