Re: Does gtk2 provide a case 'in'-sensitive text search via 'gtk_text_iter_..._search'?
- From: "David C. Rankin" <drankinatty suddenlinkmail com>
- To: cecashon aol com, gtk-app-devel-list gnome org
- Subject: Re: Does gtk2 provide a case 'in'-sensitive text search via 'gtk_text_iter_..._search'?
- Date: Tue, 21 Feb 2017 20:26:14 -0600
On 02/17/2017 08:26 PM, cecashon 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.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]