[goffice] Support SI prefixes in scientific format selector. [#588516]



commit ee970758904099ba7c0a7701ed51656683100ee2
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date:   Thu Sep 1 00:07:40 2011 -0600

    Support SI prefixes in scientific format selector. [#588516]
    
    2011-09-01  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* goffice/gtk/go-format-sel.c (cb_si_toggle): new
    	(fmt_dialog_enable_widgets): handle si_button
    	(format_entry_set_text): check for null text
    	(nfs_init): connect cb_si_toggle
    	* goffice/gtk/go-format-sel.ui: add si_button
    	* goffice/utils/go-format.h: move defs here from the .c file
    	* goffice/utils/go-format.c: move defs to .h file
    	(go_format_token2): split E token into separate tokens
    	(go_format_preparse): handle new tokens
    	(go_format_parse_number_new_1): new ' scale
    	(go_format_parse_number_E): support SI prefixes
    	(si_reduction): new
    	(go_format_execute): support SI prefixes
    	(go_format_generate_scientific_str): appens SI marker
    	(go_format_get_details): store SI info

 ChangeLog                    |   18 ++++
 NEWS                         |    1 +
 goffice/gtk/go-format-sel.c  |   40 +++++++-
 goffice/gtk/go-format-sel.ui |   36 +++++++
 goffice/utils/go-format.c    |  230 +++++++++++++++++++++++++++++++++++------
 goffice/utils/go-format.h    |    8 ++
 6 files changed, 297 insertions(+), 36 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8a25ce4..c7b573f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-09-01  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* goffice/gtk/go-format-sel.c (cb_si_toggle): new
+	(fmt_dialog_enable_widgets): handle si_button
+	(format_entry_set_text): check for null text
+	(nfs_init): connect cb_si_toggle
+	* goffice/gtk/go-format-sel.ui: add si_button
+	* goffice/utils/go-format.h: move defs here from the .c file
+	* goffice/utils/go-format.c: move defs to .h file
+	(go_format_token2): split E token into separate tokens
+	(go_format_preparse): handle new tokens
+	(go_format_parse_number_new_1): new ' scale
+	(go_format_parse_number_E): support SI prefixes
+	(si_reduction): new
+	(go_format_execute): support SI prefixes
+	(go_format_generate_scientific_str): appens SI marker
+	(go_format_get_details): store SI info
+
 2011-08-31  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/graph/gog-renderer.c (gog_renderer_draw_data_label): center
diff --git a/NEWS b/NEWS
index 6b2f108..f6180d1 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Andreas:
 	* Extend encoding specification from file-openers to plugin services.
 	* Improve the scientific number formats selector. [#657187][#623847]
 	* Improve fraction format selector. [#117215]
+	* Support SI prefixes in scientific format selector. [#588516]
 
 Jean:
 	* Port to gtk+-3.0.
diff --git a/goffice/gtk/go-format-sel.c b/goffice/gtk/go-format-sel.c
index 8648587..7945848 100644
--- a/goffice/gtk/go-format-sel.c
+++ b/goffice/gtk/go-format-sel.c
@@ -93,6 +93,7 @@ typedef enum {
 	F_LIST_LABEL,		F_LIST_SCROLL,		F_LIST,
 	F_DECIMAL_SPIN,		F_ENGINEERING_BUTTON,
 	F_SUPERSCRIPT_BUTTON,	F_SUPERSCRIPT_HIDE_1_BUTTON,
+	F_SI_BUTTON,
 	F_EXP_DIGITS,           F_EXP_DIGITS_LABEL,
 	F_NEGATIVE_LABEL,	F_NEGATIVE_SCROLL,	F_NEGATIVE,
 	F_DECIMAL_LABEL,	F_CODE_LABEL,
@@ -384,6 +385,15 @@ cb_engineering_toggle (GtkWidget *w, GOFormatSel *gfs)
 }
 
 static void
+cb_si_toggle (GtkWidget *w, GOFormatSel *gfs)
+{
+	gfs->format.details.append_SI =
+		gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+
+	draw_format_preview (gfs, TRUE);
+}
+
+static void
 cb_superscript_toggle (GtkWidget *w, GOFormatSel *gfs)
 {
 	gfs->format.details.use_markup =
@@ -589,8 +599,10 @@ fmt_dialog_enable_widgets (GOFormatSel *gfs, int page)
 			F_FRACTION_MIN_DENOM_DIGITS_LABEL,
 			F_FRACTION_MAX_DENOM_DIGITS,
 			F_FRACTION_MIN_DENOM_DIGITS,
+#ifdef ALLOW_PI_SLASH
 			F_FRACTION_PI_SCALE,
 			F_BASE_SEPARATOR,
+#endif
 			F_MAX_WIDGET
 		},
 		/* Scientific */
@@ -603,6 +615,9 @@ fmt_dialog_enable_widgets (GOFormatSel *gfs, int page)
 			F_SUPERSCRIPT_HIDE_1_BUTTON,
 			F_EXP_DIGITS,
 			F_EXP_DIGITS_LABEL,
+#ifdef ALLOW_SI_APPEND
+			F_SI_BUTTON,
+#endif
 			F_MAX_WIDGET
 		},
 		/* Text */
@@ -736,20 +751,24 @@ stays:
 			break;
 
 		case F_SUPERSCRIPT_BUTTON:
+#ifdef ALLOW_EE_MARKUP
 			if (gfs->show_format_with_markup) {
 				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w),
 							      gfs->format.details.use_markup);
 			} else
+#endif
 				show_widget = FALSE;
 			break;
 
 		case F_SUPERSCRIPT_HIDE_1_BUTTON:
+#ifdef ALLOW_EE_MARKUP
 			if (gfs->show_format_with_markup) {
 
 				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w),
 							      gfs->format.details.simplify_mantissa);
 				gtk_widget_set_sensitive (w, gfs->format.details.use_markup);
 			} else
