void utl_gui_text_buffer_toggle_tags (GtkTextBuffer *buffer, const gchar *tag_name) { GtkTextTagTable *tag_table; GtkTextTag *tag; GtkTextIter start, end, titer; gboolean itagged; tag_table = gtk_text_buffer_get_tag_table (buffer); tag = gtk_text_tag_table_lookup (tag_table, tag_name); g_return_if_fail (tag != NULL); gtk_text_buffer_get_selection_bounds (buffer, &start, &end); itagged = TRUE; for (titer = start; !gtk_text_iter_equal (&titer, &end); gtk_text_iter_forward_char (&titer)) { if ((itagged = gtk_text_iter_has_tag (&titer, tag)) == FALSE) { break; } } if (itagged) { gtk_text_buffer_remove_tag (buffer, tag, &start, &end); } else { gtk_text_buffer_apply_tag (buffer, tag, &start, &end); } }
gboolean ide_editor_spell_utils_skip_no_spell_check (GtkTextTag *no_spell_check_tag, GtkTextIter *start, const GtkTextIter *end) { g_return_val_if_fail (start != NULL, FALSE); g_return_val_if_fail (end != NULL, FALSE); if (no_spell_check_tag == NULL) return TRUE; g_return_val_if_fail (GTK_IS_TEXT_TAG (no_spell_check_tag), FALSE); while (gtk_text_iter_has_tag (start, no_spell_check_tag)) { GtkTextIter last = *start; if (!gtk_text_iter_forward_to_tag_toggle (start, no_spell_check_tag)) return FALSE; if (gtk_text_iter_compare (start, &last) <= 0) return FALSE; ide_editor_spell_utils_text_iter_forward_word_end (start); ide_editor_spell_utils_text_iter_backward_word_start (start); if (gtk_text_iter_compare (start, &last) <= 0) return FALSE; if (gtk_text_iter_compare (start, end) >= 0) return FALSE; } return TRUE; }
GtkTextTag * gimp_text_buffer_get_iter_font (GimpTextBuffer *buffer, const GtkTextIter *iter, gchar **font) { GList *list; for (list = buffer->font_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if (gtk_text_iter_has_tag (iter, tag)) { if (font) *font = gimp_text_tag_get_font (tag); return tag; } } if (font) *font = NULL; return NULL; }
static void populate_popup (GtkTextView *textview, GtkMenu *menu, GeditAutomaticSpellChecker *spell) { GtkWidget *img, *mi; GtkTextIter start, end; char *word; /* we need to figure out if they picked a misspelled word. */ get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click); /* if our highlight algorithm ever messes up, * this isn't correct, either. */ if (!gtk_text_iter_has_tag (&start, spell->tag_highlight)) return; /* word wasn't misspelled. */ /* menu separator comes first. */ mi = gtk_separator_menu_item_new (); gtk_widget_show (mi); gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); /* then, on top of it, the suggestions menu. */ img = gtk_image_new_from_stock (GTK_STOCK_SPELL_CHECK, GTK_ICON_SIZE_MENU); mi = gtk_image_menu_item_new_with_mnemonic (_("_Spelling Suggestions...")); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img); word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE); gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), build_suggestion_menu (spell, word)); g_free(word); gtk_widget_show_all (mi); gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); }
GtkTextTag * gimp_text_buffer_get_iter_kerning (GimpTextBuffer *buffer, const GtkTextIter *iter, gint *kerning) { GList *list; for (list = buffer->kerning_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if (gtk_text_iter_has_tag (iter, tag)) { if (kerning) *kerning = gimp_text_tag_get_kerning (tag); return tag; } } if (kerning) *kerning = 0; return NULL; }
GtkTextTag * gimp_text_buffer_get_iter_baseline (GimpTextBuffer *buffer, const GtkTextIter *iter, gint *baseline) { GList *list; for (list = buffer->baseline_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if (gtk_text_iter_has_tag (iter, tag)) { if (baseline) *baseline = gimp_text_tag_get_baseline (tag); return tag; } } if (baseline) *baseline = 0; return NULL; }
static gboolean get_tag_bounds (GtkTextIter *iter, GtkTextTag *tag, GtkTextIter *start, GtkTextIter *end) { gboolean res = FALSE; g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (tag != NULL, FALSE); g_return_val_if_fail (start != NULL, FALSE); g_return_val_if_fail (end != NULL, FALSE); if (gtk_text_iter_has_tag (iter, tag)) { *start = *iter; *end = *iter; if (!gtk_text_iter_begins_tag (start, tag)) gtk_text_iter_backward_to_tag_toggle (start, tag); if (!gtk_text_iter_ends_tag (end, tag)) gtk_text_iter_forward_to_tag_toggle (end, tag); res = TRUE; } return res; }
static void update_mouse_cursor (GtkTextView *text_view, gint x, gint y) { static GdkCursor *hand_cursor = NULL; static GdkCursor *regular_cursor = NULL; gboolean hovering = FALSE, hovering_over_link = FALSE, hovering_real; guint32 state; GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view); GtkTextTagTable *tag_table; GtkTextTag *tag; GtkTextIter iter; if (!hand_cursor) { hand_cursor = gdk_cursor_new (GDK_HAND2); regular_cursor = gdk_cursor_new (GDK_XTERM); } g_return_if_fail (buffer != NULL); tag_table = gtk_text_buffer_get_tag_table (buffer); tag = gtk_text_tag_table_lookup (tag_table, E_BUFFER_TAGGER_LINK_TAG); g_return_if_fail (tag != NULL); state = get_state (buffer); gtk_text_view_get_iter_at_location (text_view, &iter, x, y); hovering_real = gtk_text_iter_has_tag (&iter, tag); hovering_over_link = (state & E_BUFFER_TAGGER_STATE_IS_HOVERING) != 0; if ((state & E_BUFFER_TAGGER_STATE_CTRL_DOWN) == 0) { hovering = FALSE; } else { hovering = hovering_real; } if (hovering != hovering_over_link) { update_state (buffer, E_BUFFER_TAGGER_STATE_IS_HOVERING, hovering); if (hovering && gtk_widget_has_focus (GTK_WIDGET (text_view))) gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), hand_cursor); else gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), regular_cursor); /* XXX Is this necessary? Appears to be a no-op. */ get_pointer_position (text_view, NULL, NULL); } hovering_over_link = (state & E_BUFFER_TAGGER_STATE_IS_HOVERING_TOOLTIP) != 0; if (hovering_real != hovering_over_link) { update_state (buffer, E_BUFFER_TAGGER_STATE_IS_HOVERING_TOOLTIP, hovering_real); gtk_widget_trigger_tooltip_query (GTK_WIDGET (text_view)); } }
static gboolean chat_text_view_event_cb (EmpathyChatTextView *view, GdkEventMotion *event, GtkTextTag *tag) { static GdkCursor *hand = NULL; static GdkCursor *beam = NULL; GtkTextWindowType type; GtkTextIter iter; GdkWindow *win; gint x, y, buf_x, buf_y; type = gtk_text_view_get_window_type (GTK_TEXT_VIEW (view), event->window); if (type != GTK_TEXT_WINDOW_TEXT) { return FALSE; } /* Get where the pointer really is. */ win = gtk_text_view_get_window (GTK_TEXT_VIEW (view), type); if (!win) { return FALSE; } gdk_window_get_pointer (win, &x, &y, NULL); /* Get the iter where the cursor is at */ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view), type, x, y, &buf_x, &buf_y); gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, buf_x, buf_y); if (gtk_text_iter_has_tag (&iter, tag)) { if (!hand) { hand = gdk_cursor_new (GDK_HAND2); beam = gdk_cursor_new (GDK_XTERM); } gdk_window_set_cursor (win, hand); } else { if (!beam) { beam = gdk_cursor_new (GDK_XTERM); } gdk_window_set_cursor (win, beam); } return FALSE; }
static gboolean chatroom_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { gint wx, wy, bx, by; GtkTextView *chatroom = GTK_TEXT_VIEW(widget); GtkTextBuffer *buffer = gtk_text_view_get_buffer(chatroom); GtkTextTag *link_tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "link"); GdkWindow *window = gtk_text_view_get_window(chatroom, GTK_TEXT_WINDOW_TEXT); GtkTextIter iter; if(event->type == GDK_MOTION_NOTIFY) { GdkEventMotion *motion_ev = (GdkEventMotion *)event; wx = motion_ev->x; wy = motion_ev->y; gtk_text_view_window_to_buffer_coords(chatroom, GTK_TEXT_WINDOW_TEXT, wx, wy, &bx, &by); gtk_text_view_get_iter_at_location(chatroom, &iter, bx, by); if(gtk_text_iter_has_tag(&iter, link_tag)) { chatroom_enable_hand_cursor(window, TRUE); } else { chatroom_enable_hand_cursor(window, FALSE); } } return FALSE; }
GtkTextTag * gimp_text_buffer_get_iter_color (GimpTextBuffer *buffer, const GtkTextIter *iter, GimpRGB *color) { GList *list; for (list = buffer->color_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if (gtk_text_iter_has_tag (iter, tag)) { if (color) gimp_text_tag_get_color (tag, color); return tag; } } return NULL; }
static gboolean query_tooltip_text_view_cb (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data) { GtkTextTag *tag = data; GtkTextIter iter; GtkTextView *text_view = GTK_TEXT_VIEW (widget); GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view); if (keyboard_tip) { gint offset; g_object_get (buffer, "cursor-position", &offset, NULL); gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset); } else { gint bx, by, trailing; gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_TEXT, x, y, &bx, &by); gtk_text_view_get_iter_at_position (text_view, &iter, &trailing, bx, by); } if (gtk_text_iter_has_tag (&iter, tag)) gtk_tooltip_set_text (tooltip, "Tooltip on text tag"); else return FALSE; return TRUE; }
static gboolean gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (editor->buffer); if (editor->update_idle_id) { g_source_remove (editor->update_idle_id); editor->update_idle_id = 0; } if (gtk_text_buffer_get_has_selection (buffer)) { GtkTextIter start, end; GtkTextIter iter; GList *list; gboolean any_toggle_active = TRUE; gboolean font_differs = FALSE; gboolean color_differs = FALSE; gboolean size_differs = FALSE; gboolean baseline_differs = FALSE; gboolean kerning_differs = FALSE; GtkTextTag *font_tag = NULL; GtkTextTag *color_tag = NULL; GtkTextTag *size_tag = NULL; GtkTextTag *baseline_tag = NULL; GtkTextTag *kerning_tag = NULL; gtk_text_buffer_get_selection_bounds (buffer, &start, &end); gtk_text_iter_order (&start, &end); /* first, switch all toggles on */ for (list = editor->toggles; list; list = g_list_next (list)) { GtkToggleButton *toggle = list->data; gimp_text_style_editor_set_toggle (editor, toggle, TRUE); } /* and get some initial values */ font_tag = gimp_text_buffer_get_iter_font (editor->buffer, &start, NULL); color_tag = gimp_text_buffer_get_iter_color (editor->buffer, &start, NULL); size_tag = gimp_text_buffer_get_iter_size (editor->buffer, &start, NULL); baseline_tag = gimp_text_buffer_get_iter_baseline (editor->buffer, &start, NULL); kerning_tag = gimp_text_buffer_get_iter_kerning (editor->buffer, &start, NULL); for (iter = start; gtk_text_iter_in_range (&iter, &start, &end); gtk_text_iter_forward_cursor_position (&iter)) { if (any_toggle_active) { any_toggle_active = FALSE; for (list = editor->toggles; list; list = g_list_next (list)) { GtkToggleButton *toggle = list->data; GtkTextTag *tag = g_object_get_data (G_OBJECT (toggle), "tag"); if (! gtk_text_iter_has_tag (&iter, tag)) { gimp_text_style_editor_set_toggle (editor, toggle, FALSE); } else { any_toggle_active = TRUE; } } } if (! font_differs) { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_font (editor->buffer, &iter, NULL); if (tag != font_tag) font_differs = TRUE; } if (! color_differs) { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_color (editor->buffer, &iter, NULL); if (tag != color_tag) color_differs = TRUE; } if (! size_differs) { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_size (editor->buffer, &iter, NULL); if (tag != size_tag) size_differs = TRUE; } if (! baseline_differs) { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_baseline (editor->buffer, &iter, NULL); if (tag != baseline_tag) baseline_differs = TRUE; } if (! kerning_differs) { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_kerning (editor->buffer, &iter, NULL); if (tag != kerning_tag) kerning_differs = TRUE; } if (! any_toggle_active && color_differs && font_differs && size_differs && baseline_differs && kerning_differs) break; } if (font_differs) gimp_text_style_editor_set_font (editor, NULL); else if (font_tag) gimp_text_style_editor_set_font (editor, font_tag); else gimp_text_style_editor_set_default_font (editor); if (color_differs) gimp_text_style_editor_set_color (editor, NULL); else if (color_tag) gimp_text_style_editor_set_color (editor, color_tag); else gimp_text_style_editor_set_default_color (editor); if (size_differs) gimp_text_style_editor_set_size (editor, NULL); else if (size_tag) gimp_text_style_editor_set_size (editor, size_tag); else gimp_text_style_editor_set_default_size (editor); if (baseline_differs) gtk_entry_set_text (GTK_ENTRY (editor->baseline_spinbutton), ""); else gimp_text_style_editor_set_baseline (editor, baseline_tag); if (kerning_differs) gtk_entry_set_text (GTK_ENTRY (editor->kerning_spinbutton), ""); else gimp_text_style_editor_set_kerning (editor, kerning_tag); } else /* no selection */ { GtkTextIter cursor; GSList *tags; GSList *tags_on; GSList *tags_off; GList *list; gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); tags = gtk_text_iter_get_tags (&cursor); tags_on = gtk_text_iter_get_toggled_tags (&cursor, TRUE); tags_off = gtk_text_iter_get_toggled_tags (&cursor, FALSE); for (list = editor->buffer->font_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if ((g_slist_find (tags, tag) && ! g_slist_find (tags_on, tag)) || g_slist_find (tags_off, tag)) { gimp_text_style_editor_set_font (editor, tag); break; } } if (! list) gimp_text_style_editor_set_default_font (editor); for (list = editor->buffer->color_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if ((g_slist_find (tags, tag) && ! g_slist_find (tags_on, tag)) || g_slist_find (tags_off, tag)) { gimp_text_style_editor_set_color (editor, tag); break; } } if (! list) gimp_text_style_editor_set_default_color (editor); for (list = editor->buffer->size_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if ((g_slist_find (tags, tag) && ! g_slist_find (tags_on, tag)) || g_slist_find (tags_off, tag)) { gimp_text_style_editor_set_size (editor, tag); break; } } if (! list) gimp_text_style_editor_set_default_size (editor); for (list = editor->buffer->baseline_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; if ((g_slist_find (tags, tag) && ! g_slist_find (tags_on, tag)) || g_slist_find (tags_off, tag)) { gimp_text_style_editor_set_baseline (editor, tag); break; } } if (! list) gimp_text_style_editor_set_baseline (editor, NULL); for (list = editor->toggles; list; list = g_list_next (list)) { GtkToggleButton *toggle = list->data; GtkTextTag *tag = g_object_get_data (G_OBJECT (toggle), "tag"); gimp_text_style_editor_set_toggle (editor, toggle, (g_slist_find (tags, tag) && ! g_slist_find (tags_on, tag)) || g_slist_find (tags_off, tag)); } { GtkTextTag *tag; tag = gimp_text_buffer_get_iter_kerning (editor->buffer, &cursor, NULL); gimp_text_style_editor_set_kerning (editor, tag); } g_slist_free (tags); g_slist_free (tags_on); g_slist_free (tags_off); } return FALSE; }
static void check_range (GeditAutomaticSpellChecker *spell, GtkTextIter start, GtkTextIter end, gboolean force_all) { /* we need to "split" on word boundaries. * luckily, Pango knows what "words" are * so we don't have to figure it out. */ GtkTextIter wstart; GtkTextIter wend; GtkTextIter cursor; GtkTextIter precursor; gboolean highlight; /* g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start), gtk_text_iter_get_offset (&end)); */ if (gtk_text_iter_inside_word (&end)) gtk_text_iter_forward_word_end (&end); if (!gtk_text_iter_starts_word (&start)) { if (gtk_text_iter_inside_word (&start) || gtk_text_iter_ends_word (&start)) { gtk_text_iter_backward_word_start (&start); } else { /* if we're neither at the beginning nor inside a word, * me must be in some spaces. * skip forward to the beginning of the next word. */ if (gtk_text_iter_forward_word_end (&start)) gtk_text_iter_backward_word_start (&start); } } gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &cursor, gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc))); precursor = cursor; gtk_text_iter_backward_char (&precursor); highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) || gtk_text_iter_has_tag (&precursor, spell->tag_highlight); gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end); /* Fix a corner case when replacement occurs at beginning of buffer: * An iter at offset 0 seems to always be inside a word, * even if it's not. Possibly a pango bug. */ if (gtk_text_iter_get_offset (&start) == 0) { gtk_text_iter_forward_word_end(&start); gtk_text_iter_backward_word_start(&start); } wstart = start; while (gedit_spell_utils_skip_no_spell_check (&wstart, &end) && gtk_text_iter_compare (&wstart, &end) < 0) { gboolean inword; /* move wend to the end of the current word. */ wend = wstart; gtk_text_iter_forward_word_end (&wend); inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) && (gtk_text_iter_compare (&cursor, &wend) <= 0); if (inword && !force_all) { /* this word is being actively edited, * only check if it's already highligted, * otherwise defer this check until later. */ if (highlight) check_word (spell, &wstart, &wend); else spell->deferred_check = TRUE; } else { check_word (spell, &wstart, &wend); spell->deferred_check = FALSE; } /* now move wend to the beginning of the next word, */ gtk_text_iter_forward_word_end (&wend); gtk_text_iter_backward_word_start (&wend); /* make sure we've actually advanced * (we don't advance in some corner cases), */ if (gtk_text_iter_equal (&wstart, &wend)) break; /* we're done in these cases.. */ /* and then pick this as the new next word beginning. */ wstart = wend; } }
static VALUE rg_has_tag_p(VALUE self, VALUE tag) { return CBOOL2RVAL(gtk_text_iter_has_tag(_SELF(self), RVAL2TAG(tag))); }