[goffice] Rewrite go_format_output_date_to_odf to leave the style program alone



commit b20e2033b4214d20cd45e548db80b1239d795776
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Sun May 31 00:06:14 2009 -0600

    Rewrite go_format_output_date_to_odf to leave the style program alone
    
    2009-05-31  Andreas J. Guelzow  <aguelzow pyrshep ca>
    
    	* goffice/utils/go-format.c (fill_accumulator): delete
    	(go_format_output_date_to_odf): rewrite without reference to the
    	  style program
---
 ChangeLog                 |    8 +-
 goffice/utils/go-format.c |  407 +++++++++++++++++++++++++++------------------
 2 files changed, 253 insertions(+), 162 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 29669db..1dd5562 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-05-31  Andreas J. Guelzow  <aguelzow pyrshep ca>
+
+	* goffice/utils/go-format.c (fill_accumulator): delete
+	(go_format_output_date_to_odf): rewrite without reference to the 
+	  style program
+
 2009-05-30  Andreas J. Guelzow  <aguelzow pyrshep ca>
 
 	* goffice/utils/go-format.h: use a descriptive name for arguments
@@ -6,7 +12,7 @@
 	(go_format_output_date_to_odf): fix typo
 	(go_format_output_number_to_odf): handle conditional format
 	(go_format_output_currency_to_odf): ditto
-	(-go_format_output_to_odf): ditto
+	(go_format_output_to_odf): ditto
 
 2009-05-30  Morten Welinder  <terra gnome org>
 
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index 387588e..cc7b10b 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -5453,237 +5453,322 @@ go_format_odf_style_map (GOFormat const *fmt, int cond_part)
 
 #ifdef DEFINE_COMMON
 
