← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~jjardon/indicator-datetime/update_map into lp:indicator-datetime

 

Javier Jardón has proposed merging lp:~jjardon/indicator-datetime/update_map into lp:indicator-datetime.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)
Related bugs:
  Bug #754275 in Indicator Date and Time: "Time zones map is wrong"
  https://bugs.launchpad.net/indicator-datetime/+bug/754275

For more details, see:
https://code.launchpad.net/~jjardon/indicator-datetime/update_map/+merge/76144
-- 
https://code.launchpad.net/~jjardon/indicator-datetime/update_map/+merge/76144
Your team ayatana-commits is subscribed to branch lp:indicator-datetime.
=== modified file 'libmap/Makefile.am'
--- libmap/Makefile.am	2011-02-23 18:28:53 +0000
+++ libmap/Makefile.am	2011-09-20 04:43:25 +0000
@@ -16,6 +16,7 @@
 	data/timezone_12.png \
 	data/timezone_12.75.png \
 	data/timezone_13.png \
+	data/timezone_14.png \
 	data/timezone_-2.png \
 	data/timezone_2.png \
 	data/timezone_-3.png \
@@ -38,6 +39,7 @@
 	data/timezone_7.png \
 	data/timezone_-8.png \
 	data/timezone_8.png \
+	data/timezone_8.75.png \
 	data/timezone_-9.png \
 	data/timezone_9.png \
 	data/timezone_-9.5.png \
@@ -55,7 +57,7 @@
 
 noinst_PROGRAMS = test-timezone
 
-test_timezone_SOURCES = test-timezone.c tz.c tz.h
+test_timezone_SOURCES = test-timezone.c tz.c tz.h cc-timezone-map.h cc-timezone-map.c
 test_timezone_LDADD = $(LIBMAP_LIBS)
 test_timezone_CFLAGS = $(LIBMAP_CFLAGS)
 

=== modified file 'libmap/cc-timezone-map.c'
--- libmap/cc-timezone-map.c	2011-06-29 13:10:25 +0000
+++ libmap/cc-timezone-map.c	2011-09-20 04:43:25 +0000
@@ -25,6 +25,7 @@
 
 #include "cc-timezone-map.h"
 #include <math.h>
+#include <string.h>
 #include "tz.h"
 
 G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
@@ -50,10 +51,10 @@
   GdkPixbuf *background;
   GdkPixbuf *color_map;
   GdkPixbuf *olsen_map;
-
+ 
   guchar *visible_map_pixels;
   gint visible_map_rowstride;
-
+ 
   gint olsen_map_channels;
   guchar *olsen_map_pixels;
   gint olsen_map_rowstride;
@@ -64,7 +65,6 @@
 
   TzDB *tzdb;
   TzLocation *location;
-  GHashTable *alias_db;
 };
 
 enum
@@ -570,12 +570,6 @@
       priv->visible_map_rowstride = 0;
     }
 
-  if (priv->alias_db)
-    {
-      g_hash_table_destroy (priv->alias_db);
-      priv->alias_db = NULL;
-    }
-
   if (priv->watermark)
     {
       g_free (priv->watermark);
@@ -686,11 +680,10 @@
   window = gdk_window_new (gtk_widget_get_parent_window (widget), &attr,
                            GDK_WA_X | GDK_WA_Y);
 
-  gdk_window_set_user_data (window, widget);
-
   cursor = gdk_cursor_new (GDK_HAND2);
   gdk_window_set_cursor (window, cursor);
 
+  gdk_window_set_user_data (window, widget);
   gtk_widget_set_window (widget, window);
 }
 
@@ -739,23 +732,26 @@
   CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
   GdkPixbuf *hilight, *orig_hilight, *pin;
   GtkAllocation alloc;
+  GtkStateFlags state;
+  GtkStyleContext *context;
+  GdkRGBA rgba;
   gchar *file;
   GError *err = NULL;
   gdouble pointx, pointy;
   gdouble alpha = 1.0;
-  GtkStyle *style;
   char buf[16];
 
   gtk_widget_get_allocation (widget, &alloc);
 
-  style = gtk_widget_get_style (widget);
+  state = gtk_widget_get_state_flags (widget);
 
   /* Check if insensitive */
-  if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE)
+  if (state & GTK_STATE_FLAG_INSENSITIVE)
     alpha = 0.5;
 
   /* paint background */
