static void
chat_text_view_highlight (EmpathyChatView *view,
			    const gchar     *text,
			    gboolean         match_case)
{
	GtkTextBuffer *buffer;
	GtkTextIter    iter;
	GtkTextIter    iter_start;
	GtkTextIter    iter_end;
	GtkTextIter    iter_match_start;
	GtkTextIter    iter_match_end;
	gboolean       found;

	g_return_if_fail (EMPATHY_IS_CHAT_TEXT_VIEW (view));

	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

	gtk_text_buffer_get_start_iter (buffer, &iter);

	gtk_text_buffer_get_bounds (buffer, &iter_start, &iter_end);
	gtk_text_buffer_remove_tag_by_name (buffer, EMPATHY_CHAT_TEXT_VIEW_TAG_HIGHLIGHT,
					    &iter_start,
					    &iter_end);

	if (EMP_STR_EMPTY (text)) {
		return;
	}

	while (1) {
		if (match_case) {
			found = gtk_text_iter_forward_search (&iter,
							      text,
							      0,
							      &iter_match_start,
							      &iter_match_end,
							      NULL);
		} else {
			found = empathy_text_iter_forward_search (&iter,
								  text,
								  &iter_match_start,
								  &iter_match_end,
								  NULL);
		}
		if (!found) {
			break;
		}

		gtk_text_buffer_apply_tag_by_name (buffer, EMPATHY_CHAT_TEXT_VIEW_TAG_HIGHLIGHT,
						   &iter_match_start,
						   &iter_match_end);

		iter = iter_match_end;
	}
}
static void
chat_text_view_find_abilities (EmpathyChatView *view,
				 const gchar    *search_criteria,
				 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);
		}
		
		*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);
		}
		
		*can_do_next = empathy_text_iter_forward_search (&iter_at_mark,
								 search_criteria,
								 &iter_match_start,
								 &iter_match_end,
								 NULL);
	}
}
static gboolean
chat_text_view_find_next (EmpathyChatView *view,
			    const gchar     *search_criteria,
			    gboolean         new_search)
{
	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_next) {
			gtk_text_buffer_get_start_iter (buffer, &iter_at_mark);
			
			gtk_text_buffer_move_mark (buffer,
						   priv->find_mark_next,
						   &iter_at_mark);
			gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
						      priv->find_mark_next,
						      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 (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);
		from_start = TRUE;
	}
	
	priv->find_last_direction = TRUE;
	
	found = empathy_text_iter_forward_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_next (view,
							     search_criteria,
							     FALSE);
			priv->find_wrapped = FALSE;
		}
		
		return result;
	}
	
	/* Set new mark and show on screen */
	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);
	}
	
	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);
	}
	
	gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
				      priv->find_mark_next,
				      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;
}