static void change_cb (GeditSpellCheckerDialog *dlg, const gchar *word, const gchar *change, GeditView *view) { GeditDocument *doc; CheckRange *range; gchar *w = NULL; GtkTextIter start, end; gedit_debug (DEBUG_PLUGINS); g_return_if_fail (view != NULL); g_return_if_fail (word != NULL); g_return_if_fail (change != NULL); doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); g_return_if_fail (doc != NULL); range = get_check_range (doc); g_return_if_fail (range != NULL); gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start); if (range->mw_end < 0) gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); else gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end); w = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE); g_return_if_fail (w != NULL); if (strcmp (w, word) != 0) { g_free (w); return; } g_free (w); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER(doc)); gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &start, &end); gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &start, change, -1); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER(doc)); update_current (doc, range->mw_start + g_utf8_strlen (change, -1)); /* go to next misspelled word */ ignore_cb (dlg, word, view); }
gint main (gint argc, gchar **argv) { GtkSourceBuffer *source_buffer; GtkTextBuffer *text_buffer; GtkTextIter iter; GTimer *timer; gint nb_actions; gint i; gtk_init (&argc, &argv); source_buffer = gtk_source_buffer_new (NULL); text_buffer = GTK_TEXT_BUFFER (source_buffer); gtk_text_buffer_get_start_iter (text_buffer, &iter); for (i = 0; i < NB_LINES; i++) { gtk_text_buffer_begin_user_action (text_buffer); gtk_text_buffer_insert (text_buffer, &iter, "A line of text to fill the text buffer. Is it long enough?\n", -1); gtk_text_buffer_end_user_action (text_buffer); } timer = g_timer_new (); nb_actions = test_undo_redo (source_buffer, NB_LINES / 10); g_timer_stop (timer); g_print ("Undo/Redo %d actions: %lf seconds.\n", nb_actions, g_timer_elapsed (timer, NULL)); g_timer_start (timer); nb_actions = test_undo_redo (source_buffer, NB_LINES); g_timer_stop (timer); g_print ("Undo/Redo %d actions: %lf seconds.\n", nb_actions, g_timer_elapsed (timer, NULL)); g_object_unref (source_buffer); g_timer_destroy (timer); return 0; }
static void replace_selected_text (GtkTextBuffer *buffer, const gchar *replace) { g_return_if_fail (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)); g_return_if_fail (replace != NULL); gtk_text_buffer_begin_user_action (buffer); gtk_text_buffer_delete_selection (buffer, FALSE, TRUE); gtk_text_buffer_insert_at_cursor (buffer, replace, strlen (replace)); gtk_text_buffer_end_user_action (buffer); }
static void gbp_spell_navigator_change_all (GspellNavigator *navigator, const gchar *word, const gchar *change_to) { GbpSpellNavigator *self = (GbpSpellNavigator *)navigator; GtkTextIter iter; g_assert (GBP_IS_SPELL_NAVIGATOR (self)); g_assert (GTK_IS_TEXT_MARK (self->start_boundary)); g_assert (GTK_IS_TEXT_MARK (self->end_boundary)); gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, self->start_boundary); gtk_text_buffer_begin_user_action (self->buffer); while (TRUE) { gboolean found; GtkTextIter match_start; GtkTextIter match_end; GtkTextIter limit; gtk_text_buffer_get_iter_at_mark (self->buffer, &limit, self->end_boundary); found = gtk_text_iter_forward_search (&iter, word, GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, &limit); if (!found) break; if (gbp_spell_utils_text_iter_starts_word (&match_start) && gbp_spell_utils_text_iter_ends_word (&match_end)) { gtk_text_buffer_delete (self->buffer, &match_start, &match_end); gtk_text_buffer_insert (self->buffer, &match_end, change_to, -1); } iter = match_end; } gtk_text_buffer_end_user_action (self->buffer); }
void gtr_actions_edit_redo (GtkAction * action, GtrWindow * window) { GtrView *active_view; GtkSourceBuffer *active_document; active_view = gtr_window_get_active_view (window); g_return_if_fail (active_view); active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view))); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (active_document)); gtk_source_buffer_redo (active_document); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (active_document)); gtk_widget_grab_focus (GTK_WIDGET (active_view)); }
static void gimp_text_style_editor_clear_tags (GtkButton *button, GimpTextStyleEditor *editor) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (editor->buffer); if (gtk_text_buffer_get_has_selection (buffer)) { GtkTextIter start, end; gtk_text_buffer_get_selection_bounds (buffer, &start, &end); gtk_text_buffer_begin_user_action (buffer); gtk_text_buffer_remove_all_tags (buffer, &start, &end); gtk_text_buffer_end_user_action (buffer); } }
static void change_case (CeditWindow *window, ChangeCaseChoice choice) { CeditDocument *doc; GtkTextIter start, end; cedit_debug (DEBUG_PLUGINS); doc = cedit_window_get_active_document (window); g_return_if_fail (doc != NULL); if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start, &end)) { return; } gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); switch (choice) { case TO_UPPER_CASE: do_upper_case (GTK_TEXT_BUFFER (doc), &start, &end); break; case TO_LOWER_CASE: do_lower_case (GTK_TEXT_BUFFER (doc), &start, &end); break; case INVERT_CASE: do_invert_case (GTK_TEXT_BUFFER (doc), &start, &end); break; case TO_TITLE_CASE: do_title_case (GTK_TEXT_BUFFER (doc), &start, &end); break; default: g_return_if_reached (); } gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); }
/* Format->Uncomment Selection */ void action_uncomment_selection(GtkAction *action, I7Document *document) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER(i7_document_get_buffer(document)); GtkTextIter start, end; if(!gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) return; /* Find first [ from the beginning of the selection, then the last ] between there and the end of the selection */ if(gtk_text_iter_get_char(&start) != '[' && !gtk_text_iter_forward_find_char(&start, char_equals, GUINT_TO_POINTER('['), &end)) return; gtk_text_iter_backward_char(&end); if(gtk_text_iter_get_char(&end) != ']' && !gtk_text_iter_backward_find_char(&end, char_equals, GUINT_TO_POINTER(']'), &start)) return; gtk_text_iter_forward_char(&end); gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); /* Treat it as one single undo action */ gtk_text_buffer_begin_user_action(buffer); /* Delete the comment and re-insert it without brackets */ gtk_text_buffer_delete(buffer, &start, &end); gchar *newtext = g_strndup(text + 1, strlen(text) - 2); GtkTextMark *tempmark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); gtk_text_buffer_insert(buffer, &end, newtext, -1); gtk_text_buffer_end_user_action(buffer); g_free(text); g_free(newtext); /* Select only the uncommented text again */ gtk_text_buffer_get_iter_at_mark(buffer, &start, tempmark); gtk_text_buffer_select_range(buffer, &start, &end); gtk_text_buffer_delete_mark(buffer, tempmark); }
static GtkSnippetsGtvVar* search_var(GtkSnippetsInPlaceParser *self, GtkTextBuffer *buffer,GtkTextMark *init_mark, GtkTextMark *limit_mark) { GtkSnippetsGtvVar *var = NULL; GtkTextMark *start_mark, *end_mark, *temp_mark; gchar *definition; const gchar *default_value; GtkTextIter start, end, temp_iter; GtkTextIter pos, limit; GError *error = NULL; gtk_text_buffer_get_iter_at_mark(buffer,&pos, init_mark); gtk_text_buffer_get_iter_at_mark(buffer,&limit, limit_mark); gboolean found = gtk_text_iter_forward_search(&pos, "${", GTK_TEXT_SEARCH_VISIBLE_ONLY, &start, NULL, &limit); if (found) { temp_iter = start; gtk_text_iter_forward_to_line_end(&temp_iter); found = gtk_text_iter_forward_search(&start, "}", GTK_TEXT_SEARCH_VISIBLE_ONLY, &end, NULL, &temp_iter); if (found) { gtk_text_iter_forward_char(&end); start_mark = gtk_text_buffer_create_mark(buffer, NULL, &start, TRUE); end_mark = gtk_text_buffer_create_mark(buffer, NULL, &end, FALSE); gtk_text_iter_forward_chars(&start,2); gtk_text_iter_forward_chars(&end,-1); definition = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); var = gtksnippets_gtv_var_new(definition, self->priv->view, start_mark, end_mark, VAR_TAG_NAME, VAR_ERROR_TAG_NAME); g_free(definition); default_value = gsnippets_variable_get_default_value(GSNIPPETS_VARIABLE(var)); if (default_value==NULL) default_value = gsnippets_variable_get_name(GSNIPPETS_VARIABLE(var)); gtk_text_buffer_begin_user_action(buffer); gtksnippets_gtv_var_set_text(var, default_value, &error); gtk_text_buffer_end_user_action(buffer); if (error != NULL) { g_warning("Error parsing variable: %s",error->message); g_error_free(error); } } else { /* If there is ${ but not } in the line, we must to search a new variable because if we return NULL, it is the end of the search */ gtk_text_iter_forward_chars(&start,2); temp_mark = gtk_text_buffer_create_mark(buffer, NULL, &start, TRUE); gtk_text_buffer_move_mark(buffer,temp_mark,&start); var = search_var(self,buffer,temp_mark,limit_mark); gtk_text_buffer_delete_mark(buffer,temp_mark); } } return var; }
void utl_gui_text_buffer_set_text_with_tags (GtkTextBuffer *buffer, const gchar *text, gboolean clear) { GtkTextIter start, end; GList *tags = NULL; gchar **tokens; gint count; gchar tag_char_utf8[7] = {0}; if (!text) return; gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); if (clear == TRUE) { gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end); gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &start, &end); } gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end); g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8); tokens = g_strsplit (text, tag_char_utf8, 0); for (count = 0; tokens[count]; count++) { if (count % 2 == 0) { gint offset; GList *j; offset = gtk_text_iter_get_offset (&end); gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &end, tokens[count], -1); gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, offset); for (j = tags; j; j = j->next) { gtk_text_buffer_apply_tag_by_name (GTK_TEXT_BUFFER (buffer), j->data, &start, &end); } } else { if (tokens[count][0] != '/') { tags = g_list_prepend (tags, tokens[count]); } else { GList *element = g_list_find_custom (tags, &(tokens[count][1]), (GCompareFunc) g_ascii_strcasecmp); if (element) { tags = g_list_delete_link (tags, element); } } } } gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); g_strfreev (tokens); }
static void process_communicate_utf8_cb (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr (GSubprocess) process = (GSubprocess *)object; g_autoptr (GTask) task = (GTask *)user_data; g_autofree gchar *stdout_str = NULL; g_autofree gchar *stderr_str = NULL; g_autoptr(GError) error = NULL; GtkSourceCompletion *completion; GtkTextBuffer *buffer; GtkTextIter begin; GtkTextIter end; ProcessState *state; gboolean status; g_assert (G_IS_SUBPROCESS (process)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (G_IS_TASK (task)); if (!g_subprocess_communicate_utf8_finish (process, result, &stdout_str, &stderr_str, &error)) { g_task_return_error (task, g_steal_pointer (&error)); return; } if (g_task_return_error_if_cancelled (task)) return; state = (ProcessState *)g_task_get_task_data (task); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (state->source_view)); completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (state->source_view)); if (!ide_str_empty0 (stdout_str)) { gtk_source_completion_block_interactive (completion); gtk_text_buffer_begin_user_action (buffer); gtk_text_buffer_get_iter_at_mark (buffer, &begin, state->begin_mark); gtk_text_buffer_get_iter_at_mark (buffer, &end, state->end_mark); gtk_text_buffer_delete (buffer, &begin, &end); gtk_text_buffer_insert (buffer, &begin, stdout_str, -1); /* Get valid iters from marks */ gtk_text_buffer_get_iter_at_mark (buffer, &begin, state->begin_mark); gtk_text_buffer_get_iter_at_mark (buffer, &end, state->end_mark); gtk_text_buffer_select_range (buffer, &begin, &end); g_signal_emit_by_name (state->source_view, "selection-theatric", IDE_SOURCE_VIEW_THEATRIC_EXPAND); gtk_text_buffer_end_user_action (buffer); gtk_source_completion_unblock_interactive (completion); g_task_return_boolean (task, TRUE); } else g_warning ("beautify plugin: output empty"); if (g_subprocess_get_if_exited (process)) { status = g_subprocess_get_exit_status (process); if (status != 0 && stderr_str != NULL && !ide_str_empty0 (stderr_str)) { g_warning ("beautify plugin stderr:\n%s", stderr_str); } } }
gboolean gimp_text_buffer_load (GimpTextBuffer *buffer, GFile *file, GError **error) { GInputStream *input; gchar buf[2048]; gint to_read; gsize bytes_read; gsize total_read = 0; gint remaining = 0; GtkTextIter iter; GError *my_error = NULL; g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), FALSE); g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); if (! input) { g_set_error (error, my_error->domain, my_error->code, _("Could not open '%s' for reading: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); return FALSE; } gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); gimp_text_buffer_set_text (buffer, NULL); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &iter); do { gboolean success; const char *leftover; to_read = sizeof (buf) - remaining - 1; success = g_input_stream_read_all (input, buf + remaining, to_read, &bytes_read, NULL, &my_error); total_read += bytes_read; buf[bytes_read + remaining] = '\0'; g_utf8_validate (buf, bytes_read + remaining, &leftover); gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, buf, leftover - buf); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &iter); remaining = (buf + remaining + bytes_read) - leftover; memmove (buf, leftover, remaining); if (! success) { if (total_read > 0) { g_message (_("Input file '%s' appears truncated: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); break; } gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); g_object_unref (input); g_propagate_error (error, my_error); return FALSE; } } while (remaining <= 6 && bytes_read == to_read); if (remaining) g_message (_("Invalid UTF-8 data in file '%s'."), gimp_file_get_utf8_name (file)); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); g_object_unref (input); return TRUE; }
/* Format->Renumber All Sections */ void action_renumber_all_sections(GtkAction *action, I7Document *document) { GtkTextIter pos, end; int volume = 1, book = 1, part = 1, chapter = 1, section = 1; GtkTextBuffer *buffer = GTK_TEXT_BUFFER(i7_document_get_buffer(document)); gtk_text_buffer_get_start_iter(buffer, &pos); /* Renumbering sections counts as one action for Undo */ gtk_text_buffer_begin_user_action(buffer); while(gtk_text_iter_get_char(&pos) != 0) { if(gtk_text_iter_get_char(&pos) != '\n') { gtk_text_iter_forward_line(&pos); continue; } gtk_text_iter_forward_line(&pos); end = pos; gboolean not_last = gtk_text_iter_forward_line(&end); if(!not_last || gtk_text_iter_get_char(&end) == '\n') { /* Preceded and followed by a blank line, or only preceded by one and current line is last line */ /* Get the entire line and its line number, chop the \n */ gchar *text = gtk_text_iter_get_text(&pos, &end); gchar *lcase = g_utf8_strdown(text, -1); gchar *title = strchr(text, '-'); if(title && g_str_has_suffix(title, "\n")) *(strrchr(title, '\n')) = '\0'; /* remove trailing \n */ gchar *newtitle; if(g_str_has_prefix(lcase, "volume")) { newtitle = g_strdup_printf("Volume %d %s\n", volume++, title); gtk_text_buffer_delete(buffer, &pos, &end); gtk_text_buffer_insert(buffer, &pos, newtitle, -1); g_free(newtitle); book = part = chapter = section = 1; } else if(g_str_has_prefix(lcase, "book")) { newtitle = g_strdup_printf("Book %d %s\n", book++, title); gtk_text_buffer_delete(buffer, &pos, &end); gtk_text_buffer_insert(buffer, &pos, newtitle, -1); g_free(newtitle); part = chapter = section = 1; } else if(g_str_has_prefix(lcase, "part")) { newtitle = g_strdup_printf("Part %d %s\n", part++, title); gtk_text_buffer_delete(buffer, &pos, &end); gtk_text_buffer_insert(buffer, &pos, newtitle, -1); g_free(newtitle); chapter = section = 1; } else if(g_str_has_prefix(lcase, "chapter")) { newtitle = g_strdup_printf("Chapter %d %s\n", chapter++, title); gtk_text_buffer_delete(buffer, &pos, &end); gtk_text_buffer_insert(buffer, &pos, newtitle, -1); g_free(newtitle); section = 1; } else if(g_str_has_prefix(lcase, "section")) { newtitle = g_strdup_printf("Section %d %s\n", section++, title); gtk_text_buffer_delete(buffer, &pos, &end); gtk_text_buffer_insert(buffer, &pos, newtitle, -1); g_free(newtitle); } g_free(text); g_free(lcase); } } gtk_text_buffer_end_user_action(buffer); }
void gimp_text_buffer_insert (GimpTextBuffer *buffer, const gchar *text) { GtkTextIter iter, start; gint start_offset; gboolean insert_tags_set; GList *insert_tags; GList *remove_tags; GSList *tags_off = NULL; g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer)); gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (buffer))); start_offset = gtk_text_iter_get_offset (&iter); insert_tags_set = buffer->insert_tags_set; insert_tags = buffer->insert_tags; remove_tags = buffer->remove_tags; buffer->insert_tags_set = FALSE; buffer->insert_tags = NULL; buffer->remove_tags = NULL; tags_off = gtk_text_iter_get_toggled_tags (&iter, FALSE); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, text, -1); gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, start_offset); if (insert_tags_set) { GList *list; for (list = remove_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } for (list = insert_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } } if (tags_off) { GSList *slist; for (slist = tags_off; slist; slist = g_slist_next (slist)) { GtkTextTag *tag = slist->data; if (! g_list_find (remove_tags, tag) && ! g_list_find (buffer->kerning_tags, tag)) { gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } } g_slist_free (tags_off); } g_list_free (remove_tags); g_list_free (insert_tags); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); }
void gimp_text_buffer_change_kerning (GimpTextBuffer *buffer, const GtkTextIter *start, const GtkTextIter *end, gint count) { GtkTextIter iter; GtkTextIter span_start; GtkTextIter span_end; GtkTextTag *span_tag; gint span_kerning; g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer)); g_return_if_fail (start != NULL); g_return_if_fail (end != NULL); if (gtk_text_iter_equal (start, end)) return; iter = *start; span_start = *start; span_tag = gimp_text_buffer_get_iter_kerning (buffer, &iter, &span_kerning); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); do { GtkTextTag *iter_tag; gint iter_kerning; gtk_text_iter_forward_char (&iter); iter_tag = gimp_text_buffer_get_iter_kerning (buffer, &iter, &iter_kerning); span_end = iter; if (iter_kerning != span_kerning || gtk_text_iter_compare (&iter, end) >= 0) { if (span_kerning != 0) { gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), span_tag, &span_start, &span_end); } if (span_kerning + count != 0) { span_tag = gimp_text_buffer_get_kerning_tag (buffer, span_kerning + count); gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), span_tag, &span_start, &span_end); } span_start = iter; span_kerning = iter_kerning; span_tag = iter_tag; } /* We might have moved too far */ if (gtk_text_iter_compare (&iter, end) > 0) iter = *end; } while (! gtk_text_iter_equal (&iter, end)); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); }
static gboolean gb_vim_command_substitute (GtkWidget *active_widget, const gchar *command, const gchar *options, GError **error) { IdeSourceView *source_view; GtkTextBuffer *buffer; const gchar *search_begin = NULL; const gchar *search_end = NULL; const gchar *replace_begin = NULL; const gchar *replace_end = NULL; g_autofree gchar *search_text = NULL; g_autofree gchar *replace_text = NULL; GtkTextIter *substitute_begin = NULL; GtkTextIter *substitute_end = NULL; gunichar separator; gboolean replace_in_every_line = FALSE; gboolean replace_every_occurence_in_line = FALSE; gboolean replace_ask_for_confirmation = FALSE; GtkTextIter selection_begin, selection_end; g_assert (GTK_IS_WIDGET (active_widget)); g_assert (g_str_has_prefix (command, "%s") || g_str_has_prefix (command, "s")); if (IDE_IS_EDITOR_PAGE (active_widget)) source_view = ide_editor_page_get_view (IDE_EDITOR_PAGE (active_widget)); else return gb_vim_set_source_view_error (error); if (command[0] == '%') { replace_in_every_line = TRUE; command++; } command++; separator = g_utf8_get_char (command); if (!separator) goto invalid_request; search_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { search_end = command; break; } } if (search_end == NULL) { search_text = g_strdup (search_begin); replace_text = g_strdup (""); } else { search_text = g_strndup (search_begin, search_end - search_begin); replace_begin = command = g_utf8_next_char (command); for (; *command; command = g_utf8_next_char (command)) { if (*command == '\\') { command = g_utf8_next_char (command); if (!*command) goto invalid_request; continue; } if (g_utf8_get_char (command) == separator) { replace_end = command; break; } } if (replace_end == NULL) replace_text = g_strdup (replace_begin); else { replace_text = g_strndup (replace_begin, replace_end - replace_begin); command = g_utf8_next_char (command); } if (*command) { for (; *command; command++) { switch (*command) { case 'c': replace_ask_for_confirmation = TRUE; break; case 'g': replace_every_occurence_in_line = TRUE; break; /* what other options are supported? */ default: break; } } } } if (replace_ask_for_confirmation) { GVariant *variant; GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY); g_variant_builder_add (&builder, "s", search_text); g_variant_builder_add (&builder, "s", replace_text); variant = g_variant_builder_end (&builder); dzl_gtk_widget_action (active_widget, "editor-page", "replace-confirm", variant); return TRUE; } buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)); if (gtk_text_buffer_get_has_selection (buffer)) { gtk_text_buffer_get_selection_bounds (buffer, &selection_begin, &selection_end); substitute_begin = &selection_begin; substitute_end = &selection_end; } gtk_text_buffer_begin_user_action (buffer); gb_vim_do_substitute (buffer, substitute_begin, substitute_end, search_text, replace_text, replace_every_occurence_in_line, replace_in_every_line); gtk_text_buffer_end_user_action (buffer); return TRUE; invalid_request: g_set_error (error, GB_VIM_ERROR, GB_VIM_ERROR_UNKNOWN_OPTION, _("Invalid search and replace request")); return FALSE; }
/** called repeatedly to add more text to the editor as each page is read from the PDF file, via g_timeout_add. Spelling needs to be turned off during loading, re-attached it at the end if GConf says spelling should be enabled. This function is asynchronous - a background task. Don't do things with the progress bar or status bar whilst a load task could be running. */ static gboolean load_pdf (gpointer data) { GtkProgressBar * progressbar; GtkStatusbar * statusbar; GtkTextView * text_view; GtkTextBuffer * buffer; gchar *page, * msg, * G_GNUC_UNUSED lang; gdouble fraction, step, width, height; PopplerPage * PDFPage; const gchar * str; gint pages; guint id; Equeue * queue; queue= (Equeue *)data; text_view = GTK_TEXT_VIEW(gtk_builder_get_object (queue->ebook->builder, "textview")); buffer = gtk_text_view_get_buffer (text_view); if (!queue) { gtk_text_buffer_end_user_action (buffer); return FALSE; } if (!queue->ebook) { gtk_text_buffer_end_user_action (buffer); return FALSE; } progressbar = GTK_PROGRESS_BAR(gtk_builder_get_object (queue->ebook->builder, "progressbar")); statusbar = GTK_STATUSBAR(gtk_builder_get_object (queue->ebook->builder, "statusbar")); id = gtk_statusbar_get_context_id (statusbar, PACKAGE); pages = poppler_document_get_n_pages (queue->ebook->PDFDoc); if (queue->c >= pages) { lang = gconf_client_get_string (queue->ebook->client, queue->ebook->language.key, NULL); #ifdef HAVE_GTKSPELL /* spell_attach is already a background task. */ if (queue->spell_state) gtkspell_new_attach (text_view, (lang == NULL || *lang == '\0') ? NULL : lang, NULL); #endif gtk_progress_bar_set_text (progressbar, ""); gtk_progress_bar_set_fraction (progressbar, 0.0); if (queue->ebook->utf8_count > 0) { /* Translators: Please try to keep this string brief, there often isn't a lot of room in the statusbar. */ str = ngettext ("%ld non-UTF8 character was removed", "%ld non-UTF-8 characters were removed", queue->ebook->utf8_count); msg = g_strdup_printf (str, queue->ebook->utf8_count); id = gtk_statusbar_get_context_id (statusbar, PACKAGE); gtk_statusbar_push (statusbar, id, msg); g_free (msg); } else { gtk_statusbar_push (statusbar, id, _("Done")); } return FALSE; } PDFPage = poppler_document_get_page (queue->ebook->PDFDoc, queue->c); fraction = 0.0; /* fraction never reaches 1.0 - allow room for spelling attachment. */ if (queue->spell_state) step = 0.90/(gdouble)pages; else step = 0.99/(gdouble)pages; fraction += step * queue->c; /* update progress bar as we go */ gtk_progress_bar_set_fraction (progressbar, fraction); poppler_page_get_size (PDFPage, &width, &height); queue->rect->x2 = width; queue->rect->y2 = height; #if POPPLER_CHECK_VERSION(0, 14, 1) page = poppler_page_get_selected_text (PDFPage, POPPLER_SELECTION_LINE, queue->rect); #else page = poppler_page_get_text (PDFPage, POPPLER_SELECTION_LINE, queue->rect); #endif set_text (queue->ebook, page, queue->lines, queue->pagenums, queue->hyphens); g_free (page); queue->c++; /* add the page to the progressbar count. */ msg = g_strdup_printf ("%d/%d", queue->c, pages); gtk_progress_bar_set_text (progressbar, msg); g_free (msg); /* more to do yet, so return TRUE to call me again. */ return TRUE; }