-  gdk_cairo_set_source_color (cr, &style->bg[gtk_widget_get_state (widget)]);
+  gtk_style_context_get_color (context, state, &rgba);
+  gdk_cairo_set_source_rgba (cr, &rgba);
   cairo_paint (cr);
   gdk_cairo_set_source_pixbuf (cr, priv->background, 0, 0);
   cairo_paint_with_alpha (cr, alpha);
@@ -773,10 +769,6 @@
     cairo_stroke(cr);
   }
 
-  if (!priv->location) {
-    return TRUE;
-  }
-
   /* paint hilight */
   file = g_strdup_printf (DATADIR "/timezone_%s.png",
                           g_ascii_formatd (buf, sizeof (buf),
@@ -813,16 +805,23 @@
       g_clear_error (&err);
     }
 
-  pointx = convert_longtitude_to_x (priv->location->longitude, alloc.width);
-  pointy = convert_latitude_to_y (priv->location->latitude, alloc.height);
-
-  if (pointy > alloc.height)
-    pointy = alloc.height;
+  if (priv->location)
+    {
+      pointx = convert_longtitude_to_x (priv->location->longitude, alloc.width);
+      pointy = convert_latitude_to_y (priv->location->latitude, alloc.height);
+
+      if (pointy > alloc.height)
+        pointy = alloc.height;
+
+      if (pin)
+        {
+          gdk_cairo_set_source_pixbuf (cr, pin, pointx - 8, pointy - 14);
+          cairo_paint_with_alpha (cr, alpha);
+        }
+    }
 
   if (pin)
     {
-      gdk_cairo_set_source_pixbuf (cr, pin, pointx - 8, pointy - 14);
-      cairo_paint_with_alpha (cr, alpha);
       g_object_unref (pin);
     }
 
@@ -964,6 +963,7 @@
 {
   TzLocation * loc = get_loc_for_xy (widget, event->x, event->y);
   set_location (CC_TIMEZONE_MAP (widget), loc);
+
   return TRUE;
 }
 
@@ -975,57 +975,6 @@
 }
 
 static void
-load_backward_tz (CcTimezoneMap *self)
-{
-  GError *error = NULL;
-  char **lines, *contents;
-  guint i;
-
-  self->priv->alias_db = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-  if (g_file_get_contents (GNOMECC_DATA_DIR "/datetime/backward", &contents, NULL, &error) == FALSE)
-    {
-      g_warning ("Failed to load 'backward' file: %s", error->message);
-      return;
-    }
-  lines = g_strsplit (contents, "\n", -1);
-  g_free (contents);
-  for (i = 0; lines[i] != NULL; i++)
-    {
-      char **items;
-      guint j;
-      char *real, *alias;
-
-      if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0)
-        continue;
-
-      items = g_strsplit (lines[i], "\t", -1);
-      real = NULL;
-      alias = NULL;
-      /* Skip the "Link<tab>" part */
-      for (j = 1; items[j] != NULL; j++)
-        {
-          if (items[j][0] == '\0')
-            continue;
-          if (real == NULL)
-            {
-              real = items[j];
-              continue;
-            }
-          alias = items[j];
-          break;
-        }
-
-      if (real == NULL || alias == NULL)
-        g_warning ("Could not parse line: %s", lines[i]);
-
-      g_hash_table_insert (self->priv->alias_db, g_strdup (alias), g_strdup (real));
-      g_strfreev (items);
-    }
-  g_strfreev (lines);
-}
-
-static void
 cc_timezone_map_init (CcTimezoneMap *self)
 {
   CcTimezoneMapPrivate *priv;
@@ -1070,8 +1019,6 @@
                     NULL);
   g_signal_connect (self, "state-flags-changed", G_CALLBACK (state_flags_changed),
                     NULL);
-
-  load_backward_tz (self);
 }
 
 CcTimezoneMap *
@@ -1080,17 +1027,19 @@
   return g_object_new (CC_TYPE_TIMEZONE_MAP, NULL);
 }
 
-void
+gboolean
 cc_timezone_map_set_timezone (CcTimezoneMap *map,
                               const gchar   *timezone)
 {
   GPtrArray *locations;
   guint i;
   char *real_tz;
+  gboolean ret;
 
-  real_tz = g_hash_table_lookup (map->priv->alias_db, timezone);
+  real_tz = tz_info_get_clean_name (map->priv->tzdb, timezone);
 
   locations = tz_get_locations (map->priv->tzdb);
+  ret = FALSE;
 
   for (i = 0; i < locations->len; i++)
     {
@@ -1099,18 +1048,17 @@
       if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
         {
           set_location (map, loc);
+          ret = TRUE;
           break;
         }
     }
 
-  gtk_widget_queue_draw (GTK_WIDGET (map));
-}
-
-void
-cc_timezone_map_set_coords (CcTimezoneMap *map, gdouble lon, gdouble lat)
-{
-  const gchar * zone = cc_timezone_map_get_timezone_at_coords (map, lon, lat);
-  cc_timezone_map_set_timezone (map, zone);
+  if (ret)
+    gtk_widget_queue_draw (GTK_WIDGET (map));
+
+  g_free (real_tz);
+
+  return ret;
 }
 
 const gchar *

