[goffice] GOFormat: add "min_digits" to details.



commit d7a315b0119ce411e5abbff17863f36c22e95ac5
Author: Morten Welinder <terra gnome org>
Date:   Tue Jun 2 11:53:57 2009 -0400

    GOFormat: add "min_digits" to details.
---
 ChangeLog                   |   14 +++
 goffice/gtk/go-format-sel.c |   20 ++++-
 goffice/utils/formats.c     |   21 +++--
 goffice/utils/go-format.c   |  193 +++++++++++++++++++++++-------------------
 goffice/utils/go-format.h   |   21 +----
 5 files changed, 152 insertions(+), 117 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3d6aa37..73c2c7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2009-06-02  Morten Welinder  <terra gnome org>
+
+	* goffice/gtk/go-format-sel.c (study_format): Deal with issues the
+	GUI does not handle.
+
+	* goffice/utils/go-format.c (go_format_get_details): Figure out
+	min_digit_width too.  Figure out decimals for seconds.  Use
+	go_format_details_init.
+	(go_format_details_init): New function.
+	(go_format_generate_currency_str,
+	go_format_generate_accounting_str,
+	go_format_generate_scientific_str): Make static and just take
+	details.  All callers fixed use to go_format_generate_str.
+
 2009-06-02  Andreas J. Guelzow  <aguelzow pyrshep ca>
 
 	* goffice/utils/go-format.c (go_format_output_number_to_odf): set
diff --git a/goffice/gtk/go-format-sel.c b/goffice/gtk/go-format-sel.c
index aaf6015..de4369c 100644
--- a/goffice/gtk/go-format-sel.c
+++ b/goffice/gtk/go-format-sel.c
@@ -830,15 +830,27 @@ study_format (GOFormatSel *gfs)
 {
 	const GOFormat *fmt = gfs->format.spec;
 	gboolean exact;
+	GOFormatDetails *details = &gfs->format.details;
+
+	go_format_get_details (fmt, details, &exact);
+
+	if (exact) {
+		/* Thing we do not have GUI for: */
+		if (details->family == GO_FORMAT_ACCOUNTING &&
+		    !details->thousands_sep)
+			exact = FALSE;
+
+		if (details->min_digits != 1)
+			exact = FALSE;
+	}
 
-	go_format_get_details (fmt, &gfs->format.details, &exact);
 	if (!exact) {
 		const char *str = go_format_as_XL (fmt);
-		if (!find_builtin (str, gfs->format.details.family, FALSE))
-			gfs->format.details.family = FMT_CUSTOM;
+		if (!find_builtin (str, details->family, FALSE))
+			details->family = FMT_CUSTOM;
 	}
 
-	return gfs->format.details.family;
+	return details->family;
 }
 
 
diff --git a/goffice/utils/formats.c b/goffice/utils/formats.c
index 197506c..2f3aa84 100644
--- a/goffice/utils/formats.c
+++ b/goffice/utils/formats.c
@@ -201,24 +201,25 @@ go_currency_date_format_init (void)
 	GOFormat *fmt;
 	guint N;
 	int i;
+	GOFormatDetails details;
 
+	go_format_details_init (&details, GO_FORMAT_CURRENCY);
+	details.currency = currency;
 	for (i = 0; i < 6; i++) {
-		int num_decimals = (i >= 3) ? 2 : 0;
-		gboolean negative_red = (i % 3 == 2);
-		gboolean negative_paren = (i % 3 >= 1);
 		GString *str = g_string_new (NULL);
-		go_format_generate_currency_str (str, num_decimals, TRUE,
-						 negative_red, negative_paren,
-						 currency, FALSE);
+		details.num_decimals = (i >= 3) ? 2 : 0;
+		details.negative_red = (i % 3 == 2);
+		details.negative_paren = (i % 3 >= 1);
+		go_format_generate_str (str, &details);
 		fmts_currency[i] = g_string_free (str, FALSE);
 	}
 
