static void print_iter(char *name, GtkTextIter *iter) { g_print("%1s[%d%c%c%c] ", name, gtk_text_iter_get_offset(iter), gtk_text_iter_starts_word(iter) ? 's' : ' ', gtk_text_iter_inside_word(iter) ? 'i' : ' ', gtk_text_iter_ends_word(iter) ? 'e' : ' '); }
bool Gobby::FindDialog::find_range(const GtkTextIter* from, const GtkTextIter* to, SearchDirection direction, GtkTextIter* match_start, GtkTextIter* match_end) { GtkTextIter start_pos = *from; while(find_range_once(&start_pos, to, direction, match_start, match_end)) { if(m_check_whole_word->get_active() ) { if(!gtk_text_iter_starts_word(match_start) || !gtk_text_iter_ends_word(match_end)) { if(direction == SEARCH_FORWARD) start_pos = *match_end; else start_pos = *match_start; continue; } } return true; } return false; }
gboolean _gtk_source_iter_ends_extra_natural_word (const GtkTextIter *iter, gboolean visible) { GtkTextIter prev; gboolean ends_word; prev = *iter; if (!backward_cursor_position (&prev, visible)) { return FALSE; } ends_word = gtk_text_iter_ends_word (iter); if (gtk_text_iter_is_end (iter)) { return ends_word || gtk_text_iter_get_char (&prev) == '_'; } if (ends_word) { return gtk_text_iter_get_char (iter) != '_'; } return (gtk_text_iter_get_char (&prev) == '_' && gtk_text_iter_get_char (iter) != '_' && !gtk_text_iter_starts_word (iter)); }
static void do_title_case (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) { GString *s = g_string_new (NULL); while (!gtk_text_iter_is_end (start) && !gtk_text_iter_equal (start, end)) { gunichar c, nc; c = gtk_text_iter_get_char (start); if (gtk_text_iter_starts_word (start)) nc = g_unichar_totitle (c); else nc = g_unichar_tolower (c); g_string_append_unichar (s, nc); gtk_text_iter_forward_char (start); } gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len); g_string_free (s, TRUE); }
static void update_words (ExampleAppWindow *win) { ExampleAppWindowPrivate *priv; GHashTable *strings; GHashTableIter iter; GtkWidget *tab, *view, *row; GtkTextBuffer *buffer; GtkTextIter start, end; GList *children, *l; gchar *word, *key; priv = example_app_window_get_instance_private (win); tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); if (tab == NULL) return; view = gtk_bin_get_child (GTK_BIN (tab)); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); gtk_text_buffer_get_start_iter (buffer, &start); while (!gtk_text_iter_is_end (&start)) { while (!gtk_text_iter_starts_word (&start)) { if (!gtk_text_iter_forward_char (&start)) goto done; } end = start; if (!gtk_text_iter_forward_word_end (&end)) goto done; word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); g_hash_table_add (strings, g_utf8_strdown (word, -1)); g_free (word); start = end; } done: children = gtk_container_get_children (GTK_CONTAINER (priv->words)); for (l = children; l; l = l->next) gtk_container_remove (GTK_CONTAINER (priv->words), GTK_WIDGET (l->data)); g_list_free (children); g_hash_table_iter_init (&iter, strings); while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL)) { row = gtk_button_new_with_label (key); g_signal_connect (row, "clicked", G_CALLBACK (find_word), win); gtk_widget_show (row); gtk_container_add (GTK_CONTAINER (priv->words), row); } g_hash_table_unref (strings); }
static void get_cur_word_extents(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) { gtk_text_buffer_get_iter_at_mark(buffer, start, gtk_text_buffer_get_insert(buffer)); if (!gtk_text_iter_starts_word(start)) gtk_text_iter_backward_word_start(start); *end = *start; if (gtk_text_iter_inside_word(end)) gtk_text_iter_forward_word_end(end); }
static void update_current (GeditDocument *doc, gint current) { CheckRange *range; GtkTextIter iter; GtkTextIter end_iter; gedit_debug (DEBUG_PLUGINS); g_return_if_fail (doc != NULL); g_return_if_fail (current >= 0); range = get_check_range (doc); g_return_if_fail (range != NULL); gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &iter, current); if (!gtk_text_iter_inside_word (&iter)) { /* if we're not inside a word, * we must be in some spaces. * skip forward to the beginning of the next word. */ if (!gtk_text_iter_is_end (&iter)) { gtk_text_iter_forward_word_end (&iter); gtk_text_iter_backward_word_start (&iter); } } else { if (!gtk_text_iter_starts_word (&iter)) gtk_text_iter_backward_word_start (&iter); } gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &end_iter, range->end_mark); if (gtk_text_iter_compare (&end_iter, &iter) < 0) { gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, &end_iter); } else { gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, &iter); } }
static void check_range(GtkSpell *spell, GtkTextBuffer *buffer, GtkTextIter start, GtkTextIter end) { /* we need to "split" on word boundaries. * luckily, pango knows what "words" are * so we don't have to figure it out. */ GtkTextIter wstart, wend; if (debug) { g_print("check_range: "); print_iter("s", &start); print_iter("e", &end); g_print(" -> "); } if (gtk_text_iter_inside_word(&end)) gtk_text_iter_forward_word_end(&end); if (!gtk_text_iter_starts_word(&start)) { if (gtk_text_iter_inside_word(&start) || gtk_text_iter_ends_word(&start)) { gtk_text_iter_backward_word_start(&start); } else { /* if we're neither at the beginning nor inside a word, * me must be in some spaces. * skip forward to the beginning of the next word. */ //gtk_text_buffer_remove_tag(buffer, tag_highlight, &start, &end); if (gtk_text_iter_forward_word_end(&start)) gtk_text_iter_backward_word_start(&start); } } gtk_text_buffer_remove_tag(buffer, spell->tag_highlight, &start, &end); if (debug) {print_iter("s", &start); print_iter("e", &end); g_print("\n");} wstart = start; while (gtk_text_iter_compare(&wstart, &end) < 0) { /* move wend to the end of the current word. */ wend = wstart; gtk_text_iter_forward_word_end(&wend); check_word(spell, buffer, &wstart, &wend); /* now move wend to the beginning of the next word, */ gtk_text_iter_forward_word_end(&wend); gtk_text_iter_backward_word_start(&wend); /* make sure we've actually advanced * (we don't advance in some corner cases), */ if (gtk_text_iter_equal(&wstart, &wend)) break; /* we're done in these cases.. */ /* and then pick this as the new next word beginning. */ wstart = wend; } }
static void insert_link_tags(GtkTextBuffer *buffer, const GtkTextIter *begin, const GtkTextIter *end) { GtkTextIter iter = *begin; while(gtk_text_iter_compare(&iter, end) < 0) { if(gtk_text_iter_starts_word(&iter) && ( word_starts_with(&iter, "http://") || word_starts_with(&iter, "https://") || word_starts_with(&iter, "ftp://") || word_starts_with(&iter, "ftps://"))) { GtkTextIter uri_begin = iter; if(gtk_text_iter_forward_find_char(&iter, is_space, NULL, end)) { gtk_text_buffer_apply_tag_by_name(buffer, "link", &uri_begin, &iter); } } gtk_text_iter_forward_char(&iter); } }
static void get_word_extents_from_mark (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GtkTextMark *mark) { gtk_text_buffer_get_iter_at_mark(buffer, start, mark); if (!gtk_text_iter_starts_word (start)) gtk_text_iter_backward_word_start (start); *end = *start; if (gtk_text_iter_inside_word (end)) gtk_text_iter_forward_word_end (end); }
void gimp_text_tool_editor_button_press (GimpTextTool *text_tool, gdouble x, gdouble y, GimpButtonPressType press_type) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; gimp_text_tool_xy_to_iter (text_tool, x, y, &cursor); selection = cursor; text_tool->select_start_iter = cursor; text_tool->select_words = FALSE; text_tool->select_lines = FALSE; switch (press_type) { case GIMP_BUTTON_PRESS_NORMAL: gtk_text_buffer_place_cursor (buffer, &cursor); break; case GIMP_BUTTON_PRESS_DOUBLE: text_tool->select_words = TRUE; if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); if (! gtk_text_iter_ends_word (&selection) && ! gtk_text_iter_forward_visible_word_ends (&selection, 1)) gtk_text_iter_forward_to_line_end (&selection); gtk_text_buffer_select_range (buffer, &cursor, &selection); break; case GIMP_BUTTON_PRESS_TRIPLE: text_tool->select_lines = TRUE; gtk_text_iter_set_line_offset (&cursor, 0); gtk_text_iter_forward_to_line_end (&selection); gtk_text_buffer_select_range (buffer, &cursor, &selection); break; } }
/* Extends the definition of a natural-language word used by Pango. The * underscore is added to the possible characters of a natural-language word. */ void _gtk_source_iter_forward_extra_natural_word_end (GtkTextIter *iter) { GtkTextIter next_word_end = *iter; GtkTextIter next_underscore_end = *iter; GtkTextIter *limit = NULL; gboolean found; if (gtk_text_iter_forward_visible_word_end (&next_word_end)) { limit = &next_word_end; } found = gtk_text_iter_forward_search (iter, "_", GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY, NULL, &next_underscore_end, limit); if (found) { *iter = next_underscore_end; } else { *iter = next_word_end; } while (TRUE) { if (gtk_text_iter_get_char (iter) == '_') { gtk_text_iter_forward_visible_cursor_position (iter); } else if (gtk_text_iter_starts_word (iter)) { gtk_text_iter_forward_visible_word_end (iter); } else { break; } } }
gboolean ide_editor_spell_utils_text_iter_inside_word (const GtkTextIter *iter) { g_return_val_if_fail (iter != NULL, FALSE); if (gtk_text_iter_inside_word (iter)) return TRUE; if (gtk_text_iter_ends_word (iter) && is__text_iter_apostrophe_or_dash (iter)) { GtkTextIter next_char = *iter; gtk_text_iter_forward_char (&next_char); return gtk_text_iter_starts_word (&next_char); } return FALSE; }
gboolean ide_editor_spell_utils_text_iter_starts_word (const GtkTextIter *iter) { GtkTextIter prev_char; g_return_val_if_fail (iter != NULL, FALSE); if (!gtk_text_iter_starts_word (iter)) return FALSE; prev_char = *iter; if (!gtk_text_iter_backward_char (&prev_char)) return TRUE; if (is__text_iter_apostrophe_or_dash (&prev_char) && gtk_text_iter_ends_word (&prev_char)) return FALSE; return TRUE; }
gboolean mousepad_util_iter_starts_word (const GtkTextIter *iter) { GtkTextIter prev; /* normal gtk word start */ if (!gtk_text_iter_starts_word (iter)) return FALSE; /* init iter for previous char */ prev = *iter; /* return true when we could not step backwards (start of buffer) */ if (!gtk_text_iter_backward_char (&prev)) return TRUE; /* check if the previous char also belongs to the word */ if (mousepad_util_iter_word_characters (&prev)) return FALSE; return TRUE; }
gboolean ide_editor_spell_utils_text_iter_forward_word_end (GtkTextIter *iter) { g_return_val_if_fail (iter != NULL, FALSE); while (gtk_text_iter_forward_word_end (iter)) { GtkTextIter next_char; if (!is__text_iter_apostrophe_or_dash (iter)) return TRUE; next_char = *iter; gtk_text_iter_forward_char (&next_char); if (!gtk_text_iter_starts_word (&next_char)) return TRUE; *iter = next_char; } return FALSE; }
gboolean gbp_spell_utils_text_iter_ends_word (const GtkTextIter *iter) { GtkTextIter next_char; g_return_val_if_fail (iter != NULL, FALSE); if (!gtk_text_iter_ends_word (iter)) return FALSE; if (gtk_text_iter_is_end (iter)) return TRUE; next_char = *iter; gtk_text_iter_forward_char (&next_char); if (is__text_iter_apostrophe_or_dash (iter) && gtk_text_iter_starts_word (&next_char)) return FALSE; return TRUE; }
static gint console_complete_word (GtkTextBuffer *buf, GtkTextIter *iter) { GtkTextIter start, end; const char *targ = NULL; gchar *src; start = end = *iter; if (!gtk_text_iter_starts_word(&start)) { gtk_text_iter_backward_word_start(&start); } if (!gtk_text_iter_ends_word(&end)) { gtk_text_iter_forward_word_end(&end); } src = gtk_text_buffer_get_text(buf, &start, &end, FALSE); if (src != NULL && *src != '\0') { if (gtk_text_iter_get_line_offset(&start) == 2) { /* first word on line */ targ = gretl_command_complete(src); } else { targ = console_varname_complete(src); } if (targ != NULL) { gtk_text_buffer_delete(buf, &start, &end); gtk_text_buffer_insert(buf, &start, targ, -1); } else { console_beep(); } } g_free(src); return TRUE; }
static void remove_tag_to_word (GeditAutomaticSpellChecker *spell, const gchar *word) { GtkTextIter iter; GtkTextIter match_start, match_end; gboolean found; gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (spell->doc), &iter, 0); found = TRUE; while (found) { found = gtk_text_iter_forward_search (&iter, word, GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, NULL); if (found) { if (gtk_text_iter_starts_word (&match_start) && gtk_text_iter_ends_word (&match_end)) { gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &match_start, &match_end); } iter = match_end; } } }
/** @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; }
bool searchwords_find_fast (const ustring& text, const vector <ustring>& searchwords, const vector <bool>& wholewords, const vector <bool>& casesensitives, vector <size_t>& startpositions, vector <size_t>& lengths) // Finds occurrences of searchwords in the text. // text: Text to be looked through. // searchwords: Search words to look for. // wholewords / casesensitives: Attributes of the searchwords. // startpositions: If non-NULL, will be filled with the positions that each searchword starts at. // lengths: If non-NULL, will be filled with the lengths of the searchwords found. // Returns whether one or more searchwords were found in the text. { // Clear output containers. startpositions.clear(); lengths.clear(); // A textbuffer makes searching text easier in this case. GtkTextBuffer * textbuffer = gtk_text_buffer_new (NULL); gtk_text_buffer_set_text (textbuffer, text.c_str(), -1); GtkTextIter startiter; gtk_text_buffer_get_start_iter(textbuffer, &startiter); bool found = false; // Go through all words to look for. for (unsigned int i2 = 0; i2 < searchwords.size(); i2++) { // Define this search word and its parameters. ustring searchword = searchwords[i2]; bool wholeword = wholewords[i2]; bool casesensitive = casesensitives[i2]; // Handle case sensitivity. ustring mytext; ustring mysearchword; if (casesensitive) { mytext = text; mysearchword = searchword; } else { mytext = text.casefold(); mysearchword = searchword.casefold(); } // Find all occurrences of the word. size_t position = mytext.find(mysearchword); while (position != string::npos) { bool temporally_approved = true; GtkTextIter approvedstart = startiter; GtkTextIter approvedend; gtk_text_iter_forward_chars(&approvedstart, position); approvedend = approvedstart; gtk_text_iter_forward_chars(&approvedend, searchword.length()); if (wholeword) { if (!gtk_text_iter_starts_word(&approvedstart)) temporally_approved = false; if (!gtk_text_iter_ends_word(&approvedend)) temporally_approved = false; } if (temporally_approved) { found = true; startpositions.push_back (position); lengths.push_back (searchword.length()); } position = mytext.find(mysearchword, ++position); } } // Free textbuffer used. g_object_unref (textbuffer); if (found) { // Sort the output. quick_sort (startpositions, lengths, 0, (unsigned int)startpositions.size()); // Overlapping items need to be combined to avoid crashes. xml_combine_overlaps (startpositions, lengths); } // Return true if anything was found. return found; }
static void check_range (GeditAutomaticSpellChecker *spell, GtkTextIter start, GtkTextIter end, gboolean force_all) { /* we need to "split" on word boundaries. * luckily, Pango knows what "words" are * so we don't have to figure it out. */ GtkTextIter wstart; GtkTextIter wend; GtkTextIter cursor; GtkTextIter precursor; gboolean highlight; /* g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start), gtk_text_iter_get_offset (&end)); */ if (gtk_text_iter_inside_word (&end)) gtk_text_iter_forward_word_end (&end); if (!gtk_text_iter_starts_word (&start)) { if (gtk_text_iter_inside_word (&start) || gtk_text_iter_ends_word (&start)) { gtk_text_iter_backward_word_start (&start); } else { /* if we're neither at the beginning nor inside a word, * me must be in some spaces. * skip forward to the beginning of the next word. */ if (gtk_text_iter_forward_word_end (&start)) gtk_text_iter_backward_word_start (&start); } } gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &cursor, gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc))); precursor = cursor; gtk_text_iter_backward_char (&precursor); highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) || gtk_text_iter_has_tag (&precursor, spell->tag_highlight); gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end); /* Fix a corner case when replacement occurs at beginning of buffer: * An iter at offset 0 seems to always be inside a word, * even if it's not. Possibly a pango bug. */ if (gtk_text_iter_get_offset (&start) == 0) { gtk_text_iter_forward_word_end(&start); gtk_text_iter_backward_word_start(&start); } wstart = start; while (gedit_spell_utils_skip_no_spell_check (&wstart, &end) && gtk_text_iter_compare (&wstart, &end) < 0) { gboolean inword; /* move wend to the end of the current word. */ wend = wstart; gtk_text_iter_forward_word_end (&wend); inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) && (gtk_text_iter_compare (&cursor, &wend) <= 0); if (inword && !force_all) { /* this word is being actively edited, * only check if it's already highligted, * otherwise defer this check until later. */ if (highlight) check_word (spell, &wstart, &wend); else spell->deferred_check = TRUE; } else { check_word (spell, &wstart, &wend); spell->deferred_check = FALSE; } /* now move wend to the beginning of the next word, */ gtk_text_iter_forward_word_end (&wend); gtk_text_iter_backward_word_start (&wend); /* make sure we've actually advanced * (we don't advance in some corner cases), */ if (gtk_text_iter_equal (&wstart, &wend)) break; /* we're done in these cases.. */ /* and then pick this as the new next word beginning. */ wstart = wend; } }
static void gimp_text_tool_delete_from_cursor (GimpTextTool *text_tool, GtkDeleteType type, gint count) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter end; GIMP_LOG (TEXT_EDITING, "%s count = %d", g_enum_get_value (g_type_class_ref (GTK_TYPE_DELETE_TYPE), type)->value_name, count); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); end = cursor; switch (type) { case GTK_DELETE_CHARS: if (gtk_text_buffer_get_has_selection (buffer)) { gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); return; } else { gtk_text_iter_forward_cursor_positions (&end, count); } break; case GTK_DELETE_WORD_ENDS: if (count < 0) { if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); } else if (count > 0) { if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); } break; case GTK_DELETE_WORDS: if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); break; case GTK_DELETE_DISPLAY_LINES: break; case GTK_DELETE_DISPLAY_LINE_ENDS: break; case GTK_DELETE_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&end)) gtk_text_iter_forward_to_line_end (&end); else gtk_text_iter_forward_cursor_positions (&end, 1); } break; case GTK_DELETE_PARAGRAPHS: break; case GTK_DELETE_WHITESPACE: find_whitepace_region (&cursor, &cursor, &end); break; } if (! gtk_text_iter_equal (&cursor, &end)) { gtk_text_buffer_delete_interactive (buffer, &cursor, &end, TRUE); } }
void gimp_text_tool_editor_motion (GimpTextTool *text_tool, gdouble x, gdouble y) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter old_cursor; GtkTextIter old_selection; GtkTextIter cursor; GtkTextIter selection; gtk_text_buffer_get_iter_at_mark (buffer, &old_cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &old_selection, gtk_text_buffer_get_selection_bound (buffer)); gimp_text_tool_xy_to_iter (text_tool, x, y, &cursor); selection = text_tool->select_start_iter; if (text_tool->select_words || text_tool->select_lines) { GtkTextIter start; GtkTextIter end; if (gtk_text_iter_compare (&cursor, &selection) < 0) { start = cursor; end = selection; } else { start = selection; end = cursor; } if (text_tool->select_words) { if (! gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_visible_word_starts (&start, 1); if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); } else if (text_tool->select_lines) { gtk_text_iter_set_line_offset (&start, 0); gtk_text_iter_forward_to_line_end (&end); } if (gtk_text_iter_compare (&cursor, &selection) < 0) { cursor = start; selection = end; } else { selection = start; cursor = end; } } if (! gtk_text_iter_equal (&cursor, &old_cursor) || ! gtk_text_iter_equal (&selection, &old_selection)) { gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gtk_text_buffer_select_range (buffer, &cursor, &selection); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } }
/** * gail_text_util_get_text: * @textutil: A #GailTextUtil * @layout: A gpointer which is a PangoLayout, a GtkTreeView of NULL * @function: An enumeration specifying whether to return the text before, at, or * after the offset. * @boundary_type: The boundary type. * @offset: The offset of the text in the GailTextUtil * @start_offset: Address of location in which the start offset is returned * @end_offset: Address of location in which the end offset is returned * * This function gets the requested substring from the text in the GtkTextUtil. * The layout is used only for getting the text on a line. The value is NULL * for a GtkTextView which is not wrapped, is a GtkTextView for a GtkTextView * which is wrapped and is a PangoLayout otherwise. * * Returns: the substring requested **/ gchar* gail_text_util_get_text (GailTextUtil *textutil, gpointer layout, GailOffsetType function, AtkTextBoundary boundary_type, gint offset, gint *start_offset, gint *end_offset) { GtkTextIter start, end; gint line_number; GtkTextBuffer *buffer; g_return_val_if_fail (GAIL_IS_TEXT_UTIL (textutil), NULL); buffer = textutil->buffer; if (buffer == NULL) { *start_offset = 0; *end_offset = 0; return NULL; } if (!gtk_text_buffer_get_char_count (buffer)) { *start_offset = 0; *end_offset = 0; return g_strdup (""); } gtk_text_buffer_get_iter_at_offset (buffer, &start, offset); end = start; switch (function) { case GAIL_BEFORE_OFFSET: switch (boundary_type) { case ATK_TEXT_BOUNDARY_CHAR: gtk_text_iter_backward_char(&start); break; case ATK_TEXT_BOUNDARY_WORD_START: if (!gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_word_start (&start); end = start; gtk_text_iter_backward_word_start(&start); break; case ATK_TEXT_BOUNDARY_WORD_END: if (gtk_text_iter_inside_word (&start) && !gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_word_start (&start); while (!gtk_text_iter_ends_word (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } end = start; gtk_text_iter_backward_word_start(&start); while (!gtk_text_iter_ends_word (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } break; case ATK_TEXT_BOUNDARY_SENTENCE_START: if (!gtk_text_iter_starts_sentence (&start)) gtk_text_iter_backward_sentence_start (&start); end = start; gtk_text_iter_backward_sentence_start (&start); break; case ATK_TEXT_BOUNDARY_SENTENCE_END: if (gtk_text_iter_inside_sentence (&start) && !gtk_text_iter_starts_sentence (&start)) gtk_text_iter_backward_sentence_start (&start); while (!gtk_text_iter_ends_sentence (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } end = start; gtk_text_iter_backward_sentence_start (&start); while (!gtk_text_iter_ends_sentence (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } break; case ATK_TEXT_BOUNDARY_LINE_START: if (layout == NULL) { line_number = gtk_text_iter_get_line (&start); if (line_number == 0) { gtk_text_buffer_get_iter_at_offset (buffer, &start, 0); } else { gtk_text_iter_backward_line (&start); gtk_text_iter_forward_line (&start); } end = start; gtk_text_iter_backward_line (&start); } else if GTK_IS_TEXT_VIEW (layout) { GtkTextView *view = GTK_TEXT_VIEW (layout); gtk_text_view_backward_display_line_start (view, &start); end = start; gtk_text_view_backward_display_line (view, &start); } else if (PANGO_IS_LAYOUT (layout)) get_pango_text_offsets (PANGO_LAYOUT (layout), buffer, function, boundary_type, offset, start_offset, end_offset, &start, &end); break; case ATK_TEXT_BOUNDARY_LINE_END: if (layout == NULL) { line_number = gtk_text_iter_get_line (&start); if (line_number == 0) { gtk_text_buffer_get_iter_at_offset (buffer, &start, 0); end = start; } else { gtk_text_iter_backward_line (&start); end = start; while (!gtk_text_iter_ends_line (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } gtk_text_iter_forward_to_line_end (&end); } } else if GTK_IS_TEXT_VIEW (layout) { GtkTextView *view = GTK_TEXT_VIEW (layout); gtk_text_view_backward_display_line_start (view, &start); if (!gtk_text_iter_is_start (&start)) { gtk_text_view_backward_display_line (view, &start); end = start; if (!gtk_text_iter_is_start (&start)) { gtk_text_view_backward_display_line (view, &start); gtk_text_view_forward_display_line_end (view, &start); } gtk_text_view_forward_display_line_end (view, &end); } else { end = start; } } else if (PANGO_IS_LAYOUT (layout)) get_pango_text_offsets (PANGO_LAYOUT (layout), buffer, function, boundary_type, offset, start_offset, end_offset, &start, &end); break; }
void Highlight::searchwords_find_slow(GtkTextBuffer * textbuffer, GtkTextIter * beginbound, GtkTextIter * endbound, const ustring & searchword, bool casesensitive, bool globbing, bool matchbegin, bool matchend, vector < GtkTextIter > &wordstart, vector < GtkTextIter > &wordend) /* Searches for words to highlight. Problem when case insensitive searching: Character ffi was changed to ffi after casefolding, and as that one is 2 characters longer than the original ffi, we ran in problems of searching past the line, which gave an exception in Gtk. The solution was to determine the length of the word from the ones that are to highlight, not from the casefolded searchword, but the original one. */ { // Variable. GtkTextIter begin; GtkTextIter end; // Extract the line. ustring line = gtk_text_buffer_get_slice(textbuffer, beginbound, endbound, false); // Find all places in this line that have the search word. /* To do that properly for glob-style pattern matching, for begin/end word matching and case (in)sensitivity, we need to open the box of tricks. We produce all possible combinations for characters and lengths, e.g. We have this text: he is We then make the following strings from it, and see whether they match: "h" "he" "he " "he i" "he is" "e" "e " "e i" "e is" " " " i" " is" "i" "is" "s" Any string matching will then be highlighted. */ // Deal with case sensitivity. ustring case_considerate_search_word(searchword); if (!casesensitive) case_considerate_search_word = case_considerate_search_word.casefold(); for (unsigned int i = 0; i < line.length(); i++) { if (interrupt_thread) continue; ustring line2(line.substr(0, i + 1)); for (unsigned int offposition = 0; offposition < line2.length(); offposition++) { // Get the line as described above. // We use optimization here to get the speed acceptable when we have // long lines. But when globbing is done, because of the characters of // glob-style matching, we don't know how long the searchword might be, // we do not use that optimization. unsigned int linelength = line2.length() - offposition; if (!globbing) if (linelength > searchword.length()) continue; ustring compareline(line2.substr(offposition, linelength)); // Deal with case sensitivity. if (!casesensitive) compareline = compareline.casefold(); // Now compare. bool match = false; if (globbing) { if (g_pattern_match_simple(case_considerate_search_word.c_str(), compareline.c_str())) match = true; } else { if (case_considerate_search_word == compareline) match = true; } // Get the iterators in the textbuffer that belong to this possible match. if (match) { begin = *beginbound; gtk_text_iter_forward_chars(&begin, offposition); end = begin; gtk_text_iter_forward_chars(&end, searchword.length()); } // Deal with begin-word matching. if (match) { if (matchbegin) { if (!gtk_text_iter_starts_word(&begin)) match = false; } } // Deal with end-word matching. if (match) { if (matchend) { if (!gtk_text_iter_ends_word(&end)) match = false; } } // Add the boundaries of the word to highlight. if (match) { wordstart.push_back(begin); wordend.push_back(end); } } } }
bool WindowCheckKeyterms::find_renderings (const ustring& text, const vector <ustring>& renderings, const vector <bool>& wholewords, const vector <bool>& casesensitives, vector <size_t> * startpositions, vector <size_t> * lengths) // Finds renderings in the text. // text: Text to be looked into. // renderings: Renderings to look for. // wholewords / casesensitives: Attributes of the renderings. // startpositions: If non-NULL, will be filled with the positions that each rendering starts at. // lengths: If non-NULL, will be filled with the lengths of the renderings found. // Returns whether one or more renderings were found in the verse. { if (startpositions) startpositions->clear(); if (lengths) lengths->clear(); GtkTextBuffer * textbuffer = gtk_text_buffer_new (NULL); gtk_text_buffer_set_text (textbuffer, text.c_str(), -1); GtkTextIter startiter; gtk_text_buffer_get_start_iter(textbuffer, &startiter); bool found = false; for (unsigned int i2 = 0; i2 < renderings.size(); i2++) { ustring rendering = renderings[i2]; bool wholeword = wholewords[i2]; bool casesensitive = casesensitives[i2]; ustring mytext; ustring myrendering; if (casesensitive) { mytext = text; myrendering = rendering; } else { mytext = text.casefold(); myrendering = rendering.casefold(); } size_t position = mytext.find(myrendering); while (position != string::npos) { bool temporally_approved = true; GtkTextIter approvedstart = startiter; GtkTextIter approvedend; gtk_text_iter_forward_chars(&approvedstart, position); approvedend = approvedstart; gtk_text_iter_forward_chars(&approvedend, rendering.length()); if (wholeword) { if (!gtk_text_iter_starts_word(&approvedstart)) temporally_approved = false; if (!gtk_text_iter_ends_word(&approvedend)) temporally_approved = false; } if (temporally_approved) { found = true; if (startpositions) startpositions->push_back (position); if (lengths) lengths->push_back (rendering.length()); } position = mytext.find(myrendering, ++position); } } g_object_unref (textbuffer); return found; }
void my_text_buffer_highlight(GtkTextBuffer *buffer, char *word, short mode) { /*mode: 0:title/occurance 1:title 2:keyword, 3:invisible 4:highlight 5:normal others:normal*/ gboolean found = TRUE, titled = FALSE; GtkTextTag *tag = occurance; gtk_text_buffer_get_iter_at_offset(text2, &start, 0); current = start; end = start; #ifdef MinGW int zhTitle = 0; int isTitle = 0; #endif while(found) { found = gtk_text_iter_forward_search( &end, word, GTK_TEXT_SEARCH_VISIBLE_ONLY, ¤t, &end, NULL); if(found) { #ifdef MinGW /*check zh char*/ char *sample = gtk_text_iter_get_slice (¤t, &end); int sampleLen = strlen(sample); if( testZh(sample, sampleLen)) zhTitle = 1; #endif /*title or body*/ if(1== mode || (0 == mode && !titled && 0 == gtk_text_iter_get_line(¤t))) { #ifdef MinGW isTitle = 1; #endif tag = title; titled = TRUE; } else if( 0 == mode ) { tag = occurance; } else if( 2 == mode) { #ifdef MinGW /*keyword, pretend title to use better font*/ isTitle = 1; #endif tag = keyword; } else if( 3 == mode) { tag = invisible; #ifdef MinGW zhTitle = 0; isTitle = 0; #endif } else if( 4 == mode) { tag = highlight; } else if( 5 == mode) { tag = normal; /* will do remove-tag after extending to full word */ } else { tag = normal; #ifdef MinGW zhTitle = 0; isTitle = 0; #endif } /*extend word*/ if( 2 != mode && 3 != mode && !gtk_text_iter_starts_word(¤t)) { gtk_text_iter_backward_visible_word_start(¤t); } if(2 != mode && 3 != mode && !gtk_text_iter_ends_word(&end)) { gtk_text_iter_forward_visible_word_end(&end); } if (5 == mode) { gtk_text_buffer_remove_tag (buffer, highlight, ¤t, &end); } #ifdef MinGW /*Clear default_font to allow better font only when no zh chars present*/ if( !zhTitle && isTitle ) gtk_text_buffer_remove_tag (buffer, default_font, ¤t, &end); #endif gtk_text_buffer_apply_tag(buffer, tag, ¤t, &end); } } current = start; end = start; }