-static const guchar *
-fill_accumulator (GString *accum, const guchar *prg)
-{
-	g_string_erase (accum, 0, -1);
-
-	while (1) {
-		switch (*prg) {
-		case OP_CHAR: {
-			const guchar *next;
-			prg++;
-			next = g_utf8_next_char (prg);
-			g_string_append_len (accum, prg, next - prg);
-			prg = next;
-			break;
-		}
-		case OP_STRING: {
-			size_t len;
-			prg++;
-			len = strlen (prg);
-			g_string_append (accum, prg);
-			prg += len + 1;
-			break;
-		}
-		default:
-			return prg;
-		}
-	}
-}
+#define ODF_CLOSE_STRING  if (string_is_open) {  \
+                                 gsf_xml_out_add_cstr (xout, NULL, accum->str); \
+                                 gsf_xml_out_end_element (xout); /* </number:text> */  \
+				 string_is_open = FALSE; \
+                          }
+#define ODF_OPEN_STRING   if (!string_is_open) { \
+	                         gsf_xml_out_start_element (xout, NUMBER "text");\
+                                 string_is_open = TRUE; \
+				 g_string_erase (accum, 0, -1); \
+				 }
 
 static void
 go_format_output_date_to_odf (GsfXMLOut *xout, GOFormat const *fmt, char const *name, GOFormatDetails *dst)
 {
-	const guchar *prg = fmt->u.number.program;
+	char const *xl = go_format_as_XL (fmt);
 	GString *accum = g_string_new (NULL);
 	gboolean time_only = (dst->family == GO_FORMAT_TIME);
+	gboolean seen_year = FALSE;
+	gboolean seen_month = FALSE;
+	gboolean seen_day = FALSE;
+	gboolean seen_weekday = FALSE;
+	gboolean seen_time = FALSE;
+	gboolean seen_hour = FALSE;
+	gboolean seen_ampm = FALSE;
+	gboolean seen_minute = FALSE;
+	gboolean seen_second = FALSE;
+	gboolean seen_elapsed = FALSE;
+	gboolean m_is_minutes = FALSE;
+	gboolean string_is_open = FALSE;
+	gboolean seconds_trigger_minutes = TRUE;
 
 	gsf_xml_out_start_element (xout,  time_only ? 
 				   NUMBER "time-style" : NUMBER "date-style");
 	gsf_xml_out_add_cstr (xout, STYLE "name", name);
 	gsf_xml_out_add_cstr (xout, NUMBER "format-source", "fixed");
-	
+	gsf_xml_out_add_cstr (xout, "gnm:format", xl);
+
 	while (1) {
-		GOFormatOp op = *prg++;
+		const char *token = xl;
+		GOFormatTokenType tt;
+		int t = go_format_token (&xl, &tt);
 
-		switch (op) {
-		case OP_END:
+		switch (t) {
+		case 0: case ';':
+			ODF_CLOSE_STRING;
 			gsf_xml_out_end_element (xout); /* </number:date-style or time-style> */
 			g_string_free (accum, TRUE);
 			return;
 
-		case OP_STRING:
-		case OP_CHAR:
-			prg = fill_accumulator (accum, prg - 1);
-			gsf_xml_out_simple_element (xout, NUMBER "text", accum->str);
-			break;
-
-		case OP_CHAR_INVISIBLE:
-		case OP_FILL:
-			prg = g_utf8_next_char (prg);
-			break;
-
-		case OP_LOCALE: {
-			prg += sizeof (GOFormatLocale);
-			prg += strlen ((const char *)prg) + 1;
+		case 'd': case 'D': {
+			int n = 1;
+			while (*xl == 'd' || *xl == 'D')
+				xl++, n++;
+			if (time_only) break; 
+			switch (n) {
+			case 1: 
+			case 2: if (seen_day) break;
+				seen_day = TRUE;
+				ODF_CLOSE_STRING;
+				gsf_xml_out_start_element (xout, NUMBER "day");
+				gsf_xml_out_add_cstr (xout, NUMBER "style", 
+						      (n==1) ? "short" : "long");
+				gsf_xml_out_end_element (xout); /* </number:day> */
+				break;
+			case 3: 
+			default: if (seen_weekday) break;
+				seen_weekday = TRUE;
+				ODF_CLOSE_STRING;
+				gsf_xml_out_start_element (xout, NUMBER "day-of-week");
+				gsf_xml_out_add_cstr (xout, NUMBER "style", 
+						      (n==3) ? "short" : "long");
+				gsf_xml_out_end_element (xout); /* </number:day-of-week> */
+				break;
+			}
 			break;
 		}
 
-		case OP_DATE_ROUND:
-			prg += 2;
-			break;
-
-		case OP_DATE_YEAR:
-			if (time_only) break;
+		case 'y': case 'Y': {
+			int n = 1;
+			while (*xl == 'y' || *xl == 'Y')
+				xl++, n++;
+			if (time_only || seen_year) break; 
+			seen_year = TRUE;
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "year");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
+			gsf_xml_out_add_cstr (xout, NUMBER "style", 
+					      (n <= 2) ? "short" : "long");
 			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "gregorian");
 			gsf_xml_out_end_element (xout); /* </number:year> */
 			break;
+		}
 
-		case OP_DATE_YEAR_2:
-			if (time_only) break;
+		case 'b': case 'B': {
+			int n = 1;
+			while (*xl == 'b' || *xl == 'B')
+				xl++, n++;
+			if (time_only || seen_year) break; 
+			seen_year = TRUE;
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "year");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "gregorian");
+			gsf_xml_out_add_cstr (xout, NUMBER "style", 
+					      (n <= 2) ? "short" : "long");
+			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "buddhist");
 			gsf_xml_out_end_element (xout); /* </number:year> */
 			break;
+		}
 
-		case OP_DATE_YEAR_THAI:
-			if (time_only) break;
+		case 'e': {  /* What is 'e' really? */
+			while (*xl == 'e') xl++;
+			if (time_only || seen_year) break; 
+			seen_year = TRUE;
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "year");
 			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "buddhist");
+			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "gregorian");
 			gsf_xml_out_end_element (xout); /* </number:year> */
 			break;
-
-		case OP_DATE_YEAR_THAI_2:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "year");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_add_cstr (xout, NUMBER "calendar", "buddhist");
-			gsf_xml_out_end_element (xout); /* </number:year> */
+		}
+			
+		case 'g': case 'G':
+			/* Something with Japanese eras.  Blank for me. */
 			break;
 