+	go_format_details_init (&details, GO_FORMAT_ACCOUNTING);
 	for (i = 0; i < 4; i++) {
-		int num_decimals = (i >= 2) ? 2 : 0;
-		gboolean no_currency = (i & 1);
 		GString *str = g_string_new (NULL);
-		go_format_generate_accounting_str
-			(str, num_decimals, no_currency ? NULL : currency);
+		details.num_decimals = (i >= 2) ? 2 : 0;
+		details.currency = (i & 1) ? NULL : currency;
+		go_format_generate_str (str, &details);
 		fmts_accounting[i] = g_string_free (str, FALSE);
 	}
 
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index c1f3208..e044633 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -4974,6 +4974,7 @@ go_format_default_accounting (void)
 /**
  * go_format_generate_number_str:
  * @dst: GString to append format string to.
+ * @min_digits: minimum number of digits before decimal separator.
  * @num_decimals: number of decimals
  * @thousands_sep: if true, use a thousands separator.
  * @negative_red: if true, make negative values red.
@@ -4986,6 +4987,7 @@ go_format_default_accounting (void)
  **/
 void
 go_format_generate_number_str (GString *dst,
+			       int min_digits,
 			       int num_decimals,
 			       gboolean thousands_sep,
 			       gboolean negative_red,
@@ -4995,13 +4997,31 @@ go_format_generate_number_str (GString *dst,
 	size_t init_len = dst->len;
 	size_t plain_len;
 
+	if (min_digits < 0) min_digits = 0;
+	if (num_decimals < 0) num_decimals = 0;
+
 	if (prefix)
 		g_string_append (dst, prefix);
 
-	if (thousands_sep)
-		g_string_append (dst, "#,##0");
-	else
-		g_string_append_c (dst, '0');
+	if (thousands_sep) {
+		switch (min_digits) {
+		case 0: g_string_append (dst, "#,###"); break;
+		case 1: g_string_append (dst, "#,##0"); break;
+		case 2: g_string_append (dst, "#,#00"); break;
+		case 3: g_string_append (dst, "#,000"); break;
+		default: {
+			int r = min_digits % 3;
+			go_string_append_c_n (dst, '0', r ? r : 3);
+			for (r = min_digits; r > 3; r -= 3)
+				g_string_append (dst, ",000");
+		}
+		}
+	} else {
+		if (min_digits > 0)
+			go_string_append_c_n (dst, '0', min_digits);
+		else
+			g_string_append_c (dst, '#');
+	}
 
 	if (num_decimals > 0) {
 		g_string_append_c (dst, '.');
@@ -5029,36 +5049,21 @@ go_format_generate_number_str (GString *dst,
 #endif
 
 #ifdef DEFINE_COMMON
-/**
- * go_format_generate_scientific_str:
- * @dst: GString to append format string to.
- * @num_decimals: number of decimals
- * @exponent_step: pick exponent divisible by them.  Typically 1 or 3.
- * @use_markup: if true, use pango markup for exponent.
- * @simplify_mantissa: if true, avoid pointless "1*" mantissas.
- *
- * Generates a format string for a scientific format with the given
- * parameters and appends it to @dst.
- **/
-void
-go_format_generate_scientific_str (GString *dst,
-				   int num_decimals,
-				   int exponent_step,
-				   gboolean use_markup,
-				   gboolean simplify_mantissa)
+static void
+go_format_generate_scientific_str (GString *dst, GOFormatDetails const *details)
 {
-	go_string_append_c_n (dst, '#', MAX (0, exponent_step - 1));
-	if (simplify_mantissa)
+	go_string_append_c_n (dst, '#', MAX (0, details->exponent_step - 1));
+	if (details->simplify_mantissa)
 		g_string_append_c (dst, '#');
 	else
 		g_string_append_c (dst, '0');
 
-	if (num_decimals > 0) {
+	if (details->num_decimals > 0) {
 		g_string_append_c (dst, '.');
-		go_string_append_c_n (dst, '0', num_decimals);
+		go_string_append_c_n (dst, '0', details->num_decimals);
 	}
 
-	if (use_markup)
+	if (details->use_markup)
 		g_string_append (dst, "EE0");
 	else
 		g_string_append (dst, "E+00");
@@ -5066,25 +5071,16 @@ go_format_generate_scientific_str (GString *dst,
 #endif
 
 #ifdef DEFINE_COMMON
-/**
- * go_format_generate_accounting_str:
- * @dst: GString to append format string to.
- * @num_decimals: number of decimals.
- * @currency: optional currency descriptor.
- *
- * Generates a format string for an accounting format with the given
- * parameters and appends it to @dst.
- **/
-void
+static void
 go_format_generate_accounting_str (GString *dst,
-				   int num_decimals,
-				   GOFormatCurrency const *currency)
+				   GOFormatDetails const *details)
 {
 	GString *num = g_string_new (NULL);
 	GString *sym = g_string_new (NULL);
 	GString *q = g_string_new (NULL);
 	const char *symstr;
 	const char *quote = "\"";
+	GOFormatCurrency const *currency = details->currency;
 
 	if (!currency)
 		currency = &go_format_currencies[0];
@@ -5106,9 +5102,11 @@ go_format_generate_accounting_str (GString *dst,
 		break;
 	}
 
-	go_format_generate_number_str (num, num_decimals, TRUE,
+	go_format_generate_number_str (num, details->min_digits,
+				       details->num_decimals,
+				       details->thousands_sep,
 				       FALSE, FALSE, NULL, NULL);
-	go_string_append_c_n (q, '?', num_decimals);
+	go_string_append_c_n (q, '?', details->num_decimals);
 
 	if (currency->precedes) {
 		g_string_append (sym, quote);
@@ -5145,36 +5143,19 @@ go_format_generate_accounting_str (GString *dst,
 #endif
 
 #ifdef DEFINE_COMMON
-/**
- * go_format_generate_currency_str:
- * @dst: GString to append format string to.
- * @num_decimals: number of decimals.
- * @thousands_sep: if true, use a thousands separator.
- * @negative_red: if true, make negative values red.
- * @negative_paren: if true, enclose negative values in parentheses.
- * @currency: currency descriptor.
- * @force_quoted: if true, make sure the currency symbol is quoted.
- *
- * Generates a format string for a currency format with the given
- * parameters and appends it to @dst.
- **/
-void
+static void
 go_format_generate_currency_str (GString *dst,
-				 int num_decimals,
-				 gboolean thousands_sep,
-				 gboolean negative_red,
-				 gboolean negative_paren,
-				 GOFormatCurrency const *currency,
-				 gboolean force_quoted)
+				 GOFormatDetails const *details)
 {
 	GString *prefix = NULL;
 	GString *postfix = NULL;
 	gboolean extra_quotes;
+	GOFormatCurrency const *currency = details->currency;
 
 	if (!currency)
 		currency = &go_format_currencies[0];
 
-	extra_quotes = (force_quoted &&
+	extra_quotes = (details->force_quoted &&
 			currency->symbol[0] != '"' &&
 			currency->symbol[0] != 0);
 
@@ -5193,8 +5174,12 @@ go_format_generate_currency_str (GString *dst,
 		if (extra_quotes) g_string_append_c (postfix, '"');
 	}
 
-	go_format_generate_number_str (dst, num_decimals, thousands_sep,
-				       negative_red, negative_paren,
+	go_format_generate_number_str (dst,
+				       details->min_digits,
+				       details->num_decimals,
+				       details->thousands_sep,
+				       details->negative_red,
+				       details->negative_paren,
 				       prefix ? prefix->str : NULL,
 				       postfix ? postfix->str : NULL);
 
@@ -5261,6 +5246,7 @@ go_format_generate_str (GString *dst, GOFormatDetails const *details)
 	case GO_FORMAT_NUMBER:
 		go_format_generate_number_str
 			(dst,
+			 details->min_digits,
 			 details->num_decimals,
 			 details->thousands_sep,
 			 details->negative_red,
@@ -5268,22 +5254,15 @@ go_format_generate_str (GString *dst, GOFormatDetails const *details)
 			 NULL, NULL);
 		break;
 	case GO_FORMAT_CURRENCY:
-		go_format_generate_currency_str
-			(dst,
-			 details->num_decimals,
-			 details->thousands_sep,
-			 details->negative_red,
-			 details->negative_paren,
-			 details->currency,
-			 details->force_quoted);
+		go_format_generate_currency_str (dst, details);
 		break;
 	case GO_FORMAT_ACCOUNTING:
-		go_format_generate_accounting_str
-			(dst, details->num_decimals, details->currency);
+		go_format_generate_accounting_str (dst, details);
 		break;
 	case GO_FORMAT_PERCENTAGE:
 		go_format_generate_number_str
 			(dst,
+			 details->min_digits,
 			 details->num_decimals,
 			 details->thousands_sep,
 			 details->negative_red,
@@ -5291,12 +5270,7 @@ go_format_generate_str (GString *dst, GOFormatDetails const *details)
 			 NULL, "%");
 		break;
 	case GO_FORMAT_SCIENTIFIC:
-		go_format_generate_scientific_str
-			(dst,
-			 details->num_decimals,
-			 details->exponent_step,
-			 details->use_markup,
-			 details->simplify_mantissa);
+		go_format_generate_scientific_str (dst, details);
 		break;
 	default:
 		break;
@@ -5306,6 +5280,24 @@ go_format_generate_str (GString *dst, GOFormatDetails const *details)
 
 #ifdef DEFINE_COMMON
 void
+go_format_details_init (GOFormatDetails *details, GOFormatFamily family)
+{
+	g_return_if_fail (details != NULL);
+
+	memset (details, 0, sizeof (*details));
+	/* Assign reasonable defaults.  For most, the memset is just fine. */
+	details->family = family;
+	details->thousands_sep = (family == GO_FORMAT_ACCOUNTING ||
+				  family == GO_FORMAT_CURRENCY);
+	details->magic = GO_FORMAT_MAGIC_NONE;
+	details->exponent_step = 1;
+	details->min_digits = 1;
+}
+#endif
+
+
+#ifdef DEFINE_COMMON
+void
 go_format_get_details (GOFormat const *fmt,
 		       GOFormatDetails *dst,
 		       gboolean *exact)
@@ -5314,15 +5306,12 @@ go_format_get_details (GOFormat const *fmt,
 	GString *newstr = NULL;
 	static GOFormatCurrency currency;
 
-	if (dst) memset (dst, 0, sizeof (*dst));
-	if (exact) *exact = FALSE;
 	g_return_if_fail (fmt != NULL);
 	g_return_if_fail (dst != NULL);
 
-	dst->family = go_format_get_family (fmt);
+	if (exact) *exact = FALSE;
+	go_format_details_init (dst, go_format_get_family (fmt));
 	dst->magic = go_format_get_magic (fmt);
-	/* Assign reasonable defaults.  For most, the memset is just fine. */
-	dst->exponent_step = 1;
 
 	str = go_format_as_XL (fmt);
 
@@ -5337,13 +5326,25 @@ go_format_get_details (GOFormat const *fmt,
 		 * the formats we generate ourselves.
 		 */
 
-		const char *dot = strchr (str, '.');
+ 		const char *dot = strchr (str, '.');
+ 		const char *zero = strchr (str, '0');
+ 		const char *comma = strchr (str, ',');
 
 		if (dot) {
 			while (dot[dst->num_decimals + 1] == '0')
 				dst->num_decimals++;
 		}
 
+		dst->min_digits = 0;
+		if (zero) {
+			const char *p = zero;
+			while (*p == ',' || *p == '0') {
+				if (*p == '0')
+					dst->min_digits++;
+				p++;
+			}
+		}
+
 		dst->negative_red = (strstr (str, ";[Red]") != NULL);
 		dst->negative_paren = (strstr (str, "_);") != NULL);
 
@@ -5400,16 +5401,22 @@ go_format_get_details (GOFormat const *fmt,
 			}
 		}
 
-		dst->thousands_sep = (strstr (str, "#,##0") != NULL);
+		dst->thousands_sep = (comma > str &&
+				      (comma[-1] == '0' || comma[-1] == '#') &&
+				      (comma[1] == '0' || comma[1] == '#') &&
+				      (comma[2] == '0' || comma[2] == '#') &&
+				      (comma[3] == '0' || comma[3] == '#'));
 
 		if (dst->family == GO_FORMAT_SCIENTIFIC) {
 			const char *mend = dot ? dot : strchr (str, 'E');
 			dst->use_markup = (strstr (str, "EE0") != NULL);
 			dst->exponent_step = mend - str;
 			dst->simplify_mantissa = mend != str && mend[-1] == '#';
+			if (dst->simplify_mantissa)
+				dst->min_digits = 0;
 		}			
 
-		if (exact) {
+		if (exact != NULL) {
 			newstr = g_string_new (NULL);
 			go_format_generate_str (newstr, dst);
 		}
@@ -5417,6 +5424,18 @@ go_format_get_details (GOFormat const *fmt,
 		break;
 	}
 
+	case GO_FORMAT_DATE:
+	case GO_FORMAT_TIME: {
+		const char *sdot = strstr (str, "s.");
+
+		if (sdot) {
+			while (sdot[dst->num_decimals + 2] == '0')
+				dst->num_decimals++;
+		}
+
+		break;
+	}
+
 	default:
 		break;
 	}
diff --git a/goffice/utils/go-format.h b/goffice/utils/go-format.h
index 12c985d..ecce13c 100644
--- a/goffice/utils/go-format.h
+++ b/goffice/utils/go-format.h
@@ -81,9 +81,10 @@ typedef struct {
 	GOFormatMagic magic;
 
 	/* NUMBER, SCIENTIFIC, CURRENCY, ACCOUNTING, PERCENTAGE: */
+	int min_digits;
 	int num_decimals;
 
-	/* NUMBER, CURRENCY, PERCENTAGE: */
+	/* NUMBER, CURRENCY, ACCOUNTING, PERCENTAGE: */
 	gboolean thousands_sep;
 
 	/* NUMBER, CURRENCY, ACCOUNTING, PERCENTAGE: */
@@ -140,27 +141,15 @@ GOFormat *go_format_default_money	(void);
 GOFormat *go_format_default_accounting  (void);
 
 void      go_format_generate_number_str (GString *dst,
+					 int min_digits,
 					 int num_decimals,
 					 gboolean thousands_sep,
 					 gboolean negative_red,
 					 gboolean negative_paren,
 					 const char *prefix,
 					 const char *postfix);
-void  go_format_generate_scientific_str (GString *dst,
-					 int num_decimals,
-					 int exponent_step,
-					 gboolean use_markup,
-					 gboolean simplify_mantissa);
-void  go_format_generate_accounting_str (GString *dst,
-					 int num_decimals,
-					 GOFormatCurrency const *currency);
-void  go_format_generate_currency_str   (GString *dst,
-					 int num_decimals,
-					 gboolean thousands_sep,
-					 gboolean negative_red,
-					 gboolean negative_paren,
-					 GOFormatCurrency const *currency,
-					 gboolean force_quoted);
+void  go_format_details_init            (GOFormatDetails *details,
+					 GOFormatFamily family);
 void  go_format_generate_str            (GString *dst,
 					 GOFormatDetails const *details);
 



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