/* * 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; }
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; }
/* 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; } } }
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; }
/** * 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; }
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 (©); gtk_text_iter_backward_char (©); if (gtk_text_iter_get_char (©) == '/') return NULL; copy = *begin; if (gtk_text_iter_backward_search (©, "<", 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 (©); text = gtk_text_iter_get_slice (&match_begin, ©); 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; }
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; }
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); } } }
/** @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; }
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, ¤t, &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, ¤t); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), ¤t, 0.0, TRUE, 0.0, 0.0 ); /*move current to end*/ current = end; break; case 0:/*search backward*/ found = gtk_text_iter_backward_search( ¤t, needle, GTK_TEXT_SEARCH_VISIBLE_ONLY, ¤t, &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, ¤t); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), ¤t, 0.0, TRUE, 0.0, 0.0 ); break; default: break; } }