[grisbi-cvs] grisbi/src gsb_real.c,1.31,1.32

Pierre Biava pbiava at users.sourceforge.net
Sat May 9 19:04:39 CEST 2009


Update of /cvsroot/grisbi/grisbi/src
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv17909

Modified Files:
	gsb_real.c 
Log Message:
new version for gsb_real_format_string and gsb_real_get_from_string_normalized to integrate the management of UTF8 characters

Index: gsb_real.c
===================================================================
RCS file: /cvsroot/grisbi/grisbi/src/gsb_real.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- gsb_real.c	2 May 2009 15:39:15 -0000	1.31
+++ gsb_real.c	9 May 2009 17:04:37 -0000	1.32
@@ -112,19 +112,19 @@
  *			function will never return NULL) 
  */
 gchar *gsb_real_format_string ( gsb_real number,
-				gint currency_number,
-				gboolean show_symbol )
+                        gint currency_number,
+                        gboolean show_symbol )
 {
     struct lconv * conv = localeconv ( );
-    div_t result_div;
-    gchar *string, *exponent, *mantissa;
-    gint i = 0, j=0;
+    gchar *string, *exponent = NULL, *mantissa;
     glong num;
+    gint nbre_char;
     const gchar *currency_symbol = NULL;
+    char buf[G_ASCII_DTOSTR_BUF_SIZE];
 
-    /* as we use localeconv, all the currencies in grisbi will be formatted as the locale of the system
-     * i think it's ok like that, and to adapt the view according with the currency and not the current
-     * locale is much more complicated */
+    /* as we use localeconv, all the currencies in grisbi will be formatted as the locale of 
+     * the system i think it's ok like that, and to adapt the view according with the 
+     * currency and not the current locale is much more complicated */
     if (currency_number && show_symbol)
         currency_symbol = gsb_data_currency_get_code (currency_number);
     
@@ -140,79 +140,82 @@
     }
 
     /* first we need to adapt the exponent to the currency */
+    /* if the exponent of the real is not the same of the currency, need to adapt it */
     if ( currency_number
-	&&
-	number.exponent != gsb_data_currency_get_floating_point (currency_number) )
-        /* the exponent of the real is not the same of the currency, need to adapt it */
+      &&
+      number.exponent != gsb_data_currency_get_floating_point (currency_number) )
         number = gsb_real_adjust_exponent ( number, gsb_data_currency_get_floating_point (
                         currency_number) );
-    
-    /* for a long int : max 11 char
-     * so with the possible -, the spaces and the .
-     * we arrive to maximum 14 char : -21 474 836.48 + 1 for the 0 terminal */
-    mantissa = g_malloc0 ( 15*sizeof (gchar) );
-    exponent = g_malloc0 ( 15*sizeof (gchar) );
-    string = mantissa;
 
+    /* on traite la conversion avec g_ascii_dtostr */
     num = labs(number.mantissa);
 
-    /* Construct the result in the reverse order from right to left, then reverse it. */
-    do
+    mantissa = g_ascii_dtostr ( buf, sizeof (buf), num );
+    if ( ! mantissa )
+            return g_strdup ("Error");
+
+    nbre_char = g_utf8_strlen ( mantissa, -1);
+
+    /* on extrait la partie entière et la partie décimale */
+    if ( nbre_char > number.exponent )
     {
-        if ( i == number.exponent)
+        exponent = g_strdup ( mantissa + (nbre_char - number.exponent ) );
+        mantissa = g_strndup ( mantissa, (nbre_char - number.exponent) );
+    }
+    else
+    {
+        if ( nbre_char < number.exponent )
         {
-            *string = 0;
-            string = exponent;
-            result_div.quot = num;
+            exponent = g_strnfill ( number.exponent - nbre_char, '0' );
+            exponent = g_strconcat ( exponent, mantissa, NULL );
         }
         else
+            exponent = g_strdup ( mantissa );
+        mantissa = g_strdup ( "0" );
+    }
+
+    /* on insère le séparateur des milliers */
+    gchar *mon_thousands_sep_utf8;
+
+    if ( nbre_char > 3 && (mon_thousands_sep_utf8 = g_locale_to_utf8 (
+                        conv->mon_thousands_sep, -1, NULL, NULL, NULL )) )
+    {
+        gchar *reverse;
+        gchar *ptr_char, *ptr_fin = NULL;
+        gchar *dest = NULL;
+        gchar *ch;
+        gint i = 0;
+
+        reverse = g_utf8_strreverse ( mantissa, -1 );
+        dest = g_malloc0 ( 30 * sizeof (gunichar));
+
+        nbre_char = g_utf8_strlen ( reverse, -1);
+        ptr_char = reverse;
+        ptr_fin = dest;
+        for (i = 0; i < nbre_char; i++)
         {
-            if (i > number.exponent)
-                j++;
+            ch = g_strndup (ptr_char, 1);
+            if ( i == 3 )
+                ptr_fin = g_stpcpy (ptr_fin, mon_thousands_sep_utf8 );
+            ptr_fin = g_stpcpy ( ptr_fin, ch );
+            ptr_char = g_utf8_next_char ( ptr_char );
 
-            if ( j == 4 )
-            {
-                j=0;
-                if ( * (conv -> mon_thousands_sep ) )
-                {
-                    *string++ = * ( conv -> mon_thousands_sep );
-                }
-                else
-                {
-                    i--;
-                }
-                result_div.quot = num;
-            }
-            else
-            {
-                result_div = div ( num, 10 );
-                *string++ = result_div.rem + '0';
-            }
+            if (ptr_char == NULL) break;
         }
-        i++;
-        /* we check also i < (number.exponent+2)
-         * the +2 is for 0. at the left of the separator,
-         * with that check, 0 will be 0.00 if exponent = 2,
-         * and 0.51 will be 0.51 and no 51 without that check */
+        mantissa = g_utf8_strreverse ( dest, -1 );
+        g_free ( reverse );
+        g_free ( dest );
     }
