diff --git a/gnoemoe/widgets/gm-world-text-view.c b/gnoemoe/widgets/gm-world-text-view.c index 40492ba..9d4130d 100644 --- a/gnoemoe/widgets/gm-world-text-view.c +++ b/gnoemoe/widgets/gm-world-text-view.c @@ -22,6 +22,8 @@ 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 on_gm_world_text_view_populate_popup(GmWorldTextView *view, GtkMenu *menu, + gpointer user_data); void gm_world_text_view_create_tags(GmWorldTextView *view); void gm_world_text_view_init_tags(GmWorldTextView *view); @@ -42,8 +44,8 @@ struct _GmWorldTextViewInsertInfo { struct _GmWorldTextViewPrivate { gboolean is_hand; - gint character_width; - gint character_height; + guint character_width; + guint character_height; gint max_lines; GmWorldTextViewInsertInfo last_info; GmColorTable *color_table; @@ -96,11 +98,11 @@ gm_world_text_view_class_init(GmWorldTextViewClass *klass) { G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmWorldTextViewClass, character_size_changed), NULL, NULL, - gm_marshal_VOID__INT_INT, + gm_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, - G_TYPE_INT, - G_TYPE_INT); + G_TYPE_UINT, + G_TYPE_UINT); g_type_class_add_private(object_class, sizeof(GmWorldTextViewPrivate)); } @@ -118,6 +120,8 @@ gm_world_text_view_init(GmWorldTextView *view) { gtk_widget_modify_text(GTK_WIDGET(view), GTK_STATE_ACTIVE, &(GTK_WIDGET(view)->style->text[GTK_STATE_SELECTED])); + gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE); + // Margins gtk_text_view_set_left_margin(GTK_TEXT_VIEW(view), 3); gtk_text_view_set_right_margin(GTK_TEXT_VIEW(view), 3); @@ -137,6 +141,8 @@ gm_world_text_view_init(GmWorldTextView *view) { // Connect style set signal g_signal_connect(view, "style-set", G_CALLBACK(on_gm_world_text_view_style_set), NULL); + g_signal_connect(view, "populate_popup", + G_CALLBACK(on_gm_world_text_view_populate_popup), NULL); } /* Private functions */ @@ -361,24 +367,24 @@ gm_world_text_view_insert_text(GmWorldTextView *view, const gchar *text, const gchar * gm_world_text_view_tagname_from_code(guint code) { - int i, len; + gint i, len; - len = (sizeof(ansi_colors) / sizeof(ansinamepair)); + len = (sizeof(ansi_colors) / sizeof(ansinamepair)); - for (i = 0; i < len; i++) { - if (ansi_colors[i].code == code) { - return ansi_colors[i].name; - } - } - - len = sizeof(ansi_styles) / sizeof(ansinamepair); - for (i = 0; i < len; i++) { - if (ansi_styles[i].code == code) { - return ansi_styles[i].name; - } - } + for (i = 0; i < len; i++) { + if (ansi_colors[i].code == code) { + return ansi_colors[i].name; + } + } - return NULL; + len = sizeof(ansi_styles) / sizeof(ansinamepair); + for (i = 0; i < len; i++) { + if (ansi_styles[i].code == code) { + return ansi_styles[i].name; + } + } + + return NULL; } GList * @@ -837,6 +843,13 @@ gm_world_text_view_insert(GmWorldTextView *view, const gchar *text) { return ptr; } +void +gm_world_text_view_get_metrics(GmWorldTextView *view, guint *width, + guint *height) { + *width = view->priv->character_width; + *height = view->priv->character_height; +} + /* Callbacks */ void on_gm_world_text_view_style_set(GmWorldTextView *view, GtkStyle *previous_style, @@ -854,13 +867,13 @@ on_gm_world_text_view_style_set(GmWorldTextView *view, GtkStyle *previous_style, pango_layout_get_pixel_size(pl, &(cwidth), &(cheight)); - if (view->priv->character_width != cwidth || - view->priv->character_height != cheight) { - view->priv->character_width = cwidth; - view->priv->character_height = cheight; + if (view->priv->character_width != (guint)cwidth || + view->priv->character_height != (guint)cheight) { + view->priv->character_width = (guint)cwidth; + view->priv->character_height = (guint)cheight; g_signal_emit(view, world_text_view_signals[CHARACTER_SIZE_CHANGED], 0, - cwidth, cheight); + view->priv->character_width, view->priv->character_height); } g_object_unref(pl); @@ -897,6 +910,74 @@ on_gm_world_text_view_url_event(GtkTextTag *tag, GObject *object, return FALSE; } +void +on_gm_world_text_view_copy_address(GtkMenuItem *item, GmWorldTextView *view) { + GtkClipboard *clipboard; + gchar *url = (gchar *)(g_object_get_data(G_OBJECT(gtk_widget_get_parent( + GTK_WIDGET(item))), "url")); + + clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(clipboard, url, -1); +} + +void +on_gm_world_text_view_open_address(GtkMenuItem *item, GmWorldTextView *view) { + gchar *url = (gchar *)(g_object_get_data(G_OBJECT(gtk_widget_get_parent( + GTK_WIDGET(item))), "url")); + + g_signal_emit(view, world_text_view_signals[URL_ACTIVATE], 0, url); +} + +void +on_gm_world_text_view_populate_popup(GmWorldTextView *view, GtkMenu *menu, + gpointer user_data) { + GtkTextTagTable *table; + GtkTextTag *tag; + gint x, y; + GtkTextIter iter, start, end; + GtkWidget *item; + gchar *str = NULL; + + table = gtk_text_buffer_get_tag_table(GM_WORLD_TEXT_VIEW_BUFFER(view)); + tag = gtk_text_tag_table_lookup(table, "url"); + + gtk_widget_get_pointer(GTK_WIDGET(view), &x, &y); + gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(view), + GTK_TEXT_WINDOW_WIDGET, x, y, &x, &y); + + gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(view), &iter, x, y); + start = end = iter; + + if (gtk_text_iter_backward_to_tag_toggle(&start, tag) && + gtk_text_iter_forward_to_tag_toggle(&end, tag)) { + str = gtk_text_buffer_get_text(GM_WORLD_TEXT_VIEW_BUFFER(view), + &start, &end, FALSE); + } + + if (str == NULL || *str == '\0') { + return; + } + + item = gtk_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + + /* Set data just to get the string freed when not needed. */ + g_object_set_data_full(G_OBJECT(menu), "url", str, (GDestroyNotify)g_free); + + item = gtk_menu_item_new_with_mnemonic(_("_Copy Link Address")); + g_signal_connect(item, "activate", + G_CALLBACK(on_gm_world_text_view_copy_address), view); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + + item = gtk_menu_item_new_with_mnemonic(_("_Open Link")); + g_signal_connect(item, "activate", + G_CALLBACK(on_gm_world_text_view_open_address), view); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); +} + gboolean on_gm_world_text_view_event(GmWorldTextView *view, GdkEventMotion *event, GtkTextTag *tag) {