=== modified file 'libmap/cc-timezone-map.h'
--- libmap/cc-timezone-map.h	2011-02-23 21:26:49 +0000
+++ libmap/cc-timezone-map.h	2011-09-20 04:43:25 +0000
@@ -72,10 +72,8 @@
 
 void cc_timezone_map_set_watermark (CcTimezoneMap * map,
                                     const gchar * watermark);
-void cc_timezone_map_set_timezone (CcTimezoneMap *map,
-                                   const gchar   *timezone);
-void cc_timezone_map_set_coords (CcTimezoneMap *map,
-                                 gdouble lon, gdouble lat);
+gboolean cc_timezone_map_set_timezone (CcTimezoneMap *map,
+                                       const gchar   *timezone);
 const gchar * cc_timezone_map_get_timezone_at_coords (CcTimezoneMap *map,
                                                       gdouble lon, gdouble lat);
 TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);

=== modified file 'libmap/data/cc.png'
Binary files libmap/data/cc.png	2011-02-22 16:20:34 +0000 and libmap/data/cc.png	2011-09-20 04:43:25 +0000 differ
=== modified file 'libmap/data/timezone_-11.png'
Binary files libmap/data/timezone_-11.png	2011-02-22 16:20:34 +0000 and libmap/data/timezone_-11.png	2011-09-20 04:43:25 +0000 differ
=== modified file 'libmap/data/timezone_8.png'
Binary files libmap/data/timezone_8.png	2011-02-22 16:20:34 +0000 and libmap/data/timezone_8.png	2011-09-20 04:43:25 +0000 differ
=== modified file 'libmap/test-timezone.c'
--- libmap/test-timezone.c	2011-02-25 16:41:56 +0000
+++ libmap/test-timezone.c	2011-09-20 04:43:25 +0000
@@ -1,56 +1,101 @@
-#include <config.h>
-#include <locale.h>
-
-#include "tz.h"
+#include <gtk/gtk.h>
+#include "cc-timezone-map.h"
+
+#define TZ_DIR "/usr/share/zoneinfo/"
+
+static GList *
+get_timezone_list (GList *tzs,
+		   const char *top_path,
+		   const char *subpath)
+{
+	GDir *dir;
+	char *fullpath;
+	const char *name;
+
+	if (subpath == NULL)
+		fullpath = g_strdup (top_path);
+	else
+		fullpath = g_build_filename (top_path, subpath, NULL);
+	dir = g_dir_open (fullpath, 0, NULL);
+	if (dir == NULL) {
+		g_warning ("Could not open %s", fullpath);
+		return NULL;
+	}
+	while ((name = g_dir_read_name (dir)) != NULL) {
+		char *path;
+
+		if (g_str_has_suffix (name, ".tab"))
+			continue;
+
+		if (subpath != NULL)
+			path = g_build_filename (top_path, subpath, name, NULL);
+		else
+			path = g_build_filename (top_path, name, NULL);
+		if (g_file_test (path, G_FILE_TEST_IS_DIR)) {
+			if (subpath == NULL) {
+				tzs = get_timezone_list (tzs, top_path, name);
+			} else {
+				char *new_subpath;
+				new_subpath = g_strdup_printf ("%s/%s", subpath, name);
+				tzs = get_timezone_list (tzs, top_path, new_subpath);
+				g_free (new_subpath);
+			}
+		} else if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
+			if (subpath == NULL)
+				tzs = g_list_prepend (tzs, g_strdup (name));
+			else {
+				char *tz;
+				tz = g_strdup_printf ("%s/%s", subpath, name);
+				tzs = g_list_prepend (tzs, tz);
+			}
+		}
+		g_free (path);
+	}
+	g_dir_close (dir);
+
+	return tzs;
+}
 
 int main (int argc, char **argv)
 {
-	TzDB *db;
-	GPtrArray *locs;
-	guint i;
-	char *pixmap_dir;
-	int retval = 0;
-
-        setlocale (LC_ALL, "");
-
-	if (argc == 2) {
-		pixmap_dir = g_strdup (argv[1]);
-	} else if (argc == 1) {
-		pixmap_dir = g_strdup ("data/");
-	} else {
-		g_message ("Usage: %s [PIXMAP DIRECTORY]", argv[0]);
-		return 1;
-	}
-
-	db = tz_load_db ();
-	locs = tz_get_locations (db);
-	for (i = 0; i < locs->len ; i++) {
-		TzLocation *loc = locs->pdata[i];
-		TzInfo *info;
-		char *filename, *path;
-		gdouble selected_offset;
-                char buf[16];
-
-		info = tz_info_from_location (loc);
-		selected_offset = tz_location_get_utc_offset (loc)
-			/ (60.0*60.0) + ((info->daylight) ? -1.0 : 0.0);
-
-		filename = g_strdup_printf ("timezone_%s.png",
-                                            g_ascii_formatd (buf, sizeof (buf),
-                                                             "%g", selected_offset));
-		path = g_build_filename (pixmap_dir, filename, NULL);
-
-		if (g_file_test (path, G_FILE_TEST_IS_REGULAR) == FALSE) {
-			g_message ("File '%s' missing for zone '%s'", filename, loc->zone);
-			retval = 1;
+	CcTimezoneMap *map;
+	TzDB *tz_db;
+	GList *tzs, *l;
+	GHashTable *ht;
+	int ret = 0;
+
+	gtk_init (&argc, &argv);
+
+	ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	map = cc_timezone_map_new ();
+	tz_db = tz_load_db ();
+	tzs = get_timezone_list (NULL, TZ_DIR, NULL);
+	for (l = tzs; l != NULL; l = l->next) {
+		char *timezone = l->data;
+		char *clean_tz;
+
+		clean_tz = tz_info_get_clean_name (tz_db, timezone);
+
+		if (cc_timezone_map_set_timezone (map, clean_tz) == FALSE) {
+			if (g_hash_table_lookup (ht, clean_tz) == NULL) {
+				if (g_strcmp0 (clean_tz, timezone) == 0)
+					g_print ("Failed to locate timezone '%s'\n", timezone);
+				else
+					g_print ("Failed to locate timezone '%s' (original name: '%s')\n", clean_tz, timezone);
+				g_hash_table_insert (ht, g_strdup (clean_tz), GINT_TO_POINTER (TRUE));
+			}
+			/* We don't warn for those two, we'll just fallback
+			 * in the panel code */
+			if (!g_str_equal (clean_tz, "posixrules") &&
+			    !g_str_equal (clean_tz, "Factory"))
+				ret = 1;
 		}
-
-		g_free (filename);
-		g_free (path);
-		tz_info_free (info);
+		g_free (timezone);
+		g_free (clean_tz);
 	}
-	tz_db_free (db);
-	g_free (pixmap_dir);
+	g_list_free (tzs);
+	tz_db_free (tz_db);
+	g_hash_table_destroy (ht);
 
-	return retval;
+	return ret;
 }

=== modified file 'libmap/tz.c'
--- libmap/tz.c	2011-02-23 18:28:53 +0000
+++ libmap/tz.c	2011-09-20 04:43:25 +0000
@@ -39,7 +39,7 @@
 static int compare_country_names (const void *a, const void *b);
 static void sort_locations_by_country (GPtrArray *locations);
 static gchar * tz_data_file_get (void);
-
+static void load_backward_tz (TzDB *tz_db);
 
 /* ---------------- *
  * Public interface *
@@ -124,9 +124,12 @@
 	sort_locations_by_country (tz_db->locations);
 	
 	g_free (tz_data_file);
-	
+
+	/* Load up the hashtable of backward links */
+	load_backward_tz (tz_db);
+
 	return tz_db;
-}    
+}
 
 static void
 tz_location_free (TzLocation *loc)
