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 gboolean goto_next_word (GeditDocument *doc) { CheckRange *range; GtkTextIter current_iter; GtkTextIter old_current_iter; GtkTextIter end_iter; gedit_debug (DEBUG_PLUGINS); g_return_val_if_fail (doc != NULL, FALSE); range = get_check_range (doc); g_return_val_if_fail (range != NULL, FALSE); gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), ¤t_iter, range->current_mark); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end_iter); old_current_iter = current_iter; gtk_text_iter_forward_word_ends (¤t_iter, 2); gtk_text_iter_backward_word_start (¤t_iter); if (gedit_spell_utils_skip_no_spell_check (¤t_iter, &end_iter) && (gtk_text_iter_compare (&old_current_iter, ¤t_iter) < 0) && (gtk_text_iter_compare (¤t_iter, &end_iter) < 0)) { update_current (doc, gtk_text_iter_get_offset (¤t_iter)); return TRUE; } return FALSE; }
/** Kolorowanie słów. Słowa nie znajdujące się w słowniku - potencjalnie błędne - zostają oznaczone na czerwono. */ static void show_errors() { GtkTextIter start, end, text_end; int i, range; char *word; gunichar *wword; gtk_text_buffer_create_tag(editor_buf, "red_fg", "foreground", "red", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_get_end_iter(editor_buf, &text_end); gtk_text_buffer_get_start_iter(editor_buf, &end); range = gtk_text_buffer_get_char_count(editor_buf); while (!gtk_text_iter_is_end(&end)) { gtk_text_iter_forward_word_end(&end); start = end; gtk_text_iter_backward_word_start(&start); word = gtk_text_iter_get_text(&start, &end); wword = g_utf8_to_ucs4_fast(word, -1, NULL); if (make_lowercase(wword)) { if (!dictionary_find(dict, wword)) gtk_text_buffer_apply_tag_by_name(editor_buf, "red_fg", &start, &end); } g_free(word); g_free(wword); } }
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 gboolean gtkspell_text_iter_backward_word_start(GtkTextIter *i) { GtkTextIter iter; if (!gtk_text_iter_backward_word_start(i)) return FALSE; iter = *i; if (gtk_text_iter_backward_char(&iter)) { if (gtk_text_iter_get_char(&iter) == '\'') { if (gtk_text_iter_backward_char(&iter)) { if (g_unichar_isalpha(gtk_text_iter_get_char(&iter))) { return (gtk_text_iter_backward_word_start(i)); } } } } return TRUE; }
// Koloruje słowa nie ze słownika na czerwono static void ColorMistakes (GtkMenuItem *item, gpointer data) { GtkTextIter start, end, buffEnd; gtk_text_buffer_get_start_iter(editor_buf, &end); //Teraz sztuczką przesuwamy końcowy iterator na koniec ostatniego słowa gtk_text_buffer_get_end_iter(editor_buf, &buffEnd); gtk_text_iter_backward_word_start(&buffEnd); gtk_text_iter_forward_word_end(&buffEnd); gtk_text_buffer_create_tag(editor_buf, "red_fg", "foreground", "red", "weight", PANGO_WEIGHT_BOLD, NULL); // Aktualizacja słownika if(update_actual_dict() < 0) return; start = end; while (!gtk_text_iter_equal(&end, &buffEnd)) { // Inkrementacja zmiennych gtk_text_iter_forward_word_end(&end); start = end; gtk_text_iter_backward_word_start(&start); // Usuwamy etykietkę ze słowa jeśli jest gtk_text_buffer_remove_tag_by_name(editor_buf, "red_fg", &start, &end); // Separujemy słowo char* word = gtk_text_iter_get_text(&start, &end); gunichar* wword = g_utf8_to_ucs4_fast(word, -1, NULL); // Jeśli znaleziono w słowniku to kolorujemy if(!dictionary_find(dict, (const wchar_t*)wword)) gtk_text_buffer_apply_tag_by_name(editor_buf, "red_fg", &start, &end); g_free(word); } }
gboolean snippets_key_press_cb (GuSnippets* sc, GuEditor* ec, GdkEventKey* ev) { GtkTextIter current, start; if (ev->keyval == GDK_KEY_Tab) { gchar* key = NULL; editor_get_current_iter (ec, ¤t); if (gtk_text_iter_ends_word (¤t)) { start = current; gtk_text_iter_backward_word_start (&start); key = gtk_text_iter_get_text (&start, ¤t); if (snippets_get_value (sc, key)) { gtk_text_buffer_delete (ec_buffer, &start, ¤t); snippets_activate (sc, ec, key); g_free (key); return TRUE; } g_free (key); } } if (sc->info) { if (ev->keyval == GDK_KEY_Tab) { if (!snippet_info_goto_next_placeholder (sc->info, ec)) snippets_deactivate (sc, ec); return TRUE; } else if (ev->keyval == GDK_KEY_ISO_Left_Tab && ev->state & GDK_SHIFT_MASK) { if (!snippet_info_goto_prev_placeholder (sc->info, ec)) snippets_deactivate (sc, ec); return TRUE; } /* Deactivate snippet if the current insert range is not within the * snippet */ editor_get_current_iter (ec, ¤t); gint offset = gtk_text_iter_get_offset (¤t); GList* last = g_list_last (sc->info->einfo); if (last) { gtk_text_buffer_get_iter_at_mark (ec_buffer, ¤t, GU_SNIPPET_EXPAND_INFO (last->data)->left_mark); gint bound_end = gtk_text_iter_get_offset (¤t); if (offset < sc->info->start_offset || offset > bound_end) snippets_deactivate (sc, ec); } } return FALSE; }
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); }
gboolean ide_editor_spell_utils_text_iter_backward_word_start (GtkTextIter *iter) { g_return_val_if_fail (iter != NULL, FALSE); while (gtk_text_iter_backward_word_start (iter)) { GtkTextIter prev_char = *iter; if (!gtk_text_iter_backward_char (&prev_char) || !is__text_iter_apostrophe_or_dash (&prev_char) || !gtk_text_iter_ends_word (&prev_char)) return TRUE; *iter = prev_char; } return FALSE; }
void insert_open_brace(GtkWidget **tip_win, GtkWidget *text_view, GtkTextIter *arg1) { GdkWindow *win; GtkTextIter start; GdkRectangle buf_loc; gint x, y; gint win_x, win_y; gchar *text; gchar *tip_text; start = *arg1; if (!gtk_text_iter_backward_word_start (&start)) return; text = gtk_text_iter_get_text (&start, arg1); g_strstrip (text); tip_text = get_tip(text); if (tip_text == NULL) return; gtk_text_view_get_iter_location (GTK_TEXT_VIEW (text_view), arg1, &buf_loc); g_printf ("Buffer: %d, %d\n", buf_loc.x, buf_loc.y); gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (text_view), GTK_TEXT_WINDOW_WIDGET, buf_loc.x, buf_loc.y, &win_x, &win_y); g_printf ("Window: %d, %d\n", win_x, win_y); win = gtk_text_view_get_window (GTK_TEXT_VIEW (text_view), GTK_TEXT_WINDOW_WIDGET); gdk_window_get_origin (win, &x, &y); if (*tip_win != NULL) gtk_widget_destroy (GTK_WIDGET (*tip_win)); *tip_win = tip_window_new (tip_text); g_free(tip_text); gtk_window_move (GTK_WINDOW (*tip_win), win_x + x, win_y + y + buf_loc.height); gtk_widget_show_all (*tip_win); }
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; }
ParseWords::ParseWords(const ustring & text) // Parses a line of text in its separate words. // Note: This is comparable to object Parse, but does a better job. { // Load text into buffer. ustring text2(text); text2.append(" "); GtkTextBuffer *textbuffer; textbuffer = gtk_text_buffer_new(NULL); gtk_text_buffer_set_text(textbuffer, text2.c_str(), -1); // Iterators. GtkTextIter startiter, enditer; // Parse into separate words. gtk_text_buffer_get_start_iter(textbuffer, &enditer); while (gtk_text_iter_forward_word_end(&enditer)) { startiter = enditer; gtk_text_iter_backward_word_start(&startiter); ustring word = gtk_text_iter_get_text(&startiter, &enditer); words.push_back(word); } // Free memory g_object_unref(textbuffer); }
gboolean xed_spell_utils_skip_no_spell_check (GtkTextIter *start, GtkTextIter *end) { GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (start)); while (gtk_source_buffer_iter_has_context_class (buffer, start, "no-spell-check")) { GtkTextIter last = *start; if (!gtk_source_buffer_iter_forward_to_context_class_toggle (buffer, start, "no-spell-check")) { return FALSE; } if (gtk_text_iter_compare (start, &last) <= 0) { return FALSE; } gtk_text_iter_forward_word_end (start); gtk_text_iter_backward_word_start (start); if (gtk_text_iter_compare (start, &last) <= 0) { return FALSE; } if (gtk_text_iter_compare (start, end) >= 0) { return FALSE; } } return TRUE; }
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; } }
bool search_in_bibledit_word_boundaries_match(const ustring & text, const ustring & searchword, bool matchbeginning, bool matchending, bool globbing) // Does the word boundary matching. { /* Deal with matching the start of a word and/or of the end. There are four cases here. 1. Match word start only. 2. Match word end only. 3. Both match start end end of a word, which implies "whole word". 4. No matching at all. Boundary resolution is handled by pango_break(). Textual boundaries such as word boundaries and line boundaries are determined for each item. In most cases a general algorithm suffices for this process, but in some cases a language module will override the generic algorithm with a more specific one. It seems to be easier programming to use GtkTextIter and GtkTextBuffer, rather than pango_break() directly. */ // Whether the word matches. bool match = false; // Textbuffer for determining word boundaries. GtkTextBuffer *textbuffer = gtk_text_buffer_new(NULL); gtk_text_buffer_set_text(textbuffer, text.c_str(), -1); // Iterators needed. GtkTextIter startiter; GtkTextIter enditer; // Store segments of text to compare against. vector < ustring > segments; // Deal with case one: Match word start only. if (matchbeginning && !matchending) { // Create a patternword for the glob-style pattern matching. ustring patternword = searchword + "*"; // Collect all strings starting with a word. gtk_text_buffer_get_start_iter(textbuffer, &startiter); gtk_text_buffer_get_end_iter(textbuffer, &enditer); while (gtk_text_iter_forward_word_end(&startiter)) { gtk_text_iter_backward_word_start(&startiter); segments.push_back(gtk_text_iter_get_text(&startiter, &enditer)); gtk_text_iter_forward_word_end(&startiter); } // See whether the word is in it. for (unsigned int i2 = 0; i2 < segments.size(); i2++) { if (globbing) { // Glob-style pattern matching. if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) { match = true; break; } } else { // Straight compare. if (segments[i2].find(searchword) == 0) { match = true; break; } } } } // Deal with case two: Match word end only. if (!matchbeginning && matchending) { // Create a patternword for the glob-style pattern matching. ustring patternword = "*" + searchword; // Collect all strings ending with a word. gtk_text_buffer_get_start_iter(textbuffer, &startiter); gtk_text_buffer_get_start_iter(textbuffer, &enditer); while (gtk_text_iter_forward_word_end(&enditer)) { segments.push_back(gtk_text_iter_get_text(&startiter, &enditer)); } // See whether the word is in it. for (unsigned int i2 = 0; i2 < segments.size(); i2++) { if (globbing) { // Glob-style pattern matching. if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) { match = true; break; } } else { // Straight compare. size_t matchposition; matchposition = segments[i2].length() - searchword.length(); // Negative match positions cause a false match. Solve that here. matchposition = CLAMP(matchposition, 0, 99999999); if (segments[i2].find(searchword) == matchposition) { match = true; break; } } } } // Deal with case three: Match both word start and end. // Interpreted as "match whole word". if (matchbeginning && matchending) { // Create a patternword for the glob-style pattern matching. ustring patternword = searchword; // Collect all whole words. gtk_text_buffer_get_start_iter(textbuffer, &enditer); while (gtk_text_iter_forward_word_end(&enditer)) { startiter = enditer; gtk_text_iter_backward_word_start(&startiter); segments.push_back(gtk_text_iter_get_text(&startiter, &enditer)); } // See whether the word is in it. for (unsigned int i2 = 0; i2 < segments.size(); i2++) { if (globbing) { // Glob-style pattern matching. if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) { match = true; break; } } else { // Straight compare. if (segments[i2] == searchword) { match = true; break; } } } } // Case four: Nothing to test, so set found to true. if (!matchbeginning && !matchending) match = true; // Free memory. g_object_unref(textbuffer); // Return whether match. return match; }
/** * Handles the keypress events from webview and inputbox. */ VbResult ex_keypress(int key) { GtkTextIter start, end; GtkTextBuffer *buffer = vb.gui.buffer; GtkTextMark *mark; /* delegate call to the submode */ if (RESULT_COMPLETE == hints_keypress(key)) { return RESULT_COMPLETE; } switch (key) { case KEY_TAB: complete(1); break; case KEY_SHIFT_TAB: complete(-1); break; case CTRL('['): case CTRL('C'): mode_enter('n'); vb_set_input_text(""); break; case KEY_CR: input_activate(); break; case KEY_UP: history(true); break; case KEY_DOWN: history(false); break; /* basic command line editing */ case CTRL('H'): /* delete the last char before the cursor */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); gtk_text_buffer_backspace(buffer, &start, true, true); break; case CTRL('W'): /* delete word backward from cursor */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); /* copy the iter to build start and end point for deletion */ start = end; /* move the iterator to the beginning of previous word */ if (gtk_text_iter_backward_word_start(&start)) { gtk_text_buffer_delete(buffer, &start, &end); } break; case CTRL('B'): /* move the cursor direct behind the prompt */ gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); gtk_text_buffer_place_cursor(buffer, &start); break; case CTRL('E'): /* move the cursor to the end of line */ gtk_text_buffer_get_end_iter(buffer, &start); gtk_text_buffer_place_cursor(buffer, &start); break; case CTRL('U'): /* remove everythings between cursor and prompt */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); gtk_text_buffer_delete(buffer, &start, &end); break; default: /* if is printable ascii char, than write it at the cursor * position into input box */ if (key >= 0x20 && key <= 0x7e) { gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1); } else {
static void set_check_range (GeditDocument *doc, GtkTextIter *start, GtkTextIter *end) { CheckRange *range; GtkTextIter iter; gedit_debug (DEBUG_PLUGINS); range = get_check_range (doc); if (range == NULL) { gedit_debug_message (DEBUG_PLUGINS, "There was not a previous check range"); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); range = g_new0 (CheckRange, 1); range->start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), "check_range_start_mark", &iter, TRUE); range->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), "check_range_end_mark", &iter, FALSE); range->current_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), "check_range_current_mark", &iter, TRUE); g_object_set_qdata_full (G_OBJECT (doc), check_range_id, range, (GDestroyNotify)g_free); } if (gedit_spell_utils_skip_no_spell_check (start, end)) { if (!gtk_text_iter_inside_word (end)) { /* if we're neither inside a word, * we must be in some spaces. * skip backward to the end of the previous word. */ if (!gtk_text_iter_is_end (end)) { gtk_text_iter_backward_word_start (end); gtk_text_iter_forward_word_end (end); } } else { if (!gtk_text_iter_ends_word (end)) gtk_text_iter_forward_word_end (end); } } else { /* no spell checking in the specified range */ start = end; } gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->start_mark, start); gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->end_mark, end); range->mw_start = -1; range->mw_end = -1; update_current (doc, gtk_text_iter_get_offset (start)); }
/** * Handles the keypress events from webview and inputbox. */ VbResult ex_keypress(int key) { GtkTextIter start, end; gboolean check_empty = false; GtkTextBuffer *buffer = vb.gui.buffer; GtkTextMark *mark; VbResult res; const char *text; /* delegate call to hint mode if this is active */ if (vb.mode->flags & FLAG_HINTING && RESULT_COMPLETE == hints_keypress(key)) { return RESULT_COMPLETE; } /* process the register */ if (info.phase == PHASE_REG) { info.reg = (char)key; info.phase = PHASE_REG; /* insert the register text at cursor position */ text = vb_register_get((char)key); if (text) { gtk_text_buffer_insert_at_cursor(buffer, text, strlen(text)); } res = RESULT_COMPLETE; } else { res = RESULT_COMPLETE; switch (key) { case KEY_TAB: complete(1); break; case KEY_SHIFT_TAB: complete(-1); break; case CTRL('['): case CTRL('C'): vb_enter('n'); vb_set_input_text(""); break; case KEY_CR: input_activate(); break; case KEY_UP: history(true); break; case KEY_DOWN: history(false); break; /* basic command line editing */ case CTRL('H'): /* delete the last char before the cursor */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); gtk_text_buffer_backspace(buffer, &start, true, true); check_empty = true; break; case CTRL('W'): /* delete word backward from cursor */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); /* copy the iter to build start and end point for deletion */ start = end; /* move the iterator to the beginning of previous word */ if (gtk_text_iter_backward_word_start(&start)) { gtk_text_buffer_delete(buffer, &start, &end); } check_empty = true; break; case CTRL('B'): /* move the cursor direct behind the prompt */ gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); gtk_text_buffer_place_cursor(buffer, &start); break; case CTRL('E'): /* move the cursor to the end of line */ gtk_text_buffer_get_end_iter(buffer, &start); gtk_text_buffer_place_cursor(buffer, &start); break; case CTRL('U'): /* remove everything between cursor and prompt */ mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); gtk_text_buffer_delete(buffer, &start, &end); break; case CTRL('R'): info.phase = PHASE_REG; vb.mode->flags |= FLAG_NOMAP; res = RESULT_MORE; break; default: /* if is printable ascii char, than write it at the cursor * position into input box */ if (key >= 0x20 && key <= 0x7e) { gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1); } else {
static void WhatCheck (GtkMenuItem *item, gpointer data) { GtkWidget *dialog; GtkTextIter start, end; char *word; gunichar *wword; // Znajdujemy pozycję kursora gtk_text_buffer_get_iter_at_mark(editor_buf, &start, gtk_text_buffer_get_insert(editor_buf)); // Jeśli nie wewnątrz słowa, kończymy if (!gtk_text_iter_inside_word(&start)) { dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Kursor musi być w środku słowa"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } // Znajdujemy początek i koniec słowa, a potem samo słowo end = start; gtk_text_iter_backward_word_start(&start); gtk_text_iter_forward_word_end(&end); word = gtk_text_iter_get_text(&start, &end); // Zamieniamy na wide char (no prawie) wword = g_utf8_to_ucs4_fast(word, -1, NULL); if(update_actual_dict() < 0) return; // Sprawdzamy if (dictionary_find(dict, (wchar_t *)wword)) { dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Wszystko w porządku,\nśpij spokojnie"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } else { // Czas korekty GtkWidget *vbox, *label, *combo; struct word_list hints; int i; wchar_t **words; dictionary_hints(dict, (wchar_t *)wword, &hints); words = word_list_get(&hints); dialog = gtk_dialog_new_with_buttons("Korekta", NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); // W treści dialogu dwa elementy vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); // Tekst label = gtk_label_new("Coś nie tak, mam kilka propozycji"); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 1); // Spuszczane menu combo = gtk_combo_box_text_new(); for (i = 0; i < word_list_size(&hints); i++) { // Combo box lubi mieć Gtk char *uword = g_ucs4_to_utf8((gunichar *)words[i], -1, NULL, NULL, NULL); // Dodajemy kolejny element gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), uword); g_free(uword); } //gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo),"<inne...>"); gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 1); gtk_widget_show(combo); char *korekta, *question; GtkWidget *ask_dialog, *ask_vbox, *ask_label; switch (gtk_dialog_run(GTK_DIALOG(dialog))) { case GTK_RESPONSE_ACCEPT: korekta = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo)); // Usuwamy stare gtk_text_buffer_delete(editor_buf, &start, &end); // Wstawiamy nowe gtk_text_buffer_insert(editor_buf, &start, korekta, -1); g_free(korekta); break; case GTK_RESPONSE_REJECT: question = "Czy chcesz dodać to słowo do słownika?"; ask_dialog = gtk_dialog_new_with_buttons(question, NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); ask_vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); // Tekst ask_label = gtk_label_new("Coś nie tak, mam kilka propozycji"); gtk_widget_show(ask_label); gtk_box_pack_start(GTK_BOX(ask_vbox), ask_label, FALSE, FALSE, 1); // Jeśli chiciał dodać nowe słowo do słownika to dodamy i zapiszemy if (gtk_dialog_run(GTK_DIALOG(ask_dialog)) == GTK_RESPONSE_ACCEPT) { dictionary_insert(dict, (wchar_t *)wword); dictionary_save_lang(dict, dict_location); } gtk_widget_destroy(ask_dialog); break; } gtk_widget_destroy(dialog); } }
void CheckCapitalization::check_capitalization(vector < int >&chapters, vector < ustring > &verses, ustring & text, vector < size_t > &pointers, bool end_check) /* Check capitalization in text. If "end_check" is true, it also check for final sentence closing. */ { /* Note that this at first used gtk_text_iter_starts_sentence (&iter) and gtk_text_iter_ends_sentence (&iter), but these functions are not good enough, because do not work in several cases, like e.g. in the following line, it does not indicate the end of the sentence: As soon as the leaders of the tribes of Israel took their places, the Israelites said, “How could such a horrible thing happen?" Therefore we use other means to check sentences. */ // No check if there's no text. if (trim(text).empty()) return; // Some variables needed. bool expect_capital_now = false; bool expect_capital_caused_by_reference = false; gunichar previous_char = 0; int localchapter = 0; ustring localverse = "0"; GtkTextBuffer *textbuffer; textbuffer = gtk_text_buffer_new(NULL); gtk_text_buffer_set_text(textbuffer, text.c_str(), -1); GtkTextIter iter; gtk_text_buffer_get_start_iter(textbuffer, &iter); bool going = true; while (going) { // Get the unicode character. gunichar unichar = gtk_text_iter_get_char(&iter); // See whether to expect a capital now. if (punctuation_followed_by_capitals_set.find(unichar) != punctuation_followed_by_capitals_set.end()) { // Ok, expect capital. expect_capital_now = true; expect_capital_caused_by_reference = false; // Was this expectation caused by a reference? if (is_reference(iter)) expect_capital_caused_by_reference = true; } // If we expect a capital, and we find one, no longer look for one. if (expect_capital_now) { if (g_unichar_isupper(unichar)) { expect_capital_now = false; } } // If we expect a capital, and we get lower case, that might be trouble. if (expect_capital_now) { if (g_unichar_islower(unichar)) { // There is no trouble if it follows a character after which to ignore lower case. if (ignore_lower_case_following_set.find(previous_char) != ignore_lower_case_following_set.end()) { expect_capital_now = false; } // If the lowercase character follows an abbreviation, there is no trouble either. GtkTextIter iter2 = iter; gtk_text_iter_backward_word_start(&iter2); GtkTextIter iter3 = iter2; gtk_text_iter_forward_word_end(&iter3); gtk_text_iter_forward_char(&iter3); ustring abbreviation = gtk_text_iter_get_text(&iter2, &iter3); if (abbreviations.find(abbreviation) != abbreviations.end()) { expect_capital_now = false; } // If it follows a reference, there is no trouble. if (expect_capital_caused_by_reference) expect_capital_now = false; // Ok, give message. if (expect_capital_now) { // Determine chapter and verse. get_chapter_and_verse(chapters, verses, pointers, iter, localchapter, localverse); message(book, localchapter, localverse, _("Capital expected: ") + get_context(iter)); } // Only give one message about missing capitals in this context. expect_capital_now = false; } } // Store this characters as the previous characters for the next round. if (g_unichar_isgraph(unichar)) previous_char = unichar; // Next round. going = gtk_text_iter_forward_char(&iter); } // The sentence should be ended with proper punctuation. if (end_check) { if (expect_capital_now) if (g_unichar_isdigit(previous_char)) expect_capital_now = false; if (!expect_capital_now) { message(book, chapter, verse, _("Unended sentence: ") + get_context(iter)); } } // Free memory g_object_unref(textbuffer); }
void CheckCapitalization::check_suspicious_capitalization(ustring & text) /* Checks on suspicious capitalization, like "bOat" or "BOat". There are exceptions to this check. */ { // Load text into buffer. ustring text2(text); text2.append(" "); GtkTextBuffer *textbuffer; textbuffer = gtk_text_buffer_new(NULL); gtk_text_buffer_set_text(textbuffer, text2.c_str(), -1); // Iterators. GtkTextIter startiter, enditer; // Check all separate words. gtk_text_buffer_get_start_iter(textbuffer, &enditer); while (gtk_text_iter_forward_word_end(&enditer)) { startiter = enditer; gtk_text_iter_backward_word_start(&startiter); vector < bool > capspattern; unsigned int capscount = 0; GtkTextIter iter = startiter; while (gtk_text_iter_in_range(&iter, &startiter, &enditer)) { bool upper = g_unichar_isupper(gtk_text_iter_get_char(&iter)); capspattern.push_back(upper); if (upper) capscount++; gtk_text_iter_forward_char(&iter); } // No further checking if words are too short. if (capspattern.size() < 2) continue; // No further checking if only small letters. if (capscount == 0) continue; // No further checking if all capitals. if (capscount == capspattern.size()) continue; // No further checking if first letter capitalized only. if ((capspattern[0]) && (capscount == 1)) continue; // Ok, there could be a problem of mixed capitalization. // Get the prefix before the first capital, and the suffix after it. ustring word = gtk_text_iter_get_text(&startiter, &enditer); ustring uncapitalized_prefix; ustring capitalized_suffix; for (unsigned int i = 1; i < capspattern.size(); i++) { if (capspattern[i]) { uncapitalized_prefix = word.substr(0, i); capitalized_suffix = word.substr(i, word.length() - i); break; } } // See whether the suffix is properly capitalized. unsigned int suffix_capital_count = 0; for (unsigned int i = 0; i < capitalized_suffix.length(); i++) { if (g_unichar_isupper(g_utf8_get_char(capitalized_suffix.substr(i, 1).c_str()))) suffix_capital_count++; } bool suffix_properly_capitalized = false; if (suffix_capital_count == 1) suffix_properly_capitalized = true; if (suffix_capital_count == capitalized_suffix.length()) suffix_properly_capitalized = true; // Give message and continue if capitalization error in suffix, but only // if this so-called wrongly capitalized suffix has not been approved af. if (!suffix_properly_capitalized) { if (capitalized_suffixes.find(capitalized_suffix) == capitalized_suffixes.end()) { mixed_capitalization_message(word); continue; } } // No further checking if this uncapitalized prefix is in the list, // or any is allowed. if (uncapitalized_prefixes.find(uncapitalized_prefix) != uncapitalized_prefixes.end()) continue; if (allow_any_uncapitalized_prefixes) continue; // Ok, not in the list. Try again with lower case initial. ustring initial = uncapitalized_prefix.substr(0, 1); initial = initial.casefold(); uncapitalized_prefix.replace(0, 1, initial); if (uncapitalized_prefixes.find(uncapitalized_prefix) != uncapitalized_prefixes.end()) continue; // No further checking if the suffix is in the list of approved suffixes. if (capitalized_suffixes.find(capitalized_suffix) != capitalized_suffixes.end()) continue; // Ok, not found, but it could be this suffix is in all capitals. Handle that. initial = capitalized_suffix.substr(0, 1); capitalized_suffix.erase(0, 1); capitalized_suffix = capitalized_suffix.casefold(); capitalized_suffix.insert(0, initial); if (capitalized_suffixes.find(capitalized_suffix) != capitalized_suffixes.end()) continue; // Ok, it appears we've got an error here -> give message. mixed_capitalization_message(word); } // Free memory g_object_unref(textbuffer); }
/** Sprawdzenie słowa, na którym aktualnie znajduje się kursor. Ewentualne dodanie do słownika. @param[in] item element menu. @param[in] data wskaźnik na wartość. */ static void WhatCheck (GtkMenuItem *item, gpointer data) { GtkWidget *dialog; GtkTextIter start, end; char *word; gunichar *wword; //load_dictionary_from_menu(&dict); // Znajdujemy pozycję kursora gtk_text_buffer_get_iter_at_mark(editor_buf, &start, gtk_text_buffer_get_insert(editor_buf)); // Jeśli nie wewnątrz słowa, kończymy if (!gtk_text_iter_inside_word(&start)) { dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Kursor musi być w środku słowa"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } // Znajdujemy początek i koniec słowa, a potem samo słowo end = start; gtk_text_iter_backward_word_start(&start); gtk_text_iter_forward_word_end(&end); word = gtk_text_iter_get_text(&start, &end); // Zamieniamy na wide char (no prawie) wword = g_utf8_to_ucs4_fast(word, -1, NULL); if (!make_lowercase(wword)) { dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Podane słowo nie jest słowem słownikowym."); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } else { // Sprawdzamy if (dictionary_find(dict, (wchar_t *)wword)) { dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Wszystko w porządku,\nśpij spokojnie"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } else { // Czas korekty GtkWidget *vbox, *label, *combo; struct word_list hints; int i; wchar_t **words; dictionary_hints(dict, (wchar_t *)wword, &hints); words = (wchar_t **) word_list_get(&hints); dialog = gtk_dialog_new_with_buttons("Korekta", NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_ADD, GTK_RESPONSE_APPLY, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); // W treści dialogu dwa elementy vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); // Tekst label = gtk_label_new("Słowo nie znajduje się w słowniku. Wybierz \njedną z propozycji lub dodaj słowa do słownika."); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 1); // Spuszczane menu combo = gtk_combo_box_text_new(); for (i = 0; i < word_list_size(&hints); i++) { // Combo box lubi mieć Gtk char *uword = g_ucs4_to_utf8((gunichar *)words[i], -1, NULL, NULL, NULL); // Dodajemy kolejny element gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), uword); g_free(uword); } gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 1); gtk_widget_show(combo); gint click = gtk_dialog_run(GTK_DIALOG(dialog)); if (click == GTK_RESPONSE_ACCEPT) { char *korekta = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo)); // Usuwamy stare gtk_text_buffer_delete(editor_buf, &start, &end); // Wstawiamy nowe gtk_text_buffer_insert(editor_buf, &start, korekta, -1); g_free(korekta); } // Proponujemy dodanie słowa do słownika else if (click == GTK_RESPONSE_APPLY) dictionary_insert(dict, wword); gtk_widget_destroy(dialog); } } g_free(word); g_free(wword); }
void load_file (const gchar *demoname, const gchar *filename) { GtkTextBuffer *info_buffer, *source_buffer; GtkTextIter start, end; char *resource_filename; GError *err = NULL; int state = 0; gboolean in_para = 0; gchar **lines; GBytes *bytes; gint i; if (!g_strcmp0 (current_file, filename)) return; remove_data_tabs (); add_data_tab (demoname); g_free (current_file); current_file = g_strdup (filename); info_buffer = gtk_text_buffer_new (NULL); gtk_text_buffer_create_tag (info_buffer, "title", "font", "Sans 18", "pixels-below-lines", 10, NULL); source_buffer = gtk_text_buffer_new (NULL); gtk_text_buffer_create_tag (source_buffer, "source", "font", "monospace", NULL); gtk_text_buffer_create_tag (source_buffer, "comment", "foreground", "DodgerBlue", NULL); gtk_text_buffer_create_tag (source_buffer, "type", "foreground", "ForestGreen", NULL); gtk_text_buffer_create_tag (source_buffer, "string", "foreground", "RosyBrown", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_create_tag (source_buffer, "control", "foreground", "purple", NULL); gtk_text_buffer_create_tag (source_buffer, "preprocessor", "style", PANGO_STYLE_OBLIQUE, "foreground", "burlywood4", NULL); gtk_text_buffer_create_tag (source_buffer, "function", "weight", PANGO_WEIGHT_BOLD, "foreground", "DarkGoldenrod4", NULL); resource_filename = g_strconcat ("/sources/", filename, NULL); bytes = g_resources_lookup_data (resource_filename, 0, &err); g_free (resource_filename); if (bytes == NULL) { g_warning ("Cannot open source for %s: %s\n", filename, err->message); g_error_free (err); return; } lines = g_strsplit (g_bytes_get_data (bytes, NULL), "\n", -1); g_bytes_unref (bytes); gtk_text_buffer_get_iter_at_offset (info_buffer, &start, 0); for (i = 0; lines[i] != NULL; i++) { gchar *p; gchar *q; gchar *r; /* Make sure \r is stripped at the end for the poor windows people */ lines[i] = g_strchomp (lines[i]); p = lines[i]; switch (state) { case 0: /* Reading title */ while (*p == '/' || *p == '*' || g_ascii_isspace (*p)) p++; r = p; while (*r != '\0') { while (*r != '/' && *r != ':' && *r != '\0') r++; if (*r == '/') { r++; p = r; } if (r[0] == ':' && r[1] == ':') *r = '\0'; } q = p + strlen (p); while (q > p && g_ascii_isspace (*(q - 1))) q--; if (q > p) { int len_chars = g_utf8_pointer_to_offset (p, q); end = start; g_assert (strlen (p) >= q - p); gtk_text_buffer_insert (info_buffer, &end, p, q - p); start = end; gtk_text_iter_backward_chars (&start, len_chars); gtk_text_buffer_apply_tag_by_name (info_buffer, "title", &start, &end); start = end; while (*p && *p != '\n') p++; state++; } break; case 1: /* Reading body of info section */ while (g_ascii_isspace (*p)) p++; if (*p == '*' && *(p + 1) == '/') { gtk_text_buffer_get_iter_at_offset (source_buffer, &start, 0); state++; } else { int len; while (*p == '*' || g_ascii_isspace (*p)) p++; len = strlen (p); while (g_ascii_isspace (*(p + len - 1))) len--; if (len > 0) { if (in_para) gtk_text_buffer_insert (info_buffer, &start, " ", 1); g_assert (strlen (p) >= len); gtk_text_buffer_insert (info_buffer, &start, p, len); in_para = 1; } else { gtk_text_buffer_insert (info_buffer, &start, "\n", 1); in_para = 0; } } break; case 2: /* Skipping blank lines */ while (g_ascii_isspace (*p)) p++; if (*p) { p = lines[i]; state++; /* Fall through */ } else break; case 3: /* Reading program body */ gtk_text_buffer_insert (source_buffer, &start, p, -1); if (lines[i+1] != NULL) gtk_text_buffer_insert (source_buffer, &start, "\n", 1); break; } } g_strfreev (lines); fontify (source_buffer); gtk_text_buffer_create_tag (source_buffer, "top-margin", "pixels-above-lines", 20, NULL); gtk_text_buffer_get_start_iter (source_buffer, &start); end = start; gtk_text_iter_forward_word_end (&end); gtk_text_buffer_apply_tag_by_name (source_buffer, "top-margin", &start, &end); gtk_text_buffer_create_tag (source_buffer, "bottom-margin", "pixels-below-lines", 20, NULL); gtk_text_buffer_get_end_iter (source_buffer, &end); start = end; gtk_text_iter_backward_word_start (&start); gtk_text_buffer_apply_tag_by_name (source_buffer, "bottom-margin", &start, &end); gtk_text_view_set_buffer (GTK_TEXT_VIEW (source_view), source_buffer); g_object_unref (source_buffer); gtk_text_buffer_create_tag (info_buffer, "top-margin", "pixels-above-lines", 20, NULL); gtk_text_buffer_get_start_iter (info_buffer, &start); end = start; gtk_text_iter_forward_word_end (&end); gtk_text_buffer_apply_tag_by_name (info_buffer, "top-margin", &start, &end); gtk_text_buffer_create_tag (info_buffer, "bottom-margin", "pixels-below-lines", 20, NULL); gtk_text_buffer_get_end_iter (info_buffer, &end); start = end; gtk_text_iter_backward_word_start (&start); gtk_text_buffer_apply_tag_by_name (info_buffer, "bottom-margin", &start, &end); gtk_text_view_set_buffer (GTK_TEXT_VIEW (info_view), info_buffer); g_object_unref (info_buffer); }
/** * 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; }