+#endif
 				show_widget = FALSE;
 			break;
 
@@ -767,6 +786,16 @@ stays:
 			}
 			break;
 
+		case F_SI_BUTTON:
+			gtk_toggle_button_set_active 
+#ifdef ALLOW_SI_APPEND
+				(GTK_TOGGLE_BUTTON (w),
+				 gfs->format.details.append_SI);
+#else
+				(GTK_TOGGLE_BUTTON (w), FALSE);
+#endif
+			break;
+
 		case F_ENGINEERING_BUTTON:
 			gtk_toggle_button_set_active
 				(GTK_TOGGLE_BUTTON (w),
@@ -836,9 +865,13 @@ stays:
 			break;
 
 		case F_FRACTION_PI_SCALE:
-			gtk_toggle_button_set_active 
+			gtk_toggle_button_set_active
+#ifdef ALLOW_PI_SLASH
 				(GTK_TOGGLE_BUTTON (w),
 				 gfs->format.details.pi_scale);
+#else
+				(GTK_TOGGLE_BUTTON (w), FALSE);			
+#endif
 			break;
 
 		default:
@@ -925,7 +958,7 @@ format_entry_set_text (GOFormatSel *gfs, const gchar *text)
 	GtkEntry *entry = GTK_ENTRY (gfs->format.widget[F_ENTRY]);
 
 	g_signal_handler_block (entry, gfs->format.entry_changed_id);
-	gtk_entry_set_text (entry, text);
+	gtk_entry_set_text (entry, text ? text : "");
 	g_signal_handler_unblock (entry, gfs->format.entry_changed_id);
 	cb_format_entry_changed (GTK_EDITABLE (entry), gfs);
 }
@@ -1142,6 +1175,7 @@ nfs_init (GOFormatSel *gfs)
 		"format_engineering_button",
 		"format_superscript_button",
 		"format_superscript_hide_1_button",
+		"format_si_button",
 		"format_exp_digits",
 		"format_exp_digits_label",
 		"format_negatives_label",