@@ -143,58 +146,10 @@
 {
 	g_ptr_array_foreach (db->locations, (GFunc) tz_location_free, NULL);
 	g_ptr_array_free (db->locations, TRUE);
+	g_hash_table_destroy (db->backward);
 	g_free (db);
 }
 
-static gint
-sort_locations (TzLocation *a,
-                TzLocation *b)
-{
-  if (a->dist > b->dist)
-    return 1;
-
-  if (a->dist < b->dist)
-    return -1;
-
-  return 0;
-}
-
-static gdouble
-convert_longtitude_to_x (gdouble longitude, gint map_width)
-{
-  const gdouble xdeg_offset = -6;
-  gdouble x;
-
-  x = (map_width * (180.0 + longitude) / 360.0)
-    + (map_width * xdeg_offset / 180.0);
-
-  return x;
-}
-
-static gdouble
-radians (gdouble degrees)
-{
-  return (degrees / 360.0) * G_PI * 2;
-}
-
-static gdouble
-convert_latitude_to_y (gdouble latitude, gdouble map_height)
-{
-  gdouble bottom_lat = -59;
-  gdouble top_lat = 81;
-  gdouble top_per, y, full_range, top_offset, map_range;
-
-  top_per = top_lat / 180.0;
-  y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
-  full_range = 4.6068250867599998;
-  top_offset = full_range * top_per;
-  map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
-  y = fabs (y - top_offset);
-  y = y / map_range;
-  y = y * map_height;
-  return y;
-}
-
 GPtrArray *
 tz_get_locations (TzDB *db)
 {
@@ -242,47 +197,18 @@
 	return offset;
 }
 
