예제 #1
0
파일: editor.c 프로젝트: lemonjia/Avocado
/*
 * Search backward
 */
static gboolean editor_search_backward(const av_editor *editor,
                                       const gchar *text_search,
                                       GtkTextSearchFlags flags_search,
                                       const GtkTextIter *iter_start,
                                       const GtkTextIter *iter_end,
                                       GtkTextIter *iter_match_start,
                                       GtkTextIter *iter_match_end)
{
  GtkTextIter m_start, m_end;
  gboolean found = FALSE;

  g_return_val_if_fail(editor != NULL
                       && editor->textview != NULL
                       && editor->textbuf != NULL, FALSE);
  g_return_val_if_fail(text_search != NULL, FALSE);
  g_return_val_if_fail(iter_end != NULL, FALSE);
  g_return_val_if_fail(iter_match_start != NULL && iter_match_end != NULL, FALSE);

  found = gtk_text_iter_backward_search(iter_end,
                                       text_search,
                                       flags_search,
                                       &m_start,
                                       &m_end,
                                       iter_start);

  if (found)
  {
    *iter_match_start = m_start;
    *iter_match_end = m_end;
  }

  return found;
}
예제 #2
0
static VALUE
rg_backward_search(int argc, VALUE *argv, VALUE self)
{
    GtkTextIter m_start, m_end;
    VALUE str, flags, limit;
    gboolean ret;

    rb_scan_args(argc, argv, "21", &str, &flags, &limit);
    if (is_compat_240){
        ret = gtk_text_iter_backward_search(_SELF(self), RVAL2CSTR(str),
                                            RVAL2GFLAGS(flags, GTK_TYPE_TEXT_SEARCH_FLAGS), 
                                            &m_start, &m_end,
                                            NIL_P(limit) ? NULL : _SELF(limit));
    } else {
        ret = gtk_text_iter_backward_search(_SELF(self), RVAL2CSTR(str),
                                            RVAL2GENUM(flags, GTK_TYPE_TEXT_SEARCH_FLAGS), 
                                            &m_start, &m_end,
                                            NIL_P(limit) ? NULL : _SELF(limit));
    }
    return ret ? rb_ary_new3(2, ITR2RVAL(&m_start), ITR2RVAL(&m_end)) : Qnil;
}
예제 #3
0
/* Symmetric of iter_forward_extra_natural_word_end(). */
void
_gtk_source_iter_backward_extra_natural_word_start (GtkTextIter *iter)
{
	GtkTextIter prev_word_start = *iter;
	GtkTextIter prev_underscore_start = *iter;
	GtkTextIter *limit = NULL;
	gboolean found;

	if (gtk_text_iter_backward_visible_word_start (&prev_word_start))
	{
		limit = &prev_word_start;
	}

	found = gtk_text_iter_backward_search (iter,
					       "_",
					       GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
					       &prev_underscore_start,
					       NULL,
					       limit);

	if (found)
	{
		*iter = prev_underscore_start;
	}
	else
	{
		*iter = prev_word_start;
	}

	while (!gtk_text_iter_is_start (iter))
	{
		GtkTextIter prev = *iter;
		gtk_text_iter_backward_visible_cursor_position (&prev);

		if (gtk_text_iter_get_char (&prev) == '_')
		{
			*iter = prev;
		}
		else if (gtk_text_iter_ends_word (iter))
		{
			gtk_text_iter_backward_visible_word_start (iter);
		}
		else
		{
			break;
		}
	}
}
예제 #4
0
static gboolean
text_iter_in_cdata (const GtkTextIter *location)
{
  GtkTextIter iter = *location;
  gboolean ret = FALSE;

  if (gtk_text_iter_backward_search (&iter, "<![CDATA[",
                                     GTK_TEXT_SEARCH_TEXT_ONLY,
                                     NULL, &iter, NULL))
    {
      if (!gtk_text_iter_forward_search (&iter, "]]>",
                                         GTK_TEXT_SEARCH_TEXT_ONLY,
                                         NULL, NULL, location))
        {
          ret = TRUE;
          IDE_GOTO (cleanup);
        }
    }

cleanup:
  return ret;
}
예제 #5
0
/**
 * gtk_source_iter_backward_search:
 * @iter: a #GtkTextIter where the search begins.
 * @str: search string.
 * @flags: bitmask of flags affecting the search.
 * @match_start: return location for start of match, or %%NULL.
 * @match_end: return location for end of match, or %%NULL.
 * @limit: location of last possible @match_start, or %%NULL for start of buffer.
 * 
 * Same as gtk_text_iter_backward_search(), but supports case insensitive
 * searching.
 * 
 * Return value: whether a match was found.
 **/