@@ -1289,6 +1323,8 @@ nfs_init (GOFormatSel *gfs)
 		G_CALLBACK (cb_engineering_toggle), gfs);
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_SUPERSCRIPT_BUTTON]), "toggled",
 		G_CALLBACK (cb_superscript_toggle), gfs);
+	g_signal_connect (G_OBJECT (gfs->format.widget[F_SI_BUTTON]), "toggled",
+		G_CALLBACK (cb_si_toggle), gfs);
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_SUPERSCRIPT_HIDE_1_BUTTON]), 
 			  "toggled", G_CALLBACK (cb_superscript_hide_1_toggle), gfs);
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_FRACTION_AUTOMATIC]), 
diff --git a/goffice/gtk/go-format-sel.ui b/goffice/gtk/go-format-sel.ui
index c05295a..bbefa65 100644
--- a/goffice/gtk/go-format-sel.ui
+++ b/goffice/gtk/go-format-sel.ui
@@ -847,6 +847,7 @@
                 <property name="tooltip_text" translatable="yes">Restrict exponent to multiples of 3</property>
                 <property name="use_action_appearance">False</property>
                 <property name="use_underline">True</property>
+                <property name="xalign">0</property>
                 <property name="draw_indicator">True</property>
               </object>
               <packing>
@@ -869,6 +870,7 @@
                     <property name="tooltip_text" translatable="yes">Use superscript for exponent (e.g. 4Ã10Â)</property>
                     <property name="use_action_appearance">False</property>
                     <property name="use_underline">True</property>
+                    <property name="xalign">0</property>
                     <property name="draw_indicator">True</property>
                   </object>
                   <packing>
@@ -891,6 +893,7 @@
                         <property name="tooltip_text" translatable="yes">When mantissa is equal to 1, only show exponent part (e.g. 10Â)</property>
                         <property name="use_action_appearance">False</property>
                         <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
                         <property name="draw_indicator">True</property>
                       </object>
                     </child>
@@ -901,6 +904,39 @@
                     <property name="position">1</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkBox" id="box1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkCheckButton" id="format_si_button">
+                        <property name="label" translatable="yes">Append SI prefix</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="has_tooltip">True</property>
+                        <property name="tooltip_text" translatable="yes">Append an SI prefix (e.g. instead of 4Ã10â show 4M)</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="expand">False</property>
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index c3ebede..5f4ec70 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -53,11 +53,11 @@
 
 #define OBSERVE_XL_CONDITION_LIMITS
 #define OBSERVE_XL_EXPONENT_1
-#define ALLOW_EE_MARKUP
-#define ALLOW_PI_SLASH
 #define ALLOW_NEGATIVE_TIMES
 #define MAX_DECIMALS 100
 
+/* Note that the header file contains ALLOW_EE_MARKUP ALLOW_SI_APPEND ALLOW_PI_SLASH */
+
 /* ------------------------------------------------------------------------- */
 
 #ifndef DOUBLE