-		case OP_DATE_MONTH:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "month");
-			gsf_xml_out_add_cstr (xout, NUMBER "possessive-form", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "textual", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_end_element (xout); /* </number:month> */
+		case 'h': case 'H': {
+			int n = 1;
+			while (*xl == 'h' || *xl == 'H')
+				xl++, n++;
+			if (seen_hour) break;
+			seen_hour = TRUE;
+			ODF_CLOSE_STRING;
+			gsf_xml_out_start_element (xout, NUMBER "hours");
+			gsf_xml_out_add_cstr (xout, NUMBER "style", 
+					      (n == 1) ? "short" : "long");
+			gsf_xml_out_end_element (xout); /* </number:hours> */
+			m_is_minutes = TRUE;
 			break;
+		}
 
-		case OP_DATE_MONTH_2:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "month");
-			gsf_xml_out_add_cstr (xout, NUMBER "possessive-form", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "textual", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:month> */
-			break;
+		case 'm': case 'M': {
+			int n = 1;
+			printf ("see m: %s\n", token);
+			while (*xl == 'm' || *xl == 'M')
+				xl++, n++;
+			m_is_minutes = (n <= 2) && (m_is_minutes || tail_forces_minutes (xl));
 
-		case OP_DATE_MONTH_NAME:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "month");
-			gsf_xml_out_add_cstr (xout, NUMBER "possessive-form", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "textual", "true");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:month> */
-			break;
+			if (m_is_minutes) {
+				if (seen_minute) break;
+				seen_minute = TRUE;
+				m_is_minutes = FALSE;
+				seconds_trigger_minutes = FALSE;
+				ODF_CLOSE_STRING;
+				gsf_xml_out_start_element (xout, NUMBER "minutes");
+				gsf_xml_out_add_cstr (xout, NUMBER "style", 
+						      (n == 1) ? "short" : "long");
+				gsf_xml_out_end_element (xout); /* </number:minutes> */
+			} else {
+				if (seen_month || time_only) break;
+				seen_month = TRUE;
+				ODF_CLOSE_STRING;
+				gsf_xml_out_start_element (xout, NUMBER "month");
+				gsf_xml_out_add_cstr (xout, NUMBER "possessive-form", "false");
+				switch (n) {
+				case 1: 
+					gsf_xml_out_add_cstr (xout, NUMBER "textual", "false");
+					gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
+					break;
+				case 2: 
+					gsf_xml_out_add_cstr (xout, NUMBER "textual", "false");
+					gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
+					break;
+				case 3: /* ODF does not support single letter abbreviation */
+				case 5: 
+					gsf_xml_out_add_cstr (xout, NUMBER "textual", "true");
+					gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
+					break;
+				default: 
+					gsf_xml_out_add_cstr (xout, NUMBER "textual", "true");
+					gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
+					break;
+				}
 
-		case OP_DATE_MONTH_NAME_1:   /* ODF does not support single letter abbreviation */
-		case OP_DATE_MONTH_NAME_3:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "month");
-			gsf_xml_out_add_cstr (xout, NUMBER "possessive-form", "false");
-			gsf_xml_out_add_cstr (xout, NUMBER "textual", "true");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_end_element (xout); /* </number:month> */
+				gsf_xml_out_end_element (xout); /* </number:month> */
+			}
 			break;
+		}
 
-		case OP_DATE_DAY:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "day");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_end_element (xout); /* </number:day> */
+		case 's': case 'S': {
+			int n = 1;
+			while (*xl == 's' || *xl == 'S')
+				xl++, n++;
+			if (seconds_trigger_minutes) {
+				seconds_trigger_minutes = FALSE;
+				m_is_minutes = TRUE;
+			}
+			if (seen_second) break;
+			seen_second = TRUE;
+			ODF_CLOSE_STRING;
+			gsf_xml_out_start_element (xout, NUMBER "seconds");
+			gsf_xml_out_add_cstr (xout, NUMBER "style", 
+					      (n == 1) ? "short" : "long");
+			gsf_xml_out_end_element (xout); /* </number:seconds> */
 			break;
+		}
 
-		case OP_DATE_DAY_2:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "day");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:day> */
+		case TOK_AMPM3:
+		case TOK_AMPM5:
+			if (seen_elapsed || seen_ampm) break;
+			seen_ampm = TRUE;
+			ODF_CLOSE_STRING;
+			gsf_xml_out_simple_element (xout, NUMBER "am-pm", NULL);
 			break;
 
-		case OP_DATE_WEEKDAY:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "day-of-week");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:day-of-week> */
+		case TOK_DECIMAL:
+/* 			if (*xl == '0') { */
+/* 				int n = 0; */
+/* 				seen_time = TRUE; */
+/* 				ADD_OP (OP_TIME_SECOND_DECIMAL_START); */
+/* 				while (*xl == '0') { */
+/* 					xl++, n++; */
+/* 					ADD_OP (OP_TIME_SECOND_DECIMAL_DIGIT); */
+/* 				} */
+/* 				/\* The actual limit is debatable.  This is what XL does.  *\/ */
+/* 				if (n > 3) */
+/* 					goto error; */
+/* 				date_decimals = MAX (date_decimals, n); */
+/* 			} else { */
+/* 				ADD_OP2 (OP_CHAR, '.'); */
+/* 			} */
+			ODF_OPEN_STRING;
+			g_string_append_c (accum, '.');
 			break;
 
