[Xfce4-commits] <orage:master> 4.7.4.7 Timezone selection improvments
Juha Kautto
noreply at xfce.org
Fri Oct 2 12:54:01 CEST 2009
Updating branch refs/heads/master
to 1b1ae3db8ff86378f647ef174a62161a36d2de10 (commit)
from e41c58b12832936906baa2f87025b4758b8725f7 (commit)
commit 1b1ae3db8ff86378f647ef174a62161a36d2de10
Author: Juha Kautto <juha at xfce.org>
Date: Fri Oct 2 13:50:52 2009 +0300
4.7.4.7 Timezone selection improvments
Extra information now shows next time and how clock changes. Also
fixed how time change times are shown.
Globaltime now has better timeadjust mode.
NEWS | 13 ++
configure.in.in | 2 +-
globaltime/globaltime.c | 27 +++-
globaltime/globaltime.h | 3 +-
globaltime/gt_prefs.c | 129 +++++++----------
globaltime/timezone_selection.c | 173 +++++++++++++++--------
globaltime/timezone_selection.h | 2 +-
globaltime/tz_zoneinfo_read.c | 245 ++++++++++++++++++++++++--------
globaltime/tz_zoneinfo_read.h | 4 +-
panel-plugin/oc_config.c | 44 +-----
panel-plugin/timezone_selection.c | 173 +++++++++++++++--------
panel-plugin/timezone_selection.h | 2 +-
panel-plugin/tz_zoneinfo_read.c | 247 ++++++++++++++++++++++++--------
panel-plugin/tz_zoneinfo_read.h | 4 +-
panel-plugin/xfce4-orageclock-plugin.h | 1 -
src/appointment.c | 6 +-
src/parameters.c | 2 +-
src/timezone_selection.c | 176 ++++++++++++++---------
src/timezone_selection.h | 2 +-
src/tz_zoneinfo_read.c | 42 +++++-
src/tz_zoneinfo_read.h | 1 +
21 files changed, 853 insertions(+), 445 deletions(-)
diff --git a/NEWS b/NEWS
index 682c15a..5591a0a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,16 @@
+20091002: Globaltime and panel plugin updates
+---------
+ * Change timezone selection to be exactly the same than in Orage
+ - Removed the entry box and only include the button now.
+ - It is not as flexible, but it is easier to use for non-gurus.
+ * Modified time adjust mode in globaltime to start from zero minute.
+ - By default it now changes 30 mins per click.
+ - Page Up and Page Down can be used to tune only 1 minute.
+ - Removed message informing time change mode is starting.
+ * Timezone extra information now shows correct time change time
+ - wel, it is 1 sec off, but close enough...
+ * Timezone extra information now shows also next time and how it changes
+
20090906: Version 4.7.4
---------
* New timezone selection dialog (Bug 3876)
diff --git a/configure.in.in b/configure.in.in
index ac28494..9fe9134 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -9,7 +9,7 @@ dnl Written for Xfce by Juha Kautto <juha at xfce.org>
dnl
dnl Version information
-m4_define([orage_version], [4.7.4.6-test])
+m4_define([orage_version], [4.7.4.7-test])
m4_define([gtk_minimum_version], [2.10.0])
m4_define([xfce_minimum_version], [4.6.0])
diff --git a/globaltime/globaltime.c b/globaltime/globaltime.c
index 6c6f733..1c5377a 100644
--- a/globaltime/globaltime.c
+++ b/globaltime/globaltime.c
@@ -49,7 +49,7 @@
#include "globaltime.h"
-#define NAME_VERSION "Global Time (2.0)"
+#define NAME_VERSION "Global Time (2.1)"
global_times_struct clocks;
@@ -342,6 +342,8 @@ void show_clock(clock_struct *clockp, gint *pos)
static gboolean preferences_button_pressed(GtkWidget *widget
, GdkEventButton *event, gpointer dummy)
{
+ struct tm *now;
+
if (event->button == 2) { /* toggle spinbox sensitivity */
if (clocks.time_adj_act) { /* end it */
gtk_widget_hide(clocks.hdr_adj_mm);
@@ -355,15 +357,19 @@ static gboolean preferences_button_pressed(GtkWidget *widget
clocks.mm_adj = 0;
clocks.hh_adj = 0;
clocks.previous_secs = 70; /* trick to refresh clocks once */
- g_message(_("Ending time adjustment mode"));
gtk_window_resize(GTK_WINDOW(clocks.window), 10, 10);
}
else { /* start hour adjusting mode */
+ /* let's try to guess good starting value = to get times to
+ * 0 or 30 minutes. */
+ now = gmtime(&clocks.previous_t);
+ clocks.mm_adj = (now->tm_min < 30 ? 0 : 60) - now->tm_min;
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(clocks.hdr_adj_mm)
+ , (gdouble)clocks.mm_adj);
gtk_widget_show(clocks.hdr_adj_mm);
gtk_widget_show(clocks.hdr_adj_sep);
gtk_widget_show(clocks.hdr_adj_hh);
clocks.time_adj_act = TRUE;
- g_message(_("Starting time adjustment mode"));
}
return(FALSE);
}
@@ -408,6 +414,9 @@ static gboolean upd_clocks(void)
struct tm *now;
gint secs_now;
+ if (clocks.no_update)
+ return(TRUE);
+
now = get_time(clocks.local_tz->str); /* GMT is returmed if not found */
if (!clocks.time_adj_act) {
time(&clocks.previous_t);
@@ -424,7 +433,7 @@ static gboolean upd_clocks(void)
/* minute changed => need to update visible clocks */
g_list_foreach(clocks.clock_list, (GFunc) upd_clock, NULL);
clocks.previous_secs = secs_now;
- return (TRUE);
+ return(TRUE);
}
void adj_hh_changed(GtkSpinButton *cb, gpointer user_data)
@@ -462,7 +471,7 @@ static void init_hdr_button(void)
gtk_widget_show(image);
gtk_widget_show(clocks.hdr_button);
- clocks.hdr_adj_hh = gtk_spin_button_new_with_range(-23, 23, 1);
+ clocks.hdr_adj_hh = gtk_spin_button_new_with_range(-24, 24, 1);
gtk_box_pack_start(GTK_BOX(clocks.hdr_hbox)
, clocks.hdr_adj_hh, FALSE, FALSE, 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(clocks.hdr_adj_hh), (gdouble)0);
@@ -477,14 +486,15 @@ static void init_hdr_button(void)
gtk_box_pack_start(GTK_BOX(clocks.hdr_hbox)
, clocks.hdr_adj_sep, FALSE, FALSE, 0);
- clocks.hdr_adj_mm = gtk_spin_button_new_with_range(-59, 59, 1);
+ clocks.hdr_adj_mm = gtk_spin_button_new_with_range(-60, 60, 1);
gtk_box_pack_start(GTK_BOX(clocks.hdr_hbox)
, clocks.hdr_adj_mm, FALSE, FALSE, 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(clocks.hdr_adj_mm), (gdouble)0);
gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(clocks.hdr_adj_mm), TRUE);
+ gtk_spin_button_set_increments(GTK_SPIN_BUTTON(clocks.hdr_adj_mm), 30, 1);
gtk_widget_set_size_request(clocks.hdr_adj_mm, 40, -1);
gtk_tooltips_set_tip(clocks.tips, clocks.hdr_adj_mm
- , _("adjust to change minute"), NULL);
+ , _("adjust to change minute. Click arrows with button 2 to change only 1 minute."), NULL);
g_signal_connect((gpointer) clocks.hdr_adj_mm, "changed"
, G_CALLBACK(adj_mm_changed), NULL);
/* We want it to be hidden initially, it is special thing to do...
@@ -507,6 +517,7 @@ static void initialize_clocks()
strcpy(clocks.time_now, "88:88");
clocks.previous_secs = 61;
clocks.time_adj_act = FALSE;
+ clocks.no_update = FALSE;
clocks.hh_adj = 0;
clocks.mm_adj = 0;
/* done in read_file
@@ -605,7 +616,7 @@ static void create_global_time(void)
int main(int argc, char *argv[])
{
xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
- gtk_init (&argc, &argv);
+ gtk_init(&argc, &argv);
create_global_time();
gtk_main();
diff --git a/globaltime/globaltime.h b/globaltime/globaltime.h
index af02942..4e8c51d 100644
--- a/globaltime/globaltime.h
+++ b/globaltime/globaltime.h
@@ -32,10 +32,11 @@ typedef struct
typedef struct
{ /* all clocks */
GList *clock_list; /* list of clock_structs */
- gchar time_now[16]; /* 88:88 null terminated */
+ gchar time_now[8]; /* 88:88+ null terminated */
gint previous_secs;
time_t previous_t;
gboolean time_adj_act; /* manual time adjustment active or not */
+ gboolean no_update; /* do not update clocks */
gint hh_adj; /* adjustment hours */
gint mm_adj; /* adjustment hours */
GString *local_tz; /* local timezone. Used to set local_mday */
diff --git a/globaltime/gt_prefs.c b/globaltime/gt_prefs.c
index d8b3ecf..166c846 100644
--- a/globaltime/gt_prefs.c
+++ b/globaltime/gt_prefs.c
@@ -42,7 +42,7 @@ typedef struct modify
clock_struct *clock;
GtkWidget *window;
GtkWidget *name_entry;
- GtkWidget *tz_entry;
+ GtkWidget *button_tz;
GtkWidget *button_clock_fg;
GtkWidget *check_button_default_fg;
GtkWidget *button_clock_bg;
@@ -66,9 +66,9 @@ static void create_parameter_formatting(GtkWidget *vbox
static gboolean decoration_radio_button_pressed(GtkWidget *widget, gchar *label)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
- if (strcmp(label, _("Standard")) == 0)
+ if (strcmp(label, "Standard") == 0)
clocks.decorations = TRUE;
- else if (strcmp(label, _("None")) == 0)
+ else if (strcmp(label, "None") == 0)
clocks.decorations = FALSE;
else
g_warning("Unknown selection in decoration radio button\n");
@@ -81,9 +81,9 @@ static gboolean decoration_radio_button_pressed(GtkWidget *widget, gchar *label)
static gboolean clocksize_radio_button_pressed(GtkWidget *widget, gchar *label)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
- if (strcmp(label, _("Equal")) == 0)
+ if (strcmp(label, "Equal") == 0)
clocks.expand = TRUE;
- else if (strcmp(label, _("Vary")) == 0)
+ else if (strcmp(label, "Vary") == 0)
clocks.expand = FALSE;
else
g_warning("Unknown selection in clock size radio button\n");
@@ -108,8 +108,6 @@ static void close_preferences_window(GtkWidget *widget, GtkWidget *window)
static gboolean save_preferences(GtkWidget *widget
, modify_struct *modify_default)
{
- g_string_assign(clocks.local_tz
- , gtk_entry_get_text(GTK_ENTRY(modify_default->tz_entry)));
write_file();
return(FALSE);
}
@@ -183,8 +181,6 @@ static gboolean save_clock(GtkWidget *widget
g_string_assign(clockp->name
, gtk_entry_get_text(GTK_ENTRY(modify_clock->name_entry)));
gtk_label_set_text(GTK_LABEL(clockp->name_label), clockp->name->str);
- g_string_assign(clockp->tz
- , gtk_entry_get_text(GTK_ENTRY(modify_clock->tz_entry)));
write_file();
return(FALSE);
}
@@ -202,7 +198,7 @@ static gboolean set_timezone_from_clock(GtkWidget *widget
, modify_struct *modify_clock)
{
g_string_assign(clocks.local_tz
- , gtk_entry_get_text(GTK_ENTRY(modify_clock->tz_entry)));
+ , gtk_button_get_label((GTK_BUTTON(modify_clock->button_tz))));
write_file();
return(FALSE);
}
@@ -286,8 +282,8 @@ static void copy_clock(GtkWidget *widget, modify_struct *modify_clock)
new_pos = g_list_index(clocks.clock_list, clockp_old)+1;
clockp_new = g_new(clock_struct, 1);
- clockp_new->tz = g_string_new(gtk_entry_get_text(
- GTK_ENTRY(modify_clock->tz_entry)));
+ clockp_new->tz = g_string_new(gtk_button_get_label(
+ GTK_BUTTON(modify_clock->button_tz)));
clockp_new->name = g_string_new(_("NEW COPY"));
clockp_new->modified = FALSE;
init_attr(&clockp_new->clock_attr);
@@ -357,54 +353,43 @@ static void move_clock(GtkWidget *widget, modify_struct *modify_clock)
write_file();
}
+/* We handle here timezone setting for individual clocks, but also
+ * the generic (default) setting. We know we are doing defaults when there is no
+ * clock pointer */
static void ask_timezone(GtkButton *button, modify_struct *modify_clock)
-/* static void ask_timezone(GtkWidget *widget, modify_struct *modify_clock) */
{
- /* GtkWidget *dialog; */
- gchar *filename = NULL;
+ gchar *tz_name = NULL;
gchar *clockname = NULL;
-
+ char env_tz[256];
+
+ /* first stop all clocks and reset time to local timezone because
+ * timezone list needs to be shown in local timezone (details show time) */
+ clocks.no_update = TRUE;
+ if (clocks.local_tz && clocks.local_tz->str && clocks.local_tz->len) {
+ g_snprintf(env_tz, 256, "TZ=%s", clocks.local_tz->str);
+ putenv(env_tz);
+ tzset();
+ }
if (orage_timezone_button_clicked(button, GTK_WINDOW(modify_clock->window)
- , &filename)) {
- gtk_entry_set_text(GTK_ENTRY(modify_clock->tz_entry), filename);
- if (strlen(gtk_entry_get_text(GTK_ENTRY(modify_clock->name_entry)))
- == 0) {
- if ((clockname = strrchr(filename, (int)'/')))
- gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
- , clockname+1);
- else
- gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
- , filename);
+ , &tz_name, FALSE, NULL)) {
+ if (modify_clock->clock) { /* individual, real clock */
+ g_string_assign(modify_clock->clock->tz, tz_name);
+ if (strlen(gtk_entry_get_text(GTK_ENTRY(modify_clock->name_entry)))
+ == 0) {
+ if ((clockname = strrchr(tz_name, (int)'/')))
+ gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
+ , clockname+1);
+ else
+ gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
+ , tz_name);
+ }
}
- g_free(filename);
- }
-
- /*
- dialog = gtk_file_chooser_dialog_new(_("Select timezone"), NULL
- , GTK_FILE_CHOOSER_ACTION_OPEN
- , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
- , GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
-/ * let's try to start on few standard positions * /
- if (gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog)
- , "/usr/share/zoneinfo/GMT") == FALSE)
- gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog)
- , "/usr/lib/zoneinfo/GMT");
- if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- gtk_entry_set_text(GTK_ENTRY(modify_clock->tz_entry), filename);
- if (strlen(gtk_entry_get_text(GTK_ENTRY(modify_clock->name_entry)))
- == 0) {
- if ((clockname = strrchr(filename, (int)'/')))
- gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
- , clockname+1);
- else
- gtk_entry_set_text(GTK_ENTRY(modify_clock->name_entry)
- , filename);
+ else { /* default timezone in main setup */
+ g_string_assign(clocks.local_tz, tz_name);
}
- g_free(filename);
+ g_free(tz_name);
}
- gtk_widget_destroy(dialog);
- */
+ clocks.no_update = FALSE;
}
static void set_font(GtkWidget *widget, GString *font)
@@ -588,7 +573,6 @@ gboolean clock_parameters(GtkWidget *widget, clock_struct *clockp)
{
modify_struct *modify_clock;
GtkWidget *vbox, *hbox;
- GtkWidget *button;
gchar *window_name;
if (clockp->modified)
@@ -628,15 +612,12 @@ gboolean clock_parameters(GtkWidget *widget, clock_struct *clockp)
hbox = add_box(vbox, 'H');
add_header(hbox, _("Timezone of the clock:"), TRUE);
- modify_clock->tz_entry = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(modify_clock->tz_entry), clockp->tz->str);
- gtk_box_pack_start(GTK_BOX(hbox), modify_clock->tz_entry
- , FALSE, FALSE, 5);
- gtk_tooltips_set_tip(clocks.tips, modify_clock->tz_entry
- , _("enter timezone of clock,\n(=any valid TZ value)"), NULL);
- button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2);
- g_signal_connect(G_OBJECT(button), "clicked"
+ modify_clock->button_tz = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+ if (clockp->tz->str && clockp->tz->len)
+ gtk_button_set_label(GTK_BUTTON(modify_clock->button_tz)
+ , _(clockp->tz->str));
+ gtk_box_pack_start(GTK_BOX(hbox), modify_clock->button_tz, FALSE, FALSE, 2);
+ g_signal_connect(G_OBJECT(modify_clock->button_tz), "clicked"
, G_CALLBACK(ask_timezone), modify_clock);
/* ---------------------Text Formatting--------------------------------- */
@@ -1076,7 +1057,7 @@ gboolean default_preferences(GtkWidget *widget)
modify_default = g_new0(modify_struct, 1);
modify_default->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW (modify_default->window)
- , _("Modify Preferences"));
+ , _("Modify Globaltime Preferences"));
g_signal_connect(G_OBJECT(modify_default->window) , "destroy"
, G_CALLBACK(release_preferences_window), modify_default);
@@ -1137,20 +1118,14 @@ gboolean default_preferences(GtkWidget *widget)
/* -----------------------Local timezone------------------------------ */
hbox = add_box(vbox, 'H');
add_header(hbox, _("Local timezone:"), TRUE);
- modify_default->tz_entry = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(modify_default->tz_entry)
- , clocks.local_tz->str);
- gtk_box_pack_start(GTK_BOX(hbox), modify_default->tz_entry
- , FALSE, FALSE, 5);
- gtk_tooltips_set_tip(clocks.tips, modify_default->tz_entry
- , _("Enter local timezone. (it is used to show if time is on previous(-) or next date(+) by adding a +/- after the time)"), NULL);
- button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2);
- g_signal_connect(G_OBJECT(button), "clicked"
+ modify_default->button_tz = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+ if (clocks.local_tz->str)
+ gtk_button_set_label(GTK_BUTTON(modify_default->button_tz)
+ , _(clocks.local_tz->str));
+ gtk_box_pack_start(GTK_BOX(hbox), modify_default->button_tz, FALSE, FALSE
+ , 2);
+ g_signal_connect(G_OBJECT(modify_default->button_tz), "clicked"
, G_CALLBACK(ask_timezone), modify_default);
- /* these are needed by ask_timezone */
- modify_default->name_entry = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(modify_default->name_entry), "dummy");
/* ---------------------Text Formatting--------------------------------- */
preferences_formatting(vbox, modify_default);
diff --git a/globaltime/timezone_selection.c b/globaltime/timezone_selection.c
index 8819d04..f82eaa1 100644
--- a/globaltime/timezone_selection.c
+++ b/globaltime/timezone_selection.c
@@ -67,12 +67,13 @@ enum {
LOCATION,
LOCATION_ENG,
OFFSET,
+ CHANGES,
COUNTRY,
- NEXT_CHANGE,
N_COLUMNS
};
-static GtkTreeStore *tz_button_create_store(gboolean details)
+static GtkTreeStore *tz_button_create_store(gboolean details
+ , gboolean check_ical)
{
#undef P_N
#define P_N "tz_button_create_store: "
@@ -82,14 +83,16 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
GtkTreeIter iter1, iter2, main;
orage_timezone_array tz_a;
char area_old[MAX_AREA_LENGTH+2]; /*+2 = / + null */
- char s_offset[100], s_country[100], s_next[100];
- gint i, j, offs_hour, offs_min;
+ char s_offset[100], s_country[100], s_changes[200], s_change[50]
+ , s_change_time[50];
+ gint i, j, offs_hour, offs_min, next_offs_hour, next_offs_min
+ , change_time, change_hour, change_min;
store = gtk_tree_store_new(N_COLUMNS
, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING
, G_TYPE_STRING, G_TYPE_STRING);
strcpy(area_old, "S T a R T"); /* this never matches */
- tz_a = get_orage_timezones(details);
+ tz_a = get_orage_timezones(details, check_ical ? 1 : 0);
/*
g_print(P_N "number of timezones %d\n", tz_a.count);
*/
@@ -100,8 +103,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(" Other")
, LOCATION_ENG, " Other"
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , NEXT_CHANGE, " "
, -1);
main = iter1; /* need to remember that */
@@ -124,8 +127,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(area_old)
, LOCATION_ENG, area_old
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , NEXT_CHANGE, " "
, -1);
/* let's make sure we do not match accidentally to those
* plain names on main level. We do this by adding / */
@@ -144,26 +147,66 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
if (offs_min)
g_print(P_N " %s offset %d hour %d minutes %d\n", tz_a.city[i], tz_a.utc_offset[i], offs_hour, offs_min);
*/
- g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
- , offs_hour, offs_min
- , (tz_a.dst[i]) ? "dst" : "std"
- , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
- if (details && tz_a.country[i] && tz_a.cc[i])
- g_snprintf(s_country, 100, "%s (%s)", tz_a.country[i], tz_a.cc[i]);
- else
- strcpy(s_country, " ");
- if (details)
- g_snprintf(s_next, 100, "%s"
+ if (details && tz_a.next[i]) {
+ next_offs_hour = tz_a.next_utc_offset[i] / (60*60);
+ next_offs_min = abs((tz_a.next_utc_offset[i]
+ - next_offs_hour * (60*60)) / 60);
+ change_time = tz_a.next_utc_offset[i] - tz_a.utc_offset[i];
+ change_hour = change_time / (60*60);
+ change_min = abs((change_time - change_hour * (60*60)) /60);
+ if (change_hour && change_min)
+ g_snprintf(s_change_time, 50, _("%d hour %d mins")
+ , abs(change_hour), change_min);
+ else if (change_hour)
+ g_snprintf(s_change_time, 50, _("%d hour"), abs(change_hour));
+ else if (change_min)
+ g_snprintf(s_change_time, 50, _("%d mins"), change_min);
+ else
+ strcpy(s_change_time, " ");
+
+ if (change_time < 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("backward"), s_change_time);
+ else if (change_time > 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("forward"), s_change_time);
+ else
+ strcpy(s_change, " ");
+ g_snprintf(s_offset, 100
+ , "%+03d:%02d %s (%s)\n -> %+03d:%02d %s"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-"
+ , next_offs_hour, next_offs_min
+ , s_change);
+ }
+ else {
+ g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
+ }
+ if (details) {
+ if (tz_a.country[i] && tz_a.cc[i])
+ g_snprintf(s_country, 100, "%s (%s)"
+ , tz_a.country[i], tz_a.cc[i]);
+ else
+ strcpy(s_country, " ");
+ g_snprintf(s_changes, 200, "%s\n%s"
+ , (tz_a.prev[i]) ? tz_a.prev[i] : _("not changed")
, (tz_a.next[i]) ? tz_a.next[i] : _("not changing"));
- else
- strcpy(s_next, " ");
+ }
+ else {
+ strcpy(s_country, " ");
+ strcpy(s_changes, " ");
+ }
gtk_tree_store_set(store, &iter2
, LOCATION, _(tz_a.city[i])
, LOCATION_ENG, tz_a.city[i]
, OFFSET, s_offset
+ , CHANGES, s_changes
, COUNTRY, s_country
- , NEXT_CHANGE, s_next
, -1);
}
return(store);
@@ -220,20 +263,20 @@ GtkWidget *tz_button_create_view(gboolean details, GtkTreeStore *store)
if (details) {
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Country")
- , rend, "text", COUNTRY, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Previous/Next Change")
+ , rend, "text", CHANGES, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Next Change")
- , rend, "text", NEXT_CHANGE, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Country")
+ , rend, "text", COUNTRY, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
}
return(tree);
}
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz)
+ , gchar **tz, gboolean check_ical, char *local_tz)
{
#undef P_N
#define P_N "orage_timezone_button_clicked: "
@@ -243,30 +286,39 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
GtkWidget *window;
GtkWidget *sw;
int result;
- char *loc, *loc_eng;
+ char *loc = NULL, *loc_eng = NULL;
GtkTreeSelection *sel;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean changed = FALSE;
gboolean details = FALSE;
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
/* show it */
- window = gtk_dialog_new_with_buttons(_("Pick timezone")
- , parent
- , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
- , _("Change mode"), 4
- , _("UTC"), 1
- /* , _("floating"), 2 */
- /* , _(g_par.local_timezone), 3 */
- , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
- , NULL);
+ if (check_ical)
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , _("floating"), 3
+ , _(local_tz), 4
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
+ else
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), sw, TRUE, TRUE, 0);
- gtk_window_set_default_size(GTK_WINDOW(window), 610, 500);
+ gtk_window_set_default_size(GTK_WINDOW(window), 750, 500);
gtk_widget_show_all(window);
do {
@@ -280,50 +332,53 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
else {
gtk_tree_model_get(model, &iter, LOCATION, &loc, -1);
gtk_tree_model_get(model, &iter, LOCATION_ENG, &loc_eng
- , -1); }
+ , -1);
+ }
else {
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
}
break;
case 1:
- loc = g_strdup(_("UTC"));
- loc_eng = g_strdup("UTC");
- break;
- /*
- case 2:
- loc = g_strdup(_("floating"));
- loc_eng = g_strdup("floating");
- break;
- case 3:
- loc = g_strdup(_(g_par.local_timezone));
- loc_eng = g_strdup(g_par.local_timezone);
- break;
- */
- case 4:
free_orage_timezones(details);
details = !details;
/* gtk_widget_destroy(GTK_WIDGET(store)); */
gtk_widget_destroy(tree);
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_widget_show_all(tree);
result = 0;
break;
+ case 2:
+ loc = g_strdup(_("UTC"));
+ loc_eng = g_strdup("UTC");
+ break;
+ case 3:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_("floating"));
+ loc_eng = g_strdup("floating");
+ break;
+ case 4:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_(local_tz));
+ loc_eng = g_strdup(local_tz);
+ break;
default:
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
break;
}
} while (result == 0);
- if (g_ascii_strcasecmp(loc, (gchar *)gtk_button_get_label(button)) != 0)
+ if (loc && g_ascii_strcasecmp(loc, gtk_button_get_label(button))) {
changed = TRUE;
- gtk_button_set_label(button, loc);
-
- if (*tz)
- g_free(*tz);
- *tz = g_strdup(loc_eng);
+ /* return the real timezone and update the button to show the
+ * translated timezone name */
+ if (*tz)
+ g_free(*tz);
+ *tz = g_strdup(loc_eng);
+ gtk_button_set_label(button, loc);
+ }
g_free(loc);
g_free(loc_eng);
gtk_widget_destroy(window);
diff --git a/globaltime/timezone_selection.h b/globaltime/timezone_selection.h
index 2f0e3af..e181a41 100644
--- a/globaltime/timezone_selection.h
+++ b/globaltime/timezone_selection.h
@@ -24,6 +24,6 @@
#define __TIMEZONE_SELECTION_H__
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz);
+ , gchar **tz, gboolean check_ical, char *local_tz);
#endif /* !__TIMEZONE_SELECTION_H__ */
diff --git a/globaltime/tz_zoneinfo_read.c b/globaltime/tz_zoneinfo_read.c
index 1ff1330..508b427 100644
--- a/globaltime/tz_zoneinfo_read.c
+++ b/globaltime/tz_zoneinfo_read.c
@@ -59,63 +59,71 @@
/** This is the toplevel directory where the timezone data is installed in. */
-#define ORAGE_ZONEINFO_DIRECTORY PACKAGE_DATA_DIR "/orage/zoneinfo"
+#define ORAGE_ZONEINFO_DIRECTORY PACKAGE_DATA_DIR "/orage/zoneinfo/"
/** This is the filename of the file containing tz_convert parameters
* This file contains the location of the os zoneinfo data.
* the same than the above DEFAULT_OS_ZONEINFO_DIRECTORY */
#define TZ_CONVERT_PAR_FILENAME "tz_convert.par"
-#define TZ_CONVERT_PAR_FILE_LOC ORAGE_ZONEINFO_DIRECTORY "/" TZ_CONVERT_PAR_FILENAME
+#define TZ_CONVERT_PAR_FILE_LOC ORAGE_ZONEINFO_DIRECTORY TZ_CONVERT_PAR_FILENAME
+
+/** This is the filename of the file containing orage ical timezone names */
+#define ICAL_ZONES_TAB_FILENAME "zones.tab"
+#define ICAL_ZONES_TAB_FILE_LOC ORAGE_ZONEINFO_DIRECTORY ICAL_ZONES_TAB_FILENAME
/* this contains all timezone data */
orage_timezone_array tz_array={0, NULL, NULL, NULL, NULL, NULL, NULL};
-char *zone_tab_buf = NULL, *country_buf = NULL;
+static char *zone_tab_buf = NULL, *country_buf = NULL, *zones_tab_buf = NULL;
-int debug = 0; /* bigger number => more output */
-char version[] = "1.4.4";
-int file_cnt = 0; /* number of processed files */
+static int debug = 0; /* bigger number => more output */
+static char version[] = "1.4.4";
+static int file_cnt = 0; /* number of processed files */
-unsigned char *in_buf, *in_head, *in_tail;
-int in_file_base_offset = 0;
+static unsigned char *in_buf, *in_head, *in_tail;
+static int in_file_base_offset = 0;
-int details;
+static int details; /* show extra data (country and next change time) */
+static int check_ical; /* check that we have also the ical timezone data */
-char *in_file = NULL, *out_file = NULL;
-int in_file_is_dir = 0;
-int excl_dir_cnt = -1;
-char **excl_dir = NULL;
+static char *in_file = NULL, *out_file = NULL;
+static int in_file_is_dir = 0;
+static int excl_dir_cnt = -1;
+static char **excl_dir = NULL;
/* in_timezone_name is the real timezone name from the infile
* we are processing.
- * in_timezone_name is the timezone we are writing. Usually it is the same
+ * timezone_name is the timezone we are writing. Usually it is the same
* than in_timezone_name.
- * timezone name is for example Europe/Helsinki */
-char *timezone_name = NULL;
-char *in_timezone_name = NULL;
+ * timezone_name is for example Europe/Helsinki */
+/* FIXME: we do not need both timezone_name and in_timezone_name here.
+ * Remove one */
+static char *timezone_name = NULL;
+static char *in_timezone_name = NULL;
-int ignore_older = 1970; /* Ignore rules which are older or equal than this */
+/* Ignore rules which are older or equal than this */
+static int ignore_older = 1970;
/* time change table starts here */
-unsigned char *begin_timechanges;
+static unsigned char *begin_timechanges;
/* time change type index table starts here */
-unsigned char *begin_timechangetypeindexes;
+static unsigned char *begin_timechangetypeindexes;
/* time change type table starts here */
-unsigned char *begin_timechangetypes;
+static unsigned char *begin_timechangetypes;
/* timezone name table */
-unsigned char *begin_timezonenames;
+static unsigned char *begin_timezonenames;
-unsigned long gmtcnt;
-unsigned long stdcnt;
-unsigned long leapcnt;
-unsigned long timecnt; /* points when time changes */
-unsigned long typecnt; /* table of different time changes = types */
-unsigned long charcnt; /* length of timezone name table */
+static unsigned long gmtcnt;
+static unsigned long stdcnt;
+static unsigned long leapcnt;
+static unsigned long timecnt; /* points when time changes */
+static unsigned long typecnt; /* table of different time changes = types */
+static unsigned long charcnt; /* length of timezone name table */
static void read_file(const char *file_name, const struct stat *file_stat)
{
@@ -136,7 +144,7 @@ static void read_file(const char *file_name, const struct stat *file_stat)
printf("read_file: end\n");
}
-long get_long()
+static long get_long()
{
unsigned long tmp;
@@ -148,7 +156,7 @@ long get_long()
return(tmp);
}
-int process_header()
+static int process_header()
{
if (debug > 2)
printf("file id: %s\n", in_head);
@@ -180,7 +188,7 @@ int process_header()
return(0);
}
-process_local_time_table()
+static process_local_time_table()
{ /* points when time changes */
unsigned long tmp;
int i;
@@ -199,7 +207,7 @@ process_local_time_table()
}
}
-process_local_time_type_table()
+static process_local_time_type_table()
{ /* pointers to table, which explain how time changes */
unsigned char tmp;
int i;
@@ -215,7 +223,7 @@ process_local_time_type_table()
}
}
-process_ttinfo_table()
+static process_ttinfo_table()
{ /* table of different time changes = types */
long tmp;
unsigned char tmp2, tmp3;
@@ -236,7 +244,7 @@ process_ttinfo_table()
}
}
-process_abbr_table()
+static process_abbr_table()
{
unsigned char *tmp;
int i;
@@ -253,7 +261,7 @@ process_abbr_table()
in_head += charcnt;
}
-process_leap_table()
+static process_leap_table()
{
unsigned long tmp, tmp2;
int i;
@@ -269,7 +277,7 @@ process_leap_table()
}
}
-process_std_table()
+static process_std_table()
{
unsigned char tmp;
int i;
@@ -284,7 +292,7 @@ process_std_table()
}
}
-process_gmt_table()
+static process_gmt_table()
{
unsigned char tmp;
int i;
@@ -301,7 +309,7 @@ process_gmt_table()
/* go through the contents of the file and find the positions of
* needed data. Uses global pointer: in_head */
-int process_file(const char *file_name)
+static int process_file(const char *file_name)
{
if (debug > 1)
printf("\n\nprocess_file: start\n");
@@ -323,10 +331,10 @@ int process_file(const char *file_name)
return(0); /* ok */
}
-void get_country()
+static void get_country()
{ /* tz_array.city[tz_array.count] contains the city name.
We will find corresponding country and fill it to the table */
- char *str, *str_nl;
+ char *str, *str_nl, cc[4];
if (!(str = strstr(zone_tab_buf, tz_array.city[tz_array.count])))
return; /* not found */
@@ -343,12 +351,19 @@ void get_country()
strncpy(tz_array.cc[tz_array.count], ++str_nl, 2);
tz_array.cc[tz_array.count][2] = '\0';
- /* then search the country */
- if (!(str = strstr(country_buf, tz_array.cc[tz_array.count])))
+ /********** then search the country **********/
+ /* Need to search line, which starts with country code.
+ * Note that it is not enough to search any country coed, but it really
+ * needs to be the first two chars in the line */
+ cc[0] = '\n';
+ cc[1] = tz_array.cc[tz_array.count][0];
+ cc[2] = tz_array.cc[tz_array.count][1];
+ cc[3] = '\0';
+ if (!(str = strstr(country_buf, cc)))
return; /* not found */
/* country name is after the country code and a single tab */
- str += 3;
- /* but w still need to find how long it is.
+ str += 4;
+ /* but we still need to find how long it is.
* It ends in the line end.
* (There is a line end at the end of the file also.) */
for (str_nl = str; str_nl[0] != '\n'; str_nl++)
@@ -358,16 +373,28 @@ void get_country()
tz_array.country[tz_array.count][(str_nl - str)] = '\0';
}
+static int timezone_exists_in_ical()
+{ /* in_timezone_name contains the timezone name.
+ We will search if it exists also in the ical zones.tab file */
+ char *str;
+
+ if (str = strstr(zones_tab_buf, in_timezone_name))
+ return(1); /* yes, it is there */
+ else
+ return(0); /* not found */
+}
+
/* FIXME: need to check that if OUTFILE is given as a parameter,
* INFILE is not a directory (or make outfile to act like directory also ? */
-int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
+static int write_ical_file(const char *in_file_name
+ , const struct stat *in_file_stat)
{
int i;
unsigned int tct_i, abbr_i;
struct tm cur_gm_time;
time_t tt_now = time(NULL);
- long tc_time = 0; /* TimeChange time */
- char s_next[101];
+ long tc_time = 0, prev_tc_time; /* TimeChange times */
+ char s_next[101], s_prev[101];
if (debug > 1)
printf("***** write_ical_file: start *****\n\n");
@@ -384,6 +411,7 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
/* search for current time setting.
* timecnt tells how many changes we have in the tz file.
* i points to the next value to read. */
+ prev_tc_time = tc_time;
tc_time = get_long(); /* start time of this timechange */
}
/* i points to the next value to be read, so need to -- */
@@ -393,7 +421,9 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = "UTC";
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.count++;
return(1); /* done */
}
@@ -401,16 +431,52 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
/* we found previous and next value */
/* tc_time has the next change time */
if (details) {
+ /* NOTE: If the time change happens for example at 04:00
+ * and goes one hour backward, the new time is 03:00 and this
+ * is what localtime_r reports. In real life we want to show
+ * here 04:00, so let's subtract 1 sec to get close to that.
+ * This is a bit similar than 24:00 or 00:00. Summary:
+ * 04:00 is returned as 03:00 (change happened already) but
+ * 03:59 is returned as 03:59 (change did not yet happen) */
+ prev_tc_time -= 1;
+ localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+ strftime(s_prev, 100, "%c", &cur_gm_time);
+ tz_array.prev[tz_array.count] = strdup(s_prev);
+
+ tc_time -= 1;
localtime_r((const time_t *)&tc_time, &cur_gm_time);
strftime(s_next, 100, "%c", &cur_gm_time);
tz_array.next[tz_array.count] = strdup(s_next);
+ /* get timechange type index */
+ if (timecnt) {
+ in_head = begin_timechangetypeindexes;
+ tct_i = (unsigned int)in_head[i];
+ }
+ else
+ tct_i = 0;
+
+ /* get timechange type */
+ in_head = begin_timechangetypes;
+ in_head += 6*tct_i;
+ tz_array.next_utc_offset[tz_array.count] = (int)get_long();
}
- else
+ else {
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ }
i--; /* we need to take the previous value */
}
- else
+ else { /* no next value, but previous may exist */
tz_array.next[tz_array.count] = NULL;
+ if (details && prev_tc_time) {
+ prev_tc_time -= 1;
+ localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+ strftime(s_prev, 100, "%c", &cur_gm_time);
+ tz_array.prev[tz_array.count] = strdup(s_prev);
+ }
+ else
+ tz_array.prev[tz_array.count] = NULL;
+ }
/* i now points to latest time change and shows current time.
* So we found our result and can start collecting real data: */
@@ -441,7 +507,7 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
}
/* The main code. This is called once per each file found */
-int file_call(const char *file_name, const struct stat *sb, int flags
+static int file_call(const char *file_name, const struct stat *sb, int flags
, struct FTW *f)
{
int i;
@@ -453,14 +519,21 @@ int file_call(const char *file_name, const struct stat *sb, int flags
if (flags == FTW_F) { /* we got file */
if (debug > 0)
printf("\t\tfile_call: processing file=(%s)\n", file_name);
+ in_timezone_name = strdup(&file_name[in_file_base_offset
+ + strlen("zoneinfo/")]);
+ timezone_name = strdup(in_timezone_name);
+ if (check_ical && !timezone_exists_in_ical()) {
+ free(in_timezone_name);
+ free(timezone_name);
+ return(FTW_CONTINUE);
+ }
read_file(file_name, sb);
if (process_file(file_name)) { /* we skipped this file */
+ free(in_timezone_name);
+ free(timezone_name);
free(in_buf);
return(FTW_CONTINUE);
}
- in_timezone_name = strdup(&file_name[in_file_base_offset
- + strlen("zoneinfo/")]);
- timezone_name = strdup(in_timezone_name);
write_ical_file(file_name, sb);
free(in_buf);
@@ -499,7 +572,7 @@ int file_call(const char *file_name, const struct stat *sb, int flags
}
/* check the parameters and use defaults when possible */
-int check_parameters()
+static int check_parameters()
{
char *s_tz, *last_tz = NULL, tz[]="/zoneinfo", tz2[]="zoneinfo/";
int tz_len, i;
@@ -630,7 +703,7 @@ int check_parameters()
return(0); /* continue */
}
-void read_countries()
+static void read_countries()
{
char *tz_dir, *zone_tab_file_name, *country_file_name;
int zoneinfo_len=strlen("zoneinfo/");
@@ -730,7 +803,40 @@ void read_countries()
fclose(country_file);
}
-orage_timezone_array get_orage_timezones(int show_details)
+static void read_ical_timezones()
+{
+ FILE *zones_tab_file;
+ struct stat zones_tab_file_stat;
+
+ /****** zones.tab file ******/
+ if (!(zones_tab_file = fopen(ICAL_ZONES_TAB_FILE_LOC, "r"))) {
+ printf("read_ical_timezones: zones.tab file open failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ perror("\tfopen");
+ return;
+ }
+ if (stat(ICAL_ZONES_TAB_FILE_LOC, &zones_tab_file_stat) == -1) {
+ printf("read_ical_timezones: zones.tab file stat failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ fclose(zones_tab_file);
+ perror("\tstat");
+ return;
+ }
+ zones_tab_buf = malloc(zones_tab_file_stat.st_size+1);
+ fread(zones_tab_buf, 1, zones_tab_file_stat.st_size, zones_tab_file);
+ if (ferror(zones_tab_file)) {
+ printf("read_ical_timezones: zones.tab file read failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ perror("\tfread");
+ return;
+ }
+ zones_tab_buf[zones_tab_file_stat.st_size] = '\0';
+ printf("read_ical_timezones: zones.tab file read (%s) (%d bytes)\n"
+ , ICAL_ZONES_TAB_FILE_LOC, strlen(zones_tab_buf));
+ fclose(zones_tab_file);
+}
+
+orage_timezone_array get_orage_timezones(int show_details, int ical)
{
int tz_array_size = 1000; /* FIXME: this needs to be counted */
/*
@@ -740,12 +846,15 @@ orage_timezone_array get_orage_timezones(int show_details)
*/
details = show_details;
+ check_ical = ical;
if (tz_array.count == 0) {
tz_array.city = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.dst = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.tz = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+ tz_array.prev = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.next = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+ tz_array.next_utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.country = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.cc = (char **)malloc(sizeof(char *)*(tz_array_size+2));
/* nftw goes through the whole file structure and calls "file_call"
@@ -756,6 +865,8 @@ orage_timezone_array get_orage_timezones(int show_details)
printf("Processing %s files\n", in_file);
if (details)
read_countries();
+ if (check_ical)
+ read_ical_timezones();
if (nftw(in_file, file_call, 10, FTW_PHYS | FTW_ACTIONRETVAL) == -1) {
perror("nftw error in file handling");
exit(EXIT_FAILURE);
@@ -768,7 +879,9 @@ orage_timezone_array get_orage_timezones(int show_details)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = strdup("UTC");
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("UTC");
@@ -776,12 +889,14 @@ orage_timezone_array get_orage_timezones(int show_details)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = NULL;
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("floating");
}
- return (tz_array);
+ return(tz_array);
}
void free_orage_timezones(int show_details)
@@ -793,6 +908,8 @@ void free_orage_timezones(int show_details)
free(tz_array.city[i]);
if (tz_array.tz[i])
free(tz_array.tz[i]);
+ if (tz_array.prev[i])
+ free(tz_array.prev[i]);
if (tz_array.next[i])
free(tz_array.next[i]);
if (tz_array.country[i])
@@ -804,10 +921,24 @@ void free_orage_timezones(int show_details)
free(tz_array.utc_offset);
free(tz_array.dst);
free(tz_array.tz);
+ free(tz_array.prev);
free(tz_array.next);
+ free(tz_array.next_utc_offset);
free(tz_array.country);
free(tz_array.cc);
tz_array.count = 0;
timezone_name = NULL;
+ if (zone_tab_buf) {
+ free(zone_tab_buf);
+ zone_tab_buf = NULL;
+ }
+ if (country_buf) {
+ free(country_buf);
+ country_buf = NULL;
+ }
+ if (zones_tab_buf) {
+ free(zones_tab_buf);
+ zones_tab_buf = NULL;
+ }
file_cnt = 0; /* number of processed files */
}
diff --git a/globaltime/tz_zoneinfo_read.h b/globaltime/tz_zoneinfo_read.h
index 9002f44..7b5c634 100644
--- a/globaltime/tz_zoneinfo_read.h
+++ b/globaltime/tz_zoneinfo_read.h
@@ -25,10 +25,12 @@ typedef struct _orage_timezone_array
int *utc_offset; /* pointer to int array holding utc offsets */
int *dst; /* pointer to int array holding dst settings */
char **tz; /* pointer to timezone name strings */
+ char **prev; /* pointer to previous time change strings */
char **next; /* pointer to next time change strings */
+ int *next_utc_offset; /* pointer to int array holding utc offsets */
char **country; /* pointer to country name strings */
char **cc; /* pointer to country code strings */
} orage_timezone_array;
-orage_timezone_array get_orage_timezones(int details);
+orage_timezone_array get_orage_timezones(int details, int ical);
void free_orage_timezones(int details);
diff --git a/panel-plugin/oc_config.c b/panel-plugin/oc_config.c
index f393719..38da945 100644
--- a/panel-plugin/oc_config.c
+++ b/panel-plugin/oc_config.c
@@ -100,45 +100,18 @@ static void oc_set_width_changed(GtkSpinButton *sb, Clock *clock)
oc_size_set(clock);
}
-static void oc_timezone_changed(GtkWidget *widget, GdkEventKey *key
- , Clock *clock)
-{
- /* is it better to change only with GDK_Tab GDK_Return GDK_KP_Enter ? */
- g_string_assign(clock->timezone, gtk_entry_get_text(GTK_ENTRY(widget)));
- oc_timezone_set(clock);
-}
-
static void oc_timezone_selected(GtkButton *button, Clock *clock)
{
GtkWidget *dialog;
gchar *filename = NULL;
dialog = g_object_get_data(G_OBJECT(clock->plugin), "dialog");
- if (orage_timezone_button_clicked(button, GTK_WINDOW(dialog), &filename)) {
- gtk_entry_set_text(GTK_ENTRY(clock->tz_entry), filename);
- g_string_assign(clock->timezone, filename);
- oc_timezone_set(clock);
- g_free(filename);
- }
-/*
- dialog = gtk_file_chooser_dialog_new(_("Select timezone"), NULL
- , GTK_FILE_CHOOSER_ACTION_OPEN
- , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
- , GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
-/ * let's try to start on few standard positions * /
- if (gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog)
- , "/usr/share/zoneinfo/GMT") == FALSE)
- gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog)
- , "/usr/lib/zoneinfo/GMT");
- if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- gtk_entry_set_text(GTK_ENTRY(clock->tz_entry), filename);
+ if (orage_timezone_button_clicked(button, GTK_WINDOW(dialog)
+ , &filename, FALSE, NULL)) {
g_string_assign(clock->timezone, filename);
oc_timezone_set(clock);
g_free(filename);
}
- gtk_widget_destroy(dialog);
- */
}
static void oc_show1(GtkToggleButton *cb, Clock *clock)
@@ -303,17 +276,10 @@ static void oc_properties_options(GtkWidget *dlg, Clock *clock)
label = gtk_label_new(_("set timezone to:"));
oc_table_add(table, label, 0, 0);
- clock->tz_entry = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(clock->tz_entry), clock->timezone->str);
- oc_table_add(table, clock->tz_entry, 1, 0);
- g_signal_connect(clock->tz_entry, "key-release-event"
- , G_CALLBACK(oc_timezone_changed), clock);
- gtk_tooltips_set_tip(clock->tips, GTK_WIDGET(clock->tz_entry),
- _("Set any valid timezone (=TZ) value or pick one from the list.")
- , NULL);
-
button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
- oc_table_add(table, button, 2, 0);
+ if (clock->timezone->str && clock->timezone->len)
+ gtk_button_set_label(GTK_BUTTON(button), _(clock->timezone->str));
+ oc_table_add(table, button, 1, 0);
g_signal_connect(G_OBJECT(button), "clicked"
, G_CALLBACK(oc_timezone_selected), clock);
diff --git a/panel-plugin/timezone_selection.c b/panel-plugin/timezone_selection.c
index 8819d04..f82eaa1 100644
--- a/panel-plugin/timezone_selection.c
+++ b/panel-plugin/timezone_selection.c
@@ -67,12 +67,13 @@ enum {
LOCATION,
LOCATION_ENG,
OFFSET,
+ CHANGES,
COUNTRY,
- NEXT_CHANGE,
N_COLUMNS
};
-static GtkTreeStore *tz_button_create_store(gboolean details)
+static GtkTreeStore *tz_button_create_store(gboolean details
+ , gboolean check_ical)
{
#undef P_N
#define P_N "tz_button_create_store: "
@@ -82,14 +83,16 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
GtkTreeIter iter1, iter2, main;
orage_timezone_array tz_a;
char area_old[MAX_AREA_LENGTH+2]; /*+2 = / + null */
- char s_offset[100], s_country[100], s_next[100];
- gint i, j, offs_hour, offs_min;
+ char s_offset[100], s_country[100], s_changes[200], s_change[50]
+ , s_change_time[50];
+ gint i, j, offs_hour, offs_min, next_offs_hour, next_offs_min
+ , change_time, change_hour, change_min;
store = gtk_tree_store_new(N_COLUMNS
, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING
, G_TYPE_STRING, G_TYPE_STRING);
strcpy(area_old, "S T a R T"); /* this never matches */
- tz_a = get_orage_timezones(details);
+ tz_a = get_orage_timezones(details, check_ical ? 1 : 0);
/*
g_print(P_N "number of timezones %d\n", tz_a.count);
*/
@@ -100,8 +103,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(" Other")
, LOCATION_ENG, " Other"
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , NEXT_CHANGE, " "
, -1);
main = iter1; /* need to remember that */
@@ -124,8 +127,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(area_old)
, LOCATION_ENG, area_old
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , NEXT_CHANGE, " "
, -1);
/* let's make sure we do not match accidentally to those
* plain names on main level. We do this by adding / */
@@ -144,26 +147,66 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
if (offs_min)
g_print(P_N " %s offset %d hour %d minutes %d\n", tz_a.city[i], tz_a.utc_offset[i], offs_hour, offs_min);
*/
- g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
- , offs_hour, offs_min
- , (tz_a.dst[i]) ? "dst" : "std"
- , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
- if (details && tz_a.country[i] && tz_a.cc[i])
- g_snprintf(s_country, 100, "%s (%s)", tz_a.country[i], tz_a.cc[i]);
- else
- strcpy(s_country, " ");
- if (details)
- g_snprintf(s_next, 100, "%s"
+ if (details && tz_a.next[i]) {
+ next_offs_hour = tz_a.next_utc_offset[i] / (60*60);
+ next_offs_min = abs((tz_a.next_utc_offset[i]
+ - next_offs_hour * (60*60)) / 60);
+ change_time = tz_a.next_utc_offset[i] - tz_a.utc_offset[i];
+ change_hour = change_time / (60*60);
+ change_min = abs((change_time - change_hour * (60*60)) /60);
+ if (change_hour && change_min)
+ g_snprintf(s_change_time, 50, _("%d hour %d mins")
+ , abs(change_hour), change_min);
+ else if (change_hour)
+ g_snprintf(s_change_time, 50, _("%d hour"), abs(change_hour));
+ else if (change_min)
+ g_snprintf(s_change_time, 50, _("%d mins"), change_min);
+ else
+ strcpy(s_change_time, " ");
+
+ if (change_time < 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("backward"), s_change_time);
+ else if (change_time > 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("forward"), s_change_time);
+ else
+ strcpy(s_change, " ");
+ g_snprintf(s_offset, 100
+ , "%+03d:%02d %s (%s)\n -> %+03d:%02d %s"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-"
+ , next_offs_hour, next_offs_min
+ , s_change);
+ }
+ else {
+ g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
+ }
+ if (details) {
+ if (tz_a.country[i] && tz_a.cc[i])
+ g_snprintf(s_country, 100, "%s (%s)"
+ , tz_a.country[i], tz_a.cc[i]);
+ else
+ strcpy(s_country, " ");
+ g_snprintf(s_changes, 200, "%s\n%s"
+ , (tz_a.prev[i]) ? tz_a.prev[i] : _("not changed")
, (tz_a.next[i]) ? tz_a.next[i] : _("not changing"));
- else
- strcpy(s_next, " ");
+ }
+ else {
+ strcpy(s_country, " ");
+ strcpy(s_changes, " ");
+ }
gtk_tree_store_set(store, &iter2
, LOCATION, _(tz_a.city[i])
, LOCATION_ENG, tz_a.city[i]
, OFFSET, s_offset
+ , CHANGES, s_changes
, COUNTRY, s_country
- , NEXT_CHANGE, s_next
, -1);
}
return(store);
@@ -220,20 +263,20 @@ GtkWidget *tz_button_create_view(gboolean details, GtkTreeStore *store)
if (details) {
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Country")
- , rend, "text", COUNTRY, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Previous/Next Change")
+ , rend, "text", CHANGES, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Next Change")
- , rend, "text", NEXT_CHANGE, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Country")
+ , rend, "text", COUNTRY, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
}
return(tree);
}
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz)
+ , gchar **tz, gboolean check_ical, char *local_tz)
{
#undef P_N
#define P_N "orage_timezone_button_clicked: "
@@ -243,30 +286,39 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
GtkWidget *window;
GtkWidget *sw;
int result;
- char *loc, *loc_eng;
+ char *loc = NULL, *loc_eng = NULL;
GtkTreeSelection *sel;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean changed = FALSE;
gboolean details = FALSE;
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
/* show it */
- window = gtk_dialog_new_with_buttons(_("Pick timezone")
- , parent
- , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
- , _("Change mode"), 4
- , _("UTC"), 1
- /* , _("floating"), 2 */
- /* , _(g_par.local_timezone), 3 */
- , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
- , NULL);
+ if (check_ical)
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , _("floating"), 3
+ , _(local_tz), 4
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
+ else
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), sw, TRUE, TRUE, 0);
- gtk_window_set_default_size(GTK_WINDOW(window), 610, 500);
+ gtk_window_set_default_size(GTK_WINDOW(window), 750, 500);
gtk_widget_show_all(window);
do {
@@ -280,50 +332,53 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
else {
gtk_tree_model_get(model, &iter, LOCATION, &loc, -1);
gtk_tree_model_get(model, &iter, LOCATION_ENG, &loc_eng
- , -1); }
+ , -1);
+ }
else {
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
}
break;
case 1:
- loc = g_strdup(_("UTC"));
- loc_eng = g_strdup("UTC");
- break;
- /*
- case 2:
- loc = g_strdup(_("floating"));
- loc_eng = g_strdup("floating");
- break;
- case 3:
- loc = g_strdup(_(g_par.local_timezone));
- loc_eng = g_strdup(g_par.local_timezone);
- break;
- */
- case 4:
free_orage_timezones(details);
details = !details;
/* gtk_widget_destroy(GTK_WIDGET(store)); */
gtk_widget_destroy(tree);
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_widget_show_all(tree);
result = 0;
break;
+ case 2:
+ loc = g_strdup(_("UTC"));
+ loc_eng = g_strdup("UTC");
+ break;
+ case 3:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_("floating"));
+ loc_eng = g_strdup("floating");
+ break;
+ case 4:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_(local_tz));
+ loc_eng = g_strdup(local_tz);
+ break;
default:
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
break;
}
} while (result == 0);
- if (g_ascii_strcasecmp(loc, (gchar *)gtk_button_get_label(button)) != 0)
+ if (loc && g_ascii_strcasecmp(loc, gtk_button_get_label(button))) {
changed = TRUE;
- gtk_button_set_label(button, loc);
-
- if (*tz)
- g_free(*tz);
- *tz = g_strdup(loc_eng);
+ /* return the real timezone and update the button to show the
+ * translated timezone name */
+ if (*tz)
+ g_free(*tz);
+ *tz = g_strdup(loc_eng);
+ gtk_button_set_label(button, loc);
+ }
g_free(loc);
g_free(loc_eng);
gtk_widget_destroy(window);
diff --git a/panel-plugin/timezone_selection.h b/panel-plugin/timezone_selection.h
index 2f0e3af..e181a41 100644
--- a/panel-plugin/timezone_selection.h
+++ b/panel-plugin/timezone_selection.h
@@ -24,6 +24,6 @@
#define __TIMEZONE_SELECTION_H__
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz);
+ , gchar **tz, gboolean check_ical, char *local_tz);
#endif /* !__TIMEZONE_SELECTION_H__ */
diff --git a/panel-plugin/tz_zoneinfo_read.c b/panel-plugin/tz_zoneinfo_read.c
index b3a08d4..508b427 100644
--- a/panel-plugin/tz_zoneinfo_read.c
+++ b/panel-plugin/tz_zoneinfo_read.c
@@ -59,65 +59,73 @@
/** This is the toplevel directory where the timezone data is installed in. */
-#define ORAGE_ZONEINFO_DIRECTORY PACKAGE_DATA_DIR "/orage/zoneinfo"
+#define ORAGE_ZONEINFO_DIRECTORY PACKAGE_DATA_DIR "/orage/zoneinfo/"
/** This is the filename of the file containing tz_convert parameters
* This file contains the location of the os zoneinfo data.
* the same than the above DEFAULT_OS_ZONEINFO_DIRECTORY */
#define TZ_CONVERT_PAR_FILENAME "tz_convert.par"
-#define TZ_CONVERT_PAR_FILE_LOC ORAGE_ZONEINFO_DIRECTORY "/" TZ_CONVERT_PAR_FILENAME
+#define TZ_CONVERT_PAR_FILE_LOC ORAGE_ZONEINFO_DIRECTORY TZ_CONVERT_PAR_FILENAME
+
+/** This is the filename of the file containing orage ical timezone names */
+#define ICAL_ZONES_TAB_FILENAME "zones.tab"
+#define ICAL_ZONES_TAB_FILE_LOC ORAGE_ZONEINFO_DIRECTORY ICAL_ZONES_TAB_FILENAME
/* this contains all timezone data */
orage_timezone_array tz_array={0, NULL, NULL, NULL, NULL, NULL, NULL};
-char *zone_tab_buf = NULL, *country_buf = NULL;
+static char *zone_tab_buf = NULL, *country_buf = NULL, *zones_tab_buf = NULL;
-int debug = 0; /* bigger number => more output */
-char version[] = "1.4.4";
-int file_cnt = 0; /* number of processed files */
+static int debug = 0; /* bigger number => more output */
+static char version[] = "1.4.4";
+static int file_cnt = 0; /* number of processed files */
-unsigned char *in_buf, *in_head, *in_tail;
-int in_file_base_offset = 0;
+static unsigned char *in_buf, *in_head, *in_tail;
+static int in_file_base_offset = 0;
-int details;
+static int details; /* show extra data (country and next change time) */
+static int check_ical; /* check that we have also the ical timezone data */
-char *in_file = NULL, *out_file = NULL;
-int in_file_is_dir = 0;
-int excl_dir_cnt = -1;
-char **excl_dir = NULL;
+static char *in_file = NULL, *out_file = NULL;
+static int in_file_is_dir = 0;
+static int excl_dir_cnt = -1;
+static char **excl_dir = NULL;
/* in_timezone_name is the real timezone name from the infile
* we are processing.
- * in_timezone_name is the timezone we are writing. Usually it is the same
+ * timezone_name is the timezone we are writing. Usually it is the same
* than in_timezone_name.
- * timezone name is for example Europe/Helsinki */
-char *timezone_name = NULL;
-char *in_timezone_name = NULL;
+ * timezone_name is for example Europe/Helsinki */
+/* FIXME: we do not need both timezone_name and in_timezone_name here.
+ * Remove one */
+static char *timezone_name = NULL;
+static char *in_timezone_name = NULL;
-int ignore_older = 1970; /* Ignore rules which are older or equal than this */
+/* Ignore rules which are older or equal than this */
+static int ignore_older = 1970;
/* time change table starts here */
-unsigned char *begin_timechanges;
+static unsigned char *begin_timechanges;
/* time change type index table starts here */
-unsigned char *begin_timechangetypeindexes;
+static unsigned char *begin_timechangetypeindexes;
/* time change type table starts here */
-unsigned char *begin_timechangetypes;
+static unsigned char *begin_timechangetypes;
/* timezone name table */
-unsigned char *begin_timezonenames;
+static unsigned char *begin_timezonenames;
-unsigned long gmtcnt;
-unsigned long stdcnt;
-unsigned long leapcnt;
-unsigned long timecnt; /* points when time changes */
-unsigned long typecnt; /* table of different time changes = types */
-unsigned long charcnt; /* length of timezone name table */
+static unsigned long gmtcnt;
+static unsigned long stdcnt;
+static unsigned long leapcnt;
+static unsigned long timecnt; /* points when time changes */
+static unsigned long typecnt; /* table of different time changes = types */
+static unsigned long charcnt; /* length of timezone name table */
-void read_file(const char *file_name, const struct stat *file_stat)
+static void read_file(const char *file_name, const struct stat *file_stat)
{
FILE *file;
@@ -136,7 +144,7 @@ void read_file(const char *file_name, const struct stat *file_stat)
printf("read_file: end\n");
}
-long get_long()
+static long get_long()
{
unsigned long tmp;
@@ -148,7 +156,7 @@ long get_long()
return(tmp);
}
-int process_header()
+static int process_header()
{
if (debug > 2)
printf("file id: %s\n", in_head);
@@ -180,7 +188,7 @@ int process_header()
return(0);
}
-process_local_time_table()
+static process_local_time_table()
{ /* points when time changes */
unsigned long tmp;
int i;
@@ -199,7 +207,7 @@ process_local_time_table()
}
}
-process_local_time_type_table()
+static process_local_time_type_table()
{ /* pointers to table, which explain how time changes */
unsigned char tmp;
int i;
@@ -215,7 +223,7 @@ process_local_time_type_table()
}
}
-process_ttinfo_table()
+static process_ttinfo_table()
{ /* table of different time changes = types */
long tmp;
unsigned char tmp2, tmp3;
@@ -236,7 +244,7 @@ process_ttinfo_table()
}
}
-process_abbr_table()
+static process_abbr_table()
{
unsigned char *tmp;
int i;
@@ -253,7 +261,7 @@ process_abbr_table()
in_head += charcnt;
}
-process_leap_table()
+static process_leap_table()
{
unsigned long tmp, tmp2;
int i;
@@ -269,7 +277,7 @@ process_leap_table()
}
}
-process_std_table()
+static process_std_table()
{
unsigned char tmp;
int i;
@@ -284,7 +292,7 @@ process_std_table()
}
}
-process_gmt_table()
+static process_gmt_table()
{
unsigned char tmp;
int i;
@@ -301,7 +309,7 @@ process_gmt_table()
/* go through the contents of the file and find the positions of
* needed data. Uses global pointer: in_head */
-int process_file(const char *file_name)
+static int process_file(const char *file_name)
{
if (debug > 1)
printf("\n\nprocess_file: start\n");
@@ -323,10 +331,10 @@ int process_file(const char *file_name)
return(0); /* ok */
}
-void get_country()
+static void get_country()
{ /* tz_array.city[tz_array.count] contains the city name.
We will find corresponding country and fill it to the table */
- char *str, *str_nl;
+ char *str, *str_nl, cc[4];
if (!(str = strstr(zone_tab_buf, tz_array.city[tz_array.count])))
return; /* not found */
@@ -343,12 +351,19 @@ void get_country()
strncpy(tz_array.cc[tz_array.count], ++str_nl, 2);
tz_array.cc[tz_array.count][2] = '\0';
- /* then search the country */
- if (!(str = strstr(country_buf, tz_array.cc[tz_array.count])))
+ /********** then search the country **********/
+ /* Need to search line, which starts with country code.
+ * Note that it is not enough to search any country coed, but it really
+ * needs to be the first two chars in the line */
+ cc[0] = '\n';
+ cc[1] = tz_array.cc[tz_array.count][0];
+ cc[2] = tz_array.cc[tz_array.count][1];
+ cc[3] = '\0';
+ if (!(str = strstr(country_buf, cc)))
return; /* not found */
/* country name is after the country code and a single tab */
- str += 3;
- /* but w still need to find how long it is.
+ str += 4;
+ /* but we still need to find how long it is.
* It ends in the line end.
* (There is a line end at the end of the file also.) */
for (str_nl = str; str_nl[0] != '\n'; str_nl++)
@@ -358,16 +373,28 @@ void get_country()
tz_array.country[tz_array.count][(str_nl - str)] = '\0';
}
+static int timezone_exists_in_ical()
+{ /* in_timezone_name contains the timezone name.
+ We will search if it exists also in the ical zones.tab file */
+ char *str;
+
+ if (str = strstr(zones_tab_buf, in_timezone_name))
+ return(1); /* yes, it is there */
+ else
+ return(0); /* not found */
+}
+
/* FIXME: need to check that if OUTFILE is given as a parameter,
* INFILE is not a directory (or make outfile to act like directory also ? */
-int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
+static int write_ical_file(const char *in_file_name
+ , const struct stat *in_file_stat)
{
int i;
unsigned int tct_i, abbr_i;
struct tm cur_gm_time;
time_t tt_now = time(NULL);
- long tc_time = 0; /* TimeChange time */
- char s_next[101];
+ long tc_time = 0, prev_tc_time; /* TimeChange times */
+ char s_next[101], s_prev[101];
if (debug > 1)
printf("***** write_ical_file: start *****\n\n");
@@ -384,6 +411,7 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
/* search for current time setting.
* timecnt tells how many changes we have in the tz file.
* i points to the next value to read. */
+ prev_tc_time = tc_time;
tc_time = get_long(); /* start time of this timechange */
}
/* i points to the next value to be read, so need to -- */
@@ -393,7 +421,9 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = "UTC";
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.count++;
return(1); /* done */
}
@@ -401,16 +431,52 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
/* we found previous and next value */
/* tc_time has the next change time */
if (details) {
+ /* NOTE: If the time change happens for example at 04:00
+ * and goes one hour backward, the new time is 03:00 and this
+ * is what localtime_r reports. In real life we want to show
+ * here 04:00, so let's subtract 1 sec to get close to that.
+ * This is a bit similar than 24:00 or 00:00. Summary:
+ * 04:00 is returned as 03:00 (change happened already) but
+ * 03:59 is returned as 03:59 (change did not yet happen) */
+ prev_tc_time -= 1;
+ localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+ strftime(s_prev, 100, "%c", &cur_gm_time);
+ tz_array.prev[tz_array.count] = strdup(s_prev);
+
+ tc_time -= 1;
localtime_r((const time_t *)&tc_time, &cur_gm_time);
strftime(s_next, 100, "%c", &cur_gm_time);
tz_array.next[tz_array.count] = strdup(s_next);
+ /* get timechange type index */
+ if (timecnt) {
+ in_head = begin_timechangetypeindexes;
+ tct_i = (unsigned int)in_head[i];
+ }
+ else
+ tct_i = 0;
+
+ /* get timechange type */
+ in_head = begin_timechangetypes;
+ in_head += 6*tct_i;
+ tz_array.next_utc_offset[tz_array.count] = (int)get_long();
}
- else
+ else {
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ }
i--; /* we need to take the previous value */
}
- else
+ else { /* no next value, but previous may exist */
tz_array.next[tz_array.count] = NULL;
+ if (details && prev_tc_time) {
+ prev_tc_time -= 1;
+ localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+ strftime(s_prev, 100, "%c", &cur_gm_time);
+ tz_array.prev[tz_array.count] = strdup(s_prev);
+ }
+ else
+ tz_array.prev[tz_array.count] = NULL;
+ }
/* i now points to latest time change and shows current time.
* So we found our result and can start collecting real data: */
@@ -441,7 +507,7 @@ int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
}
/* The main code. This is called once per each file found */
-int file_call(const char *file_name, const struct stat *sb, int flags
+static int file_call(const char *file_name, const struct stat *sb, int flags
, struct FTW *f)
{
int i;
@@ -453,14 +519,21 @@ int file_call(const char *file_name, const struct stat *sb, int flags
if (flags == FTW_F) { /* we got file */
if (debug > 0)
printf("\t\tfile_call: processing file=(%s)\n", file_name);
+ in_timezone_name = strdup(&file_name[in_file_base_offset
+ + strlen("zoneinfo/")]);
+ timezone_name = strdup(in_timezone_name);
+ if (check_ical && !timezone_exists_in_ical()) {
+ free(in_timezone_name);
+ free(timezone_name);
+ return(FTW_CONTINUE);
+ }
read_file(file_name, sb);
if (process_file(file_name)) { /* we skipped this file */
+ free(in_timezone_name);
+ free(timezone_name);
free(in_buf);
return(FTW_CONTINUE);
}
- in_timezone_name = strdup(&file_name[in_file_base_offset
- + strlen("zoneinfo/")]);
- timezone_name = strdup(in_timezone_name);
write_ical_file(file_name, sb);
free(in_buf);
@@ -499,7 +572,7 @@ int file_call(const char *file_name, const struct stat *sb, int flags
}
/* check the parameters and use defaults when possible */
-int check_parameters()
+static int check_parameters()
{
char *s_tz, *last_tz = NULL, tz[]="/zoneinfo", tz2[]="zoneinfo/";
int tz_len, i;
@@ -630,7 +703,7 @@ int check_parameters()
return(0); /* continue */
}
-void read_countries()
+static void read_countries()
{
char *tz_dir, *zone_tab_file_name, *country_file_name;
int zoneinfo_len=strlen("zoneinfo/");
@@ -730,7 +803,40 @@ void read_countries()
fclose(country_file);
}
-orage_timezone_array get_orage_timezones(int show_details)
+static void read_ical_timezones()
+{
+ FILE *zones_tab_file;
+ struct stat zones_tab_file_stat;
+
+ /****** zones.tab file ******/
+ if (!(zones_tab_file = fopen(ICAL_ZONES_TAB_FILE_LOC, "r"))) {
+ printf("read_ical_timezones: zones.tab file open failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ perror("\tfopen");
+ return;
+ }
+ if (stat(ICAL_ZONES_TAB_FILE_LOC, &zones_tab_file_stat) == -1) {
+ printf("read_ical_timezones: zones.tab file stat failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ fclose(zones_tab_file);
+ perror("\tstat");
+ return;
+ }
+ zones_tab_buf = malloc(zones_tab_file_stat.st_size+1);
+ fread(zones_tab_buf, 1, zones_tab_file_stat.st_size, zones_tab_file);
+ if (ferror(zones_tab_file)) {
+ printf("read_ical_timezones: zones.tab file read failed (%s)\n"
+ , ICAL_ZONES_TAB_FILE_LOC);
+ perror("\tfread");
+ return;
+ }
+ zones_tab_buf[zones_tab_file_stat.st_size] = '\0';
+ printf("read_ical_timezones: zones.tab file read (%s) (%d bytes)\n"
+ , ICAL_ZONES_TAB_FILE_LOC, strlen(zones_tab_buf));
+ fclose(zones_tab_file);
+}
+
+orage_timezone_array get_orage_timezones(int show_details, int ical)
{
int tz_array_size = 1000; /* FIXME: this needs to be counted */
/*
@@ -740,12 +846,15 @@ orage_timezone_array get_orage_timezones(int show_details)
*/
details = show_details;
+ check_ical = ical;
if (tz_array.count == 0) {
tz_array.city = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.dst = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.tz = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+ tz_array.prev = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.next = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+ tz_array.next_utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.country = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.cc = (char **)malloc(sizeof(char *)*(tz_array_size+2));
/* nftw goes through the whole file structure and calls "file_call"
@@ -756,6 +865,8 @@ orage_timezone_array get_orage_timezones(int show_details)
printf("Processing %s files\n", in_file);
if (details)
read_countries();
+ if (check_ical)
+ read_ical_timezones();
if (nftw(in_file, file_call, 10, FTW_PHYS | FTW_ACTIONRETVAL) == -1) {
perror("nftw error in file handling");
exit(EXIT_FAILURE);
@@ -768,7 +879,9 @@ orage_timezone_array get_orage_timezones(int show_details)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = strdup("UTC");
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("UTC");
@@ -776,12 +889,14 @@ orage_timezone_array get_orage_timezones(int show_details)
tz_array.utc_offset[tz_array.count] = 0;
tz_array.dst[tz_array.count] = 0;
tz_array.tz[tz_array.count] = NULL;
+ tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("floating");
}
- return (tz_array);
+ return(tz_array);
}
void free_orage_timezones(int show_details)
@@ -793,6 +908,8 @@ void free_orage_timezones(int show_details)
free(tz_array.city[i]);
if (tz_array.tz[i])
free(tz_array.tz[i]);
+ if (tz_array.prev[i])
+ free(tz_array.prev[i]);
if (tz_array.next[i])
free(tz_array.next[i]);
if (tz_array.country[i])
@@ -804,10 +921,24 @@ void free_orage_timezones(int show_details)
free(tz_array.utc_offset);
free(tz_array.dst);
free(tz_array.tz);
+ free(tz_array.prev);
free(tz_array.next);
+ free(tz_array.next_utc_offset);
free(tz_array.country);
free(tz_array.cc);
tz_array.count = 0;
timezone_name = NULL;
+ if (zone_tab_buf) {
+ free(zone_tab_buf);
+ zone_tab_buf = NULL;
+ }
+ if (country_buf) {
+ free(country_buf);
+ country_buf = NULL;
+ }
+ if (zones_tab_buf) {
+ free(zones_tab_buf);
+ zones_tab_buf = NULL;
+ }
file_cnt = 0; /* number of processed files */
}
diff --git a/panel-plugin/tz_zoneinfo_read.h b/panel-plugin/tz_zoneinfo_read.h
index 9002f44..7b5c634 100644
--- a/panel-plugin/tz_zoneinfo_read.h
+++ b/panel-plugin/tz_zoneinfo_read.h
@@ -25,10 +25,12 @@ typedef struct _orage_timezone_array
int *utc_offset; /* pointer to int array holding utc offsets */
int *dst; /* pointer to int array holding dst settings */
char **tz; /* pointer to timezone name strings */
+ char **prev; /* pointer to previous time change strings */
char **next; /* pointer to next time change strings */
+ int *next_utc_offset; /* pointer to int array holding utc offsets */
char **country; /* pointer to country name strings */
char **cc; /* pointer to country code strings */
} orage_timezone_array;
-orage_timezone_array get_orage_timezones(int details);
+orage_timezone_array get_orage_timezones(int details, int ical);
void free_orage_timezones(int details);
diff --git a/panel-plugin/xfce4-orageclock-plugin.h b/panel-plugin/xfce4-orageclock-plugin.h
index f325e77..85e7ffa 100644
--- a/panel-plugin/xfce4-orageclock-plugin.h
+++ b/panel-plugin/xfce4-orageclock-plugin.h
@@ -50,7 +50,6 @@ typedef struct _clock
GdkColor bg;
GString *timezone;
gchar *TZ_orig;
- GtkWidget *tz_entry;
ClockLine line[OC_MAX_LINES];
GString *tooltip_data;
gchar tooltip_prev[OC_MAX_LINE_LENGTH+1];
diff --git a/src/appointment.c b/src/appointment.c
index 4a5c876..fe1d3c6 100644
--- a/src/appointment.c
+++ b/src/appointment.c
@@ -1305,7 +1305,7 @@ static void on_appStartTimezone_clicked_cb(GtkButton *button
appt = (xfical_appt *)apptw->xf_appt;
if (orage_timezone_button_clicked(button, GTK_WINDOW(apptw->Window)
- , &appt->start_tz_loc))
+ , &appt->start_tz_loc, TRUE, g_par.local_timezone))
mark_appointment_changed(apptw);
}
@@ -1317,7 +1317,7 @@ static void on_appEndTimezone_clicked_cb(GtkButton *button
appt = (xfical_appt *)apptw->xf_appt;
if (orage_timezone_button_clicked(button, GTK_WINDOW(apptw->Window)
- , &appt->end_tz_loc))
+ , &appt->end_tz_loc, TRUE, g_par.local_timezone))
mark_appointment_changed(apptw);
}
@@ -1329,7 +1329,7 @@ static void on_appCompletedTimezone_clicked_cb(GtkButton *button
appt = (xfical_appt *)apptw->xf_appt;
if (orage_timezone_button_clicked(button, GTK_WINDOW(apptw->Window)
- , &appt->completed_tz_loc))
+ , &appt->completed_tz_loc, TRUE, g_par.local_timezone))
mark_appointment_changed(apptw);
}
diff --git a/src/parameters.c b/src/parameters.c
index 2c49725..89b14d3 100644
--- a/src/parameters.c
+++ b/src/parameters.c
@@ -444,7 +444,7 @@ static void timezone_button_clicked(GtkButton *button, gpointer user_data)
g_par.local_timezone = g_strdup("floating");
}
if (orage_timezone_button_clicked(button, GTK_WINDOW(itf->orage_dialog)
- , &g_par.local_timezone))
+ , &g_par.local_timezone, TRUE, g_par.local_timezone))
xfical_set_local_timezone(FALSE);
}
diff --git a/src/timezone_selection.c b/src/timezone_selection.c
index e5eafa7..44e18a9 100644
--- a/src/timezone_selection.c
+++ b/src/timezone_selection.c
@@ -66,13 +66,13 @@ enum {
LOCATION,
LOCATION_ENG,
OFFSET,
+ CHANGES,
COUNTRY,
- PREV_CHANGE,
- NEXT_CHANGE,
N_COLUMNS
};
-static GtkTreeStore *tz_button_create_store(gboolean details)
+static GtkTreeStore *tz_button_create_store(gboolean details
+ , gboolean check_ical)
{
#undef P_N
#define P_N "tz_button_create_store: "
@@ -82,14 +82,16 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
GtkTreeIter iter1, iter2, main;
orage_timezone_array tz_a;
char area_old[MAX_AREA_LENGTH+2]; /*+2 = / + null */
- char s_offset[100], s_country[100], s_next[100], s_prev[100];
- gint i, j, offs_hour, offs_min;
+ char s_offset[100], s_country[100], s_changes[200], s_change[50]
+ , s_change_time[50];
+ gint i, j, offs_hour, offs_min, next_offs_hour, next_offs_min
+ , change_time, change_hour, change_min;
store = gtk_tree_store_new(N_COLUMNS
, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING
- , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+ , G_TYPE_STRING, G_TYPE_STRING);
strcpy(area_old, "S T a R T"); /* this never matches */
- tz_a = get_orage_timezones(details, 1);
+ tz_a = get_orage_timezones(details, check_ical ? 1 : 0);
/*
g_print(P_N "number of timezones %d\n", tz_a.count);
*/
@@ -100,9 +102,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(" Other")
, LOCATION_ENG, " Other"
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , PREV_CHANGE, " "
- , NEXT_CHANGE, " "
, -1);
main = iter1; /* need to remember that */
@@ -125,9 +126,8 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
, LOCATION, _(area_old)
, LOCATION_ENG, area_old
, OFFSET, " "
+ , CHANGES, " "
, COUNTRY, " "
- , PREV_CHANGE, " "
- , NEXT_CHANGE, " "
, -1);
/* let's make sure we do not match accidentally to those
* plain names on main level. We do this by adding / */
@@ -135,7 +135,7 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
area_old[j] = 0;
}
else {
- orage_message(310, P_N "too long line in zones.tab %s", tz_a.city[i]);
+ g_print(P_N "too long line in zones.tab %s", tz_a.city[i]);
}
}
/* then city translated and in base form used internally */
@@ -146,34 +146,66 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
if (offs_min)
g_print(P_N " %s offset %d hour %d minutes %d\n", tz_a.city[i], tz_a.utc_offset[i], offs_hour, offs_min);
*/
- g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
- , offs_hour, offs_min
- , (tz_a.dst[i]) ? "dst" : "std"
- , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
+ if (details && tz_a.next[i]) {
+ next_offs_hour = tz_a.next_utc_offset[i] / (60*60);
+ next_offs_min = abs((tz_a.next_utc_offset[i]
+ - next_offs_hour * (60*60)) / 60);
+ change_time = tz_a.next_utc_offset[i] - tz_a.utc_offset[i];
+ change_hour = change_time / (60*60);
+ change_min = abs((change_time - change_hour * (60*60)) /60);
+ if (change_hour && change_min)
+ g_snprintf(s_change_time, 50, _("%d hour %d mins")
+ , abs(change_hour), change_min);
+ else if (change_hour)
+ g_snprintf(s_change_time, 50, _("%d hour"), abs(change_hour));
+ else if (change_min)
+ g_snprintf(s_change_time, 50, _("%d mins"), change_min);
+ else
+ strcpy(s_change_time, " ");
+
+ if (change_time < 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("backward"), s_change_time);
+ else if (change_time > 0)
+ g_snprintf(s_change, 50, "(%s %s)"
+ , _("forward"), s_change_time);
+ else
+ strcpy(s_change, " ");
+ g_snprintf(s_offset, 100
+ , "%+03d:%02d %s (%s)\n -> %+03d:%02d %s"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-"
+ , next_offs_hour, next_offs_min
+ , s_change);
+ }
+ else {
+ g_snprintf(s_offset, 100, "%+03d:%02d %s (%s)"
+ , offs_hour, offs_min
+ , (tz_a.dst[i]) ? "dst" : "std"
+ , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
+ }
if (details) {
if (tz_a.country[i] && tz_a.cc[i])
g_snprintf(s_country, 100, "%s (%s)"
, tz_a.country[i], tz_a.cc[i]);
- else
+ else
strcpy(s_country, " ");
- g_snprintf(s_prev, 100, "%s"
- , (tz_a.prev[i]) ? tz_a.prev[i] : _("not changed"));
- g_snprintf(s_next, 100, "%s"
+ g_snprintf(s_changes, 200, "%s\n%s"
+ , (tz_a.prev[i]) ? tz_a.prev[i] : _("not changed")
, (tz_a.next[i]) ? tz_a.next[i] : _("not changing"));
}
else {
strcpy(s_country, " ");
- strcpy(s_prev, " ");
- strcpy(s_next, " ");
+ strcpy(s_changes, " ");
}
gtk_tree_store_set(store, &iter2
, LOCATION, _(tz_a.city[i])
, LOCATION_ENG, tz_a.city[i]
, OFFSET, s_offset
+ , CHANGES, s_changes
, COUNTRY, s_country
- , PREV_CHANGE, s_prev
- , NEXT_CHANGE, s_next
, -1);
}
return(store);
@@ -230,25 +262,20 @@ GtkWidget *tz_button_create_view(gboolean details, GtkTreeStore *store)
if (details) {
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Country")
- , rend, "text", COUNTRY, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
-
- rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Previous Change")
- , rend, "text", PREV_CHANGE, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Previous/Next Change")
+ , rend, "text", CHANGES, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
rend = gtk_cell_renderer_text_new();
- col = gtk_tree_view_column_new_with_attributes(_("Next Change")
- , rend, "text", NEXT_CHANGE, NULL);
+ col = gtk_tree_view_column_new_with_attributes(_("Country")
+ , rend, "text", COUNTRY, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
}
return(tree);
}
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz)
+ , gchar **tz, gboolean check_ical, char *local_tz)
{
#undef P_N
#define P_N "orage_timezone_button_clicked: "
@@ -258,33 +285,39 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
GtkWidget *window;
GtkWidget *sw;
int result;
- char *loc, *loc_eng;
+ char *loc = NULL, *loc_eng = NULL;
GtkTreeSelection *sel;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean changed = FALSE;
gboolean details = FALSE;
-#ifdef ORAGE_DEBUG
- orage_message(-100, P_N);
-#endif
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
/* show it */
- window = gtk_dialog_new_with_buttons(_("Pick timezone")
- , parent
- , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
- , _("Change mode"), 4
- , _("UTC"), 1
- , _("floating"), 2
- , _(g_par.local_timezone), 3
- , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
- , NULL);
+ if (check_ical)
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , _("floating"), 3
+ , _(local_tz), 4
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
+ else
+ window = gtk_dialog_new_with_buttons(_("Pick timezone")
+ , parent
+ , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ , _("Change mode"), 1
+ , _("UTC"), 2
+ , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+ , NULL);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), sw, TRUE, TRUE, 0);
- gtk_window_set_default_size(GTK_WINDOW(window), 610, 500);
+ gtk_window_set_default_size(GTK_WINDOW(window), 750, 500);
gtk_widget_show_all(window);
do {
@@ -298,48 +331,53 @@ gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
else {
gtk_tree_model_get(model, &iter, LOCATION, &loc, -1);
gtk_tree_model_get(model, &iter, LOCATION_ENG, &loc_eng
- , -1); }
+ , -1);
+ }
else {
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
}
break;
case 1:
- loc = g_strdup(_("UTC"));
- loc_eng = g_strdup("UTC");
- break;
- case 2:
- loc = g_strdup(_("floating"));
- loc_eng = g_strdup("floating");
- break;
- case 3:
- loc = g_strdup(_(g_par.local_timezone));
- loc_eng = g_strdup(g_par.local_timezone);
- break;
- case 4:
free_orage_timezones(details);
details = !details;
/* gtk_widget_destroy(GTK_WIDGET(store)); */
gtk_widget_destroy(tree);
- store = tz_button_create_store(details);
+ store = tz_button_create_store(details, check_ical);
tree = tz_button_create_view(details, store);
gtk_container_add(GTK_CONTAINER(sw), tree);
gtk_widget_show_all(tree);
result = 0;
break;
+ case 2:
+ loc = g_strdup(_("UTC"));
+ loc_eng = g_strdup("UTC");
+ break;
+ case 3:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_("floating"));
+ loc_eng = g_strdup("floating");
+ break;
+ case 4:
+ /* NOTE: this exists only if ical timezones are being used */
+ loc = g_strdup(_(local_tz));
+ loc_eng = g_strdup(local_tz);
+ break;
default:
loc = g_strdup(_(*tz));
loc_eng = g_strdup(*tz);
break;
}
} while (result == 0);
- if (g_ascii_strcasecmp(loc, (gchar *)gtk_button_get_label(button)) != 0)
+ if (loc && g_ascii_strcasecmp(loc, gtk_button_get_label(button))) {
changed = TRUE;
- gtk_button_set_label(button, loc);
-
- if (*tz)
- g_free(*tz);
- *tz = g_strdup(loc_eng);
+ /* return the real timezone and update the button to show the
+ * translated timezone name */
+ if (*tz)
+ g_free(*tz);
+ *tz = g_strdup(loc_eng);
+ gtk_button_set_label(button, loc);
+ }
g_free(loc);
g_free(loc_eng);
gtk_widget_destroy(window);
diff --git a/src/timezone_selection.h b/src/timezone_selection.h
index 2f0e3af..e181a41 100644
--- a/src/timezone_selection.h
+++ b/src/timezone_selection.h
@@ -24,6 +24,6 @@
#define __TIMEZONE_SELECTION_H__
gboolean orage_timezone_button_clicked(GtkButton *button, GtkWindow *parent
- , gchar **tz);
+ , gchar **tz, gboolean check_ical, char *local_tz);
#endif /* !__TIMEZONE_SELECTION_H__ */
diff --git a/src/tz_zoneinfo_read.c b/src/tz_zoneinfo_read.c
index 8a48d02..508b427 100644
--- a/src/tz_zoneinfo_read.c
+++ b/src/tz_zoneinfo_read.c
@@ -72,6 +72,7 @@
#define ICAL_ZONES_TAB_FILE_LOC ORAGE_ZONEINFO_DIRECTORY ICAL_ZONES_TAB_FILENAME
+
/* this contains all timezone data */
orage_timezone_array tz_array={0, NULL, NULL, NULL, NULL, NULL, NULL};
@@ -97,7 +98,7 @@ static char **excl_dir = NULL;
* timezone_name is the timezone we are writing. Usually it is the same
* than in_timezone_name.
* timezone_name is for example Europe/Helsinki */
-/* FIXME: we do nto need both timezone_name and in_timezone_name here.
+/* FIXME: we do not need both timezone_name and in_timezone_name here.
* Remove one */
static char *timezone_name = NULL;
static char *in_timezone_name = NULL;
@@ -354,14 +355,14 @@ static void get_country()
/* Need to search line, which starts with country code.
* Note that it is not enough to search any country coed, but it really
* needs to be the first two chars in the line */
- cc[0] = '\n';
+ cc[0] = '\n';
cc[1] = tz_array.cc[tz_array.count][0];
cc[2] = tz_array.cc[tz_array.count][1];
cc[3] = '\0';
if (!(str = strstr(country_buf, cc)))
return; /* not found */
/* country name is after the country code and a single tab */
- str += 3;
+ str += 4;
/* but we still need to find how long it is.
* It ends in the line end.
* (There is a line end at the end of the file also.) */
@@ -379,7 +380,7 @@ static int timezone_exists_in_ical()
if (str = strstr(zones_tab_buf, in_timezone_name))
return(1); /* yes, it is there */
- else
+ else
return(0); /* not found */
}
@@ -422,6 +423,7 @@ static int write_ical_file(const char *in_file_name
tz_array.tz[tz_array.count] = "UTC";
tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.count++;
return(1); /* done */
}
@@ -429,22 +431,45 @@ static int write_ical_file(const char *in_file_name
/* we found previous and next value */
/* tc_time has the next change time */
if (details) {
+ /* NOTE: If the time change happens for example at 04:00
+ * and goes one hour backward, the new time is 03:00 and this
+ * is what localtime_r reports. In real life we want to show
+ * here 04:00, so let's subtract 1 sec to get close to that.
+ * This is a bit similar than 24:00 or 00:00. Summary:
+ * 04:00 is returned as 03:00 (change happened already) but
+ * 03:59 is returned as 03:59 (change did not yet happen) */
+ prev_tc_time -= 1;
localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
strftime(s_prev, 100, "%c", &cur_gm_time);
tz_array.prev[tz_array.count] = strdup(s_prev);
+
+ tc_time -= 1;
localtime_r((const time_t *)&tc_time, &cur_gm_time);
strftime(s_next, 100, "%c", &cur_gm_time);
tz_array.next[tz_array.count] = strdup(s_next);
+ /* get timechange type index */
+ if (timecnt) {
+ in_head = begin_timechangetypeindexes;
+ tct_i = (unsigned int)in_head[i];
+ }
+ else
+ tct_i = 0;
+
+ /* get timechange type */
+ in_head = begin_timechangetypes;
+ in_head += 6*tct_i;
+ tz_array.next_utc_offset[tz_array.count] = (int)get_long();
}
else {
- tz_array.next[tz_array.count] = NULL;
tz_array.prev[tz_array.count] = NULL;
+ tz_array.next[tz_array.count] = NULL;
}
i--; /* we need to take the previous value */
}
else { /* no next value, but previous may exist */
tz_array.next[tz_array.count] = NULL;
if (details && prev_tc_time) {
+ prev_tc_time -= 1;
localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
strftime(s_prev, 100, "%c", &cur_gm_time);
tz_array.prev[tz_array.count] = strdup(s_prev);
@@ -494,7 +519,7 @@ static int file_call(const char *file_name, const struct stat *sb, int flags
if (flags == FTW_F) { /* we got file */
if (debug > 0)
printf("\t\tfile_call: processing file=(%s)\n", file_name);
- in_timezone_name = strdup(&file_name[in_file_base_offset
+ in_timezone_name = strdup(&file_name[in_file_base_offset
+ strlen("zoneinfo/")]);
timezone_name = strdup(in_timezone_name);
if (check_ical && !timezone_exists_in_ical()) {
@@ -678,7 +703,6 @@ static int check_parameters()
return(0); /* continue */
}
-
static void read_countries()
{
char *tz_dir, *zone_tab_file_name, *country_file_name;
@@ -830,6 +854,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
tz_array.tz = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.prev = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.next = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+ tz_array.next_utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
tz_array.country = (char **)malloc(sizeof(char *)*(tz_array_size+2));
tz_array.cc = (char **)malloc(sizeof(char *)*(tz_array_size+2));
/* nftw goes through the whole file structure and calls "file_call"
@@ -856,6 +881,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
tz_array.tz[tz_array.count] = strdup("UTC");
tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("UTC");
@@ -865,6 +891,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
tz_array.tz[tz_array.count] = NULL;
tz_array.prev[tz_array.count] = NULL;
tz_array.next[tz_array.count] = NULL;
+ tz_array.next_utc_offset[tz_array.count] = 0;
tz_array.country[tz_array.count] = NULL;
tz_array.cc[tz_array.count] = NULL;
tz_array.city[tz_array.count++] = strdup("floating");
@@ -896,6 +923,7 @@ void free_orage_timezones(int show_details)
free(tz_array.tz);
free(tz_array.prev);
free(tz_array.next);
+ free(tz_array.next_utc_offset);
free(tz_array.country);
free(tz_array.cc);
tz_array.count = 0;
diff --git a/src/tz_zoneinfo_read.h b/src/tz_zoneinfo_read.h
index 1f70f73..7b5c634 100644
--- a/src/tz_zoneinfo_read.h
+++ b/src/tz_zoneinfo_read.h
@@ -27,6 +27,7 @@ typedef struct _orage_timezone_array
char **tz; /* pointer to timezone name strings */
char **prev; /* pointer to previous time change strings */
char **next; /* pointer to next time change strings */
+ int *next_utc_offset; /* pointer to int array holding utc offsets */
char **country; /* pointer to country name strings */
char **cc; /* pointer to country code strings */
} orage_timezone_array;
More information about the Xfce4-commits
mailing list