@@ -180,10 +180,16 @@ typedef enum {
 #ifdef ALLOW_EE_MARKUP
 	OP_NUM_MARK_MANTISSA,
 	OP_NUM_SIMPLIFY_MANTISSA,
-	OP_NUM_SIMPLIFY_EXPONENT,
+	OP_NUM_SIMPLIFY_MARKUP_MANTISSA,
 	OP_MARKUP_SUPERSCRIPT_START,
 	OP_MARKUP_SUPERSCRIPT_END,
 #endif
+#ifdef ALLOW_SI_APPEND
+	OP_NUM_REDUCE_EXPONENT_SI,
+	OP_NUM_SIMPLIFY_EXPONENT_SI,
+	OP_NUM_SI_EXPONENT,
+#endif
+
 	OP_NUM_FRACTION,	/* wholep explicitp (digits|denominator) */
 	OP_NUM_FRACTION_WHOLE,
 	OP_NUM_FRACTION_NOMINATOR,
@@ -232,6 +238,17 @@ typedef enum {
 	TOK_DECIMAL,            /* Decimal sep  */
 	TOK_THOUSAND,           /* Thousand sep */
 
+	TOK_EXP,                /* E */
+#ifdef ALLOW_EE_MARKUP
+	TOK_EXP_MU,             /* EE */
+#endif
+#ifdef ALLOW_SI_APPEND
+	TOK_EXP_SI,             /* ESI */
+#endif
+#if defined(ALLOW_EE_MARKUP) && defined(ALLOW_SI_APPEND)
+	TOK_EXP_MU_SI,          /* EESI */
+#endif
+
 	TOK_ERROR
 } GOFormatToken;
 
@@ -302,6 +319,7 @@ struct _GOFormat {
 			guchar *program;
 			unsigned int E_format    : 1;
 			unsigned int use_markup  : 1;
+			unsigned int use_SI      : 1;
 			unsigned int has_date    : 1;
 			unsigned int date_ybm    : 1;  /* year, then month.  */
 			unsigned int date_mbd    : 1;  /* month, then day.  */
@@ -876,8 +894,30 @@ go_format_token2 (char const **pstr, GOFormatTokenType *ptt, gboolean localized)
 	case '#':
 	case '?':
 	case '%':
+		tt = TT_ALLOWED_IN_NUMBER | TT_STARTS_NUMBER;
+		break;
+
 	case 'E':
 		tt = TT_ALLOWED_IN_NUMBER | TT_STARTS_NUMBER;
+#ifdef ALLOW_SI_APPEND
+		if (str[1] == 'S' && str[2] == 'I') {
+			t = TOK_EXP_SI,
+			len = 3;
+		} else 
+#endif
+#if defined(ALLOW_EE_MARKUP) && defined(ALLOW_SI_APPEND)
+		if (str[1] == 'E' && str[2] == 'S' && str[3] == 'I') {
+			t = TOK_EXP_MU_SI;
+			len = 4;
+		} else 
+#endif
+#ifdef ALLOW_EE_MARKUP
+	        if (str[1] == 'E') {
+			t = TOK_EXP_MU;
+			len = 2;
+		} else
+#endif
+			t = TOK_EXP;
 		break;
 
 	case '@':
@@ -1064,15 +1104,19 @@ go_format_preparse (const char *str, GOFormatParseState *pstate,
 			ntokens++;
 			break;
 
-		case 'E':
-			ntokens++;
-			if (pstate->tno_E >= 0) {
+		case TOK_EXP:
 #ifdef ALLOW_EE_MARKUP
-				if (pstate->tno_E == tno - 1)
-					break;
+		case TOK_EXP_MU:
+#endif
+#ifdef ALLOW_SI_APPEND
+		case TOK_EXP_SI:
 #endif
+#if defined(ALLOW_EE_MARKUP) && defined(ALLOW_SI_APPEND)
+		case TOK_EXP_MU_SI:
+#endif
+			ntokens++;
+			if (pstate->tno_E >= 0)
 				goto error;
-			}
 			pstate->tno_E = tno;
 			break;
 
@@ -1579,8 +1623,13 @@ go_format_parse_number_new_1 (GString *prg, GOFormatParseState *pstate,
 			break;
 
 		case '%':
-			if (E_part != 2)
-				scale += 2;
+			if (E_part != 1 && E_part != 2)
+ 				scale += 2;
+ 			break;
+ 
+		case '\'':
+			if (E_part == 1)
+				scale += 3;
 			break;
 
 		case TOK_THOUSAND:
@@ -1605,7 +1654,8 @@ go_format_parse_number_new_1 (GString *prg, GOFormatParseState *pstate,
 	if (E_part == 1) {
 		if (tno_numstart == -1)
 			goto error;
-
+		if (scale)
+			ADD_OP2 (OP_NUM_SCALE, scale);
 		ADD_OP3 (OP_NUM_PRINTF_E, decimals, whole_digits);
 #ifdef OBSERVE_XL_EXPONENT_1
 		if (whole_digits + decimals == 0) {
@@ -1617,7 +1667,7 @@ go_format_parse_number_new_1 (GString *prg, GOFormatParseState *pstate,
 		}
 #endif
 	} else {
-		if (scale && !frac_part)
+		if (scale && !frac_part && E_part != 2)
 			ADD_OP2 (OP_NUM_SCALE, scale);
 		ADD_OP2 (OP_NUM_PRINTF_F, decimals);
 		if (thousands && !inhibit_thousands)
@@ -1668,6 +1718,10 @@ go_format_parse_number_new_1 (GString *prg, GOFormatParseState *pstate,
 			if (frac_part == 3)
 				ADD_OP2 (OP_CHAR, ',');
 			break;
+		case '\'':
+			if (E_part == 1)
+				break;
+			/* Fall through */
 		default:
 			handle_common_token (ti->tstr, ti->token, prg);
 		}
@@ -1690,6 +1744,10 @@ go_format_parse_number_new_1 (GString *prg, GOFormatParseState *pstate,
 				break;
 			case TOK_THOUSAND:
 				break;
+			case '\'':
+				if (E_part == 1)
+					break;
+				/* Fall through */
 			default:
 				handle_common_token (ti->tstr, ti->token, prg);
 			}
@@ -1732,29 +1790,39 @@ go_format_parse_number_E (GOFormatParseState *pstate)
 {
 	GOFormat *fmt;
 	GString *prg;
-	gboolean use_markup;
+	gboolean use_markup = FALSE;
+	gboolean append_SI = FALSE;
+	gboolean simplify_mantissa = TRUE;
 	int tno_end = pstate->tokens->len;
 	int tno_exp_start = pstate->tno_E + 2;
-	gboolean simplify_mantissa;
 
 	if (tno_exp_start >= tno_end)
 		return NULL;
-	switch (GET_TOKEN (pstate->tno_E + 1).token) {
-	case '-':
-		use_markup = FALSE;
-		simplify_mantissa = FALSE;
-		pstate->forced_exponent_sign = FALSE;
+
+	switch (GET_TOKEN (pstate->tno_E).token) {
+#ifdef ALLOW_SI_APPEND
+	case TOK_EXP_SI:
+		append_SI = TRUE;
 		break;
-	case '+':
-		use_markup = FALSE;
-		simplify_mantissa = FALSE;
-		pstate->forced_exponent_sign = TRUE;
+#endif
+#if defined(ALLOW_EE_MARKUP) && defined(ALLOW_SI_APPEND)
+	case TOK_EXP_MU_SI:
+		append_SI = TRUE;
+		use_markup = TRUE;
 		break;
+#endif
 #ifdef ALLOW_EE_MARKUP
-	case 'E': {
-		int i;
-
+	case TOK_EXP_MU:
 		use_markup = TRUE;
+		break;
+#endif
+	case TOK_EXP:
+	default:
+		break;
+	}
+
+	if (use_markup) {
+		int i;
 		pstate->forced_exponent_sign =
 			(GET_TOKEN (tno_exp_start).token == '+');
 		if (pstate->forced_exponent_sign)
@@ -1769,12 +1837,18 @@ go_format_parse_number_E (GOFormatParseState *pstate)
 				break;
 			}
 		}
+	} else
+		simplify_mantissa = FALSE;
 
+	switch (GET_TOKEN (pstate->tno_E + 1).token) {
+	case '-':
+		pstate->forced_exponent_sign = FALSE;
+		break;
+	case '+':
+		pstate->forced_exponent_sign = TRUE;
 		break;
-	}
-#endif
 	default:
-		return NULL;
+		break;
 	}
 
 	prg = g_string_new (NULL);
@@ -1784,6 +1858,10 @@ go_format_parse_number_E (GOFormatParseState *pstate)
 					   1, 0, NULL))
 		return NULL;
 
+#ifdef ALLOW_SI_APPEND
+	if (append_SI)
+		ADD_OP (OP_NUM_REDUCE_EXPONENT_SI);
+#endif
 	ADD_OP (OP_NUM_VAL_EXPONENT);
 #ifdef ALLOW_EE_MARKUP
 	if (use_markup) {
@@ -1805,10 +1883,16 @@ go_format_parse_number_E (GOFormatParseState *pstate)
 #ifdef ALLOW_EE_MARKUP
 	if (use_markup) {
 		if (simplify_mantissa)
-			ADD_OP (OP_NUM_SIMPLIFY_EXPONENT);
+			ADD_OP (OP_NUM_SIMPLIFY_MARKUP_MANTISSA);
 		ADD_OP  (OP_MARKUP_SUPERSCRIPT_END);
 	}
 #endif
+#ifdef ALLOW_SI_APPEND
+	if (append_SI) {
+		ADD_OP  (OP_NUM_SIMPLIFY_EXPONENT_SI);
+		ADD_OP  (OP_NUM_SI_EXPONENT);
+	}
+#endif
 
 	handle_fill (prg, pstate);
 
@@ -1816,6 +1900,7 @@ go_format_parse_number_E (GOFormatParseState *pstate)
 	fmt->u.number.program = g_string_free (prg, FALSE);
 	fmt->u.number.E_format = TRUE;
 	fmt->u.number.use_markup = use_markup;
+	fmt->u.number.use_SI = append_SI;
 	fmt->u.number.scale_is_2 = (pstate->scale == 2);
 	return fmt;
 }
@@ -2362,10 +2447,15 @@ go_format_dump_program (const guchar *prg)
 #ifdef ALLOW_EE_MARKUP
 		REGULAR(OP_NUM_MARK_MANTISSA);
 		REGULAR(OP_NUM_SIMPLIFY_MANTISSA);
-		REGULAR(OP_NUM_SIMPLIFY_EXPONENT);
+		REGULAR(OP_NUM_SIMPLIFY_MARKUP_MANTISSA);
 		REGULAR(OP_MARKUP_SUPERSCRIPT_START);
 		REGULAR(OP_MARKUP_SUPERSCRIPT_END);
 #endif
+#ifdef ALLOW_SI_APPEND
+		REGULAR(OP_NUM_REDUCE_EXPONENT_SI);
+		REGULAR(OP_NUM_SIMPLIFY_EXPONENT_SI);
+		REGULAR(OP_NUM_SI_EXPONENT);
+#endif
 		REGULAR(OP_NUM_FRACTION_WHOLE);
 		REGULAR(OP_NUM_FRACTION_NOMINATOR);
 		REGULAR(OP_NUM_FRACTION_DENOMINATOR);
@@ -2624,6 +2714,48 @@ cnt_digits (int d)
 }
 #endif
 
+#if defined(ALLOW_SI_APPEND) && defined (DEFINE_COMMON)
+static int
+si_reduction (int exponent, char const **si)
+{
+	static struct {
+		char const *prefix;
+		int power;
+	} si_prefixes[] = {
+		{"Y" , 24},
+		{"Z" , 21},
+		{"E" , 18},
+		{"P" , 15},
+		{"T" , 12},
+		{"G" ,  9},
+		{"M" ,  6},
+		{"k" ,  3},
+		{"h" ,  2},
+		{"da" , 1},
+		{"" ,  0},
+		{"d" , -1},
+		{"c" , -2},
+		{"m" , -3},
+		{"\302\265" , -6},
+		{"n" , -9},
+		{"p" ,-12},
+		{"f" ,-15},
+		{"a" ,-18},
+		{"z" ,-21},
+		{"y" ,-24}
+	};
+	guint i;
+	
+	for (i = 0; i < G_N_ELEMENTS (si_prefixes); i++)
+		if (si_prefixes[i].power <= exponent)
+			break;
+	
+	*si = si_prefixes[i].prefix;
+	return si_prefixes[i].power;
+}
+
+#endif
+
 
 
 #define INSERT_MINUS(pos) do {							\
@@ -2664,6 +2796,10 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
 	gboolean thousands = FALSE;
 	gboolean digit_count = 0;
 	int exponent = 0;
+#ifdef ALLOW_SI_APPEND
+	char const *si_str = NULL;
+	int si_pos = 0;
+#endif
 	struct {
 		DOUBLE w, n, d, val;
 		int digits;
@@ -3257,7 +3393,7 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
 				g_string_truncate (dst, mantissa_start);
 			break;
 
-		case OP_NUM_SIMPLIFY_EXPONENT:
+		case OP_NUM_SIMPLIFY_MARKUP_MANTISSA:
 			if (special_mantissa == 0) {
 				g_string_truncate (dst, mantissa_start);
 				g_string_append_c (dst, '0');
@@ -3291,6 +3427,28 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
 			}
 			break;
 #endif
+#ifdef ALLOW_SI_APPEND
+		case OP_NUM_REDUCE_EXPONENT_SI:
+			exponent -= si_reduction (exponent, &si_str);
+			si_pos = dst->len;
+			break;
+
+		case OP_NUM_SIMPLIFY_EXPONENT_SI:
+			if (exponent == 0 && si_pos > 0) {
+				int len = dst->len - si_pos;
+				if (attrs)
+					go_pango_attr_list_erase (attrs, si_pos, len);
+				g_string_erase (dst, si_pos, len);
+			}
+			break;
+
+		case OP_NUM_SI_EXPONENT:
+			g_string_append_c (dst, ' ');
+			if (si_str != NULL)
+				g_string_append (dst, si_str);
+			si_pos = 0;
+			break;
+#endif
 
 		case OP_NUM_FRACTION: {
 			gboolean wp = *prg++;
@@ -5456,10 +5614,13 @@ go_format_generate_scientific_str (GString *dst, GOFormatDetails const *details)
 
 	if (details->use_markup)
 		g_string_append_c (dst, 'E');
+	g_string_append_c (dst, 'E');
+	if (details->append_SI)
+		g_string_append_len (dst, "SI", 2);
 
 	/* Maximum not terribly important. */
 	digits = CLAMP (details->exponent_digits, 1, 10);
-	g_string_append (dst, "E+");
+	g_string_append_c (dst, '+');
 	go_string_append_c_n (dst, '0', digits);
 	
 }
@@ -5881,6 +6042,7 @@ go_format_get_details (GOFormat const *fmt,
 		if (dst->family == GO_FORMAT_SCIENTIFIC) {
 			const char *epos = strchr (str, 'E');
 			const char *mend = dot ? dot : epos;
+			dst->append_SI = (strstr (str, "ESI") != NULL);
 			dst->use_markup = (strstr (str, "EE") != NULL);
 			dst->exponent_step = mend - str;
 			dst->simplify_mantissa = mend != str && mend[-1] == '#';
diff --git a/goffice/utils/go-format.h b/goffice/utils/go-format.h
index 135ff1d..ca6c9e0 100644
--- a/goffice/utils/go-format.h
+++ b/goffice/utils/go-format.h
@@ -95,6 +95,7 @@ typedef struct {
 	int exponent_digits;
 	gboolean use_markup;
 	gboolean simplify_mantissa;
+	gboolean append_SI;
 
 	/* FRACTION: */
 	gboolean automatic_denominator;
@@ -110,6 +111,13 @@ typedef struct {
 
 /*************************************************************************/
 
+/* We need these in the format selector */
+#define ALLOW_EE_MARKUP
+#define ALLOW_SI_APPEND
+#define ALLOW_PI_SLASH
+
+/*************************************************************************/
+
 typedef int (*GOFormatMeasure) (const GString *str, PangoLayout *layout);
 int go_format_measure_zero (const GString *str, PangoLayout *layout);
 int go_format_measure_pango (const GString *str, PangoLayout *layout);



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