-    while ( ( num = result_div.quot )
-        ||
-        i < number.exponent+2
-	    ||
-  	    (currency_number
-	     &&
-	     i < gsb_data_currency_get_floating_point (currency_number)));
-
-
+    
     /* Add the sign at the end of the string just before to reverse it to avoid
        to have to insert it at the begin just after... */
     string = g_strdup_printf ( "%s%s%s%s%s%s%s%s", 
                     ( currency_symbol && conv -> p_cs_precedes ? currency_symbol : "" ),
                     ( currency_symbol && conv -> p_sep_by_space ? " " : "" ),
                     number.mantissa < 0 ? conv -> negative_sign : conv -> positive_sign,
-                    strlen (exponent) ? g_strreverse ( exponent ) : "0",
+                    mantissa,
                     ( * conv -> mon_decimal_point ? conv -> mon_decimal_point : "." ),
-                    g_strreverse ( mantissa ),
+                    strlen (exponent) ? exponent : "0",
                     ( currency_symbol && ! conv -> p_cs_precedes && conv -> p_sep_by_space ? 
                     " " : "" ),
                     ( currency_symbol && ! conv -> p_cs_precedes ? currency_symbol : "" ) );
@@ -220,7 +223,7 @@
     g_free ( exponent );
     g_free ( mantissa );
 
-    return ( string );
+    return string;
 }
 
 
@@ -279,83 +282,52 @@
  */
 gsb_real gsb_real_get_from_string_normalized ( const gchar *string, gint default_exponent )
 {
+    struct lconv * conv = localeconv ( );
     gsb_real number = null_real;
-    gint i = 0, sign;
-    gchar *string_tmp;
+    gchar *new_str;
+    gchar *mon_thousands_sep_utf8;
+    gchar *ptr;
+    gchar**	tab;
+    gint sign;
 
     if ( !string
 	 ||
 	 !strlen (string))
-	return number;
+        return number;
 
-    string_tmp = my_strdup (string);
+    new_str = my_strdup (string);
 
-    /* if there is an exponent, finish the string at the good position of the exponent */
-    if ( default_exponent > 0 )
+    /* on enlève les séparateurs des milliers */
+    mon_thousands_sep_utf8 = g_locale_to_utf8 (
+                        conv->mon_thousands_sep, -1, NULL, NULL, NULL );
+    if ( g_utf8_strchr (new_str, -1, g_utf8_get_char (mon_thousands_sep_utf8)) )
     {
-	gchar *separator, *tmp;
-
-	separator = strrchr ( string_tmp, '.' );
-	if ( ! separator )
-	    separator = strrchr ( string_tmp, ',' );
-
-	if ( separator )
-	{
-	    tmp = string_tmp + strlen ( string_tmp ) - 1;
-	    while ( * tmp == '0' && ( tmp - separator > default_exponent ) &&
-		    tmp >= string_tmp ) 
-	    {
-		* tmp = '\0';
-		tmp --;
-	    }
-	}
+        tab = g_strsplit ( new_str, mon_thousands_sep_utf8, 0 );
+        g_free ( new_str );
+        new_str = g_strjoinv ( "", tab );
+        g_strfreev ( tab );
     }
 
-    if (string_tmp[0] == '-')
-    {
-	sign = -1;
-	i++;
-    }
+    /* on extrait le signe */
+    if ( new_str[0] == *(conv -> negative_sign) )
+        sign = -1;
     else
-    {
-	sign = 1;
-	/* sometimes we can have "+12" so we pass the + */
-	if (string_tmp[0] == '+' )
-	    i++;
-    }
-
-    while (string_tmp[i])
-    {
-	switch (string_tmp[i])
-	{
-	    case ',':
-	    case '.':
-		number.exponent = strlen (string_tmp) -i -1;
-		break;
+        sign = 1;
 
-	    case ' ':
-		break;
+    /* On détermine l'exponent */
+    if ( (ptr = g_strrstr (new_str, conv -> mon_decimal_point)) )
+        number.exponent = strlen ( ptr ) - 1;
 
-	    default:
-		if (string_tmp[i] >= '0'
-		    &&
-		    string_tmp[i] <= '9' )
-		{
-		    number.mantissa = number.mantissa * 10;
-		    number.mantissa = number.mantissa + string_tmp[i] - '0';
-		}
-		else
-		{
-		    /* if there is another char, we do nothing */
-		    g_free (string_tmp);
-		    return null_real;
-		}
-	}
-	i++;
-    }
+    /* on détermine la mantisse on supprime tous les séparateurs et autres signes */
+    tab = g_strsplit_set ( new_str, g_strconcat (
+                        "+", "-", conv -> mon_decimal_point, NULL), 0 );
+    g_free ( new_str );
+    new_str = g_strjoinv ( "", tab );
+    g_strfreev ( tab );
 
+    number.mantissa = (glong) g_ascii_strtod ( new_str, NULL );
     number.mantissa = sign * number.mantissa;
-    g_free (string_tmp);
+    g_free ( new_str );
 
     return number;
 }
@@ -563,13 +535,9 @@
 gsb_real gsb_real_mul ( gsb_real number_1,
 			gsb_real number_2 )
 {
-    gsb_real number;
-
-    number = gsb_real_double_to_real ( gsb_real_real_to_double (number_1)
-				       *
-				       gsb_real_real_to_double (number_2));
-
-    return number;
+    number_1.mantissa *= number_2.mantissa;
+    number_1.exponent += number_2.exponent;
+    return number_1;
 }
 
 



More information about the cvs mailing list