-		case OP_DATE_WEEKDAY_3:
-			if (time_only) break;
-			gsf_xml_out_start_element (xout, NUMBER "day-of-week");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_end_element (xout); /* </number:day-of-week> */
+		case '0':
 			break;
 
-		case OP_TIME_HOUR:
+		case TOK_ELAPSED_H:
+			if (seen_elapsed || seen_ampm || seen_hour) break;
+			seen_hour = TRUE;
+			seen_elapsed  = TRUE;
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "hours");
 			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
 			gsf_xml_out_end_element (xout); /* </number:hours> */
+			m_is_minutes = TRUE;
 			break;
 
-		case OP_TIME_HOUR_N: 
-			prg++;
-			/* break;  fall through */
-		case OP_TIME_HOUR_2:
-			gsf_xml_out_start_element (xout, NUMBER "hours");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:hours> */
-			break;
-
-		case OP_TIME_AP:
-			prg++;
-			prg++;
-			/* break;  fall through */
-		case OP_TIME_AMPM:
-			gsf_xml_out_simple_element (xout, NUMBER "am-pm", NULL);
-			break;
-
-		case OP_TIME_MINUTE:
-			gsf_xml_out_start_element (xout, NUMBER "minutes");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
-			gsf_xml_out_end_element (xout); /* </number:minutes> */
-			break;
-
-		case OP_TIME_MINUTE_N:
-			prg++;
-			/* break;  fall through */
-		case OP_TIME_MINUTE_2:
+		case TOK_ELAPSED_M:
+			if (seen_elapsed || seen_ampm || seen_minute) break;
+			seen_minute = TRUE;
+			seen_elapsed  = TRUE;
+			m_is_minutes = FALSE;
+			seconds_trigger_minutes = FALSE;
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "minutes");
 			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
 			gsf_xml_out_end_element (xout); /* </number:minutes> */
-			break;
 
-		case OP_TIME_SECOND:
+		case TOK_ELAPSED_S:
+			if (seen_elapsed || seen_ampm || seen_second) break;
+			seen_time = TRUE;
+			seen_elapsed = TRUE;
+			seen_second = TRUE;
+			if (seconds_trigger_minutes) {
+				m_is_minutes = TRUE;
+				seconds_trigger_minutes = FALSE;
+			}
+			ODF_CLOSE_STRING;
 			gsf_xml_out_start_element (xout, NUMBER "seconds");
 			gsf_xml_out_add_cstr (xout, NUMBER "style", "short");
 			gsf_xml_out_end_element (xout); /* </number:seconds> */
 			break;
 
-		case OP_TIME_SECOND_N:
-			prg++;
-		case OP_TIME_SECOND_2:
-			gsf_xml_out_start_element (xout, NUMBER "seconds");
-			gsf_xml_out_add_cstr (xout, NUMBER "style", "long");
-			gsf_xml_out_end_element (xout); /* </number:seconds> */
+		case TOK_STRING: {
+			size_t len = strchr (token + 1, '"') - (token + 1);
+			if (len > 0) {
+				ODF_OPEN_STRING;
+				g_string_append_len (accum, token + 1, len);
+			}
 			break;
+		}
+			
+		case TOK_CHAR: {
+			size_t len = g_utf8_next_char(token) - (token);
+			if (len > 0) {
+				ODF_OPEN_STRING;
+				g_string_append_len (accum, token, len);
+			}
+			break;
+		}
 
-		case OP_TIME_SECOND_DECIMAL_START:
-			/* Reset to start of decimal string.  */
-/* 			date_dec_ptr = fsecond; */
-/* 			go_string_append_gstring (dst, decimal); */
+		case TOK_ESCAPED_CHAR: {
+			size_t len = g_utf8_next_char(token + 1) - (token + 1);
+			if (len > 0) {
+				ODF_OPEN_STRING;
+				g_string_append_len (accum, token + 1, len);
+			}
 			break;
+		}
 
-		case OP_TIME_SECOND_DECIMAL_DIGIT:
-/* 			g_string_append_c (dst, *date_dec_ptr++); */
+		case TOK_THOUSAND:
+			ODF_OPEN_STRING;
+			g_string_append_c (accum, ',');
+			break;
+
+		case TOK_GENERAL:
+		case TOK_INVISIBLE_CHAR:
+		case TOK_REPEATED_CHAR:
+		case TOK_COLOR:
+		case TOK_CONDITION:
+		case TOK_LOCALE:
+		case TOK_ERROR:
 			break;
 
 		default:
+			ODF_OPEN_STRING;
+			g_string_append_c (accum, t);
 			break;
 		}
 	}



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