static void select_range (Movement *mv, GtkTextIter *insert_iter, GtkTextIter *selection_iter) { GtkTextBuffer *buffer; GtkTextMark *insert; GtkTextMark *selection; gint insert_off; gint selection_off; g_assert (insert_iter); g_assert (selection_iter); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (mv->self)); insert = gtk_text_buffer_get_insert (buffer); selection = gtk_text_buffer_get_selection_bound (buffer); mv->ignore_select = TRUE; /* * If the caller is requesting that we select a single character, we will * keep the iter before that character. This more closely matches the visual * mode in VIM. */ insert_off = gtk_text_iter_get_offset (insert_iter); selection_off = gtk_text_iter_get_offset (selection_iter); if ((insert_off - selection_off) == 1) gtk_text_iter_order (insert_iter, selection_iter); gtk_text_buffer_move_mark (buffer, insert, insert_iter); gtk_text_buffer_move_mark (buffer, selection, selection_iter); }
void gb_beautifier_process_launch_async (GbBeautifierWorkbenchAddin *self, IdeSourceView *source_view, GtkTextIter *begin, GtkTextIter *end, GbBeautifierConfigEntry *entry, GAsyncReadyCallback callback, GCancellable *cancellable, gpointer user_data) { GtkTextBuffer *buffer; ProcessState *state; g_autoptr(GTask) task = NULL; const gchar *lang_id; g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self)); g_assert (IDE_IS_SOURCE_VIEW (source_view)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); g_assert (entry != NULL); g_assert (callback != NULL); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)); lang_id = gb_beautifier_helper_get_lang_id (self, source_view); if (begin == NULL) gtk_text_buffer_get_start_iter (buffer, begin); if (end == NULL) gtk_text_buffer_get_end_iter (buffer, begin); g_assert (gtk_text_iter_get_buffer (begin) == buffer); g_assert (gtk_text_iter_get_buffer (end) == buffer); state = g_slice_new0 (ProcessState); state->self = self; state->source_view = source_view; gtk_text_iter_order (begin, end); state->text = gtk_text_buffer_get_text (buffer, begin, end, FALSE); state->begin_mark = gtk_text_buffer_create_mark (buffer, NULL, begin, TRUE); state->end_mark = gtk_text_buffer_create_mark (buffer, NULL, end, FALSE); state->command = entry->command; state->lang_id = g_strdup (lang_id); if (G_IS_FILE (entry->config_file)) state->config_file = g_file_dup (entry->config_file); if (entry->command_args != NULL) state->command_args = command_args_copy (entry->command_args); task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, gb_beautifier_process_launch_async); g_task_set_task_data (task, state, process_state_free); gb_beautifier_helper_create_tmp_file_async (self, state->text, create_tmp_file_cb, cancellable, g_steal_pointer (&task)); }
static void ide_lsp_formatter_format_async (IdeFormatter *formatter, IdeBuffer *buffer, IdeFormatterOptions *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdeLspFormatter *self = (IdeLspFormatter *)formatter; IdeLspFormatterPrivate *priv = ide_lsp_formatter_get_instance_private (self); g_autoptr(GVariant) params = NULL; g_autoptr(IdeTask) task = NULL; g_autofree gchar *uri = NULL; g_autofree gchar *text = NULL; GtkTextIter begin; GtkTextIter end; gint64 version; gint tab_size; gboolean insert_spaces; g_assert (IDE_IS_LSP_FORMATTER (self)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); task = ide_task_new (self, cancellable, callback, user_data); ide_task_set_source_tag (task, ide_lsp_formatter_format_async); ide_task_set_task_data (task, g_object_ref (buffer), g_object_unref); gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &begin, &end); gtk_text_iter_order (&begin, &end); version = ide_buffer_get_change_count (buffer); uri = ide_buffer_dup_uri (buffer); text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer), &begin, &end, TRUE); tab_size = ide_formatter_options_get_tab_width (options); insert_spaces = ide_formatter_options_get_insert_spaces (options); params = JSONRPC_MESSAGE_NEW ( "textDocument", "{", "uri", JSONRPC_MESSAGE_PUT_STRING (uri), "text", JSONRPC_MESSAGE_PUT_STRING (text), "version", JSONRPC_MESSAGE_PUT_INT64 (version), "}", "options", "{", "tabSize", JSONRPC_MESSAGE_PUT_INT32 (tab_size), "insertSpaces", JSONRPC_MESSAGE_PUT_BOOLEAN (insert_spaces), "}" ); ide_lsp_client_call_async (priv->client, "textDocument/formatting", params, cancellable, ide_lsp_formatter_format_call_cb, g_steal_pointer (&task)); }
static void gbp_retab_editor_page_addin_action (GSimpleAction *action, GVariant *variant, gpointer user_data) { GbpRetabEditorPageAddin *self = user_data; IdeSourceView *source_view; GtkTextBuffer *buffer; IdeCompletion *completion; guint tab_width; gint start_line; gint end_line; gint indent; GtkTextIter begin; GtkTextIter end; gboolean editable; gboolean to_spaces; g_assert (GBP_IS_RETAB_EDITOR_PAGE_ADDIN (self)); g_assert (G_IS_SIMPLE_ACTION (action)); buffer = GTK_TEXT_BUFFER (ide_editor_page_get_buffer (self->editor_view)); source_view = ide_editor_page_get_view (self->editor_view); g_assert (IDE_IS_SOURCE_VIEW (source_view)); editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (source_view)); completion = ide_source_view_get_completion (IDE_SOURCE_VIEW (source_view)); tab_width = gtk_source_view_get_tab_width(GTK_SOURCE_VIEW (source_view)); to_spaces = gtk_source_view_get_insert_spaces_instead_of_tabs(GTK_SOURCE_VIEW (source_view)); if (!editable) return; gtk_text_buffer_get_selection_bounds (buffer, &begin, &end); gtk_text_iter_order (&begin, &end); if (!gtk_text_iter_equal (&begin, &end) && gtk_text_iter_starts_line (&end)) gtk_text_iter_backward_char (&end); start_line = gtk_text_iter_get_line (&begin); end_line = gtk_text_iter_get_line (&end); ide_completion_block_interactive (completion); gtk_text_buffer_begin_user_action (buffer); for (gint line = start_line; line <= end_line; ++line) { indent = get_buffer_range_indent (buffer, line, to_spaces); if (indent > 0) gbp_retab_editor_page_addin_retab (buffer, line, tab_width, indent, to_spaces); } gtk_text_buffer_end_user_action (buffer); ide_completion_unblock_interactive (completion); }
static void gimp_text_tool_change_size (GimpTextTool *text_tool, gdouble amount) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter start; GtkTextIter end; if (! gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) { return; } gtk_text_iter_order (&start, &end); gimp_text_buffer_change_size (text_tool->buffer, &start, &end, amount * PANGO_SCALE); }
static void gimp_text_tool_change_baseline (GimpTextTool *text_tool, gdouble amount) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter start; GtkTextIter end; if (! gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) { gtk_text_buffer_get_iter_at_mark (buffer, &start, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_end_iter (buffer, &end); } gtk_text_iter_order (&start, &end); gimp_text_buffer_change_baseline (text_tool->buffer, &start, &end, amount * PANGO_SCALE); }
static gboolean gb_vim_match_is_selected (GtkTextBuffer *buffer, GtkTextIter *match_begin, GtkTextIter *match_end) { GtkTextIter sel_begin; GtkTextIter sel_end; g_assert (GTK_IS_TEXT_BUFFER (buffer)); g_assert (match_begin); g_assert (match_end); gtk_text_buffer_get_selection_bounds (buffer, &sel_begin, &sel_end); gtk_text_iter_order (&sel_begin, &sel_end); return ((gtk_text_iter_compare (&sel_begin, match_begin) <= 0) && (gtk_text_iter_compare (&sel_begin, match_end) < 0) && (gtk_text_iter_compare (&sel_end, match_begin) > 0) && (gtk_text_iter_compare (&sel_end, match_end) >= 0)); }
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; }
GtkTextRegion * gtk_text_region_intersect (GtkTextRegion *region, const GtkTextIter *_start, const GtkTextIter *_end) { GList *start_node, *end_node, *node; GtkTextIter sr_start_iter, sr_end_iter; Subregion *sr, *new_sr; gboolean done; GtkTextRegion *new_region; GtkTextIter start, end; g_return_val_if_fail (region != NULL && _start != NULL && _end != NULL, NULL); start = *_start; end = *_end; gtk_text_iter_order (&start, &end); /* find bounding subregions */ start_node = find_nearest_subregion (region, &start, NULL, FALSE, FALSE); end_node = find_nearest_subregion (region, &end, start_node, TRUE, FALSE); /* easy case first */ if (start_node == NULL || end_node == NULL || end_node == start_node->prev) return NULL; new_region = gtk_text_region_new (region->buffer); done = FALSE; sr = start_node->data; gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start); gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end); /* starting node */ if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter)) { new_sr = g_new0 (Subregion, 1); new_region->subregions = g_list_prepend (new_region->subregions, new_sr); new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL, &start, TRUE); if (start_node == end_node) { /* things will finish shortly */ done = TRUE; if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter)) new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &end, FALSE); else new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_end_iter, FALSE); } else { new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_end_iter, FALSE); } node = start_node->next; } else { /* start should be the same as the subregion, so copy it in the loop */ node = start_node; } if (!done) { while (node != end_node) { /* copy intermediate subregions verbatim */ sr = node->data; gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start); gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end); new_sr = g_new0 (Subregion, 1); new_region->subregions = g_list_prepend (new_region->subregions, new_sr); new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_start_iter, TRUE); new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_end_iter, FALSE); /* next node */ node = node->next; } /* ending node */ sr = node->data; gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start); gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end); new_sr = g_new0 (Subregion, 1); new_region->subregions = g_list_prepend (new_region->subregions, new_sr); new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_start_iter, TRUE); if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter)) new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &end, FALSE); else new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL, &sr_end_iter, FALSE); } new_region->subregions = g_list_reverse (new_region->subregions); return new_region; }
void gtk_text_region_subtract (GtkTextRegion *region, const GtkTextIter *_start, const GtkTextIter *_end) { GList *start_node, *end_node, *node; GtkTextIter sr_start_iter, sr_end_iter; gboolean done; gboolean start_is_outside, end_is_outside; Subregion *sr; GtkTextIter start, end; g_return_if_fail (region != NULL && _start != NULL && _end != NULL); start = *_start; end = *_end; DEBUG (g_print ("---\n")); DEBUG (gtk_text_region_debug_print (region)); DEBUG (g_message ("region_substract (%d, %d)", gtk_text_iter_get_offset (&start), gtk_text_iter_get_offset (&end))); gtk_text_iter_order (&start, &end); /* find bounding subregions */ start_node = find_nearest_subregion (region, &start, NULL, FALSE, FALSE); end_node = find_nearest_subregion (region, &end, start_node, TRUE, FALSE); /* easy case first */ if (start_node == NULL || end_node == NULL || end_node == start_node->prev) return; /* deal with the start point */ start_is_outside = end_is_outside = FALSE; sr = start_node->data; gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start); gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end); if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter) && !gtk_text_iter_equal (&start, &sr_start_iter)) { /* the starting point is inside the first subregion */ if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) && !gtk_text_iter_equal (&end, &sr_end_iter)) { /* the ending point is also inside the first subregion: we need to split */ Subregion *new_sr = g_new0 (Subregion, 1); new_sr->end = sr->end; new_sr->start = gtk_text_buffer_create_mark (region->buffer, NULL, &end, TRUE); start_node = g_list_insert_before (start_node, start_node->next, new_sr); sr->end = gtk_text_buffer_create_mark (region->buffer, NULL, &start, FALSE); /* no further processing needed */ DEBUG (g_message ("subregion splitted")); return; } else { /* the ending point is outside, so just move the end of the subregion to the starting point */ gtk_text_buffer_move_mark (region->buffer, sr->end, &start); } } else { /* the starting point is outside (and so to the left) of the first subregion */ DEBUG (g_message ("start is outside")); start_is_outside = TRUE; } /* deal with the end point */ if (start_node != end_node) { sr = end_node->data; gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start); gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end); } if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) && !gtk_text_iter_equal (&end, &sr_end_iter)) { /* ending point is inside, move the start mark */ gtk_text_buffer_move_mark (region->buffer, sr->start, &end); } else { end_is_outside = TRUE; DEBUG (g_message ("end is outside")); } /* finally remove any intermediate subregions */ done = FALSE; node = start_node; while (!done) { if (node == end_node) /* we are done, exit in the next iteration */ done = TRUE; if ((node == start_node && !start_is_outside) || (node == end_node && !end_is_outside)) { /* skip starting or ending node */ node = node->next; } else { GList *l = node->next; sr = node->data; gtk_text_buffer_delete_mark (region->buffer, sr->start); gtk_text_buffer_delete_mark (region->buffer, sr->end); g_free (sr); region->subregions = g_list_delete_link (region->subregions, node); node = l; } } ++region->time_stamp; DEBUG (gtk_text_region_debug_print (region)); /* now get rid of empty subregions */ gtk_text_region_clear_zero_length_subregions (region); DEBUG (gtk_text_region_debug_print (region)); }
void gtk_text_region_add (GtkTextRegion *region, const GtkTextIter *_start, const GtkTextIter *_end) { GList *start_node, *end_node; GtkTextIter start, end; g_return_if_fail (region != NULL && _start != NULL && _end != NULL); start = *_start; end = *_end; DEBUG (g_print ("---\n")); DEBUG (gtk_text_region_debug_print (region)); DEBUG (g_message ("region_add (%d, %d)", gtk_text_iter_get_offset (&start), gtk_text_iter_get_offset (&end))); gtk_text_iter_order (&start, &end); /* don't add zero-length regions */ if (gtk_text_iter_equal (&start, &end)) return; /* find bounding subregions */ start_node = find_nearest_subregion (region, &start, NULL, FALSE, TRUE); end_node = find_nearest_subregion (region, &end, start_node, TRUE, TRUE); if (start_node == NULL || end_node == NULL || end_node == start_node->prev) { /* create the new subregion */ Subregion *sr = g_new0 (Subregion, 1); sr->start = gtk_text_buffer_create_mark (region->buffer, NULL, &start, TRUE); sr->end = gtk_text_buffer_create_mark (region->buffer, NULL, &end, FALSE); if (start_node == NULL) { /* append the new region */ region->subregions = g_list_append (region->subregions, sr); } else if (end_node == NULL) { /* prepend the new region */ region->subregions = g_list_prepend (region->subregions, sr); } else { /* we are in the middle of two subregions */ region->subregions = g_list_insert_before (region->subregions, start_node, sr); } } else { GtkTextIter iter; Subregion *sr = start_node->data; if (start_node != end_node) { /* we need to merge some subregions */ GList *l = start_node->next; Subregion *q; gtk_text_buffer_delete_mark (region->buffer, sr->end); while (l != end_node) { q = l->data; gtk_text_buffer_delete_mark (region->buffer, q->start); gtk_text_buffer_delete_mark (region->buffer, q->end); g_free (q); l = g_list_delete_link (l, l); } q = l->data; gtk_text_buffer_delete_mark (region->buffer, q->start); sr->end = q->end; g_free (q); l = g_list_delete_link (l, l); } /* now move marks if that action expands the region */ gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->start); if (gtk_text_iter_compare (&iter, &start) > 0) gtk_text_buffer_move_mark (region->buffer, sr->start, &start); gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->end); if (gtk_text_iter_compare (&iter, &end) < 0) gtk_text_buffer_move_mark (region->buffer, sr->end, &end); } ++region->time_stamp; DEBUG (gtk_text_region_debug_print (region)); }
static void gimp_text_tool_move_cursor (GimpTextTool *text_tool, GtkMovementStep step, gint count, gboolean extend_selection) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; GtkTextIter *sel_start; gboolean cancel_selection = FALSE; gint x_pos = -1; GIMP_LOG (TEXT_EDITING, "%s count = %d, select = %s", g_enum_get_value (g_type_class_ref (GTK_TYPE_MOVEMENT_STEP), step)->value_name, count, extend_selection ? "TRUE" : "FALSE"); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &selection, gtk_text_buffer_get_selection_bound (buffer)); if (extend_selection) { sel_start = &selection; } else { /* when there is a selection, moving the cursor without * extending it should move the cursor to the end of the * selection that is in moving direction */ if (count > 0) gtk_text_iter_order (&selection, &cursor); else gtk_text_iter_order (&cursor, &selection); sel_start = &cursor; /* if we actually have a selection, just move *to* the beginning/end * of the selection and not *from* there on LOGICAL_POSITIONS * and VISUAL_POSITIONS movement */ if (! gtk_text_iter_equal (&cursor, &selection)) cancel_selection = TRUE; } switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: if (! cancel_selection) gtk_text_iter_forward_visible_cursor_positions (&cursor, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: if (! cancel_selection) { PangoLayout *layout; const gchar *text; if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); text = pango_layout_get_text (layout); while (count != 0) { const gunichar word_joiner = 8288; /*g_utf8_get_char(WORD_JOINER);*/ gint index; gint trailing = 0; gint new_index; index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (count > 0) { if (g_utf8_get_char (text + index) == word_joiner) pango_layout_move_cursor_visually (layout, TRUE, index, 0, 1, &new_index, &trailing); else new_index = index; pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, 1, &new_index, &trailing); count--; } else { pango_layout_move_cursor_visually (layout, TRUE, index, 0, -1, &new_index, &trailing); if (new_index != -1 && new_index != G_MAXINT && g_utf8_get_char (text + new_index) == word_joiner) { pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, -1, &new_index, &trailing); } count++; } if (new_index != G_MAXINT && new_index != -1) index = new_index; else break; gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, index, TRUE); gtk_text_iter_forward_chars (&cursor, trailing); } } break; case GTK_MOVEMENT_WORDS: if (count < 0) { gtk_text_iter_backward_visible_word_starts (&cursor, -count); } else if (count > 0) { if (! gtk_text_iter_forward_visible_word_ends (&cursor, count)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINES: { GtkTextIter start; GtkTextIter end; gint cursor_index; PangoLayout *layout; PangoLayoutLine *layout_line; PangoLayoutIter *layout_iter; PangoRectangle logical; gint line; gint trailing; gint i; gtk_text_buffer_get_bounds (buffer, &start, &end); cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_index_to_line_x (layout, cursor_index, FALSE, &line, &x_pos); layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); x_pos += logical.x; pango_layout_iter_free (layout_iter); /* try to go to the remembered x_pos if it exists *and* we are at * the beginning or at the end of the current line */ if (text_tool->x_pos != -1 && (x_pos <= logical.x || x_pos >= logical.x + logical.width)) x_pos = text_tool->x_pos; line += count; if (line < 0) { cursor = start; break; } else if (line >= pango_layout_get_line_count (layout)) { cursor = end; break; } layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); layout_line = pango_layout_iter_get_line_readonly (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); pango_layout_iter_free (layout_iter); pango_layout_line_x_to_index (layout_line, x_pos - logical.x, &cursor_index, &trailing); gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, cursor_index, TRUE); while (trailing--) gtk_text_iter_forward_char (&cursor); } break; case GTK_MOVEMENT_PAGES: /* well... */ case GTK_MOVEMENT_BUFFER_ENDS: if (count < 0) { gtk_text_buffer_get_start_iter (buffer, &cursor); } else if (count > 0) { gtk_text_buffer_get_end_iter (buffer, &cursor); } break; case GTK_MOVEMENT_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; default: return; } text_tool->x_pos = x_pos; gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_select_range (buffer, &cursor, sel_start); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); }
GtkTextBuffer *gtk_text_buffer_duplicate(GtkTextBuffer *source_buffer) { // Local variables gchar *conversion_buffer; // Used when converting between unicode character types GtkTextIter end_iter; GtkTextIter end_iter_minus_one; gint end_offset; gint i; guint loop_counter; GtkTextIter loop_iter; GtkTextBuffer *new_text_buffer; guint num_tags; GtkTextIter source_buffer_end; GtkTextIter source_buffer_start; gint start_offset; GSList *tag_list; GtkTextTag *tag_ptr; gunichar temp_char; GString *temp_gstring; // Validate the tags in the source buffer text_layer_dialog_validate_buffer_tag_quantity(GTK_TEXT_BUFFER(source_buffer)); // Initialise various things temp_gstring = g_string_new(NULL); // Create a new text buffer new_text_buffer = gtk_text_buffer_new(get_text_tags_table()); // Get the bounds of the source buffer gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(source_buffer), &source_buffer_start, &source_buffer_end); gtk_text_iter_order(&source_buffer_start, &source_buffer_end); // Scan through the source text buffer one character at a time, getting the character and the tags that apply to it start_offset = gtk_text_iter_get_offset(&source_buffer_start); end_offset = gtk_text_iter_get_offset(&source_buffer_end); for (i = 0; i < end_offset; i++) { // Copy one character from the source text buffer to the new destination text buffer gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(source_buffer), &loop_iter, i); temp_char = gtk_text_iter_get_char(&loop_iter); conversion_buffer = g_ucs4_to_utf8(&temp_char, 1, NULL, NULL, NULL); if (NULL == conversion_buffer) { g_string_printf(temp_gstring, "%s ED441: %s", _("Error"), _("Could not convert unicode character from ucs4 to utf8.")); display_warning(temp_gstring->str); continue; } // Validate the retrieved character if (TRUE != g_unichar_validate(temp_char)) { // Something other than a unicode character was retrieved g_string_printf(temp_gstring, "%s ED442: %s", _("Error"), _("Invalid unicode character found in text.")); display_warning(temp_gstring->str); continue; } gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(new_text_buffer), conversion_buffer, -1); g_free(conversion_buffer); // Copy the tags from the character in the source buffer to the new character in the destination buffer tag_list = gtk_text_iter_get_tags(&loop_iter); num_tags = g_slist_length(tag_list); gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(new_text_buffer), &end_iter); end_iter_minus_one = end_iter; gtk_text_iter_backward_char(&end_iter_minus_one); for (loop_counter = 0; loop_counter < num_tags; loop_counter++) { // Copy each tag from the source text buffer to the destination one tag_ptr = g_slist_nth_data(tag_list, loop_counter); gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(new_text_buffer), tag_ptr, &end_iter_minus_one, &end_iter); } g_slist_free(tag_list); } g_string_free(temp_gstring, TRUE); // Validate the tags in the duplicated buffer text_layer_dialog_validate_buffer_tag_quantity(GTK_TEXT_BUFFER(new_text_buffer)); // Return the duplicated text buffer return new_text_buffer; }
static gboolean run_search (GeditViewFrame *frame, const gchar *entry_text, gboolean search_backward, gboolean wrap_around, gboolean typing) { GtkTextIter start_iter; GtkTextIter match_start; GtkTextIter match_end; gboolean found = FALSE; GeditDocument *doc; g_return_val_if_fail (frame->priv->search_mode == SEARCH, FALSE); doc = gedit_view_frame_get_document (frame); gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &start_iter, frame->priv->start_mark); if (*entry_text != '\0') { if (!search_backward) { if (!typing) { /* forward and _NOT_ typing */ gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start_iter, &match_end); gtk_text_iter_order (&match_end, &start_iter); } /* run search */ found = gedit_document_search_forward (doc, &start_iter, NULL, &match_start, &match_end); } else if (!typing) { /* backward and not typing */ gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start_iter, &match_end); /* run search */ found = gedit_document_search_backward (doc, NULL, &start_iter, &match_start, &match_end); } else { /* backward (while typing) */ g_return_val_if_reached (FALSE); } if (!found && wrap_around) { if (!search_backward) { found = gedit_document_search_forward (doc, NULL, NULL, /* FIXME: set the end_inter */ &match_start, &match_end); } else { found = gedit_document_search_backward (doc, NULL, /* FIXME: set the start_inter */ NULL, &match_start, &match_end); } } } else { gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start_iter, NULL); } if (found) { gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &match_start); gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc), "selection_bound", &match_end); } else if (typing) { gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &start_iter, frame->priv->start_mark); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &start_iter); } if (found || (*entry_text == '\0')) { gedit_view_scroll_to_cursor (GEDIT_VIEW (frame->priv->view)); set_entry_background (frame, frame->priv->search_entry, GEDIT_SEARCH_ENTRY_NORMAL); } else { set_entry_background (frame, frame->priv->search_entry, GEDIT_SEARCH_ENTRY_NOT_FOUND); } return found; }
static void ide_source_view_movements_previous_line (Movement *mv) { GtkTextBuffer *buffer; gboolean has_selection; guint line; guint offset = 0; buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (mv->self)); /* check for linewise */ has_selection = !gtk_text_iter_equal (&mv->insert, &mv->selection) || !mv->exclusive; line = gtk_text_iter_get_line (&mv->insert); if ((*mv->target_offset) > 0) offset = *mv->target_offset; if (line == 0) return; /* * If we have a whole line selected (from say `V`), then we need to swap the cursor and * selection. This feels to me like a slight bit of a hack. There may be cause to actually have * a selection mode and know the type of selection (line vs individual characters). */ if (is_single_line_selection (&mv->insert, &mv->selection)) { if (gtk_text_iter_compare (&mv->insert, &mv->selection) > 0) gtk_text_iter_order (&mv->insert, &mv->selection); gtk_text_iter_set_line (&mv->insert, gtk_text_iter_get_line (&mv->insert) - 1); select_range (mv, &mv->insert, &mv->selection); ensure_anchor_selected (mv); return; } if (is_single_char_selection (&mv->insert, &mv->selection)) { if (gtk_text_iter_compare (&mv->insert, &mv->selection) > 0) { if (offset) --offset; *mv->target_offset = offset; } } gtk_text_buffer_get_iter_at_line (buffer, &mv->insert, line - 1); if ((line - 1) == gtk_text_iter_get_line (&mv->insert)) { for (; offset; offset--) if (!gtk_text_iter_ends_line (&mv->insert)) if (!gtk_text_iter_forward_char (&mv->insert)) break; if (has_selection) { if (gtk_text_iter_equal (&mv->insert, &mv->selection)) gtk_text_iter_backward_char (&mv->insert); select_range (mv, &mv->insert, &mv->selection); ensure_anchor_selected (mv); } else gtk_text_buffer_select_range (buffer, &mv->insert, &mv->insert); } /* make sure selection/insert are up to date */ if (!gtk_text_buffer_get_has_selection (buffer)) mv->selection = mv->insert; }
static gboolean gb_vim_command_search (GtkWidget *active_widget, const gchar *command, const gchar *options, GError **error) { GtkSourceView *source_view; GtkTextBuffer *buffer; const gchar *search_begin = NULL; const gchar *search_end = NULL; const gchar *replace_begin = NULL; const gchar *replace_end = NULL; gchar *search_text = NULL; gchar *replace_text = NULL; gunichar separator; gboolean confirm_replace = FALSE; g_assert (GTK_IS_WIDGET (active_widget)); g_assert (g_str_has_prefix (command, "%s") || g_str_has_prefix (command, "s")); if (IDE_IS_EDITOR_VIEW (active_widget)) source_view = GTK_SOURCE_VIEW (IDE_EDITOR_VIEW (active_widget)->frame1->source_view); else return gb_vim_set_source_view_error (error); if (*command == '%') command++; command++; separator = g_utf8_get_char (command); if (!separator) goto invalid_request; search_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { search_end = command; break; } } if (!search_end) goto invalid_request; replace_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { replace_end = command; break; } } if (!replace_end) goto invalid_request; command = g_utf8_next_char (command); if (*command) { for (; *command; command++) { switch (*command) { case 'c': confirm_replace = TRUE; break; case 'g': break; /* what other options are supported? */ default: break; } } } search_text = g_strndup (search_begin, search_end - search_begin); replace_text = g_strndup (replace_begin, replace_end - replace_begin); if (confirm_replace) { GVariant *variant; GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY); g_variant_builder_add (&builder, "s", search_text); g_variant_builder_add (&builder, "s", replace_text); variant = g_variant_builder_end (&builder); ide_widget_action (GTK_WIDGET (IDE_EDITOR_VIEW (active_widget)->frame1), "frame", "replace-confirm", variant); return TRUE; } buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)); if (gtk_text_buffer_get_has_selection (buffer)) { GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_selection_bounds (buffer, &begin, &end); gtk_text_iter_order (&begin, &end); gb_vim_do_search_and_replace (buffer, &begin, &end, search_text, replace_text, FALSE); } else gb_vim_do_search_and_replace (buffer, NULL, NULL, search_text, replace_text, TRUE); g_free (search_text); g_free (replace_text); return TRUE; invalid_request: g_set_error (error, GB_VIM_ERROR, GB_VIM_ERROR_UNKNOWN_OPTION, _("Invalid search and replace request")); return FALSE; }
static gboolean gb_vim_command_search (GtkSourceView *source_view, const gchar *command, const gchar *options, GError **error) { GtkTextBuffer *buffer; const gchar *search_begin = NULL; const gchar *search_end = NULL; const gchar *replace_begin = NULL; const gchar *replace_end = NULL; gchar *search_text = NULL; gchar *replace_text = NULL; gunichar separator; g_assert (g_str_has_prefix (command, "%s") || g_str_has_prefix (command, "s")); if (*command == '%') command++; command++; separator = g_utf8_get_char (command); if (!separator) goto invalid_request; search_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { search_end = command; break; } } if (!search_end) goto invalid_request; replace_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { replace_end = command; break; } } if (!replace_end) goto invalid_request; command = g_utf8_next_char (command); if (*command) { for (; *command; command++) { switch (*command) { case 'g': break; /* what other options are supported? */ default: break; } } } search_text = g_strndup (search_begin, search_end - search_begin); replace_text = g_strndup (replace_begin, replace_end - replace_begin); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)); if (gtk_text_buffer_get_has_selection (buffer)) { GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_selection_bounds (buffer, &begin, &end); gtk_text_iter_order (&begin, &end); gb_vim_do_search_and_replace (buffer, &begin, &end, search_text, replace_text, FALSE); } else gb_vim_do_search_and_replace (buffer, NULL, NULL, search_text, replace_text, TRUE); g_free (search_text); g_free (replace_text); return TRUE; invalid_request: g_set_error (error, GB_VIM_ERROR, GB_VIM_ERROR_UNKNOWN_OPTION, _("Invalid search and replace request")); return FALSE; }
gboolean dump_selection_info(GtkWidget *calling_widget, text_dialog_widgets *text_widgets) { // Local variables GtkTextIter buffer_end_iter; gint buffer_end_offset; gint end_offset; gint i; guint loop_counter; GtkTextIter loop_iter; guint num_tags; GtkTextIter selection_end; GtkTextIter selection_start; gint start_offset; GSList *tag_list; gchar *tag_name; GtkTextTag *tag_ptr; GtkTextBuffer *text_buffer; gboolean text_selected; GtkWidget *text_view; // Initialisation text_view = text_widgets->text_view; text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); // If no text is selected then we skip the rest of the function text_selected = gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(text_buffer), &selection_start, &selection_end); gtk_text_iter_order(&selection_start, &selection_end); // Dump a count of tags that are present from the start to the end of the selection gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(text_buffer), &buffer_end_iter); start_offset = gtk_text_iter_get_offset(&selection_start); end_offset = gtk_text_iter_get_offset(&selection_end); buffer_end_offset = gtk_text_iter_get_offset(&buffer_end_iter); // Display separator printf("*******************\n"); printf("*******************\n"); // Display the characters up to the start of the selection (if any) for (i = 0; i < start_offset; i++) { gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(text_buffer), &loop_iter, i); tag_list = gtk_text_iter_get_tags(&loop_iter); num_tags = g_slist_length(tag_list); printf("Offset: %d\t # tags at this offset: %d\n", i, num_tags); for (loop_counter = 0; loop_counter < num_tags; loop_counter++) { tag_ptr = g_slist_nth_data(tag_list, loop_counter); if (tag_ptr->name == NULL) { printf("Anonymous tag with no name\n"); } else { tag_name = tag_ptr->name; printf("Tag name: %s\n", tag_name); } } g_slist_free(tag_list); printf("Character at this offset: %c\n", gtk_text_iter_get_char(&loop_iter)); } // Display separator printf("*** Selection start ***\n"); // Display the characters in the selection (if any) for (i = start_offset; i < end_offset; i++) { gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(text_buffer), &loop_iter, i); tag_list = gtk_text_iter_get_tags(&loop_iter); num_tags = g_slist_length(tag_list); printf("Offset: %d\t # tags at this offset: %d\n", i, num_tags); for (loop_counter = 0; loop_counter < num_tags; loop_counter++) { tag_ptr = g_slist_nth_data(tag_list, loop_counter); if (tag_ptr->name == NULL) { printf("Anonymous tag with no name\n"); } else { tag_name = tag_ptr->name; printf("Tag name: %s\n", tag_name); } } g_slist_free(tag_list); printf("Character at this offset: %c\n", gtk_text_iter_get_char(&loop_iter)); } // Display separator printf("*** Selection end ***\n"); // Display the characters after the end of the selection (if any) for (i = end_offset; i < buffer_end_offset; i++) { gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(text_buffer), &loop_iter, i); tag_list = gtk_text_iter_get_tags(&loop_iter); num_tags = g_slist_length(tag_list); printf("Offset: %d\t # tags at this offset: %d\n", i, num_tags); for (loop_counter = 0; loop_counter < num_tags; loop_counter++) { tag_ptr = g_slist_nth_data(tag_list, loop_counter); if (tag_ptr->name == NULL) { printf("Anonymous tag with no name\n"); } else { tag_name = tag_ptr->name; printf("Tag name: %s\n", tag_name); } } g_slist_free(tag_list); printf("Character at this offset: %c\n", gtk_text_iter_get_char(&loop_iter)); } // Add a newline separator to help space things visually in the dump printf("\n"); return FALSE; }