Searching, scrolling, selecting GtkTextView one find at a time

Hi there,
Using C language, Gtk 3.1? on Ubuntu 18.04?:
I am following the example “Using the GtkTextIter Find Function (find.c)” given in Andrew Kraus’ book “Foundations of GTK+ Development” and have it working, but not as I had hoped. I am trying to create a searching tool that scrolls and selects, one-by-one, from any place within the buffer (not always from the start of the buffer, as in find.c), through found text in the GtkTextView buffer, such as used by gedit find. Executing find.c results in the dialog showing how many times the text in the GtkEntry was found, a nice start, but not what I want.
If I then use:
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);
gtk_text_buffer_select_range(buffer, &begin, &end);
within the while-loop, it scrolls and selects the final found-text only and doesn’t stop at each string found.
If I place the following within the while-loop:
if (i == findstring)
{
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);
gtk_text_buffer_select_range(buffer, &begin, &end);
}
else if (i > findstring)
{
break;
}
where ‘findstring’ is an integer hardwired into the while-loop, it scrolls and selects that text string. I therefore tried to implement a spinbutton to scroll-to and select the desired occurrence of the string, which would be an acceptable solution, if I could get it to work.
The GtkTextView, ‘Find’ button, and ‘findstring’ spinbutton and label, are placed on a grid in a notebook tab, with the rest of the program being spread over the other notebook tabs (each with it’s own drawing function, in seperate .c files, with these all passing information via a single struct large_struct *large). The textview uses a separate g_slice() struct as per ‘find.c’ (Widgets *w, (w->)) to store and pass information. If I pass the spinbutton through ‘large_struct’ it is displayed and the value changes but the desired text string is not found. I haven’t been able to pass the spinbutton through ‘Widgets *w’, it seems because of problems initialising the things in (Widgets *w).

If I comment out the while-loop (and the un-needed dialog) and place the above scrolling and selection functions after
gtk_text_buffer_get_start_iter(buffer, &start);
gtk_text_iter_forward_visible_cursor_position(&start);
success = gtk_text_iter_forward_search(&start, (gchar*) find, GTK_TEXT_SEARCH_TEXT_ONLY, &begin, &end, NULL);
then it simply scolls and selects the first occurrence of ‘text’.
I had the idea that if I commented out the while-loop, and could start the search from where the cursor was in the buffer then I would be able to scroll and select one-by-one, with each button-press of the ‘find’ button, through the buffer. So far I haven’t been able to do this. I have tried this with:
gtk_text_buffer_place_cursor(buffer, &start)
gtk_text_buffer_place_cursor(buffer, &begin), or
gtk_text_buffer_place_cursor(buffer, &end), but a segfault always resulted.
I have also tried creating GtkTextMarks, both within the while-loop and without.
gtk_text_buffer_create_mark(buffer, (const gchar *) mark, &begin, FALSE);
gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW(textview1), (GtkTextMark *) mark, 0, TRUE, 0, 0.5);
The marks compile, scroll and select, but only the first or last occurrence, with or without the while-loop, as previously, and I also get the runtime message:
(exec:3326): Gtk-CRITICAL **: 11:57:30.107: gtk_text_view_scroll_to_mark: assertion ‘GTK_IS_TEXT_MARK (mark)’ failed

I have also tried creating an array of marks with the while-loop ‘i’ concatenated onto the mark name using a pointer array, but it seems that they point to the address of the first character and not the ‘begin’ iter.

Please help me if you can, thanks,
Roger.

Below is the (messy) search() function of find.c, along with some of my inept attempts:

void search(GtkButton *button, Widgets w /, struct large_struct *large */)
{
const gchar *find;
gchar *output;
GtkWidget *dialog;
GtkWidget *textview1;
GtkTextBuffer *buffer;
GtkTextIter start, begin, end;
GtkTextMark *mark = 0;
/const gchar mark = 0;/
/const gchar marks = malloc(2sizeof(const gchar));/
int findstring = 3;
/int findstring = w->findstring;/
/int findstring = large->findstring;/

gboolean success;
gint i = 0;
find = gtk_entry_get_text(GTK_ENTRY(w->entry1));
textview1 = w->textview1;
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview1));

gtk_text_buffer_get_start_iter(buffer, &start);
gtk_text_iter_forward_visible_cursor_position(&start);

success = gtk_text_iter_forward_search(&start, (gchar*) find, GTK_TEXT_SEARCH_TEXT_ONLY, &begin, &end, NULL);

gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);

gtk_text_buffer_create_mark(buffer, /*"mark"*/ (const gchar *) mark, &begin, FALSE);

gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW(textview1), (GtkTextMark *) mark, 0, TRUE, 0, 0.5);
/*gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textview1), (GtkTextMark *) mark);*/

gtk_text_buffer_select_range(buffer, &begin, &end);
/*gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &end, 0, TRUE, 0, 0.5);*/

/*gtk_text_buffer_create_mark(buffer, &mark, &begin, FALSE);
gtk_text_view_scroll_mark_onscreen((GtkTextView *) textview1, (GtkTextMark *) &mark);*/

/*Works for first*/
/*gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);*/

/*Works for second*/
/*start = end;
success = gtk_text_iter_forward_search(&start, (gchar*) find, 0, &begin, &end, NULL);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);
gtk_text_buffer_select_range(buffer, &begin, &end);*/

/*while(success)
{
gtk_text_iter_forward_char(&start);
success = gtk_text_iter_forward_search(&start, (gchar*) find, GTK_TEXT_SEARCH_TEXT_ONLY, &begin, &end, NULL);*/

/*if (success)
{*/
/*gtk_text_buffer_create_mark(buffer, &marks[i], &begin, FALSE);
gtk_text_mark_set_visible((GtkTextMark *) marks[i], TRUE);
gtk_text_view_scroll_mark_onscreen((GtkTextView *) textview1, (GtkTextMark *) &marks[1]);*/
/*}*/

  /*if ((success) && (i < findstring))
  {
  continue;
  }
  else*//* if (i == findstring)
  {
  gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(textview1), &begin, 0, TRUE, 0, 0.5);
  gtk_text_buffer_select_range(buffer, &begin, &end);
  }
  else if (i > findstring)
  {
  break;
  }

start = begin;
i++;
}

output = g_strdup_printf("The string '%s' was found %i times!", find, i);
dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, output, NULL);

gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free(output);*/

/*free(marks);*/

}

(ff3:3326): Gtk-CRITICAL **: 11:57:45.684: gtk_text_view_scroll_to_mark: assertion ‘GTK_IS_TEXT_MARK (mark)’ failed

Another problem is the runtime message:
Gtk-Message: 13:10:53.725: GtkDialog mapped without a transient parent. This is discouraged.
As I don’t need the dialog (at present) then this is not a pressing issue and can be avoided by temporarily commenting out the dialog, but it would be good to get rid of the problem. It is probably because the textview is in a notebook.

Issue resolved, thanks.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.