gboolean
gtk_source_iter_backward_search (const GtkTextIter   *iter,
				 const gchar         *str,
				 GtkSourceSearchFlags flags,
				 GtkTextIter         *match_start,
				 GtkTextIter         *match_end,
				 const GtkTextIter   *limit)
{
	gchar **lines = NULL;
	GtkTextIter match;
	gboolean retval = FALSE;
	GtkTextIter search;
	gboolean visible_only;
	gboolean slice;

	g_return_val_if_fail (iter != NULL, FALSE);
	g_return_val_if_fail (str != NULL, FALSE);

	if ((flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE) == 0)
		return gtk_text_iter_backward_search (iter, str, flags,
						      match_start, match_end,
						      limit); 

	if (limit && gtk_text_iter_compare (iter, limit) <= 0)
		return FALSE;

	if (*str == '\0')
	{
		/* If we can move one char, return the empty string there */
		match = *iter;

		if (gtk_text_iter_backward_char (&match))
		{
			if (limit && gtk_text_iter_equal (&match, limit))
				return FALSE;

			if (match_start)
				*match_start = match;
			if (match_end)
				*match_end = match;
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	visible_only = (flags & GTK_SOURCE_SEARCH_VISIBLE_ONLY) != 0;
	slice = (flags & GTK_SOURCE_SEARCH_TEXT_ONLY) == 0;

	/* locate all lines */
	lines = strbreakup (str, "\n", -1);

	search = *iter;

	while (TRUE)
	{
		/* This loop has an inefficient worst-case, where
		 * gtk_text_iter_get_text () is called repeatedly on
		 * a single line.
		 */
		GtkTextIter end;

		if (limit && gtk_text_iter_compare (&search, limit) <= 0)
			break;

		if (backward_lines_match (&search, (const gchar**)lines,
					  visible_only, slice, &match, &end))
		{
			if (limit == NULL || (limit &&
					      gtk_text_iter_compare (&end, limit) > 0))
			{
				retval = TRUE;

				if (match_start)
					*match_start = match;
				if (match_end)
					*match_end = end;
			}
			break;
		}

		if (gtk_text_iter_get_line_offset (&search) == 0)
		{
			if (!gtk_text_iter_backward_line (&search))
				break;
		}
		else
		{
			gtk_text_iter_set_line_offset (&search, 0);
		}
	}

	g_strfreev ((gchar**)lines);

	return retval;
}
예제 #6
0
static gchar *
ide_xml_indenter_maybe_add_closing (IdeXmlIndenter *xml,
                                    GtkTextIter    *begin,
                                    GtkTextIter    *end,
                                    gint           *cursor_offset)
{
  GtkTextIter match_begin;
  GtkTextIter match_end;
  GtkTextIter copy;

  g_return_val_if_fail (IDE_IS_XML_INDENTER (xml), NULL);
  g_return_val_if_fail (begin, NULL);
  g_return_val_if_fail (end, NULL);

  copy = *begin;

  gtk_text_iter_backward_char (&copy);
  gtk_text_iter_backward_char (&copy);

  if (gtk_text_iter_get_char (&copy) == '/')
    return NULL;

  copy = *begin;

  if (gtk_text_iter_backward_search (&copy, "<", GTK_TEXT_SEARCH_TEXT_ONLY, &match_begin, &match_end, NULL))
    {
      g_autofree gchar *text = NULL;

      /* avoid closing elements on spurious > */
      gtk_text_iter_backward_char (&copy);
      text = gtk_text_iter_get_slice (&match_begin, &copy);

      if (strchr (text, '>'))
        return NULL;

      gtk_text_iter_forward_char (&match_begin);
      if (gtk_text_iter_get_char (&match_begin) == '/')
        return NULL;

      match_end = match_begin;

      if (gtk_text_iter_forward_find_char (&match_end, find_end, NULL, begin))
        {
          gchar *slice;
          gchar *ret = NULL;

          slice = gtk_text_iter_get_slice (&match_begin, &match_end);

          if (slice && *slice && *slice != '!')
            {
              if (gtk_text_iter_get_char (end) == '>')
                ret = g_strdup_printf ("</%s", slice);
              else
                ret = g_strdup_printf ("</%s>", slice);
              *cursor_offset = -strlen (ret);
            }

          g_free (slice);

          return ret;
        }
    }

  return NULL;
}
예제 #7
0
static gboolean
chat_text_view_find_previous (EmpathyChatView *view,
				const gchar     *search_criteria,
				gboolean         new_search,
				gboolean         match_case)
{
	EmpathyChatTextViewPriv *priv;
	GtkTextBuffer      *buffer;
	GtkTextIter         iter_at_mark;
	GtkTextIter         iter_match_start;
	GtkTextIter         iter_match_end;
	gboolean            found;
	gboolean            from_start = FALSE;

	g_return_val_if_fail (EMPATHY_IS_CHAT_TEXT_VIEW (view), FALSE);
	g_return_val_if_fail (search_criteria != NULL, FALSE);

	priv = GET_PRIV (view);

	buffer = priv->buffer;

	if (EMP_STR_EMPTY (search_criteria)) {
		if (priv->find_mark_previous) {
			gtk_text_buffer_get_start_iter (buffer, &iter_at_mark);

			gtk_text_buffer_move_mark (buffer,
						   priv->find_mark_previous,
						   &iter_at_mark);
			gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
						      priv->find_mark_previous,
						      0.0,
						      TRUE,
						      0.0,
						      0.0);
			gtk_text_buffer_select_range (buffer,
						      &iter_at_mark,
						      &iter_at_mark);
		}

		return FALSE;
	}

	if (new_search) {
		from_start = TRUE;
	}

	if (!new_search && priv->find_mark_previous) {
		gtk_text_buffer_get_iter_at_mark (buffer,
						  &iter_at_mark,
						  priv->find_mark_previous);
	} else {
		gtk_text_buffer_get_end_iter (buffer, &iter_at_mark);
		from_start = TRUE;
	}

	priv->find_last_direction = FALSE;

	/* Use the standard GTK+ method for case sensitive searches. It can't do
	 * case insensitive searches (see bug #61852), so keep the custom method
	 * around for case insensitive searches. */
	if (match_case) {
		found = gtk_text_iter_backward_search (&iter_at_mark,
		                                       search_criteria,
		                                       0, /* no text search flags, we want exact matches */
		                                       &iter_match_start,
		                                       &iter_match_end,
		                                       NULL);
	} else {
		found = empathy_text_iter_backward_search (&iter_at_mark,
		                                           search_criteria,
		                                           &iter_match_start,
		                                           &iter_match_end,
		                                           NULL);
	}

	if (!found) {
		gboolean result = FALSE;

		if (from_start) {
			return result;
		}

		/* Here we wrap around. */
		if (!new_search && !priv->find_wrapped) {
			priv->find_wrapped = TRUE;
			result = chat_text_view_find_previous (view,
								 search_criteria,
								 FALSE,
								 match_case);
			priv->find_wrapped = FALSE;
		}

		return result;
	}

	/* Set new mark and show on screen */
	if (!priv->find_mark_previous) {
		priv->find_mark_previous = gtk_text_buffer_create_mark (buffer, NULL,
									&iter_match_start,
									TRUE);
	} else {
		gtk_text_buffer_move_mark (buffer,
					   priv->find_mark_previous,
					   &iter_match_start);
	}

	if (!priv->find_mark_next) {
		priv->find_mark_next = gtk_text_buffer_create_mark (buffer, NULL,
								    &iter_match_end,
								    TRUE);
	} else {
		gtk_text_buffer_move_mark (buffer,
					   priv->find_mark_next,
					   &iter_match_end);
	}

	gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
				      priv->find_mark_previous,
				      0.0,
				      TRUE,
				      0.5,
				      0.5);

	gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &iter_match_start);
	gtk_text_buffer_move_mark_by_name (buffer, "insert", &iter_match_end);

	return TRUE;
}
예제 #8
0
static void
chat_text_view_find_abilities (EmpathyChatView *view,
				 const gchar    *search_criteria,
				 gboolean        match_case,
				 gboolean       *can_do_previous,
				 gboolean       *can_do_next)
{
	EmpathyChatTextViewPriv *priv;
	GtkTextBuffer           *buffer;
	GtkTextIter              iter_at_mark;
	GtkTextIter              iter_match_start;
	GtkTextIter              iter_match_end;

	g_return_if_fail (EMPATHY_IS_CHAT_TEXT_VIEW (view));
	g_return_if_fail (search_criteria != NULL);
	g_return_if_fail (can_do_previous != NULL && can_do_next != NULL);

	priv = GET_PRIV (view);

	buffer = priv->buffer;

	if (can_do_previous) {
		if (priv->find_mark_previous) {
			gtk_text_buffer_get_iter_at_mark (buffer,
							  &iter_at_mark,
							  priv->find_mark_previous);
		} else {
			gtk_text_buffer_get_start_iter (buffer, &iter_at_mark);
		}

		if (match_case) {
			*can_do_previous = gtk_text_iter_backward_search (&iter_at_mark,
								          search_criteria,
								          0,
								          &iter_match_start,
								          &iter_match_end,
								          NULL);
		} else {
			*can_do_previous = empathy_text_iter_backward_search (&iter_at_mark,
									      search_criteria,
									      &iter_match_start,
									      &iter_match_end,
									      NULL);
		}
	}

	if (can_do_next) {
		if (priv->find_mark_next) {
			gtk_text_buffer_get_iter_at_mark (buffer,
							  &iter_at_mark,
							  priv->find_mark_next);
		} else {
			gtk_text_buffer_get_start_iter (buffer, &iter_at_mark);
		}

		if (match_case) {
			*can_do_next = gtk_text_iter_forward_search (&iter_at_mark,
								     search_criteria,
								     0,
								     &iter_match_start,
								     &iter_match_end,
								     NULL);
		} else {
			*can_do_next = empathy_text_iter_forward_search (&iter_at_mark,
									 search_criteria,
									 &iter_match_start,
									 &iter_match_end,
									 NULL);
		}
	}
}
예제 #9
0
/**
@brief Search backward from @a iter to try to find next match of @a str in textbuffer

This is like gtk_text_iter_backward_search(), but supports case-insensitive
and whole-word searching.
See comments for e2_iter_forward_search().

@param  iter a GtkTextIter where the search begins
@param  str search string, may include 1 or more \n
@param  flags bitmask of flags affecting the search
@param  match_start return location for start of match, or NULL
@param  match_end return location for end of match, or NULL
@param  limit lower bound of match end, or NULL for start of buffer

@return TRUE if a match was found
*/
gboolean e2_iter_backward_search (
		const GtkTextIter   *iter,
		const gchar         *str,
		E2TextSearchFlags    flags,
		GtkTextIter         *match_start,
		GtkTextIter         *match_end,
		const GtkTextIter   *limit)
{
	gboolean visible_only, slice, retval;
	GtkTextIter search, match;

	g_return_val_if_fail (iter != NULL, FALSE);
	g_return_val_if_fail (str != NULL, FALSE);

	if (!(flags & E2_SEARCH_CASE_INSENSITIVE))
	{
		search = *iter;
rescan:
		retval = gtk_text_iter_backward_search (&search, str, flags,
						      match_start, match_end, limit);
		if (retval && (flags & E2_SEARCH_WHOLE_WORD)
					&& (!gtk_text_iter_starts_word (match_start)
//see comment above re end-checking when highlighting || !gtk_text_iter_ends_word (match_end)
		))
		{
			search = *match_start;
			if (gtk_text_iter_backward_char (&search))
				goto rescan;
			retval = FALSE;
		}
		return retval;
	}

	if (limit != NULL && gtk_text_iter_compare (iter, limit) < 0)
		return FALSE;

	if (*str == '\0') //matching nothing
	{
		//if we can move one char, return that location for the match
		match = *iter;
		if (gtk_text_iter_backward_char (&match))
		{
			if (limit == NULL || gtk_text_iter_compare (&match, limit) >= 0)
			{
				if (match_start != NULL)
					*match_start = match;
				if (match_end != NULL)
					*match_end = match;
				return TRUE;
			}
		}
		return FALSE;
	}

	//split search string into lines
	gchar **lines = e2_utils_str_breakup (str, "\n", -1);
	if (lines == NULL)
		return FALSE;	//FIXME warn user about error

	visible_only = (flags & E2_SEARCH_VISIBLE_ONLY) != 0;
	slice = (flags & E2_SEARCH_TEXT_ONLY) == 0;
	retval = FALSE;
	search = *iter;

	while (TRUE)
	{
		/* This loop has an inefficient worst-case, where
		   gtk_text_iter_get_text() is called repeatedly on each single line */
		GtkTextIter end;
rescan2:
		if (limit != NULL && gtk_text_iter_compare (&search, limit) < 0)
			break;

		if (_e2_textiter_backward_lines_match (&search, (const gchar**)lines,
					  visible_only, slice, &match, &end))
		{
			if (limit == NULL || gtk_text_iter_compare (&end, limit) >= 0)
			{
				if ((flags & E2_SEARCH_WHOLE_WORD) &&
				(!gtk_text_iter_starts_word (&match)
//see comment above re end-checking when highlighting || !gtk_text_iter_ends_word (&end)
					))
				{
					search = match;
					if (gtk_text_iter_backward_char (&search))
						goto rescan2;
				}
				else
				{
					retval = TRUE;
					if (match_start)
						*match_start = match;
					if (match_end)
						*match_end = end;
				}
			}
			break;
		}

		if (gtk_text_iter_get_line_offset (&search) == 0)	//at start of line
		{
			if (!gtk_text_iter_backward_line (&search))	//can't move to start of previous line
				break;
		}
		else
			gtk_text_iter_set_line_offset (&search, 0);	//go to start of current line and check again
	}

	g_strfreev (lines);

	return retval;
}
예제 #10
0
파일: myre.c 프로젝트: vobiscum/myre
void
myre_move_to_string(GtkTextBuffer *text, char *needle, int mode) {
    int found = 0;
    end = current;
    switch (mode) {
    case 1:/*search forward*/
        found = gtk_text_iter_forward_search(
                    &end,
                    needle,
                    GTK_TEXT_SEARCH_VISIBLE_ONLY,
                    &current,
                    &end,
                    NULL);
        if(!found)
            gtk_statusbar_push(status,
                               gtk_statusbar_get_context_id(status, "status"),
                               "Search forward reaches end");
        else
            gtk_statusbar_push(status,
                               gtk_statusbar_get_context_id(status, "status"),
                               needle);
        /*place cursor*/
        gtk_text_buffer_place_cursor(text, &current);
        gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), &current,
                                     0.0,
                                     TRUE,
                                     0.0,
                                     0.0
                                    );
        /*move current to end*/
        current = end;
        break;
    case 0:/*search backward*/
        found = gtk_text_iter_backward_search(
                    &current,
                    needle,
                    GTK_TEXT_SEARCH_VISIBLE_ONLY,
                    &current,
                    &end,
                    NULL);
        if(!found)
            gtk_statusbar_push(status,
                               gtk_statusbar_get_context_id(status, "status"),
                               "Search backward reaches start");
        else
            gtk_statusbar_push(status,
                               gtk_statusbar_get_context_id(status, "status"),
                               needle);
        /*place cursor*/
        gtk_text_buffer_place_cursor(text, &current);
        gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), &current,
                                     0.0,
                                     TRUE,
                                     0.0,
                                     0.0
                                    );
        break;
    default:
        break;
    }
}