-gint
-tz_location_set_locally (TzLocation *loc)
-{
-	time_t curtime;
-	struct tm *curzone;
-	gboolean is_dst = FALSE;
-	gint correction = 0;
-
-	g_return_val_if_fail (loc != NULL, 0);
-	g_return_val_if_fail (loc->zone != NULL, 0);
-	
-	curtime = time (NULL);
-	curzone = localtime (&curtime);
-	is_dst = curzone->tm_isdst;
-
-	setenv ("TZ", loc->zone, 1);
-#if 0
-	curtime = time (NULL);
-	curzone = localtime (&curtime);
-
-	if (!is_dst && curzone->tm_isdst) {
-		correction = (60 * 60);
-	}
-	else if (is_dst && !curzone->tm_isdst) {
-		correction = 0;
-	}
-#endif
-
-	return correction;
-}
-
 TzInfo *
 tz_info_from_location (TzLocation *loc)
 {
 	TzInfo *tzinfo;
 	time_t curtime;
 	struct tm *curzone;
+	gchar *tz_env_value;
 	
 	g_return_val_if_fail (loc != NULL, NULL);
 	g_return_val_if_fail (loc->zone != NULL, NULL);
 	
+	tz_env_value = g_strdup (getenv ("TZ"));
 	setenv ("TZ", loc->zone, 1);
 	
 #if 0
@@ -311,6 +237,13 @@
 #endif
 
 	tzinfo->daylight = curzone->tm_isdst;
+
+	if (tz_env_value)
+		setenv ("TZ", tz_env_value, 1);
+	else
+		unsetenv ("TZ");
+
+	g_free (tz_env_value);
 	
 	return tzinfo;
 }
@@ -326,6 +259,99 @@
 	g_free (tzinfo);
 }
 
