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);
}
Example #2
0
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));
}
Example #3
0
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);
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
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));
}
Example #8
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));
}
Example #12
0
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;
}
Example #14
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
}