Re: Locales, utf8, and spinbuttons



On Tue, Jul 31, 2001 at 07:59:39PM +0100, Joel Becker wrote:
> Folks,
> 	So, I was thinking about validating numeric entry, and I wanted
> to see how to use localeconv().  Grepping brought me to gtkspinbutton.c,
> gtk_spin_button_insert_text().  This brings up a couple questions and
> problems.
> 
> Obvious problems:
> 
> o The spinbutton's validation loops on new_text_length.  If I understand
>   the "insert_text" signal correctly, new_text_length is a byte count,
>   not a character count, so this is not utf8 safe.
> o The spinbutton checks the numeric value with ascii checks.  This is ok
>   in utf8 against ascii numeral characters, but does not handle
>   non-arabic numbers (IMO, it should be using g_unichar_is_digit() and
>   g_unichar_digit_value()).

	Ok, my function is attached below.  It should be pretty easy to
merge into the spinbutton code.  But if anyone is interested in looking
at it first, to tell me if I missed any obvious stupidities, I'd
appreciate it.

Thanks
Joel

-- 

"I almost ran over an angel
 He had a nice big fat cigar.
 'In a sense,' he said, 'You're alone here
 So if you jump, you'd best jump far.'"

			http://www.jlbec.org/
			jlbec@evilplan.org
/* static void do_numeric_insert_text(GtkWidget *widget,
 *                                    gpointer arg1, gpointer arg2,
 *                                    gpointer arg3, gpointer user_data)
 *
 * Handler for the "insert_text" signal on numeric entries.  It
 * prevents users from entering text, et al.
 */
static void do_numeric_insert_text(GtkWidget *widget,
                                   gpointer arg1, gpointer arg2,
                                   gpointer arg3, gpointer user_data)
{
    gint position;
    gboolean err, done, have_sign, have_dp;
    gunichar c, dp, ts, ns, ps;
    gchar *curtext, *text, *ptr;
    struct lconv *lc;
    
    err = TRUE;
    text = (gchar *)arg1;
    if (g_utf8_validate(text, -1, NULL) == FALSE)
    {
        g_warning("g_utf8_validate failed in \"insert_text\"!\n");
        goto out;
    }

    curtext = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
    if (curtext == NULL)
        curtext = g_strdup("");
    if (g_utf8_validate(curtext, -1, NULL) == FALSE)
    {
        g_warning("g_utf8_validate failed on widget in  \"insert_text\"!\n");
        goto out;
    }

    position = *(gint *)arg3;

    lc = localeconv();
    if (lc->decimal_point)
    {
        ptr = g_locale_to_utf8(lc->decimal_point, -1, NULL, NULL, NULL);
        dp = g_utf8_get_char(ptr);
        g_free(ptr);
    }
    else
        dp = g_utf8_get_char(".");
   
    if (*(lc->negative_sign))
    {
        ptr = g_locale_to_utf8(lc->negative_sign, -1, NULL, NULL, NULL);
        ns = g_utf8_get_char(ptr);
        g_free(ptr);
    }
    else
        ns = g_utf8_get_char("-");
 
    if (*(lc->positive_sign))
    {
        ptr = g_locale_to_utf8(lc->positive_sign, -1, NULL, NULL, NULL);
        ps = g_utf8_get_char(ptr);
        g_free(ptr);
    }
    else
        ps = g_utf8_get_char("+");

    done = FALSE;
    have_sign = FALSE;
    have_dp = FALSE;
    ptr = curtext;
    while (done == FALSE)
    {
        if (*ptr != '\0')
        {
            c = g_utf8_get_char(ptr);
            if ((c == ns) || (c == ps))
                have_sign = TRUE;
            else if (c == dp)
                have_dp = TRUE;
            if (have_dp && have_sign)
                done = TRUE;
            ptr = g_utf8_next_char(ptr);
        }
        else
            done = TRUE;
    }

    done = FALSE;
    ptr = text;
    while (done == FALSE)
    {
        if (*ptr != '\0')
        {
            c = g_utf8_get_char(ptr);
            if (c == dp)
            {
                if (have_dp != FALSE)
                    goto out;
            }
            else if ((c == ns) || (c == ps))
            {
                if ((have_sign != FALSE) ||
                    (ptr != text) ||
                    (position != 0))
                    goto out;
            }
            else if (g_unichar_isdigit(c) == FALSE)
                goto out;
            ptr = g_utf8_next_char(ptr);
        }
        else
            done = TRUE;
    }

    err = FALSE;

out:
    g_free(curtext);

    if (err != FALSE)
    {
        gdk_beep();
        gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),
                                     "insert_text");
    }
}  /* do_numeric_insert_text() */




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]