+struct {
+	const char *orig;
+	const char *dest;
+} aliases[] = {
+	{ "Asia/Istanbul",  "Europe/Istanbul" },	/* Istanbul is in both Europe and Asia */
+	{ "Europe/Nicosia", "Asia/Nicosia" },		/* Ditto */
+	{ "EET",            "Europe/Istanbul" },	/* Same tz as the 2 above */
+	{ "HST",            "Pacific/Honolulu" },
+	{ "WET",            "Europe/Brussels" },	/* Other name for the mainland Europe tz */
+	{ "CET",            "Europe/Brussels" },	/* ditto */
+	{ "MET",            "Europe/Brussels" },
+	{ "Etc/Zulu",       "Etc/GMT" },
+	{ "Etc/UTC",        "Etc/GMT" },
+	{ "GMT",            "Etc/GMT" },
+	{ "Greenwich",      "Etc/GMT" },
+	{ "Etc/UCT",        "Etc/GMT" },
+	{ "Etc/GMT0",       "Etc/GMT" },
+	{ "Etc/GMT+0",      "Etc/GMT" },
+	{ "Etc/GMT-0",      "Etc/GMT" },
+	{ "Etc/Universal",  "Etc/GMT" },
+	{ "PST8PDT",        "America/Los_Angeles" },	/* Other name for the Atlantic tz */
+	{ "EST",            "America/New_York" },	/* Other name for the Eastern tz */
+	{ "EST5EDT",        "America/New_York" },	/* ditto */
+	{ "CST6CDT",        "America/Chicago" },	/* Other name for the Central tz */
+	{ "MST",            "America/Denver" },		/* Other name for the mountain tz */
+	{ "MST7MDT",        "America/Denver" },		/* ditto */
+};
+
+static gboolean
+compare_timezones (const char *a,
+		   const char *b)
+{
+	if (g_str_equal (a, b))
+		return TRUE;
+	if (strchr (b, '/') == NULL) {
+		char *prefixed;
+
+		prefixed = g_strdup_printf ("/%s", b);
+		if (g_str_has_suffix (a, prefixed)) {
+			g_free (prefixed);
+			return TRUE;
+		}
+		g_free (prefixed);
+	}
+
+	return FALSE;
+}
+
+char *
+tz_info_get_clean_name (TzDB *tz_db,
+			const char *tz)
+{
+	char *ret;
+	const char *timezone;
+	guint i;
+	gboolean replaced;
+
+	/* Remove useless prefixes */
+	if (g_str_has_prefix (tz, "right/"))
+		tz = tz + strlen ("right/");
+	else if (g_str_has_prefix (tz, "posix/"))
+		tz = tz + strlen ("posix/");
+
+	/* Here start the crazies */
+	replaced = FALSE;
+
+	for (i = 0; i < G_N_ELEMENTS (aliases); i++) {
+		if (compare_timezones (tz, aliases[i].orig)) {
+			replaced = TRUE;
+			timezone = aliases[i].dest;
+			break;
+		}
+	}
+
+	/* Try again! */
+	if (!replaced) {
+		/* Ignore crazy solar times from the '80s */
+		if (g_str_has_prefix (tz, "Asia/Riyadh") ||
+		    g_str_has_prefix (tz, "Mideast/Riyadh")) {
+			timezone = "Asia/Riyadh";
+			replaced = TRUE;
+		}
+	}
+
+	if (!replaced)
+		timezone = tz;
+
+	ret = g_hash_table_lookup (tz_db->backward, timezone);
+	if (ret == NULL)
+		return g_strdup (timezone);
+	return g_strdup (ret);
+}
+
 /* ----------------- *
  * Private functions *
  * ----------------- */
@@ -397,3 +423,60 @@
 	qsort (locations->pdata, locations->len, sizeof (gpointer),
 	       compare_country_names);
 }
+
+static void
+load_backward_tz (TzDB *tz_db)
+{
+  GError *error = NULL;
+  char **lines, *contents;
+  guint i;
+
+  tz_db->backward = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  if (g_file_get_contents (GNOMECC_DATA_DIR "/datetime/backward", &contents, NULL, &error) == FALSE)
+    {
+      g_warning ("Failed to load 'backward' file: %s", error->message);
+      return;
+    }
+  lines = g_strsplit (contents, "\n", -1);
+  g_free (contents);
+  for (i = 0; lines[i] != NULL; i++)
+    {
+      char **items;
+      guint j;
+      char *real, *alias;
+
+      if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0)
+        continue;
+
+      items = g_strsplit (lines[i], "\t", -1);
+      real = NULL;
+      alias = NULL;
+      /* Skip the "Link<tab>" part */
+      for (j = 1; items[j] != NULL; j++)
+        {
+          if (items[j][0] == '\0')
+            continue;
+          if (real == NULL)
+            {
+              real = items[j];
+              continue;
+            }
+          alias = items[j];
+          break;
+        }
+
+      if (real == NULL || alias == NULL)
+        g_warning ("Could not parse line: %s", lines[i]);
+
+      /* We don't need more than one name for it */
+      if (g_str_equal (real, "Etc/UTC") ||
+          g_str_equal (real, "Etc/UCT"))
+        real = "Etc/GMT";
+
+      g_hash_table_insert (tz_db->backward, g_strdup (alias), g_strdup (real));
+      g_strfreev (items);
+    }
+  g_strfreev (lines);
+}
+

=== modified file 'libmap/tz.h'
--- libmap/tz.h	2011-02-22 16:20:34 +0000
+++ libmap/tz.h	2011-09-20 04:43:25 +0000
@@ -41,7 +41,8 @@
 
 struct _TzDB
 {
-	GPtrArray *locations;
+	GPtrArray  *locations;
+	GHashTable *backward;
 };
 
 struct _TzLocation
@@ -72,6 +73,8 @@
 
 TzDB      *tz_load_db                 (void);
 void       tz_db_free                 (TzDB *db);
+char *     tz_info_get_clean_name     (TzDB *tz_db,
+				       const char *tz);
 GPtrArray *tz_get_locations           (TzDB *db);
 void       tz_location_get_position   (TzLocation *loc,
 				       double *longitude, double *latitude);


Follow ups