[gnome-control-center] datetime: Implement date endianess detection



commit 2898b86e68be5be01e8fe5bba72f2df87e92225d
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Mar 8 07:57:37 2011 +0000

    datetime: Implement date endianess detection
    
    Implement fairly robust detection of endianess based on
    the d_fmt format exported by glibc.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=636896

 panels/datetime/cc-datetime-panel.c |    2 +-
 panels/datetime/date-endian.c       |  131 +++++++++++++++++++++++++++++++++--
 panels/datetime/date-endian.h       |    6 +-
 3 files changed, 130 insertions(+), 9 deletions(-)
---
diff --git a/panels/datetime/cc-datetime-panel.c b/panels/datetime/cc-datetime-panel.c
index 369ea1e..16bb0e8 100644
--- a/panels/datetime/cc-datetime-panel.c
+++ b/panels/datetime/cc-datetime-panel.c
@@ -828,7 +828,7 @@ cc_date_time_panel_init (CcDateTimePanel *self)
 
   /* set up date editing widgets */
   priv->date = g_date_time_new_now_local ();
-  endianess = date_endian_get_default ();
+  endianess = date_endian_get_default (FALSE);
   reorder_date_widget (endianess, priv);
 
   gtk_combo_box_set_active (GTK_COMBO_BOX (W ("month-combobox")),
diff --git a/panels/datetime/date-endian.c b/panels/datetime/date-endian.c
index a45f849..715d22b 100644
--- a/panels/datetime/date-endian.c
+++ b/panels/datetime/date-endian.c
@@ -22,32 +22,151 @@
 #include <langinfo.h>
 #include <locale.h>
 #include <glib.h>
+#include <string.h>
 
 #include "date-endian.h"
 
+/* We default to returning DATE_ENDIANESS_MIDDLE because that's
+ * what 3.2 billion people use */
+#define DEFAULT_ENDIANESS DATE_ENDIANESS_LITTLE
+
+typedef enum {
+	ITEM_NONE = 0,
+	ITEM_DAY,
+	ITEM_MONTH,
+	ITEM_YEAR
+} Item;
+
+static gboolean
+has_item (Item *items,
+	  Item  item)
+{
+	guint i;
+
+	for (i = 0; i < 3; i++) {
+		if (items[i] == ITEM_NONE)
+			return FALSE;
+		if (items[i] == item)
+			return TRUE;
+	}
+	return FALSE;
+}
+
 DateEndianess
-date_endian_get_default (void)
+date_endian_get_default (gboolean verbose)
 {
 	const char *fmt;
+	const char *p;
+	Item items[3];
+	guint i;
 
 	fmt = nl_langinfo (D_FMT);
-	g_return_val_if_fail (fmt != NULL, DATE_ENDIANESS_MIDDLE);
+	g_return_val_if_fail (fmt != NULL, DEFAULT_ENDIANESS);
+
+	if (verbose)
+		g_print ("%s", fmt);
+
+	if (g_str_equal (fmt, "%F"))
+		return DATE_ENDIANESS_BIG;
 
-	/* FIXME, implement */
+	i = 0;
+	memset (&items, 0, sizeof(items));
 
-	return DATE_ENDIANESS_MIDDLE;
+	/* Assume ASCII only */
+	for (p = fmt; *p != '\0'; p++) {
+		char c;
+
+		/* Look for '%' */
+		if (*p != '%')
+			continue;
+
+		/* Only assert when we're sure we don't have another '%' */
+		if (i >= 4) {
+			g_warning ("Could not parse format '%s', too many formats", fmt);
+			return DEFAULT_ENDIANESS;
+		}
+
+		c = *(p + 1);
+		/* Ignore alternative formats */
+		if (c == 'O' || c == '-' || c == 'E')
+			c = *(p + 2);
+		if (c == '\0') {
+			g_warning ("Count not parse format '%s', unterminated '%%'", fmt);
+			return DEFAULT_ENDIANESS;
+		}
+		switch (c) {
+		case 'd':
+		case 'e':
+			if (has_item (items, ITEM_DAY) == FALSE) {
+				items[i] = ITEM_DAY;
+				i++;
+			}
+			break;
+		case 'm':
+		case 'b':
+		case 'B':
+			if (has_item (items, ITEM_MONTH) == FALSE) {
+				items[i] = ITEM_MONTH;
+				i++;
+			}
+			break;
+		case 'y':
+		case 'Y':
+			if (has_item (items, ITEM_YEAR) == FALSE) {
+				items[i] = ITEM_YEAR;
+				i++;
+			}
+			break;
+		case 'A':
+		case 'a':
+			/* Ignore */
+			;
+		}
+	}
+
+	if (items[0] == ITEM_DAY &&
+	    items[1] == ITEM_MONTH &&
+	    items[2] == ITEM_YEAR)
+		return DATE_ENDIANESS_LITTLE;
+	if (items[0] == ITEM_YEAR &&
+	    items[1] == ITEM_MONTH &&
+	    items[2] == ITEM_DAY)
+		return DATE_ENDIANESS_BIG;
+	if (items[0] == ITEM_MONTH &&
+	    items[1] == ITEM_DAY &&
+	    items[2] == ITEM_YEAR)
+		return DATE_ENDIANESS_MIDDLE;
+
+	g_warning ("Could not parse format '%s'", fmt);
+
+	return DEFAULT_ENDIANESS;
 }
 
 DateEndianess
-date_endian_get_for_lang (const char *lang)
+date_endian_get_for_lang (const char *lang,
+			  gboolean    verbose)
 {
 	const char *old_lang;
 	DateEndianess endian;
 
 	old_lang = setlocale (LC_TIME, lang);
-	endian = date_endian_get_default ();
+	endian = date_endian_get_default (verbose);
 	setlocale (LC_TIME, old_lang);
 
 	return endian;
 }
 
+const char *
+date_endian_to_string (DateEndianess endianess)
+{
+	switch (endianess) {
+	case DATE_ENDIANESS_LITTLE:
+		return "Little (DD-MM-YYYY)";
+	case DATE_ENDIANESS_BIG:
+		return "Big (YYYY-MM-DD)";
+	case DATE_ENDIANESS_MIDDLE:
+		return "Middle (MM-DD-YYYY)";
+	default:
+		g_assert_not_reached ();
+	}
+}
diff --git a/panels/datetime/date-endian.h b/panels/datetime/date-endian.h
index 3c10a6b..4916485 100644
--- a/panels/datetime/date-endian.h
+++ b/panels/datetime/date-endian.h
@@ -26,5 +26,7 @@ typedef enum {
   DATE_ENDIANESS_MIDDLE  /* Middle-endian (month, day, year), e.g. 04/05/03 */
 } DateEndianess;
 
-DateEndianess date_endian_get_default (void);
-DateEndianess date_endian_get_for_lang (const char *lang);
+DateEndianess date_endian_get_default  (gboolean verbose);
+DateEndianess date_endian_get_for_lang (const char *lang,
+					gboolean    verbose);
+const char  * date_endian_to_string    (DateEndianess endianess);



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