On 02/17/2017 08:26 PM, cecas...@aol.com wrote: > David, > > I asked a question about this on the gtk-devel-list > > https://mail.gnome.org/archives/gtk-devel-list/2017-January/msg00018.html > > last month. A lot I didn't know about this. For UTF-8 it is a bit complicated > even for English. For GTK's case in-sensitive search they use a casefold > function and a normalizing function. This way you can do a case in-sensitive > search on strings with ligatures and accents. If you are just sticking with > asci english chars then just converting and comparing case should work. There > is a bit more to it though for UTF-8 and unicode chars. > > I worked on this a little bit so that I could understand it better. My last > attempt was > > https://github.com/cecashon/OrderedSetVelociRaptor/blob/master/Misc/Csamples/search_textbuffer4.c > > The GTK developers are working on GTK4. GTK3.22 should be stable for 3. GTK2 > or 3 is fine with me. > > Eric >
Eric, After working with it a bit more, I encapsulated the forward and reverse case-insensitive search functions for use without gtksourceview. They are part of a little editor project I put together at: https://github.com/drankinatty/gtkwrite The functions are: /** case insensitive forward search for implementation without * GtkSourceView. */ gboolean gtk_text_iter_forward_search_nocase (GtkTextIter *iter, const gchar *text, GtkTextSearchFlags flags, GtkTextIter *mstart, GtkTextIter *mend) { gunichar c; gchar *lctext = g_strdup (text); /* copy text */ gsize textlen = g_strlen (text); /* get length */ str2lower (lctext); for (;;) { /* iterate over all chars in range */ gsize len = textlen; /* get char at iter */ c = g_unichar_tolower (gtk_text_iter_get_char (iter)); if (c == (gunichar)lctext[0]) /* compare 1st in lctext */ { *mstart = *iter; /* set start iter to current */ for (gsize i = 0; i < len; i++) { c = g_unichar_tolower (gtk_text_iter_get_char (iter)); /* compare/advance -- order IS important */ if (c != (gunichar)lctext[i] || !gtk_text_iter_forward_char (iter)) goto next; /* start next search */ } *mend = *iter; /* set end iter */ if (lctext) g_free (lctext); /* free lctext */ return TRUE; /* return true */ } next:; /* if at end of selecton break */ if (!gtk_text_iter_forward_char (iter)) break; } if (lctext) g_free (lctext); /* free lctext */ if (mstart || mend || flags) {} return FALSE; } /** case insensitive backward search for implementation without * GtkSourceView. */ gboolean gtk_text_iter_backward_search_nocase (GtkTextIter *iter, const gchar *text, GtkTextSearchFlags flags, GtkTextIter *mstart, GtkTextIter *mend) { gunichar c; gchar *lctext = g_strdup (text); /* copy text */ gsize textlen = g_strlen (text); /* get length */ str2lower (lctext); /* convert to lower-case */ *mend = *iter; /* initialize end iterator */ while (gtk_text_iter_backward_char (iter)) { gsize len = textlen - 1; /* index for last in lctext */ c = g_unichar_tolower (gtk_text_iter_get_char (iter)); if (c == (gunichar)lctext[len]) /* initial comparison */ { /* iterate over remaining chars in lctext/compare */ while (len-- && gtk_text_iter_backward_char (iter)) { c = g_unichar_tolower (gtk_text_iter_get_char (iter)); if (c != (gunichar)lctext[len]) { /* reset iter to right of char */ gtk_text_iter_forward_char (iter); goto prev; } } *mstart = *iter; /* set start iter before last char */ if (lctext) g_free (lctext); /* free lctext */ return TRUE; /* return success */ } prev:; *mend = *iter; /* set end iter after next search char */ } if (lctext) g_free (lctext); /* free lctext */ if (mstart || mend || flags) {} return FALSE; /* no match */ } Implementation is using the cpp #define HAVESOURCEVIEW for compilation purposes, e.g. /* case sensitive forward/reverse search from iter for 'text' setting * iters mstart & mend pointing to first & last char in matched text. */ if (app->optback) { /* search backward */ if (app->optcase) { /* case sensitive */ found = gtk_text_iter_backward_search (&iter, text, 0, &mstart, &mend, NULL); } else { /* case insensitive backwards search */ #ifdef HAVESOURCEVIEW found = gtk_source_iter_backward_search (&iter, text, GTK_SOURCE_SEARCH_CASE_INSENSITIVE, &mstart, &mend, NULL); #else found = gtk_text_iter_backward_search_nocase (&iter, text, 0, &mstart, &mend); #endif } } else { /* search forward */ if (app->optcase) { /* case sensitive */ found = gtk_text_iter_forward_search (&iter, text, 0, &mstart, &mend, NULL); } else { /* case insensitive forward search */ #ifdef HAVESOURCEVIEW found = gtk_source_iter_forward_search (&iter, text, GTK_SOURCE_SEARCH_CASE_INSENSITIVE, &mstart, &mend, NULL); #else found = gtk_text_iter_forward_search_nocase (&iter, text, 0, &mstart, &mend); #endif } } Hope this can help someone else. -- David C. Rankin, J.D.,P.E. _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list