diff options
author | Matthias Clasen <mclasen@fedoraproject.org> | 2007-10-14 06:15:56 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@fedoraproject.org> | 2007-10-14 06:15:56 +0000 |
commit | e0b3ac9bb97fdfcfaa66696b3173f0dc6a386a8e (patch) | |
tree | 9f8052f7d6e8d48a8a0de17016137a4b32845887 | |
parent | a2405b974a926937f0c49613761e30c4d583a93c (diff) | |
download | gnome-panel-e0b3ac9bb97fdfcfaa66696b3173f0dc6a386a8e.tar.gz gnome-panel-e0b3ac9bb97fdfcfaa66696b3173f0dc6a386a8e.tar.xz gnome-panel-e0b3ac9bb97fdfcfaa66696b3173f0dc6a386a8e.zip |
Add network monitoring to intlclockgnome-panel-2_20_0_1-8_fc9
-rw-r--r-- | gnome-panel.spec | 8 | ||||
-rw-r--r-- | intlclock-changes-20071005.patch | 9697 | ||||
-rw-r--r-- | intlclock-changes-20071009.patch | 10832 | ||||
-rw-r--r-- | intlclock-changes-20071014.patch (renamed from intlclock-changes-20071013.patch) | 116 |
4 files changed, 111 insertions, 20542 deletions
diff --git a/gnome-panel.spec b/gnome-panel.spec index c34adfa..7a6a43e 100644 --- a/gnome-panel.spec +++ b/gnome-panel.spec @@ -22,7 +22,7 @@ Summary: GNOME panel Name: gnome-panel Version: 2.20.0.1 -Release: 7%{?dist} +Release: 8%{?dist} URL: http://www.gnome.org Source0: http://download.gnome.org/sources/gnome-panel/2.20/%{name}-%{version}.tar.bz2 # we are upstream for this @@ -30,7 +30,7 @@ Source1: timezone.tar.gz # Novell intlclock, I don't think this has a canonical upstream location Source2: intlclock-1.0.tar.gz Patch98: timezone-changes.patch -Patch99: intlclock-changes-20071009.patch +Patch99: intlclock-changes-20071014.patch Patch100: dont-build-clock.patch Patch101: intlclock-build-fixes.patch @@ -94,6 +94,7 @@ BuildRequires: dbus-devel >= %{dbus_version} BuildRequires: PolicyKit-devel BuildRequires: gnome-applets-devel BuildRequires: librsvg2-devel +BuildRequires: NetworkManager-devel Patch0: gnome-panel-2.19.5-vendor.patch Patch1: gnome-panel-2.10.1-speak-to-us-ye-old-wise-fish.patch @@ -380,6 +381,9 @@ fi %{_datadir}/gtk-doc/html/* %changelog +* Sun Oct 14 2007 Matthias Clasen <mclasen@redhat.com> - 2.20.0.1-8 +- Add network monitoring to the intlclock + * Sat Oct 13 2007 Matthias Clasen <mclasen@redhat.com> - 2.20.0.1-7 - Another round of intlclock updates * show offsets in popup diff --git a/intlclock-changes-20071005.patch b/intlclock-changes-20071005.patch deleted file mode 100644 index 32496a1..0000000 --- a/intlclock-changes-20071005.patch +++ /dev/null @@ -1,9697 +0,0 @@ -diff --git a/configure.in b/configure.in -index 4e818da..6c75db1 100644 ---- a/configure.in -+++ b/configure.in -@@ -59,7 +59,7 @@ if test -n "$LIBECAL_REQUIREMENT"; then - fi - AM_CONDITIONAL(HAVE_LIBECAL, test -n "$LIBECAL_REQUIREMENT") - --PKG_CHECK_MODULES(INTLCLOCK, [ glib-2.0 gobject-2.0 gtk+-2.0 gdk-2.0 librsvg-2.0 libpanelapplet-2.0 libgnome-2.0 gconf-2.0 $LIBECAL_REQUIREMENT ]) -+PKG_CHECK_MODULES(INTLCLOCK, [ glib-2.0 gobject-2.0 gtk+-2.0 gdk-2.0 librsvg-2.0 libpanelapplet-2.0 libgnome-2.0 gconf-2.0 $LIBECAL_REQUIREMENT dbus-glib-1 gweather libxml-2.0 polkit polkit-dbus ]) - - AC_SUBST(INTLCLOCK_CFLAGS) - AC_SUBST(INTLCLOCK_LIBS) -diff --git a/data/GNOME_IntlClockApplet.xml b/data/GNOME_IntlClockApplet.xml -index dd2e8b8..152f26c 100644 ---- a/data/GNOME_IntlClockApplet.xml -+++ b/data/GNOME_IntlClockApplet.xml -@@ -1,9 +1,6 @@ - <Root> - <popups> - <popup name="button3"> -- <menuitem name="Clock Configure Item" verb="IntlClockConfig" -- _label="Cha_nge Date or Time" -- pixtype="stock" pixname="gtk-preferences"/> - <menuitem name="Clock Preferences Item" verb="IntlClockPreferences" _label="_Preferences" - pixtype="stock" pixname="gtk-properties"/> - </popup> -diff --git a/data/GNOME_IntlClockApplet_Factory.server.in.in b/data/GNOME_IntlClockApplet_Factory.server.in.in -index 1446822..705fb76 100644 ---- a/data/GNOME_IntlClockApplet_Factory.server.in.in -+++ b/data/GNOME_IntlClockApplet_Factory.server.in.in -@@ -20,7 +20,7 @@ - </oaf_attribute> - <oaf_attribute name="name" type="string" value="International Clock"/> - <oaf_attribute name="description" type="string" value="International Clock applet for the GNOME panel"/> -- <oaf_attribute name="panel:icon" type="string" value="clock.png"/> -+ <oaf_attribute name="panel:icon" type="string" value="gnome-panel-clock"/> - </oaf_server> - - <oaf_server iid="OAFIID:GNOME_ClockApplet" -diff --git a/data/intlclock.glade b/data/intlclock.glade -index e7b8c01..b23ade0 100644 ---- a/data/intlclock.glade -+++ b/data/intlclock.glade -@@ -26,7 +26,7 @@ - <property name="spacing">0</property> - - <child> -- <widget class="GtkNotebook" id="notebook1"> -+ <widget class="GtkNotebook" id="notebook"> - <property name="border_width">6</property> - <property name="visible">True</property> - <property name="can_focus">True</property> -@@ -37,194 +37,35 @@ - <property name="enable_popup">False</property> - - <child> -- <widget class="GtkTable" id="table1"> -- <property name="border_width">6</property> -+ <widget class="GtkVBox" id="vbox17"> -+ <property name="border_width">12</property> - <property name="visible">True</property> -- <property name="n_rows">4</property> -- <property name="n_columns">3</property> - <property name="homogeneous">False</property> -- <property name="row_spacing">6</property> -- <property name="column_spacing">6</property> -+ <property name="spacing">18</property> - - <child> -- <widget class="GtkLabel" id="label11"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Clock options:</property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label12"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label13"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">3</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label14"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label15"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="seconds_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show s_econds</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">3</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">3</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkHBox" id="hbox3"> -+ <widget class="GtkVBox" id="vbox18"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> -- <widget class="GtkRadioButton" id="12hr_radio"> -+ <widget class="GtkLabel" id="label210"> - <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">12 _hour format</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -+ <property name="label" translatable="yes"><b>Clock Options</b></property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">True</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> -@@ -234,290 +75,15 @@ - </child> - - <child> -- <widget class="GtkRadioButton" id="24hr_radio"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">24 h_our format</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- <property name="group">12hr_radio</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="date_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show the _date</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label16"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label17"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label201"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- </widget> -- <packing> -- <property name="tab_expand">False</property> -- <property name="tab_fill">True</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label1"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">General</property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="type">tab</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkTable" id="table5"> -- <property name="border_width">6</property> -- <property name="visible">True</property> -- <property name="n_rows">8</property> -- <property name="n_columns">4</property> -- <property name="homogeneous">False</property> -- <property name="row_spacing">6</property> -- <property name="column_spacing">6</property> -- -- <child> -- <widget class="GtkLabel" id="label36"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label37"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkScrolledWindow" id="scrolledwindow2"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> -- <property name="vscrollbar_policy">GTK_POLICY_NEVER</property> -- <property name="shadow_type">GTK_SHADOW_IN</property> -- <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -- -- <child> -- <widget class="GtkTreeView" id="cities_list"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="headers_visible">False</property> -- <property name="rules_hint">False</property> -- <property name="reorderable">False</property> -- <property name="enable_search">True</property> -- <property name="fixed_height_mode">False</property> -- <property name="hover_selection">False</property> -- <property name="hover_expand">True</property> -- </widget> -- </child> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">3</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">8</property> -- <property name="x_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkAlignment" id="alignment6"> -- <property name="visible">True</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xscale">0</property> -- <property name="yscale">1</property> -- <property name="top_padding">0</property> -- <property name="bottom_padding">0</property> -- <property name="left_padding">0</property> -- <property name="right_padding">0</property> -- -- <child> -- <widget class="GtkVBox" id="vbox2"> -+ <widget class="GtkHBox" id="hbox48"> - <property name="visible">True</property> - <property name="homogeneous">False</property> -- <property name="spacing">6</property> -+ <property name="spacing">0</property> - - <child> -- <widget class="GtkLabel" id="label39"> -+ <widget class="GtkLabel" id="label211"> - <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -+ <property name="label"> </property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> -@@ -540,62 +106,163 @@ - </child> - - <child> -- <widget class="GtkVButtonBox" id="vbuttonbox1"> -+ <widget class="GtkVBox" id="vbox19"> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_START</property> -+ <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> -- <widget class="GtkButton" id="prefs-locations-add-button"> -- <property name="width_request">24</property> -- <property name="height_request">25</property> -+ <widget class="GtkHBox" id="hbox49"> - <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-add</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">13</property> -+ -+ <child> -+ <widget class="GtkRadioButton" id="12hr_radio"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">12 _hour format</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkRadioButton" id="24hr_radio"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">24 h_our format</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ <property name="group">12hr_radio</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> - </child> - - <child> -- <widget class="GtkButton" id="prefs-locations-edit-button"> -- <property name="width_request">24</property> -- <property name="height_request">24</property> -+ <widget class="GtkCheckButton" id="date_check"> - <property name="visible">True</property> -- <property name="can_default">True</property> - <property name="can_focus">True</property> -- <property name="label">gtk-edit</property> -- <property name="use_stock">True</property> -+ <property name="label" translatable="yes">Show the _date</property> -+ <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> - </child> - - <child> -- <widget class="GtkButton" id="prefs-locations-remove-button"> -+ <widget class="GtkCheckButton" id="seconds_check"> - <property name="visible">True</property> -- <property name="can_default">True</property> - <property name="can_focus">True</property> -- <property name="label">gtk-remove</property> -- <property name="use_stock">True</property> -+ <property name="label" translatable="yes">Show _seconds</property> -+ <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> - </packing> - </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox20"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label212"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes"><b>Time Settings</b></property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">True</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="time_settings_box"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> - - <child> -- <widget class="GtkLabel" id="label38"> -+ <widget class="GtkLabel" id="label217"> - <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -+ <property name="label"> </property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> -@@ -616,115 +283,377 @@ - <property name="fill">False</property> - </packing> - </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox52"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">12</property> -+ -+ <child> -+ <widget class="GtkCalendar" id="calendar"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="display_options">GTK_CALENDAR_SHOW_HEADING</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox22"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label218"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Current Time:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label219"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Time:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox23"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="current_time_label"> -+ <property name="visible">True</property> -+ <property name="label">23:59:59</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox53"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkSpinButton" id="hours_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">23 0 23 1 12 12</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkSpinButton" id="minutes_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">59 0 59 1 30 30</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkSpinButton" id="seconds_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">59 0 59 1 30 30</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkAlignment" id="alignment30"> -+ <property name="visible">True</property> -+ <property name="xalign">1</property> -+ <property name="yalign">1</property> -+ <property name="xscale">0</property> -+ <property name="yscale">0</property> -+ <property name="top_padding">0</property> -+ <property name="bottom_padding">0</property> -+ <property name="left_padding">0</property> -+ <property name="right_padding">0</property> -+ -+ <child> -+ <widget class="GtkButton" id="set_time_button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Set System Time</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> - </child> - </widget> - <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">8</property> -- <property name="x_options"></property> -- <property name="y_options">fill</property> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">True</property> - </packing> - </child> -+ </widget> -+ <packing> -+ <property name="tab_expand">False</property> -+ <property name="tab_fill">True</property> -+ </packing> -+ </child> - -- <child> -- <widget class="GtkCheckButton" id="show_map_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show the world _map in the clock</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -+ <child> -+ <widget class="GtkLabel" id="label209"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">General</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="type">tab</property> -+ </packing> -+ </child> - -- <child> -- <widget class="GtkLabel" id="label41"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="y_options"></property> -- </packing> -- </child> -+ <child> -+ <widget class="GtkVBox" id="vbox24"> -+ <property name="border_width">12</property> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">18</property> - - <child> -- <widget class="GtkLabel" id="label160"> -+ <widget class="GtkHBox" id="hbox54"> - <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -+ <property name="homogeneous">False</property> -+ <property name="spacing">12</property> - -- <child> -- <widget class="GtkCheckButton" id="show_locations_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">S_how locations in the clock</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -+ <child> -+ <widget class="GtkScrolledWindow" id="scrolledwindow10"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> -+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property> -+ <property name="shadow_type">GTK_SHADOW_IN</property> -+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -+ -+ <child> -+ <widget class="GtkTreeView" id="cities_list"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="headers_visible">False</property> -+ <property name="rules_hint">False</property> -+ <property name="reorderable">False</property> -+ <property name="enable_search">True</property> -+ <property name="fixed_height_mode">False</property> -+ <property name="hover_selection">False</property> -+ <property name="hover_expand">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVButtonBox" id="vbuttonbox2"> -+ <property name="visible">True</property> -+ <property name="layout_style">GTK_BUTTONBOX_START</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkButton" id="prefs-locations-add-button"> -+ <property name="width_request">24</property> -+ <property name="height_request">25</property> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-add</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="prefs-locations-edit-button"> -+ <property name="width_request">24</property> -+ <property name="height_request">24</property> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-edit</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="prefs-locations-remove-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-remove</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> - </widget> - <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">3</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> - </packing> - </child> - </widget> -@@ -735,7 +664,7 @@ - </child> - - <child> -- <widget class="GtkLabel" id="label2"> -+ <widget class="GtkLabel" id="label220"> - <property name="visible">True</property> - <property name="label" translatable="yes">Locations</property> - <property name="use_underline">False</property> -@@ -791,80 +720,6 @@ - <property name="spacing">6</property> - - <child> -- <widget class="GtkButton" id="prefs-time-settings-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- -- <child> -- <widget class="GtkAlignment" id="alignment5"> -- <property name="visible">True</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xscale">0</property> -- <property name="yscale">0</property> -- <property name="top_padding">0</property> -- <property name="bottom_padding">0</property> -- <property name="left_padding">0</property> -- <property name="right_padding">0</property> -- -- <child> -- <widget class="GtkHBox" id="hbox8"> -- <property name="visible">True</property> -- <property name="homogeneous">False</property> -- <property name="spacing">2</property> -- -- <child> -- <widget class="GtkImage" id="image5"> -- <property name="visible">True</property> -- <property name="stock">gtk-properties</property> -- <property name="icon_size">4</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label35"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Time _Settings</property> -- <property name="use_underline">True</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- </widget> -- </child> -- </widget> -- </child> -- </widget> -- </child> -- -- <child> - <widget class="GtkButton" id="prefs-close-button"> - <property name="visible">True</property> - <property name="can_default">True</property> -@@ -910,13 +765,13 @@ - - <child> - <widget class="GtkVBox" id="vbox14"> -+ <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> -- <property name="spacing">0</property> -+ <property name="spacing">24</property> - - <child> - <widget class="GtkTable" id="table23"> -- <property name="border_width">6</property> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">3</property> -@@ -926,7 +781,6 @@ - - <child> - <widget class="GtkVBox" id="vbox15"> -- <property name="border_width">6</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> -@@ -1088,27 +942,6 @@ - </child> - - <child> -- <widget class="GtkEntry" id="edit-location-name-entry"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="editable">True</property> -- <property name="visibility">True</property> -- <property name="max_length">0</property> -- <property name="text" translatable="yes"></property> -- <property name="has_frame">True</property> -- <property name="invisible_char">●</property> -- <property name="activates_default">False</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">4</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> - <widget class="GtkLabel" id="label208"> - <property name="visible">True</property> - <property name="label" translatable="yes">Longitude:</property> -@@ -1269,6 +1102,57 @@ South</property> - <property name="y_options"></property> - </packing> - </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox55"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkEntry" id="edit-location-name-entry"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="editable">True</property> -+ <property name="visibility">True</property> -+ <property name="max_length">0</property> -+ <property name="text" translatable="yes"></property> -+ <property name="has_frame">True</property> -+ <property name="invisible_char">●</property> -+ <property name="activates_default">False</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find_location_button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Find...</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="left_attach">1</property> -+ <property name="right_attach">4</property> -+ <property name="top_attach">1</property> -+ <property name="bottom_attach">2</property> -+ <property name="x_options">fill</property> -+ <property name="y_options">fill</property> -+ </packing> -+ </child> - </widget> - <packing> - <property name="padding">0</property> -@@ -1294,60 +1178,33 @@ South</property> - </child> - - <child> -- <widget class="GtkHBox" id="hbox40"> -- <property name="border_width">6</property> -+ <widget class="GtkHButtonBox" id="hbuttonbox20"> - <property name="visible">True</property> -- <property name="homogeneous">False</property> -- <property name="spacing">0</property> -+ <property name="layout_style">GTK_BUTTONBOX_END</property> -+ <property name="spacing">6</property> - - <child> -- <widget class="GtkHButtonBox" id="hbuttonbox12"> -+ <widget class="GtkButton" id="edit-location-cancel-button"> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property> -- <property name="spacing">0</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-cancel</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> - </child> - - <child> -- <widget class="GtkHButtonBox" id="hbuttonbox18"> -+ <widget class="GtkButton" id="edit-location-ok-button"> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_END</property> -- <property name="spacing">6</property> -- -- <child> -- <widget class="GtkButton" id="edit-location-cancel-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-cancel</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -- -- <child> -- <widget class="GtkButton" id="edit-location-ok-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-ok</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-ok</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">True</property> -- <property name="fill">True</property> -- </packing> - </child> - </widget> - <packing> -@@ -1723,4 +1580,245 @@ South</property> - </child> - </widget> - -+<widget class="GtkWindow" id="find-location-window"> -+ <property name="title" translatable="yes"></property> -+ <property name="type">GTK_WINDOW_TOPLEVEL</property> -+ <property name="window_position">GTK_WIN_POS_NONE</property> -+ <property name="modal">False</property> -+ <property name="resizable">True</property> -+ <property name="destroy_with_parent">False</property> -+ <property name="decorated">True</property> -+ <property name="skip_taskbar_hint">False</property> -+ <property name="skip_pager_hint">False</property> -+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> -+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> -+ <property name="focus_on_map">True</property> -+ <property name="urgency_hint">False</property> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox25"> -+ <property name="border_width">12</property> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">24</property> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox26"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkScrolledWindow" id="scrolledwindow11"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> -+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> -+ <property name="shadow_type">GTK_SHADOW_IN</property> -+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -+ -+ <child> -+ <widget class="GtkTreeView" id="find_location_tree"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="headers_visible">False</property> -+ <property name="rules_hint">False</property> -+ <property name="reorderable">False</property> -+ <property name="enable_search">True</property> -+ <property name="fixed_height_mode">False</property> -+ <property name="hover_selection">False</property> -+ <property name="hover_expand">False</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox56"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label221"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">_Find:</property> -+ <property name="use_underline">True</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="mnemonic_widget">find_location_entry</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkEntry" id="find_location_entry"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="editable">True</property> -+ <property name="visibility">True</property> -+ <property name="max_length">0</property> -+ <property name="text" translatable="yes"></property> -+ <property name="has_frame">True</property> -+ <property name="invisible_char">•</property> -+ <property name="activates_default">False</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find_next_location_button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ -+ <child> -+ <widget class="GtkAlignment" id="alignment31"> -+ <property name="visible">True</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xscale">0</property> -+ <property name="yscale">0</property> -+ <property name="top_padding">0</property> -+ <property name="bottom_padding">0</property> -+ <property name="left_padding">0</property> -+ <property name="right_padding">0</property> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox57"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">2</property> -+ -+ <child> -+ <widget class="GtkImage" id="image29"> -+ <property name="visible">True</property> -+ <property name="stock">gtk-find</property> -+ <property name="icon_size">4</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label222"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Find _Next</property> -+ <property name="use_underline">True</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ </child> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHButtonBox" id="hbuttonbox19"> -+ <property name="visible">True</property> -+ <property name="layout_style">GTK_BUTTONBOX_END</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkButton" id="find-location-cancel-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-cancel</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find-location-ok-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-ok</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ </child> -+</widget> -+ - </glade-interface> -diff --git a/data/intlclock.schemas.in b/data/intlclock.schemas.in -index 2ab6772..00fee4f 100644 ---- a/data/intlclock.schemas.in -+++ b/data/intlclock.schemas.in -@@ -89,41 +89,54 @@ - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/show_locations</key> -+ <key>/schemas/apps/intlclock_applet/prefs/cities</key> -+ <owner>clock-applet</owner> -+ <type>list</type> -+ <list_type>string</list_type> -+ <default>[]</default> -+ <locale name="C"> -+ <short>List of cities for the clock.</short> -+ <long> -+ List of cities to display in the international clock. -+ </long> -+ </locale> -+ </schema> -+ -+ <schema> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_locations</key> - <owner>clock-applet</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> -- <short>Show other locations in clock</short> -+ <short>Expand the location section in clock</short> - <long> -- If true, show a list of locations in the international clock. -+ If true, expand the list of locations in the international clock. - </long> - </locale> - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/show_map</key> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_tasks</key> - <owner>clock-applet</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> -- <short>Show world map in clock</short> -+ <short>Expand the tasks section in clock</short> - <long> -- If true, show the world map in the international clock. -+ If true, expand the list of tasks in the international clock. - </long> - </locale> - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/cities</key> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_appointments</key> - <owner>clock-applet</owner> -- <type>list</type> -- <list_type>string</list_type> -- <default>[]</default> -+ <type>bool</type> -+ <default>true</default> - <locale name="C"> -- <short>List of cities for the clock.</short> -+ <short>Expand the appointments section in clock</short> - <long> -- List of cities to display in the international clock. -+ If true, expand the list of appointments in the international clock. - </long> - </locale> - </schema> -diff --git a/intltool-extract.in b/intltool-extract.in -deleted file mode 100755 -index bb6c368..340fc8d ---- a/intltool-extract.in -+++ /dev/null -@@ -1,841 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Extractor --# --# Copyright (C) 2000-2001, 2003 Free Software Foundation. --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License as --# published by the Free Software Foundation; either version 2 of the --# License, or (at your option) any later version. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Kenneth Christiansen <kenneth@gnu.org> --# Darin Adler <darin@bentspoon.com> --# -- --## Release information --my $PROGRAM = "intltool-extract"; --my $PACKAGE = "intltool"; --my $VERSION = "0.35.0"; -- --## Loaded modules --use strict; --use File::Basename; --use Getopt::Long; -- --## Scalars used by the option stuff --my $TYPE_ARG = "0"; --my $LOCAL_ARG = "0"; --my $HELP_ARG = "0"; --my $VERSION_ARG = "0"; --my $UPDATE_ARG = "0"; --my $QUIET_ARG = "0"; --my $SRCDIR_ARG = "."; -- --my $FILE; --my $OUTFILE; -- --my $gettext_type = ""; --my $input; --my %messages = (); --my %loc = (); --my %count = (); --my %comments = (); --my $strcount = 0; -- --my $XMLCOMMENT = ""; -- --## Use this instead of \w for XML files to handle more possible characters. --my $w = "[-A-Za-z0-9._:]"; -- --## Always print first --$| = 1; -- --## Handle options --GetOptions ( -- "type=s" => \$TYPE_ARG, -- "local|l" => \$LOCAL_ARG, -- "help|h" => \$HELP_ARG, -- "version|v" => \$VERSION_ARG, -- "update" => \$UPDATE_ARG, -- "quiet|q" => \$QUIET_ARG, -- "srcdir=s" => \$SRCDIR_ARG, -- ) or &error; -- --&split_on_argument; -- -- --## Check for options. --## This section will check for the different options. -- --sub split_on_argument { -- -- if ($VERSION_ARG) { -- &version; -- -- } elsif ($HELP_ARG) { -- &help; -- -- } elsif ($LOCAL_ARG) { -- &place_local; -- &extract; -- -- } elsif ($UPDATE_ARG) { -- &place_normal; -- &extract; -- -- } elsif (@ARGV > 0) { -- &place_normal; -- &message; -- &extract; -- -- } else { -- &help; -- -- } --} -- --sub place_normal { -- $FILE = $ARGV[0]; -- $OUTFILE = "$FILE.h"; --} -- --sub place_local { -- $FILE = $ARGV[0]; -- $OUTFILE = fileparse($FILE, ()); -- if (!-e "tmp/") { -- system("mkdir tmp/"); -- } -- $OUTFILE = "./tmp/$OUTFILE.h" --} -- --sub determine_type { -- if ($TYPE_ARG =~ /^gettext\/(.*)/) { -- $gettext_type=$1 -- } --} -- --## Sub for printing release information --sub version{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) $VERSION --Copyright (C) 2000, 2003 Free Software Foundation, Inc. --Written by Kenneth Christiansen, 2000. -- --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --## Sub for printing usage information --sub help { -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... [FILENAME] --Generates a header file from an XML source file. -- --It grabs all strings between <_translatable_node> and its end tag in --XML files. Read manpage (man ${PROGRAM}) for more info. -- -- --type=TYPE Specify the file type of FILENAME. Currently supports: -- "gettext/glade", "gettext/ini", "gettext/keys" -- "gettext/rfc822deb", "gettext/schemas", -- "gettext/scheme", "gettext/xml" -- -l, --local Writes output into current working directory -- (conflicts with --update) -- --update Writes output into the same directory the source file -- reside (conflicts with --local) -- --srcdir Root of the source tree -- -v, --version Output version information and exit -- -h, --help Display this help and exit -- -q, --quiet Quiet mode -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- --## Sub for printing error messages --sub error{ -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit; --} -- --sub message { -- print "Generating C format header file for translation.\n" unless $QUIET_ARG; --} -- --sub extract { -- &determine_type; -- -- &convert; -- -- open OUT, ">$OUTFILE"; -- binmode (OUT) if $^O eq 'MSWin32'; -- &msg_write; -- close OUT; -- -- print "Wrote $OUTFILE\n" unless $QUIET_ARG; --} -- --sub convert { -- -- ## Reading the file -- { -- local (*IN); -- local $/; #slurp mode -- open (IN, "<$SRCDIR_ARG/$FILE") || die "can't open $SRCDIR_ARG/$FILE: $!"; -- $input = <IN>; -- } -- -- &type_ini if $gettext_type eq "ini"; -- &type_keys if $gettext_type eq "keys"; -- &type_xml if $gettext_type eq "xml"; -- &type_glade if $gettext_type eq "glade"; -- &type_scheme if $gettext_type eq "scheme"; -- &type_schemas if $gettext_type eq "schemas"; -- &type_rfc822deb if $gettext_type eq "rfc822deb"; --} -- --sub entity_decode_minimal --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- -- return $_; --} -- --sub entity_decode --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- s/</</g; -- s/>/>/g; -- -- return $_; --} -- --sub escape_char --{ -- return '\"' if $_ eq '"'; -- return '\n' if $_ eq "\n"; -- return '\\' if $_ eq '\\'; -- -- return $_; --} -- --sub escape --{ -- my ($string) = @_; -- return join "", map &escape_char, split //, $string; --} -- --sub type_ini { -- ### For generic translatable desktop files ### -- while ($input =~ /^_.*=(.*)$/mg) { -- $messages{$1} = []; -- } --} -- --sub type_keys { -- ### For generic translatable mime/keys files ### -- while ($input =~ /^\s*_\w+=(.*)$/mg) { -- $messages{$1} = []; -- } --} -- --sub type_xml { -- ### For generic translatable XML files ### -- my $tree = readXml($input); -- parseTree(0, $tree); --} -- --sub print_var { -- my $var = shift; -- my $vartype = ref $var; -- -- if ($vartype =~ /ARRAY/) { -- my @arr = @{$var}; -- print "[ "; -- foreach my $el (@arr) { -- print_var($el); -- print ", "; -- } -- print "] "; -- } elsif ($vartype =~ /HASH/) { -- my %hash = %{$var}; -- print "{ "; -- foreach my $key (keys %hash) { -- print "$key => "; -- print_var($hash{$key}); -- print ", "; -- } -- print "} "; -- } else { -- print $var; -- } --} -- --# Same syntax as getAttributeString in intltool-merge.in.in, similar logic (look for ## differences comment) --sub getAttributeString --{ -- my $sub = shift; -- my $do_translate = shift || 1; -- my $language = shift || ""; -- my $translate = shift; -- my $result = ""; -- foreach my $e (reverse(sort(keys %{ $sub }))) { -- my $key = $e; -- my $string = $sub->{$e}; -- my $quote = '"'; -- -- $string =~ s/^[\s]+//; -- $string =~ s/[\s]+$//; -- -- if ($string =~ /^'.*'$/) -- { -- $quote = "'"; -- } -- $string =~ s/^['"]//g; -- $string =~ s/['"]$//g; -- -- ## differences from intltool-merge.in.in -- if ($key =~ /^_/) { -- $comments{entity_decode($string)} = $XMLCOMMENT if $XMLCOMMENT; -- $messages{entity_decode($string)} = []; -- $$translate = 2; -- } -- ## differences end here from intltool-merge.in.in -- $result .= " $key=$quote$string$quote"; -- } -- return $result; --} -- --# Verbatim copy from intltool-merge.in.in --sub getXMLstring --{ -- my $ref = shift; -- my $spacepreserve = shift || 0; -- my @list = @{ $ref }; -- my $result = ""; -- -- my $count = scalar(@list); -- my $attrs = $list[0]; -- my $index = 1; -- -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- -- while ($index < $count) { -- my $type = $list[$index]; -- my $content = $list[$index+1]; -- if (! $type ) { -- # We've got CDATA -- if ($content) { -- # lets strip the whitespace here, and *ONLY* here -- $content =~ s/\s+/ /gs if (!$spacepreserve); -- $result .= $content; -- } -- } elsif ( "$type" ne "1" ) { -- # We've got another element -- $result .= "<$type"; -- $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements -- if ($content) { -- my $subresult = getXMLstring($content, $spacepreserve); -- if ($subresult) { -- $result .= ">".$subresult . "</$type>"; -- } else { -- $result .= "/>"; -- } -- } else { -- $result .= "/>"; -- } -- } -- $index += 2; -- } -- return $result; --} -- --# Verbatim copy from intltool-merge.in.in, except for MULTIPLE_OUTPUT handling removed --# Translate list of nodes if necessary --sub translate_subnodes --{ -- my $fh = shift; -- my $content = shift; -- my $language = shift || ""; -- my $singlelang = shift || 0; -- my $spacepreserve = shift || 0; -- -- my @nodes = @{ $content }; -- -- my $count = scalar(@nodes); -- my $index = 0; -- while ($index < $count) { -- my $type = $nodes[$index]; -- my $rest = $nodes[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } --} -- --# Based on traverse() in intltool-merge.in.in --sub traverse --{ -- my $fh = shift; # unused, to allow us to sync code between -merge and -extract -- my $nodename = shift; -- my $content = shift; -- my $language = shift || ""; -- my $spacepreserve = shift || 0; -- -- if ($nodename && "$nodename" eq "1") { -- $XMLCOMMENT = $content; -- } elsif ($nodename) { -- # element -- my @all = @{ $content }; -- my $attrs = shift @all; -- my $translate = 0; -- my $outattr = getAttributeString($attrs, 1, $language, \$translate); -- -- if ($nodename =~ /^_/) { -- $translate = 1; -- $nodename =~ s/^_//; -- } -- my $lookup = ''; -- -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- if ($translate) { -- $lookup = getXMLstring($content, $spacepreserve); -- if (!$spacepreserve) { -- $lookup =~ s/^\s+//s; -- $lookup =~ s/\s+$//s; -- } -- -- if ($lookup && $translate != 2) { -- $comments{$lookup} = $XMLCOMMENT if $XMLCOMMENT; -- $messages{$lookup} = []; -- } elsif ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } -- } else { -- $XMLCOMMENT = ""; -- my $count = scalar(@all); -- if ($count > 0) { -- my $index = 0; -- while ($index < $count) { -- my $type = $all[$index]; -- my $rest = $all[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } -- } -- } -- $XMLCOMMENT = ""; -- } --} -- -- --# Verbatim copy from intltool-merge.in.in, $fh for compatibility --sub parseTree --{ -- my $fh = shift; -- my $ref = shift; -- my $language = shift || ""; -- -- my $name = shift @{ $ref }; -- my $cont = shift @{ $ref }; -- -- while (!$name || "$name" eq "1") { -- $name = shift @{ $ref }; -- $cont = shift @{ $ref }; -- } -- -- my $spacepreserve = 0; -- my $attrs = @{$cont}[0]; -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- traverse($fh, $name, $cont, $language, $spacepreserve); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_comment --{ -- my $expat = shift; -- my $data = $expat->original_string(); -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $data =~ s/^<!--//s; -- $data =~ s/-->$//s; -- push @$clist, 1 => $data; --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_cdatastart --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 0 => $expat->original_string(); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_cdataend --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $clist->[$pos] .= $expat->original_string(); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_char --{ -- my $expat = shift; -- my $text = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- # Use original_string so that we retain escaped entities -- # in CDATA sections. -- # -- if ($pos > 0 and $clist->[$pos - 1] eq '0') { -- $clist->[$pos] .= $expat->original_string(); -- } else { -- push @$clist, 0 => $expat->original_string(); -- } --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_start --{ -- my $expat = shift; -- my $tag = shift; -- my @origlist = (); -- -- # Use original_string so that we retain escaped entities -- # in attribute values. We must convert the string to an -- # @origlist array to conform to the structure of the Tree -- # Style. -- # -- my @original_array = split /\x/, $expat->original_string(); -- my $source = $expat->original_string(); -- -- # Remove leading tag. -- # -- $source =~ s|^\s*<\s*(\S+)||s; -- -- # Grab attribute key/value pairs and push onto @origlist array. -- # -- while ($source) -- { -- if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s; -- push @origlist, $1; -- push @origlist, '"' . $2 . '"'; -- } -- elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s; -- push @origlist, $1; -- push @origlist, "'" . $2 . "'"; -- } -- else -- { -- last; -- } -- } -- -- my $ol = [ { @origlist } ]; -- -- push @{ $expat->{Lists} }, $expat->{Curlist}; -- push @{ $expat->{Curlist} }, $tag => $ol; -- $expat->{Curlist} = $ol; --} -- --# Copied from intltool-merge.in.in and added comment handler. --sub readXml --{ -- my $xmldoc = shift || return; -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- my $xp = new XML::Parser(Style => 'Tree'); -- $xp->setHandlers(Char => \&intltool_tree_char); -- $xp->setHandlers(Start => \&intltool_tree_start); -- $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart); -- $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend); -- -- ## differences from intltool-merge.in.in -- $xp->setHandlers(Comment => \&intltool_tree_comment); -- ## differences end here from intltool-merge.in.in -- -- my $tree = $xp->parse($xmldoc); -- #print_var($tree); -- --# <foo><!-- comment --><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> --# would be: --# [foo, [{}, 1, "comment", head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, --# [{}, 0, "Howdy", ref, [{}]], 0, "do" ] ] -- -- return $tree; --} -- --sub type_schemas { -- ### For schemas XML files ### -- -- # FIXME: We should handle escaped < (less than) -- while ($input =~ / -- <locale\ name="C">\s* -- (<default>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/default>\s*)? -- (<short>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/short>\s*)? -- (<long>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/long>\s*)? -- <\/locale> -- /sgx) { -- my @totranslate = ($3,$6,$9); -- my @eachcomment = ($2,$5,$8); -- foreach (@totranslate) { -- my $currentcomment = shift @eachcomment; -- next if !$_; -- s/\s+/ /g; -- $messages{entity_decode_minimal($_)} = []; -- $comments{entity_decode_minimal($_)} = $currentcomment if (defined($currentcomment)); -- } -- } --} -- --sub type_rfc822deb { -- ### For rfc822-style Debian configuration files ### -- -- my $lineno = 1; -- my $type = ''; -- while ($input =~ /\G(.*?)(^|\n)(_+)([^:]+):[ \t]*(.*?)(?=\n\S|$)/sg) -- { -- my ($pre, $newline, $underscore, $tag, $text) = ($1, $2, $3, $4, $5); -- while ($pre =~ m/\n/g) -- { -- $lineno ++; -- } -- $lineno += length($newline); -- my @str_list = rfc822deb_split(length($underscore), $text); -- for my $str (@str_list) -- { -- $strcount++; -- $messages{$str} = []; -- $loc{$str} = $lineno; -- $count{$str} = $strcount; -- my $usercomment = ''; -- while($pre =~ s/(^|\n)#([^\n]*)$//s) -- { -- $usercomment = "\n" . $2 . $usercomment; -- } -- $comments{$str} = $tag . $usercomment; -- } -- $lineno += ($text =~ s/\n//g); -- } --} -- --sub rfc822deb_split { -- # Debian defines a special way to deal with rfc822-style files: -- # when a value contain newlines, it consists of -- # 1. a short form (first line) -- # 2. a long description, all lines begin with a space, -- # and paragraphs are separated by a single dot on a line -- # This routine returns an array of all paragraphs, and reformat -- # them. -- # When first argument is 2, the string is a comma separated list of -- # values. -- my $type = shift; -- my $text = shift; -- $text =~ s/^[ \t]//mg; -- return (split(/, */, $text, 0)) if $type ne 1; -- return ($text) if $text !~ /\n/; -- -- $text =~ s/([^\n]*)\n//; -- my @list = ($1); -- my $str = ''; -- for my $line (split (/\n/, $text)) -- { -- chomp $line; -- if ($line =~ /^\.\s*$/) -- { -- # New paragraph -- $str =~ s/\s*$//; -- push(@list, $str); -- $str = ''; -- } -- elsif ($line =~ /^\s/) -- { -- # Line which must not be reformatted -- $str .= "\n" if length ($str) && $str !~ /\n$/; -- $line =~ s/\s+$//; -- $str .= $line."\n"; -- } -- else -- { -- # Continuation line, remove newline -- $str .= " " if length ($str) && $str !~ /\n$/; -- $str .= $line; -- } -- } -- $str =~ s/\s*$//; -- push(@list, $str) if length ($str); -- return @list; --} -- --sub type_glade { -- ### For translatable Glade XML files ### -- -- my $tags = "label|title|text|format|copyright|comments|preview_text|tooltip|message"; -- -- while ($input =~ /<($tags)>([^<]+)<\/($tags)>/sg) { -- # Glade sometimes uses tags that normally mark translatable things for -- # little bits of non-translatable content. We work around this by not -- # translating strings that only includes something like label4 or window1. -- $messages{entity_decode($2)} = [] unless $2 =~ /^(window|label|dialog)[0-9]+$/; -- } -- -- while ($input =~ /<items>(..[^<]*)<\/items>/sg) { -- for my $item (split (/\n/, $1)) { -- $messages{entity_decode($item)} = []; -- } -- } -- -- ## handle new glade files -- while ($input =~ /<(property|atkproperty)\s+[^>]*translatable\s*=\s*"yes"(?:\s+[^>]*comments\s*=\s*"([^"]*)")?[^>]*>([^<]+)<\/\1>/sg) { -- $messages{entity_decode($3)} = [] unless $3 =~ /^(window|label)[0-9]+$/; -- if (defined($2) and !($3 =~ /^(window|label)[0-9]+$/)) { -- $comments{entity_decode($3)} = entity_decode($2) ; -- } -- } -- while ($input =~ /<atkaction\s+action_name="([^>]*)"\s+description="([^>]+)"\/>/sg) { -- $messages{entity_decode_minimal($2)} = []; -- } --} -- --sub type_scheme { -- my ($line, $i, $state, $str, $trcomment, $char); -- for $line (split(/\n/, $input)) { -- $i = 0; -- $state = 0; # 0 - nothing, 1 - string, 2 - translatable string -- while ($i < length($line)) { -- if (substr($line,$i,1) eq "\"") { -- if ($state == 2) { -- $comments{$str} = $trcomment if ($trcomment); -- $messages{$str} = []; -- $str = ''; -- $state = 0; $trcomment = ""; -- } elsif ($state == 1) { -- $str = ''; -- $state = 0; $trcomment = ""; -- } else { -- $state = 1; -- $str = ''; -- if ($i>0 && substr($line,$i-1,1) eq '_') { -- $state = 2; -- } -- } -- } elsif (!$state) { -- if (substr($line,$i,1) eq ";") { -- $trcomment = substr($line,$i+1); -- $trcomment =~ s/^;*\s*//; -- $i = length($line); -- } elsif ($trcomment && substr($line,$i,1) !~ /\s|\(|\)|_/) { -- $trcomment = ""; -- } -- } else { -- if (substr($line,$i,1) eq "\\") { -- $char = substr($line,$i+1,1); -- if ($char ne "\"" && $char ne "\\") { -- $str = $str . "\\"; -- } -- $i++; -- } -- $str = $str . substr($line,$i,1); -- } -- $i++; -- } -- } --} -- --sub msg_write { -- my @msgids; -- if (%count) -- { -- @msgids = sort { $count{$a} <=> $count{$b} } keys %count; -- } -- else -- { -- @msgids = sort keys %messages; -- } -- for my $message (@msgids) -- { -- my $offsetlines = 1; -- $offsetlines++ if $message =~ /%/; -- if (defined ($comments{$message})) -- { -- while ($comments{$message} =~ m/\n/g) -- { -- $offsetlines++; -- } -- } -- print OUT "# ".($loc{$message} - $offsetlines). " \"$FILE\"\n" -- if defined $loc{$message}; -- print OUT "/* ".$comments{$message}." */\n" -- if defined $comments{$message}; -- print OUT "/* xgettext:no-c-format */\n" if $message =~ /%/; -- -- my @lines = split (/\n/, $message, -1); -- for (my $n = 0; $n < @lines; $n++) -- { -- if ($n == 0) -- { -- print OUT "char *s = N_(\""; -- } -- else -- { -- print OUT " \""; -- } -- -- print OUT escape($lines[$n]); -- -- if ($n < @lines - 1) -- { -- print OUT "\\n\"\n"; -- } -- else -- { -- print OUT "\");\n"; -- } -- } -- } --} -- -diff --git a/intltool-extract.in b/intltool-extract.in -new file mode 120000 -index bb6c368..340fc8d ---- /dev/null -+++ b/intltool-extract.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-extract.in -\ No newline at end of file -diff --git a/intltool-merge.in b/intltool-merge.in -deleted file mode 100755 -index d0535ab..2238bbd ---- a/intltool-merge.in -+++ /dev/null -@@ -1,1356 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Merger --# --# Copyright (C) 2000, 2003 Free Software Foundation. --# Copyright (C) 2000, 2001 Eazel, Inc --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License --# version 2 published by the Free Software Foundation. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Maciej Stachowiak <mjs@noisehavoc.org> --# Kenneth Christiansen <kenneth@gnu.org> --# Darin Adler <darin@bentspoon.com> --# --# Proper XML UTF-8'ification written by Cyrille Chepelov <chepelov@calixo.net> --# -- --## Release information --my $PROGRAM = "intltool-merge"; --my $PACKAGE = "intltool"; --my $VERSION = "0.35.0"; -- --## Loaded modules --use strict; --use Getopt::Long; --use Text::Wrap; --use File::Basename; -- --my $must_end_tag = -1; --my $last_depth = -1; --my $translation_depth = -1; --my @tag_stack = (); --my @entered_tag = (); --my @translation_strings = (); --my $leading_space = ""; -- --## Scalars used by the option stuff --my $HELP_ARG = 0; --my $VERSION_ARG = 0; --my $BA_STYLE_ARG = 0; --my $XML_STYLE_ARG = 0; --my $KEYS_STYLE_ARG = 0; --my $DESKTOP_STYLE_ARG = 0; --my $SCHEMAS_STYLE_ARG = 0; --my $RFC822DEB_STYLE_ARG = 0; --my $QUIET_ARG = 0; --my $PASS_THROUGH_ARG = 0; --my $UTF8_ARG = 0; --my $MULTIPLE_OUTPUT = 0; --my $cache_file; -- --## Handle options --GetOptions --( -- "help" => \$HELP_ARG, -- "version" => \$VERSION_ARG, -- "quiet|q" => \$QUIET_ARG, -- "oaf-style|o" => \$BA_STYLE_ARG, ## for compatibility -- "ba-style|b" => \$BA_STYLE_ARG, -- "xml-style|x" => \$XML_STYLE_ARG, -- "keys-style|k" => \$KEYS_STYLE_ARG, -- "desktop-style|d" => \$DESKTOP_STYLE_ARG, -- "schemas-style|s" => \$SCHEMAS_STYLE_ARG, -- "rfc822deb-style|r" => \$RFC822DEB_STYLE_ARG, -- "pass-through|p" => \$PASS_THROUGH_ARG, -- "utf8|u" => \$UTF8_ARG, -- "multiple-output|m" => \$MULTIPLE_OUTPUT, -- "cache|c=s" => \$cache_file -- ) or &error; -- --my $PO_DIR; --my $FILE; --my $OUTFILE; -- --my %po_files_by_lang = (); --my %translations = (); --my $iconv = $ENV{"ICONV"} || $ENV{"INTLTOOL_ICONV"} || "@INTLTOOL_ICONV@"; --my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null'); -- --# Use this instead of \w for XML files to handle more possible characters. --my $w = "[-A-Za-z0-9._:]"; -- --# XML quoted string contents --my $q = "[^\\\"]*"; -- --## Check for options. -- --if ($VERSION_ARG) --{ -- &print_version; --} --elsif ($HELP_ARG) --{ -- &print_help; --} --elsif ($BA_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &ba_merge_translations; -- &finalize; --} --elsif ($XML_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &xml_merge_output; -- &finalize; --} --elsif ($KEYS_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &keys_merge_translations; -- &finalize; --} --elsif ($DESKTOP_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &desktop_merge_translations; -- &finalize; --} --elsif ($SCHEMAS_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &schemas_merge_translations; -- &finalize; --} --elsif ($RFC822DEB_STYLE_ARG && @ARGV > 2) --{ -- &preparation; -- &print_message; -- &rfc822deb_merge_translations; -- &finalize; --} --else --{ -- &print_help; --} -- --exit; -- --## Sub for printing release information --sub print_version --{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) ${VERSION} --Written by Maciej Stachowiak, Darin Adler and Kenneth Christiansen. -- --Copyright (C) 2000-2003 Free Software Foundation, Inc. --Copyright (C) 2000-2001 Eazel, Inc. --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --## Sub for printing usage information --sub print_help --{ -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... PO_DIRECTORY FILENAME OUTPUT_FILE --Generates an output file that includes some localized attributes from an --untranslated source file. -- --Mandatory options: (exactly one must be specified) -- -b, --ba-style includes translations in the bonobo-activation style -- -d, --desktop-style includes translations in the desktop style -- -k, --keys-style includes translations in the keys style -- -s, --schemas-style includes translations in the schemas style -- -r, --rfc822deb-style includes translations in the RFC822 style -- -x, --xml-style includes translations in the standard xml style -- --Other options: -- -u, --utf8 convert all strings to UTF-8 before merging -- (default for everything except RFC822 style) -- -p, --pass-through deprecated, does nothing and issues a warning -- -m, --multiple-output output one localized file per locale, instead of -- a single file containing all localized elements -- -c, --cache=FILE specify cache file name -- (usually \$top_builddir/po/.intltool-merge-cache) -- -q, --quiet suppress most messages -- --help display this help and exit -- --version output version information and exit -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- -- --## Sub for printing error messages --sub print_error --{ -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit; --} -- -- --sub print_message --{ -- print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG; --} -- -- --sub preparation --{ -- $PO_DIR = $ARGV[0]; -- $FILE = $ARGV[1]; -- $OUTFILE = $ARGV[2]; -- -- &gather_po_files; -- &get_translation_database; --} -- --# General-purpose code for looking up translations in .po files -- --sub po_file2lang --{ -- my ($tmp) = @_; -- $tmp =~ s/^.*\/(.*)\.po$/$1/; -- return $tmp; --} -- --sub gather_po_files --{ -- for my $po_file (glob "$PO_DIR/*.po") { -- $po_files_by_lang{po_file2lang($po_file)} = $po_file; -- } --} -- --sub get_local_charset --{ -- my ($encoding) = @_; -- my $alias_file = $ENV{"G_CHARSET_ALIAS"} || "@INTLTOOL_LIBDIR@/charset.alias"; -- -- # seek character encoding aliases in charset.alias (glib) -- -- if (open CHARSET_ALIAS, $alias_file) -- { -- while (<CHARSET_ALIAS>) -- { -- next if /^\#/; -- return $1 if (/^\s*([-._a-zA-Z0-9]+)\s+$encoding\b/i) -- } -- -- close CHARSET_ALIAS; -- } -- -- # if not found, return input string -- -- return $encoding; --} -- --sub get_po_encoding --{ -- my ($in_po_file) = @_; -- my $encoding = ""; -- -- open IN_PO_FILE, $in_po_file or die; -- while (<IN_PO_FILE>) -- { -- ## example: "Content-Type: text/plain; charset=ISO-8859-1\n" -- if (/Content-Type\:.*charset=([-a-zA-Z0-9]+)\\n/) -- { -- $encoding = $1; -- last; -- } -- } -- close IN_PO_FILE; -- -- if (!$encoding) -- { -- print STDERR "Warning: no encoding found in $in_po_file. Assuming ISO-8859-1\n" unless $QUIET_ARG; -- $encoding = "ISO-8859-1"; -- } -- -- system ("$iconv -f $encoding -t UTF-8 <$devnull 2>$devnull"); -- if ($?) { -- $encoding = get_local_charset($encoding); -- } -- -- return $encoding --} -- --sub utf8_sanity_check --{ -- print STDERR "Warning: option --pass-through has been removed.\n" if $PASS_THROUGH_ARG; -- $UTF8_ARG = 1; --} -- --sub get_translation_database --{ -- if ($cache_file) { -- &get_cached_translation_database; -- } else { -- &create_translation_database; -- } --} -- --sub get_newest_po_age --{ -- my $newest_age; -- -- foreach my $file (values %po_files_by_lang) -- { -- my $file_age = -M $file; -- $newest_age = $file_age if !$newest_age || $file_age < $newest_age; -- } -- -- $newest_age = 0 if !$newest_age; -- -- return $newest_age; --} -- --sub create_cache --{ -- print "Generating and caching the translation database\n" unless $QUIET_ARG; -- -- &create_translation_database; -- -- open CACHE, ">$cache_file" || die; -- print CACHE join "\x01", %translations; -- close CACHE; --} -- --sub load_cache --{ -- print "Found cached translation database\n" unless $QUIET_ARG; -- -- my $contents; -- open CACHE, "<$cache_file" || die; -- { -- local $/; -- $contents = <CACHE>; -- } -- close CACHE; -- %translations = split "\x01", $contents; --} -- --sub get_cached_translation_database --{ -- my $cache_file_age = -M $cache_file; -- if (defined $cache_file_age) -- { -- if ($cache_file_age <= &get_newest_po_age) -- { -- &load_cache; -- return; -- } -- print "Found too-old cached translation database\n" unless $QUIET_ARG; -- } -- -- &create_cache; --} -- --sub create_translation_database --{ -- for my $lang (keys %po_files_by_lang) -- { -- my $po_file = $po_files_by_lang{$lang}; -- -- if ($UTF8_ARG) -- { -- my $encoding = get_po_encoding ($po_file); -- -- if (lc $encoding eq "utf-8") -- { -- open PO_FILE, "<$po_file"; -- } -- else -- { -- print "NOTICE: $po_file is not in UTF-8 but $encoding, converting...\n" unless $QUIET_ARG;; -- -- open PO_FILE, "$iconv -f $encoding -t UTF-8 $po_file|"; -- } -- } -- else -- { -- open PO_FILE, "<$po_file"; -- } -- -- my $nextfuzzy = 0; -- my $inmsgid = 0; -- my $inmsgstr = 0; -- my $msgid = ""; -- my $msgstr = ""; -- -- while (<PO_FILE>) -- { -- $nextfuzzy = 1 if /^#, fuzzy/; -- -- if (/^msgid "((\\.|[^\\])*)"/ ) -- { -- $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr; -- $msgid = ""; -- $msgstr = ""; -- -- if ($nextfuzzy) { -- $inmsgid = 0; -- } else { -- $msgid = unescape_po_string($1); -- $inmsgid = 1; -- } -- $inmsgstr = 0; -- $nextfuzzy = 0; -- } -- -- if (/^msgstr "((\\.|[^\\])*)"/) -- { -- $msgstr = unescape_po_string($1); -- $inmsgstr = 1; -- $inmsgid = 0; -- } -- -- if (/^"((\\.|[^\\])*)"/) -- { -- $msgid .= unescape_po_string($1) if $inmsgid; -- $msgstr .= unescape_po_string($1) if $inmsgstr; -- } -- } -- $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr; -- } --} -- --sub finalize --{ --} -- --sub unescape_one_sequence --{ -- my ($sequence) = @_; -- -- return "\\" if $sequence eq "\\\\"; -- return "\"" if $sequence eq "\\\""; -- return "\n" if $sequence eq "\\n"; -- return "\r" if $sequence eq "\\r"; -- return "\t" if $sequence eq "\\t"; -- return "\b" if $sequence eq "\\b"; -- return "\f" if $sequence eq "\\f"; -- return "\a" if $sequence eq "\\a"; -- return chr(11) if $sequence eq "\\v"; # vertical tab, see ascii(7) -- -- return chr(hex($1)) if ($sequence =~ /\\x([0-9a-fA-F]{2})/); -- return chr(oct($1)) if ($sequence =~ /\\([0-7]{3})/); -- -- # FIXME: Is \0 supported as well? Kenneth and Rodney don't want it, see bug #48489 -- -- return $sequence; --} -- --sub unescape_po_string --{ -- my ($string) = @_; -- -- $string =~ s/(\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\.)/unescape_one_sequence($1)/eg; -- -- return $string; --} -- --## NOTE: deal with < - < but not > - > because it seems its ok to have --## > in the entity. For further info please look at #84738. --sub entity_decode --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- s/</</g; -- -- return $_; --} -- --# entity_encode: (string) --# --# Encode the given string to XML format (encode '<' etc). -- --sub entity_encode --{ -- my ($pre_encoded) = @_; -- -- my @list_of_chars = unpack ('C*', $pre_encoded); -- -- # with UTF-8 we only encode minimalistic -- return join ('', map (&entity_encode_int_minimalist, @list_of_chars)); --} -- --sub entity_encode_int_minimalist --{ -- return """ if $_ == 34; -- return "&" if $_ == 38; -- return "'" if $_ == 39; -- return "<" if $_ == 60; -- return chr $_; --} -- --sub entity_encoded_translation --{ -- my ($lang, $string) = @_; -- -- my $translation = $translations{$lang, $string}; -- return $string if !$translation; -- return entity_encode ($translation); --} -- --## XML (bonobo-activation specific) merge code -- --sub ba_merge_translations --{ -- my $source; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">$OUTFILE" or die "can't open $OUTFILE: $!"; -- # Binmode so that selftest works ok if using a native Win32 Perl... -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while ($source =~ s|^(.*?)([ \t]*<\s*$w+\s+($w+\s*=\s*"$q"\s*)+/?>)([ \t]*\n)?||s) -- { -- print OUTPUT $1; -- -- my $node = $2 . "\n"; -- -- my @strings = (); -- $_ = $node; -- while (s/(\s)_($w+\s*=\s*"($q)")/$1$2/s) { -- push @strings, entity_decode($3); -- } -- print OUTPUT; -- -- my %langs; -- for my $string (@strings) -- { -- for my $lang (keys %po_files_by_lang) -- { -- $langs{$lang} = 1 if $translations{$lang, $string}; -- } -- } -- -- for my $lang (sort keys %langs) -- { -- $_ = $node; -- s/(\sname\s*=\s*)"($q)"/$1"$2-$lang"/s; -- s/(\s)_($w+\s*=\s*")($q)"/$1 . $2 . entity_encoded_translation($lang, $3) . '"'/seg; -- print OUTPUT; -- } -- } -- -- print OUTPUT $source; -- -- close OUTPUT; --} -- -- --## XML (non-bonobo-activation) merge code -- -- --# Process tag attributes --# Only parameter is a HASH containing attributes -> values mapping --sub getAttributeString --{ -- my $sub = shift; -- my $do_translate = shift || 0; -- my $language = shift || ""; -- my $result = ""; -- my $translate = shift; -- foreach my $e (reverse(sort(keys %{ $sub }))) { -- my $key = $e; -- my $string = $sub->{$e}; -- my $quote = '"'; -- -- $string =~ s/^[\s]+//; -- $string =~ s/[\s]+$//; -- -- if ($string =~ /^'.*'$/) -- { -- $quote = "'"; -- } -- $string =~ s/^['"]//g; -- $string =~ s/['"]$//g; -- -- if ($do_translate && $key =~ /^_/) { -- $key =~ s|^_||g; -- if ($language) { -- # Handle translation -- my $decode_string = entity_decode($string); -- my $translation = $translations{$language, $decode_string}; -- if ($translation) { -- $translation = entity_encode($translation); -- $string = $translation; -- } -- $$translate = 2; -- } else { -- $$translate = 2 if ($translate && (!$$translate)); # watch not to "overwrite" $translate -- } -- } -- -- $result .= " $key=$quote$string$quote"; -- } -- return $result; --} -- --# Returns a translatable string from XML node, it works on contents of every node in XML::Parser tree --sub getXMLstring --{ -- my $ref = shift; -- my $spacepreserve = shift || 0; -- my @list = @{ $ref }; -- my $result = ""; -- -- my $count = scalar(@list); -- my $attrs = $list[0]; -- my $index = 1; -- -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- -- while ($index < $count) { -- my $type = $list[$index]; -- my $content = $list[$index+1]; -- if (! $type ) { -- # We've got CDATA -- if ($content) { -- # lets strip the whitespace here, and *ONLY* here -- $content =~ s/\s+/ /gs if (!$spacepreserve); -- $result .= $content; -- } -- } elsif ( "$type" ne "1" ) { -- # We've got another element -- $result .= "<$type"; -- $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements -- if ($content) { -- my $subresult = getXMLstring($content, $spacepreserve); -- if ($subresult) { -- $result .= ">".$subresult . "</$type>"; -- } else { -- $result .= "/>"; -- } -- } else { -- $result .= "/>"; -- } -- } -- $index += 2; -- } -- return $result; --} -- --# Translate list of nodes if necessary --sub translate_subnodes --{ -- my $fh = shift; -- my $content = shift; -- my $language = shift || ""; -- my $singlelang = shift || 0; -- my $spacepreserve = shift || 0; -- -- my @nodes = @{ $content }; -- -- my $count = scalar(@nodes); -- my $index = 0; -- while ($index < $count) { -- my $type = $nodes[$index]; -- my $rest = $nodes[$index+1]; -- if ($singlelang) { -- my $oldMO = $MULTIPLE_OUTPUT; -- $MULTIPLE_OUTPUT = 1; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $MULTIPLE_OUTPUT = $oldMO; -- } else { -- traverse($fh, $type, $rest, $language, $spacepreserve); -- } -- $index += 2; -- } --} -- --sub isWellFormedXmlFragment --{ -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- -- my $fragment = shift; -- return 0 if (!$fragment); -- -- $fragment = "<root>$fragment</root>"; -- my $xp = new XML::Parser(Style => 'Tree'); -- my $tree = 0; -- eval { $tree = $xp->parse($fragment); }; -- return $tree; --} -- --sub traverse --{ -- my $fh = shift; -- my $nodename = shift; -- my $content = shift; -- my $language = shift || ""; -- my $spacepreserve = shift || 0; -- -- if (!$nodename) { -- if ($content =~ /^[\s]*$/) { -- $leading_space .= $content; -- } -- print $fh $content; -- } else { -- # element -- my @all = @{ $content }; -- my $attrs = shift @all; -- my $translate = 0; -- my $outattr = getAttributeString($attrs, 1, $language, \$translate); -- -- if ($nodename =~ /^_/) { -- $translate = 1; -- $nodename =~ s/^_//; -- } -- my $lookup = ''; -- -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- print $fh "<$nodename", $outattr; -- if ($translate) { -- $lookup = getXMLstring($content, $spacepreserve); -- if (!$spacepreserve) { -- $lookup =~ s/^\s+//s; -- $lookup =~ s/\s+$//s; -- } -- -- if ($lookup || $translate == 2) { -- my $translation = $translations{$language, $lookup} if isWellFormedXmlFragment($translations{$language, $lookup}); -- if ($MULTIPLE_OUTPUT && ($translation || $translate == 2)) { -- $translation = $lookup if (!$translation); -- print $fh " xml:lang=\"", $language, "\"" if $language; -- print $fh ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } else { -- print $fh $translation; -- } -- print $fh "</$nodename>"; -- -- return; # this means there will be no same translation with xml:lang="$language"... -- # if we want them both, just remove this "return" -- } else { -- print $fh ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } else { -- print $fh $lookup; -- } -- print $fh "</$nodename>"; -- } -- } else { -- print $fh "/>"; -- } -- -- for my $lang (sort keys %po_files_by_lang) { -- if ($MULTIPLE_OUTPUT && $lang ne "$language") { -- next; -- } -- if ($lang) { -- # Handle translation -- # -- my $translate = 0; -- my $localattrs = getAttributeString($attrs, 1, $lang, \$translate); -- my $translation = $translations{$lang, $lookup} if isWellFormedXmlFragment($translations{$lang, $lookup}); -- if ($translate && !$translation) { -- $translation = $lookup; -- } -- -- if ($translation || $translate) { -- print $fh "\n"; -- $leading_space =~ s/.*\n//g; -- print $fh $leading_space; -- print $fh "<", $nodename, " xml:lang=\"", $lang, "\"", $localattrs, ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $lang, 1, $spacepreserve); -- } else { -- print $fh $translation; -- } -- print $fh "</$nodename>"; -- } -- } -- } -- -- } else { -- my $count = scalar(@all); -- if ($count > 0) { -- print $fh ">"; -- my $index = 0; -- while ($index < $count) { -- my $type = $all[$index]; -- my $rest = $all[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } -- print $fh "</$nodename>"; -- } else { -- print $fh "/>"; -- } -- } -- } --} -- --sub intltool_tree_comment --{ -- my $expat = shift; -- my $data = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 1 => $data; --} -- --sub intltool_tree_cdatastart --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 0 => $expat->original_string(); --} -- --sub intltool_tree_cdataend --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $clist->[$pos] .= $expat->original_string(); --} -- --sub intltool_tree_char --{ -- my $expat = shift; -- my $text = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- # Use original_string so that we retain escaped entities -- # in CDATA sections. -- # -- if ($pos > 0 and $clist->[$pos - 1] eq '0') { -- $clist->[$pos] .= $expat->original_string(); -- } else { -- push @$clist, 0 => $expat->original_string(); -- } --} -- --sub intltool_tree_start --{ -- my $expat = shift; -- my $tag = shift; -- my @origlist = (); -- -- # Use original_string so that we retain escaped entities -- # in attribute values. We must convert the string to an -- # @origlist array to conform to the structure of the Tree -- # Style. -- # -- my @original_array = split /\x/, $expat->original_string(); -- my $source = $expat->original_string(); -- -- # Remove leading tag. -- # -- $source =~ s|^\s*<\s*(\S+)||s; -- -- # Grab attribute key/value pairs and push onto @origlist array. -- # -- while ($source) -- { -- if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s; -- push @origlist, $1; -- push @origlist, '"' . $2 . '"'; -- } -- elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s; -- push @origlist, $1; -- push @origlist, "'" . $2 . "'"; -- } -- else -- { -- last; -- } -- } -- -- my $ol = [ { @origlist } ]; -- -- push @{ $expat->{Lists} }, $expat->{Curlist}; -- push @{ $expat->{Curlist} }, $tag => $ol; -- $expat->{Curlist} = $ol; --} -- --sub readXml --{ -- my $filename = shift || return; -- if(!-f $filename) { -- die "ERROR Cannot find filename: $filename\n"; -- } -- -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- my $xp = new XML::Parser(Style => 'Tree'); -- $xp->setHandlers(Char => \&intltool_tree_char); -- $xp->setHandlers(Start => \&intltool_tree_start); -- $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart); -- $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend); -- my $tree = $xp->parsefile($filename); -- --# <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> --# would be: --# [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [{}, --# 0, "Howdy", ref, [{}]], 0, "do" ] ] -- -- return $tree; --} -- --sub print_header --{ -- my $infile = shift; -- my $fh = shift; -- my $source; -- -- if(!-f $infile) { -- die "ERROR Cannot find filename: $infile\n"; -- } -- -- print $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n}; -- { -- local $/; -- open DOCINPUT, "<${FILE}" or die; -- $source = <DOCINPUT>; -- close DOCINPUT; -- } -- if ($source =~ /(<!DOCTYPE.*\[.*\]\s*>)/s) -- { -- print $fh "$1\n"; -- } -- elsif ($source =~ /(<!DOCTYPE[^>]*>)/s) -- { -- print $fh "$1\n"; -- } --} -- --sub parseTree --{ -- my $fh = shift; -- my $ref = shift; -- my $language = shift || ""; -- -- my $name = shift @{ $ref }; -- my $cont = shift @{ $ref }; -- -- while (!$name || "$name" eq "1") { -- $name = shift @{ $ref }; -- $cont = shift @{ $ref }; -- } -- -- my $spacepreserve = 0; -- my $attrs = @{$cont}[0]; -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- traverse($fh, $name, $cont, $language, $spacepreserve); --} -- --sub xml_merge_output --{ -- my $source; -- -- if ($MULTIPLE_OUTPUT) { -- for my $lang (sort keys %po_files_by_lang) { -- if ( ! -e $lang ) { -- mkdir $lang or die "Cannot create subdirectory $lang: $!\n"; -- } -- open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n"; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- my $tree = readXml($FILE); -- print_header($FILE, \*OUTPUT); -- parseTree(\*OUTPUT, $tree, $lang); -- close OUTPUT; -- print "CREATED $lang/$OUTFILE\n" unless $QUIET_ARG; -- } -- } -- open OUTPUT, ">$OUTFILE" or die "Cannot open $OUTFILE: $!\n"; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- my $tree = readXml($FILE); -- print_header($FILE, \*OUTPUT); -- parseTree(\*OUTPUT, $tree); -- close OUTPUT; -- print "CREATED $OUTFILE\n" unless $QUIET_ARG; --} -- --sub keys_merge_translations --{ -- open INPUT, "<${FILE}" or die; -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while (<INPUT>) -- { -- if (s/^(\s*)_(\w+=(.*))/$1$2/) -- { -- my $string = $3; -- -- print OUTPUT; -- -- my $non_translated_line = $_; -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $translation = $translations{$lang, $string}; -- next if !$translation; -- -- $_ = $non_translated_line; -- s/(\w+)=.*/[$lang]$1=$translation/; -- print OUTPUT; -- } -- } -- else -- { -- print OUTPUT; -- } -- } -- -- close OUTPUT; -- close INPUT; --} -- --sub desktop_merge_translations --{ -- open INPUT, "<${FILE}" or die; -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while (<INPUT>) -- { -- if (s/^(\s*)_(\w+=(.*))/$1$2/) -- { -- my $string = $3; -- -- print OUTPUT; -- -- my $non_translated_line = $_; -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $translation = $translations{$lang, $string}; -- next if !$translation; -- -- $_ = $non_translated_line; -- s/(\w+)=.*/${1}[$lang]=$translation/; -- print OUTPUT; -- } -- } -- else -- { -- print OUTPUT; -- } -- } -- -- close OUTPUT; -- close INPUT; --} -- --sub schemas_merge_translations --{ -- my $source; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">$OUTFILE" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- # FIXME: support attribute translations -- -- # Empty nodes never need translation, so unmark all of them. -- # For example, <_foo/> is just replaced by <foo/>. -- $source =~ s|<\s*_($w+)\s*/>|<$1/>|g; -- -- while ($source =~ s/ -- (.*?) -- (\s+)(<locale\ name="C">(\s*) -- (<default>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/default>)?(\s*) -- (<short>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/short>)?(\s*) -- (<long>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/long>)?(\s*) -- <\/locale>) -- //sx) -- { -- print OUTPUT $1; -- -- my $locale_start_spaces = $2 ? $2 : ''; -- my $default_spaces = $4 ? $4 : ''; -- my $short_spaces = $7 ? $7 : ''; -- my $long_spaces = $10 ? $10 : ''; -- my $locale_end_spaces = $13 ? $13 : ''; -- my $c_default_block = $3 ? $3 : ''; -- my $default_string = $6 ? $6 : ''; -- my $short_string = $9 ? $9 : ''; -- my $long_string = $12 ? $12 : ''; -- -- print OUTPUT "$locale_start_spaces$c_default_block"; -- -- $default_string =~ s/\s+/ /g; -- $default_string = entity_decode($default_string); -- $short_string =~ s/\s+/ /g; -- $short_string = entity_decode($short_string); -- $long_string =~ s/\s+/ /g; -- $long_string = entity_decode($long_string); -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $default_translation = $translations{$lang, $default_string}; -- my $short_translation = $translations{$lang, $short_string}; -- my $long_translation = $translations{$lang, $long_string}; -- -- next if (!$default_translation && !$short_translation && -- !$long_translation); -- -- print OUTPUT "\n$locale_start_spaces<locale name=\"$lang\">"; -- -- print OUTPUT "$default_spaces"; -- -- if ($default_translation) -- { -- $default_translation = entity_encode($default_translation); -- print OUTPUT "<default>$default_translation</default>"; -- } -- -- print OUTPUT "$short_spaces"; -- -- if ($short_translation) -- { -- $short_translation = entity_encode($short_translation); -- print OUTPUT "<short>$short_translation</short>"; -- } -- -- print OUTPUT "$long_spaces"; -- -- if ($long_translation) -- { -- $long_translation = entity_encode($long_translation); -- print OUTPUT "<long>$long_translation</long>"; -- } -- -- print OUTPUT "$locale_end_spaces</locale>"; -- } -- } -- -- print OUTPUT $source; -- -- close OUTPUT; --} -- --sub rfc822deb_merge_translations --{ -- my %encodings = (); -- for my $lang (keys %po_files_by_lang) { -- $encodings{$lang} = ($UTF8_ARG ? 'UTF-8' : get_po_encoding($po_files_by_lang{$lang})); -- } -- -- my $source; -- -- $Text::Wrap::huge = 'overflow'; -- $Text::Wrap::break = qr/\n|\s(?=\S)/; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while ($source =~ /(^|\n+)(_*)([^:\s]+)(:[ \t]*)(.*?)(?=\n[\S\n]|$)/sg) -- { -- my $sep = $1; -- my $non_translated_line = $3.$4; -- my $string = $5; -- my $underscore = length($2); -- next if $underscore eq 0 && $non_translated_line =~ /^#/; -- # Remove [] dummy strings -- my $stripped = $string; -- $stripped =~ s/\[\s[^\[\]]*\],/,/g if $underscore eq 2; -- $stripped =~ s/\[\s[^\[\]]*\]$//; -- $non_translated_line .= $stripped; -- -- print OUTPUT $sep.$non_translated_line; -- -- if ($underscore) -- { -- my @str_list = rfc822deb_split($underscore, $string); -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $is_translated = 1; -- my $str_translated = ''; -- my $first = 1; -- -- for my $str (@str_list) -- { -- my $translation = $translations{$lang, $str}; -- -- if (!$translation) -- { -- $is_translated = 0; -- last; -- } -- -- # $translation may also contain [] dummy -- # strings, mostly to indicate an empty string -- $translation =~ s/\[\s[^\[\]]*\]$//; -- -- if ($first) -- { -- if ($underscore eq 2) -- { -- $str_translated .= $translation; -- } -- else -- { -- $str_translated .= -- Text::Tabs::expand($translation) . -- "\n"; -- } -- } -- else -- { -- if ($underscore eq 2) -- { -- $str_translated .= ', ' . $translation; -- } -- else -- { -- $str_translated .= Text::Tabs::expand( -- Text::Wrap::wrap(' ', ' ', $translation)) . -- "\n .\n"; -- } -- } -- $first = 0; -- -- # To fix some problems with Text::Wrap::wrap -- $str_translated =~ s/(\n )+\n/\n .\n/g; -- } -- next unless $is_translated; -- -- $str_translated =~ s/\n \.\n$//; -- $str_translated =~ s/\s+$//; -- -- $_ = $non_translated_line; -- s/^(\w+):\s*.*/$sep${1}-$lang.$encodings{$lang}: $str_translated/s; -- print OUTPUT; -- } -- } -- } -- print OUTPUT "\n"; -- -- close OUTPUT; -- close INPUT; --} -- --sub rfc822deb_split --{ -- # Debian defines a special way to deal with rfc822-style files: -- # when a value contain newlines, it consists of -- # 1. a short form (first line) -- # 2. a long description, all lines begin with a space, -- # and paragraphs are separated by a single dot on a line -- # This routine returns an array of all paragraphs, and reformat -- # them. -- # When first argument is 2, the string is a comma separated list of -- # values. -- my $type = shift; -- my $text = shift; -- $text =~ s/^[ \t]//mg; -- return (split(/, */, $text, 0)) if $type ne 1; -- return ($text) if $text !~ /\n/; -- -- $text =~ s/([^\n]*)\n//; -- my @list = ($1); -- my $str = ''; -- -- for my $line (split (/\n/, $text)) -- { -- chomp $line; -- if ($line =~ /^\.\s*$/) -- { -- # New paragraph -- $str =~ s/\s*$//; -- push(@list, $str); -- $str = ''; -- } -- elsif ($line =~ /^\s/) -- { -- # Line which must not be reformatted -- $str .= "\n" if length ($str) && $str !~ /\n$/; -- $line =~ s/\s+$//; -- $str .= $line."\n"; -- } -- else -- { -- # Continuation line, remove newline -- $str .= " " if length ($str) && $str !~ /\n$/; -- $str .= $line; -- } -- } -- -- $str =~ s/\s*$//; -- push(@list, $str) if length ($str); -- -- return @list; --} -- -diff --git a/intltool-merge.in b/intltool-merge.in -new file mode 120000 -index d0535ab..2238bbd ---- /dev/null -+++ b/intltool-merge.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-merge.in -\ No newline at end of file -diff --git a/intltool-update.in b/intltool-update.in -deleted file mode 100755 -index 661d8fe..0b1800f ---- a/intltool-update.in -+++ /dev/null -@@ -1,1089 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Updater --# --# Copyright (C) 2000-2003 Free Software Foundation. --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License --# version 2 published by the Free Software Foundation. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Kenneth Christiansen <kenneth@gnu.org> --# Maciej Stachowiak --# Darin Adler <darin@bentspoon.com> -- --## Release information --my $PROGRAM = "intltool-update"; --my $VERSION = "0.35.0"; --my $PACKAGE = "intltool"; -- --## Loaded modules --use strict; --use Getopt::Long; --use Cwd; --use File::Copy; --use File::Find; -- --## Scalars used by the option stuff --my $HELP_ARG = 0; --my $VERSION_ARG = 0; --my $DIST_ARG = 0; --my $POT_ARG = 0; --my $HEADERS_ARG = 0; --my $MAINTAIN_ARG = 0; --my $REPORT_ARG = 0; --my $VERBOSE = 0; --my $GETTEXT_PACKAGE = ""; --my $OUTPUT_FILE = ""; -- --my @languages; --my %varhash = (); --my %po_files_by_lang = (); -- --# Regular expressions to categorize file types. --# FIXME: Please check if the following is correct -- --my $xml_support = --"xml(?:\\.in)*|". # http://www.w3.org/XML/ (Note: .in is not required) --"ui|". # Bonobo specific - User Interface desc. files --"lang|". # ? --"glade2?(?:\\.in)*|". # Glade specific - User Interface desc. files (Note: .in is not required) --"scm(?:\\.in)*|". # ? (Note: .in is not required) --"oaf(?:\\.in)+|". # DEPRECATED: Replaces by Bonobo .server files --"etspec|". # ? --"server(?:\\.in)+|". # Bonobo specific --"sheet(?:\\.in)+|". # ? --"schemas(?:\\.in)+|". # GConf specific --"pong(?:\\.in)+|". # DEPRECATED: PONG is not used [by GNOME] any longer. --"kbd(?:\\.in)+"; # GOK specific. -- --my $ini_support = --"icon(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec --"desktop(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec --"caves(?:\\.in)+|". # GNOME Games specific --"directory(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec --"soundlist(?:\\.in)+|". # GNOME specific --"keys(?:\\.in)+|". # GNOME Mime database specific --"theme(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec --"service(?:\\.in)+"; # DBus specific -- --my $buildin_gettext_support = --"c|y|cs|cc|cpp|c\\+\\+|h|hh|gob|py"; -- --## Always flush buffer when printing --$| = 1; -- --## Sometimes the source tree will be rooted somewhere else. --my $SRCDIR = "."; --my $POTFILES_in; -- --$SRCDIR = $ENV{"srcdir"} if $ENV{"srcdir"}; --$POTFILES_in = "<$SRCDIR/POTFILES.in"; -- --my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null'); -- --## Handle options --GetOptions --( -- "help" => \$HELP_ARG, -- "version" => \$VERSION_ARG, -- "dist|d" => \$DIST_ARG, -- "pot|p" => \$POT_ARG, -- "headers|s" => \$HEADERS_ARG, -- "maintain|m" => \$MAINTAIN_ARG, -- "report|r" => \$REPORT_ARG, -- "verbose|x" => \$VERBOSE, -- "gettext-package|g=s" => \$GETTEXT_PACKAGE, -- "output-file|o=s" => \$OUTPUT_FILE, -- ) or &Console_WriteError_InvalidOption; -- --&Console_Write_IntltoolHelp if $HELP_ARG; --&Console_Write_IntltoolVersion if $VERSION_ARG; -- --my $arg_count = ($DIST_ARG > 0) -- + ($POT_ARG > 0) -- + ($HEADERS_ARG > 0) -- + ($MAINTAIN_ARG > 0) -- + ($REPORT_ARG > 0); -- --&Console_Write_IntltoolHelp if $arg_count > 1; -- --# --version and --help don't require a module name --my $MODULE = $GETTEXT_PACKAGE || &FindPackageName || "unknown"; -- --if ($POT_ARG) --{ -- &GenerateHeaders; -- &GeneratePOTemplate; --} --elsif ($HEADERS_ARG) --{ -- &GenerateHeaders; --} --elsif ($MAINTAIN_ARG) --{ -- &FindLeftoutFiles; --} --elsif ($REPORT_ARG) --{ -- &GenerateHeaders; -- &GeneratePOTemplate; -- &Console_Write_CoverageReport; --} --elsif ((defined $ARGV[0]) && $ARGV[0] =~ /^[a-z]/) --{ -- my $lang = $ARGV[0]; -- -- ## Report error if the language file supplied -- ## to the command line is non-existent -- &Console_WriteError_NotExisting("$SRCDIR/$lang.po") -- if ! -s "$SRCDIR/$lang.po"; -- -- if (!$DIST_ARG) -- { -- print "Working, please wait..." if $VERBOSE; -- &GenerateHeaders; -- &GeneratePOTemplate; -- } -- &POFile_Update ($lang, $OUTPUT_FILE); -- &Console_Write_TranslationStatus ($lang, $OUTPUT_FILE); --} --else --{ -- &Console_Write_IntltoolHelp; --} -- --exit; -- --######### -- --sub Console_Write_IntltoolVersion --{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) $VERSION --Written by Kenneth Christiansen, Maciej Stachowiak, and Darin Adler. -- --Copyright (C) 2000-2003 Free Software Foundation, Inc. --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --sub Console_Write_IntltoolHelp --{ -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... LANGCODE --Updates PO template files and merge them with the translations. -- --Mode of operation (only one is allowed): -- -p, --pot generate the PO template only -- -s, --headers generate the header files in POTFILES.in -- -m, --maintain search for left out files from POTFILES.in -- -r, --report display a status report for the module -- -d, --dist merge LANGCODE.po with existing PO template -- --Extra options: -- -g, --gettext-package=NAME override PO template name, useful with --pot -- -o, --output-file=FILE write merged translation to FILE -- -x, --verbose display lots of feedback -- --help display this help and exit -- --version output version information and exit -- --Examples of use: --${PROGRAM} --pot just create a new PO template --${PROGRAM} xy create new PO template and merge xy.po with it -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- --sub echo_n --{ -- my $str = shift; -- my $ret = `echo "$str"`; -- -- $ret =~ s/\n$//; # do we need the "s" flag? -- -- return $ret; --} -- --sub POFile_DetermineType ($) --{ -- my $type = $_; -- my $gettext_type; -- -- my $xml_regex = "(?:" . $xml_support . ")"; -- my $ini_regex = "(?:" . $ini_support . ")"; -- my $buildin_regex = "(?:" . $buildin_gettext_support . ")"; -- -- if ($type =~ /\[type: gettext\/([^\]].*)]/) -- { -- $gettext_type=$1; -- } -- elsif ($type =~ /schemas(\.in)+$/) -- { -- $gettext_type="schemas"; -- } -- elsif ($type =~ /glade2?(\.in)*$/) -- { -- $gettext_type="glade"; -- } -- elsif ($type =~ /scm(\.in)*$/) -- { -- $gettext_type="scheme"; -- } -- elsif ($type =~ /keys(\.in)+$/) -- { -- $gettext_type="keys"; -- } -- -- # bucket types -- -- elsif ($type =~ /$xml_regex$/) -- { -- $gettext_type="xml"; -- } -- elsif ($type =~ /$ini_regex$/) -- { -- $gettext_type="ini"; -- } -- elsif ($type =~ /$buildin_regex$/) -- { -- $gettext_type="buildin"; -- } -- else -- { -- $gettext_type="unknown"; -- } -- -- return "gettext\/$gettext_type"; --} -- --sub TextFile_DetermineEncoding ($) --{ -- my $gettext_code="ASCII"; # All files are ASCII by default -- my $filetype=`file $_ | cut -d ' ' -f 2`; -- -- if ($? eq "0") -- { -- if ($filetype =~ /^(ISO|UTF)/) -- { -- chomp ($gettext_code = $filetype); -- } -- elsif ($filetype =~ /^XML/) -- { -- $gettext_code="UTF-8"; # We asume that .glade and other .xml files are UTF-8 -- } -- } -- -- return $gettext_code; --} -- --sub isNotValidMissing --{ -- my ($file) = @_; -- -- return if $file =~ /^\{arch\}\/.*$/; -- return if $file =~ /^$varhash{"PACKAGE"}-$varhash{"VERSION"}\/.*$/; --} -- --sub FindLeftoutFiles --{ -- my (@buf_i18n_plain, -- @buf_i18n_xml, -- @buf_i18n_xml_unmarked, -- @buf_i18n_ini, -- @buf_potfiles, -- @buf_potfiles_ignore, -- @buf_allfiles, -- @buf_allfiles_sorted, -- @buf_potfiles_sorted -- ); -- -- ## Search and find all translatable files -- find sub { -- push @buf_i18n_plain, "$File::Find::name" if /\.($buildin_gettext_support)$/; -- push @buf_i18n_xml, "$File::Find::name" if /\.($xml_support)$/; -- push @buf_i18n_ini, "$File::Find::name" if /\.($ini_support)$/; -- push @buf_i18n_xml_unmarked, "$File::Find::name" if /\.(schemas(\.in)+)$/; -- }, ".."; -- -- -- open POTFILES, $POTFILES_in or die "$PROGRAM: there's no POTFILES.in!\n"; -- @buf_potfiles = grep !/^(#|\s*$)/, <POTFILES>; -- close POTFILES; -- -- foreach (@buf_potfiles) { -- s/^\[.*]\s*//; -- } -- -- print "Searching for missing translatable files...\n" if $VERBOSE; -- -- ## Check if we should ignore some found files, when -- ## comparing with POTFILES.in -- foreach my $ignore ("POTFILES.skip", "POTFILES.ignore") -- { -- (-s $ignore) or next; -- -- if ("$ignore" eq "POTFILES.ignore") -- { -- print "The usage of POTFILES.ignore is deprecated. Please consider moving the\n". -- "content of this file to POTFILES.skip.\n"; -- } -- -- print "Found $ignore: Ignoring files...\n" if $VERBOSE; -- open FILE, "<$ignore" or die "ERROR: Failed to open $ignore!\n"; -- -- while (<FILE>) -- { -- push @buf_potfiles_ignore, $_ unless /^(#|\s*$)/; -- } -- close FILE; -- -- @buf_potfiles = (@buf_potfiles_ignore, @buf_potfiles); -- } -- -- foreach my $file (@buf_i18n_plain) -- { -- my $in_comment = 0; -- my $in_macro = 0; -- -- open FILE, "<$file"; -- while (<FILE>) -- { -- # Handle continued multi-line comment. -- if ($in_comment) -- { -- next unless s-.*\*/--; -- $in_comment = 0; -- } -- -- # Handle continued macro. -- if ($in_macro) -- { -- $in_macro = 0 unless /\\$/; -- next; -- } -- -- # Handle start of macro (or any preprocessor directive). -- if (/^\s*\#/) -- { -- $in_macro = 1 if /^([^\\]|\\.)*\\$/; -- next; -- } -- -- # Handle comments and quoted text. -- while (m-(/\*|//|\'|\")-) # \' and \" keep emacs perl mode happy -- { -- my $match = $1; -- if ($match eq "/*") -- { -- if (!s-/\*.*?\*/--) -- { -- s-/\*.*--; -- $in_comment = 1; -- } -- } -- elsif ($match eq "//") -- { -- s-//.*--; -- } -- else # ' or " -- { -- if (!s-$match([^\\]|\\.)*?$match-QUOTEDTEXT-) -- { -- warn "mismatched quotes at line $. in $file\n"; -- s-$match.*--; -- } -- } -- } -- -- if (/\.GetString ?\(QUOTEDTEXT/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- ## Remove the first 3 chars and add newline -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- -- if (/_\(QUOTEDTEXT/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- ## Remove the first 3 chars and add newline -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_xml) -- { -- open FILE, "<$file"; -- -- while (<FILE>) -- { -- # FIXME: share the pattern matching code with intltool-extract -- if (/\s_[-A-Za-z0-9._:]+\s*=\s*\"([^"]+)\"/ || /<_[^>]+>/ || /translatable=\"yes\"/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_ini) -- { -- open FILE, "<$file"; -- while (<FILE>) -- { -- if (/_(.*)=/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_xml_unmarked) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- } -- -- -- @buf_allfiles_sorted = sort (@buf_allfiles); -- @buf_potfiles_sorted = sort (@buf_potfiles); -- -- my %in2; -- foreach (@buf_potfiles_sorted) -- { -- $in2{$_} = 1; -- } -- -- my @result; -- -- foreach (@buf_allfiles_sorted) -- { -- if (!exists($in2{$_})) -- { -- push @result, $_ -- } -- } -- -- my @buf_potfiles_notexist; -- -- foreach (@buf_potfiles_sorted) -- { -- chomp (my $dummy = $_); -- if ("$dummy" ne "" and ! -f "../$dummy") -- { -- push @buf_potfiles_notexist, $_; -- } -- } -- -- ## Save file with information about the files missing -- ## if any, and give information about this procedure. -- if (@result + @buf_potfiles_notexist > 0) -- { -- if (@result) -- { -- print "\n" if $VERBOSE; -- unlink "missing"; -- open OUT, ">missing"; -- print OUT @result; -- close OUT; -- warn "\e[1mThe following files contain translations and are currently not in use. Please\e[0m\n". -- "\e[1mconsider adding these to the POTFILES.in file, located in the po/ directory.\e[0m\n\n"; -- print STDERR @result, "\n"; -- warn "If some of these files are left out on purpose then please add them to\n". -- "POTFILES.skip instead of POTFILES.in. A file \e[1m'missing'\e[0m containing this list\n". -- "of left out files has been written in the current directory.\n"; -- } -- if (@buf_potfiles_notexist) -- { -- unlink "notexist"; -- open OUT, ">notexist"; -- print OUT @buf_potfiles_notexist; -- close OUT; -- warn "\n" if ($VERBOSE or @result); -- warn "\e[1mThe following files do not exist anymore:\e[0m\n\n"; -- warn @buf_potfiles_notexist, "\n"; -- warn "Please remove them from POTFILES.in or POTFILES.skip. A file \e[1m'notexist'\e[0m\n". -- "containing this list of absent files has been written in the current directory.\n"; -- } -- } -- -- ## If there is nothing to complain about, notify the user -- else { -- print "\nAll files containing translations are present in POTFILES.in.\n" if $VERBOSE; -- } --} -- --sub Console_WriteError_InvalidOption --{ -- ## Handle invalid arguments -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit 1; --} -- --sub GenerateHeaders --{ -- my $EXTRACT = "@INTLTOOL_EXTRACT@"; -- chomp $EXTRACT; -- -- $EXTRACT = $ENV{"INTLTOOL_EXTRACT"} if $ENV{"INTLTOOL_EXTRACT"}; -- -- ## Generate the .h header files, so we can allow glade and -- ## xml translation support -- if (! -x "$EXTRACT") -- { -- print STDERR "\n *** The intltool-extract script wasn't found!" -- ."\n *** Without it, intltool-update can not generate files.\n"; -- exit; -- } -- else -- { -- open (FILE, $POTFILES_in) or die "$PROGRAM: POTFILES.in not found.\n"; -- -- while (<FILE>) -- { -- chomp; -- next if /^\[\s*encoding/; -- -- ## Find xml files in POTFILES.in and generate the -- ## files with help from the extract script -- -- my $gettext_type= &POFile_DetermineType ($1); -- -- if (/\.($xml_support|$ini_support)$/ || /^\[/) -- { -- s/^\[[^\[].*]\s*//; -- -- my $filename = "../$_"; -- -- if ($VERBOSE) -- { -- system ($EXTRACT, "--update", "--srcdir=$SRCDIR", -- "--type=$gettext_type", $filename); -- } -- else -- { -- system ($EXTRACT, "--update", "--type=$gettext_type", -- "--srcdir=$SRCDIR", "--quiet", $filename); -- } -- } -- } -- close FILE; -- } --} -- --# --# Generate .pot file from POTFILES.in --# --sub GeneratePOTemplate --{ -- my $XGETTEXT = $ENV{"XGETTEXT"} || "@INTLTOOL_XGETTEXT@"; -- my $XGETTEXT_ARGS = $ENV{"XGETTEXT_ARGS"} || ''; -- chomp $XGETTEXT; -- -- if (! -x $XGETTEXT) -- { -- print STDERR " *** xgettext is not found on this system!\n". -- " *** Without it, intltool-update can not extract strings.\n"; -- exit; -- } -- -- print "Building $MODULE.pot...\n" if $VERBOSE; -- -- open INFILE, $POTFILES_in; -- unlink "POTFILES.in.temp"; -- open OUTFILE, ">POTFILES.in.temp" or die("Cannot open POTFILES.in.temp for writing"); -- -- my $gettext_support_nonascii = 0; -- -- # checks for GNU gettext >= 0.12 -- my $dummy = `$XGETTEXT --version --from-code=UTF-8 >$devnull 2>$devnull`; -- if ($? == 0) -- { -- $gettext_support_nonascii = 1; -- } -- else -- { -- # urge everybody to upgrade gettext -- print STDERR "WARNING: This version of gettext does not support extracting non-ASCII\n". -- " strings. That means you should install a version of gettext\n". -- " that supports non-ASCII strings (such as GNU gettext >= 0.12),\n". -- " or have to let non-ASCII strings untranslated. (If there is any)\n"; -- } -- -- my $encoding = "ASCII"; -- my $forced_gettext_code; -- my @temp_headers; -- my $encoding_problem_is_reported = 0; -- -- while (<INFILE>) -- { -- next if (/^#/ or /^\s*$/); -- -- chomp; -- -- my $gettext_code; -- -- if (/^\[\s*encoding:\s*(.*)\s*\]/) -- { -- $forced_gettext_code=$1; -- } -- elsif (/\.($xml_support|$ini_support)$/ || /^\[/) -- { -- s/^\[.*]\s*//; -- print OUTFILE "../$_.h\n"; -- push @temp_headers, "../$_.h"; -- $gettext_code = &TextFile_DetermineEncoding ("../$_.h") if ($gettext_support_nonascii and not defined $forced_gettext_code); -- } -- else -- { -- if ($SRCDIR eq ".") { -- print OUTFILE "../$_\n"; -- } else { -- print OUTFILE "$SRCDIR/../$_\n"; -- } -- $gettext_code = &TextFile_DetermineEncoding ("../$_") if ($gettext_support_nonascii and not defined $forced_gettext_code); -- } -- -- next if (! $gettext_support_nonascii); -- -- if (defined $forced_gettext_code) -- { -- $encoding=$forced_gettext_code; -- } -- elsif (defined $gettext_code and "$encoding" ne "$gettext_code") -- { -- if ($encoding eq "ASCII") -- { -- $encoding=$gettext_code; -- } -- elsif ($gettext_code ne "ASCII") -- { -- # Only report once because the message is quite long -- if (! $encoding_problem_is_reported) -- { -- print STDERR "WARNING: You should use the same file encoding for all your project files,\n". -- " but $PROGRAM thinks that most of the source files are in\n". -- " $encoding encoding, while \"$_\" is (likely) in\n". -- " $gettext_code encoding. If you are sure that all translatable strings\n". -- " are in same encoding (say UTF-8), please \e[1m*prepend*\e[0m the following\n". -- " line to POTFILES.in:\n\n". -- " [encoding: UTF-8]\n\n". -- " and make sure that configure.in/ac checks for $PACKAGE >= 0.27 .\n". -- "(such warning message will only be reported once.)\n"; -- $encoding_problem_is_reported = 1; -- } -- } -- } -- } -- -- close OUTFILE; -- close INFILE; -- -- unlink "$MODULE.pot"; -- my @xgettext_argument=("$XGETTEXT", -- "--add-comments", -- "--directory\=\.", -- "--output\=$MODULE\.pot", -- "--files-from\=\.\/POTFILES\.in\.temp"); -- my $XGETTEXT_KEYWORDS = &FindPOTKeywords; -- push @xgettext_argument, $XGETTEXT_KEYWORDS; -- my $MSGID_BUGS_ADDRESS = &FindMakevarsBugAddress; -- push @xgettext_argument, "--msgid-bugs-address\=$MSGID_BUGS_ADDRESS" if $MSGID_BUGS_ADDRESS; -- push @xgettext_argument, "--from-code\=$encoding" if ($gettext_support_nonascii); -- push @xgettext_argument, $XGETTEXT_ARGS if $XGETTEXT_ARGS; -- my $xgettext_command = join ' ', @xgettext_argument; -- -- # intercept xgettext error message -- print "Running $xgettext_command\n" if $VERBOSE; -- my $xgettext_error_msg = `$xgettext_command 2>\&1`; -- my $command_failed = $?; -- -- unlink "POTFILES.in.temp"; -- -- print "Removing generated header (.h) files..." if $VERBOSE; -- unlink foreach (@temp_headers); -- print "done.\n" if $VERBOSE; -- -- if (! $command_failed) -- { -- if (! -e "$MODULE.pot") -- { -- print "None of the files in POTFILES.in contain strings marked for translation.\n" if $VERBOSE; -- } -- else -- { -- print "Wrote $MODULE.pot\n" if $VERBOSE; -- } -- } -- else -- { -- if ($xgettext_error_msg =~ /--from-code/) -- { -- # replace non-ASCII error message with a more useful one. -- print STDERR "ERROR: xgettext failed to generate PO template file because there is non-ASCII\n". -- " string marked for translation. Please make sure that all strings marked\n". -- " for translation are in uniform encoding (say UTF-8), then \e[1m*prepend*\e[0m the\n". -- " following line to POTFILES.in and rerun $PROGRAM:\n\n". -- " [encoding: UTF-8]\n\n"; -- } -- else -- { -- print STDERR "$xgettext_error_msg"; -- if (-e "$MODULE.pot") -- { -- # is this possible? -- print STDERR "ERROR: xgettext failed but still managed to generate PO template file.\n". -- " Please consult error message above if there is any.\n"; -- } -- else -- { -- print STDERR "ERROR: xgettext failed to generate PO template file. Please consult\n". -- " error message above if there is any.\n"; -- } -- } -- exit (1); -- } --} -- --sub POFile_Update --{ -- -f "$MODULE.pot" or die "$PROGRAM: $MODULE.pot does not exist.\n"; -- -- my $MSGMERGE = $ENV{"MSGMERGE"} || "@INTLTOOL_MSGMERGE@"; -- my ($lang, $outfile) = @_; -- -- print "Merging $SRCDIR/$lang.po with $MODULE.pot..." if $VERBOSE; -- -- my $infile = "$SRCDIR/$lang.po"; -- $outfile = "$SRCDIR/$lang.po" if ($outfile eq ""); -- -- # I think msgmerge won't overwrite old file if merge is not successful -- system ("$MSGMERGE", "-o", $outfile, $infile, "$MODULE.pot"); --} -- --sub Console_WriteError_NotExisting --{ -- my ($file) = @_; -- -- ## Report error if supplied language file is non-existing -- print STDERR "$PROGRAM: $file does not exist!\n"; -- print STDERR "Try '$PROGRAM --help' for more information.\n"; -- exit; --} -- --sub GatherPOFiles --{ -- my @po_files = glob ("./*.po"); -- -- @languages = map (&POFile_GetLanguage, @po_files); -- -- foreach my $lang (@languages) -- { -- $po_files_by_lang{$lang} = shift (@po_files); -- } --} -- --sub POFile_GetLanguage ($) --{ -- s/^(.*\/)?(.+)\.po$/$2/; -- return $_; --} -- --sub Console_Write_TranslationStatus --{ -- my ($lang, $output_file) = @_; -- my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@"; -- -- $output_file = "$SRCDIR/$lang.po" if ($output_file eq ""); -- -- system ("$MSGFMT", "-o", "$devnull", "--verbose", $output_file); --} -- --sub Console_Write_CoverageReport --{ -- my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@"; -- -- &GatherPOFiles; -- -- foreach my $lang (@languages) -- { -- print "$lang: "; -- &POFile_Update ($lang, ""); -- } -- -- print "\n\n * Current translation support in $MODULE \n\n"; -- -- foreach my $lang (@languages) -- { -- print "$lang: "; -- system ("$MSGFMT", "-o", "$devnull", "--verbose", "$SRCDIR/$lang.po"); -- } --} -- --sub SubstituteVariable --{ -- my ($str) = @_; -- -- # always need to rewind file whenever it has been accessed -- seek (CONF, 0, 0); -- -- # cache each variable. varhash is global to we can add -- # variables elsewhere. -- while (<CONF>) -- { -- if (/^(\w+)=(.*)$/) -- { -- ($varhash{$1} = $2) =~ s/^["'](.*)["']$/$1/; -- } -- } -- -- if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/) -- { -- my $rest = $3; -- my $untouched = $1; -- my $sub = ""; -- # Ignore recursive definitions of variables -- $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/; -- -- return SubstituteVariable ("$untouched$sub$rest"); -- } -- -- # We're using Perl backticks ` and "echo -n" here in order to -- # expand any shell escapes (such as backticks themselves) in every variable -- return echo_n ($str); --} -- --sub CONF_Handle_Open --{ -- my $base_dirname = getcwd(); -- $base_dirname =~ s@.*/@@; -- -- my ($conf_in, $src_dir); -- -- if ($base_dirname =~ /^po(-.+)?$/) -- { -- if (-f "Makevars") -- { -- my $makefile_source; -- -- local (*IN); -- open (IN, "<Makevars") || die "can't open Makevars: $!"; -- -- while (<IN>) -- { -- if (/^top_builddir[ \t]*=/) -- { -- $src_dir = $_; -- $src_dir =~ s/^top_builddir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/; -- -- chomp $src_dir; -- if (-f "$src_dir" . "/configure.ac") { -- $conf_in = "$src_dir" . "/configure.ac" . "\n"; -- } else { -- $conf_in = "$src_dir" . "/configure.in" . "\n"; -- } -- last; -- } -- } -- close IN; -- -- $conf_in || die "Cannot find top_builddir in Makevars."; -- } -- elsif (-f "../configure.ac") -- { -- $conf_in = "../configure.ac"; -- } -- elsif (-f "../configure.in") -- { -- $conf_in = "../configure.in"; -- } -- else -- { -- my $makefile_source; -- -- local (*IN); -- open (IN, "<Makefile") || return; -- -- while (<IN>) -- { -- if (/^top_srcdir[ \t]*=/) -- { -- $src_dir = $_; -- $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/; -- -- chomp $src_dir; -- $conf_in = "$src_dir" . "/configure.in" . "\n"; -- -- last; -- } -- } -- close IN; -- -- $conf_in || die "Cannot find top_srcdir in Makefile."; -- } -- -- open (CONF, "<$conf_in"); -- } -- else -- { -- print STDERR "$PROGRAM: Unable to proceed.\n" . -- "Make sure to run this script inside the po directory.\n"; -- exit; -- } --} -- --sub FindPackageName --{ -- my $version; -- my $domain = &FindMakevarsDomain; -- my $name = $domain || "untitled"; -- -- &CONF_Handle_Open; -- -- my $conf_source; { -- local (*IN); -- open (IN, "<&CONF") || return $name; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $conf_source = <IN>; -- close IN; -- } -- -- # priority for getting package name: -- # 1. GETTEXT_PACKAGE -- # 2. first argument of AC_INIT (with >= 2 arguments) -- # 3. first argument of AM_INIT_AUTOMAKE (with >= 2 argument) -- -- # /^AM_INIT_AUTOMAKE\([\s\[]*([^,\)\s\]]+)/m -- # the \s makes this not work, why? -- if ($conf_source =~ /^AM_INIT_AUTOMAKE\(([^,\)]+),([^,\)]+)/m) -- { -- ($name, $version) = ($1, $2); -- $name =~ s/[\[\]\s]//g; -- $version =~ s/[\[\]\s]//g; -- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); -- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); -- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); -- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); -- } -- -- if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)/m) -- { -- ($name, $version) = ($1, $2); -- $name =~ s/[\[\]\s]//g; -- $version =~ s/[\[\]\s]//g; -- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); -- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); -- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); -- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); -- } -- -- # \s makes this not work, why? -- $name = $1 if $conf_source =~ /^GETTEXT_PACKAGE=\[?([^\n\]]+)/m; -- -- # m4 macros AC_PACKAGE_NAME, AC_PACKAGE_VERSION etc. have same value -- # as corresponding $PACKAGE_NAME, $PACKAGE_VERSION etc. shell variables. -- $name =~ s/\bAC_PACKAGE_/\$PACKAGE_/g; -- -- $name = $domain if $domain; -- -- $name = SubstituteVariable ($name); -- $name =~ s/^["'](.*)["']$/$1/; -- -- return $name if $name; --} -- -- --sub FindPOTKeywords --{ -- -- my $keywords = "--keyword\=\_ --keyword\=N\_ --keyword\=U\_ --keyword\=Q\_"; -- my $varname = "XGETTEXT_OPTIONS"; -- my $make_source; { -- local (*IN); -- open (IN, "<Makevars") || (open(IN, "<Makefile.in.in") && ($varname = "XGETTEXT_KEYWORDS")) || return $keywords; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $make_source = <IN>; -- close IN; -- } -- -- $keywords = $1 if $make_source =~ /^$varname[ ]*=\[?([^\n\]]+)/m; -- -- return $keywords; --} -- --sub FindMakevarsDomain --{ -- -- my $domain = ""; -- my $makevars_source; { -- local (*IN); -- open (IN, "<Makevars") || return $domain; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $makevars_source = <IN>; -- close IN; -- } -- -- $domain = $1 if $makevars_source =~ /^DOMAIN[ ]*=\[?([^\n\]\$]+)/m; -- $domain =~ s/^\s+//; -- $domain =~ s/\s+$//; -- -- return $domain; --} -- --sub FindMakevarsBugAddress --{ -- -- my $address = ""; -- my $makevars_source; { -- local (*IN); -- open (IN, "<Makevars") || return undef; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $makevars_source = <IN>; -- close IN; -- } -- -- $address = $1 if $makevars_source =~ /^MSGID_BUGS_ADDRESS[ ]*=\[?([^\n\]\$]+)/m; -- $address =~ s/^\s+//; -- $address =~ s/\s+$//; -- -- return $address; --} -diff --git a/intltool-update.in b/intltool-update.in -new file mode 120000 -index 661d8fe..0b1800f ---- /dev/null -+++ b/intltool-update.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-update.in -\ No newline at end of file -diff --git a/pixmaps/intlclock-map-location-current.png b/pixmaps/intlclock-map-location-current.png -new file mode 100644 -index 0000000..5c505d1 -Binary files /dev/null and b/pixmaps/intlclock-map-location-current.png differ -diff --git a/pixmaps/intlclock-map-location-current.svg b/pixmaps/intlclock-map-location-current.svg -new file mode 100644 -index 0000000..93b5188 ---- /dev/null -+++ b/pixmaps/intlclock-map-location-current.svg -@@ -0,0 +1,76 @@ -+<?xml version="1.0" encoding="UTF-8" standalone="no"?> -+<!-- Created with Inkscape (http://www.inkscape.org/) --> -+<svg -+ xmlns:dc="http://purl.org/dc/elements/1.1/" -+ xmlns:cc="http://web.resource.org/cc/" -+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -+ xmlns:svg="http://www.w3.org/2000/svg" -+ xmlns="http://www.w3.org/2000/svg" -+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" -+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" -+ width="10" -+ height="10" -+ id="svg2" -+ sodipodi:version="0.32" -+ inkscape:version="0.45.1" -+ sodipodi:docbase="/home/mclasen/Desktop" -+ sodipodi:docname="star.svg" -+ inkscape:output_extension="org.inkscape.output.svg.inkscape" -+ version="1.0"> -+ <defs -+ id="defs4" /> -+ <sodipodi:namedview -+ id="base" -+ pagecolor="#ffffff" -+ bordercolor="#666666" -+ borderopacity="1.0" -+ gridtolerance="10000" -+ guidetolerance="10" -+ objecttolerance="10" -+ inkscape:pageopacity="0.0" -+ inkscape:pageshadow="2" -+ inkscape:zoom="1" -+ inkscape:cx="88.125" -+ inkscape:cy="-22.797357" -+ inkscape:document-units="px" -+ inkscape:current-layer="layer1" -+ inkscape:window-width="1003" -+ inkscape:window-height="824" -+ inkscape:window-x="93" -+ inkscape:window-y="30" -+ width="10px" -+ height="10px" /> -+ <metadata -+ id="metadata7"> -+ <rdf:RDF> -+ <cc:Work -+ rdf:about=""> -+ <dc:format>image/svg+xml</dc:format> -+ <dc:type -+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> -+ </cc:Work> -+ </rdf:RDF> -+ </metadata> -+ <g -+ inkscape:label="Layer 1" -+ inkscape:groupmode="layer" -+ id="layer1" -+ transform="translate(-164.31866,-172.88433)"> -+ <path -+ sodipodi:type="star" -+ style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:10.30000114;stroke-miterlimit:3.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" -+ id="path2160" -+ sodipodi:sides="5" -+ sodipodi:cx="311.42856" -+ sodipodi:cy="320.93362" -+ sodipodi:r1="121.8637" -+ sodipodi:r2="42.747437" -+ sodipodi:arg1="1.0073988" -+ sodipodi:arg2="1.6371268" -+ inkscape:flatsided="false" -+ inkscape:rounded="0" -+ inkscape:randomized="0" -+ d="M 376.51129,423.96274 L 308.59518,363.58706 L 233.55372,414.66873 L 269.98717,331.41956 L 198.21652,275.83599 L 288.64975,284.76085 L 319.33452,199.32664 L 338.79187,288.09169 L 429.52674,290.87401 L 351.11882,336.80896 L 376.51129,423.96274 z " -+ transform="matrix(3.8213745e-2,-2.1588882e-2,2.2396111e-2,3.6200569e-2,150.72076,172.68179)" /> -+ </g> -+</svg> -diff --git a/pixmaps/intlclock-map-location-hilight.png b/pixmaps/intlclock-map-location-hilight.png -new file mode 100644 -index 0000000..d7de5b7 -Binary files /dev/null and b/pixmaps/intlclock-map-location-hilight.png differ -diff --git a/pixmaps/intlclock-map-location-hilight.svg b/pixmaps/intlclock-map-location-hilight.svg -new file mode 100644 -index 0000000..4a245e0 ---- /dev/null -+++ b/pixmaps/intlclock-map-location-hilight.svg -@@ -0,0 +1,90 @@ -+<?xml version="1.0" encoding="UTF-8" standalone="no"?> -+<!-- Created with Inkscape (http://www.inkscape.org/) --> -+<svg -+ xmlns:dc="http://purl.org/dc/elements/1.1/" -+ xmlns:cc="http://web.resource.org/cc/" -+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -+ xmlns:svg="http://www.w3.org/2000/svg" -+ xmlns="http://www.w3.org/2000/svg" -+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" -+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" -+ width="7" -+ height="7" -+ id="svg6063" -+ sodipodi:version="0.32" -+ inkscape:version="0.45.1" -+ version="1.0" -+ sodipodi:docbase="/home/mclasen/Desktop/intlclock/pixmaps" -+ sodipodi:docname="intlclock-map-location-hilight.svg" -+ inkscape:output_extension="org.inkscape.output.svg.inkscape" -+ inkscape:export-filename="/home/garrett/Desktop/dot.png" -+ inkscape:export-xdpi="90" -+ inkscape:export-ydpi="90"> -+ <defs -+ id="defs6065"> -+ <linearGradient -+ id="linearGradient7251"> -+ <stop -+ style="stop-color:#e1d9dc;stop-opacity:1;" -+ offset="0" -+ id="stop7253" /> -+ <stop -+ id="stop3143" -+ offset="0.5" -+ style="stop-color:#e3bfca;stop-opacity:1;" /> -+ <stop -+ style="stop-color:#3d0e1a;stop-opacity:1;" -+ offset="1" -+ id="stop7255" /> -+ </linearGradient> -+ </defs> -+ <sodipodi:namedview -+ id="base" -+ pagecolor="#ffffff" -+ bordercolor="#666666" -+ borderopacity="1.0" -+ gridtolerance="10000" -+ guidetolerance="10" -+ objecttolerance="10" -+ inkscape:pageopacity="0.0" -+ inkscape:pageshadow="2" -+ inkscape:zoom="22.627417" -+ inkscape:cx="2.5000319" -+ inkscape:cy="2.5000319" -+ inkscape:document-units="px" -+ inkscape:current-layer="layer1" -+ inkscape:window-width="872" -+ inkscape:window-height="750" -+ inkscape:window-x="0" -+ inkscape:window-y="30" /> -+ <metadata -+ id="metadata6068"> -+ <rdf:RDF> -+ <cc:Work -+ rdf:about=""> -+ <dc:format>image/svg+xml</dc:format> -+ <dc:type -+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> -+ </cc:Work> -+ </rdf:RDF> -+ </metadata> -+ <g -+ inkscape:label="Layer 1" -+ inkscape:groupmode="layer" -+ id="layer1" -+ transform="translate(-474.64282,-409.86216)"> -+ <path -+ sodipodi:type="arc" -+ style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:13.16123206;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" -+ id="path7259" -+ sodipodi:cx="-418.5" -+ sodipodi:cy="-489.5" -+ sodipodi:rx="39.5" -+ sodipodi:ry="39.5" -+ d="M -379 -489.5 A 39.5 39.5 0 1 1 -458,-489.5 A 39.5 39.5 0 1 1 -379 -489.5 z" -+ transform="matrix(5.4243529e-2,8.5329805e-4,-8.5329805e-4,5.4243529e-2,499.42608,439.2715)" -+ inkscape:export-filename="/home/garrett/Desktop/map-new.png" -+ inkscape:export-xdpi="90" -+ inkscape:export-ydpi="90" /> -+ </g> -+</svg> -diff --git a/pixmaps/intlclock-map-location-marker.png b/pixmaps/intlclock-map-location-marker.png -new file mode 100644 -index 0000000..48d2184 -Binary files /dev/null and b/pixmaps/intlclock-map-location-marker.png differ -diff --git a/po/Makefile.in.in b/po/Makefile.in.in -deleted file mode 100755 -index d2d4e4c..e4713cf ---- a/po/Makefile.in.in -+++ /dev/null -@@ -1,221 +0,0 @@ --# Makefile for program source directory in GNU NLS utilities package. --# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> --# --# This file file be copied and used freely without restrictions. It can --# be used in projects which are not available under the GNU Public License --# but which still want to provide support for the GNU gettext functionality. --# Please note that the actual code is *not* freely available. --# --# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE --# instead of PACKAGE and to look for po2tbl in ./ not in intl/ --# --# - Modified by jacob berkman <jacob@ximian.com> to install --# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize --# --# - Modified by Rodney Dawes <dobey@novell.com> for use with intltool --# --# We have the following line for use by intltoolize: --# INTLTOOL_MAKEFILE -- --GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ --PACKAGE = @PACKAGE@ --VERSION = @VERSION@ -- --SHELL = /bin/sh -- --srcdir = @srcdir@ --top_srcdir = @top_srcdir@ --top_builddir = .. --VPATH = @srcdir@ -- --prefix = @prefix@ --exec_prefix = @exec_prefix@ --datadir = @datadir@ --datarootdir = @datarootdir@ --libdir = @libdir@ --DATADIRNAME = @DATADIRNAME@ --itlocaledir = $(prefix)/$(DATADIRNAME)/locale --subdir = po --install_sh = @install_sh@ --# Automake >= 1.8 provides @mkdir_p@. --# Until it can be supposed, use the safe fallback: --mkdir_p = $(install_sh) -d -- --INSTALL = @INSTALL@ --INSTALL_DATA = @INSTALL_DATA@ -- --GMSGFMT = @GMSGFMT@ --MSGFMT = @MSGFMT@ --XGETTEXT = @XGETTEXT@ --INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ --INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ --MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist --GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot -- --ALL_LINGUAS = @ALL_LINGUAS@ -- --PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi) -- --POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done) -- --DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES) --EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS -- --POTFILES = \ --#This Gets Replace for some reason -- --CATALOGS=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) -- --.SUFFIXES: --.SUFFIXES: .po .pox .gmo .mo .msg .cat -- --.po.pox: -- $(MAKE) $(GETTEXT_PACKAGE).pot -- $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox -- --.po.mo: -- $(MSGFMT) -o $@ $< -- --.po.gmo: -- file=`echo $* | sed 's,.*/,,'`.gmo \ -- && rm -f $$file && $(GMSGFMT) -o $$file $< -- --.po.cat: -- sed -f ../intl/po2msg.sed < $< > $*.msg \ -- && rm -f $@ && gencat $@ $*.msg -- -- --all: all-@USE_NLS@ -- --all-yes: $(CATALOGS) --all-no: -- --$(GETTEXT_PACKAGE).pot: $(POTFILES) -- $(GENPOT) -- --install: install-data --install-data: install-data-@USE_NLS@ --install-data-no: all --install-data-yes: all -- $(mkdir_p) $(DESTDIR)$(itlocaledir) -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ -- $(mkdir_p) $$dir; \ -- if test -r $$lang.gmo; then \ -- $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -- echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ -- else \ -- $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -- echo "installing $(srcdir)/$$lang.gmo as" \ -- "$$dir/$(GETTEXT_PACKAGE).mo"; \ -- fi; \ -- if test -r $$lang.gmo.m; then \ -- $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ -- echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ -- else \ -- if test -r $(srcdir)/$$lang.gmo.m ; then \ -- $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ -- $$dir/$(GETTEXT_PACKAGE).mo.m; \ -- echo "installing $(srcdir)/$$lang.gmo.m as" \ -- "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ -- else \ -- true; \ -- fi; \ -- fi; \ -- done -- --# Empty stubs to satisfy archaic automake needs --dvi info tags TAGS ID: -- --# Define this as empty until I found a useful application. --installcheck: -- --uninstall: -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ -- rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ -- done -- --check: all $(GETTEXT_PACKAGE).pot -- --mostlyclean: -- rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp -- rm -f .intltool-merge-cache -- --clean: mostlyclean -- --distclean: clean -- rm -f Makefile Makefile.in POTFILES stamp-it -- rm -f *.mo *.msg *.cat *.cat.m *.gmo -- --maintainer-clean: distclean -- @echo "This command is intended for maintainers to use;" -- @echo "it deletes files that may require special tools to rebuild." -- rm -f Makefile.in.in -- --distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) --dist distdir: $(DISTFILES) -- dists="$(DISTFILES)"; \ -- extra_dists="$(EXTRA_DISTFILES)"; \ -- for file in $$extra_dists; do \ -- test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ -- done; \ -- for file in $$dists; do \ -- test -f $$file || file="$(srcdir)/$$file"; \ -- ln $$file $(distdir) 2> /dev/null \ -- || cp -p $$file $(distdir); \ -- done -- --update-po: Makefile -- $(MAKE) $(GETTEXT_PACKAGE).pot -- tmpdir=`pwd`; \ -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- echo "$$lang:"; \ -- result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ -- if $$result; then \ -- if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ -- rm -f $$tmpdir/$$lang.new.po; \ -- else \ -- if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ -- :; \ -- else \ -- echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ -- rm -f $$tmpdir/$$lang.new.po; \ -- exit 1; \ -- fi; \ -- fi; \ -- else \ -- echo "msgmerge for $$lang.gmo failed!"; \ -- rm -f $$tmpdir/$$lang.new.po; \ -- fi; \ -- done -- --Makefile POTFILES: stamp-it -- @if test ! -f $@; then \ -- rm -f stamp-it; \ -- $(MAKE) stamp-it; \ -- fi -- --stamp-it: Makefile.in.in ../config.status POTFILES.in -- cd .. \ -- && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ -- $(SHELL) ./config.status -- --# Tell versions [3.59,3.63) of GNU make not to export all variables. --# Otherwise a system limit (for SysV at least) may be exceeded. --.NOEXPORT: -diff --git a/po/Makefile.in.in b/po/Makefile.in.in -new file mode 120000 -index d2d4e4c..e4713cf ---- /dev/null -+++ b/po/Makefile.in.in -@@ -0,0 +1 @@ -+/usr/share/intltool/Makefile.in.in -\ No newline at end of file -diff --git a/src/Makefile.am b/src/Makefile.am -index 80d1419..d681d39 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -3,7 +3,7 @@ - INCLUDES = \ - $(INTLCLOCK_CFLAGS) \ - -DGNOMELOCALEDIR=\"$(prefix)/$(DATADIRNAME)/locale\" \ -- -DEVOLUTION_TEXTDOMAIN=\"evolution-2.6\" \ -+ -DEVOLUTION_TEXTDOMAIN=\"evolution-2.12\" \ - -DINTLCLOCK_TEXTDOMAIN=\"gnome-panel-2.0\" \ - -DINTLCLOCK_ICONDIR=\"$(pkgdatadir)\" \ - -DINTLCLOCK_DATADIR=\"$(pkgdatadir)\" \ -@@ -60,7 +60,11 @@ COMMON_SOURCES = \ - intlclock-zoneinfo.c \ - intlclock-zoneinfo.h \ - intlclock-zonetable.c \ -- intlclock-zonetable.h -+ intlclock-zonetable.h \ -+ set-timezone.c \ -+ set-timezone.h \ -+ gweather-xml.c \ -+ gweather-xml.h - - - intlclock_applet_SOURCES = \ -diff --git a/src/gweather-xml.c b/src/gweather-xml.c -new file mode 100644 -index 0000000..1de649f ---- /dev/null -+++ b/src/gweather-xml.c -@@ -0,0 +1,505 @@ -+/* gweather-xml.c - Locations.xml parsing code -+ * -+ * Copyright (C) 2005 Ryan Lortie, 2004 Gareth Owen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+ -+/* There is very little error checking in the parsing code below, it relies -+ * heavily on the locations file being in the correct format. If you have -+ * <name> elements within a parent element, they must come first and be -+ * grouped together. -+ * The format is as follows: -+ * -+ * <gweather format="1.0"> -+ * <region> -+ * <name>Name of the region</name> -+ * <name xml:lang="xx">Translated Name</name> -+ * <name xml:lang="zz">Another Translated Name</name> -+ * <country> -+ * <name>Name of the country</name> -+ * <location> -+ * <name>Name of the location</name> -+ * <code>IWIN code</code> -+ * <zone>Forecast code (North America, Australia, UK only)</zone> -+ * <radar>Weather.com radar map code (North America only)</radar> -+ * <coordinates>Latitude and longitude as DD-MM[-SS][H] pair</coordinates> -+ * </location> -+ * <state> -+ * <location> -+ * .... -+ * </location> -+ * <city> -+ * <name>Name of city with multiple locations</city> -+ * <zone>Forecast code</zone> -+ * <radar>Radar Map code</radar> -+ * <location> -+ * ... -+ * </location> -+ * </city> -+ * </state> -+ * </country> -+ * </region> -+ * <gweather> -+ * -+ * The thing to note is that each country can either contain different locations -+ * or be split into "states" which in turn contain a list of locations. -+ * -+ */ -+ -+#include <string.h> -+#include <math.h> -+#include <locale.h> -+#include <gtk/gtk.h> -+#include <libxml/xmlreader.h> -+ -+#include "gweather-xml.h" -+ -+static gint -+gweather_xml_location_sort_func( GtkTreeModel *model, GtkTreeIter *a, -+ GtkTreeIter *b, gpointer user_data ) -+{ -+ gint res; -+ gchar *name_a, *name_b; -+ gchar *fold_a, *fold_b; -+ -+ gtk_tree_model_get (model, a, GWEATHER_XML_COL_LOC, &name_a, -1); -+ gtk_tree_model_get (model, b, GWEATHER_XML_COL_LOC, &name_b, -1); -+ -+ fold_a = g_utf8_casefold(name_a, -1); -+ fold_b = g_utf8_casefold(name_b, -1); -+ -+ res = g_utf8_collate(fold_a, fold_b); -+ -+ g_free(name_a); -+ g_free(name_b); -+ g_free(fold_a); -+ g_free(fold_b); -+ -+ return res; -+} -+ -+static char* -+gweather_xml_get_value( xmlTextReaderPtr xml ) -+{ -+ char* value; -+ -+ /* check for null node */ -+ if ( xmlTextReaderIsEmptyElement( xml ) ) -+ return NULL; -+ -+ /* the next "node" is the text node containing the value we want to get */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ return NULL; -+ -+ value = (char *) xmlTextReaderValue( xml ); -+ -+ /* move on to the end of this node */ -+ while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_END_ELEMENT ) -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( value ); -+ return NULL; -+ } -+ -+ /* consume the end element too */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( value ); -+ return NULL; -+ } -+ -+ return value; -+} -+ -+static char * -+gweather_xml_parse_name( xmlTextReaderPtr xml ) -+{ -+ const char * const *locales; -+ const char *this_language; -+ int best_match = INT_MAX; -+ char *lang, *tagname; -+ gboolean keep_going; -+ char *name = NULL; -+ int i; -+ -+ locales = g_get_language_names(); -+ -+ do -+ { -+ /* First let's get the language */ -+ lang = (char *) xmlTextReaderXmlLang( xml ); -+ -+ if( lang == NULL ) -+ this_language = "C"; -+ else -+ this_language = lang; -+ -+ /* the next "node" is text node containing the actual name */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( lang ); -+ return NULL; -+ } -+ -+ for( i = 0; locales[i] && i < best_match; i++ ) -+ if( !strcmp( locales[i], this_language ) ) -+ { -+ /* if we've already encounted a less accurate -+ translation, then free it */ -+ xmlFree( name ); -+ -+ name = (char *) xmlTextReaderValue( xml ); -+ best_match = i; -+ -+ break; -+ } -+ -+ xmlFree( lang ); -+ -+ while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_ELEMENT ) -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( name ); -+ return NULL; -+ } -+ -+ /* if the next tag is another <name> then keep going */ -+ tagname = (char *) xmlTextReaderName( xml ); -+ keep_going = !strcmp( tagname, "name" ); -+ xmlFree( tagname ); -+ -+ } while( keep_going ); -+ -+ return name; -+} -+ -+static int -+gweather_xml_parse_node (GtkTreeView *view, GtkTreeIter *parent, -+ xmlTextReaderPtr xml, WeatherLocation *current, -+ const char *dflt_radar, const char *dflt_zone, -+ const char *cityname) -+{ -+ GtkTreeStore *store = GTK_TREE_STORE( gtk_tree_view_get_model( view ) ); -+ char *name, *code, *zone, *radar, *coordinates; -+ char **city, *nocity = NULL; -+ GtkTreeIter iter, *self; -+ gboolean is_location; -+ char *tagname; -+ int ret = -1; -+ int tagtype; -+ -+ if( (tagname = (char *) xmlTextReaderName( xml )) == NULL ) -+ return -1; -+ -+ if( !strcmp( tagname, "city" ) ) -+ city = &name; -+ else -+ city = &nocity; -+ -+ is_location = !strcmp( tagname, "location" ); -+ -+ /* if we're processing the top-level, then don't create a new iter */ -+ if( !strcmp( tagname, "gweather" ) ) -+ self = NULL; -+ else -+ { -+ self = &iter; -+ /* insert this node into the tree */ -+ gtk_tree_store_append( store, self, parent ); -+ } -+ -+ xmlFree( tagname ); -+ -+ coordinates = NULL; -+ radar = NULL; -+ zone = NULL; -+ code = NULL; -+ name = NULL; -+ -+ /* absorb the start tag */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ -+ /* start parsing the actual contents of the node */ -+ while( (tagtype = xmlTextReaderNodeType( xml )) != -+ XML_READER_TYPE_END_ELEMENT ) -+ { -+ -+ /* skip non-element types */ -+ if( tagtype != XML_READER_TYPE_ELEMENT ) -+ { -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ -+ continue; -+ } -+ -+ tagname = (char *) xmlTextReaderName( xml ); -+ -+ if( !strcmp( tagname, "region" ) || !strcmp( tagname, "country" ) || -+ !strcmp( tagname, "state" ) || !strcmp( tagname, "city" ) || -+ !strcmp( tagname, "location" ) ) -+ { -+ /* recursively handle sub-sections */ -+ if( gweather_xml_parse_node( view, self, xml, current, -+ radar, zone, *city ) ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "name" ) ) -+ { -+ xmlFree( name ); -+ if( (name = gweather_xml_parse_name( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "code" ) ) -+ { -+ xmlFree( code ); -+ if( (code = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "zone" ) ) -+ { -+ xmlFree( zone ); -+ if( (zone = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "radar" ) ) -+ { -+ xmlFree( radar ); -+ if( (radar = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "coordinates" ) ) -+ { -+ xmlFree( coordinates ); -+ if( (coordinates = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else /* some strange tag */ -+ { -+ /* skip past it */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ } -+ -+ xmlFree( tagname ); -+ } -+ -+ if( self ) -+ gtk_tree_store_set( store, self, GWEATHER_XML_COL_LOC, name, -1 ); -+ -+ /* absorb the end tag. in the case of processing a <gweather> then 'self' -+ is NULL. In this case, we let this fail since we might be at EOF */ -+ if( xmlTextReaderRead( xml ) != 1 && self ) -+ goto error_out; -+ -+ /* if this is an actual location, setup the WeatherLocation for it */ -+ if( is_location ) -+ { -+ WeatherLocation *new_loc; -+ -+ if( cityname == NULL ) -+ cityname = name; -+ -+ if( radar != NULL ) -+ dflt_radar = radar; -+ -+ if( zone != NULL ) -+ dflt_zone = zone; -+ -+ new_loc = weather_location_new( cityname, code, dflt_zone, -+ dflt_radar, coordinates ); -+ -+ gtk_tree_store_set( store, &iter, GWEATHER_XML_COL_POINTER, new_loc, -1 ); -+ -+ /* If this location is actually the currently selected one, select it */ -+ if( current && weather_location_equal( new_loc, current ) ) -+ { -+ GtkTreePath *path; -+ -+ path = gtk_tree_model_get_path( GTK_TREE_MODEL (store), &iter ); -+ gtk_tree_view_expand_to_path( view, path ); -+ gtk_tree_view_set_cursor( view, path, NULL, FALSE ); -+ gtk_tree_view_scroll_to_cell( view, path, NULL, TRUE, 0.5, 0.5 ); -+ gtk_tree_path_free( path ); -+ } -+ } -+ -+ ret = 0; -+ -+error_out: -+ xmlFree( name ); -+ xmlFree( code ); -+ xmlFree( zone ); -+ xmlFree( radar ); -+ xmlFree( coordinates ); -+ -+ return ret; -+} -+ -+/***************************************************************************** -+ * Func: gweather_xml_load_locations() -+ * Desc: Main entry point for loading the locations from the XML file -+ * Parm: -+ * *tree: tree to view locations -+ * *current: currently selected location -+ */ -+int -+gweather_xml_load_locations( GtkTreeView *tree, WeatherLocation *current ) -+{ -+ char *tagname, *format; -+ GtkTreeSortable *sortable; -+ xmlTextReaderPtr xml; -+ int keep_going; -+ int ret = -1; -+ -+ /* Open the xml file containing the different locations */ -+#ifdef GWEATHER_XML_LOCATION -+ xml = xmlNewTextReaderFilename (GWEATHER_XML_LOCATION "Locations.xml"); -+#else -+ xml = xmlNewTextReaderFilename ("/usr/share/gnome-applets/gweather/Locations.xml"); -+#endif -+ if( xml == NULL ) -+ goto error_out; -+ -+ /* fast forward to the first element */ -+ do -+ { -+ /* if we encounter a problem here, exit right away */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ } while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_ELEMENT ); -+ -+ /* check the name and format */ -+ tagname = (char *) xmlTextReaderName( xml ); -+ keep_going = tagname && !strcmp( tagname, "gweather" ); -+ xmlFree( tagname ); -+ -+ if( !keep_going ) -+ goto error_out; -+ -+ format = (char *) xmlTextReaderGetAttribute( xml, (xmlChar *) "format" ); -+ keep_going = format && !strcmp( format, "1.0" ); -+ xmlFree( format ); -+ -+ if( !keep_going ) -+ goto error_out; -+ -+ ret = gweather_xml_parse_node( tree, NULL, xml, current, NULL, NULL, NULL ); -+ -+ if( ret ) -+ goto error_out; -+ -+ /* Sort the tree */ -+ sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model( tree )); -+ gtk_tree_sortable_set_default_sort_func( sortable, -+ &gweather_xml_location_sort_func, -+ NULL, NULL); -+ gtk_tree_sortable_set_sort_column_id( sortable, -+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, -+ GTK_SORT_ASCENDING ); -+error_out: -+ xmlFreeTextReader( xml ); -+ -+ return ret; -+} -+ -+typedef struct { -+ const gchar *name; -+ gdouble latitude; -+ gdouble longitude; -+ gdouble distance; -+ WeatherLocation *location; -+} SearchData; -+ -+ -+static gdouble -+distance (gdouble lat1, gdouble lon1, -+ gdouble lat2, gdouble lon2) -+{ -+ gdouble radius = 6372.795; -+ -+ return acos (cos (lat1) * cos (lat2) * cos (lon1 - lon2) + sin (lat1) * sin (lat2)) * radius; -+} -+ -+gboolean -+compare_location (GtkTreeModel *model, -+ GtkTreePath *path, -+ GtkTreeIter *iter, -+ gpointer user_data) -+{ -+ SearchData *data = user_data; -+ WeatherLocation *loc; -+ gdouble d; -+ -+ gtk_tree_model_get (model, iter, GWEATHER_XML_COL_POINTER, &loc, -1); -+ -+ if (!loc) -+ return FALSE; -+ -+ d = distance (data->latitude, data->longitude, loc->latitude, loc->longitude); -+ -+ if (d < data->distance) { -+ data->distance = d; -+ data->location = loc; -+ } -+ -+ return FALSE; -+} -+ -+gchar * -+find_weather_code (const gchar *name, -+ gdouble lat, -+ gdouble lon) -+{ -+ GtkTreeStore *model; -+ GtkWidget *tv; -+ GtkTreeViewColumn *column; -+ GtkCellRenderer *cell_renderer; -+ SearchData data; -+ gchar *code; -+ -+ model = gtk_tree_store_new (GWEATHER_XML_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER); -+ tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); -+ -+ cell_renderer = gtk_cell_renderer_text_new (); -+ column = gtk_tree_view_column_new_with_attributes ("not used", cell_renderer, -+ "text", GWEATHER_XML_COL_LOC, NULL); -+ gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column); -+ gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tv), column); -+ gweather_xml_load_locations (GTK_TREE_VIEW (tv), NULL); -+ -+ data.name = name; -+ data.latitude = lat; -+ data.longitude = lon; -+ data.distance = 1e6; -+ data.location = NULL; -+ -+ gtk_tree_model_foreach (GTK_TREE_MODEL (model), compare_location, &data); -+ -+ if (data.distance < 50) -+ code = g_strdup (data.location->code); -+ else -+ code = g_strdup ("-"); -+ -+ g_debug ("distance: %f\nin: %s\nlat, lon: %f, %f\nout: %s\nDMS: %s\ncode: %s\n", -+ data.distance, name, lat, lon, data.location->name, data.location->coordinates, code); -+ -+ gtk_widget_destroy (tv); -+ -+ return code; -+} -diff --git a/src/gweather-xml.h b/src/gweather-xml.h -new file mode 100644 -index 0000000..6d012c4 ---- /dev/null -+++ b/src/gweather-xml.h -@@ -0,0 +1,37 @@ -+/* gweather-xml.h -+ * -+ * Copyright (C) 2004 Gareth Owen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __GWEATHER_XML_H__ -+#define __GWEATHER_XML_H__ -+ -+#include <gtk/gtk.h> -+#include <libgweather/weather.h> -+ -+enum -+{ -+ GWEATHER_XML_COL_LOC = 0, -+ GWEATHER_XML_COL_POINTER, -+ GWEATHER_XML_NUM_COLUMNS -+}; -+ -+int gweather_xml_load_locations( GtkTreeView *tree, WeatherLocation *current ); -+gchar *find_weather_code (const gchar *name, gdouble lat, gdouble lon); -+ -+ -+#endif /* __GWEATHER_XML_H__ */ -diff --git a/src/intlclock-events-popup.c b/src/intlclock-events-popup.c -index 4276f81..a54f6e3 100644 ---- a/src/intlclock-events-popup.c -+++ b/src/intlclock-events-popup.c -@@ -1,6 +1,8 @@ - #include <gtk/gtk.h> - #include <string.h> - #include <time.h> -+#include <gconf/gconf-client.h> -+#include <panel-applet-gconf.h> - - #ifdef HAVE_CONFIG_H - #include "config.h" -@@ -11,12 +13,18 @@ - #endif - - #include "intlclock-events-popup.h" -+#include "intlclock-ui.h" -+ -+#define KEY_EXPAND_LOCATIONS "expand_locations" -+#define KEY_EXPAND_TASKS "expand_tasks" -+#define KEY_EXPAND_APPOINTMENTS "expand_appointments" - - G_DEFINE_TYPE (IntlClockEventsPopup, intlclock_events_popup, GTK_TYPE_WINDOW) - - typedef struct { - IntlClock *clock; - PanelApplet *panel_applet; -+ IntlClockUI *ui; - - GtkWidget *calendar; - GtkWidget *main_section; -@@ -126,7 +134,7 @@ intlclock_events_popup_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc - } - - IntlClockEventsPopup * --intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet) -+intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet, IntlClockUI *ui) - { - IntlClockEventsPopup *this; - IntlClockEventsPopupPrivate *priv; -@@ -138,6 +146,7 @@ intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet) - - priv->clock = g_object_ref (clock); - priv->panel_applet = panel_applet; -+ priv->ui = ui; - - gtk_widget_set_name (GTK_WIDGET (this), "intlclock-events-window"); - gtk_container_set_border_width (GTK_CONTAINER (this), 0); -@@ -275,6 +284,21 @@ intlclock_events_popup_tick (IntlClock *clock, IntlClockEventsPopup *this) - gmtime (&priv->current_time); - } - -+static GtkWidget * create_hig_frame (IntlClockEventsPopup *this, -+ const char *title, -+ const char *button_label, -+ const char *key, -+ GCallback callback); -+ -+ -+static void -+edit_locations (IntlClockEventsPopup *this) -+{ -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ -+ intlclock_ui_edit_locations (priv->ui); -+} -+ - static void - intlclock_events_popup_fill (IntlClockEventsPopup *this) - { -@@ -296,7 +320,10 @@ intlclock_events_popup_fill (IntlClockEventsPopup *this) - - orient = panel_applet_get_orient (priv->panel_applet); - -- priv->clock_container = gtk_vbox_new (FALSE, 0); -+ priv->clock_container = create_hig_frame (this, -+ _("Locations"), _("Edit"), -+ KEY_EXPAND_LOCATIONS, -+ G_CALLBACK (edit_locations)); - - switch (orient) { - case PANEL_APPLET_ORIENT_UP: -@@ -642,28 +669,167 @@ modify_task_text_attributes (GtkTreeModel *model, - g_value_take_boxed (value, attr_list); - } - -+static void -+expand_collapse_child (GtkWidget *child, -+ gpointer data) -+{ -+ gboolean expanded; -+ -+ if (data == child || gtk_widget_is_ancestor (data, child)) -+ return; -+ -+ expanded = gtk_expander_get_expanded (GTK_EXPANDER (data)); -+ g_object_set (child, "visible", expanded, NULL); -+} -+ -+static void -+expand_collapse (GtkWidget *expander, -+ GParamSpec *pspec, -+ gpointer data) -+{ -+ GtkWidget *box = data; -+ -+ gtk_container_foreach (GTK_CONTAINER (box), -+ (GtkCallback)expand_collapse_child, -+ expander); -+} -+ -+static void -+expander_activated (GtkExpander *expander, -+ gpointer data) -+{ -+ IntlClockEventsPopup *this = data; -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ const gchar *key; -+ gboolean expanded; -+ -+ key = (const gchar*)g_object_get_data (G_OBJECT (expander), "gconf-key"); -+ expanded = gtk_expander_get_expanded (expander); -+ -+ panel_applet_gconf_set_bool (priv->panel_applet, key, expanded, NULL); -+} -+ -+static void -+expanded_changed (GConfClient *client, -+ guint cnxn_id, -+ GConfEntry *entry, -+ GtkExpander *expander) -+{ -+ if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -+ return; -+ -+ gtk_expander_set_expanded (expander, -+ gconf_value_get_bool (entry->value)); -+} -+ -+static void -+remove_listener (gpointer data) -+{ -+ GConfClient *client; -+ -+ client = gconf_client_get_default (); -+ gconf_client_notify_remove (client, GPOINTER_TO_UINT (data)); -+ g_object_unref (client); -+} -+ -+static void -+connect_expander_with_gconf (IntlClockEventsPopup *this, -+ GtkWidget *expander, -+ const gchar *key) -+{ -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ GConfClient *client; -+ gboolean expanded; -+ guint listener; -+ gchar *full_key; -+ -+ g_object_set_data (G_OBJECT (expander), "gconf-key", (gpointer)key); -+ -+ expanded = panel_applet_gconf_get_bool (priv->panel_applet, key, NULL); -+ gtk_expander_set_expanded (GTK_EXPANDER (expander), expanded); -+ -+ g_signal_connect_after (expander, "activate", -+ G_CALLBACK (expander_activated), -+ this); -+ -+ client = gconf_client_get_default (); -+ full_key = panel_applet_gconf_get_full_key (priv->panel_applet, key); -+ listener = gconf_client_notify_add (client, full_key, -+ (GConfClientNotifyFunc)expanded_changed, -+ expander, NULL, NULL); -+ g_object_set_data_full (G_OBJECT (expander), "listener-id", -+ GUINT_TO_POINTER (listener), remove_listener); -+ g_object_unref (client); -+} -+ -+static void add_child (GtkContainer *container, -+ GtkWidget *child, -+ GtkExpander *expander) -+{ -+ gboolean expanded; -+ -+ expanded = gtk_expander_get_expanded (expander); -+ g_object_set (child, "visible", expanded, NULL); -+} -+ - static GtkWidget * --create_hig_frame (const char *title) -+create_hig_frame (IntlClockEventsPopup *this, -+ const char *title, -+ const char *button_label, -+ const char *key, -+ GCallback callback) - { - GtkWidget *vbox; - GtkWidget *alignment; - GtkWidget *label; -+ GtkWidget *hbox; -+ GtkWidget *button; - char *bold_title; -+ char *text; -+ GtkWidget *expander; - - vbox = gtk_vbox_new (FALSE, 6); - - bold_title = g_strdup_printf ("<b>%s</b>", title); -- -- alignment = gtk_alignment_new (0, 0.5, 0, 0); -- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0); -- gtk_widget_show (alignment); -- -- label = gtk_label_new (bold_title); -- gtk_label_set_use_markup (GTK_LABEL (label), TRUE); -- gtk_container_add (GTK_CONTAINER (alignment), label); -- gtk_widget_show (label); -- -+ expander = gtk_expander_new (""); -+ gtk_expander_set_label (GTK_EXPANDER (expander), bold_title); - g_free (bold_title); -+ gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE); -+ -+ hbox = gtk_hbox_new (FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (hbox), expander, FALSE, FALSE, 0); -+ gtk_widget_show_all (vbox); -+ -+ g_signal_connect (expander, "notify::expanded", -+ G_CALLBACK (expand_collapse), hbox); -+ g_signal_connect (expander, "notify::expanded", -+ G_CALLBACK (expand_collapse), vbox); -+ -+ /* FIXME: this doesn't really work, since "add" does not -+ * get emitted for e.g. gtk_box_pack_start -+ */ -+ g_signal_connect (vbox, "add", G_CALLBACK (add_child), expander); -+ g_signal_connect (hbox, "add", G_CALLBACK (add_child), expander); -+ -+ if (button_label) { -+ button = gtk_button_new (); -+ text = g_markup_printf_escaped ("<small>%s</small>", button_label); -+ label = gtk_label_new (text); -+ g_free (text); -+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE); -+ gtk_container_add (GTK_CONTAINER (button), label); -+ -+ alignment = gtk_alignment_new (1, 0, 0, 0); -+ gtk_container_add (GTK_CONTAINER (alignment), button); -+ gtk_widget_show_all (alignment); -+ -+ gtk_container_add (GTK_CONTAINER (hbox), alignment); -+ -+ g_signal_connect_swapped (button, "clicked", callback, this); -+ } -+ -+ connect_expander_with_gconf (this, expander, key); - - return vbox; - } -@@ -791,6 +957,12 @@ compare_tasks (GtkTreeModel *model, - } - } - -+static void -+edit_tasks (IntlClockEventsPopup *this) -+{ -+ clock_launch_evolution (this, "--component=tasks"); -+} -+ - static GtkWidget * - create_task_list (IntlClockEventsPopup *this, - GtkWidget **tree_view, -@@ -804,7 +976,9 @@ create_task_list (IntlClockEventsPopup *this, - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - -- vbox = create_hig_frame (_("Tasks")); -+ vbox = create_hig_frame (this, _("Tasks"), _("Edit"), -+ KEY_EXPAND_TASKS, -+ G_CALLBACK (edit_tasks)); - - *scrolled_window = scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), -@@ -812,8 +986,8 @@ create_task_list (IntlClockEventsPopup *this, - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); -- gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0); - gtk_widget_show (scrolled); -+ gtk_container_add (GTK_CONTAINER (vbox), scrolled); - - if (!priv->tasks_model) { - GType column_types [N_TASK_COLUMNS] = { -@@ -984,6 +1158,12 @@ handle_appointments_changed (IntlClockEventsPopup *this) - update_frame_visibility (priv->appointment_list, GTK_TREE_MODEL (priv->appointments_model)); - } - -+static void -+edit_appointments (IntlClockEventsPopup *this) -+{ -+ clock_launch_evolution (this, "--component=calendar"); -+} -+ - static GtkWidget * - create_appointment_list (IntlClockEventsPopup *this, - GtkWidget **tree_view, -@@ -997,7 +1177,9 @@ create_appointment_list (IntlClockEventsPopup *this, - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - -- vbox = create_hig_frame ( _("Appointments")); -+ vbox = create_hig_frame (this, _("Appointments"), _("Edit"), -+ KEY_EXPAND_APPOINTMENTS, -+ G_CALLBACK (edit_appointments)); - - *scrolled_window = scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), -@@ -1005,8 +1187,8 @@ create_appointment_list (IntlClockEventsPopup *this, - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); -- gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0); - gtk_widget_show (scrolled); -+ gtk_container_add (GTK_CONTAINER (vbox), scrolled); - - if (!priv->appointments_model) { - priv->appointments_model = -diff --git a/src/intlclock-events-popup.h b/src/intlclock-events-popup.h -index 84a5183..b88e4c7 100644 ---- a/src/intlclock-events-popup.h -+++ b/src/intlclock-events-popup.h -@@ -2,6 +2,7 @@ - #define __INTLCLOCK_EVENTS_POPUP_H__ - - #include "intlclock.h" -+#include "intlclock-ui.h" - - #include <glib.h> - #include <gtk/gtk.h> -@@ -29,7 +30,8 @@ typedef struct - GType intlclock_events_popup_get_type (void); - - IntlClockEventsPopup *intlclock_events_popup_new (IntlClock *clock, -- PanelApplet *panel_applet); -+ PanelApplet *panel_applet, -+ IntlClockUI *ui); - void intlclock_events_popup_set_date (IntlClockEventsPopup *this, - guint year, guint month, guint mday); - GtkWidget *intlclock_events_popup_get_clock_container (IntlClockEventsPopup *this); -diff --git a/src/intlclock-location-tile.c b/src/intlclock-location-tile.c -index 40d96e3..412ad22 100644 ---- a/src/intlclock-location-tile.c -+++ b/src/intlclock-location-tile.c -@@ -23,9 +23,18 @@ typedef struct { - - IntlClockFaceSize size; - -+ GtkWidget *box; - GtkWidget *clock_face; - GtkWidget *city_label; - GtkWidget *time_label; -+ -+ GtkWidget *current_button; -+ GtkWidget *current_label; -+ GtkWidget *current_marker; -+ GtkSizeGroup *button_group; -+ -+ GtkWidget *weather_icon; -+ - } IntlClockLocationTilePrivate; - - static void intlclock_location_tile_finalize (GObject *); -@@ -36,6 +45,12 @@ static void intlclock_location_tile_refresh (IntlClockLocationTile *this); - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_LOCATION_TILE_TYPE, IntlClockLocationTilePrivate)) - - static void intlclock_location_tile_fill (IntlClockLocationTile *this); -+static void update_weather_icon (IntlClockLocation *loc, WeatherInfo *info, gpointer data); -+static gboolean weather_tooltip (GtkWidget *widget, -+ gint x, gint y, -+ gboolean keyboard_mode, -+ GtkTooltip *tooltip, -+ gpointer data); - - IntlClockLocationTile * - intlclock_location_tile_new (IntlClock *clock, IntlClockUI *ui, -@@ -56,13 +71,17 @@ intlclock_location_tile_new (IntlClock *clock, IntlClockUI *ui, - priv->location = g_object_ref (loc); - priv->size = size; - -- gtk_alignment_set (GTK_ALIGNMENT (this), 0.0, 0.0, 0.0, 0.0); -- gtk_alignment_set_padding (GTK_ALIGNMENT (this), 3, 3, 3, 3); -- - intlclock_location_tile_fill (this); - -- g_signal_connect (G_OBJECT (priv->clock), "tick", -- G_CALLBACK (intlclock_location_tile_tick), this); -+ update_weather_icon (loc, intlclock_location_get_weather_info (loc), this); -+ gtk_widget_set_has_tooltip (priv->weather_icon, TRUE); -+ -+ g_signal_connect (priv->weather_icon, "query-tooltip", -+ G_CALLBACK (weather_tooltip), this); -+ g_signal_connect (G_OBJECT (loc), "weather-updated", -+ G_CALLBACK (update_weather_icon), this); -+ g_signal_connect (G_OBJECT (priv->clock), "tick", -+ G_CALLBACK (intlclock_location_tile_tick), this); - - return this; - } -@@ -133,13 +152,99 @@ intlclock_location_tile_finalize (GObject *g_obj) - priv->location = NULL; - } - -+ if (priv->button_group) { -+ g_object_unref (priv->button_group); -+ priv->button_group = NULL; -+ } -+ - G_OBJECT_CLASS (intlclock_location_tile_parent_class)->finalize (g_obj); - } - -+static gboolean -+press_on_tile (GtkWidget *widget, -+ GdkEventButton *event, -+ IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ -+ intlclock_blink_location (priv->clock, priv->location); -+ -+ return TRUE; -+} -+ -+static void -+make_current (GtkWidget *widget, IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ GError *error = NULL; -+ GtkWidget *dialog; -+ -+ if (intlclock_location_make_current (priv->location, &error)) { -+ g_signal_emit_by_name (priv->clock, "current-timezone-changed", 0); -+ } -+ else if (error) { -+ dialog = gtk_message_dialog_new (NULL, -+ 0, -+ GTK_MESSAGE_ERROR, -+ GTK_BUTTONS_OK, -+ _("Failed to set the system timezone")); -+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error->message); -+ g_signal_connect (dialog, "response", -+ G_CALLBACK (gtk_widget_destroy), NULL); -+ gtk_window_present (GTK_WINDOW (dialog)); -+ -+ g_error_free (error); -+ } -+} -+ -+static gboolean -+enter_or_leave_tile (GtkWidget *widget, -+ GdkEventCrossing *event, -+ IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ -+ if (event->type == GDK_ENTER_NOTIFY) { -+ gint can_set; -+ -+ can_set = can_set_system_timezone (); -+ if (!intlclock_location_is_current (priv->location) && -+ can_set != 0) { -+ gtk_label_set_markup (GTK_LABEL (priv->current_label), -+ can_set == 1 ? -+ _("<small>Set...</small>") : -+ _("<small>Set</small>")); -+ gtk_widget_show (priv->current_button); -+ } -+ } -+ else { -+ if (event->detail != GDK_NOTIFY_INFERIOR) -+ gtk_widget_hide (priv->current_button); -+ } -+ -+ return TRUE; -+} -+ - static void - intlclock_location_tile_fill (IntlClockLocationTile *this) - { - IntlClockLocationTilePrivate *priv = PRIVATE (this); -+ GtkWidget *align; -+ GtkWidget *strut; -+ GtkWidget *box; -+ -+ priv->box = gtk_event_box_new (); -+ -+ gtk_widget_add_events (priv->box, GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); -+ g_signal_connect (priv->box, "button-press-event", -+ G_CALLBACK (press_on_tile), this); -+ g_signal_connect (priv->box, "enter-notify-event", -+ G_CALLBACK (enter_or_leave_tile), this); -+ g_signal_connect (priv->box, "leave-notify-event", -+ G_CALLBACK (enter_or_leave_tile), this); -+ -+ GtkWidget *alignment = gtk_alignment_new (0, 0, 1, 0); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 0); - - GtkWidget *tile = gtk_hbox_new (FALSE, 6); - GtkWidget *head_section = gtk_vbox_new (FALSE, 0); -@@ -147,21 +252,55 @@ intlclock_location_tile_fill (IntlClockLocationTile *this) - priv->city_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (priv->city_label), 0, 0); - -+ align = gtk_alignment_new (0, 0, 0, 0); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, 3); -+ gtk_container_add (GTK_CONTAINER (align), priv->city_label); -+ gtk_box_pack_start (GTK_BOX (head_section), align, FALSE, FALSE, 0); -+ - priv->time_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (priv->time_label), 0, 0); - -- gtk_box_pack_start (GTK_BOX (head_section), priv->city_label, -- FALSE, FALSE, 0); -- gtk_box_pack_start (GTK_BOX (head_section), priv->time_label, -- FALSE, FALSE, 0); -+ priv->weather_icon = gtk_image_new (); -+ align = gtk_alignment_new (0, 0, 0, 0); -+ gtk_container_add (GTK_CONTAINER (align), priv->weather_icon); -+ -+ box = gtk_hbox_new (FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (head_section), box, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->time_label, FALSE, FALSE, 0); -+ -+ priv->current_button = gtk_button_new (); -+ priv->current_label = gtk_label_new (""); -+ gtk_widget_show (priv->current_label); -+ gtk_widget_set_no_show_all (priv->current_button, TRUE); -+ gtk_container_add (GTK_CONTAINER (priv->current_button), priv->current_label); -+ gtk_widget_set_tooltip_text (priv->current_button, _("Set as current timezone for this computer")); -+ -+ priv->current_marker = gtk_image_new_from_icon_name ("go-home", GTK_ICON_SIZE_BUTTON); -+ gtk_widget_set_no_show_all (priv->current_marker, TRUE); -+ -+ align = gtk_alignment_new (1, 1, 0, 0); -+ strut = gtk_event_box_new (); -+ gtk_box_pack_start (GTK_BOX (box), strut, TRUE, TRUE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->current_button, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->current_marker, FALSE, FALSE, 0); -+ priv->button_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); -+ gtk_size_group_set_ignore_hidden (priv->button_group, FALSE); -+ gtk_size_group_add_widget (priv->button_group, strut); -+ gtk_size_group_add_widget (priv->button_group, priv->current_button); -+ -+ g_signal_connect (priv->current_button, "clicked", -+ G_CALLBACK (make_current), this); - - priv->clock_face = intlclock_face_new_with_location ( - priv->size, priv->location, head_section); - - gtk_box_pack_start (GTK_BOX (tile), priv->clock_face, FALSE, FALSE, 0); -- gtk_box_pack_start (GTK_BOX (tile), head_section, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (tile), head_section, TRUE, TRUE, 0); - -- gtk_container_add (GTK_CONTAINER (this), tile); -+ gtk_container_add (GTK_CONTAINER (alignment), tile); -+ gtk_container_add (GTK_CONTAINER (priv->box), alignment); -+ gtk_container_add (GTK_CONTAINER (this), priv->box); - - intlclock_location_tile_refresh (this); - } -@@ -231,6 +370,21 @@ intlclock_location_tile_refresh (IntlClockLocationTile *this) - char buf[256]; - struct tm now; - -+ if (intlclock_location_is_current (priv->location)) { -+ if (!GTK_WIDGET_VISIBLE (priv->current_marker)) { -+ GdkPixbuf *pixbuf; -+ -+ pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (priv->weather_icon)); -+ intlclock_ui_update_weather_icon (priv->ui, pixbuf); -+ } -+ -+ gtk_widget_hide (priv->current_button); -+ gtk_widget_show (priv->current_marker); -+ } -+ else { -+ gtk_widget_hide (priv->current_marker); -+ } -+ - if (intlclock_needs_face_refresh (this)) { - intlclock_face_refresh (INTLCLOCK_FACE (priv->clock_face)); - } -@@ -271,3 +425,86 @@ intlclock_location_tile_tick (IntlClock *clock, - - intlclock_location_tile_refresh (this); - } -+ -+static gboolean -+weather_tooltip (GtkWidget *widget, -+ gint x, -+ gint y, -+ gboolean keyboard_mode, -+ GtkTooltip *tooltip, -+ gpointer data) -+{ -+ IntlClockLocationTile *tile = data; -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ WeatherInfo *info; -+ GdkPixbuf *pixbuf = NULL; -+ gchar *conditions, *temp, *apparent, *wind; -+ gchar *line1, *line2, *line3, *line4, *tip; -+ -+ info = intlclock_location_get_weather_info (priv->location); -+ -+ if (!info || !weather_info_is_valid (info)) -+ return FALSE; -+ -+ weather_info_get_pixbuf (info, &pixbuf); -+ if (pixbuf) -+ gtk_tooltip_set_icon (tooltip, pixbuf); -+ -+ conditions = weather_info_get_conditions (info); -+ if (strcmp (conditions, "-") != 0) -+ line1 = g_strdup_printf (_("%s, %s"), -+ conditions, -+ weather_info_get_sky (info)); -+ else -+ line1 = g_strdup (weather_info_get_sky (info)); -+ -+ temp = weather_info_get_temp (info); -+ apparent = weather_info_get_apparent (info); -+ if (strcmp (apparent, temp) != 0 && -+ /* FIXME libgweather needs some real api */ -+ strcmp (apparent, dgettext ("gnome-applets-2.0", "Unknown")) != 0) -+ line2 = g_strdup_printf (_("%s, feels like %s"), temp, apparent); -+ else -+ line2 = g_strdup (temp); -+ -+ wind = weather_info_get_wind (info); -+ if (strcmp (apparent, dgettext ("gnome-applets-2.0", "Unknown")) != 0) -+ line3 = g_strdup_printf ("%s\n", wind); -+ else -+ line3 = g_strdup (""); -+ -+ line4 = g_strdup_printf (_("Sunrise: %s / Sunset: %s"), -+ weather_info_get_sunrise (info), -+ weather_info_get_sunset (info)); -+ -+ tip = g_strdup_printf ("<b>%s</b>\n%s\n%s%s", line1, line2, line3, line4); -+ gtk_tooltip_set_markup (tooltip, tip); -+ g_free (line1); -+ g_free (line2); -+ g_free (line3); -+ g_free (line4); -+ g_free (tip); -+ -+ return TRUE; -+} -+ -+ -+static void -+update_weather_icon (IntlClockLocation *loc, WeatherInfo *info, gpointer data) -+{ -+ IntlClockLocationTile *tile = data; -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ GdkPixbuf *pixbuf = NULL; -+ -+ if (!info || !weather_info_is_valid (info)) -+ return; -+ -+ weather_info_get_pixbuf_mini (info, &pixbuf); -+ -+ if (pixbuf) { -+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->weather_icon), pixbuf); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (gtk_widget_get_parent (priv->weather_icon)), 0, 0, 0, 6); -+ intlclock_ui_update_weather_icon (priv->ui, pixbuf); -+ } -+} -+ -diff --git a/src/intlclock-location.c b/src/intlclock-location.c -index 384b2aa..911505c 100644 ---- a/src/intlclock-location.c -+++ b/src/intlclock-location.c -@@ -1,4 +1,3 @@ --#include "intlclock-location.h" - - #ifdef HAVE_CONFIG_H - #include <config.h> -@@ -13,9 +12,16 @@ - #include <sys/stat.h> - #include <time.h> - #include <unistd.h> -+#include <math.h> - - #include <glib.h> - #include <libgnome/gnome-i18n.h> -+#include <libgnomevfs/gnome-vfs.h> -+ -+#include "intlclock-location.h" -+#include "intlclock-marshallers.h" -+#include "set-timezone.h" -+#include "gweather-xml.h" - - G_DEFINE_TYPE (IntlClockLocation, intlclock_location, G_TYPE_OBJECT) - -@@ -29,17 +35,31 @@ typedef struct { - - gfloat latitude; - gfloat longitude; -+ -+ gchar *weather_code; -+ WeatherInfo *weather_info; -+ guint weather_timeout; -+ - } IntlClockLocationPrivate; - -+enum { -+ WEATHER_UPDATED, -+ LAST_SIGNAL -+}; -+ -+static guint location_signals[LAST_SIGNAL] = { 0 }; -+ - static void intlclock_location_finalize (GObject *); - static void intlclock_location_set_tz (IntlClockLocation *this); - static void intlclock_location_unset_tz (IntlClockLocation *this); -+static void setup_weather_updates (IntlClockLocation *loc); - - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_LOCATION_TYPE, IntlClockLocationPrivate)) - - IntlClockLocation * - intlclock_location_new (const gchar *name, const gchar *timezone, -- gfloat latitude, gfloat longitude) -+ gfloat latitude, gfloat longitude, -+ const gchar *code) - { - IntlClockLocation *this; - IntlClockLocationPrivate *priv; -@@ -62,6 +82,14 @@ intlclock_location_new (const gchar *name, const gchar *timezone, - priv->latitude = latitude; - priv->longitude = longitude; - -+ if (code) -+ priv->weather_code = g_strdup (code); -+ else -+ priv->weather_code = find_weather_code (name, -+ latitude * M_PI/180.0, -+ longitude * M_PI/180.0); -+ setup_weather_updates (this); -+ - return this; - } - -@@ -193,6 +221,77 @@ guess_zone_from_tree (const gchar *localtime, IntlClockZoneTable *zones) - return ret; - } - -+static const gchar *current_zone = NULL; -+static GnomeVFSMonitorHandle *monitor = NULL; -+ -+static void -+parse_etc_sysconfig_clock (void) -+{ -+ gchar *data; -+ gsize len; -+ gchar **lines; -+ gchar *res; -+ gint i; -+ gchar *p, *q; -+ -+ lines = NULL; -+ res = NULL; -+ if (g_file_test ("/etc/sysconfig/clock", -+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { -+ if (!g_file_get_contents ("/etc/sysconfig/clock", -+ &data, &len, NULL)) -+ goto out; -+ -+ lines = g_strsplit (data, "\n", 0); -+ g_free (data); -+ -+ for (i = 0; lines[i] && !res; i++) { -+ if (g_str_has_prefix (lines[i], "ZONE=")) { -+ p = lines[i] + strlen ("ZONE="); -+ if (p[0] != '\"') -+ goto out; -+ p++; -+ q = strchr (p, '\"'); -+ q[0] = '\0'; -+ res = g_strdup (p); -+ } -+ } -+ } -+ -+out: -+ if (lines) -+ g_strfreev (lines); -+ -+ g_free (current_zone); -+ current_zone = res; -+} -+ -+static void -+monitor_etc_sysconfig_clock (GnomeVFSMonitorHandle *handle, -+ const gchar *monitor_uri, -+ const gchar *info_uri, -+ GnomeVFSMonitorEventType event_type, -+ gpointer user_data) -+{ -+ parse_etc_sysconfig_clock (); -+} -+ -+static const gchar * -+zone_from_etc_sysconfig_clock (void) -+{ -+ if (monitor == NULL) { -+ parse_etc_sysconfig_clock (); -+ -+ gnome_vfs_monitor_add (&monitor, -+ "/etc/sysconfig/clock", -+ GNOME_VFS_MONITOR_FILE, -+ monitor_etc_sysconfig_clock, -+ NULL); -+ } -+ -+ return current_zone; -+} -+ - static gchar * - intlclock_location_guess_zone (IntlClockZoneTable *zones) - { -@@ -200,6 +299,12 @@ intlclock_location_guess_zone (IntlClockZoneTable *zones) - const char *localtime = "/etc/localtime"; - gchar *linkfile = NULL; - GError *err = NULL; -+ gchar *zone; -+ -+ /* look for /etc/sysconfig/clock */ -+ if ((zone = zone_from_etc_sysconfig_clock ())) { -+ return g_strdup (zone); -+ } - - /* guess the current time zone by readlink() on /etc/localtime */ - linkfile = g_file_read_link (localtime, &err); -@@ -235,14 +340,14 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) - - if (zone == NULL) { - /* make a fake location with a null TZ */ -- return intlclock_location_new (_("Unknown Location"), NULL, 0.0, 0.0); -+ return intlclock_location_new (_("Unknown Location"), NULL, 0.0, 0.0, NULL); - } - - info = intlclock_zonetable_get_zone (zones, zone); - - if (info == NULL) { - /* make a fake location with the current TZ */ -- return intlclock_location_new (_("Unknown Location"), zone, 0.0, 0.0); -+ return intlclock_location_new (_("Unknown Location"), zone, 0.0, 0.0, NULL); - } - - g_free (zone); -@@ -260,7 +365,7 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) - } - - ret = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), -- lat, lon); -+ lat, lon, NULL); - - g_free (name); - -@@ -274,6 +379,15 @@ intlclock_location_class_init (IntlClockLocationClass *this_class) - - g_obj_class->finalize = intlclock_location_finalize; - -+ location_signals[WEATHER_UPDATED] = -+ g_signal_new ("weather-updated", -+ G_OBJECT_CLASS_TYPE (g_obj_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (IntlClockLocationClass, weather_updated), -+ NULL, NULL, -+ _intlclock_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, G_TYPE_POINTER); -+ - g_type_class_add_private (this_class, sizeof (IntlClockLocationPrivate)); - } - -@@ -318,6 +432,21 @@ intlclock_location_finalize (GObject *g_obj) - priv->tzname = NULL; - } - -+ if (priv->weather_code) { -+ g_free (priv->weather_code); -+ priv->weather_code = NULL; -+ } -+ -+ if (priv->weather_info) { -+ weather_info_free (priv->weather_info); -+ priv->weather_info = NULL; -+ } -+ -+ if (priv->weather_timeout) { -+ g_source_remove (priv->weather_timeout); -+ priv->weather_timeout = 0; -+ } -+ - G_OBJECT_CLASS (intlclock_location_parent_class)->finalize (g_obj); - } - -@@ -467,3 +596,156 @@ intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm) - - intlclock_location_unset_tz (loc); - } -+ -+gboolean -+intlclock_location_is_current (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ gboolean current; -+ long sys_timezone; -+ const char *zone; -+ -+ if ((zone = zone_from_etc_sysconfig_clock ())) -+ return strcmp (zone, priv->timezone) == 0; -+ -+ unsetenv ("TZ"); -+ tzset (); -+ sys_timezone = timezone; -+ -+ setenv ("TZ", priv->timezone, 1); -+ tzset(); -+ -+ current = sys_timezone == timezone; -+ -+ if (priv->sys_timezone) { -+ setenv ("TZ", priv->sys_timezone, 1); -+ } else { -+ unsetenv ("TZ"); -+ } -+ tzset(); -+ -+ return current; -+} -+ -+gboolean -+intlclock_location_make_current (IntlClockLocation *loc, GError **error) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ gchar *filename; -+ gboolean ret; -+ -+ filename = g_build_filename (SYSTEM_ZONEINFODIR, priv->timezone, NULL); -+ ret = set_system_timezone (filename, error); -+ g_free (filename); -+ -+ /* FIXME this ugly shortcut is necessary until we move the -+ * current timezone tracking to intlclock.c and emit the -+ * signal from there -+ */ -+ g_free (current_zone); -+ current_zone = g_strdup (priv->timezone); -+ -+ return ret; -+} -+ -+const gchar * -+intlclock_location_get_weather_code (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ return priv->weather_code; -+} -+ -+WeatherInfo * -+intlclock_location_get_weather_info (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ return priv->weather_info; -+} -+ -+static void -+weather_info_updated (WeatherInfo *info, gpointer data) -+{ -+ IntlClockLocation *loc = data; -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ g_signal_emit (loc, location_signals[WEATHER_UPDATED], -+ 0, priv->weather_info); -+} -+ -+static gboolean -+update_weather_info (gpointer data) -+{ -+ IntlClockLocation *loc = data; -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ WeatherPrefs prefs = { -+ FORECAST_STATE, -+ FALSE, -+ NULL, -+ TEMP_UNIT_CENTIGRADE, -+ SPEED_UNIT_MS, -+ PRESSURE_UNIT_MB, -+ DISTANCE_UNIT_KM -+ }; -+ -+ weather_info_update (priv->weather_info, -+ &prefs, weather_info_updated, loc); -+ -+ return TRUE; -+} -+ -+static gchar * -+rad2dms (gfloat lat, gfloat lon) -+{ -+ gchar h, h2; -+ gfloat d, deg, min, d2, deg2, min2; -+ -+ h = lat > 0 ? 'N' : 'S'; -+ d = fabs (lat); -+ deg = floor (d); -+ min = floor (60 * (d - deg)); -+ h2 = lon > 0 ? 'E' : 'W'; -+ d2 = fabs (lon); -+ deg2 = floor (d2); -+ min2 = floor (60 * (d2 - deg2)); -+ return g_strdup_printf ("%02d-%02d%c %02d-%02d%c", -+ (int)deg, (int)min, h, -+ (int)deg2, (int)min2, h2); -+} -+ -+static void -+setup_weather_updates (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ const gchar *code; -+ WeatherLocation *wl; -+ WeatherPrefs prefs = { -+ FORECAST_STATE, -+ FALSE, -+ NULL, -+ TEMP_UNIT_CENTIGRADE, -+ SPEED_UNIT_MS, -+ PRESSURE_UNIT_MB, -+ DISTANCE_UNIT_KM -+ }; -+ gfloat lat, lon; -+ gchar *dms; -+ -+ if (!priv->weather_code || strcmp (priv->weather_code, "-") == 0) -+ return; -+ -+ dms = rad2dms (priv->latitude, priv->longitude); -+ wl = weather_location_new (priv->name, priv->weather_code, -+ NULL, NULL, dms); -+ -+ priv->weather_info = -+ weather_info_new (wl, &prefs, weather_info_updated, loc); -+ -+ priv->weather_timeout = -+ g_timeout_add_seconds (1800, update_weather_info, loc); -+ -+ weather_location_free (wl); -+ g_free (dms); -+} -+ -diff --git a/src/intlclock-location.h b/src/intlclock-location.h -index 824ee3c..a3856e7 100644 ---- a/src/intlclock-location.h -+++ b/src/intlclock-location.h -@@ -4,6 +4,7 @@ - #include <time.h> - #include <glib.h> - #include <glib-object.h> -+#include <libgweather/weather.h> - - #include "intlclock-zonetable.h" - -@@ -24,12 +25,16 @@ typedef struct - typedef struct - { - GObjectClass g_object_class; -+ -+ void (* weather_updated) (IntlClockLocation *location, WeatherInfo *info); -+ - } IntlClockLocationClass; - - GType intlclock_location_get_type (void); - - IntlClockLocation *intlclock_location_new (const gchar *name, const gchar *timezone, -- gfloat latitude, gfloat longitude); -+ gfloat latitude, gfloat longitude, -+ const gchar *code); - - IntlClockLocation *intlclock_location_new_from_env (IntlClockZoneTable *zones); - -@@ -46,5 +51,11 @@ void intlclock_location_set_coords (IntlClockLocation *loc, gfloat latitude, gfl - - void intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm); - -+gboolean intlclock_location_is_current (IntlClockLocation *loc); -+gboolean intlclock_location_make_current (IntlClockLocation *loc, GError **error); -+ -+const gchar *intlclock_location_get_weather_code (IntlClockLocation *loc); -+WeatherInfo *intlclock_location_get_weather_info (IntlClockLocation *loc); -+ - G_END_DECLS - #endif /* __INTLCLOCK_LOCATION_H__ */ -diff --git a/src/intlclock-map.c b/src/intlclock-map.c -index 2d72975..9ded127 100644 ---- a/src/intlclock-map.c -+++ b/src/intlclock-map.c -@@ -25,7 +25,7 @@ typedef struct { - gint height; - - GdkPixbuf *stock_map_pixbuf; -- GdkPixbuf *location_marker_pixbuf; -+ GdkPixbuf *location_marker_pixbuf[3]; - - GdkPixbuf *location_map_pixbuf; - -@@ -54,6 +54,7 @@ static void intlclock_map_display (IntlClockMap *this); - - - static void intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this); -+static void intlclock_map_blink_location (IntlClock *clock, IntlClockLocation *loc, IntlClockMap *this); - static void intlclock_map_tick (IntlClock *clock, IntlClockMap *this); - - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_MAP_TYPE, IntlClockMapPrivate)) -@@ -69,8 +70,12 @@ intlclock_map_new (IntlClock *clock) - - priv->clock = g_object_ref (clock); - -- priv->location_marker_pixbuf = rsvg_pixbuf_from_file -- (INTLCLOCK_ICONDIR "/intlclock-map-location-marker.svg", NULL); -+ priv->location_marker_pixbuf[0] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-marker.png", NULL); -+ priv->location_marker_pixbuf[1] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-hilight.png", NULL); -+ priv->location_marker_pixbuf[2] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-current.png", NULL); - - g_signal_connect (G_OBJECT (priv->clock), "tick", - G_CALLBACK (intlclock_map_tick), this); -@@ -78,6 +83,12 @@ intlclock_map_new (IntlClock *clock) - g_signal_connect (G_OBJECT (priv->clock), "locations_changed", - G_CALLBACK (intlclock_map_locations_changed), this); - -+ g_signal_connect (G_OBJECT (priv->clock), "current_timezone_changed", -+ G_CALLBACK (intlclock_map_locations_changed), this); -+ -+ g_signal_connect (G_OBJECT (priv->clock), "blink_location", -+ G_CALLBACK (intlclock_map_blink_location), this); -+ - intlclock_map_refresh (this); - - return this; -@@ -109,13 +120,16 @@ intlclock_map_init (IntlClockMap *this) - priv->clock = NULL; - - priv->stock_map_pixbuf = NULL; -- priv->location_marker_pixbuf = NULL; -+ priv->location_marker_pixbuf[0] = NULL; -+ priv->location_marker_pixbuf[1] = NULL; -+ priv->location_marker_pixbuf[2] = NULL; - } - - static void - intlclock_map_finalize (GObject *g_obj) - { - IntlClockMapPrivate *priv = PRIVATE (g_obj); -+ int i; - - g_signal_handlers_disconnect_by_func - (priv->clock, G_CALLBACK (intlclock_map_tick), g_obj); -@@ -130,10 +144,12 @@ intlclock_map_finalize (GObject *g_obj) - priv->stock_map_pixbuf = NULL; - } - -- if (priv->location_marker_pixbuf) { -- gdk_pixbuf_unref (priv->location_marker_pixbuf); -- priv->location_marker_pixbuf = NULL; -- } -+ for (i = 0; i < 3; i++) { -+ if (priv->location_marker_pixbuf[i]) { -+ gdk_pixbuf_unref (priv->location_marker_pixbuf[i]); -+ priv->location_marker_pixbuf[i] = NULL; -+ } -+ } - - if (priv->location_map_pixbuf) { - gdk_pixbuf_unref (priv->location_map_pixbuf); -@@ -164,12 +180,13 @@ intlclock_map_refresh (IntlClockMap *this) - IntlClockMapPrivate *priv = PRIVATE (this); - GtkWidget *widget = GTK_WIDGET (this); - GtkWidget *parent = gtk_widget_get_parent (widget); -+ GtkRequisition req; - gint width; - gint height; - -- gtk_widget_size_request (widget, &(widget->requisition)); -- width = widget->requisition.width; -- height = widget->requisition.height; -+ gtk_widget_size_request (widget, &req); -+ width = req.width; -+ height = req.height; - - if (parent) { - if (widget->allocation.width != 1) { -@@ -276,10 +293,10 @@ intlclock_map_size_allocate (GtkWidget *this, GtkAllocation *allocation) - } - - static void --intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude) -+intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude, gint mark) - { - IntlClockMapPrivate *priv = PRIVATE (this); -- GdkPixbuf *marker = priv->location_marker_pixbuf; -+ GdkPixbuf *marker = priv->location_marker_pixbuf[mark]; - GdkPixbuf *partial = NULL; - - int x, y; -@@ -395,14 +412,22 @@ intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude) - } - - static void --intlclock_map_place_location (IntlClockMap *this, IntlClockLocation *loc) -+intlclock_map_place_location (IntlClockMap *this, IntlClockLocation *loc, gboolean hilight) - { - IntlClockMapPrivate *priv = PRIVATE (this); - gfloat latitude, longitude; -+ gint marker; - - intlclock_location_get_coords (loc, &latitude, &longitude); - -- intlclock_map_mark (this, latitude, longitude); -+ if (hilight) -+ marker = 1; -+ else if (intlclock_location_is_current (loc)) -+ marker = 2; -+ else -+ marker = 0; -+ -+ intlclock_map_mark (this, latitude, longitude, marker); - } - - static void -@@ -428,7 +453,7 @@ intlclock_map_place_locations (IntlClockMap *this) - while (locs) { - loc = INTLCLOCK_LOCATION (locs->data); - -- intlclock_map_place_location (this, loc); -+ intlclock_map_place_location (this, loc, FALSE); - - locs = locs->next; - } -@@ -633,16 +658,12 @@ intlclock_map_rotate (IntlClockMap *this) - static void - intlclock_map_display (IntlClockMap *this) - { -- IntlClockMapPrivate *priv = PRIVATE (this); -- - gtk_widget_queue_draw (GTK_WIDGET (this)); - } - - static void - intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this) - { -- IntlClockMapPrivate *priv = PRIVATE (this); -- - intlclock_map_place_locations (this); - - intlclock_map_render_shadow (this); -@@ -651,6 +672,49 @@ intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this) - intlclock_map_display (this); - } - -+typedef struct { -+ IntlClockMap *map; -+ IntlClockLocation *location; -+ int count; -+} BlinkData; -+ -+static gboolean -+highlight (gpointer user_data) -+{ -+ BlinkData *data = user_data; -+ -+ if (data->count == 6) { -+ g_free (data); -+ return FALSE; -+ } -+ -+ if (data->count % 2 == 0) -+ intlclock_map_place_location (data->map, data->location, TRUE); -+ else -+ intlclock_map_place_locations (data->map); -+ intlclock_map_render_shadow (data->map); -+ intlclock_map_rotate (data->map); -+ intlclock_map_display (data->map); -+ -+ data->count++; -+ -+ return TRUE; -+} -+ -+static void -+intlclock_map_blink_location (IntlClock *clock, IntlClockLocation *loc, IntlClockMap *this) -+{ -+ BlinkData *data; -+ -+ data = g_new0 (BlinkData, 1); -+ data->map = this; -+ data->location = loc; -+ -+ highlight (data); -+ -+ g_timeout_add (300, highlight, data); -+} -+ - static gboolean - intlclock_map_needs_refresh (IntlClockMap *this) - { -diff --git a/src/intlclock-marshallers.c b/src/intlclock-marshallers.c -deleted file mode 100644 -index 8f01ab8..0000000 ---- a/src/intlclock-marshallers.c -+++ /dev/null -@@ -1,51 +0,0 @@ -- --#include <glib-object.h> -- -- --#ifdef G_ENABLE_DEBUG --#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) --#define g_marshal_value_peek_char(v) g_value_get_char (v) --#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) --#define g_marshal_value_peek_int(v) g_value_get_int (v) --#define g_marshal_value_peek_uint(v) g_value_get_uint (v) --#define g_marshal_value_peek_long(v) g_value_get_long (v) --#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) --#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) --#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) --#define g_marshal_value_peek_enum(v) g_value_get_enum (v) --#define g_marshal_value_peek_flags(v) g_value_get_flags (v) --#define g_marshal_value_peek_float(v) g_value_get_float (v) --#define g_marshal_value_peek_double(v) g_value_get_double (v) --#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) --#define g_marshal_value_peek_param(v) g_value_get_param (v) --#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) --#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) --#define g_marshal_value_peek_object(v) g_value_get_object (v) --#else /* !G_ENABLE_DEBUG */ --/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. -- * Do not access GValues directly in your code. Instead, use the -- * g_value_get_*() functions -- */ --#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int --#define g_marshal_value_peek_char(v) (v)->data[0].v_int --#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint --#define g_marshal_value_peek_int(v) (v)->data[0].v_int --#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint --#define g_marshal_value_peek_long(v) (v)->data[0].v_long --#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong --#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 --#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 --#define g_marshal_value_peek_enum(v) (v)->data[0].v_long --#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong --#define g_marshal_value_peek_float(v) (v)->data[0].v_float --#define g_marshal_value_peek_double(v) (v)->data[0].v_double --#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer --#endif /* !G_ENABLE_DEBUG */ -- -- --/* VOID:VOID (intlclock-marshallers.list:1) */ -- -diff --git a/src/intlclock-marshallers.h b/src/intlclock-marshallers.h -deleted file mode 100644 -index c022a3e..0000000 ---- a/src/intlclock-marshallers.h -+++ /dev/null -@@ -1,15 +0,0 @@ -- --#ifndef ___intlclock_marshal_MARSHAL_H__ --#define ___intlclock_marshal_MARSHAL_H__ -- --#include <glib-object.h> -- --G_BEGIN_DECLS -- --/* VOID:VOID (intlclock-marshallers.list:1) */ --#define _intlclock_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID -- --G_END_DECLS -- --#endif /* ___intlclock_marshal_MARSHAL_H__ */ -- -diff --git a/src/intlclock-marshallers.list b/src/intlclock-marshallers.list -index 5b76282..e737cac 100644 ---- a/src/intlclock-marshallers.list -+++ b/src/intlclock-marshallers.list -@@ -1 +1,3 @@ - VOID:VOID -+VOID:OBJECT -+VOID:POINTER -diff --git a/src/intlclock-sunpos.c b/src/intlclock-sunpos.c -index 942617b..89d4cc1 100644 ---- a/src/intlclock-sunpos.c -+++ b/src/intlclock-sunpos.c -@@ -1,348 +1,196 @@ - /* -- * sunpos.c -- * kirk johnson -- * july 1993 -+ * Copyright (C) 2007 Red Hat, Inc. - * -- * includes revisions from Frank T. Solensky, february 1999 -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. - * -- * code for calculating the position on the earth's surface for which -- * the sun is directly overhead (adapted from _practical astronomy -- * with your calculator, third edition_, peter duffett-smith, -- * cambridge university press, 1988.) -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. - * -- * Copyright (C) 1989, 1990, 1993-1995, 1999 Kirk Lauritz Johnson -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -+ * 02111-1307, USA. - * -- * Parts of the source code (as marked) are: -- * Copyright (C) 1989, 1990, 1991 by Jim Frost -- * Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com> -- * -- * Permission to use, copy, modify and freely distribute xearth for -- * non-commercial and not-for-profit purposes is hereby granted -- * without fee, provided that both the above copyright notice and this -- * permission notice appear in all copies and in supporting -- * documentation. -- * -- * Unisys Corporation holds worldwide patent rights on the Lempel Zev -- * Welch (LZW) compression technique employed in the CompuServe GIF -- * image file format as well as in other formats. Unisys has made it -- * clear, however, that it does not require licensing or fees to be -- * paid for freely distributed, non-commercial applications (such as -- * xearth) that employ LZW/GIF technology. Those wishing further -- * information about licensing the LZW patent should contact Unisys -- * directly at (lzw_info@unisys.com) or by writing to -- * -- * Unisys Corporation -- * Welch Licensing Department -- * M/S-C1SW19 -- * P.O. Box 500 -- * Blue Bell, PA 19424 -- * -- * The author makes no representations about the suitability of this -- * software for any purpose. It is provided "as is" without express or -- * implied warranty. -- * -- * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT -- * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * Authors: -+ * Jonathan Blandford <jrb@redhat.com> -+ * Matthias Clasen <mclasen@redhat.com> - */ -- --#include <assert.h> --#include <math.h> -+ - #include <time.h> -+#include <gtk/gtk.h> -+#include <math.h> - --#include "intlclock-sunpos.h" -- --#define TWOPI (2*M_PI) --#define DegsToRads(x) ((x)*(TWOPI/360)) -- --/* -- * the epoch upon which these astronomical calculations are based is -- * 1990 january 0.0, 631065600 seconds since the beginning of the -- * "unix epoch" (00:00:00 GMT, Jan. 1, 1970) -- * -- * given a number of seconds since the start of the unix epoch, -- * DaysSinceEpoch() computes the number of days since the start of the -- * astronomical epoch (1990 january 0.0) -- */ -- --#define EpochStart (631065600) --#define DaysSinceEpoch(secs) (((secs)-EpochStart)*(1.0/(24*3600))) -- --/* -- * assuming the apparent orbit of the sun about the earth is circular, -- * the rate at which the orbit progresses is given by RadsPerDay -- -- * TWOPI radians per orbit divided by 365.242191 days per year: -- */ -- --#define RadsPerDay (TWOPI/365.242191) -- --/* -- * details of sun's apparent orbit at epoch 1990.0 (after -- * duffett-smith, table 6, section 46) -- * -- * Epsilon_g (ecliptic longitude at epoch 1990.0) 279.403303 degrees -- * OmegaBar_g (ecliptic longitude of perigee) 282.768422 degrees -- * Eccentricity (eccentricity of orbit) 0.016713 -+/* Calculated with the methods and figures from "Practical Astronomy With Your -+ * Calculator, version 3" by Peter Duffet-Smith. - */ -+/* Table 6. Details of the Sun's apparent orbit at epoch 1990.0 */ - --#define Epsilon_g (DegsToRads(279.403303)) --#define OmegaBar_g (DegsToRads(282.768422)) --#define Eccentricity (0.016713) -+#define EPOCH 2447891.5 /* days */ /* epoch 1990 */ -+#define UNIX_EPOCH 2440586.5 /* days */ /* epoch 1970 */ -+#define EPSILON_G 279.403303 /* degrees */ /* ecliptic longitude at epoch 1990.0 */ -+#define MU_G 282.768422 /* degrees */ /* ecliptic longitude at perigree */ -+#define ECCENTRICITY 0.016713 /* eccentricity of orbit */ -+#define R_0 149598500 /* km */ /* semi-major access */ -+#define THETA_0 0.533128 /* degrees */ /* angular diameter at r = r_0 */ -+#define MEAN_OBLIQUITY 23.440592 /* degrees */ /* mean obliquity of earths axis at epoch 1990.0 */ - --/* -- * MeanObliquity gives the mean obliquity of the earth's axis at epoch -- * 1990.0 (computed as 23.440592 degrees according to the method given -- * in duffett-smith, section 27) -- */ --#define MeanObliquity (23.440592*(TWOPI/360)) -+#define NORMALIZE(x) \ -+ while (x>360) x-=360; while (x<0) x+= 360; - --/* -- * Lunar parameters, epoch January 0, 1990.0 -- */ --#define MoonMeanLongitude DegsToRads(318.351648) --#define MoonMeanLongitudePerigee DegsToRads( 36.340410) --#define MoonMeanLongitudeNode DegsToRads(318.510107) --#define MoonInclination DegsToRads( 5.145396) -+#define DEG_TO_RADS(x) \ -+ (x * G_PI/180.0) - --#define SideralMonth (27.3217) -+#define RADS_TO_DEG(x) \ -+ (x * 180.0/G_PI) - --/* -- * Force an angular value into the range [-PI, +PI] -+/* Calculate number of days since 4713BC. - */ --#define Normalize(x) \ -- do { \ -- if ((x) < -M_PI) \ -- do (x) += TWOPI; while ((x) < -M_PI); \ -- else if ((x) > M_PI) \ -- do (x) -= TWOPI; while ((x) > M_PI); \ -- } while (0) -- --static double solve_keplers_equation (double); --static double mean_sun (double); --static double sun_ecliptic_longitude (time_t); --static void ecliptic_to_equatorial (double, double, double *, double *); --static double julian_date (int, int, int); --static double GST (time_t); -- --/* -- * solve Kepler's equation via Newton's method -- * (after duffett-smith, section 47) -- */ --static double solve_keplers_equation(M) -- double M; -+static gdouble -+unix_time_to_julian_date (gint unix_time) - { -- double E; -- double delta; -- -- E = M; -- while (1) -- { -- delta = E - Eccentricity*sin(E) - M; -- if (fabs(delta) <= 1e-10) break; -- E -= delta / (1 - Eccentricity*cos(E)); -- } -- -- return E; -+ return UNIX_EPOCH + (double) unix_time / (60 * 60 * 24); - } - -+/* Finds an iterative solution for [ E - e sin (E) = M ] for values of e less -+ than 0.1. Page 90 */ - --/* -- * Calculate the position of the mean sun: where the sun would -- * be if the earth's orbit were circular instead of ellipictal. -- */ -+#define ERROR_ACCURACY 1e-6 /* radians */ - --static double mean_sun (D) -- double D; /* days since ephemeris epoch */ -+static gdouble -+solve_keplers_equation (gdouble e, -+ gdouble M) - { -- double N, M; -+ gdouble d, E; - -- N = RadsPerDay * D; -- N = fmod(N, TWOPI); -- if (N < 0) N += TWOPI; -+ /* start with an initial estimate */ -+ E = M; -+ -+ d = E - e * sin (E) - M; -+ -+ while (ABS (d) > ERROR_ACCURACY) -+ { -+ E = E - (d / (1 - e * cos (E))); -+ d = E - e * sin (E) - M; -+ } - -- M = N + Epsilon_g - OmegaBar_g; -- if (M < 0) M += TWOPI; -- return M; -+ return E; - } - --/* -- * compute ecliptic longitude of sun (in radians) -- * (after duffett-smith, section 47) -- */ --static double sun_ecliptic_longitude(ssue) -- time_t ssue; /* seconds since unix epoch */ -+ /* convert the ecliptic longitude to right ascension and declination. Section 27. */ -+static void -+ecliptic_to_equatorial (gdouble lambda, -+ gdouble beta, -+ gdouble *ra, -+ gdouble *dec) - { -- double D; -- double M_sun, E; -- double v; -+ gdouble cos_mo; -+ gdouble sin_mo; - -- D = DaysSinceEpoch(ssue); -- M_sun = mean_sun(D); -+ g_assert (ra != NULL); -+ g_assert (dec != NULL); - -- E = solve_keplers_equation(M_sun); -- v = 2 * atan(sqrt((1+Eccentricity)/(1-Eccentricity)) * tan(E/2)); -+ sin_mo = sin (DEG_TO_RADS (MEAN_OBLIQUITY)); -+ cos_mo = cos (DEG_TO_RADS (MEAN_OBLIQUITY)); - -- return (v + OmegaBar_g); -+ *ra = atan2 (sin (lambda) * cos_mo - tan (beta) * sin_mo, cos (lambda)); -+ *dec = asin (sin (beta) * cos_mo + cos (beta) * sin_mo * sin (lambda)); - } - -- --/* -- * convert from ecliptic to equatorial coordinates -- * (after duffett-smith, section 27) -- */ --static void ecliptic_to_equatorial(lambda, beta, alpha, delta) -- double lambda; /* ecliptic longitude */ -- double beta; /* ecliptic latitude */ -- double *alpha; /* (return) right ascension */ -- double *delta; /* (return) declination */ -+/* calculate GST. Section 12 */ -+static gdouble -+greenwich_sidereal_time (gdouble unix_time) - { -- double sin_e, cos_e; -+ gdouble u, JD, T, T0, UT; - -- sin_e = sin(MeanObliquity); -- cos_e = cos(MeanObliquity); -+ u = fmod (unix_time, 24 * 60 * 60); -+ JD = unix_time_to_julian_date (unix_time - u); -+ T = (JD - 2451545) / 36525; -+ T0 = 6.697374558 + (2400.051336 * T) + (0.000025862 * T * T); -+ T0 = fmod (T0, 24); -+ UT = u / (60 * 60); -+ T0 = T0 + UT * 1.002737909; -+ T0 = fmod (T0, 24); - -- *alpha = atan2(sin(lambda)*cos_e - tan(beta)*sin_e, cos(lambda)); -- *delta = asin(sin(beta)*cos_e + cos(beta)*sin_e*sin(lambda)); -+ return T0; - } - -- --/* -- * computing julian dates (assuming gregorian calendar, thus this is -- * only valid for dates of 1582 oct 15 or later) -- * (after duffett-smith, section 4) -- */ --static double julian_date(y, m, d) -- int y; /* year (e.g. 19xx) */ -- int m; /* month (jan=1, feb=2, ...) */ -- int d; /* day of month */ -+/* Calculate the position of the sun at a given time. pages 89-91 */ -+void -+sun_position (gint unix_time, gdouble *lat, gdouble *lon) - { -- int A, B, C, D; -- double JD; -+ gdouble jd, D, N, M, E, x, v, lambda; -+ gdouble ra, dec; -+ jd = unix_time_to_julian_date (unix_time); - -- /* lazy test to ensure gregorian calendar */ -- assert(y >= 1583); -+ /* Calculate number of days since the epoch */ -+ D = jd - EPOCH; - -- if ((m == 1) || (m == 2)) -- { -- y -= 1; -- m += 12; -- } -+ N = D*360/365.242191; - -- A = y / 100; -- B = 2 - A + (A / 4); -- C = 365.25 * y; -- D = 30.6001 * (m + 1); -+ /* normalize to 0 - 360 degrees */ -+ NORMALIZE (N); - -- JD = B + C + D + d + 1720994.5; -+ /* Step 4: */ -+ M = N + EPSILON_G - MU_G; -+ NORMALIZE (M); - -- return JD; --} -- -- --/* -- * compute greenwich mean sidereal time (GST) corresponding to a given -- * number of seconds since the unix epoch -- * (after duffett-smith, section 12) -- */ --static double GST(ssue) -- time_t ssue; /* seconds since unix epoch */ --{ -- double JD; -- double T, T0; -- double UT; -- struct tm *tm; -+ /* Step 5: convert to radians */ -+ M = DEG_TO_RADS (M); - -- tm = gmtime(&ssue); -+ /* Step 6: */ -+ E = solve_keplers_equation (ECCENTRICITY, M); - -- JD = julian_date(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); -- T = (JD - 2451545) / 36525; -+ /* Step 7: */ -+ x = sqrt ((1 + ECCENTRICITY)/(1 - ECCENTRICITY)) * tan (E/2); - -- T0 = ((T + 2.5862e-5) * T + 2400.051336) * T + 6.697374558; -+ /* Step 8, 9 */ -+ v = 2 * RADS_TO_DEG (atan (x)); -+ NORMALIZE (v); - -- T0 = fmod(T0, 24.0); -- if (T0 < 0) T0 += 24; -+ /* Step 10 */ -+ lambda = v + MU_G; -+ NORMALIZE (lambda); - -- UT = tm->tm_hour + (tm->tm_min + tm->tm_sec / 60.0) / 60.0; -+ /* convert the ecliptic longitude to right ascension and declination */ -+ ecliptic_to_equatorial (DEG_TO_RADS (lambda), 0.0, &ra, &dec); - -- T0 += UT * 1.002737909; -- T0 = fmod(T0, 24.0); -- if (T0 < 0) T0 += 24; -+ ra = ra - (G_PI/12) * greenwich_sidereal_time (unix_time); -+ ra = RADS_TO_DEG (ra); -+ dec = RADS_TO_DEG (dec); -+ NORMALIZE (ra); -+ NORMALIZE (dec); - -- return T0; -+ *lat = dec; -+ *lon = ra; - } - - --/* -- * given a particular time (expressed in seconds since the unix -- * epoch), compute position on the earth (lat, lon) such that sun is -- * directly overhead. -- */ --void sun_position(ssue, lat, lon) -- time_t ssue; /* seconds since unix epoch */ -- double *lat; /* (return) latitude */ -- double *lon; /* (return) longitude */ -+#if 0 -+int -+main (int argc, char *argv[]) - { -- double lambda; -- double alpha, delta; -- double tmp; -+ gint i; -+ gint now; -+ GTimeVal timeval; -+ gdouble lat, lon; - -- lambda = sun_ecliptic_longitude(ssue); -- ecliptic_to_equatorial(lambda, 0.0, &alpha, &delta); -+ gtk_init (&argc, &argv); - -- tmp = alpha - (TWOPI/24)*GST(ssue); -- Normalize(tmp); -- *lon = tmp * (360/TWOPI); -- *lat = delta * (360/TWOPI); --} -+ g_get_current_time (&timeval); -+ now = timeval.tv_sec; - -+ for (i = 0; i < now; i += 15 * 60) -+ { -+ sun_position (i, &lat, &lon); -+ g_print ("%d: %f %f\n", lat, lon); -+ } - --/* -- * given a particular time (expressed in seconds since the unix -- * epoch), compute position on the earth (lat, lon) such that the -- * moon is directly overhead. -- * -- * Based on duffett-smith **2nd ed** section 61; combines some steps -- * into single expressions to reduce the number of extra variables. -- */ --void moon_position(ssue, lat, lon) -- time_t ssue; /* seconds since unix epoch */ -- double *lat; /* (return) latitude */ -- double *lon; /* (return) longitude */ --{ -- double lambda, beta; -- double D, L, Ms, Mm, N, Ev, Ae, Ec, alpha, delta; -- -- D = DaysSinceEpoch(ssue); -- lambda = sun_ecliptic_longitude(ssue); -- Ms = mean_sun(D); -- -- L = fmod(D/SideralMonth, 1.0)*TWOPI + MoonMeanLongitude; -- Normalize(L); -- Mm = L - DegsToRads(0.1114041*D) - MoonMeanLongitudePerigee; -- Normalize(Mm); -- N = MoonMeanLongitudeNode - DegsToRads(0.0529539*D); -- Normalize(N); -- Ev = DegsToRads(1.2739) * sin(2.0*(L-lambda)-Mm); -- Ae = DegsToRads(0.1858) * sin(Ms); -- Mm += Ev - Ae - DegsToRads(0.37)*sin(Ms); -- Ec = DegsToRads(6.2886) * sin(Mm); -- L += Ev + Ec - Ae + DegsToRads(0.214) * sin(2.0*Mm); -- L += DegsToRads(0.6583) * sin(2.0*(L-lambda)); -- N -= DegsToRads(0.16) * sin(Ms); -- -- L -= N; -- lambda =(fabs(cos(L)) < 1e-12) ? -- (N + sin(L) * cos(MoonInclination) * M_PI/2) : -- (N + atan2(sin(L) * cos(MoonInclination), cos(L))); -- Normalize(lambda); -- beta = asin(sin(L) * sin(MoonInclination)); -- ecliptic_to_equatorial(lambda, beta, &alpha, &delta); -- alpha -= (TWOPI/24)*GST(ssue); -- Normalize(alpha); -- *lon = alpha * (360/TWOPI); -- *lat = delta * (360/TWOPI); -+ return 0; - } -+ -+#endif -diff --git a/src/intlclock-ui.c b/src/intlclock-ui.c -index f51e4de..a856aef 100644 ---- a/src/intlclock-ui.c -+++ b/src/intlclock-ui.c -@@ -14,6 +14,7 @@ - #include <libgnome/gnome-i18n.h> - #include <locale.h> - #include <math.h> -+#include <time.h> - #include <panel-applet-gconf.h> - #include <stdlib.h> - #include <string.h> -@@ -26,18 +27,17 @@ - #include "intlclock-map.h" - #include "intlclock-zoneinfo.h" - #include "intlclock-zonetable.h" -+#include "set-timezone.h" - - G_DEFINE_TYPE (IntlClockUI, intlclock_ui, G_TYPE_OBJECT) - - /* GConf keys for compatibility with the older GNOME clock */ --#define N_GCONF_PREFS 7 -+#define N_GCONF_PREFS 5 - static const char *KEY_CITIES = "cities"; - static const char *KEY_FORMAT = "format"; - static const char *KEY_SHOW_SECONDS = "show_seconds"; - static const char *KEY_SHOW_DATE = "show_date"; - static const char *KEY_SHOW_WEEK = "show_week_numbers"; --static const char *KEY_SHOW_LOCATIONS = "show_locations"; --static const char *KEY_SHOW_MAP = "show_map"; - - /* Needs to match the indices in the combo */ - typedef enum { -@@ -78,12 +78,14 @@ typedef struct { - GtkWidget *panel_box; - GtkWidget *panel_button; - GtkWidget *panel_label; -+ GtkWidget *panel_weather_icon; - - GtkTooltips *panel_tips; - - GtkWidget *panel_button_popup; - - GtkWidget *clock_vbox; -+ GtkSizeGroup *clock_group; - - GtkWidget *main_section; - GtkWidget *clock_calendar; -@@ -97,12 +99,20 @@ typedef struct { - - GtkListStore *cities_store; - -- gboolean show_locations; -- gboolean show_map; -- - GtkWidget *prefs_window; - GtkTreeView *prefs_locations; - -+ GtkWidget *prefs_location_add_button; -+ GtkWidget *prefs_location_edit_button; -+ GtkWidget *prefs_location_remove_button; -+ -+ GtkWidget *hours_spin; -+ GtkWidget *minutes_spin; -+ GtkWidget *seconds_spin; -+ GtkWidget *calendar; -+ GtkWidget *current_time_label; -+ GtkWidget *set_time_button; -+ - gboolean format_12hr; - gboolean format_show_seconds; - gboolean format_show_date; -@@ -118,9 +128,6 @@ static gboolean update_panel_label (gpointer this); - static void setup_gconf (IntlClockUI *this); - static void load_gconf_settings (IntlClockUI *this); - --static void bonobo_run_time_configuration (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname); - static void bonobo_display_properties_dialog (BonoboUIComponent *uic, - IntlClockUI *this, - const gchar *verbname); -@@ -141,9 +148,8 @@ static void position_popup_window (IntlClockUI *this, - GtkWindow *window, - GtkWidget *origin); - -+static void display_prefs_window (IntlClockUI *this, gboolean locations); - static void display_prefs_window_cb (GtkButton *button, gpointer this); --static void run_time_configuration (IntlClockUI *this); --static void run_time_configuration_cb (GtkButton *button, gpointer this); - static void run_prefs_locations_add (GtkButton *button, gpointer this); - static void run_prefs_locations_edit (GtkButton *button, gpointer this); - static void run_prefs_locations_remove (GtkButton *button, gpointer this); -@@ -162,7 +168,6 @@ static void zone_combo_changed (GtkComboBox *widget, gpointer this); - - static const BonoboUIVerb intlclock_menu_verbs [] = { - BONOBO_UI_UNSAFE_VERB ("IntlClockPreferences", bonobo_display_properties_dialog), -- BONOBO_UI_UNSAFE_VERB ("IntlClockConfig", bonobo_run_time_configuration), - BONOBO_UI_VERB_END - }; - -@@ -206,7 +211,9 @@ intlclock_ui_reset_timeout (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - -- if (GTK_WIDGET_VISIBLE (priv->events_window) || priv->format_show_seconds) { -+ if (GTK_WIDGET_VISIBLE (priv->events_window) || -+ (priv->prefs_window && GTK_WIDGET_VISIBLE (priv->prefs_window)) || -+ priv->format_show_seconds) { - intlclock_set_tick_timeout (INTLCLOCK (priv->clock), 1); - } else { - intlclock_set_tick_timeout (INTLCLOCK (priv->clock), 60); -@@ -435,22 +442,20 @@ intlclock_window_expose_cb (GtkWidget *widget, GdkEventExpose *event, gpointer u - - /* draw map pane background */ - -- if (priv->show_map) { -- cairo_rectangle ( -- cr, -- priv->map_section->allocation.x + 0.5, -- priv->map_section->allocation.y + 0.5, -- priv->map_section->allocation.width - 1, -- priv->map_section->allocation.height - 1); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->bg [GTK_STATE_NORMAL].red / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].green / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].blue / 65535.0); -- -- cairo_fill (cr); -- } -+ cairo_rectangle ( -+ cr, -+ priv->map_section->allocation.x + 0.5, -+ priv->map_section->allocation.y + 0.5, -+ priv->map_section->allocation.width - 1, -+ priv->map_section->allocation.height - 1); -+ -+ cairo_set_source_rgb ( -+ cr, -+ widget->style->bg [GTK_STATE_NORMAL].red / 65535.0, -+ widget->style->bg [GTK_STATE_NORMAL].green / 65535.0, -+ widget->style->bg [GTK_STATE_NORMAL].blue / 65535.0); -+ -+ cairo_fill (cr); - - /* draw internal window outline */ - -@@ -469,47 +474,43 @@ intlclock_window_expose_cb (GtkWidget *widget, GdkEventExpose *event, gpointer u - - /* draw map/cities pane separator */ - -- if (priv->show_map) { -- cairo_move_to ( -- cr, -- priv->map_section->allocation.x + 0.5, -- priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); -+ cairo_move_to ( -+ cr, -+ priv->map_section->allocation.x + 0.5, -+ priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); - -- cairo_line_to ( -- cr, -- priv->map_section->allocation.x + priv->map_section->allocation.width - 0.5, -- priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); -+ cairo_line_to ( -+ cr, -+ priv->map_section->allocation.x + priv->map_section->allocation.width - 0.5, -+ priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); - -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -+ cairo_set_source_rgb ( -+ cr, -+ widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -+ widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -+ widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); - -- cairo_stroke (cr); -- } -+ cairo_stroke (cr); - - /* draw cities/main pane separator */ - -- if (priv->show_locations) { -- cairo_move_to ( -- cr, -- priv->cities_section->allocation.x + 0.5, -- priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); -+ cairo_move_to ( -+ cr, -+ priv->cities_section->allocation.x + 0.5, -+ priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); - -- cairo_line_to ( -- cr, -- priv->cities_section->allocation.x + priv->cities_section->allocation.width - 0.5, -- priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); -+ cairo_line_to ( -+ cr, -+ priv->cities_section->allocation.x + priv->cities_section->allocation.width - 0.5, -+ priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); - -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -+ cairo_set_source_rgb ( -+ cr, -+ widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -+ widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -+ widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); - -- cairo_stroke (cr); -- } -+ cairo_stroke (cr); - - cairo_destroy (cr); - -@@ -532,7 +533,6 @@ intlclock_ui_locations_changed (IntlClock *clock, IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - - create_cities_section (this); -- intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); - } - - static gboolean -@@ -550,12 +550,20 @@ update_panel_label (gpointer this) - time (&now_t); - localtime_r (&now_t, &now); - -+ if (priv->current_time_label && -+ GTK_WIDGET_VISIBLE (priv->current_time_label)) { -+ date = intlclock_format_time (priv->clock, &now, -+ FALSE, FALSE, TRUE, -+ FALSE, FALSE, NULL, TRUE); -+ gtk_label_set_markup (GTK_LABEL (priv->current_time_label), date); -+ g_free (date); -+ } -+ - date = intlclock_format_time (priv->clock, &now, - priv->format_show_date, - priv->format_12hr, - priv->format_show_seconds, - FALSE, priv->format_show_date, NULL, TRUE); -- - gtk_label_set_markup (GTK_LABEL (priv->panel_label), date); - g_free (date); - -@@ -583,6 +591,7 @@ create_panel_buttons (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - PanelAppletOrient orient; -+ GtkWidget *box; - - orient = panel_applet_get_orient (priv->panel_applet); - -@@ -590,13 +599,16 @@ create_panel_buttons (IntlClockUI *this) - case PANEL_APPLET_ORIENT_UP: - case PANEL_APPLET_ORIENT_DOWN: - priv->panel_box = gtk_hbox_new (FALSE, 0); -+ box = gtk_hbox_new (FALSE, 6); - break; - case PANEL_APPLET_ORIENT_RIGHT: - case PANEL_APPLET_ORIENT_LEFT: - priv->panel_box = gtk_vbox_new (FALSE, 0); -+ box = gtk_vbox_new (FALSE, 6); - break; - } - priv->panel_label = gtk_label_new (NULL); -+ priv->panel_weather_icon = gtk_image_new (); - priv->panel_button = gtk_toggle_button_new (); - priv->panel_tips = gtk_tooltips_new (); - -@@ -626,8 +638,9 @@ create_panel_buttons (IntlClockUI *this) - gtk_button_set_relief (GTK_BUTTON (priv->panel_button), - GTK_RELIEF_NONE); - -- gtk_container_add (GTK_CONTAINER (priv->panel_button), -- priv->panel_label); -+ gtk_container_add (GTK_CONTAINER (priv->panel_button), box); -+ gtk_container_add (GTK_CONTAINER (box), priv->panel_weather_icon); -+ gtk_container_add (GTK_CONTAINER (box), priv->panel_label); - - g_signal_connect ( - G_OBJECT (priv->panel_button), "clicked", -@@ -655,12 +668,13 @@ create_panel_buttons (IntlClockUI *this) - ); - - gtk_widget_show (priv->panel_label); -+ gtk_widget_show (priv->panel_weather_icon); -+ gtk_widget_show (box); - - gtk_box_pack_start (GTK_BOX (priv->panel_box), priv->panel_button, - FALSE, FALSE, 0); - -- gtk_container_add (GTK_CONTAINER (priv->panel_applet), -- priv->panel_box); -+ gtk_container_add (GTK_CONTAINER (priv->panel_applet), priv->panel_box); - - gtk_widget_show_all (priv->panel_box); - } -@@ -671,10 +685,16 @@ intlclock_ui_change_orient (PanelApplet *applet, - IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -- -- if (GTK_IS_WIDGET (priv->panel_box)) -- gtk_widget_destroy (priv->panel_box); -+ GdkPixbuf *pixbuf = NULL; -+ -+ if (GTK_IS_WIDGET (priv->panel_box)) { -+ pixbuf = g_object_ref (gtk_image_get_pixbuf (GTK_IMAGE (priv->panel_weather_icon))); -+ gtk_widget_destroy (priv->panel_box); -+ } - create_panel_buttons (this); -+ intlclock_ui_update_weather_icon (this, pixbuf); -+ if (pixbuf) -+ g_object_unref (pixbuf); - } - - static void -@@ -714,7 +734,7 @@ create_events_window (IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - - priv->events_window = -- GTK_WIDGET (intlclock_events_popup_new (priv->clock, priv->panel_applet)); -+ GTK_WIDGET (intlclock_events_popup_new (priv->clock, priv->panel_applet, this)); - - g_signal_connect (G_OBJECT (priv->events_window), "size-allocate", - G_CALLBACK (intlclock_events_window_size_allocate_cb), this); -@@ -723,17 +743,35 @@ create_events_window (IntlClockUI *this) - } - - static void -+add_to_group (GtkWidget *child, gpointer data) -+{ -+ GtkSizeGroup *group = data; -+ -+ gtk_size_group_add_widget (group, child); -+} -+ -+static void - create_clock_window (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - GtkSettings *settings; - GtkStyle *style; -+ GtkWidget *clock_container; - -- priv->clock_vbox = intlclock_events_popup_get_clock_container -+ clock_container = intlclock_events_popup_get_clock_container - (INTLCLOCK_EVENTS_POPUP (priv->events_window)); -- gtk_widget_show (priv->clock_vbox); --} -+ gtk_widget_show (clock_container); - -+ priv->clock_vbox = gtk_vbox_new (FALSE, 6); -+ gtk_container_add (GTK_CONTAINER (clock_container), priv->clock_vbox); -+ -+ priv->clock_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); -+ gtk_size_group_set_ignore_hidden (priv->clock_group, FALSE); -+ -+ gtk_container_foreach (GTK_CONTAINER (clock_container), -+ (GtkCallback)add_to_group, -+ priv->clock_group); -+} - static void - create_main_section (IntlClockUI *this) - { -@@ -750,7 +788,6 @@ create_main_section (IntlClockUI *this) - MAIN_SECTION_PADDING); - gtk_box_pack_end (GTK_BOX (priv->clock_vbox), - priv->main_section, FALSE, FALSE, 0); -- - } else { - gtk_container_foreach (GTK_CONTAINER (priv->main_section), - (GtkCallback)gtk_widget_destroy, -@@ -824,7 +861,7 @@ create_cities_section (IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - GList *node; - IntlClockLocationTile *city; -- GtkWidget *header, *subheader, *image;; -+ GtkWidget *header, *subheader, *image; - GList *cities; - - if (priv->cities_section) { -@@ -832,12 +869,8 @@ create_cities_section (IntlClockUI *this) - priv->cities_section = NULL; - } - -- if (!priv->show_locations) { -- return; -- } -- - priv->cities_section = gtk_vbox_new (FALSE, 6); -- gtk_container_set_border_width (GTK_CONTAINER (priv->cities_section), 8); -+ gtk_container_set_border_width (GTK_CONTAINER (priv->cities_section), 0); - - cities = intlclock_get_locations (priv->clock); - if (g_list_length (cities) == 0) { -@@ -884,10 +917,6 @@ create_map_section (IntlClockUI *this) - priv->map_widget = NULL; - } - -- if (!priv->show_map) { -- return; -- } -- - map = intlclock_map_new (priv->clock); - - priv->map_section = gtk_alignment_new (0, 0, 1, 1); -@@ -895,11 +924,10 @@ create_map_section (IntlClockUI *this) - - gtk_container_add (GTK_CONTAINER (priv->map_section), priv->map_widget); - -- gtk_box_pack_start (GTK_BOX (priv->clock_vbox), -- priv->map_section, FALSE, FALSE, 0); -- - gtk_alignment_set_padding (GTK_ALIGNMENT (priv->map_section), - 1, 1, 1, 1); -+ gtk_box_pack_start (GTK_BOX (priv->clock_vbox), -+ priv->map_section, FALSE, FALSE, 0); - - gtk_widget_show (priv->map_widget); - gtk_widget_show (priv->map_section); -@@ -959,6 +987,8 @@ intlclock_prefs_hide (GtkWidget *widget, IntlClockUI *this) - - gtk_tree_selection_unselect_all - (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree))); -+ -+ intlclock_ui_reset_timeout (this); - } - - static gboolean -@@ -1057,28 +1087,6 @@ set_seconds_check_cb (GtkWidget *widget, IntlClockUI *this) - } - - static void --set_locations_check_cb (GtkWidget *widget, IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- panel_applet_gconf_set_bool (PANEL_APPLET (priv->panel_applet), -- KEY_SHOW_LOCATIONS, -- GTK_TOGGLE_BUTTON (widget)->active, -- NULL); --} -- --static void --set_map_check_cb (GtkWidget *widget, IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- panel_applet_gconf_set_bool (PANEL_APPLET (priv->panel_applet), -- KEY_SHOW_MAP, -- GTK_TOGGLE_BUTTON (widget)->active, -- NULL); --} -- --static void - fill_prefs_window (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -@@ -1087,6 +1095,9 @@ fill_prefs_window (IntlClockUI *this) - GtkCellRenderer *renderer; - GtkTreeViewColumn *col; - -+ time_t now_t; -+ struct tm now; -+ - /* Set the 12 hour / 24 hour widget */ - widget = glade_xml_get_widget (priv->glade_xml, "12hr_radio"); - g_signal_connect (widget, "toggled", -@@ -1109,18 +1120,6 @@ fill_prefs_window (IntlClockUI *this) - g_signal_connect (widget, "toggled", G_CALLBACK (set_seconds_check_cb), - this); - -- /* Set the "Show Locations" checkbox */ -- widget = glade_xml_get_widget (priv->glade_xml, "show_locations_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), priv->show_locations); -- g_signal_connect (widget, "toggled", G_CALLBACK (set_locations_check_cb), -- this); -- -- /* Set the "Show Map" checkbox */ -- widget = glade_xml_get_widget (priv->glade_xml, "show_map_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), priv->show_map); -- g_signal_connect (widget, "toggled", G_CALLBACK (set_map_check_cb), -- this); -- - /* Fill the Cities list */ - widget = glade_xml_get_widget (priv->glade_xml, "cities_list"); - -@@ -1136,6 +1135,15 @@ fill_prefs_window (IntlClockUI *this) - - gtk_tree_view_set_model (GTK_TREE_VIEW (widget), - GTK_TREE_MODEL (priv->cities_store)); -+ -+ /* Fill the time settings */ -+ tzset (); -+ time (&now_t); -+ localtime_r (&now_t, &now); -+ -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->seconds_spin), now.tm_sec); -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->minutes_spin), now.tm_min); -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->hours_spin), now.tm_hour); - } - - static gint -@@ -1150,19 +1158,139 @@ sort_zoneinfo_by_l10n_name (gconstpointer a, gconstpointer b) - return strcmp (name_a, name_b); - } - -+static void -+intlclock_prefs_locations_changed (GtkTreeSelection *selection, -+ IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gint n; -+ -+ n = gtk_tree_selection_count_selected_rows (selection); -+ gtk_widget_set_sensitive (priv->prefs_location_edit_button, n > 0); -+ gtk_widget_set_sensitive (priv->prefs_location_remove_button, n > 0); -+} -+ -+static void -+wrap_cb (GtkSpinButton *spin, -+ IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gdouble value; -+ gdouble min, max; -+ GtkWidget *next; -+ GtkSpinType direction; -+ -+ value = gtk_spin_button_get_value (spin); -+ gtk_spin_button_get_range (spin, &min, &max); -+ -+ if (value == min) -+ direction = GTK_SPIN_STEP_FORWARD; -+ else -+ direction = GTK_SPIN_STEP_BACKWARD; -+ -+ if (spin == (GtkSpinButton *)priv->seconds_spin) -+ gtk_spin_button_spin (GTK_SPIN_BUTTON (priv->minutes_spin), -+ direction, 1.0); -+ else if (spin == (GtkSpinButton *)priv->minutes_spin) -+ gtk_spin_button_spin (GTK_SPIN_BUTTON (priv->hours_spin), -+ direction, 1.0); -+ else { -+ guint year, month, day; -+ GDate *date; -+ -+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), -+ &year, &month, &day); -+ -+ date = g_date_new_dmy (day, month + 1, year); -+ -+ if (direction == GTK_SPIN_STEP_FORWARD) -+ g_date_add_days (date, 1); -+ else -+ g_date_subtract_days (date, 1); -+ -+ year = g_date_get_year (date); -+ month = g_date_get_month (date) - 1; -+ day = g_date_get_day (date); -+ -+ gtk_calendar_select_month (GTK_CALENDAR (priv->calendar), -+ month, year); -+ gtk_calendar_select_day (GTK_CALENDAR (priv->calendar), -+ day); -+ -+ g_date_free (date); -+ } -+} -+ -+static void -+update_set_time_button (IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gint can_set; -+ GtkWidget *box; -+ -+ can_set = can_set_system_time (); -+ box = glade_xml_get_widget (priv->glade_xml, "time_settings_box"); -+ -+ gtk_widget_set_sensitive (box, can_set != 0); -+ gtk_button_set_label (GTK_BUTTON (priv->set_time_button), -+ can_set == 1 ? -+ _("Set System Time...") : -+ _("Set System Time")); -+} -+ -+static void -+set_time_callback (IntlClockUI *this, GError *error) -+{ -+ GtkWidget *dialog; -+ -+ if (error) { -+ dialog = gtk_message_dialog_new (NULL, -+ 0, -+ GTK_MESSAGE_ERROR, -+ GTK_BUTTONS_OK, -+ _("Failed to set the system time")); -+ -+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error->message); -+ g_signal_connect (dialog, "response", -+ G_CALLBACK (gtk_widget_destroy), NULL); -+ gtk_window_present (GTK_WINDOW (dialog)); -+ -+ g_error_free (error); -+ } -+ else -+ update_set_time_button (this); -+} -+ - static void --display_prefs_window (IntlClockUI *this) -+set_time (GtkWidget *widget, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ struct tm t; -+ gint64 time; -+ -+ t.tm_sec = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->seconds_spin)); -+ t.tm_min = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->minutes_spin)); -+ t.tm_hour = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->hours_spin)); -+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), -+ &t.tm_year, &t.tm_mon, &t.tm_mday); -+ t.tm_year -= 1900; -+ -+ time = mktime (&t); -+ -+ set_system_time_async (time, (GFunc)set_time_callback, this, NULL); -+} -+ -+static void -+display_prefs_window (IntlClockUI *this, gboolean locations) - { - IntlClockUIPrivate *priv = PRIVATE (this); - GtkWidget *edit_window; - GtkWidget *prefs_window; - GtkWidget *prefs_close_button; -- GtkWidget *prefs_settings_button; - GtkWidget *edit_cancel_button; - GtkWidget *edit_ok_button; - GtkWidget *zone_combo; -- -- GtkWidget *tmp_button; -+ GtkTreeSelection *selection; - - if (!priv->prefs_window) { - priv->prefs_window = -@@ -1170,38 +1298,36 @@ display_prefs_window (IntlClockUI *this) - - prefs_close_button = - glade_xml_get_widget (priv->glade_xml, "prefs-close-button"); -- -- prefs_settings_button = -- glade_xml_get_widget (priv->glade_xml, "prefs-time-settings-button"); -- - priv->prefs_locations = - GTK_TREE_VIEW (glade_xml_get_widget (priv->glade_xml, "cities_list")); - -+ selection = gtk_tree_view_get_selection (priv->prefs_locations); -+ g_signal_connect (G_OBJECT (selection), "changed", -+ G_CALLBACK (intlclock_prefs_locations_changed), this); -+ -+ - g_signal_connect (G_OBJECT (priv->prefs_window), "delete_event", - G_CALLBACK (intlclock_prefs_hide_event), this); - - g_signal_connect (G_OBJECT (prefs_close_button), "clicked", - G_CALLBACK (intlclock_prefs_hide), this); - -- g_signal_connect (G_OBJECT (prefs_settings_button), "clicked", -- G_CALLBACK (run_time_configuration_cb), this); -- -- tmp_button = -+ priv->prefs_location_remove_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-remove-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_remove_button), "clicked", - G_CALLBACK (run_prefs_locations_remove), this); -- -- tmp_button = -+ -+ priv->prefs_location_add_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-add-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_add_button), "clicked", - G_CALLBACK (run_prefs_locations_add), this); - -- tmp_button = -+ priv->prefs_location_edit_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-edit-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_edit_button), "clicked", - G_CALLBACK (run_prefs_locations_edit), this); - - edit_window = glade_xml_get_widget (priv->glade_xml, -@@ -1234,11 +1360,48 @@ display_prefs_window (IntlClockUI *this) - item. */ - gtk_combo_box_remove_text (GTK_COMBO_BOX (zone_combo), 0); - -+ /* Set up the time setting section */ -+ priv->current_time_label = glade_xml_get_widget (priv->glade_xml, "current_time_label"); -+ priv->set_time_button = glade_xml_get_widget (priv->glade_xml, "set_time_button"); -+ g_signal_connect (priv->set_time_button, "clicked", G_CALLBACK (set_time), this); -+ -+ priv->calendar = glade_xml_get_widget (priv->glade_xml, "calendar"); -+ priv->hours_spin = glade_xml_get_widget (priv->glade_xml, "hours_spin"); -+ priv->minutes_spin = glade_xml_get_widget (priv->glade_xml, "minutes_spin"); -+ priv->seconds_spin = glade_xml_get_widget (priv->glade_xml, "seconds_spin"); -+ -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->hours_spin), 2); -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->minutes_spin), 2); -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->seconds_spin), 2); -+ -+ gtk_entry_set_alignment (GTK_ENTRY (priv->hours_spin), 1.0); -+ gtk_entry_set_alignment (GTK_ENTRY (priv->minutes_spin), 1.0); -+ gtk_entry_set_alignment (GTK_ENTRY (priv->seconds_spin), 1.0); -+ g_signal_connect (priv->seconds_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ g_signal_connect (priv->minutes_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ g_signal_connect (priv->hours_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ - /* fill it with the current preferences */ - fill_prefs_window (this); - } - -+ if (locations) { -+ GtkWidget *notebook = -+ glade_xml_get_widget (priv->glade_xml, "notebook"); -+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1); -+ } -+ -+ update_set_time_button (this); -+ - gtk_window_present (GTK_WINDOW (priv->prefs_window)); -+ -+ intlclock_ui_reset_timeout (this); -+} -+ -+void -+intlclock_ui_edit_locations (IntlClockUI *ui) -+{ -+ display_prefs_window (ui, TRUE); - } - - static void -@@ -1306,16 +1469,11 @@ intlclock_ui_new (IntlClock *clock, PanelApplet *applet) - create_events_window (this); - create_clock_window (this); - create_cities_store (this); -- -- if (priv->show_locations) { -- create_cities_section (this); -- } -- -- if (priv->show_map) { -- create_map_section (this); -- intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); -- } -- -+ create_cities_section (this); -+ create_map_section (this); -+ -+ intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); -+ - intlclock_ui_reset_timeout (this); - - return this; -@@ -1365,9 +1523,6 @@ intlclock_ui_init (IntlClockUI *this) - - priv->cities_store = NULL; - -- priv->show_locations = TRUE; -- priv->show_map = TRUE; -- - priv->prefs_window = NULL; - - priv->format_12hr = TRUE; -@@ -1547,56 +1702,6 @@ gconf_show_week_changed (GConfClient *client, - } - - static void --gconf_show_locations_changed (GConfClient *client, -- guint cnxn_id, -- GConfEntry *entry, -- IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- GtkWidget *widget; -- -- gboolean value; -- -- if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -- return; -- -- value = gconf_value_get_bool (entry->value); -- -- priv->show_locations = (value != 0); -- -- widget = glade_xml_get_widget (priv->glade_xml, "show_locations_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), -- priv->show_locations); -- -- create_cities_section (this); --} -- --static void --gconf_show_map_changed (GConfClient *client, -- guint cnxn_id, -- GConfEntry *entry, -- IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- GtkWidget *widget; -- -- gboolean value; -- -- if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -- return; -- -- value = gconf_value_get_bool (entry->value); -- -- priv->show_map = (value != 0); -- -- widget = glade_xml_get_widget (priv->glade_xml, "show_map_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), -- priv->show_map); -- -- create_map_section (this); --} -- --static void - location_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, -@@ -1614,6 +1719,7 @@ location_start_element (GMarkupParseContext *context, - gchar *timezone = NULL; - gfloat latitude = 0.0; - gfloat longitude = 0.0; -+ gchar *code = NULL; - - int index = 0; - -@@ -1633,6 +1739,8 @@ location_start_element (GMarkupParseContext *context, - sscanf (attribute_values[index], "%f", &latitude); - } else if (strcmp (att_name, "longitude") == 0) { - sscanf (attribute_values[index], "%f", &longitude); -+ } else if (strcmp (att_name, "code") == 0) { -+ code = (gchar *)attribute_values[index]; - } - } - -@@ -1642,7 +1750,7 @@ location_start_element (GMarkupParseContext *context, - return; - } - -- loc = intlclock_location_new (name, timezone, latitude, longitude); -+ loc = intlclock_location_new (name, timezone, latitude, longitude, code); - - *(GList **)user_data = g_list_append (ret, loc); - } -@@ -1713,10 +1821,11 @@ gconf_loc_to_string (IntlClockLocation *loc) - prev_locale = setlocale (LC_NUMERIC, "POSIX"); - - ret = g_markup_printf_escaped -- ("<location name=\"%s\" timezone=\"%s\" latitude=\"%f\" longitude=\"%f\" />", -+ ("<location name=\"%s\" timezone=\"%s\" latitude=\"%f\" longitude=\"%f\" code=\"%s\"/>", - intlclock_location_get_name (loc), - intlclock_location_get_timezone (loc), -- latitude, longitude); -+ latitude, longitude, -+ intlclock_location_get_weather_code (loc)); - - setlocale (LC_NUMERIC, ""); - -@@ -1803,24 +1912,6 @@ setup_gconf (IntlClockUI *this) - g_free (key); - - key = panel_applet_gconf_get_full_key -- (PANEL_APPLET (priv->panel_applet), KEY_SHOW_LOCATIONS); -- priv->listeners [index++] = -- gconf_client_notify_add ( -- client, key, -- (GConfClientNotifyFunc) gconf_show_locations_changed, -- this, NULL, NULL); -- g_free (key); -- -- key = panel_applet_gconf_get_full_key -- (PANEL_APPLET (priv->panel_applet), KEY_SHOW_MAP); -- priv->listeners [index++] = -- gconf_client_notify_add ( -- client, key, -- (GConfClientNotifyFunc) gconf_show_map_changed, -- this, NULL, NULL); -- g_free (key); -- -- key = panel_applet_gconf_get_full_key - (PANEL_APPLET (priv->panel_applet), KEY_CITIES); - priv->listeners [index++] = - gconf_client_notify_add ( -@@ -1868,14 +1959,6 @@ load_gconf_settings (IntlClockUI *this) - panel_applet_gconf_get_bool (priv->panel_applet, - KEY_SHOW_WEEK, NULL); - -- priv->show_locations = -- panel_applet_gconf_get_bool (priv->panel_applet, -- KEY_SHOW_LOCATIONS, NULL); -- -- priv->show_map = -- panel_applet_gconf_get_bool (priv->panel_applet, -- KEY_SHOW_MAP, NULL); -- - values = panel_applet_gconf_get_list (priv->panel_applet, KEY_CITIES, - GCONF_VALUE_STRING, NULL); - -@@ -1894,90 +1977,14 @@ static void bonobo_display_properties_dialog (BonoboUIComponent *uic, - { - IntlClockUIPrivate *priv = PRIVATE (this); - -- display_prefs_window (this); --} -- --static void bonobo_run_time_configuration (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- run_time_configuration (this); -+ display_prefs_window (this, FALSE); - } - - static void display_prefs_window_cb (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - -- display_prefs_window (this); --} -- --static void --run_time_configuration_cb (GtkButton *button, gpointer this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- run_time_configuration (this); --} -- --static void --run_time_configuration (IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- GtkWidget *dialog; -- GError *err; -- char **argv; -- char *path; -- -- GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (priv->events_window)); -- gchar *tool = "/opt/gnome/bin/gnomesu /sbin/yast2 timezone"; -- -- if (!tool || tool[0] == '\0') -- return; -- -- if (!g_shell_parse_argv (tool, NULL, &argv, NULL)) -- return; -- -- if (!(path = g_find_program_in_path (argv [0]))) { -- g_strfreev (argv); -- return; -- } -- -- g_free (path); -- -- err = NULL; -- if (gdk_spawn_on_screen (screen, -- NULL, -- argv, -- NULL, -- G_SPAWN_SEARCH_PATH, -- NULL, -- NULL, -- NULL, -- &err)) { -- g_strfreev (argv); -- return; -- } -- -- g_strfreev (argv); -- -- dialog = gtk_message_dialog_new (NULL, -- GTK_DIALOG_DESTROY_WITH_PARENT, -- GTK_MESSAGE_ERROR, -- GTK_BUTTONS_OK, -- _("Failed to launch time configuration tool: %s"), -- err->message); -- g_error_free (err); -- -- g_signal_connect (dialog, "response", -- G_CALLBACK (gtk_widget_destroy), NULL); -- -- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); -- gtk_window_set_screen (GTK_WINDOW (dialog), screen); -- -- gtk_widget_show_all (dialog); -+ display_prefs_window (this, FALSE); - } - - static void -@@ -2205,7 +2212,7 @@ static void - run_prefs_locations_remove (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -- GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations);; -+ GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations); - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->prefs_locations)); - - gtk_tree_selection_selected_foreach (sel, remove_tree_row, this); -@@ -2230,7 +2237,7 @@ run_prefs_locations_edit (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); - -- GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations);; -+ GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations); - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->prefs_locations)); - - gtk_tree_selection_selected_foreach (sel, edit_tree_row, this); -@@ -2283,7 +2290,7 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - intlclock_location_set_coords (loc, lat, lon); - } else { - GList *locs; -- loc = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), lat, lon); -+ loc = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), lat, lon, NULL); - - locs = g_list_copy (intlclock_get_locations (priv->clock)); - locs = g_list_append (locs, loc); -@@ -2294,3 +2301,11 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - - intlclock_edit_hide (edit_window, this); - } -+ -+void -+intlclock_ui_update_weather_icon (IntlClockUI *ui, GdkPixbuf *pixbuf) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (ui)); -+ -+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->panel_weather_icon), pixbuf); -+} -diff --git a/src/intlclock-ui.h b/src/intlclock-ui.h -index ecbee03..a10099a 100644 ---- a/src/intlclock-ui.h -+++ b/src/intlclock-ui.h -@@ -29,6 +29,8 @@ GType intlclock_ui_get_type (void); - - IntlClockUI *intlclock_ui_new (IntlClock *clock, PanelApplet *applet); - gboolean intlclock_ui_is_12hr (IntlClockUI *ui); -+void intlclock_ui_edit_locations (IntlClockUI *ui); -+void intlclock_ui_update_weather_icon (IntlClockUI *ui, GdkPixbuf *pixbuf); - - G_END_DECLS - #endif /* __INTLCLOCK_UI_H__ */ -diff --git a/src/intlclock.c b/src/intlclock.c -index 02f5b0a..552c45c 100644 ---- a/src/intlclock.c -+++ b/src/intlclock.c -@@ -32,6 +32,8 @@ typedef struct { - enum { - TICK, - LOCATIONS_CHANGED, -+ BLINK_LOCATION, -+ CURRENT_TIMEZONE_CHANGED, - LAST_SIGNAL - }; - -@@ -87,7 +89,25 @@ intlclock_class_init (IntlClockClass *this_class) - _intlclock_marshal_VOID__VOID, - G_TYPE_NONE, 0); - -- g_type_class_add_private (this_class, sizeof (IntlClockPrivate)); -+ intlclock_signals[BLINK_LOCATION] = g_signal_new -+ ("blink-location", -+ G_OBJECT_CLASS_TYPE (obj_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (IntlClockClass, blink_location), -+ NULL, NULL, -+ _intlclock_marshal_VOID__OBJECT, -+ G_TYPE_NONE, 1, INTLCLOCK_LOCATION_TYPE); -+ -+ intlclock_signals[CURRENT_TIMEZONE_CHANGED] = g_signal_new -+ ("current-timezone-changed", -+ G_OBJECT_CLASS_TYPE (obj_class), -+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, -+ G_STRUCT_OFFSET (IntlClockClass, current_timezone_changed), -+ NULL, NULL, -+ _intlclock_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ -+ g_type_class_add_private (this_class, sizeof (IntlClockPrivate)); - } - - static void -@@ -133,7 +153,7 @@ intlclock_set_locations (IntlClock *this, GList *locations) - - priv->locations = locations; - -- g_signal_emit_by_name (this, "locations-changed"); -+ g_signal_emit (this, intlclock_signals[LOCATIONS_CHANGED], 0); - } - - GList * -@@ -202,7 +222,7 @@ intlclock_emit_tick (gpointer data) - IntlClock *this = INTLCLOCK (data); - IntlClockPrivate *priv = PRIVATE (this); - -- g_signal_emit_by_name (this, "tick"); -+ g_signal_emit (this, intlclock_signals[TICK], 0); - - if (priv->in_partial_timeout) { - intlclock_reset_timeout (this); -@@ -353,3 +373,9 @@ intlclock_free_locations (IntlClock *this) - g_list_free (priv->locations); - priv->locations = NULL; - } -+ -+void -+intlclock_blink_location (IntlClock *this, IntlClockLocation *loc) -+{ -+ g_signal_emit (this, intlclock_signals[BLINK_LOCATION], 0, loc); -+} -diff --git a/src/intlclock.h b/src/intlclock.h -index 3b0012c..20c681d 100644 ---- a/src/intlclock.h -+++ b/src/intlclock.h -@@ -27,6 +27,9 @@ typedef struct - - void (* tick) (IntlClock *clock); - void (* locations_changed) (IntlClock *clock); -+ void (* blink_location) (IntlClock *clock, IntlClockLocation *loc); -+ void (* current_timezone_changed) (IntlClock *clock); -+ - } IntlClockClass; - - GType intlclock_get_type (void); -@@ -35,6 +38,7 @@ IntlClock *intlclock_new (void); - - void intlclock_set_locations (IntlClock *this, GList *list); - GList *intlclock_get_locations (IntlClock *this); -+void intlclock_blink_location (IntlClock *this, IntlClockLocation *loc); - - IntlClockZoneTable *intlclock_get_zonetable (IntlClock *this); - gchar *intlclock_format_time (IntlClock *this, struct tm *now, -diff --git a/src/set-timezone.c b/src/set-timezone.c -new file mode 100644 -index 0000000..3233ce3 ---- /dev/null -+++ b/src/set-timezone.c -@@ -0,0 +1,432 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include "config.h" -+#endif -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <string.h> -+#include <sys/wait.h> -+ -+#include <dbus/dbus-glib.h> -+#include <dbus/dbus-glib-lowlevel.h> -+ -+#include <polkit/polkit.h> -+#include <polkit-dbus/polkit-dbus.h> -+ -+static DBusGConnection * -+get_session_bus (void) -+{ -+ GError *error; -+ static DBusGConnection *bus = NULL; -+ -+ if (bus == NULL) { -+ error = NULL; -+ bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); -+ if (bus == NULL) { -+ g_warning ("Couldn't connect to session bus: %s", -+ error->message); -+ g_error_free (error); -+ } -+ } -+ -+ return bus; -+} -+ -+static DBusGConnection * -+get_system_bus (void) -+{ -+ GError *error; -+ static DBusGConnection *bus = NULL; -+ -+ if (bus == NULL) { -+ error = NULL; -+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); -+ if (bus == NULL) { -+ g_warning ("Couldn't connect to system bus: %s", -+ error->message); -+ g_error_free (error); -+ } -+ } -+ -+ return bus; -+} -+ -+static PolKitContext * -+get_pk_context (void) -+{ -+ static PolKitContext *pk_context = NULL; -+ -+ if (pk_context == NULL) { -+ pk_context = polkit_context_new (); -+ if (!polkit_context_init (pk_context, NULL)) { -+ polkit_context_unref (pk_context); -+ pk_context = NULL; -+ } -+ } -+ -+ return pk_context; -+} -+ -+gboolean -+set_system_timezone (const char *filename, GError **err) -+{ -+ DBusGConnection *session_bus; -+ DBusGConnection *system_bus; -+ DBusGProxy *mechanism_proxy; -+ DBusGProxy *polkit_gnome_proxy; -+ gboolean ret = FALSE; -+ -+ session_bus = get_session_bus (); -+ if (session_bus == NULL) -+ goto out; -+ -+ system_bus = get_system_bus (); -+ if (system_bus == NULL) -+ goto out; -+ -+ mechanism_proxy = dbus_g_proxy_new_for_name (system_bus, -+ "org.gnome.ClockApplet.Mechanism", -+ "/", -+ "org.gnome.ClockApplet.Mechanism"); -+ -+ polkit_gnome_proxy = dbus_g_proxy_new_for_name (session_bus, -+ "org.gnome.PolicyKit", -+ "/org/gnome/PolicyKit/Manager", -+ "org.gnome.PolicyKit.Manager"); -+ -+ if (filename != NULL) { -+ GError *error; -+ -+ g_debug ("Trying to set timezone '%s'", filename); -+ try_again: -+ error = NULL; -+ /* first, try to call into the mechanism */ -+ if (!dbus_g_proxy_call_with_timeout (mechanism_proxy, -+ "SetTimezone", -+ INT_MAX, -+ &error, -+ /* parameters: */ -+ G_TYPE_STRING, filename, -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_INVALID)) { -+ if (dbus_g_error_has_name (error, "org.gnome.ClockApplet.Mechanism.NotPrivileged")) { -+ char **tokens; -+ char *polkit_result_textual; -+ char *polkit_action; -+ gboolean gained_privilege; -+ -+ tokens = g_strsplit (error->message, " ", 2); -+ g_error_free (error); -+ if (g_strv_length (tokens) != 2) { -+ g_warning ("helper return string malformed"); -+ g_strfreev (tokens); -+ goto out; -+ } -+ polkit_action = tokens[0]; -+ polkit_result_textual = tokens[1]; -+ -+ g_debug ("helper refused; returned polkit_result='%s' and polkit_action='%s'", -+ polkit_result_textual, polkit_action); -+ -+ /* Now ask the user for auth... */ -+ if (!dbus_g_proxy_call_with_timeout (polkit_gnome_proxy, -+ "ShowDialog", -+ INT_MAX, -+ &error, -+ /* parameters: */ -+ G_TYPE_STRING, polkit_action, -+ G_TYPE_UINT, 0, /* X11 window ID; none */ -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_BOOLEAN, &gained_privilege, -+ G_TYPE_INVALID)) { -+ g_propagate_error (err, error); -+ g_strfreev (tokens); -+ goto out; -+ } -+ g_strfreev (tokens); -+ -+ if (gained_privilege) { -+ g_debug ("Gained privilege; trying to set timezone again"); -+ goto try_again; -+ } -+ -+ } else { -+ g_propagate_error (err, error); -+ } -+ goto out; -+ } -+ -+ g_debug ("Successfully set time zone to '%s'", filename); -+ } -+ -+ ret = TRUE; -+out: -+ g_object_unref (mechanism_proxy); -+ g_object_unref (polkit_gnome_proxy); -+ -+ return ret; -+} -+ -+static gint -+can_do (const gchar *pk_action_id) -+{ -+ DBusConnection *system_bus; -+ PolKitCaller *pk_caller; -+ PolKitAction *pk_action; -+ PolKitResult pk_result; -+ PolKitContext *pk_context; -+ DBusError dbus_error; -+ gint res = 0; -+ -+ system_bus = dbus_g_connection_get_connection (get_system_bus ()); -+ if (system_bus == NULL) -+ goto out; -+ -+ pk_context = get_pk_context (); -+ if (pk_context == NULL) -+ goto out; -+ -+ pk_caller = NULL; -+ pk_action = NULL; -+ -+ pk_action = polkit_action_new (); -+ polkit_action_set_action_id (pk_action, pk_action_id); -+ -+ dbus_error_init (&dbus_error); -+ pk_caller = polkit_caller_new_from_pid (system_bus, getpid (), &dbus_error); -+ if (pk_caller == NULL) { -+ fprintf (stderr, "cannot get caller from dbus name\n"); -+ goto out; -+ } -+ -+ pk_result = polkit_context_can_caller_do_action (pk_context, pk_action, pk_caller); -+ -+ switch (pk_result) { -+ default: -+ case POLKIT_RESULT_UNKNOWN: -+ case POLKIT_RESULT_NO: -+ res = 0; -+ break; -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH: -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION: -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: -+ res = 1; -+ break; -+ case POLKIT_RESULT_YES: -+ res = 2; -+ break; -+ } -+ -+out: -+ if (pk_action != NULL) -+ polkit_action_unref (pk_action); -+ if (pk_caller != NULL) -+ polkit_caller_unref (pk_caller); -+ -+ return res; -+} -+ -+gint -+can_set_system_timezone (void) -+{ -+ return can_do ("org.gnome.clockapplet.mechanism.settimezone"); -+} -+ -+gint -+can_set_system_time (void) -+{ -+ return can_do ("org.gnome.clockapplet.mechanism.settime"); -+} -+ -+typedef struct { -+ gint ref_count; -+ gint64 time; -+ GFunc callback; -+ gpointer data; -+ GDestroyNotify notify; -+} SetTimeCallbackData; -+ -+static void -+free_data (gpointer d) -+{ -+ SetTimeCallbackData *data = d; -+ -+ data->ref_count--; -+ if (data->ref_count == 0) { -+ if (data->notify) -+ data->notify (data->data); -+ g_free (data); -+ } -+} -+ -+static void set_time_async (SetTimeCallbackData *data); -+ -+static void -+auth_notify (DBusGProxy *proxy, -+ DBusGProxyCall *call, -+ void *user_data) -+{ -+ SetTimeCallbackData *data = user_data; -+ GError *error = NULL; -+ gboolean gained_privilege; -+ -+ g_print ("ending async ShowDialog call\n"); -+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_BOOLEAN, &gained_privilege, G_TYPE_INVALID)) { -+ g_print ("result: %d\n", gained_privilege); -+ if (gained_privilege) -+ set_time_async (data); -+ } -+ else { -+ if (data->callback) -+ data->callback (data->data, error); -+ else -+ g_error_free (error); -+ } -+} -+ -+static void -+do_auth_async (const gchar *action, -+ const gchar *result, -+ SetTimeCallbackData *data) -+{ -+ DBusGConnection *bus; -+ DBusGProxy *proxy; -+ -+ g_debug ("helper refused; returned polkit_result='%s' and polkit_action='%s'", -+ result, action); -+ -+ /* Now ask the user for auth... */ -+ bus = get_session_bus (); -+ if (bus == NULL) -+ return; -+ -+ proxy = dbus_g_proxy_new_for_name (bus, -+ "org.gnome.PolicyKit", -+ "/org/gnome/PolicyKit/Manager", -+ "org.gnome.PolicyKit.Manager"); -+ -+ g_print ("beginning async ShowDialog call\n"); -+ data->ref_count++; -+ dbus_g_proxy_begin_call_with_timeout (proxy, -+ "ShowDialog", -+ auth_notify, -+ data, free_data, -+ INT_MAX, -+ G_TYPE_STRING, action, -+ G_TYPE_UINT, 0, -+ G_TYPE_INVALID); -+} -+ -+static void -+set_time_notify (DBusGProxy *proxy, -+ DBusGProxyCall *call, -+ void *user_data) -+{ -+ SetTimeCallbackData *data = user_data; -+ GError *error = NULL; -+ -+ g_print ("ending async SetTime call\n"); -+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { -+ g_print ("calling user callback\n"); -+ if (data->callback) -+ data->callback (data->data, NULL); -+ } -+ else { -+ if (dbus_g_error_has_name (error, "org.gnome.ClockApplet.Mechanism.NotPrivileged")) { -+ gchar **tokens; -+ -+ tokens = g_strsplit (error->message, " ", 2); -+ g_error_free (error); -+ if (g_strv_length (tokens) == 2) -+ do_auth_async (tokens[0], tokens[1], data); -+ else -+ g_warning ("helper return string malformed"); -+ g_strfreev (tokens); -+ } -+ else { -+ if (data->callback) -+ data->callback (data->data, error); -+ else -+ g_error_free (error); -+ } -+ } -+} -+ -+static void -+set_time_async (SetTimeCallbackData *data) -+{ -+ DBusGConnection *bus; -+ DBusGProxy *proxy; -+ DBusGProxyCall *call; -+ -+ bus = get_system_bus (); -+ if (bus == NULL) -+ return; -+ -+ proxy = dbus_g_proxy_new_for_name (bus, -+ "org.gnome.ClockApplet.Mechanism", -+ "/", -+ "org.gnome.ClockApplet.Mechanism"); -+ -+ g_print ("beginning async SetTime call\n"); -+ data->ref_count++; -+ dbus_g_proxy_begin_call_with_timeout (proxy, -+ "SetTime", -+ set_time_notify, -+ data, free_data, -+ INT_MAX, -+ /* parameters: */ -+ G_TYPE_INT64, data->time, -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_INVALID); -+} -+ -+void -+set_system_time_async (gint64 time, -+ GFunc callback, -+ gpointer d, -+ GDestroyNotify notify) -+{ -+ SetTimeCallbackData *data; -+ -+ if (time == -1) -+ return; -+ -+ data = g_new (SetTimeCallbackData, 1); -+ data->ref_count = 1; -+ data->time = time; -+ data->callback = callback; -+ data->data = d; -+ data->notify = notify; -+ -+ set_time_async (data); -+ free_data (data); -+} -diff --git a/src/set-timezone.h b/src/set-timezone.h -new file mode 100644 -index 0000000..c71622c ---- /dev/null -+++ b/src/set-timezone.h -@@ -0,0 +1,36 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ */ -+ -+#ifndef __SET_SYSTEM_TIMEZONE_H__ -+ -+#include <time.h> -+ -+gboolean set_system_timezone (const char *filename, -+ GError **err); -+gint can_set_system_timezone (void); -+ -+gint can_set_system_time (void); -+ -+void set_system_time_async (gint64 time, -+ GFunc callback, -+ gpointer data, -+ GDestroyNotify notify); -+ -+#endif diff --git a/intlclock-changes-20071009.patch b/intlclock-changes-20071009.patch deleted file mode 100644 index 911110a..0000000 --- a/intlclock-changes-20071009.patch +++ /dev/null @@ -1,10832 +0,0 @@ -diff --git a/configure.in b/configure.in -index 4e818da..6c75db1 100644 ---- a/configure.in -+++ b/configure.in -@@ -59,7 +59,7 @@ if test -n "$LIBECAL_REQUIREMENT"; then - fi - AM_CONDITIONAL(HAVE_LIBECAL, test -n "$LIBECAL_REQUIREMENT") - --PKG_CHECK_MODULES(INTLCLOCK, [ glib-2.0 gobject-2.0 gtk+-2.0 gdk-2.0 librsvg-2.0 libpanelapplet-2.0 libgnome-2.0 gconf-2.0 $LIBECAL_REQUIREMENT ]) -+PKG_CHECK_MODULES(INTLCLOCK, [ glib-2.0 gobject-2.0 gtk+-2.0 gdk-2.0 librsvg-2.0 libpanelapplet-2.0 libgnome-2.0 gconf-2.0 $LIBECAL_REQUIREMENT dbus-glib-1 gweather libxml-2.0 polkit polkit-dbus ]) - - AC_SUBST(INTLCLOCK_CFLAGS) - AC_SUBST(INTLCLOCK_LIBS) -diff --git a/data/GNOME_IntlClockApplet.xml b/data/GNOME_IntlClockApplet.xml -index dd2e8b8..a88dc3d 100644 ---- a/data/GNOME_IntlClockApplet.xml -+++ b/data/GNOME_IntlClockApplet.xml -@@ -1,9 +1,14 @@ - <Root> - <popups> - <popup name="button3"> -+ <menuitem name="Clock Copy Time Item" verb="ClockCopyTime" _label="Copy _Time" -+ pixtype="stock" pixname="gtk-copy"/> -+ <menuitem name="Clock Copy Date Item" verb="ClockCopyDate" _label="Copy _Date" -+ pixtype="stock" pixname="gtk-copy"/> -+ <separator/> - <menuitem name="Clock Configure Item" verb="IntlClockConfig" -- _label="Cha_nge Date or Time" -- pixtype="stock" pixname="gtk-preferences"/> -+ _label="Ad_just Date & Time" -+ pixtype="stock" pixname="gtk-preferences"/> - <menuitem name="Clock Preferences Item" verb="IntlClockPreferences" _label="_Preferences" - pixtype="stock" pixname="gtk-properties"/> - </popup> -diff --git a/data/GNOME_IntlClockApplet_Factory.server.in.in b/data/GNOME_IntlClockApplet_Factory.server.in.in -index 1446822..705fb76 100644 ---- a/data/GNOME_IntlClockApplet_Factory.server.in.in -+++ b/data/GNOME_IntlClockApplet_Factory.server.in.in -@@ -20,7 +20,7 @@ - </oaf_attribute> - <oaf_attribute name="name" type="string" value="International Clock"/> - <oaf_attribute name="description" type="string" value="International Clock applet for the GNOME panel"/> -- <oaf_attribute name="panel:icon" type="string" value="clock.png"/> -+ <oaf_attribute name="panel:icon" type="string" value="gnome-panel-clock"/> - </oaf_server> - - <oaf_server iid="OAFIID:GNOME_ClockApplet" -diff --git a/data/intlclock.glade b/data/intlclock.glade -index e7b8c01..626d835 100644 ---- a/data/intlclock.glade -+++ b/data/intlclock.glade -@@ -21,12 +21,13 @@ - - <child> - <widget class="GtkVBox" id="vbox1"> -+ <property name="border_width">6</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> -- <widget class="GtkNotebook" id="notebook1"> -+ <widget class="GtkNotebook" id="notebook"> - <property name="border_width">6</property> - <property name="visible">True</property> - <property name="can_focus">True</property> -@@ -37,194 +38,35 @@ - <property name="enable_popup">False</property> - - <child> -- <widget class="GtkTable" id="table1"> -- <property name="border_width">6</property> -+ <widget class="GtkVBox" id="vbox17"> -+ <property name="border_width">12</property> - <property name="visible">True</property> -- <property name="n_rows">4</property> -- <property name="n_columns">3</property> - <property name="homogeneous">False</property> -- <property name="row_spacing">6</property> -- <property name="column_spacing">6</property> -+ <property name="spacing">18</property> - - <child> -- <widget class="GtkLabel" id="label11"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Clock options:</property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label12"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label13"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">3</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label14"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label15"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="seconds_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show s_econds</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">3</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">3</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkHBox" id="hbox3"> -+ <widget class="GtkVBox" id="vbox18"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> -- <widget class="GtkRadioButton" id="12hr_radio"> -+ <widget class="GtkLabel" id="label210"> - <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">12 _hour format</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -+ <property name="label" translatable="yes"><b>Clock Options</b></property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">True</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> -@@ -234,138 +76,150 @@ - </child> - - <child> -- <widget class="GtkRadioButton" id="24hr_radio"> -+ <widget class="GtkHBox" id="hbox48"> - <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">24 h_our format</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- <property name="group">12hr_radio</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label211"> -+ <property name="visible">True</property> -+ <property name="label"> </property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox19"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox49"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">13</property> -+ -+ <child> -+ <widget class="GtkRadioButton" id="12hr_radio"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">12 _hour format</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkRadioButton" id="24hr_radio"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">24 h_our format</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ <property name="group">12hr_radio</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkCheckButton" id="date_check"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Show the _date</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkCheckButton" id="seconds_check"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Show _seconds</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ <property name="active">False</property> -+ <property name="inconsistent">False</property> -+ <property name="draw_indicator">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> - </widget> - <packing> - <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="date_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show the _date</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label16"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label17"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label201"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">3</property> -- <property name="bottom_attach">4</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">True</property> - </packing> - </child> - </widget> -@@ -376,7 +230,7 @@ - </child> - - <child> -- <widget class="GtkLabel" id="label1"> -+ <widget class="GtkLabel" id="label209"> - <property name="visible">True</property> - <property name="label" translatable="yes">General</property> - <property name="use_underline">False</property> -@@ -399,332 +253,105 @@ - </child> - - <child> -- <widget class="GtkTable" id="table5"> -- <property name="border_width">6</property> -+ <widget class="GtkVBox" id="vbox24"> -+ <property name="border_width">12</property> - <property name="visible">True</property> -- <property name="n_rows">8</property> -- <property name="n_columns">4</property> - <property name="homogeneous">False</property> -- <property name="row_spacing">6</property> -- <property name="column_spacing">6</property> -- -- <child> -- <widget class="GtkLabel" id="label36"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label37"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -+ <property name="spacing">18</property> - - <child> -- <widget class="GtkScrolledWindow" id="scrolledwindow2"> -+ <widget class="GtkHBox" id="hbox54"> - <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> -- <property name="vscrollbar_policy">GTK_POLICY_NEVER</property> -- <property name="shadow_type">GTK_SHADOW_IN</property> -- <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">12</property> - - <child> -- <widget class="GtkTreeView" id="cities_list"> -+ <widget class="GtkScrolledWindow" id="scrolledwindow10"> - <property name="visible">True</property> - <property name="can_focus">True</property> -- <property name="headers_visible">False</property> -- <property name="rules_hint">False</property> -- <property name="reorderable">False</property> -- <property name="enable_search">True</property> -- <property name="fixed_height_mode">False</property> -- <property name="hover_selection">False</property> -- <property name="hover_expand">True</property> -+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> -+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property> -+ <property name="shadow_type">GTK_SHADOW_IN</property> -+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -+ -+ <child> -+ <widget class="GtkTreeView" id="cities_list"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="headers_visible">False</property> -+ <property name="rules_hint">False</property> -+ <property name="reorderable">False</property> -+ <property name="enable_search">True</property> -+ <property name="fixed_height_mode">False</property> -+ <property name="hover_selection">False</property> -+ <property name="hover_expand">True</property> -+ </widget> -+ </child> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> - </child> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">3</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">8</property> -- <property name="x_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkAlignment" id="alignment6"> -- <property name="visible">True</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xscale">0</property> -- <property name="yscale">1</property> -- <property name="top_padding">0</property> -- <property name="bottom_padding">0</property> -- <property name="left_padding">0</property> -- <property name="right_padding">0</property> - - <child> -- <widget class="GtkVBox" id="vbox2"> -+ <widget class="GtkVButtonBox" id="vbuttonbox2"> - <property name="visible">True</property> -- <property name="homogeneous">False</property> -+ <property name="layout_style">GTK_BUTTONBOX_START</property> - <property name="spacing">6</property> - - <child> -- <widget class="GtkLabel" id="label39"> -+ <widget class="GtkButton" id="prefs-locations-add-button"> -+ <property name="width_request">24</property> -+ <property name="height_request">25</property> - <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-add</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> - </child> - - <child> -- <widget class="GtkVButtonBox" id="vbuttonbox1"> -+ <widget class="GtkButton" id="prefs-locations-edit-button"> -+ <property name="width_request">24</property> -+ <property name="height_request">24</property> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_START</property> -- <property name="spacing">6</property> -- -- <child> -- <widget class="GtkButton" id="prefs-locations-add-button"> -- <property name="width_request">24</property> -- <property name="height_request">25</property> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-add</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -- -- <child> -- <widget class="GtkButton" id="prefs-locations-edit-button"> -- <property name="width_request">24</property> -- <property name="height_request">24</property> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-edit</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -- -- <child> -- <widget class="GtkButton" id="prefs-locations-remove-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-remove</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-edit</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> - </child> - - <child> -- <widget class="GtkLabel" id="label38"> -+ <widget class="GtkButton" id="prefs-locations-remove-button"> - <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-remove</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> - </child> - </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> - </child> - </widget> - <packing> -- <property name="left_attach">3</property> -- <property name="right_attach">4</property> -- <property name="top_attach">2</property> -- <property name="bottom_attach">8</property> -- <property name="x_options"></property> -- <property name="y_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="show_map_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">Show the world _map in the clock</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label41"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">2</property> -- <property name="right_attach">3</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label160"> -- <property name="visible">True</property> -- <property name="label" translatable="yes"></property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">2</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkCheckButton" id="show_locations_check"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="label" translatable="yes">S_how locations in the clock</property> -- <property name="use_underline">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- <property name="active">False</property> -- <property name="inconsistent">False</property> -- <property name="draw_indicator">True</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">3</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> - </packing> - </child> - </widget> -@@ -735,7 +362,7 @@ - </child> - - <child> -- <widget class="GtkLabel" id="label2"> -+ <widget class="GtkLabel" id="label220"> - <property name="visible">True</property> - <property name="label" translatable="yes">Locations</property> - <property name="use_underline">False</property> -@@ -772,95 +399,20 @@ - <property name="spacing">0</property> - - <child> -- <widget class="GtkHButtonBox" id="hbuttonbox2"> -- <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property> -- <property name="spacing">0</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkHButtonBox" id="hbuttonbox3"> -+ <widget class="GtkHButtonBox" id="hbuttonbox22"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <property name="spacing">6</property> - - <child> -- <widget class="GtkButton" id="prefs-time-settings-button"> -+ <widget class="GtkButton" id="time-settings-button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Time Settings</property> -+ <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> -- -- <child> -- <widget class="GtkAlignment" id="alignment5"> -- <property name="visible">True</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xscale">0</property> -- <property name="yscale">0</property> -- <property name="top_padding">0</property> -- <property name="bottom_padding">0</property> -- <property name="left_padding">0</property> -- <property name="right_padding">0</property> -- -- <child> -- <widget class="GtkHBox" id="hbox8"> -- <property name="visible">True</property> -- <property name="homogeneous">False</property> -- <property name="spacing">2</property> -- -- <child> -- <widget class="GtkImage" id="image5"> -- <property name="visible">True</property> -- <property name="stock">gtk-properties</property> -- <property name="icon_size">4</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label35"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Time _Settings</property> -- <property name="use_underline">True</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0.5</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> -- </child> -- </widget> -- </child> -- </widget> -- </child> - </widget> - </child> - -@@ -910,13 +462,13 @@ - - <child> - <widget class="GtkVBox" id="vbox14"> -+ <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> -- <property name="spacing">0</property> -+ <property name="spacing">24</property> - - <child> - <widget class="GtkTable" id="table23"> -- <property name="border_width">6</property> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">3</property> -@@ -926,7 +478,6 @@ - - <child> - <widget class="GtkVBox" id="vbox15"> -- <property name="border_width">6</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> -@@ -974,62 +525,6 @@ - <property name="column_spacing">6</property> - - <child> -- <widget class="GtkLabel" id="label174"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Timezone:</property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkLabel" id="label175"> -- <property name="visible">True</property> -- <property name="label" translatable="yes">Location Name:</property> -- <property name="use_underline">False</property> -- <property name="use_markup">False</property> -- <property name="justify">GTK_JUSTIFY_LEFT</property> -- <property name="wrap">False</property> -- <property name="selectable">False</property> -- <property name="xalign">0</property> -- <property name="yalign">0.5</property> -- <property name="xpad">0</property> -- <property name="ypad">0</property> -- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -- <property name="width_chars">-1</property> -- <property name="single_line_mode">False</property> -- <property name="angle">0</property> -- </widget> -- <packing> -- <property name="left_attach">0</property> -- <property name="right_attach">1</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="x_options">fill</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> - <widget class="GtkVBox" id="vbox16"> - <property name="visible">True</property> - <property name="homogeneous">True</property> -@@ -1070,45 +565,6 @@ - </child> - - <child> -- <widget class="GtkComboBoxEntry" id="edit-location-timezone-combo"> -- <property name="visible">True</property> -- <property name="items">Dummy Item</property> -- <property name="add_tearoffs">False</property> -- <property name="has_frame">True</property> -- <property name="focus_on_click">True</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">4</property> -- <property name="top_attach">0</property> -- <property name="bottom_attach">1</property> -- <property name="x_options">fill</property> -- <property name="y_options">fill</property> -- </packing> -- </child> -- -- <child> -- <widget class="GtkEntry" id="edit-location-name-entry"> -- <property name="visible">True</property> -- <property name="can_focus">True</property> -- <property name="editable">True</property> -- <property name="visibility">True</property> -- <property name="max_length">0</property> -- <property name="text" translatable="yes"></property> -- <property name="has_frame">True</property> -- <property name="invisible_char">●</property> -- <property name="activates_default">False</property> -- </widget> -- <packing> -- <property name="left_attach">1</property> -- <property name="right_attach">4</property> -- <property name="top_attach">1</property> -- <property name="bottom_attach">2</property> -- <property name="y_options"></property> -- </packing> -- </child> -- -- <child> - <widget class="GtkLabel" id="label208"> - <property name="visible">True</property> - <property name="label" translatable="yes">Longitude:</property> -@@ -1145,7 +601,7 @@ - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> -- <property name="invisible_char">●</property> -+ <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> -@@ -1258,7 +714,7 @@ South</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> -- <property name="invisible_char">●</property> -+ <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> -@@ -1269,6 +725,131 @@ South</property> - <property name="y_options"></property> - </packing> - </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label175"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Location Name:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="left_attach">0</property> -+ <property name="right_attach">1</property> -+ <property name="top_attach">0</property> -+ <property name="bottom_attach">1</property> -+ <property name="x_options">fill</property> -+ <property name="y_options"></property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label174"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Timezone:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="left_attach">0</property> -+ <property name="right_attach">1</property> -+ <property name="top_attach">1</property> -+ <property name="bottom_attach">2</property> -+ <property name="x_options">fill</property> -+ <property name="y_options"></property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox55"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkEntry" id="edit-location-name-entry"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="editable">True</property> -+ <property name="visibility">True</property> -+ <property name="max_length">0</property> -+ <property name="text" translatable="yes"></property> -+ <property name="has_frame">True</property> -+ <property name="invisible_char">•</property> -+ <property name="activates_default">False</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find-location-button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Find...</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="left_attach">1</property> -+ <property name="right_attach">4</property> -+ <property name="top_attach">0</property> -+ <property name="bottom_attach">1</property> -+ <property name="x_options">fill</property> -+ <property name="y_options">fill</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkComboBoxEntry" id="edit-location-timezone-combo"> -+ <property name="visible">True</property> -+ <property name="items">Dummy Item</property> -+ <property name="add_tearoffs">False</property> -+ <property name="has_frame">True</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ <packing> -+ <property name="left_attach">1</property> -+ <property name="right_attach">4</property> -+ <property name="top_attach">1</property> -+ <property name="bottom_attach">2</property> -+ <property name="x_options">fill</property> -+ <property name="y_options">fill</property> -+ </packing> -+ </child> - </widget> - <packing> - <property name="padding">0</property> -@@ -1294,60 +875,33 @@ South</property> - </child> - - <child> -- <widget class="GtkHBox" id="hbox40"> -- <property name="border_width">6</property> -+ <widget class="GtkHButtonBox" id="hbuttonbox20"> - <property name="visible">True</property> -- <property name="homogeneous">False</property> -- <property name="spacing">0</property> -+ <property name="layout_style">GTK_BUTTONBOX_END</property> -+ <property name="spacing">6</property> - - <child> -- <widget class="GtkHButtonBox" id="hbuttonbox12"> -+ <widget class="GtkButton" id="edit-location-cancel-button"> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property> -- <property name="spacing">0</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-cancel</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">False</property> -- <property name="fill">False</property> -- </packing> - </child> - - <child> -- <widget class="GtkHButtonBox" id="hbuttonbox18"> -+ <widget class="GtkButton" id="edit-location-ok-button"> - <property name="visible">True</property> -- <property name="layout_style">GTK_BUTTONBOX_END</property> -- <property name="spacing">6</property> -- -- <child> -- <widget class="GtkButton" id="edit-location-cancel-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-cancel</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -- -- <child> -- <widget class="GtkButton" id="edit-location-ok-button"> -- <property name="visible">True</property> -- <property name="can_default">True</property> -- <property name="can_focus">True</property> -- <property name="label">gtk-ok</property> -- <property name="use_stock">True</property> -- <property name="relief">GTK_RELIEF_NORMAL</property> -- <property name="focus_on_click">True</property> -- </widget> -- </child> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-ok</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> - </widget> -- <packing> -- <property name="padding">0</property> -- <property name="expand">True</property> -- <property name="fill">True</property> -- </packing> - </child> - </widget> - <packing> -@@ -1723,4 +1277,580 @@ South</property> - </child> - </widget> - -+<widget class="GtkWindow" id="find-location-window"> -+ <property name="title" translatable="yes"></property> -+ <property name="type">GTK_WINDOW_TOPLEVEL</property> -+ <property name="window_position">GTK_WIN_POS_NONE</property> -+ <property name="modal">False</property> -+ <property name="resizable">True</property> -+ <property name="destroy_with_parent">False</property> -+ <property name="decorated">True</property> -+ <property name="skip_taskbar_hint">False</property> -+ <property name="skip_pager_hint">False</property> -+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> -+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> -+ <property name="focus_on_map">True</property> -+ <property name="urgency_hint">False</property> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox25"> -+ <property name="border_width">12</property> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">24</property> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox26"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkScrolledWindow" id="scrolledwindow11"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> -+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> -+ <property name="shadow_type">GTK_SHADOW_IN</property> -+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property> -+ -+ <child> -+ <widget class="GtkTreeView" id="find-location-tree"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="headers_visible">False</property> -+ <property name="rules_hint">False</property> -+ <property name="reorderable">False</property> -+ <property name="enable_search">False</property> -+ <property name="fixed_height_mode">False</property> -+ <property name="hover_selection">False</property> -+ <property name="hover_expand">False</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox56"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label221"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">_Find:</property> -+ <property name="use_underline">True</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="mnemonic_widget">find-location-entry</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkEntry" id="find-location-entry"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="editable">True</property> -+ <property name="visibility">True</property> -+ <property name="max_length">0</property> -+ <property name="text" translatable="yes"></property> -+ <property name="has_frame">True</property> -+ <property name="invisible_char">•</property> -+ <property name="activates_default">False</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find-next-location-button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ -+ <child> -+ <widget class="GtkAlignment" id="alignment31"> -+ <property name="visible">True</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xscale">0</property> -+ <property name="yscale">0</property> -+ <property name="top_padding">0</property> -+ <property name="bottom_padding">0</property> -+ <property name="left_padding">0</property> -+ <property name="right_padding">0</property> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox57"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">2</property> -+ -+ <child> -+ <widget class="GtkImage" id="image29"> -+ <property name="visible">True</property> -+ <property name="stock">gtk-find</property> -+ <property name="icon_size">4</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label222"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Find _Next</property> -+ <property name="use_underline">True</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ </child> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHButtonBox" id="hbuttonbox19"> -+ <property name="visible">True</property> -+ <property name="layout_style">GTK_BUTTONBOX_END</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkButton" id="find-location-cancel-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-cancel</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="find-location-ok-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-ok</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ </child> -+</widget> -+ -+<widget class="GtkWindow" id="set-time-window"> -+ <property name="border_width">12</property> -+ <property name="title" translatable="yes">Time Settings</property> -+ <property name="type">GTK_WINDOW_TOPLEVEL</property> -+ <property name="window_position">GTK_WIN_POS_NONE</property> -+ <property name="modal">False</property> -+ <property name="resizable">True</property> -+ <property name="destroy_with_parent">False</property> -+ <property name="decorated">True</property> -+ <property name="skip_taskbar_hint">False</property> -+ <property name="skip_pager_hint">False</property> -+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> -+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> -+ <property name="focus_on_map">True</property> -+ <property name="urgency_hint">False</property> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox20"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label212"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes"><b>Time Settings</b></property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">True</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="time_settings_box"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label217"> -+ <property name="visible">True</property> -+ <property name="label"> </property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0.5</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox52"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">12</property> -+ -+ <child> -+ <widget class="GtkCalendar" id="calendar"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="display_options">GTK_CALENDAR_SHOW_HEADING</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox22"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="label218"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Current Time:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkLabel" id="label219"> -+ <property name="visible">True</property> -+ <property name="label" translatable="yes">Time:</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkVBox" id="vbox23"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkLabel" id="current_time_label"> -+ <property name="visible">True</property> -+ <property name="label">23:59:59</property> -+ <property name="use_underline">False</property> -+ <property name="use_markup">False</property> -+ <property name="justify">GTK_JUSTIFY_LEFT</property> -+ <property name="wrap">False</property> -+ <property name="selectable">False</property> -+ <property name="xalign">0</property> -+ <property name="yalign">0.5</property> -+ <property name="xpad">0</property> -+ <property name="ypad">0</property> -+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> -+ <property name="width_chars">-1</property> -+ <property name="single_line_mode">False</property> -+ <property name="angle">0</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox53"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkSpinButton" id="hours_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">23 0 23 1 12 12</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkSpinButton" id="minutes_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">59 0 59 1 30 30</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkSpinButton" id="seconds_spin"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="climb_rate">1</property> -+ <property name="digits">0</property> -+ <property name="numeric">True</property> -+ <property name="update_policy">GTK_UPDATE_ALWAYS</property> -+ <property name="snap_to_ticks">False</property> -+ <property name="wrap">True</property> -+ <property name="adjustment">59 0 59 1 30 30</property> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ </packing> -+ </child> -+ -+ <child> -+ <widget class="GtkHBox" id="hbox58"> -+ <property name="visible">True</property> -+ <property name="homogeneous">False</property> -+ <property name="spacing">0</property> -+ -+ <child> -+ <widget class="GtkHButtonBox" id="hbuttonbox21"> -+ <property name="visible">True</property> -+ <property name="layout_style">GTK_BUTTONBOX_END</property> -+ <property name="spacing">6</property> -+ -+ <child> -+ <widget class="GtkButton" id="cancel-set-time-button"> -+ <property name="visible">True</property> -+ <property name="can_default">True</property> -+ <property name="can_focus">True</property> -+ <property name="label">gtk-cancel</property> -+ <property name="use_stock">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ -+ <child> -+ <widget class="GtkButton" id="set-time-button"> -+ <property name="visible">True</property> -+ <property name="can_focus">True</property> -+ <property name="label" translatable="yes">Set System Time</property> -+ <property name="use_underline">True</property> -+ <property name="relief">GTK_RELIEF_NORMAL</property> -+ <property name="focus_on_click">True</property> -+ </widget> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">True</property> -+ <property name="fill">True</property> -+ </packing> -+ </child> -+ </widget> -+ <packing> -+ <property name="padding">0</property> -+ <property name="expand">False</property> -+ <property name="fill">False</property> -+ <property name="pack_type">GTK_PACK_END</property> -+ </packing> -+ </child> -+ </widget> -+ </child> -+</widget> -+ - </glade-interface> -diff --git a/data/intlclock.schemas.in b/data/intlclock.schemas.in -index 2ab6772..00fee4f 100644 ---- a/data/intlclock.schemas.in -+++ b/data/intlclock.schemas.in -@@ -89,41 +89,54 @@ - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/show_locations</key> -+ <key>/schemas/apps/intlclock_applet/prefs/cities</key> -+ <owner>clock-applet</owner> -+ <type>list</type> -+ <list_type>string</list_type> -+ <default>[]</default> -+ <locale name="C"> -+ <short>List of cities for the clock.</short> -+ <long> -+ List of cities to display in the international clock. -+ </long> -+ </locale> -+ </schema> -+ -+ <schema> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_locations</key> - <owner>clock-applet</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> -- <short>Show other locations in clock</short> -+ <short>Expand the location section in clock</short> - <long> -- If true, show a list of locations in the international clock. -+ If true, expand the list of locations in the international clock. - </long> - </locale> - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/show_map</key> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_tasks</key> - <owner>clock-applet</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> -- <short>Show world map in clock</short> -+ <short>Expand the tasks section in clock</short> - <long> -- If true, show the world map in the international clock. -+ If true, expand the list of tasks in the international clock. - </long> - </locale> - </schema> - - <schema> -- <key>/schemas/apps/intlclock_applet/prefs/cities</key> -+ <key>/schemas/apps/intlclock_applet/prefs/expand_appointments</key> - <owner>clock-applet</owner> -- <type>list</type> -- <list_type>string</list_type> -- <default>[]</default> -+ <type>bool</type> -+ <default>true</default> - <locale name="C"> -- <short>List of cities for the clock.</short> -+ <short>Expand the appointments section in clock</short> - <long> -- List of cities to display in the international clock. -+ If true, expand the list of appointments in the international clock. - </long> - </locale> - </schema> -diff --git a/intltool-extract.in b/intltool-extract.in -deleted file mode 100755 -index bb6c368..340fc8d ---- a/intltool-extract.in -+++ /dev/null -@@ -1,841 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Extractor --# --# Copyright (C) 2000-2001, 2003 Free Software Foundation. --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License as --# published by the Free Software Foundation; either version 2 of the --# License, or (at your option) any later version. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Kenneth Christiansen <kenneth@gnu.org> --# Darin Adler <darin@bentspoon.com> --# -- --## Release information --my $PROGRAM = "intltool-extract"; --my $PACKAGE = "intltool"; --my $VERSION = "0.35.0"; -- --## Loaded modules --use strict; --use File::Basename; --use Getopt::Long; -- --## Scalars used by the option stuff --my $TYPE_ARG = "0"; --my $LOCAL_ARG = "0"; --my $HELP_ARG = "0"; --my $VERSION_ARG = "0"; --my $UPDATE_ARG = "0"; --my $QUIET_ARG = "0"; --my $SRCDIR_ARG = "."; -- --my $FILE; --my $OUTFILE; -- --my $gettext_type = ""; --my $input; --my %messages = (); --my %loc = (); --my %count = (); --my %comments = (); --my $strcount = 0; -- --my $XMLCOMMENT = ""; -- --## Use this instead of \w for XML files to handle more possible characters. --my $w = "[-A-Za-z0-9._:]"; -- --## Always print first --$| = 1; -- --## Handle options --GetOptions ( -- "type=s" => \$TYPE_ARG, -- "local|l" => \$LOCAL_ARG, -- "help|h" => \$HELP_ARG, -- "version|v" => \$VERSION_ARG, -- "update" => \$UPDATE_ARG, -- "quiet|q" => \$QUIET_ARG, -- "srcdir=s" => \$SRCDIR_ARG, -- ) or &error; -- --&split_on_argument; -- -- --## Check for options. --## This section will check for the different options. -- --sub split_on_argument { -- -- if ($VERSION_ARG) { -- &version; -- -- } elsif ($HELP_ARG) { -- &help; -- -- } elsif ($LOCAL_ARG) { -- &place_local; -- &extract; -- -- } elsif ($UPDATE_ARG) { -- &place_normal; -- &extract; -- -- } elsif (@ARGV > 0) { -- &place_normal; -- &message; -- &extract; -- -- } else { -- &help; -- -- } --} -- --sub place_normal { -- $FILE = $ARGV[0]; -- $OUTFILE = "$FILE.h"; --} -- --sub place_local { -- $FILE = $ARGV[0]; -- $OUTFILE = fileparse($FILE, ()); -- if (!-e "tmp/") { -- system("mkdir tmp/"); -- } -- $OUTFILE = "./tmp/$OUTFILE.h" --} -- --sub determine_type { -- if ($TYPE_ARG =~ /^gettext\/(.*)/) { -- $gettext_type=$1 -- } --} -- --## Sub for printing release information --sub version{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) $VERSION --Copyright (C) 2000, 2003 Free Software Foundation, Inc. --Written by Kenneth Christiansen, 2000. -- --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --## Sub for printing usage information --sub help { -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... [FILENAME] --Generates a header file from an XML source file. -- --It grabs all strings between <_translatable_node> and its end tag in --XML files. Read manpage (man ${PROGRAM}) for more info. -- -- --type=TYPE Specify the file type of FILENAME. Currently supports: -- "gettext/glade", "gettext/ini", "gettext/keys" -- "gettext/rfc822deb", "gettext/schemas", -- "gettext/scheme", "gettext/xml" -- -l, --local Writes output into current working directory -- (conflicts with --update) -- --update Writes output into the same directory the source file -- reside (conflicts with --local) -- --srcdir Root of the source tree -- -v, --version Output version information and exit -- -h, --help Display this help and exit -- -q, --quiet Quiet mode -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- --## Sub for printing error messages --sub error{ -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit; --} -- --sub message { -- print "Generating C format header file for translation.\n" unless $QUIET_ARG; --} -- --sub extract { -- &determine_type; -- -- &convert; -- -- open OUT, ">$OUTFILE"; -- binmode (OUT) if $^O eq 'MSWin32'; -- &msg_write; -- close OUT; -- -- print "Wrote $OUTFILE\n" unless $QUIET_ARG; --} -- --sub convert { -- -- ## Reading the file -- { -- local (*IN); -- local $/; #slurp mode -- open (IN, "<$SRCDIR_ARG/$FILE") || die "can't open $SRCDIR_ARG/$FILE: $!"; -- $input = <IN>; -- } -- -- &type_ini if $gettext_type eq "ini"; -- &type_keys if $gettext_type eq "keys"; -- &type_xml if $gettext_type eq "xml"; -- &type_glade if $gettext_type eq "glade"; -- &type_scheme if $gettext_type eq "scheme"; -- &type_schemas if $gettext_type eq "schemas"; -- &type_rfc822deb if $gettext_type eq "rfc822deb"; --} -- --sub entity_decode_minimal --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- -- return $_; --} -- --sub entity_decode --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- s/</</g; -- s/>/>/g; -- -- return $_; --} -- --sub escape_char --{ -- return '\"' if $_ eq '"'; -- return '\n' if $_ eq "\n"; -- return '\\' if $_ eq '\\'; -- -- return $_; --} -- --sub escape --{ -- my ($string) = @_; -- return join "", map &escape_char, split //, $string; --} -- --sub type_ini { -- ### For generic translatable desktop files ### -- while ($input =~ /^_.*=(.*)$/mg) { -- $messages{$1} = []; -- } --} -- --sub type_keys { -- ### For generic translatable mime/keys files ### -- while ($input =~ /^\s*_\w+=(.*)$/mg) { -- $messages{$1} = []; -- } --} -- --sub type_xml { -- ### For generic translatable XML files ### -- my $tree = readXml($input); -- parseTree(0, $tree); --} -- --sub print_var { -- my $var = shift; -- my $vartype = ref $var; -- -- if ($vartype =~ /ARRAY/) { -- my @arr = @{$var}; -- print "[ "; -- foreach my $el (@arr) { -- print_var($el); -- print ", "; -- } -- print "] "; -- } elsif ($vartype =~ /HASH/) { -- my %hash = %{$var}; -- print "{ "; -- foreach my $key (keys %hash) { -- print "$key => "; -- print_var($hash{$key}); -- print ", "; -- } -- print "} "; -- } else { -- print $var; -- } --} -- --# Same syntax as getAttributeString in intltool-merge.in.in, similar logic (look for ## differences comment) --sub getAttributeString --{ -- my $sub = shift; -- my $do_translate = shift || 1; -- my $language = shift || ""; -- my $translate = shift; -- my $result = ""; -- foreach my $e (reverse(sort(keys %{ $sub }))) { -- my $key = $e; -- my $string = $sub->{$e}; -- my $quote = '"'; -- -- $string =~ s/^[\s]+//; -- $string =~ s/[\s]+$//; -- -- if ($string =~ /^'.*'$/) -- { -- $quote = "'"; -- } -- $string =~ s/^['"]//g; -- $string =~ s/['"]$//g; -- -- ## differences from intltool-merge.in.in -- if ($key =~ /^_/) { -- $comments{entity_decode($string)} = $XMLCOMMENT if $XMLCOMMENT; -- $messages{entity_decode($string)} = []; -- $$translate = 2; -- } -- ## differences end here from intltool-merge.in.in -- $result .= " $key=$quote$string$quote"; -- } -- return $result; --} -- --# Verbatim copy from intltool-merge.in.in --sub getXMLstring --{ -- my $ref = shift; -- my $spacepreserve = shift || 0; -- my @list = @{ $ref }; -- my $result = ""; -- -- my $count = scalar(@list); -- my $attrs = $list[0]; -- my $index = 1; -- -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- -- while ($index < $count) { -- my $type = $list[$index]; -- my $content = $list[$index+1]; -- if (! $type ) { -- # We've got CDATA -- if ($content) { -- # lets strip the whitespace here, and *ONLY* here -- $content =~ s/\s+/ /gs if (!$spacepreserve); -- $result .= $content; -- } -- } elsif ( "$type" ne "1" ) { -- # We've got another element -- $result .= "<$type"; -- $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements -- if ($content) { -- my $subresult = getXMLstring($content, $spacepreserve); -- if ($subresult) { -- $result .= ">".$subresult . "</$type>"; -- } else { -- $result .= "/>"; -- } -- } else { -- $result .= "/>"; -- } -- } -- $index += 2; -- } -- return $result; --} -- --# Verbatim copy from intltool-merge.in.in, except for MULTIPLE_OUTPUT handling removed --# Translate list of nodes if necessary --sub translate_subnodes --{ -- my $fh = shift; -- my $content = shift; -- my $language = shift || ""; -- my $singlelang = shift || 0; -- my $spacepreserve = shift || 0; -- -- my @nodes = @{ $content }; -- -- my $count = scalar(@nodes); -- my $index = 0; -- while ($index < $count) { -- my $type = $nodes[$index]; -- my $rest = $nodes[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } --} -- --# Based on traverse() in intltool-merge.in.in --sub traverse --{ -- my $fh = shift; # unused, to allow us to sync code between -merge and -extract -- my $nodename = shift; -- my $content = shift; -- my $language = shift || ""; -- my $spacepreserve = shift || 0; -- -- if ($nodename && "$nodename" eq "1") { -- $XMLCOMMENT = $content; -- } elsif ($nodename) { -- # element -- my @all = @{ $content }; -- my $attrs = shift @all; -- my $translate = 0; -- my $outattr = getAttributeString($attrs, 1, $language, \$translate); -- -- if ($nodename =~ /^_/) { -- $translate = 1; -- $nodename =~ s/^_//; -- } -- my $lookup = ''; -- -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- if ($translate) { -- $lookup = getXMLstring($content, $spacepreserve); -- if (!$spacepreserve) { -- $lookup =~ s/^\s+//s; -- $lookup =~ s/\s+$//s; -- } -- -- if ($lookup && $translate != 2) { -- $comments{$lookup} = $XMLCOMMENT if $XMLCOMMENT; -- $messages{$lookup} = []; -- } elsif ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } -- } else { -- $XMLCOMMENT = ""; -- my $count = scalar(@all); -- if ($count > 0) { -- my $index = 0; -- while ($index < $count) { -- my $type = $all[$index]; -- my $rest = $all[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } -- } -- } -- $XMLCOMMENT = ""; -- } --} -- -- --# Verbatim copy from intltool-merge.in.in, $fh for compatibility --sub parseTree --{ -- my $fh = shift; -- my $ref = shift; -- my $language = shift || ""; -- -- my $name = shift @{ $ref }; -- my $cont = shift @{ $ref }; -- -- while (!$name || "$name" eq "1") { -- $name = shift @{ $ref }; -- $cont = shift @{ $ref }; -- } -- -- my $spacepreserve = 0; -- my $attrs = @{$cont}[0]; -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- traverse($fh, $name, $cont, $language, $spacepreserve); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_comment --{ -- my $expat = shift; -- my $data = $expat->original_string(); -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $data =~ s/^<!--//s; -- $data =~ s/-->$//s; -- push @$clist, 1 => $data; --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_cdatastart --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 0 => $expat->original_string(); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_cdataend --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $clist->[$pos] .= $expat->original_string(); --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_char --{ -- my $expat = shift; -- my $text = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- # Use original_string so that we retain escaped entities -- # in CDATA sections. -- # -- if ($pos > 0 and $clist->[$pos - 1] eq '0') { -- $clist->[$pos] .= $expat->original_string(); -- } else { -- push @$clist, 0 => $expat->original_string(); -- } --} -- --# Verbatim copy from intltool-merge.in.in --sub intltool_tree_start --{ -- my $expat = shift; -- my $tag = shift; -- my @origlist = (); -- -- # Use original_string so that we retain escaped entities -- # in attribute values. We must convert the string to an -- # @origlist array to conform to the structure of the Tree -- # Style. -- # -- my @original_array = split /\x/, $expat->original_string(); -- my $source = $expat->original_string(); -- -- # Remove leading tag. -- # -- $source =~ s|^\s*<\s*(\S+)||s; -- -- # Grab attribute key/value pairs and push onto @origlist array. -- # -- while ($source) -- { -- if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s; -- push @origlist, $1; -- push @origlist, '"' . $2 . '"'; -- } -- elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s; -- push @origlist, $1; -- push @origlist, "'" . $2 . "'"; -- } -- else -- { -- last; -- } -- } -- -- my $ol = [ { @origlist } ]; -- -- push @{ $expat->{Lists} }, $expat->{Curlist}; -- push @{ $expat->{Curlist} }, $tag => $ol; -- $expat->{Curlist} = $ol; --} -- --# Copied from intltool-merge.in.in and added comment handler. --sub readXml --{ -- my $xmldoc = shift || return; -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- my $xp = new XML::Parser(Style => 'Tree'); -- $xp->setHandlers(Char => \&intltool_tree_char); -- $xp->setHandlers(Start => \&intltool_tree_start); -- $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart); -- $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend); -- -- ## differences from intltool-merge.in.in -- $xp->setHandlers(Comment => \&intltool_tree_comment); -- ## differences end here from intltool-merge.in.in -- -- my $tree = $xp->parse($xmldoc); -- #print_var($tree); -- --# <foo><!-- comment --><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> --# would be: --# [foo, [{}, 1, "comment", head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, --# [{}, 0, "Howdy", ref, [{}]], 0, "do" ] ] -- -- return $tree; --} -- --sub type_schemas { -- ### For schemas XML files ### -- -- # FIXME: We should handle escaped < (less than) -- while ($input =~ / -- <locale\ name="C">\s* -- (<default>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/default>\s*)? -- (<short>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/short>\s*)? -- (<long>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/long>\s*)? -- <\/locale> -- /sgx) { -- my @totranslate = ($3,$6,$9); -- my @eachcomment = ($2,$5,$8); -- foreach (@totranslate) { -- my $currentcomment = shift @eachcomment; -- next if !$_; -- s/\s+/ /g; -- $messages{entity_decode_minimal($_)} = []; -- $comments{entity_decode_minimal($_)} = $currentcomment if (defined($currentcomment)); -- } -- } --} -- --sub type_rfc822deb { -- ### For rfc822-style Debian configuration files ### -- -- my $lineno = 1; -- my $type = ''; -- while ($input =~ /\G(.*?)(^|\n)(_+)([^:]+):[ \t]*(.*?)(?=\n\S|$)/sg) -- { -- my ($pre, $newline, $underscore, $tag, $text) = ($1, $2, $3, $4, $5); -- while ($pre =~ m/\n/g) -- { -- $lineno ++; -- } -- $lineno += length($newline); -- my @str_list = rfc822deb_split(length($underscore), $text); -- for my $str (@str_list) -- { -- $strcount++; -- $messages{$str} = []; -- $loc{$str} = $lineno; -- $count{$str} = $strcount; -- my $usercomment = ''; -- while($pre =~ s/(^|\n)#([^\n]*)$//s) -- { -- $usercomment = "\n" . $2 . $usercomment; -- } -- $comments{$str} = $tag . $usercomment; -- } -- $lineno += ($text =~ s/\n//g); -- } --} -- --sub rfc822deb_split { -- # Debian defines a special way to deal with rfc822-style files: -- # when a value contain newlines, it consists of -- # 1. a short form (first line) -- # 2. a long description, all lines begin with a space, -- # and paragraphs are separated by a single dot on a line -- # This routine returns an array of all paragraphs, and reformat -- # them. -- # When first argument is 2, the string is a comma separated list of -- # values. -- my $type = shift; -- my $text = shift; -- $text =~ s/^[ \t]//mg; -- return (split(/, */, $text, 0)) if $type ne 1; -- return ($text) if $text !~ /\n/; -- -- $text =~ s/([^\n]*)\n//; -- my @list = ($1); -- my $str = ''; -- for my $line (split (/\n/, $text)) -- { -- chomp $line; -- if ($line =~ /^\.\s*$/) -- { -- # New paragraph -- $str =~ s/\s*$//; -- push(@list, $str); -- $str = ''; -- } -- elsif ($line =~ /^\s/) -- { -- # Line which must not be reformatted -- $str .= "\n" if length ($str) && $str !~ /\n$/; -- $line =~ s/\s+$//; -- $str .= $line."\n"; -- } -- else -- { -- # Continuation line, remove newline -- $str .= " " if length ($str) && $str !~ /\n$/; -- $str .= $line; -- } -- } -- $str =~ s/\s*$//; -- push(@list, $str) if length ($str); -- return @list; --} -- --sub type_glade { -- ### For translatable Glade XML files ### -- -- my $tags = "label|title|text|format|copyright|comments|preview_text|tooltip|message"; -- -- while ($input =~ /<($tags)>([^<]+)<\/($tags)>/sg) { -- # Glade sometimes uses tags that normally mark translatable things for -- # little bits of non-translatable content. We work around this by not -- # translating strings that only includes something like label4 or window1. -- $messages{entity_decode($2)} = [] unless $2 =~ /^(window|label|dialog)[0-9]+$/; -- } -- -- while ($input =~ /<items>(..[^<]*)<\/items>/sg) { -- for my $item (split (/\n/, $1)) { -- $messages{entity_decode($item)} = []; -- } -- } -- -- ## handle new glade files -- while ($input =~ /<(property|atkproperty)\s+[^>]*translatable\s*=\s*"yes"(?:\s+[^>]*comments\s*=\s*"([^"]*)")?[^>]*>([^<]+)<\/\1>/sg) { -- $messages{entity_decode($3)} = [] unless $3 =~ /^(window|label)[0-9]+$/; -- if (defined($2) and !($3 =~ /^(window|label)[0-9]+$/)) { -- $comments{entity_decode($3)} = entity_decode($2) ; -- } -- } -- while ($input =~ /<atkaction\s+action_name="([^>]*)"\s+description="([^>]+)"\/>/sg) { -- $messages{entity_decode_minimal($2)} = []; -- } --} -- --sub type_scheme { -- my ($line, $i, $state, $str, $trcomment, $char); -- for $line (split(/\n/, $input)) { -- $i = 0; -- $state = 0; # 0 - nothing, 1 - string, 2 - translatable string -- while ($i < length($line)) { -- if (substr($line,$i,1) eq "\"") { -- if ($state == 2) { -- $comments{$str} = $trcomment if ($trcomment); -- $messages{$str} = []; -- $str = ''; -- $state = 0; $trcomment = ""; -- } elsif ($state == 1) { -- $str = ''; -- $state = 0; $trcomment = ""; -- } else { -- $state = 1; -- $str = ''; -- if ($i>0 && substr($line,$i-1,1) eq '_') { -- $state = 2; -- } -- } -- } elsif (!$state) { -- if (substr($line,$i,1) eq ";") { -- $trcomment = substr($line,$i+1); -- $trcomment =~ s/^;*\s*//; -- $i = length($line); -- } elsif ($trcomment && substr($line,$i,1) !~ /\s|\(|\)|_/) { -- $trcomment = ""; -- } -- } else { -- if (substr($line,$i,1) eq "\\") { -- $char = substr($line,$i+1,1); -- if ($char ne "\"" && $char ne "\\") { -- $str = $str . "\\"; -- } -- $i++; -- } -- $str = $str . substr($line,$i,1); -- } -- $i++; -- } -- } --} -- --sub msg_write { -- my @msgids; -- if (%count) -- { -- @msgids = sort { $count{$a} <=> $count{$b} } keys %count; -- } -- else -- { -- @msgids = sort keys %messages; -- } -- for my $message (@msgids) -- { -- my $offsetlines = 1; -- $offsetlines++ if $message =~ /%/; -- if (defined ($comments{$message})) -- { -- while ($comments{$message} =~ m/\n/g) -- { -- $offsetlines++; -- } -- } -- print OUT "# ".($loc{$message} - $offsetlines). " \"$FILE\"\n" -- if defined $loc{$message}; -- print OUT "/* ".$comments{$message}." */\n" -- if defined $comments{$message}; -- print OUT "/* xgettext:no-c-format */\n" if $message =~ /%/; -- -- my @lines = split (/\n/, $message, -1); -- for (my $n = 0; $n < @lines; $n++) -- { -- if ($n == 0) -- { -- print OUT "char *s = N_(\""; -- } -- else -- { -- print OUT " \""; -- } -- -- print OUT escape($lines[$n]); -- -- if ($n < @lines - 1) -- { -- print OUT "\\n\"\n"; -- } -- else -- { -- print OUT "\");\n"; -- } -- } -- } --} -- -diff --git a/intltool-extract.in b/intltool-extract.in -new file mode 120000 -index bb6c368..340fc8d ---- /dev/null -+++ b/intltool-extract.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-extract.in -\ No newline at end of file -diff --git a/intltool-merge.in b/intltool-merge.in -deleted file mode 100755 -index d0535ab..2238bbd ---- a/intltool-merge.in -+++ /dev/null -@@ -1,1356 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Merger --# --# Copyright (C) 2000, 2003 Free Software Foundation. --# Copyright (C) 2000, 2001 Eazel, Inc --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License --# version 2 published by the Free Software Foundation. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Maciej Stachowiak <mjs@noisehavoc.org> --# Kenneth Christiansen <kenneth@gnu.org> --# Darin Adler <darin@bentspoon.com> --# --# Proper XML UTF-8'ification written by Cyrille Chepelov <chepelov@calixo.net> --# -- --## Release information --my $PROGRAM = "intltool-merge"; --my $PACKAGE = "intltool"; --my $VERSION = "0.35.0"; -- --## Loaded modules --use strict; --use Getopt::Long; --use Text::Wrap; --use File::Basename; -- --my $must_end_tag = -1; --my $last_depth = -1; --my $translation_depth = -1; --my @tag_stack = (); --my @entered_tag = (); --my @translation_strings = (); --my $leading_space = ""; -- --## Scalars used by the option stuff --my $HELP_ARG = 0; --my $VERSION_ARG = 0; --my $BA_STYLE_ARG = 0; --my $XML_STYLE_ARG = 0; --my $KEYS_STYLE_ARG = 0; --my $DESKTOP_STYLE_ARG = 0; --my $SCHEMAS_STYLE_ARG = 0; --my $RFC822DEB_STYLE_ARG = 0; --my $QUIET_ARG = 0; --my $PASS_THROUGH_ARG = 0; --my $UTF8_ARG = 0; --my $MULTIPLE_OUTPUT = 0; --my $cache_file; -- --## Handle options --GetOptions --( -- "help" => \$HELP_ARG, -- "version" => \$VERSION_ARG, -- "quiet|q" => \$QUIET_ARG, -- "oaf-style|o" => \$BA_STYLE_ARG, ## for compatibility -- "ba-style|b" => \$BA_STYLE_ARG, -- "xml-style|x" => \$XML_STYLE_ARG, -- "keys-style|k" => \$KEYS_STYLE_ARG, -- "desktop-style|d" => \$DESKTOP_STYLE_ARG, -- "schemas-style|s" => \$SCHEMAS_STYLE_ARG, -- "rfc822deb-style|r" => \$RFC822DEB_STYLE_ARG, -- "pass-through|p" => \$PASS_THROUGH_ARG, -- "utf8|u" => \$UTF8_ARG, -- "multiple-output|m" => \$MULTIPLE_OUTPUT, -- "cache|c=s" => \$cache_file -- ) or &error; -- --my $PO_DIR; --my $FILE; --my $OUTFILE; -- --my %po_files_by_lang = (); --my %translations = (); --my $iconv = $ENV{"ICONV"} || $ENV{"INTLTOOL_ICONV"} || "@INTLTOOL_ICONV@"; --my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null'); -- --# Use this instead of \w for XML files to handle more possible characters. --my $w = "[-A-Za-z0-9._:]"; -- --# XML quoted string contents --my $q = "[^\\\"]*"; -- --## Check for options. -- --if ($VERSION_ARG) --{ -- &print_version; --} --elsif ($HELP_ARG) --{ -- &print_help; --} --elsif ($BA_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &ba_merge_translations; -- &finalize; --} --elsif ($XML_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &xml_merge_output; -- &finalize; --} --elsif ($KEYS_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &keys_merge_translations; -- &finalize; --} --elsif ($DESKTOP_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &desktop_merge_translations; -- &finalize; --} --elsif ($SCHEMAS_STYLE_ARG && @ARGV > 2) --{ -- &utf8_sanity_check; -- &preparation; -- &print_message; -- &schemas_merge_translations; -- &finalize; --} --elsif ($RFC822DEB_STYLE_ARG && @ARGV > 2) --{ -- &preparation; -- &print_message; -- &rfc822deb_merge_translations; -- &finalize; --} --else --{ -- &print_help; --} -- --exit; -- --## Sub for printing release information --sub print_version --{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) ${VERSION} --Written by Maciej Stachowiak, Darin Adler and Kenneth Christiansen. -- --Copyright (C) 2000-2003 Free Software Foundation, Inc. --Copyright (C) 2000-2001 Eazel, Inc. --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --## Sub for printing usage information --sub print_help --{ -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... PO_DIRECTORY FILENAME OUTPUT_FILE --Generates an output file that includes some localized attributes from an --untranslated source file. -- --Mandatory options: (exactly one must be specified) -- -b, --ba-style includes translations in the bonobo-activation style -- -d, --desktop-style includes translations in the desktop style -- -k, --keys-style includes translations in the keys style -- -s, --schemas-style includes translations in the schemas style -- -r, --rfc822deb-style includes translations in the RFC822 style -- -x, --xml-style includes translations in the standard xml style -- --Other options: -- -u, --utf8 convert all strings to UTF-8 before merging -- (default for everything except RFC822 style) -- -p, --pass-through deprecated, does nothing and issues a warning -- -m, --multiple-output output one localized file per locale, instead of -- a single file containing all localized elements -- -c, --cache=FILE specify cache file name -- (usually \$top_builddir/po/.intltool-merge-cache) -- -q, --quiet suppress most messages -- --help display this help and exit -- --version output version information and exit -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- -- --## Sub for printing error messages --sub print_error --{ -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit; --} -- -- --sub print_message --{ -- print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG; --} -- -- --sub preparation --{ -- $PO_DIR = $ARGV[0]; -- $FILE = $ARGV[1]; -- $OUTFILE = $ARGV[2]; -- -- &gather_po_files; -- &get_translation_database; --} -- --# General-purpose code for looking up translations in .po files -- --sub po_file2lang --{ -- my ($tmp) = @_; -- $tmp =~ s/^.*\/(.*)\.po$/$1/; -- return $tmp; --} -- --sub gather_po_files --{ -- for my $po_file (glob "$PO_DIR/*.po") { -- $po_files_by_lang{po_file2lang($po_file)} = $po_file; -- } --} -- --sub get_local_charset --{ -- my ($encoding) = @_; -- my $alias_file = $ENV{"G_CHARSET_ALIAS"} || "@INTLTOOL_LIBDIR@/charset.alias"; -- -- # seek character encoding aliases in charset.alias (glib) -- -- if (open CHARSET_ALIAS, $alias_file) -- { -- while (<CHARSET_ALIAS>) -- { -- next if /^\#/; -- return $1 if (/^\s*([-._a-zA-Z0-9]+)\s+$encoding\b/i) -- } -- -- close CHARSET_ALIAS; -- } -- -- # if not found, return input string -- -- return $encoding; --} -- --sub get_po_encoding --{ -- my ($in_po_file) = @_; -- my $encoding = ""; -- -- open IN_PO_FILE, $in_po_file or die; -- while (<IN_PO_FILE>) -- { -- ## example: "Content-Type: text/plain; charset=ISO-8859-1\n" -- if (/Content-Type\:.*charset=([-a-zA-Z0-9]+)\\n/) -- { -- $encoding = $1; -- last; -- } -- } -- close IN_PO_FILE; -- -- if (!$encoding) -- { -- print STDERR "Warning: no encoding found in $in_po_file. Assuming ISO-8859-1\n" unless $QUIET_ARG; -- $encoding = "ISO-8859-1"; -- } -- -- system ("$iconv -f $encoding -t UTF-8 <$devnull 2>$devnull"); -- if ($?) { -- $encoding = get_local_charset($encoding); -- } -- -- return $encoding --} -- --sub utf8_sanity_check --{ -- print STDERR "Warning: option --pass-through has been removed.\n" if $PASS_THROUGH_ARG; -- $UTF8_ARG = 1; --} -- --sub get_translation_database --{ -- if ($cache_file) { -- &get_cached_translation_database; -- } else { -- &create_translation_database; -- } --} -- --sub get_newest_po_age --{ -- my $newest_age; -- -- foreach my $file (values %po_files_by_lang) -- { -- my $file_age = -M $file; -- $newest_age = $file_age if !$newest_age || $file_age < $newest_age; -- } -- -- $newest_age = 0 if !$newest_age; -- -- return $newest_age; --} -- --sub create_cache --{ -- print "Generating and caching the translation database\n" unless $QUIET_ARG; -- -- &create_translation_database; -- -- open CACHE, ">$cache_file" || die; -- print CACHE join "\x01", %translations; -- close CACHE; --} -- --sub load_cache --{ -- print "Found cached translation database\n" unless $QUIET_ARG; -- -- my $contents; -- open CACHE, "<$cache_file" || die; -- { -- local $/; -- $contents = <CACHE>; -- } -- close CACHE; -- %translations = split "\x01", $contents; --} -- --sub get_cached_translation_database --{ -- my $cache_file_age = -M $cache_file; -- if (defined $cache_file_age) -- { -- if ($cache_file_age <= &get_newest_po_age) -- { -- &load_cache; -- return; -- } -- print "Found too-old cached translation database\n" unless $QUIET_ARG; -- } -- -- &create_cache; --} -- --sub create_translation_database --{ -- for my $lang (keys %po_files_by_lang) -- { -- my $po_file = $po_files_by_lang{$lang}; -- -- if ($UTF8_ARG) -- { -- my $encoding = get_po_encoding ($po_file); -- -- if (lc $encoding eq "utf-8") -- { -- open PO_FILE, "<$po_file"; -- } -- else -- { -- print "NOTICE: $po_file is not in UTF-8 but $encoding, converting...\n" unless $QUIET_ARG;; -- -- open PO_FILE, "$iconv -f $encoding -t UTF-8 $po_file|"; -- } -- } -- else -- { -- open PO_FILE, "<$po_file"; -- } -- -- my $nextfuzzy = 0; -- my $inmsgid = 0; -- my $inmsgstr = 0; -- my $msgid = ""; -- my $msgstr = ""; -- -- while (<PO_FILE>) -- { -- $nextfuzzy = 1 if /^#, fuzzy/; -- -- if (/^msgid "((\\.|[^\\])*)"/ ) -- { -- $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr; -- $msgid = ""; -- $msgstr = ""; -- -- if ($nextfuzzy) { -- $inmsgid = 0; -- } else { -- $msgid = unescape_po_string($1); -- $inmsgid = 1; -- } -- $inmsgstr = 0; -- $nextfuzzy = 0; -- } -- -- if (/^msgstr "((\\.|[^\\])*)"/) -- { -- $msgstr = unescape_po_string($1); -- $inmsgstr = 1; -- $inmsgid = 0; -- } -- -- if (/^"((\\.|[^\\])*)"/) -- { -- $msgid .= unescape_po_string($1) if $inmsgid; -- $msgstr .= unescape_po_string($1) if $inmsgstr; -- } -- } -- $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr; -- } --} -- --sub finalize --{ --} -- --sub unescape_one_sequence --{ -- my ($sequence) = @_; -- -- return "\\" if $sequence eq "\\\\"; -- return "\"" if $sequence eq "\\\""; -- return "\n" if $sequence eq "\\n"; -- return "\r" if $sequence eq "\\r"; -- return "\t" if $sequence eq "\\t"; -- return "\b" if $sequence eq "\\b"; -- return "\f" if $sequence eq "\\f"; -- return "\a" if $sequence eq "\\a"; -- return chr(11) if $sequence eq "\\v"; # vertical tab, see ascii(7) -- -- return chr(hex($1)) if ($sequence =~ /\\x([0-9a-fA-F]{2})/); -- return chr(oct($1)) if ($sequence =~ /\\([0-7]{3})/); -- -- # FIXME: Is \0 supported as well? Kenneth and Rodney don't want it, see bug #48489 -- -- return $sequence; --} -- --sub unescape_po_string --{ -- my ($string) = @_; -- -- $string =~ s/(\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\.)/unescape_one_sequence($1)/eg; -- -- return $string; --} -- --## NOTE: deal with < - < but not > - > because it seems its ok to have --## > in the entity. For further info please look at #84738. --sub entity_decode --{ -- local ($_) = @_; -- -- s/'/'/g; # ' -- s/"/"/g; # " -- s/&/&/g; -- s/</</g; -- -- return $_; --} -- --# entity_encode: (string) --# --# Encode the given string to XML format (encode '<' etc). -- --sub entity_encode --{ -- my ($pre_encoded) = @_; -- -- my @list_of_chars = unpack ('C*', $pre_encoded); -- -- # with UTF-8 we only encode minimalistic -- return join ('', map (&entity_encode_int_minimalist, @list_of_chars)); --} -- --sub entity_encode_int_minimalist --{ -- return """ if $_ == 34; -- return "&" if $_ == 38; -- return "'" if $_ == 39; -- return "<" if $_ == 60; -- return chr $_; --} -- --sub entity_encoded_translation --{ -- my ($lang, $string) = @_; -- -- my $translation = $translations{$lang, $string}; -- return $string if !$translation; -- return entity_encode ($translation); --} -- --## XML (bonobo-activation specific) merge code -- --sub ba_merge_translations --{ -- my $source; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">$OUTFILE" or die "can't open $OUTFILE: $!"; -- # Binmode so that selftest works ok if using a native Win32 Perl... -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while ($source =~ s|^(.*?)([ \t]*<\s*$w+\s+($w+\s*=\s*"$q"\s*)+/?>)([ \t]*\n)?||s) -- { -- print OUTPUT $1; -- -- my $node = $2 . "\n"; -- -- my @strings = (); -- $_ = $node; -- while (s/(\s)_($w+\s*=\s*"($q)")/$1$2/s) { -- push @strings, entity_decode($3); -- } -- print OUTPUT; -- -- my %langs; -- for my $string (@strings) -- { -- for my $lang (keys %po_files_by_lang) -- { -- $langs{$lang} = 1 if $translations{$lang, $string}; -- } -- } -- -- for my $lang (sort keys %langs) -- { -- $_ = $node; -- s/(\sname\s*=\s*)"($q)"/$1"$2-$lang"/s; -- s/(\s)_($w+\s*=\s*")($q)"/$1 . $2 . entity_encoded_translation($lang, $3) . '"'/seg; -- print OUTPUT; -- } -- } -- -- print OUTPUT $source; -- -- close OUTPUT; --} -- -- --## XML (non-bonobo-activation) merge code -- -- --# Process tag attributes --# Only parameter is a HASH containing attributes -> values mapping --sub getAttributeString --{ -- my $sub = shift; -- my $do_translate = shift || 0; -- my $language = shift || ""; -- my $result = ""; -- my $translate = shift; -- foreach my $e (reverse(sort(keys %{ $sub }))) { -- my $key = $e; -- my $string = $sub->{$e}; -- my $quote = '"'; -- -- $string =~ s/^[\s]+//; -- $string =~ s/[\s]+$//; -- -- if ($string =~ /^'.*'$/) -- { -- $quote = "'"; -- } -- $string =~ s/^['"]//g; -- $string =~ s/['"]$//g; -- -- if ($do_translate && $key =~ /^_/) { -- $key =~ s|^_||g; -- if ($language) { -- # Handle translation -- my $decode_string = entity_decode($string); -- my $translation = $translations{$language, $decode_string}; -- if ($translation) { -- $translation = entity_encode($translation); -- $string = $translation; -- } -- $$translate = 2; -- } else { -- $$translate = 2 if ($translate && (!$$translate)); # watch not to "overwrite" $translate -- } -- } -- -- $result .= " $key=$quote$string$quote"; -- } -- return $result; --} -- --# Returns a translatable string from XML node, it works on contents of every node in XML::Parser tree --sub getXMLstring --{ -- my $ref = shift; -- my $spacepreserve = shift || 0; -- my @list = @{ $ref }; -- my $result = ""; -- -- my $count = scalar(@list); -- my $attrs = $list[0]; -- my $index = 1; -- -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- -- while ($index < $count) { -- my $type = $list[$index]; -- my $content = $list[$index+1]; -- if (! $type ) { -- # We've got CDATA -- if ($content) { -- # lets strip the whitespace here, and *ONLY* here -- $content =~ s/\s+/ /gs if (!$spacepreserve); -- $result .= $content; -- } -- } elsif ( "$type" ne "1" ) { -- # We've got another element -- $result .= "<$type"; -- $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements -- if ($content) { -- my $subresult = getXMLstring($content, $spacepreserve); -- if ($subresult) { -- $result .= ">".$subresult . "</$type>"; -- } else { -- $result .= "/>"; -- } -- } else { -- $result .= "/>"; -- } -- } -- $index += 2; -- } -- return $result; --} -- --# Translate list of nodes if necessary --sub translate_subnodes --{ -- my $fh = shift; -- my $content = shift; -- my $language = shift || ""; -- my $singlelang = shift || 0; -- my $spacepreserve = shift || 0; -- -- my @nodes = @{ $content }; -- -- my $count = scalar(@nodes); -- my $index = 0; -- while ($index < $count) { -- my $type = $nodes[$index]; -- my $rest = $nodes[$index+1]; -- if ($singlelang) { -- my $oldMO = $MULTIPLE_OUTPUT; -- $MULTIPLE_OUTPUT = 1; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $MULTIPLE_OUTPUT = $oldMO; -- } else { -- traverse($fh, $type, $rest, $language, $spacepreserve); -- } -- $index += 2; -- } --} -- --sub isWellFormedXmlFragment --{ -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- -- my $fragment = shift; -- return 0 if (!$fragment); -- -- $fragment = "<root>$fragment</root>"; -- my $xp = new XML::Parser(Style => 'Tree'); -- my $tree = 0; -- eval { $tree = $xp->parse($fragment); }; -- return $tree; --} -- --sub traverse --{ -- my $fh = shift; -- my $nodename = shift; -- my $content = shift; -- my $language = shift || ""; -- my $spacepreserve = shift || 0; -- -- if (!$nodename) { -- if ($content =~ /^[\s]*$/) { -- $leading_space .= $content; -- } -- print $fh $content; -- } else { -- # element -- my @all = @{ $content }; -- my $attrs = shift @all; -- my $translate = 0; -- my $outattr = getAttributeString($attrs, 1, $language, \$translate); -- -- if ($nodename =~ /^_/) { -- $translate = 1; -- $nodename =~ s/^_//; -- } -- my $lookup = ''; -- -- $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/)); -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- print $fh "<$nodename", $outattr; -- if ($translate) { -- $lookup = getXMLstring($content, $spacepreserve); -- if (!$spacepreserve) { -- $lookup =~ s/^\s+//s; -- $lookup =~ s/\s+$//s; -- } -- -- if ($lookup || $translate == 2) { -- my $translation = $translations{$language, $lookup} if isWellFormedXmlFragment($translations{$language, $lookup}); -- if ($MULTIPLE_OUTPUT && ($translation || $translate == 2)) { -- $translation = $lookup if (!$translation); -- print $fh " xml:lang=\"", $language, "\"" if $language; -- print $fh ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } else { -- print $fh $translation; -- } -- print $fh "</$nodename>"; -- -- return; # this means there will be no same translation with xml:lang="$language"... -- # if we want them both, just remove this "return" -- } else { -- print $fh ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $language, 1, $spacepreserve); -- } else { -- print $fh $lookup; -- } -- print $fh "</$nodename>"; -- } -- } else { -- print $fh "/>"; -- } -- -- for my $lang (sort keys %po_files_by_lang) { -- if ($MULTIPLE_OUTPUT && $lang ne "$language") { -- next; -- } -- if ($lang) { -- # Handle translation -- # -- my $translate = 0; -- my $localattrs = getAttributeString($attrs, 1, $lang, \$translate); -- my $translation = $translations{$lang, $lookup} if isWellFormedXmlFragment($translations{$lang, $lookup}); -- if ($translate && !$translation) { -- $translation = $lookup; -- } -- -- if ($translation || $translate) { -- print $fh "\n"; -- $leading_space =~ s/.*\n//g; -- print $fh $leading_space; -- print $fh "<", $nodename, " xml:lang=\"", $lang, "\"", $localattrs, ">"; -- if ($translate == 2) { -- translate_subnodes($fh, \@all, $lang, 1, $spacepreserve); -- } else { -- print $fh $translation; -- } -- print $fh "</$nodename>"; -- } -- } -- } -- -- } else { -- my $count = scalar(@all); -- if ($count > 0) { -- print $fh ">"; -- my $index = 0; -- while ($index < $count) { -- my $type = $all[$index]; -- my $rest = $all[$index+1]; -- traverse($fh, $type, $rest, $language, $spacepreserve); -- $index += 2; -- } -- print $fh "</$nodename>"; -- } else { -- print $fh "/>"; -- } -- } -- } --} -- --sub intltool_tree_comment --{ -- my $expat = shift; -- my $data = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 1 => $data; --} -- --sub intltool_tree_cdatastart --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- push @$clist, 0 => $expat->original_string(); --} -- --sub intltool_tree_cdataend --{ -- my $expat = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- $clist->[$pos] .= $expat->original_string(); --} -- --sub intltool_tree_char --{ -- my $expat = shift; -- my $text = shift; -- my $clist = $expat->{Curlist}; -- my $pos = $#$clist; -- -- # Use original_string so that we retain escaped entities -- # in CDATA sections. -- # -- if ($pos > 0 and $clist->[$pos - 1] eq '0') { -- $clist->[$pos] .= $expat->original_string(); -- } else { -- push @$clist, 0 => $expat->original_string(); -- } --} -- --sub intltool_tree_start --{ -- my $expat = shift; -- my $tag = shift; -- my @origlist = (); -- -- # Use original_string so that we retain escaped entities -- # in attribute values. We must convert the string to an -- # @origlist array to conform to the structure of the Tree -- # Style. -- # -- my @original_array = split /\x/, $expat->original_string(); -- my $source = $expat->original_string(); -- -- # Remove leading tag. -- # -- $source =~ s|^\s*<\s*(\S+)||s; -- -- # Grab attribute key/value pairs and push onto @origlist array. -- # -- while ($source) -- { -- if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s; -- push @origlist, $1; -- push @origlist, '"' . $2 . '"'; -- } -- elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/) -- { -- $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s; -- push @origlist, $1; -- push @origlist, "'" . $2 . "'"; -- } -- else -- { -- last; -- } -- } -- -- my $ol = [ { @origlist } ]; -- -- push @{ $expat->{Lists} }, $expat->{Curlist}; -- push @{ $expat->{Curlist} }, $tag => $ol; -- $expat->{Curlist} = $ol; --} -- --sub readXml --{ -- my $filename = shift || return; -- if(!-f $filename) { -- die "ERROR Cannot find filename: $filename\n"; -- } -- -- my $ret = eval 'require XML::Parser'; -- if(!$ret) { -- die "You must have XML::Parser installed to run $0\n\n"; -- } -- my $xp = new XML::Parser(Style => 'Tree'); -- $xp->setHandlers(Char => \&intltool_tree_char); -- $xp->setHandlers(Start => \&intltool_tree_start); -- $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart); -- $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend); -- my $tree = $xp->parsefile($filename); -- --# <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> --# would be: --# [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [{}, --# 0, "Howdy", ref, [{}]], 0, "do" ] ] -- -- return $tree; --} -- --sub print_header --{ -- my $infile = shift; -- my $fh = shift; -- my $source; -- -- if(!-f $infile) { -- die "ERROR Cannot find filename: $infile\n"; -- } -- -- print $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n}; -- { -- local $/; -- open DOCINPUT, "<${FILE}" or die; -- $source = <DOCINPUT>; -- close DOCINPUT; -- } -- if ($source =~ /(<!DOCTYPE.*\[.*\]\s*>)/s) -- { -- print $fh "$1\n"; -- } -- elsif ($source =~ /(<!DOCTYPE[^>]*>)/s) -- { -- print $fh "$1\n"; -- } --} -- --sub parseTree --{ -- my $fh = shift; -- my $ref = shift; -- my $language = shift || ""; -- -- my $name = shift @{ $ref }; -- my $cont = shift @{ $ref }; -- -- while (!$name || "$name" eq "1") { -- $name = shift @{ $ref }; -- $cont = shift @{ $ref }; -- } -- -- my $spacepreserve = 0; -- my $attrs = @{$cont}[0]; -- $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/)); -- -- traverse($fh, $name, $cont, $language, $spacepreserve); --} -- --sub xml_merge_output --{ -- my $source; -- -- if ($MULTIPLE_OUTPUT) { -- for my $lang (sort keys %po_files_by_lang) { -- if ( ! -e $lang ) { -- mkdir $lang or die "Cannot create subdirectory $lang: $!\n"; -- } -- open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n"; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- my $tree = readXml($FILE); -- print_header($FILE, \*OUTPUT); -- parseTree(\*OUTPUT, $tree, $lang); -- close OUTPUT; -- print "CREATED $lang/$OUTFILE\n" unless $QUIET_ARG; -- } -- } -- open OUTPUT, ">$OUTFILE" or die "Cannot open $OUTFILE: $!\n"; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- my $tree = readXml($FILE); -- print_header($FILE, \*OUTPUT); -- parseTree(\*OUTPUT, $tree); -- close OUTPUT; -- print "CREATED $OUTFILE\n" unless $QUIET_ARG; --} -- --sub keys_merge_translations --{ -- open INPUT, "<${FILE}" or die; -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while (<INPUT>) -- { -- if (s/^(\s*)_(\w+=(.*))/$1$2/) -- { -- my $string = $3; -- -- print OUTPUT; -- -- my $non_translated_line = $_; -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $translation = $translations{$lang, $string}; -- next if !$translation; -- -- $_ = $non_translated_line; -- s/(\w+)=.*/[$lang]$1=$translation/; -- print OUTPUT; -- } -- } -- else -- { -- print OUTPUT; -- } -- } -- -- close OUTPUT; -- close INPUT; --} -- --sub desktop_merge_translations --{ -- open INPUT, "<${FILE}" or die; -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while (<INPUT>) -- { -- if (s/^(\s*)_(\w+=(.*))/$1$2/) -- { -- my $string = $3; -- -- print OUTPUT; -- -- my $non_translated_line = $_; -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $translation = $translations{$lang, $string}; -- next if !$translation; -- -- $_ = $non_translated_line; -- s/(\w+)=.*/${1}[$lang]=$translation/; -- print OUTPUT; -- } -- } -- else -- { -- print OUTPUT; -- } -- } -- -- close OUTPUT; -- close INPUT; --} -- --sub schemas_merge_translations --{ -- my $source; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">$OUTFILE" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- # FIXME: support attribute translations -- -- # Empty nodes never need translation, so unmark all of them. -- # For example, <_foo/> is just replaced by <foo/>. -- $source =~ s|<\s*_($w+)\s*/>|<$1/>|g; -- -- while ($source =~ s/ -- (.*?) -- (\s+)(<locale\ name="C">(\s*) -- (<default>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/default>)?(\s*) -- (<short>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/short>)?(\s*) -- (<long>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/long>)?(\s*) -- <\/locale>) -- //sx) -- { -- print OUTPUT $1; -- -- my $locale_start_spaces = $2 ? $2 : ''; -- my $default_spaces = $4 ? $4 : ''; -- my $short_spaces = $7 ? $7 : ''; -- my $long_spaces = $10 ? $10 : ''; -- my $locale_end_spaces = $13 ? $13 : ''; -- my $c_default_block = $3 ? $3 : ''; -- my $default_string = $6 ? $6 : ''; -- my $short_string = $9 ? $9 : ''; -- my $long_string = $12 ? $12 : ''; -- -- print OUTPUT "$locale_start_spaces$c_default_block"; -- -- $default_string =~ s/\s+/ /g; -- $default_string = entity_decode($default_string); -- $short_string =~ s/\s+/ /g; -- $short_string = entity_decode($short_string); -- $long_string =~ s/\s+/ /g; -- $long_string = entity_decode($long_string); -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $default_translation = $translations{$lang, $default_string}; -- my $short_translation = $translations{$lang, $short_string}; -- my $long_translation = $translations{$lang, $long_string}; -- -- next if (!$default_translation && !$short_translation && -- !$long_translation); -- -- print OUTPUT "\n$locale_start_spaces<locale name=\"$lang\">"; -- -- print OUTPUT "$default_spaces"; -- -- if ($default_translation) -- { -- $default_translation = entity_encode($default_translation); -- print OUTPUT "<default>$default_translation</default>"; -- } -- -- print OUTPUT "$short_spaces"; -- -- if ($short_translation) -- { -- $short_translation = entity_encode($short_translation); -- print OUTPUT "<short>$short_translation</short>"; -- } -- -- print OUTPUT "$long_spaces"; -- -- if ($long_translation) -- { -- $long_translation = entity_encode($long_translation); -- print OUTPUT "<long>$long_translation</long>"; -- } -- -- print OUTPUT "$locale_end_spaces</locale>"; -- } -- } -- -- print OUTPUT $source; -- -- close OUTPUT; --} -- --sub rfc822deb_merge_translations --{ -- my %encodings = (); -- for my $lang (keys %po_files_by_lang) { -- $encodings{$lang} = ($UTF8_ARG ? 'UTF-8' : get_po_encoding($po_files_by_lang{$lang})); -- } -- -- my $source; -- -- $Text::Wrap::huge = 'overflow'; -- $Text::Wrap::break = qr/\n|\s(?=\S)/; -- -- { -- local $/; # slurp mode -- open INPUT, "<$FILE" or die "can't open $FILE: $!"; -- $source = <INPUT>; -- close INPUT; -- } -- -- open OUTPUT, ">${OUTFILE}" or die; -- binmode (OUTPUT) if $^O eq 'MSWin32'; -- -- while ($source =~ /(^|\n+)(_*)([^:\s]+)(:[ \t]*)(.*?)(?=\n[\S\n]|$)/sg) -- { -- my $sep = $1; -- my $non_translated_line = $3.$4; -- my $string = $5; -- my $underscore = length($2); -- next if $underscore eq 0 && $non_translated_line =~ /^#/; -- # Remove [] dummy strings -- my $stripped = $string; -- $stripped =~ s/\[\s[^\[\]]*\],/,/g if $underscore eq 2; -- $stripped =~ s/\[\s[^\[\]]*\]$//; -- $non_translated_line .= $stripped; -- -- print OUTPUT $sep.$non_translated_line; -- -- if ($underscore) -- { -- my @str_list = rfc822deb_split($underscore, $string); -- -- for my $lang (sort keys %po_files_by_lang) -- { -- my $is_translated = 1; -- my $str_translated = ''; -- my $first = 1; -- -- for my $str (@str_list) -- { -- my $translation = $translations{$lang, $str}; -- -- if (!$translation) -- { -- $is_translated = 0; -- last; -- } -- -- # $translation may also contain [] dummy -- # strings, mostly to indicate an empty string -- $translation =~ s/\[\s[^\[\]]*\]$//; -- -- if ($first) -- { -- if ($underscore eq 2) -- { -- $str_translated .= $translation; -- } -- else -- { -- $str_translated .= -- Text::Tabs::expand($translation) . -- "\n"; -- } -- } -- else -- { -- if ($underscore eq 2) -- { -- $str_translated .= ', ' . $translation; -- } -- else -- { -- $str_translated .= Text::Tabs::expand( -- Text::Wrap::wrap(' ', ' ', $translation)) . -- "\n .\n"; -- } -- } -- $first = 0; -- -- # To fix some problems with Text::Wrap::wrap -- $str_translated =~ s/(\n )+\n/\n .\n/g; -- } -- next unless $is_translated; -- -- $str_translated =~ s/\n \.\n$//; -- $str_translated =~ s/\s+$//; -- -- $_ = $non_translated_line; -- s/^(\w+):\s*.*/$sep${1}-$lang.$encodings{$lang}: $str_translated/s; -- print OUTPUT; -- } -- } -- } -- print OUTPUT "\n"; -- -- close OUTPUT; -- close INPUT; --} -- --sub rfc822deb_split --{ -- # Debian defines a special way to deal with rfc822-style files: -- # when a value contain newlines, it consists of -- # 1. a short form (first line) -- # 2. a long description, all lines begin with a space, -- # and paragraphs are separated by a single dot on a line -- # This routine returns an array of all paragraphs, and reformat -- # them. -- # When first argument is 2, the string is a comma separated list of -- # values. -- my $type = shift; -- my $text = shift; -- $text =~ s/^[ \t]//mg; -- return (split(/, */, $text, 0)) if $type ne 1; -- return ($text) if $text !~ /\n/; -- -- $text =~ s/([^\n]*)\n//; -- my @list = ($1); -- my $str = ''; -- -- for my $line (split (/\n/, $text)) -- { -- chomp $line; -- if ($line =~ /^\.\s*$/) -- { -- # New paragraph -- $str =~ s/\s*$//; -- push(@list, $str); -- $str = ''; -- } -- elsif ($line =~ /^\s/) -- { -- # Line which must not be reformatted -- $str .= "\n" if length ($str) && $str !~ /\n$/; -- $line =~ s/\s+$//; -- $str .= $line."\n"; -- } -- else -- { -- # Continuation line, remove newline -- $str .= " " if length ($str) && $str !~ /\n$/; -- $str .= $line; -- } -- } -- -- $str =~ s/\s*$//; -- push(@list, $str) if length ($str); -- -- return @list; --} -- -diff --git a/intltool-merge.in b/intltool-merge.in -new file mode 120000 -index d0535ab..2238bbd ---- /dev/null -+++ b/intltool-merge.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-merge.in -\ No newline at end of file -diff --git a/intltool-update.in b/intltool-update.in -deleted file mode 100755 -index 661d8fe..0b1800f ---- a/intltool-update.in -+++ /dev/null -@@ -1,1089 +0,0 @@ --#!@INTLTOOL_PERL@ -w --# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*- -- --# --# The Intltool Message Updater --# --# Copyright (C) 2000-2003 Free Software Foundation. --# --# Intltool is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License --# version 2 published by the Free Software Foundation. --# --# Intltool is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --# General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --# --# As a special exception to the GNU General Public License, if you --# distribute this file as part of a program that contains a --# configuration script generated by Autoconf, you may include it under --# the same distribution terms that you use for the rest of that program. --# --# Authors: Kenneth Christiansen <kenneth@gnu.org> --# Maciej Stachowiak --# Darin Adler <darin@bentspoon.com> -- --## Release information --my $PROGRAM = "intltool-update"; --my $VERSION = "0.35.0"; --my $PACKAGE = "intltool"; -- --## Loaded modules --use strict; --use Getopt::Long; --use Cwd; --use File::Copy; --use File::Find; -- --## Scalars used by the option stuff --my $HELP_ARG = 0; --my $VERSION_ARG = 0; --my $DIST_ARG = 0; --my $POT_ARG = 0; --my $HEADERS_ARG = 0; --my $MAINTAIN_ARG = 0; --my $REPORT_ARG = 0; --my $VERBOSE = 0; --my $GETTEXT_PACKAGE = ""; --my $OUTPUT_FILE = ""; -- --my @languages; --my %varhash = (); --my %po_files_by_lang = (); -- --# Regular expressions to categorize file types. --# FIXME: Please check if the following is correct -- --my $xml_support = --"xml(?:\\.in)*|". # http://www.w3.org/XML/ (Note: .in is not required) --"ui|". # Bonobo specific - User Interface desc. files --"lang|". # ? --"glade2?(?:\\.in)*|". # Glade specific - User Interface desc. files (Note: .in is not required) --"scm(?:\\.in)*|". # ? (Note: .in is not required) --"oaf(?:\\.in)+|". # DEPRECATED: Replaces by Bonobo .server files --"etspec|". # ? --"server(?:\\.in)+|". # Bonobo specific --"sheet(?:\\.in)+|". # ? --"schemas(?:\\.in)+|". # GConf specific --"pong(?:\\.in)+|". # DEPRECATED: PONG is not used [by GNOME] any longer. --"kbd(?:\\.in)+"; # GOK specific. -- --my $ini_support = --"icon(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec --"desktop(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec --"caves(?:\\.in)+|". # GNOME Games specific --"directory(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec --"soundlist(?:\\.in)+|". # GNOME specific --"keys(?:\\.in)+|". # GNOME Mime database specific --"theme(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec --"service(?:\\.in)+"; # DBus specific -- --my $buildin_gettext_support = --"c|y|cs|cc|cpp|c\\+\\+|h|hh|gob|py"; -- --## Always flush buffer when printing --$| = 1; -- --## Sometimes the source tree will be rooted somewhere else. --my $SRCDIR = "."; --my $POTFILES_in; -- --$SRCDIR = $ENV{"srcdir"} if $ENV{"srcdir"}; --$POTFILES_in = "<$SRCDIR/POTFILES.in"; -- --my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null'); -- --## Handle options --GetOptions --( -- "help" => \$HELP_ARG, -- "version" => \$VERSION_ARG, -- "dist|d" => \$DIST_ARG, -- "pot|p" => \$POT_ARG, -- "headers|s" => \$HEADERS_ARG, -- "maintain|m" => \$MAINTAIN_ARG, -- "report|r" => \$REPORT_ARG, -- "verbose|x" => \$VERBOSE, -- "gettext-package|g=s" => \$GETTEXT_PACKAGE, -- "output-file|o=s" => \$OUTPUT_FILE, -- ) or &Console_WriteError_InvalidOption; -- --&Console_Write_IntltoolHelp if $HELP_ARG; --&Console_Write_IntltoolVersion if $VERSION_ARG; -- --my $arg_count = ($DIST_ARG > 0) -- + ($POT_ARG > 0) -- + ($HEADERS_ARG > 0) -- + ($MAINTAIN_ARG > 0) -- + ($REPORT_ARG > 0); -- --&Console_Write_IntltoolHelp if $arg_count > 1; -- --# --version and --help don't require a module name --my $MODULE = $GETTEXT_PACKAGE || &FindPackageName || "unknown"; -- --if ($POT_ARG) --{ -- &GenerateHeaders; -- &GeneratePOTemplate; --} --elsif ($HEADERS_ARG) --{ -- &GenerateHeaders; --} --elsif ($MAINTAIN_ARG) --{ -- &FindLeftoutFiles; --} --elsif ($REPORT_ARG) --{ -- &GenerateHeaders; -- &GeneratePOTemplate; -- &Console_Write_CoverageReport; --} --elsif ((defined $ARGV[0]) && $ARGV[0] =~ /^[a-z]/) --{ -- my $lang = $ARGV[0]; -- -- ## Report error if the language file supplied -- ## to the command line is non-existent -- &Console_WriteError_NotExisting("$SRCDIR/$lang.po") -- if ! -s "$SRCDIR/$lang.po"; -- -- if (!$DIST_ARG) -- { -- print "Working, please wait..." if $VERBOSE; -- &GenerateHeaders; -- &GeneratePOTemplate; -- } -- &POFile_Update ($lang, $OUTPUT_FILE); -- &Console_Write_TranslationStatus ($lang, $OUTPUT_FILE); --} --else --{ -- &Console_Write_IntltoolHelp; --} -- --exit; -- --######### -- --sub Console_Write_IntltoolVersion --{ -- print <<_EOF_; --${PROGRAM} (${PACKAGE}) $VERSION --Written by Kenneth Christiansen, Maciej Stachowiak, and Darin Adler. -- --Copyright (C) 2000-2003 Free Software Foundation, Inc. --This is free software; see the source for copying conditions. There is NO --warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --_EOF_ -- exit; --} -- --sub Console_Write_IntltoolHelp --{ -- print <<_EOF_; --Usage: ${PROGRAM} [OPTION]... LANGCODE --Updates PO template files and merge them with the translations. -- --Mode of operation (only one is allowed): -- -p, --pot generate the PO template only -- -s, --headers generate the header files in POTFILES.in -- -m, --maintain search for left out files from POTFILES.in -- -r, --report display a status report for the module -- -d, --dist merge LANGCODE.po with existing PO template -- --Extra options: -- -g, --gettext-package=NAME override PO template name, useful with --pot -- -o, --output-file=FILE write merged translation to FILE -- -x, --verbose display lots of feedback -- --help display this help and exit -- --version output version information and exit -- --Examples of use: --${PROGRAM} --pot just create a new PO template --${PROGRAM} xy create new PO template and merge xy.po with it -- --Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE") --or send email to <xml-i18n-tools\@gnome.org>. --_EOF_ -- exit; --} -- --sub echo_n --{ -- my $str = shift; -- my $ret = `echo "$str"`; -- -- $ret =~ s/\n$//; # do we need the "s" flag? -- -- return $ret; --} -- --sub POFile_DetermineType ($) --{ -- my $type = $_; -- my $gettext_type; -- -- my $xml_regex = "(?:" . $xml_support . ")"; -- my $ini_regex = "(?:" . $ini_support . ")"; -- my $buildin_regex = "(?:" . $buildin_gettext_support . ")"; -- -- if ($type =~ /\[type: gettext\/([^\]].*)]/) -- { -- $gettext_type=$1; -- } -- elsif ($type =~ /schemas(\.in)+$/) -- { -- $gettext_type="schemas"; -- } -- elsif ($type =~ /glade2?(\.in)*$/) -- { -- $gettext_type="glade"; -- } -- elsif ($type =~ /scm(\.in)*$/) -- { -- $gettext_type="scheme"; -- } -- elsif ($type =~ /keys(\.in)+$/) -- { -- $gettext_type="keys"; -- } -- -- # bucket types -- -- elsif ($type =~ /$xml_regex$/) -- { -- $gettext_type="xml"; -- } -- elsif ($type =~ /$ini_regex$/) -- { -- $gettext_type="ini"; -- } -- elsif ($type =~ /$buildin_regex$/) -- { -- $gettext_type="buildin"; -- } -- else -- { -- $gettext_type="unknown"; -- } -- -- return "gettext\/$gettext_type"; --} -- --sub TextFile_DetermineEncoding ($) --{ -- my $gettext_code="ASCII"; # All files are ASCII by default -- my $filetype=`file $_ | cut -d ' ' -f 2`; -- -- if ($? eq "0") -- { -- if ($filetype =~ /^(ISO|UTF)/) -- { -- chomp ($gettext_code = $filetype); -- } -- elsif ($filetype =~ /^XML/) -- { -- $gettext_code="UTF-8"; # We asume that .glade and other .xml files are UTF-8 -- } -- } -- -- return $gettext_code; --} -- --sub isNotValidMissing --{ -- my ($file) = @_; -- -- return if $file =~ /^\{arch\}\/.*$/; -- return if $file =~ /^$varhash{"PACKAGE"}-$varhash{"VERSION"}\/.*$/; --} -- --sub FindLeftoutFiles --{ -- my (@buf_i18n_plain, -- @buf_i18n_xml, -- @buf_i18n_xml_unmarked, -- @buf_i18n_ini, -- @buf_potfiles, -- @buf_potfiles_ignore, -- @buf_allfiles, -- @buf_allfiles_sorted, -- @buf_potfiles_sorted -- ); -- -- ## Search and find all translatable files -- find sub { -- push @buf_i18n_plain, "$File::Find::name" if /\.($buildin_gettext_support)$/; -- push @buf_i18n_xml, "$File::Find::name" if /\.($xml_support)$/; -- push @buf_i18n_ini, "$File::Find::name" if /\.($ini_support)$/; -- push @buf_i18n_xml_unmarked, "$File::Find::name" if /\.(schemas(\.in)+)$/; -- }, ".."; -- -- -- open POTFILES, $POTFILES_in or die "$PROGRAM: there's no POTFILES.in!\n"; -- @buf_potfiles = grep !/^(#|\s*$)/, <POTFILES>; -- close POTFILES; -- -- foreach (@buf_potfiles) { -- s/^\[.*]\s*//; -- } -- -- print "Searching for missing translatable files...\n" if $VERBOSE; -- -- ## Check if we should ignore some found files, when -- ## comparing with POTFILES.in -- foreach my $ignore ("POTFILES.skip", "POTFILES.ignore") -- { -- (-s $ignore) or next; -- -- if ("$ignore" eq "POTFILES.ignore") -- { -- print "The usage of POTFILES.ignore is deprecated. Please consider moving the\n". -- "content of this file to POTFILES.skip.\n"; -- } -- -- print "Found $ignore: Ignoring files...\n" if $VERBOSE; -- open FILE, "<$ignore" or die "ERROR: Failed to open $ignore!\n"; -- -- while (<FILE>) -- { -- push @buf_potfiles_ignore, $_ unless /^(#|\s*$)/; -- } -- close FILE; -- -- @buf_potfiles = (@buf_potfiles_ignore, @buf_potfiles); -- } -- -- foreach my $file (@buf_i18n_plain) -- { -- my $in_comment = 0; -- my $in_macro = 0; -- -- open FILE, "<$file"; -- while (<FILE>) -- { -- # Handle continued multi-line comment. -- if ($in_comment) -- { -- next unless s-.*\*/--; -- $in_comment = 0; -- } -- -- # Handle continued macro. -- if ($in_macro) -- { -- $in_macro = 0 unless /\\$/; -- next; -- } -- -- # Handle start of macro (or any preprocessor directive). -- if (/^\s*\#/) -- { -- $in_macro = 1 if /^([^\\]|\\.)*\\$/; -- next; -- } -- -- # Handle comments and quoted text. -- while (m-(/\*|//|\'|\")-) # \' and \" keep emacs perl mode happy -- { -- my $match = $1; -- if ($match eq "/*") -- { -- if (!s-/\*.*?\*/--) -- { -- s-/\*.*--; -- $in_comment = 1; -- } -- } -- elsif ($match eq "//") -- { -- s-//.*--; -- } -- else # ' or " -- { -- if (!s-$match([^\\]|\\.)*?$match-QUOTEDTEXT-) -- { -- warn "mismatched quotes at line $. in $file\n"; -- s-$match.*--; -- } -- } -- } -- -- if (/\.GetString ?\(QUOTEDTEXT/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- ## Remove the first 3 chars and add newline -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- -- if (/_\(QUOTEDTEXT/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- ## Remove the first 3 chars and add newline -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_xml) -- { -- open FILE, "<$file"; -- -- while (<FILE>) -- { -- # FIXME: share the pattern matching code with intltool-extract -- if (/\s_[-A-Za-z0-9._:]+\s*=\s*\"([^"]+)\"/ || /<_[^>]+>/ || /translatable=\"yes\"/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_ini) -- { -- open FILE, "<$file"; -- while (<FILE>) -- { -- if (/_(.*)=/) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- last; -- } -- } -- close FILE; -- } -- -- foreach my $file (@buf_i18n_xml_unmarked) -- { -- if (defined isNotValidMissing (unpack("x3 A*", $file))) { -- push @buf_allfiles, unpack("x3 A*", $file) . "\n"; -- } -- } -- -- -- @buf_allfiles_sorted = sort (@buf_allfiles); -- @buf_potfiles_sorted = sort (@buf_potfiles); -- -- my %in2; -- foreach (@buf_potfiles_sorted) -- { -- $in2{$_} = 1; -- } -- -- my @result; -- -- foreach (@buf_allfiles_sorted) -- { -- if (!exists($in2{$_})) -- { -- push @result, $_ -- } -- } -- -- my @buf_potfiles_notexist; -- -- foreach (@buf_potfiles_sorted) -- { -- chomp (my $dummy = $_); -- if ("$dummy" ne "" and ! -f "../$dummy") -- { -- push @buf_potfiles_notexist, $_; -- } -- } -- -- ## Save file with information about the files missing -- ## if any, and give information about this procedure. -- if (@result + @buf_potfiles_notexist > 0) -- { -- if (@result) -- { -- print "\n" if $VERBOSE; -- unlink "missing"; -- open OUT, ">missing"; -- print OUT @result; -- close OUT; -- warn "\e[1mThe following files contain translations and are currently not in use. Please\e[0m\n". -- "\e[1mconsider adding these to the POTFILES.in file, located in the po/ directory.\e[0m\n\n"; -- print STDERR @result, "\n"; -- warn "If some of these files are left out on purpose then please add them to\n". -- "POTFILES.skip instead of POTFILES.in. A file \e[1m'missing'\e[0m containing this list\n". -- "of left out files has been written in the current directory.\n"; -- } -- if (@buf_potfiles_notexist) -- { -- unlink "notexist"; -- open OUT, ">notexist"; -- print OUT @buf_potfiles_notexist; -- close OUT; -- warn "\n" if ($VERBOSE or @result); -- warn "\e[1mThe following files do not exist anymore:\e[0m\n\n"; -- warn @buf_potfiles_notexist, "\n"; -- warn "Please remove them from POTFILES.in or POTFILES.skip. A file \e[1m'notexist'\e[0m\n". -- "containing this list of absent files has been written in the current directory.\n"; -- } -- } -- -- ## If there is nothing to complain about, notify the user -- else { -- print "\nAll files containing translations are present in POTFILES.in.\n" if $VERBOSE; -- } --} -- --sub Console_WriteError_InvalidOption --{ -- ## Handle invalid arguments -- print STDERR "Try `${PROGRAM} --help' for more information.\n"; -- exit 1; --} -- --sub GenerateHeaders --{ -- my $EXTRACT = "@INTLTOOL_EXTRACT@"; -- chomp $EXTRACT; -- -- $EXTRACT = $ENV{"INTLTOOL_EXTRACT"} if $ENV{"INTLTOOL_EXTRACT"}; -- -- ## Generate the .h header files, so we can allow glade and -- ## xml translation support -- if (! -x "$EXTRACT") -- { -- print STDERR "\n *** The intltool-extract script wasn't found!" -- ."\n *** Without it, intltool-update can not generate files.\n"; -- exit; -- } -- else -- { -- open (FILE, $POTFILES_in) or die "$PROGRAM: POTFILES.in not found.\n"; -- -- while (<FILE>) -- { -- chomp; -- next if /^\[\s*encoding/; -- -- ## Find xml files in POTFILES.in and generate the -- ## files with help from the extract script -- -- my $gettext_type= &POFile_DetermineType ($1); -- -- if (/\.($xml_support|$ini_support)$/ || /^\[/) -- { -- s/^\[[^\[].*]\s*//; -- -- my $filename = "../$_"; -- -- if ($VERBOSE) -- { -- system ($EXTRACT, "--update", "--srcdir=$SRCDIR", -- "--type=$gettext_type", $filename); -- } -- else -- { -- system ($EXTRACT, "--update", "--type=$gettext_type", -- "--srcdir=$SRCDIR", "--quiet", $filename); -- } -- } -- } -- close FILE; -- } --} -- --# --# Generate .pot file from POTFILES.in --# --sub GeneratePOTemplate --{ -- my $XGETTEXT = $ENV{"XGETTEXT"} || "@INTLTOOL_XGETTEXT@"; -- my $XGETTEXT_ARGS = $ENV{"XGETTEXT_ARGS"} || ''; -- chomp $XGETTEXT; -- -- if (! -x $XGETTEXT) -- { -- print STDERR " *** xgettext is not found on this system!\n". -- " *** Without it, intltool-update can not extract strings.\n"; -- exit; -- } -- -- print "Building $MODULE.pot...\n" if $VERBOSE; -- -- open INFILE, $POTFILES_in; -- unlink "POTFILES.in.temp"; -- open OUTFILE, ">POTFILES.in.temp" or die("Cannot open POTFILES.in.temp for writing"); -- -- my $gettext_support_nonascii = 0; -- -- # checks for GNU gettext >= 0.12 -- my $dummy = `$XGETTEXT --version --from-code=UTF-8 >$devnull 2>$devnull`; -- if ($? == 0) -- { -- $gettext_support_nonascii = 1; -- } -- else -- { -- # urge everybody to upgrade gettext -- print STDERR "WARNING: This version of gettext does not support extracting non-ASCII\n". -- " strings. That means you should install a version of gettext\n". -- " that supports non-ASCII strings (such as GNU gettext >= 0.12),\n". -- " or have to let non-ASCII strings untranslated. (If there is any)\n"; -- } -- -- my $encoding = "ASCII"; -- my $forced_gettext_code; -- my @temp_headers; -- my $encoding_problem_is_reported = 0; -- -- while (<INFILE>) -- { -- next if (/^#/ or /^\s*$/); -- -- chomp; -- -- my $gettext_code; -- -- if (/^\[\s*encoding:\s*(.*)\s*\]/) -- { -- $forced_gettext_code=$1; -- } -- elsif (/\.($xml_support|$ini_support)$/ || /^\[/) -- { -- s/^\[.*]\s*//; -- print OUTFILE "../$_.h\n"; -- push @temp_headers, "../$_.h"; -- $gettext_code = &TextFile_DetermineEncoding ("../$_.h") if ($gettext_support_nonascii and not defined $forced_gettext_code); -- } -- else -- { -- if ($SRCDIR eq ".") { -- print OUTFILE "../$_\n"; -- } else { -- print OUTFILE "$SRCDIR/../$_\n"; -- } -- $gettext_code = &TextFile_DetermineEncoding ("../$_") if ($gettext_support_nonascii and not defined $forced_gettext_code); -- } -- -- next if (! $gettext_support_nonascii); -- -- if (defined $forced_gettext_code) -- { -- $encoding=$forced_gettext_code; -- } -- elsif (defined $gettext_code and "$encoding" ne "$gettext_code") -- { -- if ($encoding eq "ASCII") -- { -- $encoding=$gettext_code; -- } -- elsif ($gettext_code ne "ASCII") -- { -- # Only report once because the message is quite long -- if (! $encoding_problem_is_reported) -- { -- print STDERR "WARNING: You should use the same file encoding for all your project files,\n". -- " but $PROGRAM thinks that most of the source files are in\n". -- " $encoding encoding, while \"$_\" is (likely) in\n". -- " $gettext_code encoding. If you are sure that all translatable strings\n". -- " are in same encoding (say UTF-8), please \e[1m*prepend*\e[0m the following\n". -- " line to POTFILES.in:\n\n". -- " [encoding: UTF-8]\n\n". -- " and make sure that configure.in/ac checks for $PACKAGE >= 0.27 .\n". -- "(such warning message will only be reported once.)\n"; -- $encoding_problem_is_reported = 1; -- } -- } -- } -- } -- -- close OUTFILE; -- close INFILE; -- -- unlink "$MODULE.pot"; -- my @xgettext_argument=("$XGETTEXT", -- "--add-comments", -- "--directory\=\.", -- "--output\=$MODULE\.pot", -- "--files-from\=\.\/POTFILES\.in\.temp"); -- my $XGETTEXT_KEYWORDS = &FindPOTKeywords; -- push @xgettext_argument, $XGETTEXT_KEYWORDS; -- my $MSGID_BUGS_ADDRESS = &FindMakevarsBugAddress; -- push @xgettext_argument, "--msgid-bugs-address\=$MSGID_BUGS_ADDRESS" if $MSGID_BUGS_ADDRESS; -- push @xgettext_argument, "--from-code\=$encoding" if ($gettext_support_nonascii); -- push @xgettext_argument, $XGETTEXT_ARGS if $XGETTEXT_ARGS; -- my $xgettext_command = join ' ', @xgettext_argument; -- -- # intercept xgettext error message -- print "Running $xgettext_command\n" if $VERBOSE; -- my $xgettext_error_msg = `$xgettext_command 2>\&1`; -- my $command_failed = $?; -- -- unlink "POTFILES.in.temp"; -- -- print "Removing generated header (.h) files..." if $VERBOSE; -- unlink foreach (@temp_headers); -- print "done.\n" if $VERBOSE; -- -- if (! $command_failed) -- { -- if (! -e "$MODULE.pot") -- { -- print "None of the files in POTFILES.in contain strings marked for translation.\n" if $VERBOSE; -- } -- else -- { -- print "Wrote $MODULE.pot\n" if $VERBOSE; -- } -- } -- else -- { -- if ($xgettext_error_msg =~ /--from-code/) -- { -- # replace non-ASCII error message with a more useful one. -- print STDERR "ERROR: xgettext failed to generate PO template file because there is non-ASCII\n". -- " string marked for translation. Please make sure that all strings marked\n". -- " for translation are in uniform encoding (say UTF-8), then \e[1m*prepend*\e[0m the\n". -- " following line to POTFILES.in and rerun $PROGRAM:\n\n". -- " [encoding: UTF-8]\n\n"; -- } -- else -- { -- print STDERR "$xgettext_error_msg"; -- if (-e "$MODULE.pot") -- { -- # is this possible? -- print STDERR "ERROR: xgettext failed but still managed to generate PO template file.\n". -- " Please consult error message above if there is any.\n"; -- } -- else -- { -- print STDERR "ERROR: xgettext failed to generate PO template file. Please consult\n". -- " error message above if there is any.\n"; -- } -- } -- exit (1); -- } --} -- --sub POFile_Update --{ -- -f "$MODULE.pot" or die "$PROGRAM: $MODULE.pot does not exist.\n"; -- -- my $MSGMERGE = $ENV{"MSGMERGE"} || "@INTLTOOL_MSGMERGE@"; -- my ($lang, $outfile) = @_; -- -- print "Merging $SRCDIR/$lang.po with $MODULE.pot..." if $VERBOSE; -- -- my $infile = "$SRCDIR/$lang.po"; -- $outfile = "$SRCDIR/$lang.po" if ($outfile eq ""); -- -- # I think msgmerge won't overwrite old file if merge is not successful -- system ("$MSGMERGE", "-o", $outfile, $infile, "$MODULE.pot"); --} -- --sub Console_WriteError_NotExisting --{ -- my ($file) = @_; -- -- ## Report error if supplied language file is non-existing -- print STDERR "$PROGRAM: $file does not exist!\n"; -- print STDERR "Try '$PROGRAM --help' for more information.\n"; -- exit; --} -- --sub GatherPOFiles --{ -- my @po_files = glob ("./*.po"); -- -- @languages = map (&POFile_GetLanguage, @po_files); -- -- foreach my $lang (@languages) -- { -- $po_files_by_lang{$lang} = shift (@po_files); -- } --} -- --sub POFile_GetLanguage ($) --{ -- s/^(.*\/)?(.+)\.po$/$2/; -- return $_; --} -- --sub Console_Write_TranslationStatus --{ -- my ($lang, $output_file) = @_; -- my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@"; -- -- $output_file = "$SRCDIR/$lang.po" if ($output_file eq ""); -- -- system ("$MSGFMT", "-o", "$devnull", "--verbose", $output_file); --} -- --sub Console_Write_CoverageReport --{ -- my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@"; -- -- &GatherPOFiles; -- -- foreach my $lang (@languages) -- { -- print "$lang: "; -- &POFile_Update ($lang, ""); -- } -- -- print "\n\n * Current translation support in $MODULE \n\n"; -- -- foreach my $lang (@languages) -- { -- print "$lang: "; -- system ("$MSGFMT", "-o", "$devnull", "--verbose", "$SRCDIR/$lang.po"); -- } --} -- --sub SubstituteVariable --{ -- my ($str) = @_; -- -- # always need to rewind file whenever it has been accessed -- seek (CONF, 0, 0); -- -- # cache each variable. varhash is global to we can add -- # variables elsewhere. -- while (<CONF>) -- { -- if (/^(\w+)=(.*)$/) -- { -- ($varhash{$1} = $2) =~ s/^["'](.*)["']$/$1/; -- } -- } -- -- if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/) -- { -- my $rest = $3; -- my $untouched = $1; -- my $sub = ""; -- # Ignore recursive definitions of variables -- $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/; -- -- return SubstituteVariable ("$untouched$sub$rest"); -- } -- -- # We're using Perl backticks ` and "echo -n" here in order to -- # expand any shell escapes (such as backticks themselves) in every variable -- return echo_n ($str); --} -- --sub CONF_Handle_Open --{ -- my $base_dirname = getcwd(); -- $base_dirname =~ s@.*/@@; -- -- my ($conf_in, $src_dir); -- -- if ($base_dirname =~ /^po(-.+)?$/) -- { -- if (-f "Makevars") -- { -- my $makefile_source; -- -- local (*IN); -- open (IN, "<Makevars") || die "can't open Makevars: $!"; -- -- while (<IN>) -- { -- if (/^top_builddir[ \t]*=/) -- { -- $src_dir = $_; -- $src_dir =~ s/^top_builddir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/; -- -- chomp $src_dir; -- if (-f "$src_dir" . "/configure.ac") { -- $conf_in = "$src_dir" . "/configure.ac" . "\n"; -- } else { -- $conf_in = "$src_dir" . "/configure.in" . "\n"; -- } -- last; -- } -- } -- close IN; -- -- $conf_in || die "Cannot find top_builddir in Makevars."; -- } -- elsif (-f "../configure.ac") -- { -- $conf_in = "../configure.ac"; -- } -- elsif (-f "../configure.in") -- { -- $conf_in = "../configure.in"; -- } -- else -- { -- my $makefile_source; -- -- local (*IN); -- open (IN, "<Makefile") || return; -- -- while (<IN>) -- { -- if (/^top_srcdir[ \t]*=/) -- { -- $src_dir = $_; -- $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/; -- -- chomp $src_dir; -- $conf_in = "$src_dir" . "/configure.in" . "\n"; -- -- last; -- } -- } -- close IN; -- -- $conf_in || die "Cannot find top_srcdir in Makefile."; -- } -- -- open (CONF, "<$conf_in"); -- } -- else -- { -- print STDERR "$PROGRAM: Unable to proceed.\n" . -- "Make sure to run this script inside the po directory.\n"; -- exit; -- } --} -- --sub FindPackageName --{ -- my $version; -- my $domain = &FindMakevarsDomain; -- my $name = $domain || "untitled"; -- -- &CONF_Handle_Open; -- -- my $conf_source; { -- local (*IN); -- open (IN, "<&CONF") || return $name; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $conf_source = <IN>; -- close IN; -- } -- -- # priority for getting package name: -- # 1. GETTEXT_PACKAGE -- # 2. first argument of AC_INIT (with >= 2 arguments) -- # 3. first argument of AM_INIT_AUTOMAKE (with >= 2 argument) -- -- # /^AM_INIT_AUTOMAKE\([\s\[]*([^,\)\s\]]+)/m -- # the \s makes this not work, why? -- if ($conf_source =~ /^AM_INIT_AUTOMAKE\(([^,\)]+),([^,\)]+)/m) -- { -- ($name, $version) = ($1, $2); -- $name =~ s/[\[\]\s]//g; -- $version =~ s/[\[\]\s]//g; -- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); -- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); -- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); -- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); -- } -- -- if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)/m) -- { -- ($name, $version) = ($1, $2); -- $name =~ s/[\[\]\s]//g; -- $version =~ s/[\[\]\s]//g; -- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); -- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); -- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); -- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); -- } -- -- # \s makes this not work, why? -- $name = $1 if $conf_source =~ /^GETTEXT_PACKAGE=\[?([^\n\]]+)/m; -- -- # m4 macros AC_PACKAGE_NAME, AC_PACKAGE_VERSION etc. have same value -- # as corresponding $PACKAGE_NAME, $PACKAGE_VERSION etc. shell variables. -- $name =~ s/\bAC_PACKAGE_/\$PACKAGE_/g; -- -- $name = $domain if $domain; -- -- $name = SubstituteVariable ($name); -- $name =~ s/^["'](.*)["']$/$1/; -- -- return $name if $name; --} -- -- --sub FindPOTKeywords --{ -- -- my $keywords = "--keyword\=\_ --keyword\=N\_ --keyword\=U\_ --keyword\=Q\_"; -- my $varname = "XGETTEXT_OPTIONS"; -- my $make_source; { -- local (*IN); -- open (IN, "<Makevars") || (open(IN, "<Makefile.in.in") && ($varname = "XGETTEXT_KEYWORDS")) || return $keywords; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $make_source = <IN>; -- close IN; -- } -- -- $keywords = $1 if $make_source =~ /^$varname[ ]*=\[?([^\n\]]+)/m; -- -- return $keywords; --} -- --sub FindMakevarsDomain --{ -- -- my $domain = ""; -- my $makevars_source; { -- local (*IN); -- open (IN, "<Makevars") || return $domain; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $makevars_source = <IN>; -- close IN; -- } -- -- $domain = $1 if $makevars_source =~ /^DOMAIN[ ]*=\[?([^\n\]\$]+)/m; -- $domain =~ s/^\s+//; -- $domain =~ s/\s+$//; -- -- return $domain; --} -- --sub FindMakevarsBugAddress --{ -- -- my $address = ""; -- my $makevars_source; { -- local (*IN); -- open (IN, "<Makevars") || return undef; -- seek (IN, 0, 0); -- local $/; # slurp mode -- $makevars_source = <IN>; -- close IN; -- } -- -- $address = $1 if $makevars_source =~ /^MSGID_BUGS_ADDRESS[ ]*=\[?([^\n\]\$]+)/m; -- $address =~ s/^\s+//; -- $address =~ s/\s+$//; -- -- return $address; --} -diff --git a/intltool-update.in b/intltool-update.in -new file mode 120000 -index 661d8fe..0b1800f ---- /dev/null -+++ b/intltool-update.in -@@ -0,0 +1 @@ -+/usr/share/intltool/intltool-update.in -\ No newline at end of file -diff --git a/pixmaps/intlclock-map-location-current.png b/pixmaps/intlclock-map-location-current.png -new file mode 100644 -index 0000000..5c505d1 -Binary files /dev/null and b/pixmaps/intlclock-map-location-current.png differ -diff --git a/pixmaps/intlclock-map-location-current.svg b/pixmaps/intlclock-map-location-current.svg -new file mode 100644 -index 0000000..93b5188 ---- /dev/null -+++ b/pixmaps/intlclock-map-location-current.svg -@@ -0,0 +1,76 @@ -+<?xml version="1.0" encoding="UTF-8" standalone="no"?> -+<!-- Created with Inkscape (http://www.inkscape.org/) --> -+<svg -+ xmlns:dc="http://purl.org/dc/elements/1.1/" -+ xmlns:cc="http://web.resource.org/cc/" -+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -+ xmlns:svg="http://www.w3.org/2000/svg" -+ xmlns="http://www.w3.org/2000/svg" -+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" -+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" -+ width="10" -+ height="10" -+ id="svg2" -+ sodipodi:version="0.32" -+ inkscape:version="0.45.1" -+ sodipodi:docbase="/home/mclasen/Desktop" -+ sodipodi:docname="star.svg" -+ inkscape:output_extension="org.inkscape.output.svg.inkscape" -+ version="1.0"> -+ <defs -+ id="defs4" /> -+ <sodipodi:namedview -+ id="base" -+ pagecolor="#ffffff" -+ bordercolor="#666666" -+ borderopacity="1.0" -+ gridtolerance="10000" -+ guidetolerance="10" -+ objecttolerance="10" -+ inkscape:pageopacity="0.0" -+ inkscape:pageshadow="2" -+ inkscape:zoom="1" -+ inkscape:cx="88.125" -+ inkscape:cy="-22.797357" -+ inkscape:document-units="px" -+ inkscape:current-layer="layer1" -+ inkscape:window-width="1003" -+ inkscape:window-height="824" -+ inkscape:window-x="93" -+ inkscape:window-y="30" -+ width="10px" -+ height="10px" /> -+ <metadata -+ id="metadata7"> -+ <rdf:RDF> -+ <cc:Work -+ rdf:about=""> -+ <dc:format>image/svg+xml</dc:format> -+ <dc:type -+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> -+ </cc:Work> -+ </rdf:RDF> -+ </metadata> -+ <g -+ inkscape:label="Layer 1" -+ inkscape:groupmode="layer" -+ id="layer1" -+ transform="translate(-164.31866,-172.88433)"> -+ <path -+ sodipodi:type="star" -+ style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:10.30000114;stroke-miterlimit:3.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" -+ id="path2160" -+ sodipodi:sides="5" -+ sodipodi:cx="311.42856" -+ sodipodi:cy="320.93362" -+ sodipodi:r1="121.8637" -+ sodipodi:r2="42.747437" -+ sodipodi:arg1="1.0073988" -+ sodipodi:arg2="1.6371268" -+ inkscape:flatsided="false" -+ inkscape:rounded="0" -+ inkscape:randomized="0" -+ d="M 376.51129,423.96274 L 308.59518,363.58706 L 233.55372,414.66873 L 269.98717,331.41956 L 198.21652,275.83599 L 288.64975,284.76085 L 319.33452,199.32664 L 338.79187,288.09169 L 429.52674,290.87401 L 351.11882,336.80896 L 376.51129,423.96274 z " -+ transform="matrix(3.8213745e-2,-2.1588882e-2,2.2396111e-2,3.6200569e-2,150.72076,172.68179)" /> -+ </g> -+</svg> -diff --git a/pixmaps/intlclock-map-location-hilight.png b/pixmaps/intlclock-map-location-hilight.png -new file mode 100644 -index 0000000..d7de5b7 -Binary files /dev/null and b/pixmaps/intlclock-map-location-hilight.png differ -diff --git a/pixmaps/intlclock-map-location-hilight.svg b/pixmaps/intlclock-map-location-hilight.svg -new file mode 100644 -index 0000000..4a245e0 ---- /dev/null -+++ b/pixmaps/intlclock-map-location-hilight.svg -@@ -0,0 +1,90 @@ -+<?xml version="1.0" encoding="UTF-8" standalone="no"?> -+<!-- Created with Inkscape (http://www.inkscape.org/) --> -+<svg -+ xmlns:dc="http://purl.org/dc/elements/1.1/" -+ xmlns:cc="http://web.resource.org/cc/" -+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -+ xmlns:svg="http://www.w3.org/2000/svg" -+ xmlns="http://www.w3.org/2000/svg" -+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" -+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" -+ width="7" -+ height="7" -+ id="svg6063" -+ sodipodi:version="0.32" -+ inkscape:version="0.45.1" -+ version="1.0" -+ sodipodi:docbase="/home/mclasen/Desktop/intlclock/pixmaps" -+ sodipodi:docname="intlclock-map-location-hilight.svg" -+ inkscape:output_extension="org.inkscape.output.svg.inkscape" -+ inkscape:export-filename="/home/garrett/Desktop/dot.png" -+ inkscape:export-xdpi="90" -+ inkscape:export-ydpi="90"> -+ <defs -+ id="defs6065"> -+ <linearGradient -+ id="linearGradient7251"> -+ <stop -+ style="stop-color:#e1d9dc;stop-opacity:1;" -+ offset="0" -+ id="stop7253" /> -+ <stop -+ id="stop3143" -+ offset="0.5" -+ style="stop-color:#e3bfca;stop-opacity:1;" /> -+ <stop -+ style="stop-color:#3d0e1a;stop-opacity:1;" -+ offset="1" -+ id="stop7255" /> -+ </linearGradient> -+ </defs> -+ <sodipodi:namedview -+ id="base" -+ pagecolor="#ffffff" -+ bordercolor="#666666" -+ borderopacity="1.0" -+ gridtolerance="10000" -+ guidetolerance="10" -+ objecttolerance="10" -+ inkscape:pageopacity="0.0" -+ inkscape:pageshadow="2" -+ inkscape:zoom="22.627417" -+ inkscape:cx="2.5000319" -+ inkscape:cy="2.5000319" -+ inkscape:document-units="px" -+ inkscape:current-layer="layer1" -+ inkscape:window-width="872" -+ inkscape:window-height="750" -+ inkscape:window-x="0" -+ inkscape:window-y="30" /> -+ <metadata -+ id="metadata6068"> -+ <rdf:RDF> -+ <cc:Work -+ rdf:about=""> -+ <dc:format>image/svg+xml</dc:format> -+ <dc:type -+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> -+ </cc:Work> -+ </rdf:RDF> -+ </metadata> -+ <g -+ inkscape:label="Layer 1" -+ inkscape:groupmode="layer" -+ id="layer1" -+ transform="translate(-474.64282,-409.86216)"> -+ <path -+ sodipodi:type="arc" -+ style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:13.16123206;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" -+ id="path7259" -+ sodipodi:cx="-418.5" -+ sodipodi:cy="-489.5" -+ sodipodi:rx="39.5" -+ sodipodi:ry="39.5" -+ d="M -379 -489.5 A 39.5 39.5 0 1 1 -458,-489.5 A 39.5 39.5 0 1 1 -379 -489.5 z" -+ transform="matrix(5.4243529e-2,8.5329805e-4,-8.5329805e-4,5.4243529e-2,499.42608,439.2715)" -+ inkscape:export-filename="/home/garrett/Desktop/map-new.png" -+ inkscape:export-xdpi="90" -+ inkscape:export-ydpi="90" /> -+ </g> -+</svg> -diff --git a/pixmaps/intlclock-map-location-marker.png b/pixmaps/intlclock-map-location-marker.png -new file mode 100644 -index 0000000..48d2184 -Binary files /dev/null and b/pixmaps/intlclock-map-location-marker.png differ -diff --git a/po/Makefile.in.in b/po/Makefile.in.in -deleted file mode 100755 -index d2d4e4c..e4713cf ---- a/po/Makefile.in.in -+++ /dev/null -@@ -1,221 +0,0 @@ --# Makefile for program source directory in GNU NLS utilities package. --# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> --# --# This file file be copied and used freely without restrictions. It can --# be used in projects which are not available under the GNU Public License --# but which still want to provide support for the GNU gettext functionality. --# Please note that the actual code is *not* freely available. --# --# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE --# instead of PACKAGE and to look for po2tbl in ./ not in intl/ --# --# - Modified by jacob berkman <jacob@ximian.com> to install --# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize --# --# - Modified by Rodney Dawes <dobey@novell.com> for use with intltool --# --# We have the following line for use by intltoolize: --# INTLTOOL_MAKEFILE -- --GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ --PACKAGE = @PACKAGE@ --VERSION = @VERSION@ -- --SHELL = /bin/sh -- --srcdir = @srcdir@ --top_srcdir = @top_srcdir@ --top_builddir = .. --VPATH = @srcdir@ -- --prefix = @prefix@ --exec_prefix = @exec_prefix@ --datadir = @datadir@ --datarootdir = @datarootdir@ --libdir = @libdir@ --DATADIRNAME = @DATADIRNAME@ --itlocaledir = $(prefix)/$(DATADIRNAME)/locale --subdir = po --install_sh = @install_sh@ --# Automake >= 1.8 provides @mkdir_p@. --# Until it can be supposed, use the safe fallback: --mkdir_p = $(install_sh) -d -- --INSTALL = @INSTALL@ --INSTALL_DATA = @INSTALL_DATA@ -- --GMSGFMT = @GMSGFMT@ --MSGFMT = @MSGFMT@ --XGETTEXT = @XGETTEXT@ --INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ --INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ --MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist --GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot -- --ALL_LINGUAS = @ALL_LINGUAS@ -- --PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi) -- --POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done) -- --DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES) --EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS -- --POTFILES = \ --#This Gets Replace for some reason -- --CATALOGS=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) -- --.SUFFIXES: --.SUFFIXES: .po .pox .gmo .mo .msg .cat -- --.po.pox: -- $(MAKE) $(GETTEXT_PACKAGE).pot -- $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox -- --.po.mo: -- $(MSGFMT) -o $@ $< -- --.po.gmo: -- file=`echo $* | sed 's,.*/,,'`.gmo \ -- && rm -f $$file && $(GMSGFMT) -o $$file $< -- --.po.cat: -- sed -f ../intl/po2msg.sed < $< > $*.msg \ -- && rm -f $@ && gencat $@ $*.msg -- -- --all: all-@USE_NLS@ -- --all-yes: $(CATALOGS) --all-no: -- --$(GETTEXT_PACKAGE).pot: $(POTFILES) -- $(GENPOT) -- --install: install-data --install-data: install-data-@USE_NLS@ --install-data-no: all --install-data-yes: all -- $(mkdir_p) $(DESTDIR)$(itlocaledir) -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ -- $(mkdir_p) $$dir; \ -- if test -r $$lang.gmo; then \ -- $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -- echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ -- else \ -- $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -- echo "installing $(srcdir)/$$lang.gmo as" \ -- "$$dir/$(GETTEXT_PACKAGE).mo"; \ -- fi; \ -- if test -r $$lang.gmo.m; then \ -- $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ -- echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ -- else \ -- if test -r $(srcdir)/$$lang.gmo.m ; then \ -- $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ -- $$dir/$(GETTEXT_PACKAGE).mo.m; \ -- echo "installing $(srcdir)/$$lang.gmo.m as" \ -- "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ -- else \ -- true; \ -- fi; \ -- fi; \ -- done -- --# Empty stubs to satisfy archaic automake needs --dvi info tags TAGS ID: -- --# Define this as empty until I found a useful application. --installcheck: -- --uninstall: -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ -- rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ -- done -- --check: all $(GETTEXT_PACKAGE).pot -- --mostlyclean: -- rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp -- rm -f .intltool-merge-cache -- --clean: mostlyclean -- --distclean: clean -- rm -f Makefile Makefile.in POTFILES stamp-it -- rm -f *.mo *.msg *.cat *.cat.m *.gmo -- --maintainer-clean: distclean -- @echo "This command is intended for maintainers to use;" -- @echo "it deletes files that may require special tools to rebuild." -- rm -f Makefile.in.in -- --distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) --dist distdir: $(DISTFILES) -- dists="$(DISTFILES)"; \ -- extra_dists="$(EXTRA_DISTFILES)"; \ -- for file in $$extra_dists; do \ -- test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ -- done; \ -- for file in $$dists; do \ -- test -f $$file || file="$(srcdir)/$$file"; \ -- ln $$file $(distdir) 2> /dev/null \ -- || cp -p $$file $(distdir); \ -- done -- --update-po: Makefile -- $(MAKE) $(GETTEXT_PACKAGE).pot -- tmpdir=`pwd`; \ -- if test -n "$(PO_LINGUAS)"; then \ -- linguas="$(PO_LINGUAS)"; \ -- else \ -- linguas="$(ALL_LINGUAS)"; \ -- fi; \ -- for lang in $$linguas; do \ -- echo "$$lang:"; \ -- result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ -- if $$result; then \ -- if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ -- rm -f $$tmpdir/$$lang.new.po; \ -- else \ -- if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ -- :; \ -- else \ -- echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ -- rm -f $$tmpdir/$$lang.new.po; \ -- exit 1; \ -- fi; \ -- fi; \ -- else \ -- echo "msgmerge for $$lang.gmo failed!"; \ -- rm -f $$tmpdir/$$lang.new.po; \ -- fi; \ -- done -- --Makefile POTFILES: stamp-it -- @if test ! -f $@; then \ -- rm -f stamp-it; \ -- $(MAKE) stamp-it; \ -- fi -- --stamp-it: Makefile.in.in ../config.status POTFILES.in -- cd .. \ -- && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ -- $(SHELL) ./config.status -- --# Tell versions [3.59,3.63) of GNU make not to export all variables. --# Otherwise a system limit (for SysV at least) may be exceeded. --.NOEXPORT: -diff --git a/po/Makefile.in.in b/po/Makefile.in.in -new file mode 120000 -index d2d4e4c..e4713cf ---- /dev/null -+++ b/po/Makefile.in.in -@@ -0,0 +1 @@ -+/usr/share/intltool/Makefile.in.in -\ No newline at end of file -diff --git a/src/Makefile.am b/src/Makefile.am -index 80d1419..d681d39 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -3,7 +3,7 @@ - INCLUDES = \ - $(INTLCLOCK_CFLAGS) \ - -DGNOMELOCALEDIR=\"$(prefix)/$(DATADIRNAME)/locale\" \ -- -DEVOLUTION_TEXTDOMAIN=\"evolution-2.6\" \ -+ -DEVOLUTION_TEXTDOMAIN=\"evolution-2.12\" \ - -DINTLCLOCK_TEXTDOMAIN=\"gnome-panel-2.0\" \ - -DINTLCLOCK_ICONDIR=\"$(pkgdatadir)\" \ - -DINTLCLOCK_DATADIR=\"$(pkgdatadir)\" \ -@@ -60,7 +60,11 @@ COMMON_SOURCES = \ - intlclock-zoneinfo.c \ - intlclock-zoneinfo.h \ - intlclock-zonetable.c \ -- intlclock-zonetable.h -+ intlclock-zonetable.h \ -+ set-timezone.c \ -+ set-timezone.h \ -+ gweather-xml.c \ -+ gweather-xml.h - - - intlclock_applet_SOURCES = \ -diff --git a/src/gweather-xml.c b/src/gweather-xml.c -new file mode 100644 -index 0000000..94b275d ---- /dev/null -+++ b/src/gweather-xml.c -@@ -0,0 +1,490 @@ -+/* gweather-xml.c - Locations.xml parsing code -+ * -+ * Copyright (C) 2005 Ryan Lortie, 2004 Gareth Owen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+ -+/* There is very little error checking in the parsing code below, it relies -+ * heavily on the locations file being in the correct format. If you have -+ * <name> elements within a parent element, they must come first and be -+ * grouped together. -+ * The format is as follows: -+ * -+ * <gweather format="1.0"> -+ * <region> -+ * <name>Name of the region</name> -+ * <name xml:lang="xx">Translated Name</name> -+ * <name xml:lang="zz">Another Translated Name</name> -+ * <country> -+ * <name>Name of the country</name> -+ * <location> -+ * <name>Name of the location</name> -+ * <code>IWIN code</code> -+ * <zone>Forecast code (North America, Australia, UK only)</zone> -+ * <radar>Weather.com radar map code (North America only)</radar> -+ * <coordinates>Latitude and longitude as DD-MM[-SS][H] pair</coordinates> -+ * </location> -+ * <state> -+ * <location> -+ * .... -+ * </location> -+ * <city> -+ * <name>Name of city with multiple locations</city> -+ * <zone>Forecast code</zone> -+ * <radar>Radar Map code</radar> -+ * <location> -+ * ... -+ * </location> -+ * </city> -+ * </state> -+ * </country> -+ * </region> -+ * <gweather> -+ * -+ * The thing to note is that each country can either contain different locations -+ * or be split into "states" which in turn contain a list of locations. -+ * -+ */ -+ -+#include <string.h> -+#include <math.h> -+#include <locale.h> -+#include <gtk/gtk.h> -+#include <libxml/xmlreader.h> -+ -+#include "gweather-xml.h" -+ -+static gint -+gweather_xml_location_sort_func( GtkTreeModel *model, GtkTreeIter *a, -+ GtkTreeIter *b, gpointer user_data ) -+{ -+ gint res; -+ gchar *name_a, *name_b; -+ gchar *fold_a, *fold_b; -+ -+ gtk_tree_model_get (model, a, GWEATHER_XML_COL_LOC, &name_a, -1); -+ gtk_tree_model_get (model, b, GWEATHER_XML_COL_LOC, &name_b, -1); -+ -+ fold_a = g_utf8_casefold(name_a, -1); -+ fold_b = g_utf8_casefold(name_b, -1); -+ -+ res = g_utf8_collate(fold_a, fold_b); -+ -+ g_free(name_a); -+ g_free(name_b); -+ g_free(fold_a); -+ g_free(fold_b); -+ -+ return res; -+} -+ -+static char* -+gweather_xml_get_value( xmlTextReaderPtr xml ) -+{ -+ char* value; -+ -+ /* check for null node */ -+ if ( xmlTextReaderIsEmptyElement( xml ) ) -+ return NULL; -+ -+ /* the next "node" is the text node containing the value we want to get */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ return NULL; -+ -+ value = (char *) xmlTextReaderValue( xml ); -+ -+ /* move on to the end of this node */ -+ while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_END_ELEMENT ) -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( value ); -+ return NULL; -+ } -+ -+ /* consume the end element too */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( value ); -+ return NULL; -+ } -+ -+ return value; -+} -+ -+static char * -+gweather_xml_parse_name( xmlTextReaderPtr xml ) -+{ -+ const char * const *locales; -+ const char *this_language; -+ int best_match = INT_MAX; -+ char *lang, *tagname; -+ gboolean keep_going; -+ char *name = NULL; -+ int i; -+ -+ locales = g_get_language_names(); -+ -+ do -+ { -+ /* First let's get the language */ -+ lang = (char *) xmlTextReaderXmlLang( xml ); -+ -+ if( lang == NULL ) -+ this_language = "C"; -+ else -+ this_language = lang; -+ -+ /* the next "node" is text node containing the actual name */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( lang ); -+ return NULL; -+ } -+ -+ for( i = 0; locales[i] && i < best_match; i++ ) -+ if( !strcmp( locales[i], this_language ) ) -+ { -+ /* if we've already encounted a less accurate -+ translation, then free it */ -+ xmlFree( name ); -+ -+ name = (char *) xmlTextReaderValue( xml ); -+ best_match = i; -+ -+ break; -+ } -+ -+ xmlFree( lang ); -+ -+ while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_ELEMENT ) -+ if( xmlTextReaderRead( xml ) != 1 ) -+ { -+ xmlFree( name ); -+ return NULL; -+ } -+ -+ /* if the next tag is another <name> then keep going */ -+ tagname = (char *) xmlTextReaderName( xml ); -+ keep_going = !strcmp( tagname, "name" ); -+ xmlFree( tagname ); -+ -+ } while( keep_going ); -+ -+ return name; -+} -+ -+static int -+gweather_xml_parse_node (GtkTreeView *view, GtkTreeIter *parent, -+ xmlTextReaderPtr xml, WeatherLocation *current, -+ const char *dflt_radar, const char *dflt_zone, -+ const char *cityname) -+{ -+ GtkTreeStore *store = GTK_TREE_STORE( gtk_tree_view_get_model( view ) ); -+ char *name, *code, *zone, *radar, *coordinates; -+ char **city, *nocity = NULL; -+ GtkTreeIter iter, *self; -+ gboolean is_location; -+ char *tagname; -+ int ret = -1; -+ int tagtype; -+ -+ if( (tagname = (char *) xmlTextReaderName( xml )) == NULL ) -+ return -1; -+ -+ if( !strcmp( tagname, "city" ) ) -+ city = &name; -+ else -+ city = &nocity; -+ -+ is_location = !strcmp( tagname, "location" ); -+ -+ /* if we're processing the top-level, then don't create a new iter */ -+ if( !strcmp( tagname, "gweather" ) ) -+ self = NULL; -+ else -+ { -+ self = &iter; -+ /* insert this node into the tree */ -+ gtk_tree_store_append( store, self, parent ); -+ } -+ -+ xmlFree( tagname ); -+ -+ coordinates = NULL; -+ radar = NULL; -+ zone = NULL; -+ code = NULL; -+ name = NULL; -+ -+ /* absorb the start tag */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ -+ /* start parsing the actual contents of the node */ -+ while( (tagtype = xmlTextReaderNodeType( xml )) != -+ XML_READER_TYPE_END_ELEMENT ) -+ { -+ -+ /* skip non-element types */ -+ if( tagtype != XML_READER_TYPE_ELEMENT ) -+ { -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ -+ continue; -+ } -+ -+ tagname = (char *) xmlTextReaderName( xml ); -+ -+ if( !strcmp( tagname, "region" ) || !strcmp( tagname, "country" ) || -+ !strcmp( tagname, "state" ) || !strcmp( tagname, "city" ) || -+ !strcmp( tagname, "location" ) ) -+ { -+ /* recursively handle sub-sections */ -+ if( gweather_xml_parse_node( view, self, xml, current, -+ radar, zone, *city ) ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "name" ) ) -+ { -+ xmlFree( name ); -+ if( (name = gweather_xml_parse_name( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "code" ) ) -+ { -+ xmlFree( code ); -+ if( (code = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "zone" ) ) -+ { -+ xmlFree( zone ); -+ if( (zone = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "radar" ) ) -+ { -+ xmlFree( radar ); -+ if( (radar = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else if ( !strcmp( tagname, "coordinates" ) ) -+ { -+ xmlFree( coordinates ); -+ if( (coordinates = gweather_xml_get_value( xml )) == NULL ) -+ goto error_out; -+ } -+ else /* some strange tag */ -+ { -+ /* skip past it */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ } -+ -+ xmlFree( tagname ); -+ } -+ -+ if( self ) -+ gtk_tree_store_set( store, self, GWEATHER_XML_COL_LOC, name, -1 ); -+ -+ /* absorb the end tag. in the case of processing a <gweather> then 'self' -+ is NULL. In this case, we let this fail since we might be at EOF */ -+ if( xmlTextReaderRead( xml ) != 1 && self ) -+ goto error_out; -+ -+ /* if this is an actual location, setup the WeatherLocation for it */ -+ if( is_location ) -+ { -+ WeatherLocation *new_loc; -+ -+ if( cityname == NULL ) -+ cityname = name; -+ -+ if( radar != NULL ) -+ dflt_radar = radar; -+ -+ if( zone != NULL ) -+ dflt_zone = zone; -+ -+ new_loc = weather_location_new( cityname, code, dflt_zone, -+ dflt_radar, coordinates ); -+ -+ gtk_tree_store_set( store, &iter, GWEATHER_XML_COL_POINTER, new_loc, -1 ); -+ -+ /* If this location is actually the currently selected one, select it */ -+ if( current && weather_location_equal( new_loc, current ) ) -+ { -+ GtkTreePath *path; -+ -+ path = gtk_tree_model_get_path( GTK_TREE_MODEL (store), &iter ); -+ gtk_tree_view_expand_to_path( view, path ); -+ gtk_tree_view_set_cursor( view, path, NULL, FALSE ); -+ gtk_tree_view_scroll_to_cell( view, path, NULL, TRUE, 0.5, 0.5 ); -+ gtk_tree_path_free( path ); -+ } -+ } -+ -+ ret = 0; -+ -+error_out: -+ xmlFree( name ); -+ xmlFree( code ); -+ xmlFree( zone ); -+ xmlFree( radar ); -+ xmlFree( coordinates ); -+ -+ return ret; -+} -+ -+/***************************************************************************** -+ * Func: gweather_xml_load_locations() -+ * Desc: Main entry point for loading the locations from the XML file -+ * Parm: -+ * *tree: tree to view locations -+ * *current: currently selected location -+ */ -+int -+gweather_xml_load_locations( GtkTreeView *tree, WeatherLocation *current ) -+{ -+ char *tagname, *format; -+ GtkTreeSortable *sortable; -+ xmlTextReaderPtr xml; -+ int keep_going; -+ int ret = -1; -+ -+ /* Open the xml file containing the different locations */ -+#ifdef GWEATHER_XML_LOCATION -+ xml = xmlNewTextReaderFilename (GWEATHER_XML_LOCATION "Locations.xml"); -+#else -+ xml = xmlNewTextReaderFilename ("/usr/share/gnome-applets/gweather/Locations.xml"); -+#endif -+ if( xml == NULL ) -+ goto error_out; -+ -+ /* fast forward to the first element */ -+ do -+ { -+ /* if we encounter a problem here, exit right away */ -+ if( xmlTextReaderRead( xml ) != 1 ) -+ goto error_out; -+ } while( xmlTextReaderNodeType( xml ) != XML_READER_TYPE_ELEMENT ); -+ -+ /* check the name and format */ -+ tagname = (char *) xmlTextReaderName( xml ); -+ keep_going = tagname && !strcmp( tagname, "gweather" ); -+ xmlFree( tagname ); -+ -+ if( !keep_going ) -+ goto error_out; -+ -+ format = (char *) xmlTextReaderGetAttribute( xml, (xmlChar *) "format" ); -+ keep_going = format && !strcmp( format, "1.0" ); -+ xmlFree( format ); -+ -+ if( !keep_going ) -+ goto error_out; -+ -+ ret = gweather_xml_parse_node( tree, NULL, xml, current, NULL, NULL, NULL ); -+ -+ if( ret ) -+ goto error_out; -+ -+ /* Sort the tree */ -+ sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model( tree )); -+ gtk_tree_sortable_set_default_sort_func( sortable, -+ &gweather_xml_location_sort_func, -+ NULL, NULL); -+ gtk_tree_sortable_set_sort_column_id( sortable, -+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, -+ GTK_SORT_ASCENDING ); -+error_out: -+ xmlFreeTextReader( xml ); -+ -+ return ret; -+} -+ -+typedef struct { -+ const gchar *name; -+ gdouble latitude; -+ gdouble longitude; -+ gdouble distance; -+ WeatherLocation *location; -+} SearchData; -+ -+ -+static gdouble -+distance (gdouble lat1, gdouble lon1, -+ gdouble lat2, gdouble lon2) -+{ -+ gdouble radius = 6372.795; -+ -+ return acos (cos (lat1) * cos (lat2) * cos (lon1 - lon2) + sin (lat1) * sin (lat2)) * radius; -+} -+ -+gboolean -+compare_location (GtkTreeModel *model, -+ GtkTreePath *path, -+ GtkTreeIter *iter, -+ gpointer user_data) -+{ -+ SearchData *data = user_data; -+ WeatherLocation *loc; -+ gdouble d; -+ -+ gtk_tree_model_get (model, iter, GWEATHER_XML_COL_POINTER, &loc, -1); -+ -+ if (!loc) -+ return FALSE; -+ -+ d = distance (data->latitude, data->longitude, loc->latitude, loc->longitude); -+ -+ if (d < data->distance) { -+ data->distance = d; -+ data->location = loc; -+ } -+ -+ return FALSE; -+} -+ -+gchar * -+find_weather_code (GtkTreeModel *model, -+ const gchar *name, -+ gdouble lat, -+ gdouble lon) -+{ -+ SearchData data; -+ gchar *code; -+ -+ data.name = name; -+ data.latitude = lat; -+ data.longitude = lon; -+ data.distance = 1e6; -+ data.location = NULL; -+ -+ gtk_tree_model_foreach (GTK_TREE_MODEL (model), compare_location, &data); -+ -+ if (data.distance < 50) -+ code = g_strdup (data.location->code); -+ else -+ code = g_strdup ("-"); -+ -+ g_debug ("distance: %f\nin: %s\nlat, lon: %f, %f\nout: %s\nDMS: %s\ncode: %s\n", -+ data.distance, name, lat, lon, data.location->name, data.location->coordinates, code); -+ -+ return code; -+} -diff --git a/src/gweather-xml.h b/src/gweather-xml.h -new file mode 100644 -index 0000000..d65b651 ---- /dev/null -+++ b/src/gweather-xml.h -@@ -0,0 +1,37 @@ -+/* gweather-xml.h -+ * -+ * Copyright (C) 2004 Gareth Owen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __GWEATHER_XML_H__ -+#define __GWEATHER_XML_H__ -+ -+#include <gtk/gtk.h> -+#include <libgweather/weather.h> -+ -+enum -+{ -+ GWEATHER_XML_COL_LOC = 0, -+ GWEATHER_XML_COL_POINTER, -+ GWEATHER_XML_NUM_COLUMNS -+}; -+ -+int gweather_xml_load_locations( GtkTreeView *tree, WeatherLocation *current ); -+gchar *find_weather_code (GtkTreeModel *model, const gchar *name, gdouble lat, gdouble lon); -+ -+ -+#endif /* __GWEATHER_XML_H__ */ -diff --git a/src/intlclock-events-popup.c b/src/intlclock-events-popup.c -index 4276f81..a54f6e3 100644 ---- a/src/intlclock-events-popup.c -+++ b/src/intlclock-events-popup.c -@@ -1,6 +1,8 @@ - #include <gtk/gtk.h> - #include <string.h> - #include <time.h> -+#include <gconf/gconf-client.h> -+#include <panel-applet-gconf.h> - - #ifdef HAVE_CONFIG_H - #include "config.h" -@@ -11,12 +13,18 @@ - #endif - - #include "intlclock-events-popup.h" -+#include "intlclock-ui.h" -+ -+#define KEY_EXPAND_LOCATIONS "expand_locations" -+#define KEY_EXPAND_TASKS "expand_tasks" -+#define KEY_EXPAND_APPOINTMENTS "expand_appointments" - - G_DEFINE_TYPE (IntlClockEventsPopup, intlclock_events_popup, GTK_TYPE_WINDOW) - - typedef struct { - IntlClock *clock; - PanelApplet *panel_applet; -+ IntlClockUI *ui; - - GtkWidget *calendar; - GtkWidget *main_section; -@@ -126,7 +134,7 @@ intlclock_events_popup_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc - } - - IntlClockEventsPopup * --intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet) -+intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet, IntlClockUI *ui) - { - IntlClockEventsPopup *this; - IntlClockEventsPopupPrivate *priv; -@@ -138,6 +146,7 @@ intlclock_events_popup_new (IntlClock *clock, PanelApplet *panel_applet) - - priv->clock = g_object_ref (clock); - priv->panel_applet = panel_applet; -+ priv->ui = ui; - - gtk_widget_set_name (GTK_WIDGET (this), "intlclock-events-window"); - gtk_container_set_border_width (GTK_CONTAINER (this), 0); -@@ -275,6 +284,21 @@ intlclock_events_popup_tick (IntlClock *clock, IntlClockEventsPopup *this) - gmtime (&priv->current_time); - } - -+static GtkWidget * create_hig_frame (IntlClockEventsPopup *this, -+ const char *title, -+ const char *button_label, -+ const char *key, -+ GCallback callback); -+ -+ -+static void -+edit_locations (IntlClockEventsPopup *this) -+{ -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ -+ intlclock_ui_edit_locations (priv->ui); -+} -+ - static void - intlclock_events_popup_fill (IntlClockEventsPopup *this) - { -@@ -296,7 +320,10 @@ intlclock_events_popup_fill (IntlClockEventsPopup *this) - - orient = panel_applet_get_orient (priv->panel_applet); - -- priv->clock_container = gtk_vbox_new (FALSE, 0); -+ priv->clock_container = create_hig_frame (this, -+ _("Locations"), _("Edit"), -+ KEY_EXPAND_LOCATIONS, -+ G_CALLBACK (edit_locations)); - - switch (orient) { - case PANEL_APPLET_ORIENT_UP: -@@ -642,28 +669,167 @@ modify_task_text_attributes (GtkTreeModel *model, - g_value_take_boxed (value, attr_list); - } - -+static void -+expand_collapse_child (GtkWidget *child, -+ gpointer data) -+{ -+ gboolean expanded; -+ -+ if (data == child || gtk_widget_is_ancestor (data, child)) -+ return; -+ -+ expanded = gtk_expander_get_expanded (GTK_EXPANDER (data)); -+ g_object_set (child, "visible", expanded, NULL); -+} -+ -+static void -+expand_collapse (GtkWidget *expander, -+ GParamSpec *pspec, -+ gpointer data) -+{ -+ GtkWidget *box = data; -+ -+ gtk_container_foreach (GTK_CONTAINER (box), -+ (GtkCallback)expand_collapse_child, -+ expander); -+} -+ -+static void -+expander_activated (GtkExpander *expander, -+ gpointer data) -+{ -+ IntlClockEventsPopup *this = data; -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ const gchar *key; -+ gboolean expanded; -+ -+ key = (const gchar*)g_object_get_data (G_OBJECT (expander), "gconf-key"); -+ expanded = gtk_expander_get_expanded (expander); -+ -+ panel_applet_gconf_set_bool (priv->panel_applet, key, expanded, NULL); -+} -+ -+static void -+expanded_changed (GConfClient *client, -+ guint cnxn_id, -+ GConfEntry *entry, -+ GtkExpander *expander) -+{ -+ if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -+ return; -+ -+ gtk_expander_set_expanded (expander, -+ gconf_value_get_bool (entry->value)); -+} -+ -+static void -+remove_listener (gpointer data) -+{ -+ GConfClient *client; -+ -+ client = gconf_client_get_default (); -+ gconf_client_notify_remove (client, GPOINTER_TO_UINT (data)); -+ g_object_unref (client); -+} -+ -+static void -+connect_expander_with_gconf (IntlClockEventsPopup *this, -+ GtkWidget *expander, -+ const gchar *key) -+{ -+ IntlClockEventsPopupPrivate *priv = PRIVATE (this); -+ GConfClient *client; -+ gboolean expanded; -+ guint listener; -+ gchar *full_key; -+ -+ g_object_set_data (G_OBJECT (expander), "gconf-key", (gpointer)key); -+ -+ expanded = panel_applet_gconf_get_bool (priv->panel_applet, key, NULL); -+ gtk_expander_set_expanded (GTK_EXPANDER (expander), expanded); -+ -+ g_signal_connect_after (expander, "activate", -+ G_CALLBACK (expander_activated), -+ this); -+ -+ client = gconf_client_get_default (); -+ full_key = panel_applet_gconf_get_full_key (priv->panel_applet, key); -+ listener = gconf_client_notify_add (client, full_key, -+ (GConfClientNotifyFunc)expanded_changed, -+ expander, NULL, NULL); -+ g_object_set_data_full (G_OBJECT (expander), "listener-id", -+ GUINT_TO_POINTER (listener), remove_listener); -+ g_object_unref (client); -+} -+ -+static void add_child (GtkContainer *container, -+ GtkWidget *child, -+ GtkExpander *expander) -+{ -+ gboolean expanded; -+ -+ expanded = gtk_expander_get_expanded (expander); -+ g_object_set (child, "visible", expanded, NULL); -+} -+ - static GtkWidget * --create_hig_frame (const char *title) -+create_hig_frame (IntlClockEventsPopup *this, -+ const char *title, -+ const char *button_label, -+ const char *key, -+ GCallback callback) - { - GtkWidget *vbox; - GtkWidget *alignment; - GtkWidget *label; -+ GtkWidget *hbox; -+ GtkWidget *button; - char *bold_title; -+ char *text; -+ GtkWidget *expander; - - vbox = gtk_vbox_new (FALSE, 6); - - bold_title = g_strdup_printf ("<b>%s</b>", title); -- -- alignment = gtk_alignment_new (0, 0.5, 0, 0); -- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0); -- gtk_widget_show (alignment); -- -- label = gtk_label_new (bold_title); -- gtk_label_set_use_markup (GTK_LABEL (label), TRUE); -- gtk_container_add (GTK_CONTAINER (alignment), label); -- gtk_widget_show (label); -- -+ expander = gtk_expander_new (""); -+ gtk_expander_set_label (GTK_EXPANDER (expander), bold_title); - g_free (bold_title); -+ gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE); -+ -+ hbox = gtk_hbox_new (FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (hbox), expander, FALSE, FALSE, 0); -+ gtk_widget_show_all (vbox); -+ -+ g_signal_connect (expander, "notify::expanded", -+ G_CALLBACK (expand_collapse), hbox); -+ g_signal_connect (expander, "notify::expanded", -+ G_CALLBACK (expand_collapse), vbox); -+ -+ /* FIXME: this doesn't really work, since "add" does not -+ * get emitted for e.g. gtk_box_pack_start -+ */ -+ g_signal_connect (vbox, "add", G_CALLBACK (add_child), expander); -+ g_signal_connect (hbox, "add", G_CALLBACK (add_child), expander); -+ -+ if (button_label) { -+ button = gtk_button_new (); -+ text = g_markup_printf_escaped ("<small>%s</small>", button_label); -+ label = gtk_label_new (text); -+ g_free (text); -+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE); -+ gtk_container_add (GTK_CONTAINER (button), label); -+ -+ alignment = gtk_alignment_new (1, 0, 0, 0); -+ gtk_container_add (GTK_CONTAINER (alignment), button); -+ gtk_widget_show_all (alignment); -+ -+ gtk_container_add (GTK_CONTAINER (hbox), alignment); -+ -+ g_signal_connect_swapped (button, "clicked", callback, this); -+ } -+ -+ connect_expander_with_gconf (this, expander, key); - - return vbox; - } -@@ -791,6 +957,12 @@ compare_tasks (GtkTreeModel *model, - } - } - -+static void -+edit_tasks (IntlClockEventsPopup *this) -+{ -+ clock_launch_evolution (this, "--component=tasks"); -+} -+ - static GtkWidget * - create_task_list (IntlClockEventsPopup *this, - GtkWidget **tree_view, -@@ -804,7 +976,9 @@ create_task_list (IntlClockEventsPopup *this, - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - -- vbox = create_hig_frame (_("Tasks")); -+ vbox = create_hig_frame (this, _("Tasks"), _("Edit"), -+ KEY_EXPAND_TASKS, -+ G_CALLBACK (edit_tasks)); - - *scrolled_window = scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), -@@ -812,8 +986,8 @@ create_task_list (IntlClockEventsPopup *this, - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); -- gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0); - gtk_widget_show (scrolled); -+ gtk_container_add (GTK_CONTAINER (vbox), scrolled); - - if (!priv->tasks_model) { - GType column_types [N_TASK_COLUMNS] = { -@@ -984,6 +1158,12 @@ handle_appointments_changed (IntlClockEventsPopup *this) - update_frame_visibility (priv->appointment_list, GTK_TREE_MODEL (priv->appointments_model)); - } - -+static void -+edit_appointments (IntlClockEventsPopup *this) -+{ -+ clock_launch_evolution (this, "--component=calendar"); -+} -+ - static GtkWidget * - create_appointment_list (IntlClockEventsPopup *this, - GtkWidget **tree_view, -@@ -997,7 +1177,9 @@ create_appointment_list (IntlClockEventsPopup *this, - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - -- vbox = create_hig_frame ( _("Appointments")); -+ vbox = create_hig_frame (this, _("Appointments"), _("Edit"), -+ KEY_EXPAND_APPOINTMENTS, -+ G_CALLBACK (edit_appointments)); - - *scrolled_window = scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), -@@ -1005,8 +1187,8 @@ create_appointment_list (IntlClockEventsPopup *this, - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); -- gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0); - gtk_widget_show (scrolled); -+ gtk_container_add (GTK_CONTAINER (vbox), scrolled); - - if (!priv->appointments_model) { - priv->appointments_model = -diff --git a/src/intlclock-events-popup.h b/src/intlclock-events-popup.h -index 84a5183..b88e4c7 100644 ---- a/src/intlclock-events-popup.h -+++ b/src/intlclock-events-popup.h -@@ -2,6 +2,7 @@ - #define __INTLCLOCK_EVENTS_POPUP_H__ - - #include "intlclock.h" -+#include "intlclock-ui.h" - - #include <glib.h> - #include <gtk/gtk.h> -@@ -29,7 +30,8 @@ typedef struct - GType intlclock_events_popup_get_type (void); - - IntlClockEventsPopup *intlclock_events_popup_new (IntlClock *clock, -- PanelApplet *panel_applet); -+ PanelApplet *panel_applet, -+ IntlClockUI *ui); - void intlclock_events_popup_set_date (IntlClockEventsPopup *this, - guint year, guint month, guint mday); - GtkWidget *intlclock_events_popup_get_clock_container (IntlClockEventsPopup *this); -diff --git a/src/intlclock-location-tile.c b/src/intlclock-location-tile.c -index 40d96e3..7f64fee 100644 ---- a/src/intlclock-location-tile.c -+++ b/src/intlclock-location-tile.c -@@ -23,9 +23,18 @@ typedef struct { - - IntlClockFaceSize size; - -+ GtkWidget *box; - GtkWidget *clock_face; - GtkWidget *city_label; - GtkWidget *time_label; -+ -+ GtkWidget *current_button; -+ GtkWidget *current_label; -+ GtkWidget *current_marker; -+ GtkSizeGroup *button_group; -+ -+ GtkWidget *weather_icon; -+ - } IntlClockLocationTilePrivate; - - static void intlclock_location_tile_finalize (GObject *); -@@ -36,6 +45,12 @@ static void intlclock_location_tile_refresh (IntlClockLocationTile *this); - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_LOCATION_TILE_TYPE, IntlClockLocationTilePrivate)) - - static void intlclock_location_tile_fill (IntlClockLocationTile *this); -+static void update_weather_icon (IntlClockLocation *loc, WeatherInfo *info, gpointer data); -+static gboolean weather_tooltip (GtkWidget *widget, -+ gint x, gint y, -+ gboolean keyboard_mode, -+ GtkTooltip *tooltip, -+ gpointer data); - - IntlClockLocationTile * - intlclock_location_tile_new (IntlClock *clock, IntlClockUI *ui, -@@ -56,13 +71,17 @@ intlclock_location_tile_new (IntlClock *clock, IntlClockUI *ui, - priv->location = g_object_ref (loc); - priv->size = size; - -- gtk_alignment_set (GTK_ALIGNMENT (this), 0.0, 0.0, 0.0, 0.0); -- gtk_alignment_set_padding (GTK_ALIGNMENT (this), 3, 3, 3, 3); -- - intlclock_location_tile_fill (this); - -- g_signal_connect (G_OBJECT (priv->clock), "tick", -- G_CALLBACK (intlclock_location_tile_tick), this); -+ update_weather_icon (loc, intlclock_location_get_weather_info (loc), this); -+ gtk_widget_set_has_tooltip (priv->weather_icon, TRUE); -+ -+ g_signal_connect (priv->weather_icon, "query-tooltip", -+ G_CALLBACK (weather_tooltip), this); -+ g_signal_connect (G_OBJECT (loc), "weather-updated", -+ G_CALLBACK (update_weather_icon), this); -+ g_signal_connect (G_OBJECT (priv->clock), "tick", -+ G_CALLBACK (intlclock_location_tile_tick), this); - - return this; - } -@@ -133,13 +152,99 @@ intlclock_location_tile_finalize (GObject *g_obj) - priv->location = NULL; - } - -+ if (priv->button_group) { -+ g_object_unref (priv->button_group); -+ priv->button_group = NULL; -+ } -+ - G_OBJECT_CLASS (intlclock_location_tile_parent_class)->finalize (g_obj); - } - -+static gboolean -+press_on_tile (GtkWidget *widget, -+ GdkEventButton *event, -+ IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ -+ intlclock_blink_location (priv->clock, priv->location); -+ -+ return TRUE; -+} -+ -+static void -+make_current (GtkWidget *widget, IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ GError *error = NULL; -+ GtkWidget *dialog; -+ -+ if (intlclock_location_make_current (priv->location, &error)) { -+ g_signal_emit_by_name (priv->clock, "current-timezone-changed", 0); -+ } -+ else if (error) { -+ dialog = gtk_message_dialog_new (NULL, -+ 0, -+ GTK_MESSAGE_ERROR, -+ GTK_BUTTONS_OK, -+ _("Failed to set the system timezone")); -+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error->message); -+ g_signal_connect (dialog, "response", -+ G_CALLBACK (gtk_widget_destroy), NULL); -+ gtk_window_present (GTK_WINDOW (dialog)); -+ -+ g_error_free (error); -+ } -+} -+ -+static gboolean -+enter_or_leave_tile (GtkWidget *widget, -+ GdkEventCrossing *event, -+ IntlClockLocationTile *tile) -+{ -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ -+ if (event->type == GDK_ENTER_NOTIFY) { -+ gint can_set; -+ -+ can_set = can_set_system_timezone (); -+ if (!intlclock_location_is_current (priv->location) && -+ can_set != 0) { -+ gtk_label_set_markup (GTK_LABEL (priv->current_label), -+ can_set == 1 ? -+ _("<small>Set...</small>") : -+ _("<small>Set</small>")); -+ gtk_widget_show (priv->current_button); -+ } -+ } -+ else { -+ if (event->detail != GDK_NOTIFY_INFERIOR) -+ gtk_widget_hide (priv->current_button); -+ } -+ -+ return TRUE; -+} -+ - static void - intlclock_location_tile_fill (IntlClockLocationTile *this) - { - IntlClockLocationTilePrivate *priv = PRIVATE (this); -+ GtkWidget *align; -+ GtkWidget *strut; -+ GtkWidget *box; -+ -+ priv->box = gtk_event_box_new (); -+ -+ gtk_widget_add_events (priv->box, GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); -+ g_signal_connect (priv->box, "button-press-event", -+ G_CALLBACK (press_on_tile), this); -+ g_signal_connect (priv->box, "enter-notify-event", -+ G_CALLBACK (enter_or_leave_tile), this); -+ g_signal_connect (priv->box, "leave-notify-event", -+ G_CALLBACK (enter_or_leave_tile), this); -+ -+ GtkWidget *alignment = gtk_alignment_new (0, 0, 1, 0); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 0); - - GtkWidget *tile = gtk_hbox_new (FALSE, 6); - GtkWidget *head_section = gtk_vbox_new (FALSE, 0); -@@ -147,21 +252,55 @@ intlclock_location_tile_fill (IntlClockLocationTile *this) - priv->city_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (priv->city_label), 0, 0); - -+ align = gtk_alignment_new (0, 0, 0, 0); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, 3); -+ gtk_container_add (GTK_CONTAINER (align), priv->city_label); -+ gtk_box_pack_start (GTK_BOX (head_section), align, FALSE, FALSE, 0); -+ - priv->time_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (priv->time_label), 0, 0); - -- gtk_box_pack_start (GTK_BOX (head_section), priv->city_label, -- FALSE, FALSE, 0); -- gtk_box_pack_start (GTK_BOX (head_section), priv->time_label, -- FALSE, FALSE, 0); -+ priv->weather_icon = gtk_image_new (); -+ align = gtk_alignment_new (0, 0, 0, 0); -+ gtk_container_add (GTK_CONTAINER (align), priv->weather_icon); -+ -+ box = gtk_hbox_new (FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (head_section), box, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->time_label, FALSE, FALSE, 0); -+ -+ priv->current_button = gtk_button_new (); -+ priv->current_label = gtk_label_new (""); -+ gtk_widget_show (priv->current_label); -+ gtk_widget_set_no_show_all (priv->current_button, TRUE); -+ gtk_container_add (GTK_CONTAINER (priv->current_button), priv->current_label); -+ gtk_widget_set_tooltip_text (priv->current_button, _("Set as current timezone for this computer")); -+ -+ priv->current_marker = gtk_image_new_from_icon_name ("go-home", GTK_ICON_SIZE_BUTTON); -+ gtk_widget_set_no_show_all (priv->current_marker, TRUE); -+ -+ align = gtk_alignment_new (1, 1, 0, 0); -+ strut = gtk_event_box_new (); -+ gtk_box_pack_start (GTK_BOX (box), strut, TRUE, TRUE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->current_button, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (box), priv->current_marker, FALSE, FALSE, 0); -+ priv->button_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); -+ gtk_size_group_set_ignore_hidden (priv->button_group, FALSE); -+ gtk_size_group_add_widget (priv->button_group, strut); -+ gtk_size_group_add_widget (priv->button_group, priv->current_button); -+ -+ g_signal_connect (priv->current_button, "clicked", -+ G_CALLBACK (make_current), this); - - priv->clock_face = intlclock_face_new_with_location ( - priv->size, priv->location, head_section); - - gtk_box_pack_start (GTK_BOX (tile), priv->clock_face, FALSE, FALSE, 0); -- gtk_box_pack_start (GTK_BOX (tile), head_section, FALSE, FALSE, 0); -+ gtk_box_pack_start (GTK_BOX (tile), head_section, TRUE, TRUE, 0); - -- gtk_container_add (GTK_CONTAINER (this), tile); -+ gtk_container_add (GTK_CONTAINER (alignment), tile); -+ gtk_container_add (GTK_CONTAINER (priv->box), alignment); -+ gtk_container_add (GTK_CONTAINER (this), priv->box); - - intlclock_location_tile_refresh (this); - } -@@ -231,6 +370,21 @@ intlclock_location_tile_refresh (IntlClockLocationTile *this) - char buf[256]; - struct tm now; - -+ if (intlclock_location_is_current (priv->location)) { -+ if (!GTK_WIDGET_VISIBLE (priv->current_marker)) { -+ GdkPixbuf *pixbuf; -+ -+ pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (priv->weather_icon)); -+ intlclock_ui_update_weather_icon (priv->ui, pixbuf); -+ } -+ -+ gtk_widget_hide (priv->current_button); -+ gtk_widget_show (priv->current_marker); -+ } -+ else { -+ gtk_widget_hide (priv->current_marker); -+ } -+ - if (intlclock_needs_face_refresh (this)) { - intlclock_face_refresh (INTLCLOCK_FACE (priv->clock_face)); - } -@@ -271,3 +425,87 @@ intlclock_location_tile_tick (IntlClock *clock, - - intlclock_location_tile_refresh (this); - } -+ -+static gboolean -+weather_tooltip (GtkWidget *widget, -+ gint x, -+ gint y, -+ gboolean keyboard_mode, -+ GtkTooltip *tooltip, -+ gpointer data) -+{ -+ IntlClockLocationTile *tile = data; -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ WeatherInfo *info; -+ GdkPixbuf *pixbuf = NULL; -+ gchar *conditions, *temp, *apparent, *wind; -+ gchar *line1, *line2, *line3, *line4, *tip; -+ -+ info = intlclock_location_get_weather_info (priv->location); -+ -+ if (!info || !weather_info_is_valid (info)) -+ return FALSE; -+ -+ weather_info_get_pixbuf (info, &pixbuf); -+ if (pixbuf) -+ gtk_tooltip_set_icon (tooltip, pixbuf); -+ -+ conditions = weather_info_get_conditions (info); -+ if (strcmp (conditions, "-") != 0) -+ line1 = g_strdup_printf (_("%s, %s"), -+ conditions, -+ weather_info_get_sky (info)); -+ else -+ line1 = g_strdup (weather_info_get_sky (info)); -+ -+ temp = weather_info_get_temp (info); -+ apparent = weather_info_get_apparent (info); -+ if (strcmp (apparent, temp) != 0 && -+ /* FIXME libgweather needs some real api */ -+ strcmp (apparent, dgettext ("gnome-applets-2.0", "Unknown")) != 0) -+ line2 = g_strdup_printf (_("%s, feels like %s"), temp, apparent); -+ else -+ line2 = g_strdup (temp); -+ -+ wind = weather_info_get_wind (info); -+ if (strcmp (apparent, dgettext ("gnome-applets-2.0", "Unknown")) != 0) -+ line3 = g_strdup_printf ("%s\n", wind); -+ else -+ line3 = g_strdup (""); -+ -+ line4 = g_strdup_printf (_("Sunrise: %s / Sunset: %s"), -+ weather_info_get_sunrise (info), -+ weather_info_get_sunset (info)); -+ -+ tip = g_strdup_printf ("<b>%s</b>\n%s\n%s%s", line1, line2, line3, line4); -+ gtk_tooltip_set_markup (tooltip, tip); -+ g_free (line1); -+ g_free (line2); -+ g_free (line3); -+ g_free (line4); -+ g_free (tip); -+ -+ return TRUE; -+} -+ -+ -+static void -+update_weather_icon (IntlClockLocation *loc, WeatherInfo *info, gpointer data) -+{ -+ IntlClockLocationTile *tile = data; -+ IntlClockLocationTilePrivate *priv = PRIVATE (tile); -+ GdkPixbuf *pixbuf = NULL; -+ -+ if (!info || !weather_info_is_valid (info)) -+ return; -+ -+ weather_info_get_pixbuf_mini (info, &pixbuf); -+ -+ if (pixbuf) { -+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->weather_icon), pixbuf); -+ gtk_alignment_set_padding (GTK_ALIGNMENT (gtk_widget_get_parent (priv->weather_icon)), 0, 0, 0, 6); -+ if (intlclock_location_is_current (loc)) -+ intlclock_ui_update_weather_icon (priv->ui, pixbuf); -+ } -+} -+ -diff --git a/src/intlclock-location.c b/src/intlclock-location.c -index 384b2aa..0a37b48 100644 ---- a/src/intlclock-location.c -+++ b/src/intlclock-location.c -@@ -1,4 +1,3 @@ --#include "intlclock-location.h" - - #ifdef HAVE_CONFIG_H - #include <config.h> -@@ -13,9 +12,16 @@ - #include <sys/stat.h> - #include <time.h> - #include <unistd.h> -+#include <math.h> - - #include <glib.h> - #include <libgnome/gnome-i18n.h> -+#include <libgnomevfs/gnome-vfs.h> -+ -+#include "intlclock-location.h" -+#include "intlclock-marshallers.h" -+#include "set-timezone.h" -+#include "gweather-xml.h" - - G_DEFINE_TYPE (IntlClockLocation, intlclock_location, G_TYPE_OBJECT) - -@@ -29,17 +35,31 @@ typedef struct { - - gfloat latitude; - gfloat longitude; -+ -+ gchar *weather_code; -+ WeatherInfo *weather_info; -+ guint weather_timeout; -+ - } IntlClockLocationPrivate; - -+enum { -+ WEATHER_UPDATED, -+ LAST_SIGNAL -+}; -+ -+static guint location_signals[LAST_SIGNAL] = { 0 }; -+ - static void intlclock_location_finalize (GObject *); - static void intlclock_location_set_tz (IntlClockLocation *this); - static void intlclock_location_unset_tz (IntlClockLocation *this); -+static void setup_weather_updates (IntlClockLocation *loc); - - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_LOCATION_TYPE, IntlClockLocationPrivate)) - - IntlClockLocation * - intlclock_location_new (const gchar *name, const gchar *timezone, -- gfloat latitude, gfloat longitude) -+ gfloat latitude, gfloat longitude, -+ const gchar *code) - { - IntlClockLocation *this; - IntlClockLocationPrivate *priv; -@@ -62,6 +82,9 @@ intlclock_location_new (const gchar *name, const gchar *timezone, - priv->latitude = latitude; - priv->longitude = longitude; - -+ priv->weather_code = g_strdup (code); -+ setup_weather_updates (this); -+ - return this; - } - -@@ -193,6 +216,77 @@ guess_zone_from_tree (const gchar *localtime, IntlClockZoneTable *zones) - return ret; - } - -+static const gchar *current_zone = NULL; -+static GnomeVFSMonitorHandle *monitor = NULL; -+ -+static void -+parse_etc_sysconfig_clock (void) -+{ -+ gchar *data; -+ gsize len; -+ gchar **lines; -+ gchar *res; -+ gint i; -+ gchar *p, *q; -+ -+ lines = NULL; -+ res = NULL; -+ if (g_file_test ("/etc/sysconfig/clock", -+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { -+ if (!g_file_get_contents ("/etc/sysconfig/clock", -+ &data, &len, NULL)) -+ goto out; -+ -+ lines = g_strsplit (data, "\n", 0); -+ g_free (data); -+ -+ for (i = 0; lines[i] && !res; i++) { -+ if (g_str_has_prefix (lines[i], "ZONE=")) { -+ p = lines[i] + strlen ("ZONE="); -+ if (p[0] != '\"') -+ goto out; -+ p++; -+ q = strchr (p, '\"'); -+ q[0] = '\0'; -+ res = g_strdup (p); -+ } -+ } -+ } -+ -+out: -+ if (lines) -+ g_strfreev (lines); -+ -+ g_free (current_zone); -+ current_zone = res; -+} -+ -+static void -+monitor_etc_sysconfig_clock (GnomeVFSMonitorHandle *handle, -+ const gchar *monitor_uri, -+ const gchar *info_uri, -+ GnomeVFSMonitorEventType event_type, -+ gpointer user_data) -+{ -+ parse_etc_sysconfig_clock (); -+} -+ -+static const gchar * -+zone_from_etc_sysconfig_clock (void) -+{ -+ if (monitor == NULL) { -+ parse_etc_sysconfig_clock (); -+ -+ gnome_vfs_monitor_add (&monitor, -+ "/etc/sysconfig/clock", -+ GNOME_VFS_MONITOR_FILE, -+ monitor_etc_sysconfig_clock, -+ NULL); -+ } -+ -+ return current_zone; -+} -+ - static gchar * - intlclock_location_guess_zone (IntlClockZoneTable *zones) - { -@@ -200,6 +294,12 @@ intlclock_location_guess_zone (IntlClockZoneTable *zones) - const char *localtime = "/etc/localtime"; - gchar *linkfile = NULL; - GError *err = NULL; -+ gchar *zone; -+ -+ /* look for /etc/sysconfig/clock */ -+ if ((zone = zone_from_etc_sysconfig_clock ())) { -+ return g_strdup (zone); -+ } - - /* guess the current time zone by readlink() on /etc/localtime */ - linkfile = g_file_read_link (localtime, &err); -@@ -235,14 +335,14 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) - - if (zone == NULL) { - /* make a fake location with a null TZ */ -- return intlclock_location_new (_("Unknown Location"), NULL, 0.0, 0.0); -+ return intlclock_location_new (_("Unknown Location"), NULL, 0.0, 0.0, NULL); - } - - info = intlclock_zonetable_get_zone (zones, zone); - - if (info == NULL) { - /* make a fake location with the current TZ */ -- return intlclock_location_new (_("Unknown Location"), zone, 0.0, 0.0); -+ return intlclock_location_new (_("Unknown Location"), zone, 0.0, 0.0, NULL); - } - - g_free (zone); -@@ -260,7 +360,7 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) - } - - ret = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), -- lat, lon); -+ lat, lon, NULL); - - g_free (name); - -@@ -274,6 +374,15 @@ intlclock_location_class_init (IntlClockLocationClass *this_class) - - g_obj_class->finalize = intlclock_location_finalize; - -+ location_signals[WEATHER_UPDATED] = -+ g_signal_new ("weather-updated", -+ G_OBJECT_CLASS_TYPE (g_obj_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (IntlClockLocationClass, weather_updated), -+ NULL, NULL, -+ _intlclock_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, G_TYPE_POINTER); -+ - g_type_class_add_private (this_class, sizeof (IntlClockLocationPrivate)); - } - -@@ -318,6 +427,21 @@ intlclock_location_finalize (GObject *g_obj) - priv->tzname = NULL; - } - -+ if (priv->weather_code) { -+ g_free (priv->weather_code); -+ priv->weather_code = NULL; -+ } -+ -+ if (priv->weather_info) { -+ weather_info_free (priv->weather_info); -+ priv->weather_info = NULL; -+ } -+ -+ if (priv->weather_timeout) { -+ g_source_remove (priv->weather_timeout); -+ priv->weather_timeout = 0; -+ } -+ - G_OBJECT_CLASS (intlclock_location_parent_class)->finalize (g_obj); - } - -@@ -467,3 +591,179 @@ intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm) - - intlclock_location_unset_tz (loc); - } -+ -+gboolean -+intlclock_location_is_current (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ gboolean current; -+ long sys_timezone; -+ const char *zone; -+ -+ if ((zone = zone_from_etc_sysconfig_clock ())) -+ return strcmp (zone, priv->timezone) == 0; -+ -+ unsetenv ("TZ"); -+ tzset (); -+ sys_timezone = timezone; -+ -+ setenv ("TZ", priv->timezone, 1); -+ tzset(); -+ -+ current = sys_timezone == timezone; -+ -+ if (priv->sys_timezone) { -+ setenv ("TZ", priv->sys_timezone, 1); -+ } else { -+ unsetenv ("TZ"); -+ } -+ tzset(); -+ -+ return current; -+} -+ -+gboolean -+intlclock_location_make_current (IntlClockLocation *loc, GError **error) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ gchar *filename; -+ gboolean ret; -+ -+ filename = g_build_filename (SYSTEM_ZONEINFODIR, priv->timezone, NULL); -+ ret = set_system_timezone (filename, error); -+ g_free (filename); -+ -+ if (ret) { -+ /* FIXME this ugly shortcut is necessary until we move the -+ * current timezone tracking to intlclock.c and emit the -+ * signal from there -+ */ -+ g_free (current_zone); -+ current_zone = g_strdup (priv->timezone); -+ } -+ -+ return ret; -+} -+ -+const gchar * -+intlclock_location_get_weather_code (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ return priv->weather_code; -+} -+ -+void -+intlclock_location_set_weather_code (IntlClockLocation *loc, const gchar *code) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ g_free (priv->weather_code); -+ priv->weather_code = g_strdup (code); -+ -+ setup_weather_updates (loc); -+} -+ -+WeatherInfo * -+intlclock_location_get_weather_info (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ return priv->weather_info; -+} -+ -+static void -+weather_info_updated (WeatherInfo *info, gpointer data) -+{ -+ IntlClockLocation *loc = data; -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ -+ g_signal_emit (loc, location_signals[WEATHER_UPDATED], -+ 0, priv->weather_info); -+} -+ -+static gboolean -+update_weather_info (gpointer data) -+{ -+ IntlClockLocation *loc = data; -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ WeatherPrefs prefs = { -+ FORECAST_STATE, -+ FALSE, -+ NULL, -+ TEMP_UNIT_CENTIGRADE, -+ SPEED_UNIT_MS, -+ PRESSURE_UNIT_MB, -+ DISTANCE_UNIT_KM -+ }; -+ -+ weather_info_update (priv->weather_info, -+ &prefs, weather_info_updated, loc); -+ -+ return TRUE; -+} -+ -+static gchar * -+rad2dms (gfloat lat, gfloat lon) -+{ -+ gchar h, h2; -+ gfloat d, deg, min, d2, deg2, min2; -+ -+ h = lat > 0 ? 'N' : 'S'; -+ d = fabs (lat); -+ deg = floor (d); -+ min = floor (60 * (d - deg)); -+ h2 = lon > 0 ? 'E' : 'W'; -+ d2 = fabs (lon); -+ deg2 = floor (d2); -+ min2 = floor (60 * (d2 - deg2)); -+ return g_strdup_printf ("%02d-%02d%c %02d-%02d%c", -+ (int)deg, (int)min, h, -+ (int)deg2, (int)min2, h2); -+} -+ -+static void -+setup_weather_updates (IntlClockLocation *loc) -+{ -+ IntlClockLocationPrivate *priv = PRIVATE (loc); -+ const gchar *code; -+ WeatherLocation *wl; -+ WeatherPrefs prefs = { -+ FORECAST_STATE, -+ FALSE, -+ NULL, -+ TEMP_UNIT_CENTIGRADE, -+ SPEED_UNIT_MS, -+ PRESSURE_UNIT_MB, -+ DISTANCE_UNIT_KM -+ }; -+ gfloat lat, lon; -+ gchar *dms; -+ -+ if (priv->weather_info) { -+ weather_info_free (priv->weather_info); -+ priv->weather_info = NULL; -+ } -+ -+ if (priv->weather_timeout) { -+ g_source_remove (priv->weather_timeout); -+ priv->weather_timeout = 0; -+ } -+ -+ if (!priv->weather_code || strcmp (priv->weather_code, "-") == 0) -+ return; -+ -+ dms = rad2dms (priv->latitude, priv->longitude); -+ wl = weather_location_new (priv->name, priv->weather_code, -+ NULL, NULL, dms); -+ -+ priv->weather_info = -+ weather_info_new (wl, &prefs, weather_info_updated, loc); -+ -+ priv->weather_timeout = -+ g_timeout_add_seconds (1800, update_weather_info, loc); -+ -+ weather_location_free (wl); -+ g_free (dms); -+} -+ -diff --git a/src/intlclock-location.h b/src/intlclock-location.h -index 824ee3c..deb7074 100644 ---- a/src/intlclock-location.h -+++ b/src/intlclock-location.h -@@ -4,6 +4,7 @@ - #include <time.h> - #include <glib.h> - #include <glib-object.h> -+#include <libgweather/weather.h> - - #include "intlclock-zonetable.h" - -@@ -24,12 +25,16 @@ typedef struct - typedef struct - { - GObjectClass g_object_class; -+ -+ void (* weather_updated) (IntlClockLocation *location, WeatherInfo *info); -+ - } IntlClockLocationClass; - - GType intlclock_location_get_type (void); - - IntlClockLocation *intlclock_location_new (const gchar *name, const gchar *timezone, -- gfloat latitude, gfloat longitude); -+ gfloat latitude, gfloat longitude, -+ const gchar *code); - - IntlClockLocation *intlclock_location_new_from_env (IntlClockZoneTable *zones); - -@@ -46,5 +51,12 @@ void intlclock_location_set_coords (IntlClockLocation *loc, gfloat latitude, gfl - - void intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm); - -+gboolean intlclock_location_is_current (IntlClockLocation *loc); -+gboolean intlclock_location_make_current (IntlClockLocation *loc, GError **error); -+ -+const gchar *intlclock_location_get_weather_code (IntlClockLocation *loc); -+void intlclock_location_set_weather_code (IntlClockLocation *loc, const gchar *code); -+WeatherInfo *intlclock_location_get_weather_info (IntlClockLocation *loc); -+ - G_END_DECLS - #endif /* __INTLCLOCK_LOCATION_H__ */ -diff --git a/src/intlclock-map.c b/src/intlclock-map.c -index 2d72975..9ded127 100644 ---- a/src/intlclock-map.c -+++ b/src/intlclock-map.c -@@ -25,7 +25,7 @@ typedef struct { - gint height; - - GdkPixbuf *stock_map_pixbuf; -- GdkPixbuf *location_marker_pixbuf; -+ GdkPixbuf *location_marker_pixbuf[3]; - - GdkPixbuf *location_map_pixbuf; - -@@ -54,6 +54,7 @@ static void intlclock_map_display (IntlClockMap *this); - - - static void intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this); -+static void intlclock_map_blink_location (IntlClock *clock, IntlClockLocation *loc, IntlClockMap *this); - static void intlclock_map_tick (IntlClock *clock, IntlClockMap *this); - - #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_MAP_TYPE, IntlClockMapPrivate)) -@@ -69,8 +70,12 @@ intlclock_map_new (IntlClock *clock) - - priv->clock = g_object_ref (clock); - -- priv->location_marker_pixbuf = rsvg_pixbuf_from_file -- (INTLCLOCK_ICONDIR "/intlclock-map-location-marker.svg", NULL); -+ priv->location_marker_pixbuf[0] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-marker.png", NULL); -+ priv->location_marker_pixbuf[1] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-hilight.png", NULL); -+ priv->location_marker_pixbuf[2] = gdk_pixbuf_new_from_file -+ (INTLCLOCK_ICONDIR "/intlclock-map-location-current.png", NULL); - - g_signal_connect (G_OBJECT (priv->clock), "tick", - G_CALLBACK (intlclock_map_tick), this); -@@ -78,6 +83,12 @@ intlclock_map_new (IntlClock *clock) - g_signal_connect (G_OBJECT (priv->clock), "locations_changed", - G_CALLBACK (intlclock_map_locations_changed), this); - -+ g_signal_connect (G_OBJECT (priv->clock), "current_timezone_changed", -+ G_CALLBACK (intlclock_map_locations_changed), this); -+ -+ g_signal_connect (G_OBJECT (priv->clock), "blink_location", -+ G_CALLBACK (intlclock_map_blink_location), this); -+ - intlclock_map_refresh (this); - - return this; -@@ -109,13 +120,16 @@ intlclock_map_init (IntlClockMap *this) - priv->clock = NULL; - - priv->stock_map_pixbuf = NULL; -- priv->location_marker_pixbuf = NULL; -+ priv->location_marker_pixbuf[0] = NULL; -+ priv->location_marker_pixbuf[1] = NULL; -+ priv->location_marker_pixbuf[2] = NULL; - } - - static void - intlclock_map_finalize (GObject *g_obj) - { - IntlClockMapPrivate *priv = PRIVATE (g_obj); -+ int i; - - g_signal_handlers_disconnect_by_func - (priv->clock, G_CALLBACK (intlclock_map_tick), g_obj); -@@ -130,10 +144,12 @@ intlclock_map_finalize (GObject *g_obj) - priv->stock_map_pixbuf = NULL; - } - -- if (priv->location_marker_pixbuf) { -- gdk_pixbuf_unref (priv->location_marker_pixbuf); -- priv->location_marker_pixbuf = NULL; -- } -+ for (i = 0; i < 3; i++) { -+ if (priv->location_marker_pixbuf[i]) { -+ gdk_pixbuf_unref (priv->location_marker_pixbuf[i]); -+ priv->location_marker_pixbuf[i] = NULL; -+ } -+ } - - if (priv->location_map_pixbuf) { - gdk_pixbuf_unref (priv->location_map_pixbuf); -@@ -164,12 +180,13 @@ intlclock_map_refresh (IntlClockMap *this) - IntlClockMapPrivate *priv = PRIVATE (this); - GtkWidget *widget = GTK_WIDGET (this); - GtkWidget *parent = gtk_widget_get_parent (widget); -+ GtkRequisition req; - gint width; - gint height; - -- gtk_widget_size_request (widget, &(widget->requisition)); -- width = widget->requisition.width; -- height = widget->requisition.height; -+ gtk_widget_size_request (widget, &req); -+ width = req.width; -+ height = req.height; - - if (parent) { - if (widget->allocation.width != 1) { -@@ -276,10 +293,10 @@ intlclock_map_size_allocate (GtkWidget *this, GtkAllocation *allocation) - } - - static void --intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude) -+intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude, gint mark) - { - IntlClockMapPrivate *priv = PRIVATE (this); -- GdkPixbuf *marker = priv->location_marker_pixbuf; -+ GdkPixbuf *marker = priv->location_marker_pixbuf[mark]; - GdkPixbuf *partial = NULL; - - int x, y; -@@ -395,14 +412,22 @@ intlclock_map_mark (IntlClockMap *this, gfloat latitude, gfloat longitude) - } - - static void --intlclock_map_place_location (IntlClockMap *this, IntlClockLocation *loc) -+intlclock_map_place_location (IntlClockMap *this, IntlClockLocation *loc, gboolean hilight) - { - IntlClockMapPrivate *priv = PRIVATE (this); - gfloat latitude, longitude; -+ gint marker; - - intlclock_location_get_coords (loc, &latitude, &longitude); - -- intlclock_map_mark (this, latitude, longitude); -+ if (hilight) -+ marker = 1; -+ else if (intlclock_location_is_current (loc)) -+ marker = 2; -+ else -+ marker = 0; -+ -+ intlclock_map_mark (this, latitude, longitude, marker); - } - - static void -@@ -428,7 +453,7 @@ intlclock_map_place_locations (IntlClockMap *this) - while (locs) { - loc = INTLCLOCK_LOCATION (locs->data); - -- intlclock_map_place_location (this, loc); -+ intlclock_map_place_location (this, loc, FALSE); - - locs = locs->next; - } -@@ -633,16 +658,12 @@ intlclock_map_rotate (IntlClockMap *this) - static void - intlclock_map_display (IntlClockMap *this) - { -- IntlClockMapPrivate *priv = PRIVATE (this); -- - gtk_widget_queue_draw (GTK_WIDGET (this)); - } - - static void - intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this) - { -- IntlClockMapPrivate *priv = PRIVATE (this); -- - intlclock_map_place_locations (this); - - intlclock_map_render_shadow (this); -@@ -651,6 +672,49 @@ intlclock_map_locations_changed (IntlClock *clock, IntlClockMap *this) - intlclock_map_display (this); - } - -+typedef struct { -+ IntlClockMap *map; -+ IntlClockLocation *location; -+ int count; -+} BlinkData; -+ -+static gboolean -+highlight (gpointer user_data) -+{ -+ BlinkData *data = user_data; -+ -+ if (data->count == 6) { -+ g_free (data); -+ return FALSE; -+ } -+ -+ if (data->count % 2 == 0) -+ intlclock_map_place_location (data->map, data->location, TRUE); -+ else -+ intlclock_map_place_locations (data->map); -+ intlclock_map_render_shadow (data->map); -+ intlclock_map_rotate (data->map); -+ intlclock_map_display (data->map); -+ -+ data->count++; -+ -+ return TRUE; -+} -+ -+static void -+intlclock_map_blink_location (IntlClock *clock, IntlClockLocation *loc, IntlClockMap *this) -+{ -+ BlinkData *data; -+ -+ data = g_new0 (BlinkData, 1); -+ data->map = this; -+ data->location = loc; -+ -+ highlight (data); -+ -+ g_timeout_add (300, highlight, data); -+} -+ - static gboolean - intlclock_map_needs_refresh (IntlClockMap *this) - { -diff --git a/src/intlclock-marshallers.c b/src/intlclock-marshallers.c -deleted file mode 100644 -index 8f01ab8..0000000 ---- a/src/intlclock-marshallers.c -+++ /dev/null -@@ -1,51 +0,0 @@ -- --#include <glib-object.h> -- -- --#ifdef G_ENABLE_DEBUG --#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) --#define g_marshal_value_peek_char(v) g_value_get_char (v) --#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) --#define g_marshal_value_peek_int(v) g_value_get_int (v) --#define g_marshal_value_peek_uint(v) g_value_get_uint (v) --#define g_marshal_value_peek_long(v) g_value_get_long (v) --#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) --#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) --#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) --#define g_marshal_value_peek_enum(v) g_value_get_enum (v) --#define g_marshal_value_peek_flags(v) g_value_get_flags (v) --#define g_marshal_value_peek_float(v) g_value_get_float (v) --#define g_marshal_value_peek_double(v) g_value_get_double (v) --#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) --#define g_marshal_value_peek_param(v) g_value_get_param (v) --#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) --#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) --#define g_marshal_value_peek_object(v) g_value_get_object (v) --#else /* !G_ENABLE_DEBUG */ --/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. -- * Do not access GValues directly in your code. Instead, use the -- * g_value_get_*() functions -- */ --#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int --#define g_marshal_value_peek_char(v) (v)->data[0].v_int --#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint --#define g_marshal_value_peek_int(v) (v)->data[0].v_int --#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint --#define g_marshal_value_peek_long(v) (v)->data[0].v_long --#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong --#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 --#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 --#define g_marshal_value_peek_enum(v) (v)->data[0].v_long --#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong --#define g_marshal_value_peek_float(v) (v)->data[0].v_float --#define g_marshal_value_peek_double(v) (v)->data[0].v_double --#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer --#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer --#endif /* !G_ENABLE_DEBUG */ -- -- --/* VOID:VOID (intlclock-marshallers.list:1) */ -- -diff --git a/src/intlclock-marshallers.h b/src/intlclock-marshallers.h -deleted file mode 100644 -index c022a3e..0000000 ---- a/src/intlclock-marshallers.h -+++ /dev/null -@@ -1,15 +0,0 @@ -- --#ifndef ___intlclock_marshal_MARSHAL_H__ --#define ___intlclock_marshal_MARSHAL_H__ -- --#include <glib-object.h> -- --G_BEGIN_DECLS -- --/* VOID:VOID (intlclock-marshallers.list:1) */ --#define _intlclock_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID -- --G_END_DECLS -- --#endif /* ___intlclock_marshal_MARSHAL_H__ */ -- -diff --git a/src/intlclock-marshallers.list b/src/intlclock-marshallers.list -index 5b76282..e737cac 100644 ---- a/src/intlclock-marshallers.list -+++ b/src/intlclock-marshallers.list -@@ -1 +1,3 @@ - VOID:VOID -+VOID:OBJECT -+VOID:POINTER -diff --git a/src/intlclock-sunpos.c b/src/intlclock-sunpos.c -index 942617b..89d4cc1 100644 ---- a/src/intlclock-sunpos.c -+++ b/src/intlclock-sunpos.c -@@ -1,348 +1,196 @@ - /* -- * sunpos.c -- * kirk johnson -- * july 1993 -+ * Copyright (C) 2007 Red Hat, Inc. - * -- * includes revisions from Frank T. Solensky, february 1999 -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. - * -- * code for calculating the position on the earth's surface for which -- * the sun is directly overhead (adapted from _practical astronomy -- * with your calculator, third edition_, peter duffett-smith, -- * cambridge university press, 1988.) -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. - * -- * Copyright (C) 1989, 1990, 1993-1995, 1999 Kirk Lauritz Johnson -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -+ * 02111-1307, USA. - * -- * Parts of the source code (as marked) are: -- * Copyright (C) 1989, 1990, 1991 by Jim Frost -- * Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com> -- * -- * Permission to use, copy, modify and freely distribute xearth for -- * non-commercial and not-for-profit purposes is hereby granted -- * without fee, provided that both the above copyright notice and this -- * permission notice appear in all copies and in supporting -- * documentation. -- * -- * Unisys Corporation holds worldwide patent rights on the Lempel Zev -- * Welch (LZW) compression technique employed in the CompuServe GIF -- * image file format as well as in other formats. Unisys has made it -- * clear, however, that it does not require licensing or fees to be -- * paid for freely distributed, non-commercial applications (such as -- * xearth) that employ LZW/GIF technology. Those wishing further -- * information about licensing the LZW patent should contact Unisys -- * directly at (lzw_info@unisys.com) or by writing to -- * -- * Unisys Corporation -- * Welch Licensing Department -- * M/S-C1SW19 -- * P.O. Box 500 -- * Blue Bell, PA 19424 -- * -- * The author makes no representations about the suitability of this -- * software for any purpose. It is provided "as is" without express or -- * implied warranty. -- * -- * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT -- * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * Authors: -+ * Jonathan Blandford <jrb@redhat.com> -+ * Matthias Clasen <mclasen@redhat.com> - */ -- --#include <assert.h> --#include <math.h> -+ - #include <time.h> -+#include <gtk/gtk.h> -+#include <math.h> - --#include "intlclock-sunpos.h" -- --#define TWOPI (2*M_PI) --#define DegsToRads(x) ((x)*(TWOPI/360)) -- --/* -- * the epoch upon which these astronomical calculations are based is -- * 1990 january 0.0, 631065600 seconds since the beginning of the -- * "unix epoch" (00:00:00 GMT, Jan. 1, 1970) -- * -- * given a number of seconds since the start of the unix epoch, -- * DaysSinceEpoch() computes the number of days since the start of the -- * astronomical epoch (1990 january 0.0) -- */ -- --#define EpochStart (631065600) --#define DaysSinceEpoch(secs) (((secs)-EpochStart)*(1.0/(24*3600))) -- --/* -- * assuming the apparent orbit of the sun about the earth is circular, -- * the rate at which the orbit progresses is given by RadsPerDay -- -- * TWOPI radians per orbit divided by 365.242191 days per year: -- */ -- --#define RadsPerDay (TWOPI/365.242191) -- --/* -- * details of sun's apparent orbit at epoch 1990.0 (after -- * duffett-smith, table 6, section 46) -- * -- * Epsilon_g (ecliptic longitude at epoch 1990.0) 279.403303 degrees -- * OmegaBar_g (ecliptic longitude of perigee) 282.768422 degrees -- * Eccentricity (eccentricity of orbit) 0.016713 -+/* Calculated with the methods and figures from "Practical Astronomy With Your -+ * Calculator, version 3" by Peter Duffet-Smith. - */ -+/* Table 6. Details of the Sun's apparent orbit at epoch 1990.0 */ - --#define Epsilon_g (DegsToRads(279.403303)) --#define OmegaBar_g (DegsToRads(282.768422)) --#define Eccentricity (0.016713) -+#define EPOCH 2447891.5 /* days */ /* epoch 1990 */ -+#define UNIX_EPOCH 2440586.5 /* days */ /* epoch 1970 */ -+#define EPSILON_G 279.403303 /* degrees */ /* ecliptic longitude at epoch 1990.0 */ -+#define MU_G 282.768422 /* degrees */ /* ecliptic longitude at perigree */ -+#define ECCENTRICITY 0.016713 /* eccentricity of orbit */ -+#define R_0 149598500 /* km */ /* semi-major access */ -+#define THETA_0 0.533128 /* degrees */ /* angular diameter at r = r_0 */ -+#define MEAN_OBLIQUITY 23.440592 /* degrees */ /* mean obliquity of earths axis at epoch 1990.0 */ - --/* -- * MeanObliquity gives the mean obliquity of the earth's axis at epoch -- * 1990.0 (computed as 23.440592 degrees according to the method given -- * in duffett-smith, section 27) -- */ --#define MeanObliquity (23.440592*(TWOPI/360)) -+#define NORMALIZE(x) \ -+ while (x>360) x-=360; while (x<0) x+= 360; - --/* -- * Lunar parameters, epoch January 0, 1990.0 -- */ --#define MoonMeanLongitude DegsToRads(318.351648) --#define MoonMeanLongitudePerigee DegsToRads( 36.340410) --#define MoonMeanLongitudeNode DegsToRads(318.510107) --#define MoonInclination DegsToRads( 5.145396) -+#define DEG_TO_RADS(x) \ -+ (x * G_PI/180.0) - --#define SideralMonth (27.3217) -+#define RADS_TO_DEG(x) \ -+ (x * 180.0/G_PI) - --/* -- * Force an angular value into the range [-PI, +PI] -+/* Calculate number of days since 4713BC. - */ --#define Normalize(x) \ -- do { \ -- if ((x) < -M_PI) \ -- do (x) += TWOPI; while ((x) < -M_PI); \ -- else if ((x) > M_PI) \ -- do (x) -= TWOPI; while ((x) > M_PI); \ -- } while (0) -- --static double solve_keplers_equation (double); --static double mean_sun (double); --static double sun_ecliptic_longitude (time_t); --static void ecliptic_to_equatorial (double, double, double *, double *); --static double julian_date (int, int, int); --static double GST (time_t); -- --/* -- * solve Kepler's equation via Newton's method -- * (after duffett-smith, section 47) -- */ --static double solve_keplers_equation(M) -- double M; -+static gdouble -+unix_time_to_julian_date (gint unix_time) - { -- double E; -- double delta; -- -- E = M; -- while (1) -- { -- delta = E - Eccentricity*sin(E) - M; -- if (fabs(delta) <= 1e-10) break; -- E -= delta / (1 - Eccentricity*cos(E)); -- } -- -- return E; -+ return UNIX_EPOCH + (double) unix_time / (60 * 60 * 24); - } - -+/* Finds an iterative solution for [ E - e sin (E) = M ] for values of e less -+ than 0.1. Page 90 */ - --/* -- * Calculate the position of the mean sun: where the sun would -- * be if the earth's orbit were circular instead of ellipictal. -- */ -+#define ERROR_ACCURACY 1e-6 /* radians */ - --static double mean_sun (D) -- double D; /* days since ephemeris epoch */ -+static gdouble -+solve_keplers_equation (gdouble e, -+ gdouble M) - { -- double N, M; -+ gdouble d, E; - -- N = RadsPerDay * D; -- N = fmod(N, TWOPI); -- if (N < 0) N += TWOPI; -+ /* start with an initial estimate */ -+ E = M; -+ -+ d = E - e * sin (E) - M; -+ -+ while (ABS (d) > ERROR_ACCURACY) -+ { -+ E = E - (d / (1 - e * cos (E))); -+ d = E - e * sin (E) - M; -+ } - -- M = N + Epsilon_g - OmegaBar_g; -- if (M < 0) M += TWOPI; -- return M; -+ return E; - } - --/* -- * compute ecliptic longitude of sun (in radians) -- * (after duffett-smith, section 47) -- */ --static double sun_ecliptic_longitude(ssue) -- time_t ssue; /* seconds since unix epoch */ -+ /* convert the ecliptic longitude to right ascension and declination. Section 27. */ -+static void -+ecliptic_to_equatorial (gdouble lambda, -+ gdouble beta, -+ gdouble *ra, -+ gdouble *dec) - { -- double D; -- double M_sun, E; -- double v; -+ gdouble cos_mo; -+ gdouble sin_mo; - -- D = DaysSinceEpoch(ssue); -- M_sun = mean_sun(D); -+ g_assert (ra != NULL); -+ g_assert (dec != NULL); - -- E = solve_keplers_equation(M_sun); -- v = 2 * atan(sqrt((1+Eccentricity)/(1-Eccentricity)) * tan(E/2)); -+ sin_mo = sin (DEG_TO_RADS (MEAN_OBLIQUITY)); -+ cos_mo = cos (DEG_TO_RADS (MEAN_OBLIQUITY)); - -- return (v + OmegaBar_g); -+ *ra = atan2 (sin (lambda) * cos_mo - tan (beta) * sin_mo, cos (lambda)); -+ *dec = asin (sin (beta) * cos_mo + cos (beta) * sin_mo * sin (lambda)); - } - -- --/* -- * convert from ecliptic to equatorial coordinates -- * (after duffett-smith, section 27) -- */ --static void ecliptic_to_equatorial(lambda, beta, alpha, delta) -- double lambda; /* ecliptic longitude */ -- double beta; /* ecliptic latitude */ -- double *alpha; /* (return) right ascension */ -- double *delta; /* (return) declination */ -+/* calculate GST. Section 12 */ -+static gdouble -+greenwich_sidereal_time (gdouble unix_time) - { -- double sin_e, cos_e; -+ gdouble u, JD, T, T0, UT; - -- sin_e = sin(MeanObliquity); -- cos_e = cos(MeanObliquity); -+ u = fmod (unix_time, 24 * 60 * 60); -+ JD = unix_time_to_julian_date (unix_time - u); -+ T = (JD - 2451545) / 36525; -+ T0 = 6.697374558 + (2400.051336 * T) + (0.000025862 * T * T); -+ T0 = fmod (T0, 24); -+ UT = u / (60 * 60); -+ T0 = T0 + UT * 1.002737909; -+ T0 = fmod (T0, 24); - -- *alpha = atan2(sin(lambda)*cos_e - tan(beta)*sin_e, cos(lambda)); -- *delta = asin(sin(beta)*cos_e + cos(beta)*sin_e*sin(lambda)); -+ return T0; - } - -- --/* -- * computing julian dates (assuming gregorian calendar, thus this is -- * only valid for dates of 1582 oct 15 or later) -- * (after duffett-smith, section 4) -- */ --static double julian_date(y, m, d) -- int y; /* year (e.g. 19xx) */ -- int m; /* month (jan=1, feb=2, ...) */ -- int d; /* day of month */ -+/* Calculate the position of the sun at a given time. pages 89-91 */ -+void -+sun_position (gint unix_time, gdouble *lat, gdouble *lon) - { -- int A, B, C, D; -- double JD; -+ gdouble jd, D, N, M, E, x, v, lambda; -+ gdouble ra, dec; -+ jd = unix_time_to_julian_date (unix_time); - -- /* lazy test to ensure gregorian calendar */ -- assert(y >= 1583); -+ /* Calculate number of days since the epoch */ -+ D = jd - EPOCH; - -- if ((m == 1) || (m == 2)) -- { -- y -= 1; -- m += 12; -- } -+ N = D*360/365.242191; - -- A = y / 100; -- B = 2 - A + (A / 4); -- C = 365.25 * y; -- D = 30.6001 * (m + 1); -+ /* normalize to 0 - 360 degrees */ -+ NORMALIZE (N); - -- JD = B + C + D + d + 1720994.5; -+ /* Step 4: */ -+ M = N + EPSILON_G - MU_G; -+ NORMALIZE (M); - -- return JD; --} -- -- --/* -- * compute greenwich mean sidereal time (GST) corresponding to a given -- * number of seconds since the unix epoch -- * (after duffett-smith, section 12) -- */ --static double GST(ssue) -- time_t ssue; /* seconds since unix epoch */ --{ -- double JD; -- double T, T0; -- double UT; -- struct tm *tm; -+ /* Step 5: convert to radians */ -+ M = DEG_TO_RADS (M); - -- tm = gmtime(&ssue); -+ /* Step 6: */ -+ E = solve_keplers_equation (ECCENTRICITY, M); - -- JD = julian_date(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); -- T = (JD - 2451545) / 36525; -+ /* Step 7: */ -+ x = sqrt ((1 + ECCENTRICITY)/(1 - ECCENTRICITY)) * tan (E/2); - -- T0 = ((T + 2.5862e-5) * T + 2400.051336) * T + 6.697374558; -+ /* Step 8, 9 */ -+ v = 2 * RADS_TO_DEG (atan (x)); -+ NORMALIZE (v); - -- T0 = fmod(T0, 24.0); -- if (T0 < 0) T0 += 24; -+ /* Step 10 */ -+ lambda = v + MU_G; -+ NORMALIZE (lambda); - -- UT = tm->tm_hour + (tm->tm_min + tm->tm_sec / 60.0) / 60.0; -+ /* convert the ecliptic longitude to right ascension and declination */ -+ ecliptic_to_equatorial (DEG_TO_RADS (lambda), 0.0, &ra, &dec); - -- T0 += UT * 1.002737909; -- T0 = fmod(T0, 24.0); -- if (T0 < 0) T0 += 24; -+ ra = ra - (G_PI/12) * greenwich_sidereal_time (unix_time); -+ ra = RADS_TO_DEG (ra); -+ dec = RADS_TO_DEG (dec); -+ NORMALIZE (ra); -+ NORMALIZE (dec); - -- return T0; -+ *lat = dec; -+ *lon = ra; - } - - --/* -- * given a particular time (expressed in seconds since the unix -- * epoch), compute position on the earth (lat, lon) such that sun is -- * directly overhead. -- */ --void sun_position(ssue, lat, lon) -- time_t ssue; /* seconds since unix epoch */ -- double *lat; /* (return) latitude */ -- double *lon; /* (return) longitude */ -+#if 0 -+int -+main (int argc, char *argv[]) - { -- double lambda; -- double alpha, delta; -- double tmp; -+ gint i; -+ gint now; -+ GTimeVal timeval; -+ gdouble lat, lon; - -- lambda = sun_ecliptic_longitude(ssue); -- ecliptic_to_equatorial(lambda, 0.0, &alpha, &delta); -+ gtk_init (&argc, &argv); - -- tmp = alpha - (TWOPI/24)*GST(ssue); -- Normalize(tmp); -- *lon = tmp * (360/TWOPI); -- *lat = delta * (360/TWOPI); --} -+ g_get_current_time (&timeval); -+ now = timeval.tv_sec; - -+ for (i = 0; i < now; i += 15 * 60) -+ { -+ sun_position (i, &lat, &lon); -+ g_print ("%d: %f %f\n", lat, lon); -+ } - --/* -- * given a particular time (expressed in seconds since the unix -- * epoch), compute position on the earth (lat, lon) such that the -- * moon is directly overhead. -- * -- * Based on duffett-smith **2nd ed** section 61; combines some steps -- * into single expressions to reduce the number of extra variables. -- */ --void moon_position(ssue, lat, lon) -- time_t ssue; /* seconds since unix epoch */ -- double *lat; /* (return) latitude */ -- double *lon; /* (return) longitude */ --{ -- double lambda, beta; -- double D, L, Ms, Mm, N, Ev, Ae, Ec, alpha, delta; -- -- D = DaysSinceEpoch(ssue); -- lambda = sun_ecliptic_longitude(ssue); -- Ms = mean_sun(D); -- -- L = fmod(D/SideralMonth, 1.0)*TWOPI + MoonMeanLongitude; -- Normalize(L); -- Mm = L - DegsToRads(0.1114041*D) - MoonMeanLongitudePerigee; -- Normalize(Mm); -- N = MoonMeanLongitudeNode - DegsToRads(0.0529539*D); -- Normalize(N); -- Ev = DegsToRads(1.2739) * sin(2.0*(L-lambda)-Mm); -- Ae = DegsToRads(0.1858) * sin(Ms); -- Mm += Ev - Ae - DegsToRads(0.37)*sin(Ms); -- Ec = DegsToRads(6.2886) * sin(Mm); -- L += Ev + Ec - Ae + DegsToRads(0.214) * sin(2.0*Mm); -- L += DegsToRads(0.6583) * sin(2.0*(L-lambda)); -- N -= DegsToRads(0.16) * sin(Ms); -- -- L -= N; -- lambda =(fabs(cos(L)) < 1e-12) ? -- (N + sin(L) * cos(MoonInclination) * M_PI/2) : -- (N + atan2(sin(L) * cos(MoonInclination), cos(L))); -- Normalize(lambda); -- beta = asin(sin(L) * sin(MoonInclination)); -- ecliptic_to_equatorial(lambda, beta, &alpha, &delta); -- alpha -= (TWOPI/24)*GST(ssue); -- Normalize(alpha); -- *lon = alpha * (360/TWOPI); -- *lat = delta * (360/TWOPI); -+ return 0; - } -+ -+#endif -diff --git a/src/intlclock-ui.c b/src/intlclock-ui.c -index f51e4de..f0d70bd 100644 ---- a/src/intlclock-ui.c -+++ b/src/intlclock-ui.c -@@ -14,6 +14,7 @@ - #include <libgnome/gnome-i18n.h> - #include <locale.h> - #include <math.h> -+#include <time.h> - #include <panel-applet-gconf.h> - #include <stdlib.h> - #include <string.h> -@@ -26,18 +27,18 @@ - #include "intlclock-map.h" - #include "intlclock-zoneinfo.h" - #include "intlclock-zonetable.h" -+#include "set-timezone.h" -+#include "gweather-xml.h" - - G_DEFINE_TYPE (IntlClockUI, intlclock_ui, G_TYPE_OBJECT) - - /* GConf keys for compatibility with the older GNOME clock */ --#define N_GCONF_PREFS 7 -+#define N_GCONF_PREFS 5 - static const char *KEY_CITIES = "cities"; - static const char *KEY_FORMAT = "format"; - static const char *KEY_SHOW_SECONDS = "show_seconds"; - static const char *KEY_SHOW_DATE = "show_date"; - static const char *KEY_SHOW_WEEK = "show_week_numbers"; --static const char *KEY_SHOW_LOCATIONS = "show_locations"; --static const char *KEY_SHOW_MAP = "show_map"; - - /* Needs to match the indices in the combo */ - typedef enum { -@@ -78,12 +79,14 @@ typedef struct { - GtkWidget *panel_box; - GtkWidget *panel_button; - GtkWidget *panel_label; -+ GtkWidget *panel_weather_icon; - - GtkTooltips *panel_tips; - - GtkWidget *panel_button_popup; - - GtkWidget *clock_vbox; -+ GtkSizeGroup *clock_group; - - GtkWidget *main_section; - GtkWidget *clock_calendar; -@@ -97,17 +100,34 @@ typedef struct { - - GtkListStore *cities_store; - -- gboolean show_locations; -- gboolean show_map; -- - GtkWidget *prefs_window; - GtkTreeView *prefs_locations; - -+ GtkWidget *prefs_location_add_button; -+ GtkWidget *prefs_location_edit_button; -+ GtkWidget *prefs_location_remove_button; -+ -+ GtkWidget *location_tree; -+ GtkWidget *find_next_location_button; -+ GtkWidget *find_location_entry; -+ GtkWidget *find_location_ok_button; -+ -+ GtkWidget *set_time_window; -+ GtkWidget *hours_spin; -+ GtkWidget *minutes_spin; -+ GtkWidget *seconds_spin; -+ GtkWidget *calendar; -+ GtkWidget *current_time_label; -+ GtkWidget *set_time_button; -+ GtkWidget *time_settings_button; -+ - gboolean format_12hr; - gboolean format_show_seconds; - gboolean format_show_date; - gboolean format_show_week; - -+ gulong zone_combo_changed; -+ - guint listeners [N_GCONF_PREFS]; - } IntlClockUIPrivate; - -@@ -118,51 +138,51 @@ static gboolean update_panel_label (gpointer this); - static void setup_gconf (IntlClockUI *this); - static void load_gconf_settings (IntlClockUI *this); - --static void bonobo_run_time_configuration (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname); - static void bonobo_display_properties_dialog (BonoboUIComponent *uic, - IntlClockUI *this, - const gchar *verbname); --static void display_help_dialog (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname); --static void display_about_dialog (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname); -- --static void config_date (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname); - - static void intlclock_reposition_events_window (IntlClockUI *this); -- - static void position_popup_window (IntlClockUI *this, - GtkWindow *window, - GtkWidget *origin); - --static void display_prefs_window_cb (GtkButton *button, gpointer this); --static void run_time_configuration (IntlClockUI *this); --static void run_time_configuration_cb (GtkButton *button, gpointer this); -+static void display_prefs_window (IntlClockUI *this, gboolean locations); - static void run_prefs_locations_add (GtkButton *button, gpointer this); - static void run_prefs_locations_edit (GtkButton *button, gpointer this); - static void run_prefs_locations_remove (GtkButton *button, gpointer this); - static void run_prefs_edit_save (GtkButton *button, gpointer this); -- -+static void run_find_location (GtkButton *button, gpointer this); -+static void run_find_location_save (GtkButton *button, gpointer this); -+static void intlclock_edit_hide (GtkWidget *widget, IntlClockUI *this); -+static void intlclock_find_hide (GtkWidget *widget, IntlClockUI *this); - static void intlclock_ui_save_cities_store (IntlClockUI *this); - - static void intlclock_ui_locations_changed (IntlClock *clock, IntlClockUI *this); - - static void create_cities_section (IntlClockUI *this); - static void create_events_window (IntlClockUI *this); --static void create_main_section (IntlClockUI *this); - static void create_map_section (IntlClockUI *this); - - static void zone_combo_changed (GtkComboBox *widget, gpointer this); -+static void update_coords (IntlClockUI *this, gboolean valid, gfloat lat, gfloat lon); -+static void fill_location_tree (IntlClockUI *this); -+static void copy_time (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const gchar *verbname); -+static void copy_date (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const gchar *verbname); -+static void config_date (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const gchar *verbname); -+ - - static const BonoboUIVerb intlclock_menu_verbs [] = { - BONOBO_UI_UNSAFE_VERB ("IntlClockPreferences", bonobo_display_properties_dialog), -- BONOBO_UI_UNSAFE_VERB ("IntlClockConfig", bonobo_run_time_configuration), -+ BONOBO_UI_UNSAFE_VERB ("ClockCopyTime", copy_time), -+ BONOBO_UI_UNSAFE_VERB ("ClockCopyDate", copy_date), -+ BONOBO_UI_UNSAFE_VERB ("ClockConfig", config_date), - BONOBO_UI_VERB_END - }; - -@@ -190,11 +210,6 @@ intlclock_ui_is_12hr (IntlClockUI *this) - static gboolean - panel_button_press_cb (GtkWidget *button, GdkEventButton *event, gpointer data) - { -- IntlClockUI *this = INTLCLOCK_UI (data); -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (button); -- - if (event->button != 1) - g_signal_stop_emission_by_name (button, "button_press_event"); - -@@ -206,7 +221,9 @@ intlclock_ui_reset_timeout (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - -- if (GTK_WIDGET_VISIBLE (priv->events_window) || priv->format_show_seconds) { -+ if (GTK_WIDGET_VISIBLE (priv->events_window) || -+ (priv->set_time_window && GTK_WIDGET_VISIBLE (priv->set_time_window)) || -+ priv->format_show_seconds) { - intlclock_set_tick_timeout (INTLCLOCK (priv->clock), 1); - } else { - intlclock_set_tick_timeout (INTLCLOCK (priv->clock), 60); -@@ -244,20 +261,6 @@ panel_button_clicked_cb (GtkButton *button, gpointer data) - intlclock_ui_reset_timeout (this); - } - --static gboolean --panel_events_button_press_cb (GtkWidget *button, GdkEventButton *event, gpointer data) --{ -- IntlClockUI *this = INTLCLOCK_UI (data); -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (button); -- -- if (event->button != 1) -- g_signal_stop_emission_by_name (button, "button_press_event"); -- -- return FALSE; --} -- - static void - position_popup_window (IntlClockUI *this, - GtkWindow *window, -@@ -375,147 +378,6 @@ intlclock_events_window_size_allocate_cb (GtkWidget *widget, GtkAllocation *allo - intlclock_reposition_events_window (this); - } - --static gboolean --intlclock_window_expose_cb (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) --{ -- IntlClockUIPrivate *priv = PRIVATE (user_data); -- -- cairo_t *cr; -- -- cr = gdk_cairo_create (widget->window); -- -- cairo_rectangle ( -- cr, -- event->area.x, event->area.y, -- event->area.width, event->area.height); -- -- cairo_clip (cr); -- --/* draw window background */ -- -- cairo_rectangle ( -- cr, -- widget->allocation.x + 0.5, widget->allocation.y + 0.5, -- widget->allocation.width - 1, widget->allocation.height - 1); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->bg [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->bg [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->bg [GTK_STATE_ACTIVE].blue / 65535.0); -- -- cairo_fill_preserve (cr); -- --/* draw window outline */ -- -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -- -- cairo_set_line_width (cr, 1.0); -- cairo_stroke (cr); -- --/* draw main pane background */ -- -- cairo_rectangle ( -- cr, -- priv->main_section->allocation.x + 0.5, priv->main_section->allocation --.y + 0.5, -- priv->main_section->allocation.width - 1, priv->main_section->allocation.height - 1); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->bg [GTK_STATE_NORMAL].red / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].green / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].blue / 65535.0); -- -- cairo_fill (cr); -- --/* draw map pane background */ -- -- if (priv->show_map) { -- cairo_rectangle ( -- cr, -- priv->map_section->allocation.x + 0.5, -- priv->map_section->allocation.y + 0.5, -- priv->map_section->allocation.width - 1, -- priv->map_section->allocation.height - 1); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->bg [GTK_STATE_NORMAL].red / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].green / 65535.0, -- widget->style->bg [GTK_STATE_NORMAL].blue / 65535.0); -- -- cairo_fill (cr); -- } -- --/* draw internal window outline */ -- -- cairo_rectangle ( -- cr, -- priv->clock_vbox->allocation.x + 0.5, priv->clock_vbox->allocation.y + 0.5, -- priv->clock_vbox->allocation.width - 1, priv->clock_vbox->allocation.height - 1); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -- -- cairo_stroke (cr); -- --/* draw map/cities pane separator */ -- -- if (priv->show_map) { -- cairo_move_to ( -- cr, -- priv->map_section->allocation.x + 0.5, -- priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); -- -- cairo_line_to ( -- cr, -- priv->map_section->allocation.x + priv->map_section->allocation.width - 0.5, -- priv->map_section->allocation.y + priv->map_section->allocation.height - 0.5); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -- -- cairo_stroke (cr); -- } -- --/* draw cities/main pane separator */ -- -- if (priv->show_locations) { -- cairo_move_to ( -- cr, -- priv->cities_section->allocation.x + 0.5, -- priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); -- -- cairo_line_to ( -- cr, -- priv->cities_section->allocation.x + priv->cities_section->allocation.width - 0.5, -- priv->cities_section->allocation.y + priv->cities_section->allocation.height - 0.5); -- -- cairo_set_source_rgb ( -- cr, -- widget->style->dark [GTK_STATE_ACTIVE].red / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].green / 65535.0, -- widget->style->dark [GTK_STATE_ACTIVE].blue / 65535.0); -- -- cairo_stroke (cr); -- } -- -- cairo_destroy (cr); -- -- return FALSE; --} -- - static void - intlclock_ui_tick (IntlClock *clock, IntlClockUI *this) - { -@@ -529,10 +391,7 @@ intlclock_ui_tick (IntlClock *clock, IntlClockUI *this) - static void - intlclock_ui_locations_changed (IntlClock *clock, IntlClockUI *this) - { -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- create_cities_section (this); -- intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); -+ create_cities_section (this); - } - - static gboolean -@@ -550,12 +409,20 @@ update_panel_label (gpointer this) - time (&now_t); - localtime_r (&now_t, &now); - -+ if (priv->current_time_label && -+ GTK_WIDGET_VISIBLE (priv->current_time_label)) { -+ date = intlclock_format_time (priv->clock, &now, -+ FALSE, FALSE, TRUE, -+ FALSE, FALSE, NULL, TRUE); -+ gtk_label_set_markup (GTK_LABEL (priv->current_time_label), date); -+ g_free (date); -+ } -+ - date = intlclock_format_time (priv->clock, &now, - priv->format_show_date, - priv->format_12hr, - priv->format_show_seconds, - FALSE, priv->format_show_date, NULL, TRUE); -- - gtk_label_set_markup (GTK_LABEL (priv->panel_label), date); - g_free (date); - -@@ -583,6 +450,7 @@ create_panel_buttons (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - PanelAppletOrient orient; -+ GtkWidget *box; - - orient = panel_applet_get_orient (priv->panel_applet); - -@@ -590,13 +458,18 @@ create_panel_buttons (IntlClockUI *this) - case PANEL_APPLET_ORIENT_UP: - case PANEL_APPLET_ORIENT_DOWN: - priv->panel_box = gtk_hbox_new (FALSE, 0); -+ box = gtk_hbox_new (FALSE, 6); - break; - case PANEL_APPLET_ORIENT_RIGHT: - case PANEL_APPLET_ORIENT_LEFT: - priv->panel_box = gtk_vbox_new (FALSE, 0); -+ box = gtk_vbox_new (FALSE, 6); - break; -+ default: -+ g_assert_not_reached (); - } - priv->panel_label = gtk_label_new (NULL); -+ priv->panel_weather_icon = gtk_image_new (); - priv->panel_button = gtk_toggle_button_new (); - priv->panel_tips = gtk_tooltips_new (); - -@@ -626,8 +499,9 @@ create_panel_buttons (IntlClockUI *this) - gtk_button_set_relief (GTK_BUTTON (priv->panel_button), - GTK_RELIEF_NONE); - -- gtk_container_add (GTK_CONTAINER (priv->panel_button), -- priv->panel_label); -+ gtk_container_add (GTK_CONTAINER (priv->panel_button), box); -+ gtk_container_add (GTK_CONTAINER (box), priv->panel_weather_icon); -+ gtk_container_add (GTK_CONTAINER (box), priv->panel_label); - - g_signal_connect ( - G_OBJECT (priv->panel_button), "clicked", -@@ -655,12 +529,13 @@ create_panel_buttons (IntlClockUI *this) - ); - - gtk_widget_show (priv->panel_label); -+ gtk_widget_show (priv->panel_weather_icon); -+ gtk_widget_show (box); - - gtk_box_pack_start (GTK_BOX (priv->panel_box), priv->panel_button, - FALSE, FALSE, 0); - -- gtk_container_add (GTK_CONTAINER (priv->panel_applet), -- priv->panel_box); -+ gtk_container_add (GTK_CONTAINER (priv->panel_applet), priv->panel_box); - - gtk_widget_show_all (priv->panel_box); - } -@@ -671,10 +546,16 @@ intlclock_ui_change_orient (PanelApplet *applet, - IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -- -- if (GTK_IS_WIDGET (priv->panel_box)) -- gtk_widget_destroy (priv->panel_box); -+ GdkPixbuf *pixbuf = NULL; -+ -+ if (GTK_IS_WIDGET (priv->panel_box)) { -+ pixbuf = g_object_ref (gtk_image_get_pixbuf (GTK_IMAGE (priv->panel_weather_icon))); -+ gtk_widget_destroy (priv->panel_box); -+ } - create_panel_buttons (this); -+ intlclock_ui_update_weather_icon (this, pixbuf); -+ if (pixbuf) -+ g_object_unref (pixbuf); - } - - static void -@@ -706,6 +587,16 @@ create_panel_button_popup (IntlClockUI *this) - "hidden", "1", - NULL); - } -+ -+ if (!can_set_system_time ()) { -+ popup_component = panel_applet_get_popup_component -+ (PANEL_APPLET (priv->panel_applet)); -+ -+ bonobo_ui_component_set_prop (popup_component, -+ "/commands/IntlClockConfig", -+ "sensitive", "0", -+ NULL); -+ } - } - - static void -@@ -714,7 +605,7 @@ create_events_window (IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - - priv->events_window = -- GTK_WIDGET (intlclock_events_popup_new (priv->clock, priv->panel_applet)); -+ GTK_WIDGET (intlclock_events_popup_new (priv->clock, priv->panel_applet, this)); - - g_signal_connect (G_OBJECT (priv->events_window), "size-allocate", - G_CALLBACK (intlclock_events_window_size_allocate_cb), this); -@@ -723,41 +614,32 @@ create_events_window (IntlClockUI *this) - } - - static void --create_clock_window (IntlClockUI *this) -+add_to_group (GtkWidget *child, gpointer data) - { -- IntlClockUIPrivate *priv = PRIVATE (this); -- GtkSettings *settings; -- GtkStyle *style; -+ GtkSizeGroup *group = data; - -- priv->clock_vbox = intlclock_events_popup_get_clock_container -- (INTLCLOCK_EVENTS_POPUP (priv->events_window)); -- gtk_widget_show (priv->clock_vbox); -+ gtk_size_group_add_widget (group, child); - } - - static void --create_main_section (IntlClockUI *this) -+create_clock_window (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -- IntlClockLocation *loc; -- GtkWidget *header, *subheader; -- GtkWidget *prefs_button; -- GtkWidget *prefs_button_box; -- -- if (!priv->main_section) { -- priv->main_section = gtk_vbox_new (FALSE, 6); -- gtk_container_set_border_width -- (GTK_CONTAINER (priv->main_section), -- MAIN_SECTION_PADDING); -- gtk_box_pack_end (GTK_BOX (priv->clock_vbox), -- priv->main_section, FALSE, FALSE, 0); -+ GtkWidget *clock_container; - -- } else { -- gtk_container_foreach (GTK_CONTAINER (priv->main_section), -- (GtkCallback)gtk_widget_destroy, -- NULL); -- } -+ clock_container = intlclock_events_popup_get_clock_container -+ (INTLCLOCK_EVENTS_POPUP (priv->events_window)); -+ gtk_widget_show (clock_container); -+ -+ priv->clock_vbox = gtk_vbox_new (FALSE, 6); -+ gtk_container_add (GTK_CONTAINER (clock_container), priv->clock_vbox); - -- gtk_widget_show_all (priv->main_section); -+ priv->clock_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); -+ gtk_size_group_set_ignore_hidden (priv->clock_group, FALSE); -+ -+ gtk_container_foreach (GTK_CONTAINER (clock_container), -+ (GtkCallback)add_to_group, -+ priv->clock_group); - } - - static gint -@@ -824,7 +706,6 @@ create_cities_section (IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - GList *node; - IntlClockLocationTile *city; -- GtkWidget *header, *subheader, *image;; - GList *cities; - - if (priv->cities_section) { -@@ -832,12 +713,8 @@ create_cities_section (IntlClockUI *this) - priv->cities_section = NULL; - } - -- if (!priv->show_locations) { -- return; -- } -- - priv->cities_section = gtk_vbox_new (FALSE, 6); -- gtk_container_set_border_width (GTK_CONTAINER (priv->cities_section), 8); -+ gtk_container_set_border_width (GTK_CONTAINER (priv->cities_section), 0); - - cities = intlclock_get_locations (priv->clock); - if (g_list_length (cities) == 0) { -@@ -884,10 +761,6 @@ create_map_section (IntlClockUI *this) - priv->map_widget = NULL; - } - -- if (!priv->show_map) { -- return; -- } -- - map = intlclock_map_new (priv->clock); - - priv->map_section = gtk_alignment_new (0, 0, 1, 1); -@@ -895,11 +768,10 @@ create_map_section (IntlClockUI *this) - - gtk_container_add (GTK_CONTAINER (priv->map_section), priv->map_widget); - -- gtk_box_pack_start (GTK_BOX (priv->clock_vbox), -- priv->map_section, FALSE, FALSE, 0); -- - gtk_alignment_set_padding (GTK_ALIGNMENT (priv->map_section), - 1, 1, 1, 1); -+ gtk_box_pack_start (GTK_BOX (priv->clock_vbox), -+ priv->map_section, FALSE, FALSE, 0); - - gtk_widget_show (priv->map_widget); - gtk_widget_show (priv->map_section); -@@ -927,7 +799,6 @@ create_cities_store (IntlClockUI *this) - - while (list) { - IntlClockLocation *loc = INTLCLOCK_LOCATION (list->data); -- gfloat latitude, longitude; - - gtk_list_store_append (priv->cities_store, &iter); - gtk_list_store_set (priv->cities_store, &iter, -@@ -953,12 +824,16 @@ intlclock_prefs_hide (GtkWidget *widget, IntlClockUI *this) - IntlClockUIPrivate *priv = PRIVATE (this); - GtkWidget *tree; - -+ intlclock_edit_hide (widget, this); -+ - gtk_widget_hide (priv->prefs_window); - - tree = glade_xml_get_widget (priv->glade_xml, "cities_list"); - - gtk_tree_selection_unselect_all - (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree))); -+ -+ intlclock_ui_reset_timeout (this); - } - - static gboolean -@@ -974,8 +849,6 @@ intlclock_edit_clear (GtkWidget *widget, IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); - -- GtkWidget *edit_window = glade_xml_get_widget (priv->glade_xml, "edit-location-window"); -- - GtkWidget *zone_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-timezone-combo"); - GtkWidget *name_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-name-entry"); - -@@ -1003,6 +876,8 @@ intlclock_edit_hide (GtkWidget *widget, IntlClockUI *this) - - GtkWidget *edit_window = glade_xml_get_widget (priv->glade_xml, "edit-location-window"); - -+ intlclock_find_hide (widget, this); -+ - gtk_widget_hide (edit_window); - - intlclock_edit_clear (widget, this); -@@ -1016,6 +891,23 @@ intlclock_edit_hide_event (GtkWidget *widget, GdkEvent *event, IntlClockUI *this - return TRUE; - } - -+static void -+intlclock_find_hide (GtkWidget *widget, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ -+ GtkWidget *find_window = glade_xml_get_widget (priv->glade_xml, "find-location-window"); -+ -+ gtk_widget_hide (find_window); -+} -+ -+static gboolean -+intlclock_find_hide_event (GtkWidget *widget, GdkEvent *event, IntlClockUI *this) -+{ -+ intlclock_find_hide (widget, this); -+ -+ return TRUE; -+} - - static void - set_12hr_format_radio_cb (GtkWidget *widget, IntlClockUI *this) -@@ -1057,28 +949,6 @@ set_seconds_check_cb (GtkWidget *widget, IntlClockUI *this) - } - - static void --set_locations_check_cb (GtkWidget *widget, IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- panel_applet_gconf_set_bool (PANEL_APPLET (priv->panel_applet), -- KEY_SHOW_LOCATIONS, -- GTK_TOGGLE_BUTTON (widget)->active, -- NULL); --} -- --static void --set_map_check_cb (GtkWidget *widget, IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- panel_applet_gconf_set_bool (PANEL_APPLET (priv->panel_applet), -- KEY_SHOW_MAP, -- GTK_TOGGLE_BUTTON (widget)->active, -- NULL); --} -- --static void - fill_prefs_window (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -@@ -1087,6 +957,9 @@ fill_prefs_window (IntlClockUI *this) - GtkCellRenderer *renderer; - GtkTreeViewColumn *col; - -+ time_t now_t; -+ struct tm now; -+ - /* Set the 12 hour / 24 hour widget */ - widget = glade_xml_get_widget (priv->glade_xml, "12hr_radio"); - g_signal_connect (widget, "toggled", -@@ -1109,18 +982,6 @@ fill_prefs_window (IntlClockUI *this) - g_signal_connect (widget, "toggled", G_CALLBACK (set_seconds_check_cb), - this); - -- /* Set the "Show Locations" checkbox */ -- widget = glade_xml_get_widget (priv->glade_xml, "show_locations_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), priv->show_locations); -- g_signal_connect (widget, "toggled", G_CALLBACK (set_locations_check_cb), -- this); -- -- /* Set the "Show Map" checkbox */ -- widget = glade_xml_get_widget (priv->glade_xml, "show_map_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), priv->show_map); -- g_signal_connect (widget, "toggled", G_CALLBACK (set_map_check_cb), -- this); -- - /* Fill the Cities list */ - widget = glade_xml_get_widget (priv->glade_xml, "cities_list"); - -@@ -1136,6 +997,15 @@ fill_prefs_window (IntlClockUI *this) - - gtk_tree_view_set_model (GTK_TREE_VIEW (widget), - GTK_TREE_MODEL (priv->cities_store)); -+ -+ /* Fill the time settings */ -+ tzset (); -+ time (&now_t); -+ localtime_r (&now_t, &now); -+ -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->seconds_spin), now.tm_sec); -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->minutes_spin), now.tm_min); -+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->hours_spin), now.tm_hour); - } - - static gint -@@ -1150,19 +1020,334 @@ sort_zoneinfo_by_l10n_name (gconstpointer a, gconstpointer b) - return strcmp (name_a, name_b); - } - -+static void -+intlclock_prefs_locations_changed (GtkTreeSelection *selection, -+ IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gint n; -+ -+ n = gtk_tree_selection_count_selected_rows (selection); -+ gtk_widget_set_sensitive (priv->prefs_location_edit_button, n > 0); -+ gtk_widget_set_sensitive (priv->prefs_location_remove_button, n > 0); -+} -+ - static void --display_prefs_window (IntlClockUI *this) -+location_tree_selection_changed (GtkTreeSelection *selection, -+ IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ GtkTreeModel *model; -+ GtkTreeIter iter; -+ WeatherLocation *loc = NULL; -+ gboolean can_save = FALSE; -+ -+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) { -+ gtk_tree_model_get (model, &iter, GWEATHER_XML_COL_POINTER, &loc, -1); -+ if (loc != NULL) -+ can_save = TRUE; -+ } -+ -+ gtk_widget_set_sensitive (priv->find_location_ok_button, can_save); -+} -+ -+static void -+wrap_cb (GtkSpinButton *spin, -+ IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gdouble value; -+ gdouble min, max; -+ GtkSpinType direction; -+ -+ value = gtk_spin_button_get_value (spin); -+ gtk_spin_button_get_range (spin, &min, &max); -+ -+ if (value == min) -+ direction = GTK_SPIN_STEP_FORWARD; -+ else -+ direction = GTK_SPIN_STEP_BACKWARD; -+ -+ if (spin == (GtkSpinButton *)priv->seconds_spin) -+ gtk_spin_button_spin (GTK_SPIN_BUTTON (priv->minutes_spin), -+ direction, 1.0); -+ else if (spin == (GtkSpinButton *)priv->minutes_spin) -+ gtk_spin_button_spin (GTK_SPIN_BUTTON (priv->hours_spin), -+ direction, 1.0); -+ else { -+ guint year, month, day; -+ GDate *date; -+ -+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), -+ &year, &month, &day); -+ -+ date = g_date_new_dmy (day, month + 1, year); -+ -+ if (direction == GTK_SPIN_STEP_FORWARD) -+ g_date_add_days (date, 1); -+ else -+ g_date_subtract_days (date, 1); -+ -+ year = g_date_get_year (date); -+ month = g_date_get_month (date) - 1; -+ day = g_date_get_day (date); -+ -+ gtk_calendar_select_month (GTK_CALENDAR (priv->calendar), -+ month, year); -+ gtk_calendar_select_day (GTK_CALENDAR (priv->calendar), -+ day); -+ -+ g_date_free (date); -+ } -+} -+ -+static void -+update_set_time_button (IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ gint can_set; -+ -+ can_set = can_set_system_time (); -+ -+ if (priv->time_settings_button) -+ gtk_widget_set_sensitive (priv->time_settings_button, can_set != 0); -+ if (priv->set_time_button) -+ gtk_button_set_label (GTK_BUTTON (priv->set_time_button), -+ can_set == 1 ? -+ _("Set System Time...") : -+ _("Set System Time")); -+} -+ -+static void -+set_time_callback (IntlClockUI *this, GError *error) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ GtkWidget *window; -+ GtkWidget *dialog; -+ -+ if (error) { -+ dialog = gtk_message_dialog_new (NULL, -+ 0, -+ GTK_MESSAGE_ERROR, -+ GTK_BUTTONS_OK, -+ _("Failed to set the system time")); -+ -+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error->message); -+ g_signal_connect (dialog, "response", -+ G_CALLBACK (gtk_widget_destroy), NULL); -+ gtk_window_present (GTK_WINDOW (dialog)); -+ -+ g_error_free (error); -+ } -+ else -+ update_set_time_button (this); -+ -+ window = glade_xml_get_widget (priv->glade_xml, "set-time-window"); -+ gtk_widget_hide (window); -+} -+ -+static void -+set_time (GtkWidget *widget, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ struct tm t; -+ gint64 time; -+ guint year, month, day; -+ -+ t.tm_sec = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->seconds_spin)); -+ t.tm_min = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->minutes_spin)); -+ t.tm_hour = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->hours_spin)); -+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day); -+ t.tm_year = year - 1900; -+ t.tm_mon = month; -+ t.tm_mday = day; -+ -+ time = mktime (&t); -+ -+ set_system_time_async (time, (GFunc)set_time_callback, this, NULL); -+} -+ -+static gboolean -+find_location (GtkTreeModel *model, -+ GtkTreeIter *iter, -+ const gchar *location, -+ gboolean go_parent) -+{ -+ GtkTreeIter iter_child; -+ GtkTreeIter iter_parent; -+ gchar *aux_loc; -+ gboolean valid; -+ int len; -+ -+ len = strlen (location); -+ -+ if (len <= 0) { -+ return FALSE; -+ } -+ -+ do { -+ gtk_tree_model_get (model, iter, GWEATHER_XML_COL_LOC, &aux_loc, -1); -+ -+ if (g_ascii_strncasecmp (aux_loc, location, len) == 0) { -+ g_free (aux_loc); -+ return TRUE; -+ } -+ -+ if (gtk_tree_model_iter_has_child (model, iter)) { -+ gtk_tree_model_iter_nth_child (model, &iter_child, iter, 0); -+ if (find_location (model, &iter_child, location, FALSE)) { -+ /* Manual copying of the iter */ -+ iter->stamp = iter_child.stamp; -+ iter->user_data = iter_child.user_data; -+ iter->user_data2 = iter_child.user_data2; -+ iter->user_data3 = iter_child.user_data3; -+ -+ g_free (aux_loc); -+ -+ return TRUE; -+ } -+ } -+ -+ g_free (aux_loc); -+ -+ valid = gtk_tree_model_iter_next (model, iter); -+ } while (valid); -+ -+ if (go_parent) { -+ iter_parent = *iter; -+ while (gtk_tree_model_iter_parent (model, iter, &iter_parent)) { -+ if (gtk_tree_model_iter_next (model, iter)) -+ return find_location (model, iter, location, TRUE); -+ iter_parent = *iter; -+ } -+ } -+ -+ return FALSE; -+} -+ -+static void -+find_next_location (GtkButton *button, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ GtkTreeView *tree; -+ GtkTreeModel *model; -+ GtkEntry *entry; -+ GtkTreeSelection *selection; -+ GtkTreeIter iter; -+ GtkTreeIter iter_parent; -+ GtkTreePath *path; -+ const gchar *location; -+ -+ tree = GTK_TREE_VIEW (priv->location_tree); -+ model = gtk_tree_view_get_model (tree); -+ entry = GTK_ENTRY (priv->find_location_entry); -+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); -+ -+ if (gtk_tree_selection_count_selected_rows (selection) >= 1) { -+ gtk_tree_selection_get_selected (selection, &model, &iter); -+ /* Select next or select parent */ -+ if (!gtk_tree_model_iter_next (model, &iter)) { -+ iter_parent = iter; -+ if (!gtk_tree_model_iter_parent (model, &iter, &iter_parent) || -+ !gtk_tree_model_iter_next (model, &iter)) -+ gtk_tree_model_get_iter_first (model, &iter); -+ } -+ } -+ else { -+ gtk_tree_model_get_iter_first (model, &iter); -+ } -+ location = gtk_entry_get_text (entry); -+ -+ if (find_location (model, &iter, location, TRUE)) { -+ gtk_widget_set_sensitive (priv->find_next_location_button, TRUE); -+ path = gtk_tree_model_get_path (model, &iter); -+ gtk_tree_view_expand_to_path (tree, path); -+ gtk_tree_selection_select_path (selection, path); -+ gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0); -+ -+ gtk_tree_path_free (path); -+ } -+ else { -+ gtk_widget_set_sensitive (priv->find_next_location_button, FALSE); -+ } -+} -+ -+static void -+find_entry_changed (GtkEditable *entry, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ GtkTreeView *tree; -+ GtkTreeModel *model; -+ GtkTreeSelection *selection; -+ GtkTreeIter iter; -+ GtkTreePath *path; -+ const gchar *location; -+ -+ tree = GTK_TREE_VIEW (priv->location_tree); -+ model = gtk_tree_view_get_model (tree); -+ -+ selection = gtk_tree_view_get_selection (tree); -+ gtk_tree_model_get_iter_first (model, &iter); -+ -+ location = gtk_entry_get_text (GTK_ENTRY (entry)); -+ if (find_location (model, &iter, location, TRUE)) { -+ gtk_widget_set_sensitive (priv->find_next_location_button, TRUE); -+ path = gtk_tree_model_get_path (model, &iter); -+ gtk_tree_view_expand_to_path (tree, path); -+ gtk_tree_selection_select_iter (selection, &iter); -+ gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0); -+ gtk_tree_path_free (path); -+ } -+ else { -+ gtk_widget_set_sensitive (priv->find_next_location_button, FALSE); -+ } -+} -+ -+static void -+cancel_time_settings (GtkWidget *button, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ -+ gtk_widget_hide (priv->set_time_window); -+ -+ intlclock_ui_reset_timeout (this); -+} -+ -+static void -+run_time_settings (GtkWidget *button, IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (this); -+ GtkWidget *cancel_set_time_button; -+ -+ if (!priv->set_time_button) { -+ priv->set_time_button = glade_xml_get_widget (priv->glade_xml, "set-time-button"); -+ g_signal_connect (priv->set_time_button, "clicked", G_CALLBACK (set_time), this); -+ -+ cancel_set_time_button = glade_xml_get_widget (priv->glade_xml, "cancel-set-time-button"); -+ g_signal_connect (cancel_set_time_button, "clicked", G_CALLBACK (cancel_time_settings), this); -+ -+ priv->current_time_label = glade_xml_get_widget (priv->glade_xml, "current_time_label"); -+ } -+ -+ priv->set_time_window = glade_xml_get_widget (priv->glade_xml, "set-time-window"); -+ gtk_window_present (GTK_WINDOW (priv->set_time_window)); -+ -+ intlclock_ui_reset_timeout (this); -+} -+ -+static void -+display_prefs_window (IntlClockUI *this, gboolean locations) - { - IntlClockUIPrivate *priv = PRIVATE (this); - GtkWidget *edit_window; -- GtkWidget *prefs_window; - GtkWidget *prefs_close_button; -- GtkWidget *prefs_settings_button; - GtkWidget *edit_cancel_button; - GtkWidget *edit_ok_button; - GtkWidget *zone_combo; -- -- GtkWidget *tmp_button; -+ GtkWidget *find_window; -+ GtkWidget *find_location_button; -+ GtkWidget *find_location_cancel_button; -+ GtkTreeSelection *selection; - - if (!priv->prefs_window) { - priv->prefs_window = -@@ -1170,43 +1355,42 @@ display_prefs_window (IntlClockUI *this) - - prefs_close_button = - glade_xml_get_widget (priv->glade_xml, "prefs-close-button"); -- -- prefs_settings_button = -- glade_xml_get_widget (priv->glade_xml, "prefs-time-settings-button"); -- - priv->prefs_locations = - GTK_TREE_VIEW (glade_xml_get_widget (priv->glade_xml, "cities_list")); - -+ selection = gtk_tree_view_get_selection (priv->prefs_locations); -+ g_signal_connect (G_OBJECT (selection), "changed", -+ G_CALLBACK (intlclock_prefs_locations_changed), this); -+ - g_signal_connect (G_OBJECT (priv->prefs_window), "delete_event", - G_CALLBACK (intlclock_prefs_hide_event), this); - - g_signal_connect (G_OBJECT (prefs_close_button), "clicked", - G_CALLBACK (intlclock_prefs_hide), this); - -- g_signal_connect (G_OBJECT (prefs_settings_button), "clicked", -- G_CALLBACK (run_time_configuration_cb), this); -- -- tmp_button = -+ priv->prefs_location_remove_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-remove-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_remove_button), "clicked", - G_CALLBACK (run_prefs_locations_remove), this); -- -- tmp_button = -+ -+ priv->prefs_location_add_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-add-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_add_button), "clicked", - G_CALLBACK (run_prefs_locations_add), this); - -- tmp_button = -+ priv->prefs_location_edit_button = - glade_xml_get_widget (priv->glade_xml, "prefs-locations-edit-button"); - -- g_signal_connect (G_OBJECT (tmp_button), "clicked", -+ g_signal_connect (G_OBJECT (priv->prefs_location_edit_button), "clicked", - G_CALLBACK (run_prefs_locations_edit), this); - - edit_window = glade_xml_get_widget (priv->glade_xml, - "edit-location-window"); - -+ gtk_window_set_transient_for (GTK_WINDOW (edit_window), -+ GTK_WINDOW (priv->prefs_window)); - - g_signal_connect (G_OBJECT (edit_window), "delete_event", - G_CALLBACK (intlclock_edit_hide_event), this); -@@ -1219,7 +1403,35 @@ display_prefs_window (IntlClockUI *this) - - zone_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-timezone-combo"); - -- g_signal_connect (G_OBJECT (zone_combo), "changed", -+ find_window = glade_xml_get_widget (priv->glade_xml, -+ "find-location-window"); -+ -+ gtk_window_set_transient_for (GTK_WINDOW (find_window), -+ GTK_WINDOW (edit_window)); -+ -+ g_signal_connect (G_OBJECT (find_window), "delete_event", -+ G_CALLBACK (intlclock_find_hide_event), this); -+ -+ find_location_button = -+ glade_xml_get_widget (priv->glade_xml, "find-location-button"); -+ -+ priv->find_location_ok_button = -+ glade_xml_get_widget (priv->glade_xml, "find-location-ok-button"); -+ -+ find_location_cancel_button = -+ glade_xml_get_widget (priv->glade_xml, "find-location-cancel-button"); -+ -+ priv->find_next_location_button = -+ glade_xml_get_widget (priv->glade_xml, "find-next-location-button"); -+ -+ priv->find_location_entry = -+ glade_xml_get_widget (priv->glade_xml, "find-location-entry"); -+ -+ priv->location_tree = -+ glade_xml_get_widget (priv->glade_xml, "find-location-tree"); -+ -+ priv->zone_combo_changed = -+ g_signal_connect (G_OBJECT (zone_combo), "changed", - G_CALLBACK (zone_combo_changed), this); - - -@@ -1229,16 +1441,72 @@ display_prefs_window (IntlClockUI *this) - g_signal_connect (G_OBJECT (edit_ok_button), "clicked", - G_CALLBACK (run_prefs_edit_save), this); - -+ g_signal_connect (find_location_button, "clicked", -+ G_CALLBACK (run_find_location), this); -+ -+ g_signal_connect (G_OBJECT (find_location_cancel_button), "clicked", -+ G_CALLBACK (intlclock_find_hide), this); -+ -+ g_signal_connect (G_OBJECT (priv->find_location_ok_button), "clicked", -+ G_CALLBACK (run_find_location_save), this); -+ -+ g_signal_connect (G_OBJECT (priv->find_next_location_button), "clicked", -+ G_CALLBACK (find_next_location), this); -+ -+ g_signal_connect (G_OBJECT (priv->find_location_entry), "changed", -+ G_CALLBACK (find_entry_changed), this); -+ -+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->location_tree)); -+ g_signal_connect (selection, "changed", -+ G_CALLBACK (location_tree_selection_changed), this); -+ - /* We have to put an item in the combo box in the glade file - to get the simpler, string-only store. Here we remove that - item. */ - gtk_combo_box_remove_text (GTK_COMBO_BOX (zone_combo), 0); - -+ /* Set up the time setting section */ -+ -+ priv->time_settings_button = glade_xml_get_widget (priv->glade_xml, "time-settings-button"); -+ g_signal_connect (priv->time_settings_button, "clicked", G_CALLBACK (run_time_settings), this); -+ -+ priv->calendar = glade_xml_get_widget (priv->glade_xml, "calendar"); -+ priv->hours_spin = glade_xml_get_widget (priv->glade_xml, "hours_spin"); -+ priv->minutes_spin = glade_xml_get_widget (priv->glade_xml, "minutes_spin"); -+ priv->seconds_spin = glade_xml_get_widget (priv->glade_xml, "seconds_spin"); -+ -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->hours_spin), 2); -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->minutes_spin), 2); -+ gtk_entry_set_width_chars (GTK_ENTRY (priv->seconds_spin), 2); -+ -+ gtk_entry_set_alignment (GTK_ENTRY (priv->hours_spin), 1.0); -+ gtk_entry_set_alignment (GTK_ENTRY (priv->minutes_spin), 1.0); -+ gtk_entry_set_alignment (GTK_ENTRY (priv->seconds_spin), 1.0); -+ g_signal_connect (priv->seconds_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ g_signal_connect (priv->minutes_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ g_signal_connect (priv->hours_spin, "wrapped", G_CALLBACK (wrap_cb), this); -+ - /* fill it with the current preferences */ - fill_prefs_window (this); - } - -+ if (locations) { -+ GtkWidget *notebook = -+ glade_xml_get_widget (priv->glade_xml, "notebook"); -+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1); -+ } -+ -+ update_set_time_button (this); -+ - gtk_window_present (GTK_WINDOW (priv->prefs_window)); -+ -+ intlclock_ui_reset_timeout (this); -+} -+ -+void -+intlclock_ui_edit_locations (IntlClockUI *ui) -+{ -+ display_prefs_window (ui, TRUE); - } - - static void -@@ -1306,16 +1574,11 @@ intlclock_ui_new (IntlClock *clock, PanelApplet *applet) - create_events_window (this); - create_clock_window (this); - create_cities_store (this); -- -- if (priv->show_locations) { -- create_cities_section (this); -- } -- -- if (priv->show_map) { -- create_map_section (this); -- intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); -- } -- -+ create_cities_section (this); -+ create_map_section (this); -+ -+ intlclock_map_refresh (INTLCLOCK_MAP (priv->map_widget)); -+ - intlclock_ui_reset_timeout (this); - - return this; -@@ -1365,9 +1628,6 @@ intlclock_ui_init (IntlClockUI *this) - - priv->cities_store = NULL; - -- priv->show_locations = TRUE; -- priv->show_map = TRUE; -- - priv->prefs_window = NULL; - - priv->format_12hr = TRUE; -@@ -1547,56 +1807,6 @@ gconf_show_week_changed (GConfClient *client, - } - - static void --gconf_show_locations_changed (GConfClient *client, -- guint cnxn_id, -- GConfEntry *entry, -- IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- GtkWidget *widget; -- -- gboolean value; -- -- if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -- return; -- -- value = gconf_value_get_bool (entry->value); -- -- priv->show_locations = (value != 0); -- -- widget = glade_xml_get_widget (priv->glade_xml, "show_locations_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), -- priv->show_locations); -- -- create_cities_section (this); --} -- --static void --gconf_show_map_changed (GConfClient *client, -- guint cnxn_id, -- GConfEntry *entry, -- IntlClockUI *this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- GtkWidget *widget; -- -- gboolean value; -- -- if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) -- return; -- -- value = gconf_value_get_bool (entry->value); -- -- priv->show_map = (value != 0); -- -- widget = glade_xml_get_widget (priv->glade_xml, "show_map_check"); -- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), -- priv->show_map); -- -- create_map_section (this); --} -- --static void - location_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, -@@ -1614,6 +1824,7 @@ location_start_element (GMarkupParseContext *context, - gchar *timezone = NULL; - gfloat latitude = 0.0; - gfloat longitude = 0.0; -+ gchar *code = NULL; - - int index = 0; - -@@ -1633,6 +1844,8 @@ location_start_element (GMarkupParseContext *context, - sscanf (attribute_values[index], "%f", &latitude); - } else if (strcmp (att_name, "longitude") == 0) { - sscanf (attribute_values[index], "%f", &longitude); -+ } else if (strcmp (att_name, "code") == 0) { -+ code = (gchar *)attribute_values[index]; - } - } - -@@ -1642,7 +1855,7 @@ location_start_element (GMarkupParseContext *context, - return; - } - -- loc = intlclock_location_new (name, timezone, latitude, longitude); -+ loc = intlclock_location_new (name, timezone, latitude, longitude, code); - - *(GList **)user_data = g_list_append (ret, loc); - } -@@ -1713,10 +1926,11 @@ gconf_loc_to_string (IntlClockLocation *loc) - prev_locale = setlocale (LC_NUMERIC, "POSIX"); - - ret = g_markup_printf_escaped -- ("<location name=\"%s\" timezone=\"%s\" latitude=\"%f\" longitude=\"%f\" />", -+ ("<location name=\"%s\" timezone=\"%s\" latitude=\"%f\" longitude=\"%f\" code=\"%s\"/>", - intlclock_location_get_name (loc), - intlclock_location_get_timezone (loc), -- latitude, longitude); -+ latitude, longitude, -+ intlclock_location_get_weather_code (loc)); - - setlocale (LC_NUMERIC, ""); - -@@ -1727,7 +1941,7 @@ static void - intlclock_ui_save_cities_store (IntlClockUI *this) - { - IntlClockUIPrivate *priv = PRIVATE (this); -- IntlClockLocation *loc, *cur; -+ IntlClockLocation *loc; - GList *node = intlclock_get_locations (priv->clock); - - GSList *root = NULL; -@@ -1803,24 +2017,6 @@ setup_gconf (IntlClockUI *this) - g_free (key); - - key = panel_applet_gconf_get_full_key -- (PANEL_APPLET (priv->panel_applet), KEY_SHOW_LOCATIONS); -- priv->listeners [index++] = -- gconf_client_notify_add ( -- client, key, -- (GConfClientNotifyFunc) gconf_show_locations_changed, -- this, NULL, NULL); -- g_free (key); -- -- key = panel_applet_gconf_get_full_key -- (PANEL_APPLET (priv->panel_applet), KEY_SHOW_MAP); -- priv->listeners [index++] = -- gconf_client_notify_add ( -- client, key, -- (GConfClientNotifyFunc) gconf_show_map_changed, -- this, NULL, NULL); -- g_free (key); -- -- key = panel_applet_gconf_get_full_key - (PANEL_APPLET (priv->panel_applet), KEY_CITIES); - priv->listeners [index++] = - gconf_client_notify_add ( -@@ -1868,14 +2064,6 @@ load_gconf_settings (IntlClockUI *this) - panel_applet_gconf_get_bool (priv->panel_applet, - KEY_SHOW_WEEK, NULL); - -- priv->show_locations = -- panel_applet_gconf_get_bool (priv->panel_applet, -- KEY_SHOW_LOCATIONS, NULL); -- -- priv->show_map = -- panel_applet_gconf_get_bool (priv->panel_applet, -- KEY_SHOW_MAP, NULL); -- - values = panel_applet_gconf_get_list (priv->panel_applet, KEY_CITIES, - GCONF_VALUE_STRING, NULL); - -@@ -1892,92 +2080,72 @@ static void bonobo_display_properties_dialog (BonoboUIComponent *uic, - IntlClockUI *this, - const gchar *verbname) - { -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- display_prefs_window (this); -+ display_prefs_window (this, FALSE); - } - --static void bonobo_run_time_configuration (BonoboUIComponent *uic, -- IntlClockUI *this, -- const gchar *verbname) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- run_time_configuration (this); --} -- --static void display_prefs_window_cb (GtkButton *button, gpointer this) -+static void -+copy_time (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const gchar *verbname) - { - IntlClockUIPrivate *priv = PRIVATE (this); -+ gchar *utf8; -+ time_t now_t; -+ struct tm now; - -- display_prefs_window (this); --} -+ tzset (); -+ time (&now_t); -+ localtime_r (&now_t, &now); - --static void --run_time_configuration_cb (GtkButton *button, gpointer this) --{ -- IntlClockUIPrivate *priv = PRIVATE (this); -+ utf8 = intlclock_format_time (priv->clock, &now, FALSE, -+ priv->format_12hr, -+ priv->format_show_seconds, -+ FALSE, FALSE, NULL, FALSE); -+ -+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), -+ utf8, -1); -+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), -+ utf8, -1); - -- run_time_configuration (this); -+ g_free (utf8); - } - - static void --run_time_configuration (IntlClockUI *this) -+copy_date (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const gchar *verbname) - { -- IntlClockUIPrivate *priv = PRIVATE (this); -- -- GtkWidget *dialog; -- GError *err; -- char **argv; -- char *path; -+ char string[256]; -+ char *utf8, *loc; - -- GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (priv->events_window)); -- gchar *tool = "/opt/gnome/bin/gnomesu /sbin/yast2 timezone"; -- -- if (!tool || tool[0] == '\0') -- return; -- -- if (!g_shell_parse_argv (tool, NULL, &argv, NULL)) -- return; -- -- if (!(path = g_find_program_in_path (argv [0]))) { -- g_strfreev (argv); -- return; -- } -- -- g_free (path); -- -- err = NULL; -- if (gdk_spawn_on_screen (screen, -- NULL, -- argv, -- NULL, -- G_SPAWN_SEARCH_PATH, -- NULL, -- NULL, -- NULL, -- &err)) { -- g_strfreev (argv); -- return; -- } -- -- g_strfreev (argv); -+ time_t now_t; -+ struct tm now; - -- dialog = gtk_message_dialog_new (NULL, -- GTK_DIALOG_DESTROY_WITH_PARENT, -- GTK_MESSAGE_ERROR, -- GTK_BUTTONS_OK, -- _("Failed to launch time configuration tool: %s"), -- err->message); -- g_error_free (err); -+ tzset (); -+ time (&now_t); -+ localtime_r (&now_t, &now); - -- g_signal_connect (dialog, "response", -- G_CALLBACK (gtk_widget_destroy), NULL); -+ loc = g_locale_from_utf8 (_("%A, %B %d %Y"), -1, NULL, NULL, NULL); -+ if (!loc) -+ strcpy (string, "???"); -+ else if (strftime (string, sizeof (string), loc, &now) <= 0) -+ strcpy (string, "???"); -+ g_free (loc); - -- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); -- gtk_window_set_screen (GTK_WINDOW (dialog), screen); -+ utf8 = g_locale_to_utf8 (string, -1, NULL, NULL, NULL); -+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), -+ utf8, -1); -+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), -+ utf8, -1); -+ g_free (utf8); -+} - -- gtk_widget_show_all (dialog); -+static void -+config_date (BonoboUIComponent *uic, -+ IntlClockUI *this, -+ const char *verbname) -+{ -+ run_time_settings (NULL, this); - } - - static void -@@ -2000,6 +2168,46 @@ remove_tree_row (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, - } - - static void -+update_coords (IntlClockUI *this, gboolean valid, gfloat lat, gfloat lon) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ GtkWidget *lat_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-latitude-entry"); -+ GtkWidget *lon_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-longitude-entry"); -+ GtkWidget *lat_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-latitude-combo"); -+ GtkWidget *lon_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-longitude-combo"); -+ gchar *tmp; -+ -+ if (!valid) { -+ gtk_entry_set_text (GTK_ENTRY (lat_entry), ""); -+ gtk_entry_set_text (GTK_ENTRY (lon_entry), ""); -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lat_combo), -1); -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lon_combo), -1); -+ -+ return; -+ } -+ -+ tmp = g_strdup_printf ("%f", fabsf(lat)); -+ gtk_entry_set_text (GTK_ENTRY (lat_entry), tmp); -+ g_free (tmp); -+ -+ if (lat > 0) { -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lat_combo), 0); -+ } else { -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lat_combo), 1); -+ } -+ -+ tmp = g_strdup_printf ("%f", fabsf(lon)); -+ gtk_entry_set_text (GTK_ENTRY (lon_entry), tmp); -+ g_free (tmp); -+ -+ if (lon > 0) { -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lon_combo), 0); -+ } else { -+ gtk_combo_box_set_active (GTK_COMBO_BOX (lon_combo), 1); -+ } -+} -+ -+static void - zone_combo_changed (GtkComboBox *widget, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -@@ -2009,17 +2217,12 @@ zone_combo_changed (GtkComboBox *widget, gpointer this) - gchar *city = NULL; - gfloat lat = 0; - gfloat lon = 0; -- gchar *tmp; -+ GtkTreeModel *model; -+ gchar *name; - - GtkWidget *name_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-name-entry"); -- -- GtkWidget *lat_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-latitude-entry"); -- -- GtkWidget *lon_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-longitude-entry"); -- -- GtkWidget *lat_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-latitude-combo"); -- -- GtkWidget *lon_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-longitude-combo"); -+ GtkWidget *edit_window = glade_xml_get_widget (priv->glade_xml, "edit-location-window"); -+ gchar *weather_code; - - IntlClockCountry *country; - IntlClockZoneInfo *info; -@@ -2028,6 +2231,14 @@ zone_combo_changed (GtkComboBox *widget, gpointer this) - return; - } - -+ /* only fill in other field if name is not set yet, to -+ * allow correcting a guessed timezone -+ */ -+ name = gtk_entry_get_text (name_entry); -+ if (name && name[0]) { -+ return; -+ } -+ - info = intlclock_zonetable_get_l10n_zone (zones, timezone); - g_free (timezone); - -@@ -2049,26 +2260,13 @@ zone_combo_changed (GtkComboBox *widget, gpointer this) - g_free (city); - - intlclock_zoneinfo_get_coords (info, &lat, &lon); -+ update_coords (this, TRUE, lat, lon); - -- tmp = g_strdup_printf ("%f", fabsf(lat)); -- gtk_entry_set_text (GTK_ENTRY (lat_entry), tmp); -- g_free (tmp); -- -- if (lat > 0) { -- gtk_combo_box_set_active (GTK_COMBO_BOX (lat_combo), 0); -- } else { -- gtk_combo_box_set_active (GTK_COMBO_BOX (lat_combo), 1); -- } -- -- tmp = g_strdup_printf ("%f", fabsf(lon)); -- gtk_entry_set_text (GTK_ENTRY (lon_entry), tmp); -- g_free (tmp); -- -- if (lon > 0) { -- gtk_combo_box_set_active (GTK_COMBO_BOX (lon_combo), 0); -- } else { -- gtk_combo_box_set_active (GTK_COMBO_BOX (lon_combo), 1); -- } -+ fill_location_tree (this); -+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->location_tree)); -+ weather_code = find_weather_code (model, city, lat * M_PI/180.0, lon * M_PI/180.0); -+ g_object_set_data_full (G_OBJECT (edit_window), "weather-code", -+ weather_code, g_free); - } - - static void -@@ -2144,12 +2342,8 @@ edit_tree_row (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); - - IntlClockLocation *loc; -- int i; -- int timezone_idx = -1; - gchar *tmp; - gfloat lat, lon; -- GList *list; -- GList *cur; - - /* fill the dialog with this location's data, show it */ - GtkWidget *edit_window = glade_xml_get_widget (priv->glade_xml, "edit-location-window"); -@@ -2205,13 +2399,165 @@ static void - run_prefs_locations_remove (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -- GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations);; - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->prefs_locations)); - - gtk_tree_selection_selected_foreach (sel, remove_tree_row, this); - } - - static void -+run_find_location (GtkButton *button, gpointer this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ -+ GtkWidget *window = glade_xml_get_widget (priv->glade_xml, "find-location-window"); -+ -+ gtk_tree_view_collapse_all (priv->location_tree); -+ gtk_widget_grab_focus (priv->find_location_entry); -+ gtk_window_present (GTK_WINDOW (window)); -+} -+ -+static gdouble -+distance (gdouble lat1, gdouble lon1, -+ gdouble lat2, gdouble lon2) -+{ -+ gdouble radius = 6372.795; -+ -+ return acos (cos (lat1) * cos (lat2) * cos (lon1 - lon2) + sin (lat1) * sin (lat2)) * radius; -+} -+ -+static gchar * -+find_timezone (IntlClockUI *this, -+ const char *name, -+ gfloat lat, -+ gfloat lon) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ IntlClockZoneTable *zonetab = intlclock_get_zonetable (priv->clock); -+ GList *zones, *l; -+ double dist, d; -+ gfloat zlat, zlon; -+ IntlClockZoneInfo *best; -+ -+ g_print ("find zone for %s (%f %f)\n", name, lat, lon); -+ dist = 1e6; -+ best = NULL; -+ zones = intlclock_zonetable_get_zones (zonetab); -+ for (l = zones; l; l = l->next) { -+ IntlClockZoneInfo *info = l->data; -+ intlclock_zoneinfo_get_coords (info, &zlat, &zlon); -+ -+ d = distance (lat, lon, zlat*M_PI/180.0, zlon*M_PI/180.0); -+ -+ if (d < dist) { -+ best = info; -+ dist = d; -+ } -+ } -+ -+ intlclock_zoneinfo_get_coords (best, &zlat, &zlon); -+ g_print ("best: %s (%f, %f), distance: %f\n", -+ intlclock_zoneinfo_get_name (best), zlat, zlon, dist); -+ -+ return g_strdup (intlclock_zoneinfo_get_name (best)); -+} -+ -+static void -+update_timezone (IntlClockUI *this, -+ const char *name, -+ gfloat lat, -+ gfloat lon) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ GtkWidget *zone_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-timezone-combo"); -+ GtkTreeModel *model; -+ gchar *timezone; -+ IntlClockLocation *loc; -+ -+ timezone = find_timezone (this, name, lat, lon); -+ loc = intlclock_location_new (name, timezone, lat*180.0/M_PI, lon*180.0/M_PI, NULL); -+ -+ g_signal_handler_block (zone_combo, priv->zone_combo_changed); -+ -+ fill_timezone_combo_from_location (this, zone_combo, loc); -+ -+ g_signal_handler_unblock (zone_combo, priv->zone_combo_changed); -+ -+ g_object_unref (loc); -+ g_free (timezone); -+} -+ -+static void -+run_find_location_save (GtkButton *button, gpointer this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ GtkTreeSelection *selection; -+ GtkTreeModel *model; -+ GtkTreeIter iter; -+ WeatherLocation *loc = NULL; -+ GtkWidget *name_entry; -+ GtkWidget *edit_window; -+ -+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->location_tree)); -+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) -+ return; -+ -+ gtk_tree_model_get (model, &iter, GWEATHER_XML_COL_POINTER, &loc, -1); -+ -+ if (!loc) -+ return; -+ -+ edit_window = glade_xml_get_widget (priv->glade_xml, "edit-location-window"); -+ name_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-name-entry"); -+ gtk_entry_set_text (GTK_ENTRY (name_entry), loc->name); -+ g_object_set_data_full (G_OBJECT (edit_window), "weather-code", -+ g_strdup (loc->code), g_free); -+ -+ update_coords (this, loc->latlon_valid, loc->latitude*180.0/M_PI, loc->longitude*180.0/M_PI); -+ -+ update_timezone (this, loc->name, loc->latitude, loc->longitude); -+ -+ intlclock_find_hide (button, this); -+} -+ -+static void -+location_row_activated (GtkTreeView *tree_view, -+ GtkTreePath *path, -+ GtkTreeViewColumn *column, -+ IntlClockUI *this) -+{ -+ run_find_location_save (tree_view, this); -+} -+ -+static void -+fill_location_tree (IntlClockUI *this) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -+ GtkTreeView *tree; -+ GtkTreeModel *model; -+ GtkTreeViewColumn *column; -+ GtkCellRenderer *cell; -+ -+ tree = (GtkTreeView*)priv->location_tree; -+ -+ if (gtk_tree_view_get_model (tree) != NULL) -+ return; -+ -+ model = (GtkTreeModel*)gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); -+ gtk_tree_view_set_model (tree, model); -+ -+ cell = gtk_cell_renderer_text_new (); -+ column = gtk_tree_view_column_new_with_attributes ("not used", cell, -+ "text", GWEATHER_XML_COL_LOC, NULL); -+ gtk_tree_view_append_column (tree, column); -+ gtk_tree_view_set_expander_column (tree, column); -+ -+ g_signal_connect (tree, "row-activated", -+ G_CALLBACK (location_row_activated), this); -+ -+ gweather_xml_load_locations (tree, NULL); -+} -+ -+static void - run_prefs_locations_add (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); -@@ -2220,7 +2566,8 @@ run_prefs_locations_add (GtkButton *button, gpointer this) - GtkWidget *zone_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-timezone-combo"); - - fill_timezone_combo_from_location (this, zone_combo, NULL); -- -+ fill_location_tree (this); -+ - g_object_set_data (G_OBJECT (edit_window), "intlclock-location", NULL); - gtk_window_present (GTK_WINDOW (edit_window)); - } -@@ -2230,7 +2577,6 @@ run_prefs_locations_edit (GtkButton *button, gpointer this) - { - IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (this)); - -- GtkTreeModel *model = gtk_tree_view_get_model (priv->prefs_locations);; - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->prefs_locations)); - - gtk_tree_selection_selected_foreach (sel, edit_tree_row, this); -@@ -2245,7 +2591,6 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - IntlClockZoneTable *zones = intlclock_get_zonetable (priv->clock); - - IntlClockLocation *loc = g_object_get_data (G_OBJECT (edit_window), "intlclock-location"); -- - GtkWidget *zone_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-timezone-combo"); - GtkWidget *name_entry = glade_xml_get_widget (priv->glade_xml, "edit-location-name-entry"); - -@@ -2255,6 +2600,8 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - GtkWidget *lon_combo = glade_xml_get_widget (priv->glade_xml, "edit-location-longitude-combo"); - - gchar *timezone_l10n = gtk_combo_box_get_active_text (GTK_COMBO_BOX (zone_combo)); -+ gchar *weather_code = g_object_get_data (G_OBJECT (edit_window), "weather-code"); -+ - IntlClockZoneInfo *info = intlclock_zonetable_get_l10n_zone (zones, timezone_l10n); - - if (!info) { -@@ -2281,9 +2628,11 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - intlclock_location_set_timezone (loc, intlclock_zoneinfo_get_name (info)); - intlclock_location_set_name (loc, name); - intlclock_location_set_coords (loc, lat, lon); -+ intlclock_location_set_weather_code (loc, weather_code); - } else { - GList *locs; -- loc = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), lat, lon); -+ -+ loc = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), lat, lon, weather_code); - - locs = g_list_copy (intlclock_get_locations (priv->clock)); - locs = g_list_append (locs, loc); -@@ -2294,3 +2643,11 @@ run_prefs_edit_save (GtkButton *button, gpointer this) - - intlclock_edit_hide (edit_window, this); - } -+ -+void -+intlclock_ui_update_weather_icon (IntlClockUI *ui, GdkPixbuf *pixbuf) -+{ -+ IntlClockUIPrivate *priv = PRIVATE (INTLCLOCK_UI (ui)); -+ -+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->panel_weather_icon), pixbuf); -+} -diff --git a/src/intlclock-ui.h b/src/intlclock-ui.h -index ecbee03..a10099a 100644 ---- a/src/intlclock-ui.h -+++ b/src/intlclock-ui.h -@@ -29,6 +29,8 @@ GType intlclock_ui_get_type (void); - - IntlClockUI *intlclock_ui_new (IntlClock *clock, PanelApplet *applet); - gboolean intlclock_ui_is_12hr (IntlClockUI *ui); -+void intlclock_ui_edit_locations (IntlClockUI *ui); -+void intlclock_ui_update_weather_icon (IntlClockUI *ui, GdkPixbuf *pixbuf); - - G_END_DECLS - #endif /* __INTLCLOCK_UI_H__ */ -diff --git a/src/intlclock-zonetable.c b/src/intlclock-zonetable.c -index a2a0b6f..e6e27cb 100644 ---- a/src/intlclock-zonetable.c -+++ b/src/intlclock-zonetable.c -@@ -27,8 +27,6 @@ typedef struct { - GHashTable *country_table; - } IntlClockZoneTablePrivate; - --#define USE_CRIPPLED_ZONELIST 1 -- - /* Seeded with the list from Nat's Blackberry */ - char *available_zones[] = { - /* Eniwetok (-12) */ -diff --git a/src/intlclock.c b/src/intlclock.c -index 02f5b0a..552c45c 100644 ---- a/src/intlclock.c -+++ b/src/intlclock.c -@@ -32,6 +32,8 @@ typedef struct { - enum { - TICK, - LOCATIONS_CHANGED, -+ BLINK_LOCATION, -+ CURRENT_TIMEZONE_CHANGED, - LAST_SIGNAL - }; - -@@ -87,7 +89,25 @@ intlclock_class_init (IntlClockClass *this_class) - _intlclock_marshal_VOID__VOID, - G_TYPE_NONE, 0); - -- g_type_class_add_private (this_class, sizeof (IntlClockPrivate)); -+ intlclock_signals[BLINK_LOCATION] = g_signal_new -+ ("blink-location", -+ G_OBJECT_CLASS_TYPE (obj_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (IntlClockClass, blink_location), -+ NULL, NULL, -+ _intlclock_marshal_VOID__OBJECT, -+ G_TYPE_NONE, 1, INTLCLOCK_LOCATION_TYPE); -+ -+ intlclock_signals[CURRENT_TIMEZONE_CHANGED] = g_signal_new -+ ("current-timezone-changed", -+ G_OBJECT_CLASS_TYPE (obj_class), -+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, -+ G_STRUCT_OFFSET (IntlClockClass, current_timezone_changed), -+ NULL, NULL, -+ _intlclock_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ -+ g_type_class_add_private (this_class, sizeof (IntlClockPrivate)); - } - - static void -@@ -133,7 +153,7 @@ intlclock_set_locations (IntlClock *this, GList *locations) - - priv->locations = locations; - -- g_signal_emit_by_name (this, "locations-changed"); -+ g_signal_emit (this, intlclock_signals[LOCATIONS_CHANGED], 0); - } - - GList * -@@ -202,7 +222,7 @@ intlclock_emit_tick (gpointer data) - IntlClock *this = INTLCLOCK (data); - IntlClockPrivate *priv = PRIVATE (this); - -- g_signal_emit_by_name (this, "tick"); -+ g_signal_emit (this, intlclock_signals[TICK], 0); - - if (priv->in_partial_timeout) { - intlclock_reset_timeout (this); -@@ -353,3 +373,9 @@ intlclock_free_locations (IntlClock *this) - g_list_free (priv->locations); - priv->locations = NULL; - } -+ -+void -+intlclock_blink_location (IntlClock *this, IntlClockLocation *loc) -+{ -+ g_signal_emit (this, intlclock_signals[BLINK_LOCATION], 0, loc); -+} -diff --git a/src/intlclock.h b/src/intlclock.h -index 3b0012c..20c681d 100644 ---- a/src/intlclock.h -+++ b/src/intlclock.h -@@ -27,6 +27,9 @@ typedef struct - - void (* tick) (IntlClock *clock); - void (* locations_changed) (IntlClock *clock); -+ void (* blink_location) (IntlClock *clock, IntlClockLocation *loc); -+ void (* current_timezone_changed) (IntlClock *clock); -+ - } IntlClockClass; - - GType intlclock_get_type (void); -@@ -35,6 +38,7 @@ IntlClock *intlclock_new (void); - - void intlclock_set_locations (IntlClock *this, GList *list); - GList *intlclock_get_locations (IntlClock *this); -+void intlclock_blink_location (IntlClock *this, IntlClockLocation *loc); - - IntlClockZoneTable *intlclock_get_zonetable (IntlClock *this); - gchar *intlclock_format_time (IntlClock *this, struct tm *now, -diff --git a/src/set-timezone.c b/src/set-timezone.c -new file mode 100644 -index 0000000..5c96149 ---- /dev/null -+++ b/src/set-timezone.c -@@ -0,0 +1,426 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include "config.h" -+#endif -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <string.h> -+#include <sys/wait.h> -+ -+#include <dbus/dbus-glib.h> -+#include <dbus/dbus-glib-lowlevel.h> -+ -+#include <polkit/polkit.h> -+#include <polkit-dbus/polkit-dbus.h> -+ -+static DBusGConnection * -+get_session_bus (void) -+{ -+ GError *error; -+ static DBusGConnection *bus = NULL; -+ -+ if (bus == NULL) { -+ error = NULL; -+ bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); -+ if (bus == NULL) { -+ g_warning ("Couldn't connect to session bus: %s", -+ error->message); -+ g_error_free (error); -+ } -+ } -+ -+ return bus; -+} -+ -+static DBusGConnection * -+get_system_bus (void) -+{ -+ GError *error; -+ static DBusGConnection *bus = NULL; -+ -+ if (bus == NULL) { -+ error = NULL; -+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); -+ if (bus == NULL) { -+ g_warning ("Couldn't connect to system bus: %s", -+ error->message); -+ g_error_free (error); -+ } -+ } -+ -+ return bus; -+} -+ -+static PolKitContext * -+get_pk_context (void) -+{ -+ static PolKitContext *pk_context = NULL; -+ -+ if (pk_context == NULL) { -+ pk_context = polkit_context_new (); -+ if (!polkit_context_init (pk_context, NULL)) { -+ polkit_context_unref (pk_context); -+ pk_context = NULL; -+ } -+ } -+ -+ return pk_context; -+} -+ -+gboolean -+set_system_timezone (const char *filename, GError **err) -+{ -+ DBusGConnection *session_bus; -+ DBusGConnection *system_bus; -+ DBusGProxy *mechanism_proxy; -+ DBusGProxy *polkit_gnome_proxy; -+ gboolean ret = FALSE; -+ -+ session_bus = get_session_bus (); -+ if (session_bus == NULL) -+ goto out; -+ -+ system_bus = get_system_bus (); -+ if (system_bus == NULL) -+ goto out; -+ -+ mechanism_proxy = dbus_g_proxy_new_for_name (system_bus, -+ "org.gnome.ClockApplet.Mechanism", -+ "/", -+ "org.gnome.ClockApplet.Mechanism"); -+ -+ polkit_gnome_proxy = dbus_g_proxy_new_for_name (session_bus, -+ "org.gnome.PolicyKit", -+ "/org/gnome/PolicyKit/Manager", -+ "org.gnome.PolicyKit.Manager"); -+ -+ if (filename != NULL) { -+ GError *error; -+ -+ g_debug ("Trying to set timezone '%s'", filename); -+ try_again: -+ error = NULL; -+ /* first, try to call into the mechanism */ -+ if (!dbus_g_proxy_call_with_timeout (mechanism_proxy, -+ "SetTimezone", -+ INT_MAX, -+ &error, -+ /* parameters: */ -+ G_TYPE_STRING, filename, -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_INVALID)) { -+ if (dbus_g_error_has_name (error, "org.gnome.ClockApplet.Mechanism.NotPrivileged")) { -+ char **tokens; -+ char *polkit_result_textual; -+ char *polkit_action; -+ gboolean gained_privilege; -+ -+ tokens = g_strsplit (error->message, " ", 2); -+ g_error_free (error); -+ if (g_strv_length (tokens) != 2) { -+ g_warning ("helper return string malformed"); -+ g_strfreev (tokens); -+ goto out; -+ } -+ polkit_action = tokens[0]; -+ polkit_result_textual = tokens[1]; -+ -+ g_debug ("helper refused; returned polkit_result='%s' and polkit_action='%s'", -+ polkit_result_textual, polkit_action); -+ -+ /* Now ask the user for auth... */ -+ if (!dbus_g_proxy_call_with_timeout (polkit_gnome_proxy, -+ "ShowDialog", -+ INT_MAX, -+ &error, -+ /* parameters: */ -+ G_TYPE_STRING, polkit_action, -+ G_TYPE_UINT, 0, /* X11 window ID; none */ -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_BOOLEAN, &gained_privilege, -+ G_TYPE_INVALID)) { -+ g_propagate_error (err, error); -+ g_strfreev (tokens); -+ goto out; -+ } -+ g_strfreev (tokens); -+ -+ if (gained_privilege) { -+ g_debug ("Gained privilege; trying to set timezone again"); -+ goto try_again; -+ } -+ -+ } else { -+ g_propagate_error (err, error); -+ } -+ goto out; -+ } -+ -+ g_debug ("Successfully set time zone to '%s'", filename); -+ } -+ -+ ret = TRUE; -+out: -+ g_object_unref (mechanism_proxy); -+ g_object_unref (polkit_gnome_proxy); -+ -+ return ret; -+} -+ -+static gint -+can_do (const gchar *pk_action_id) -+{ -+ DBusConnection *system_bus; -+ PolKitCaller *pk_caller; -+ PolKitAction *pk_action; -+ PolKitResult pk_result; -+ PolKitContext *pk_context; -+ DBusError dbus_error; -+ gint res = 0; -+ -+ system_bus = dbus_g_connection_get_connection (get_system_bus ()); -+ if (system_bus == NULL) -+ goto out; -+ -+ pk_context = get_pk_context (); -+ if (pk_context == NULL) -+ goto out; -+ -+ pk_caller = NULL; -+ pk_action = NULL; -+ -+ pk_action = polkit_action_new (); -+ polkit_action_set_action_id (pk_action, pk_action_id); -+ -+ dbus_error_init (&dbus_error); -+ pk_caller = polkit_caller_new_from_pid (system_bus, getpid (), &dbus_error); -+ if (pk_caller == NULL) { -+ fprintf (stderr, "cannot get caller from dbus name\n"); -+ goto out; -+ } -+ -+ pk_result = polkit_context_can_caller_do_action (pk_context, pk_action, pk_caller); -+ -+ switch (pk_result) { -+ default: -+ case POLKIT_RESULT_UNKNOWN: -+ case POLKIT_RESULT_NO: -+ res = 0; -+ break; -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH: -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION: -+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: -+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: -+ res = 1; -+ break; -+ case POLKIT_RESULT_YES: -+ res = 2; -+ break; -+ } -+ -+out: -+ if (pk_action != NULL) -+ polkit_action_unref (pk_action); -+ if (pk_caller != NULL) -+ polkit_caller_unref (pk_caller); -+ -+ return res; -+} -+ -+gint -+can_set_system_timezone (void) -+{ -+ return can_do ("org.gnome.clockapplet.mechanism.settimezone"); -+} -+ -+gint -+can_set_system_time (void) -+{ -+ return can_do ("org.gnome.clockapplet.mechanism.settime"); -+} -+ -+typedef struct { -+ gint ref_count; -+ gint64 time; -+ GFunc callback; -+ gpointer data; -+ GDestroyNotify notify; -+} SetTimeCallbackData; -+ -+static void -+free_data (gpointer d) -+{ -+ SetTimeCallbackData *data = d; -+ -+ data->ref_count--; -+ if (data->ref_count == 0) { -+ if (data->notify) -+ data->notify (data->data); -+ g_free (data); -+ } -+} -+ -+static void set_time_async (SetTimeCallbackData *data); -+ -+static void -+auth_notify (DBusGProxy *proxy, -+ DBusGProxyCall *call, -+ void *user_data) -+{ -+ SetTimeCallbackData *data = user_data; -+ GError *error = NULL; -+ gboolean gained_privilege; -+ -+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_BOOLEAN, &gained_privilege, G_TYPE_INVALID)) { -+ if (gained_privilege) -+ set_time_async (data); -+ } -+ else { -+ if (data->callback) -+ data->callback (data->data, error); -+ else -+ g_error_free (error); -+ } -+} -+ -+static void -+do_auth_async (const gchar *action, -+ const gchar *result, -+ SetTimeCallbackData *data) -+{ -+ DBusGConnection *bus; -+ DBusGProxy *proxy; -+ -+ g_debug ("helper refused; returned polkit_result='%s' and polkit_action='%s'", -+ result, action); -+ -+ /* Now ask the user for auth... */ -+ bus = get_session_bus (); -+ if (bus == NULL) -+ return; -+ -+ proxy = dbus_g_proxy_new_for_name (bus, -+ "org.gnome.PolicyKit", -+ "/org/gnome/PolicyKit/Manager", -+ "org.gnome.PolicyKit.Manager"); -+ -+ data->ref_count++; -+ dbus_g_proxy_begin_call_with_timeout (proxy, -+ "ShowDialog", -+ auth_notify, -+ data, free_data, -+ INT_MAX, -+ G_TYPE_STRING, action, -+ G_TYPE_UINT, 0, -+ G_TYPE_INVALID); -+} -+ -+static void -+set_time_notify (DBusGProxy *proxy, -+ DBusGProxyCall *call, -+ void *user_data) -+{ -+ SetTimeCallbackData *data = user_data; -+ GError *error = NULL; -+ -+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { -+ if (data->callback) -+ data->callback (data->data, NULL); -+ } -+ else { -+ if (dbus_g_error_has_name (error, "org.gnome.ClockApplet.Mechanism.NotPrivileged")) { -+ gchar **tokens; -+ -+ tokens = g_strsplit (error->message, " ", 2); -+ g_error_free (error); -+ if (g_strv_length (tokens) == 2) -+ do_auth_async (tokens[0], tokens[1], data); -+ else -+ g_warning ("helper return string malformed"); -+ g_strfreev (tokens); -+ } -+ else { -+ if (data->callback) -+ data->callback (data->data, error); -+ else -+ g_error_free (error); -+ } -+ } -+} -+ -+static void -+set_time_async (SetTimeCallbackData *data) -+{ -+ DBusGConnection *bus; -+ DBusGProxy *proxy; -+ DBusGProxyCall *call; -+ -+ bus = get_system_bus (); -+ if (bus == NULL) -+ return; -+ -+ proxy = dbus_g_proxy_new_for_name (bus, -+ "org.gnome.ClockApplet.Mechanism", -+ "/", -+ "org.gnome.ClockApplet.Mechanism"); -+ -+ data->ref_count++; -+ dbus_g_proxy_begin_call_with_timeout (proxy, -+ "SetTime", -+ set_time_notify, -+ data, free_data, -+ INT_MAX, -+ /* parameters: */ -+ G_TYPE_INT64, data->time, -+ G_TYPE_INVALID, -+ /* return values: */ -+ G_TYPE_INVALID); -+} -+ -+void -+set_system_time_async (gint64 time, -+ GFunc callback, -+ gpointer d, -+ GDestroyNotify notify) -+{ -+ SetTimeCallbackData *data; -+ -+ if (time == -1) -+ return; -+ -+ data = g_new (SetTimeCallbackData, 1); -+ data->ref_count = 1; -+ data->time = time; -+ data->callback = callback; -+ data->data = d; -+ data->notify = notify; -+ -+ set_time_async (data); -+ free_data (data); -+} -diff --git a/src/set-timezone.h b/src/set-timezone.h -new file mode 100644 -index 0000000..c71622c ---- /dev/null -+++ b/src/set-timezone.h -@@ -0,0 +1,36 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ */ -+ -+#ifndef __SET_SYSTEM_TIMEZONE_H__ -+ -+#include <time.h> -+ -+gboolean set_system_timezone (const char *filename, -+ GError **err); -+gint can_set_system_timezone (void); -+ -+gint can_set_system_time (void); -+ -+void set_system_time_async (gint64 time, -+ GFunc callback, -+ gpointer data, -+ GDestroyNotify notify); -+ -+#endif diff --git a/intlclock-changes-20071013.patch b/intlclock-changes-20071014.patch index b414c42..2dd2910 100644 --- a/intlclock-changes-20071013.patch +++ b/intlclock-changes-20071014.patch @@ -8455,7 +8455,7 @@ index 40d96e3..3535d8d 100644 +} + diff --git a/src/intlclock-location.c b/src/intlclock-location.c -index 384b2aa..30154e4 100644 +index 384b2aa..dbb8f75 100644 --- a/src/intlclock-location.c +++ b/src/intlclock-location.c @@ -1,4 +1,3 @@ @@ -8463,7 +8463,7 @@ index 384b2aa..30154e4 100644 #ifdef HAVE_CONFIG_H #include <config.h> -@@ -13,9 +12,16 @@ +@@ -13,9 +12,21 @@ #include <sys/stat.h> #include <time.h> #include <unistd.h> @@ -8473,6 +8473,11 @@ index 384b2aa..30154e4 100644 #include <libgnome/gnome-i18n.h> +#include <libgnomevfs/gnome-vfs.h> + ++#include <dbus/dbus-glib.h> ++#include <dbus/dbus-glib-lowlevel.h> ++#include <NetworkManager/NetworkManager.h> ++ ++ +#include "intlclock-location.h" +#include "intlclock-marshallers.h" +#include "set-timezone.h" @@ -8480,7 +8485,7 @@ index 384b2aa..30154e4 100644 G_DEFINE_TYPE (IntlClockLocation, intlclock_location, G_TYPE_OBJECT) -@@ -29,17 +35,31 @@ typedef struct { +@@ -29,17 +40,33 @@ typedef struct { gfloat latitude; gfloat longitude; @@ -8502,6 +8507,8 @@ index 384b2aa..30154e4 100644 static void intlclock_location_set_tz (IntlClockLocation *this); static void intlclock_location_unset_tz (IntlClockLocation *this); +static void setup_weather_updates (IntlClockLocation *loc); ++static void add_to_network_monitor (IntlClockLocation *loc); ++static void remove_from_network_monitor (IntlClockLocation *loc); #define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INTLCLOCK_LOCATION_TYPE, IntlClockLocationPrivate)) @@ -8513,7 +8520,7 @@ index 384b2aa..30154e4 100644 { IntlClockLocation *this; IntlClockLocationPrivate *priv; -@@ -62,6 +82,9 @@ intlclock_location_new (const gchar *name, const gchar *timezone, +@@ -62,6 +89,9 @@ intlclock_location_new (const gchar *name, const gchar *timezone, priv->latitude = latitude; priv->longitude = longitude; @@ -8523,7 +8530,7 @@ index 384b2aa..30154e4 100644 return this; } -@@ -193,6 +216,77 @@ guess_zone_from_tree (const gchar *localtime, IntlClockZoneTable *zones) +@@ -193,6 +223,77 @@ guess_zone_from_tree (const gchar *localtime, IntlClockZoneTable *zones) return ret; } @@ -8601,7 +8608,7 @@ index 384b2aa..30154e4 100644 static gchar * intlclock_location_guess_zone (IntlClockZoneTable *zones) { -@@ -200,6 +294,12 @@ intlclock_location_guess_zone (IntlClockZoneTable *zones) +@@ -200,6 +301,12 @@ intlclock_location_guess_zone (IntlClockZoneTable *zones) const char *localtime = "/etc/localtime"; gchar *linkfile = NULL; GError *err = NULL; @@ -8614,7 +8621,7 @@ index 384b2aa..30154e4 100644 /* guess the current time zone by readlink() on /etc/localtime */ linkfile = g_file_read_link (localtime, &err); -@@ -235,14 +335,14 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) +@@ -235,14 +342,14 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) if (zone == NULL) { /* make a fake location with a null TZ */ @@ -8631,7 +8638,7 @@ index 384b2aa..30154e4 100644 } g_free (zone); -@@ -260,7 +360,7 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) +@@ -260,7 +367,7 @@ intlclock_location_new_from_env (IntlClockZoneTable *zones) } ret = intlclock_location_new (name, intlclock_zoneinfo_get_name (info), @@ -8640,7 +8647,7 @@ index 384b2aa..30154e4 100644 g_free (name); -@@ -274,6 +374,15 @@ intlclock_location_class_init (IntlClockLocationClass *this_class) +@@ -274,6 +381,15 @@ intlclock_location_class_init (IntlClockLocationClass *this_class) g_obj_class->finalize = intlclock_location_finalize; @@ -8656,7 +8663,16 @@ index 384b2aa..30154e4 100644 g_type_class_add_private (this_class, sizeof (IntlClockLocationPrivate)); } -@@ -318,6 +427,21 @@ intlclock_location_finalize (GObject *g_obj) +@@ -297,6 +413,8 @@ static void + intlclock_location_finalize (GObject *g_obj) + { + IntlClockLocationPrivate *priv = PRIVATE (g_obj); ++ ++ remove_from_network_monitor (INTLCLOCK_LOCATION (g_obj)); + + if (priv->name) { + g_free (priv->name); +@@ -318,6 +436,21 @@ intlclock_location_finalize (GObject *g_obj) priv->tzname = NULL; } @@ -8678,7 +8694,7 @@ index 384b2aa..30154e4 100644 G_OBJECT_CLASS (intlclock_location_parent_class)->finalize (g_obj); } -@@ -467,3 +591,188 @@ intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm) +@@ -467,3 +600,266 @@ intlclock_location_localtime (IntlClockLocation *loc, struct tm *tm) intlclock_location_unset_tz (loc); } @@ -8822,6 +8838,82 @@ index 384b2aa..30154e4 100644 + (int)deg2, (int)min2, h2); +} + ++static GList *locations = NULL; ++ ++static void ++update_weather_infos (void) ++{ ++ GList *l; ++ ++ for (l = locations; l; l = l->next) { ++ update_weather_info (l->data); ++ } ++} ++ ++static DBusHandlerResult ++filter_func (DBusConnection *connection, ++ DBusMessage *message, ++ void *user_data) ++{ ++ guint32 state = NM_DEVICE_STATE_UNKNOWN; ++ ++ if (dbus_message_is_signal (message, ++ NM_DBUS_INTERFACE_DEVICE, "StateChanged")) { ++ dbus_message_get_args (message, NULL, ++ DBUS_TYPE_UINT32, &state, ++ DBUS_TYPE_INVALID); ++ if (state == NM_DEVICE_STATE_ACTIVATED) { ++ update_weather_infos (); ++ } ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } ++ ++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; ++} ++ ++static void ++setup_network_monitor (void) ++{ ++ GError *error; ++ static DBusGConnection *bus = NULL; ++ DBusConnection *dbus; ++ ++ if (bus == NULL) { ++ error = NULL; ++ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); ++ if (bus == NULL) { ++ g_warning ("Couldn't connect to system bus: %s", ++ error->message); ++ g_error_free (error); ++ ++ return; ++ } ++ ++ dbus = dbus_g_connection_get_connection (bus); ++ dbus_connection_add_filter (dbus, filter_func, NULL, NULL); ++ dbus_bus_add_match (dbus, ++ "type='signal'," ++ "interface='" NM_DBUS_INTERFACE_DEVICE "'", ++ NULL); ++ } ++} ++ ++static void ++add_to_network_monitor (IntlClockLocation *loc) ++{ ++ setup_network_monitor (); ++ ++ if (!g_list_find (locations, loc)) ++ locations = g_list_prepend (locations, loc); ++} ++ ++static void ++remove_from_network_monitor (IntlClockLocation *loc) ++{ ++ locations = g_list_remove (locations, loc); ++} ++ +static void +setup_weather_updates (IntlClockLocation *loc) +{ @@ -8865,6 +8957,8 @@ index 384b2aa..30154e4 100644 + + weather_location_free (wl); + g_free (dms); ++ ++ add_to_network_monitor (loc); +} + diff --git a/src/intlclock-location.h b/src/intlclock-location.h |