aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
authorDamon Chaplin <damon@helixcode.com>2000-09-30 23:29:22 +0800
committerDamon Chaplin <damon@src.gnome.org>2000-09-30 23:29:22 +0800
commit0ff98664ba2f06f71508288247b3b25ffb7f8f47 (patch)
tree8bf1505d4c16c605042d8ab058ee85099863b093 /calendar
parent32d2e7c670ebc72b8f60172e8f6fddcc5ae7f45d (diff)
downloadgsoc2013-evolution-0ff98664ba2f06f71508288247b3b25ffb7f8f47.tar.gz
gsoc2013-evolution-0ff98664ba2f06f71508288247b3b25ffb7f8f47.tar.zst
gsoc2013-evolution-0ff98664ba2f06f71508288247b3b25ffb7f8f47.zip
updated to support RDATE end times or durations. Note that if you have two
2000-09-29 Damon Chaplin <damon@helixcode.com> * cal-util/cal-recur.c: updated to support RDATE end times or durations. Note that if you have two RDATEs with the same start times, but with different end dates/durations set, the results are unpredictable. So the event editor dialog should check for this. * gui/e-week-view-main-item.c (e_week_view_main_item_draw_day): make strftime() strings translatable, and changed the formats a bit. * NOTE: someone needs to check print.c to make sure strftime strings are OK for i18n. * gui/e-day-view.h: Changed EDayViewDateFormat enum. We now try to include the weekday if possible. Also changed EDayView struct so we store the month & weekdays with the longest names rather than the actual widths. This helps i18n. * gui/e-day-view.c (e_day_view_recalc_cell_sizes): used _() for strftime strings, tried to see if weekday fits, and rearranged a bit to make i18n easier. * gui/e-day-view-top-item.c (e_day_view_top_item_draw): used _() for strftime strings, and updated to use new formats. * gui/calendar-model.c: added use_24_hour_format boolean to CalendarModelPrivate so we can display dates in 12-hour format if requested. This meant adding a CalendarModel argument to a few functions. Also added get/set functions to set use_24_hour_format. I suppose ideally we should have an ECellDate renderer and this option should go there. svn path=/trunk/; revision=5646
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog32
-rw-r--r--calendar/cal-util/cal-recur.c294
-rw-r--r--calendar/cal-util/cal-recur.h60
-rw-r--r--calendar/cal-util/test-recur.c1
-rw-r--r--calendar/gui/calendar-model.c249
-rw-r--r--calendar/gui/calendar-model.h5
-rw-r--r--calendar/gui/e-day-view-top-item.c18
-rw-r--r--calendar/gui/e-day-view.c138
-rw-r--r--calendar/gui/e-day-view.h17
-rw-r--r--calendar/gui/e-week-view-main-item.c33
10 files changed, 621 insertions, 226 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index f8d5f360b7..ef896182e1 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,35 @@
+2000-09-29 Damon Chaplin <damon@helixcode.com>
+
+ * cal-util/cal-recur.c: updated to support RDATE end times or
+ durations. Note that if you have two RDATEs with the same start times,
+ but with different end dates/durations set, the results are
+ unpredictable. So the event editor dialog should check for this.
+
+ * gui/e-week-view-main-item.c (e_week_view_main_item_draw_day):
+ make strftime() strings translatable, and changed the formats a bit.
+
+ * NOTE: someone needs to check print.c to make sure strftime strings
+ are OK for i18n.
+
+ * gui/e-day-view.h: Changed EDayViewDateFormat enum. We now try to
+ include the weekday if possible. Also changed EDayView struct so we
+ store the month & weekdays with the longest names rather than the
+ actual widths. This helps i18n.
+
+ * gui/e-day-view.c (e_day_view_recalc_cell_sizes): used _() for
+ strftime strings, tried to see if weekday fits, and rearranged a
+ bit to make i18n easier.
+
+ * gui/e-day-view-top-item.c (e_day_view_top_item_draw): used _() for
+ strftime strings, and updated to use new formats.
+
+ * gui/calendar-model.c: added use_24_hour_format boolean to
+ CalendarModelPrivate so we can display dates in 12-hour format if
+ requested. This meant adding a CalendarModel argument to a few
+ functions. Also added get/set functions to set use_24_hour_format.
+ I suppose ideally we should have an ECellDate renderer and this option
+ should go there.
+
2000-09-27 Jesse Pavel <jpavel@helixcode.com>
* gui/event-editor.c: changed a menu entry so that it will invoke
diff --git a/calendar/cal-util/cal-recur.c b/calendar/cal-util/cal-recur.c
index 38394d2bfb..a9dfc2b250 100644
--- a/calendar/cal-util/cal-recur.c
+++ b/calendar/cal-util/cal-recur.c
@@ -87,6 +87,54 @@
*/
+/* We will use icalrecurrencetype instead of this eventually. */
+typedef struct {
+ icalrecurrencetype_frequency freq;
+
+ int interval;
+
+ /* Specifies the end of the recurrence. No occurrences are generated
+ after this date. If it is 0, the event recurs forever. */
+ time_t enddate;
+
+ /* WKST property - the week start day: 0 = Monday to 6 = Sunday. */
+ gint week_start_day;
+
+
+ /* NOTE: I've used GList's here, but it doesn't matter if we use
+ other data structures like arrays. The code should be easy to
+ change. So long as it is easy to see if the modifier is set. */
+
+ /* For BYMONTH modifier. A list of GINT_TO_POINTERs, 0-11. */
+ GList *bymonth;
+
+ /* For BYWEEKNO modifier. A list of GINT_TO_POINTERs, [+-]1-53. */
+ GList *byweekno;
+
+ /* For BYYEARDAY modifier. A list of GINT_TO_POINTERs, [+-]1-366. */
+ GList *byyearday;
+
+ /* For BYMONTHDAY modifier. A list of GINT_TO_POINTERs, [+-]1-31. */
+ GList *bymonthday;
+
+ /* For BYDAY modifier. A list of GINT_TO_POINTERs, in pairs.
+ The first of each pair is the weekday, 0 = Monday to 6 = Sunday.
+ The second of each pair is the week number [+-]0-53. */
+ GList *byday;
+
+ /* For BYHOUR modifier. A list of GINT_TO_POINTERs, 0-23. */
+ GList *byhour;
+
+ /* For BYMINUTE modifier. A list of GINT_TO_POINTERs, 0-59. */
+ GList *byminute;
+
+ /* For BYSECOND modifier. A list of GINT_TO_POINTERs, 0-60. */
+ GList *bysecond;
+
+ /* For BYSETPOS modifier. A list of GINT_TO_POINTERs, +ve or -ve. */
+ GList *bysetpos;
+} CalRecurrence;
+
/* This is what we use to pass to all the filter functions. */
typedef struct _RecurData RecurData;
struct _RecurData {
@@ -117,6 +165,27 @@ struct _RecurData {
guint8 seconds[61];
};
+/* This is what we use to represent a date & time. */
+typedef struct _CalObjTime CalObjTime;
+struct _CalObjTime {
+ guint16 year;
+ guint8 month; /* 0 - 11 */
+ guint8 day; /* 1 - 31 */
+ guint8 hour; /* 0 - 23 */
+ guint8 minute; /* 0 - 59 */
+ guint8 second; /* 0 - 59 (maybe 60 for leap second) */
+ guint8 is_rdate; /* TRUE if this is an RDATE, which may have an
+ end or duration set. */
+};
+
+/* This is what we use to represent specific recurrence dates.
+ Note that we assume it starts with a CalObjTime when sorting. */
+typedef struct _CalObjRecurrenceDate CalObjRecurrenceDate;
+struct _CalObjRecurrenceDate {
+ CalObjTime start;
+ CalComponentPeriod *period;
+};
+
/* The paramter we use to store the enddate in RRULE and EXRULE properties. */
#define EVOLUTION_END_DATE_PARAMETER "X-EVOLUTION-ENDDATE"
@@ -173,6 +242,8 @@ static gint cal_recur_ical_weekday_to_weekday (enum icalrecurrencetype_weekday d
static void cal_recur_free (CalRecurrence *r);
+static gboolean cal_object_get_rdate_end (CalObjTime *occ,
+ GArray *rdate_periods);
static void cal_object_compute_duration (CalObjTime *start,
CalObjTime *end,
gint *days,
@@ -625,6 +696,7 @@ cal_recur_generate_instances_of_rule (CalComponent *comp,
chunk_end.hour = 0;
chunk_end.minute = 0;
chunk_end.second = 0;
+ chunk_end.is_rdate = FALSE;
}
if (!generate_instances_for_year (comp, dtstart_time,
@@ -832,15 +904,18 @@ generate_instances_for_year (CalComponent *comp,
CalRecurInstanceFn cb,
gpointer cb_data)
{
- GArray *occs, *ex_occs, *tmp_occs;
+ GArray *occs, *ex_occs, *tmp_occs, *rdate_periods;
CalObjTime cotime, *occ;
GSList *elem;
- gint i, status;
+ gint i;
time_t start_time, end_time;
struct tm start_tm, end_tm;
+ gboolean retval = TRUE;
occs = g_array_new (FALSE, FALSE, sizeof (CalObjTime));
ex_occs = g_array_new (FALSE, FALSE, sizeof (CalObjTime));
+ rdate_periods = g_array_new (FALSE, FALSE,
+ sizeof (CalObjRecurrenceDate));
/* Expand each of the recurrence rules. */
for (elem = rrules; elem; elem = elem->next) {
@@ -859,20 +934,29 @@ generate_instances_for_year (CalComponent *comp,
g_array_free (tmp_occs, TRUE);
}
- /* Add on specific occurrence dates. */
+ /* Add on specific occurrence dates, flag them as RDATEs, and store
+ a pointer to the period in the rdate_periods array. */
for (elem = rdates; elem; elem = elem->next) {
- struct icaltimetype *it;
+ CalComponentPeriod *p;
+ CalObjRecurrenceDate rdate;
time_t t;
- /* FIXME we should only be dealing with dates, not times too.
-
- No, I think it is supposed to be dates & times - Damon.
- I'm not sure what the semantics of just a date would be,
- since the event could recur several times each day. */
- it = elem->data;
- t = icaltime_as_timet (*it);
+ p = elem->data;
+ t = icaltime_as_timet (p->start);
cal_object_time_from_time (&cotime, t);
+ /* Check if the end date or duration is set. If it is we need
+ to store it so we can get it later. (libical seems to set
+ second to -1 to denote an unset time. See icalvalue.c) */
+ if (p->type != CAL_COMPONENT_PERIOD_DATETIME
+ || p->u.end.second != -1) {
+ cotime.is_rdate = TRUE;
+
+ rdate.start = cotime;
+ rdate.period = p;
+ g_array_append_val (rdate_periods, rdate);
+ }
+
g_array_append_val (occs, cotime);
}
@@ -923,10 +1007,13 @@ generate_instances_for_year (CalComponent *comp,
}
- /* Sort both arrays. */
+ /* Sort all the arrays. */
cal_obj_sort_occurrences (occs);
cal_obj_sort_occurrences (ex_occs);
+ qsort (rdate_periods->data, rdate_periods->len,
+ sizeof (CalObjRecurrenceDate), cal_obj_time_compare_func);
+
/* Create the final array, by removing the exceptions from the
occurrences, and removing any duplicates. */
cal_obj_remove_exceptions (occs, ex_occs);
@@ -939,35 +1026,102 @@ generate_instances_for_year (CalComponent *comp,
check it is within the bounds of the event & interval. */
occ = &g_array_index (occs, CalObjTime, i);
- start_tm.tm_year = occ->year - 1900;
- start_tm.tm_mon = occ->month;
- start_tm.tm_mday = occ->day;
- start_tm.tm_hour = occ->hour;
- start_tm.tm_min = occ->minute;
- start_tm.tm_sec = occ->second;
+ start_tm.tm_year = occ->year - 1900;
+ start_tm.tm_mon = occ->month;
+ start_tm.tm_mday = occ->day;
+ start_tm.tm_hour = occ->hour;
+ start_tm.tm_min = occ->minute;
+ start_tm.tm_sec = occ->second;
+ start_tm.tm_isdst = -1;
start_time = mktime (&start_tm);
if (start_time < comp_dtstart
|| start_time >= interval_end_time)
continue;
- cal_obj_time_add_days (occ, duration_days);
- cal_obj_time_add_seconds (occ, duration_seconds);
+ if (occ->is_rdate) {
+ if (!cal_object_get_rdate_end (occ, rdate_periods)) {
+ cal_obj_time_add_days (occ, duration_days);
+ cal_obj_time_add_seconds (occ,
+ duration_seconds);
+ }
+ } else {
+ cal_obj_time_add_days (occ, duration_days);
+ cal_obj_time_add_seconds (occ, duration_seconds);
+ }
- end_tm.tm_year = occ->year - 1900;
- end_tm.tm_mon = occ->month;
- end_tm.tm_mday = occ->day;
- end_tm.tm_hour = occ->hour;
- end_tm.tm_min = occ->minute;
- end_tm.tm_sec = occ->second;
+ end_tm.tm_year = occ->year - 1900;
+ end_tm.tm_mon = occ->month;
+ end_tm.tm_mday = occ->day;
+ end_tm.tm_hour = occ->hour;
+ end_tm.tm_min = occ->minute;
+ end_tm.tm_sec = occ->second;
+ end_tm.tm_isdst = -1;
end_time = mktime (&end_tm);
if (end_time < interval_start_time)
continue;
- status = (*cb) (comp, start_time, end_time, cb_data);
- if (!status)
- return FALSE;
+ retval = (*cb) (comp, start_time, end_time, cb_data);
+ if (!retval)
+ break;
+ }
+
+ g_array_free (occs, TRUE);
+ g_array_free (ex_occs, TRUE);
+ g_array_free (rdate_periods, TRUE);
+
+ return retval;
+}
+
+
+/* This looks up the occurrence time in the sorted rdate_periods array, and
+ tries to compute the end time of the occurrence. If no end time or duration
+ is set it returns FALSE and the default duration will be used. */
+static gboolean
+cal_object_get_rdate_end (CalObjTime *occ,
+ GArray *rdate_periods)
+{
+ CalObjRecurrenceDate *rdate;
+ CalComponentPeriod *p;
+ gint lower, upper, middle, cmp = 0;
+ time_t t;
+
+ lower = 0;
+ upper = rdate_periods->len;
+
+ while (lower < upper) {
+ middle = (lower + upper) >> 1;
+
+ rdate = &g_array_index (rdate_periods, CalObjRecurrenceDate,
+ middle);
+
+ cmp = cal_obj_time_compare_func (occ, &rdate->start);
+
+ if (cmp == 0)
+ break;
+ else if (cmp < 0)
+ upper = middle;
+ else
+ lower = middle + 1;
+ }
+
+ /* This should never happen. */
+ if (cmp == 0) {
+ g_warning ("Recurrence date not found");
+ return FALSE;
+ }
+
+ p = rdate->period;
+ if (p->type == CAL_COMPONENT_PERIOD_DATETIME) {
+ t = icaltime_as_timet (p->u.end);
+ cal_object_time_from_time (occ, t);
+ } else {
+ cal_obj_time_add_days (occ, p->u.duration.weeks * 7
+ + p->u.duration.days);
+ cal_obj_time_add_hours (occ, p->u.duration.hours);
+ cal_obj_time_add_minutes (occ, p->u.duration.minutes);
+ cal_obj_time_add_seconds (occ, p->u.duration.seconds);
}
return TRUE;
@@ -1481,9 +1635,9 @@ static void
cal_obj_remove_exceptions (GArray *occs,
GArray *ex_occs)
{
- CalObjTime *occ, *prev_occ = NULL, *ex_occ;
+ CalObjTime *occ, *prev_occ = NULL, *ex_occ, *last_occ_kept;
gint i, j = 0, cmp, ex_index, occs_len, ex_occs_len;
- gboolean keep_occ;
+ gboolean keep_occ, current_time_is_exception = FALSE;
if (occs->len == 0 || ex_occs->len == 0)
return;
@@ -1502,29 +1656,50 @@ cal_obj_remove_exceptions (GArray *occs,
if (prev_occ
&& cal_obj_time_compare_func (occ, prev_occ) == 0) {
keep_occ = FALSE;
- } else if (ex_occ) {
- /* Step through the exceptions until we come to one
- that matches or follows this occurrence. */
- while (ex_occ) {
- cmp = cal_obj_date_only_compare_func (ex_occ, occ);
- if (cmp > 0)
- break;
- /* Move to the next exception, or set ex_occ
- to NULL when we reach the end of array. */
- ex_index++;
- if (ex_index < ex_occs_len)
- ex_occ = &g_array_index (ex_occs,
- CalObjTime,
- ex_index);
- else
- ex_occ = NULL;
-
- /* If the current exception matches this
- occurrence we remove it. */
- if (cmp == 0) {
- keep_occ = FALSE;
- break;
+ /* If this occurrence is an RDATE, and the previous
+ occurrence in the array was kept, set the RDATE flag
+ of the last one, so we still use the end date
+ or duration. */
+ if (occ->is_rdate && !current_time_is_exception) {
+ last_occ_kept = &g_array_index (occs,
+ CalObjTime,
+ j - 1);
+ last_occ_kept->is_rdate = TRUE;
+ }
+ } else {
+ /* We've found a new occurrence time. Reset the flag
+ to indicate that it hasn't been found in the
+ exceptions array (yet). */
+ current_time_is_exception = FALSE;
+
+ if (ex_occ) {
+ /* Step through the exceptions until we come
+ to one that matches or follows this
+ occurrence. */
+ while (ex_occ) {
+ cmp = cal_obj_date_only_compare_func (ex_occ, occ);
+ if (cmp > 0)
+ break;
+
+ /* Move to the next exception, or set
+ ex_occ to NULL when we reach the
+ end of array. */
+ ex_index++;
+ if (ex_index < ex_occs_len)
+ ex_occ = &g_array_index (ex_occs, CalObjTime, ex_index);
+ else
+ ex_occ = NULL;
+
+ /* If the exception did match this
+ occurrence we remove it, and set the
+ flag to indicate that the current
+ time is an exception. */
+ if (cmp == 0) {
+ current_time_is_exception = TRUE;
+ keep_occ = FALSE;
+ break;
+ }
}
}
}
@@ -3183,12 +3358,13 @@ cal_object_time_from_time (CalObjTime *cotime,
tmp_time_t = t;
tmp_tm = localtime (&tmp_time_t);
- cotime->year = tmp_tm->tm_year + 1900;
- cotime->month = tmp_tm->tm_mon;
- cotime->day = tmp_tm->tm_mday;
- cotime->hour = tmp_tm->tm_hour;
- cotime->minute = tmp_tm->tm_min;
- cotime->second = tmp_tm->tm_sec;
+ cotime->year = tmp_tm->tm_year + 1900;
+ cotime->month = tmp_tm->tm_mon;
+ cotime->day = tmp_tm->tm_mday;
+ cotime->hour = tmp_tm->tm_hour;
+ cotime->minute = tmp_tm->tm_min;
+ cotime->second = tmp_tm->tm_sec;
+ cotime->is_rdate = FALSE;
}
diff --git a/calendar/cal-util/cal-recur.h b/calendar/cal-util/cal-recur.h
index 5adc235573..bbfaafdde2 100644
--- a/calendar/cal-util/cal-recur.h
+++ b/calendar/cal-util/cal-recur.h
@@ -30,64 +30,6 @@
BEGIN_GNOME_DECLS
-typedef struct {
- icalrecurrencetype_frequency freq;
-
- int interval;
-
- /* Specifies the end of the recurrence. No occurrences are generated
- after this date. If it is 0, the event recurs forever. */
- time_t enddate;
-
- /* WKST property - the week start day: 0 = Monday to 6 = Sunday. */
- gint week_start_day;
-
-
- /* NOTE: I've used GList's here, but it doesn't matter if we use
- other data structures like arrays. The code should be easy to
- change. So long as it is easy to see if the modifier is set. */
-
- /* For BYMONTH modifier. A list of GINT_TO_POINTERs, 0-11. */
- GList *bymonth;
-
- /* For BYWEEKNO modifier. A list of GINT_TO_POINTERs, [+-]1-53. */
- GList *byweekno;
-
- /* For BYYEARDAY modifier. A list of GINT_TO_POINTERs, [+-]1-366. */
- GList *byyearday;
-
- /* For BYMONTHDAY modifier. A list of GINT_TO_POINTERs, [+-]1-31. */
- GList *bymonthday;
-
- /* For BYDAY modifier. A list of GINT_TO_POINTERs, in pairs.
- The first of each pair is the weekday, 0 = Monday to 6 = Sunday.
- The second of each pair is the week number [+-]0-53. */
- GList *byday;
-
- /* For BYHOUR modifier. A list of GINT_TO_POINTERs, 0-23. */
- GList *byhour;
-
- /* For BYMINUTE modifier. A list of GINT_TO_POINTERs, 0-59. */
- GList *byminute;
-
- /* For BYSECOND modifier. A list of GINT_TO_POINTERs, 0-60. */
- GList *bysecond;
-
- /* For BYSETPOS modifier. A list of GINT_TO_POINTERs, +ve or -ve. */
- GList *bysetpos;
-} CalRecurrence;
-
-/* This is what we use to represent a date & time. */
-typedef struct _CalObjTime CalObjTime;
-struct _CalObjTime {
- guint16 year;
- guint8 month; /* 0 - 11 */
- guint8 day; /* 1 - 31 */
- guint8 hour; /* 0 - 23 */
- guint8 minute; /* 0 - 59 */
- guint8 second; /* 0 - 59 (maybe 60 for leap second) */
-};
-
typedef gboolean (* CalRecurInstanceFn) (CalComponent *comp,
time_t instance_start,
time_t instace_end,
@@ -97,7 +39,7 @@ typedef gboolean (* CalRecurInstanceFn) (CalComponent *comp,
* Calls the given callback function for each occurrence of the event between
* the given start and end times. If end is 0 it continues until the event
* ends or forever if the event has an infinite recurrence rule.
- * If the callback routine return 0 the occurrence generation stops.
+ * If the callback routine return FALSE the occurrence generation stops.
*/
void cal_recur_generate_instances (CalComponent *comp,
time_t start,
diff --git a/calendar/cal-util/test-recur.c b/calendar/cal-util/test-recur.c
index 83602bb0d6..f3b75eb94f 100644
--- a/calendar/cal-util/test-recur.c
+++ b/calendar/cal-util/test-recur.c
@@ -24,6 +24,7 @@
/*
* This tests the recurrence rule expansion functions.
+ * FIXME: Needs to be updated to just use the public interface.
*/
#include <config.h>
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 7274c13e18..fa05ba407a 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -52,6 +52,9 @@ struct _CalendarModelPrivate {
/* UID -> array index hash */
GHashTable *uid_index_hash;
+ /* Whether we display dates in 24-hour format. */
+ gboolean use_24_hour_format;
+
/* HACK: so that ETable can do its stupid append_row() thing */
guint appending_row : 1;
};
@@ -157,6 +160,7 @@ calendar_model_init (CalendarModel *model)
priv->objects = g_array_new (FALSE, TRUE, sizeof (CalComponent *));
priv->uid_index_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->use_24_hour_format = TRUE;
}
/* Called from g_hash_table_foreach_remove(), frees a stored UID->index
@@ -261,10 +265,11 @@ calendar_model_row_count (ETableModel *etm)
/* Creates a nice string representation of a time value */
static char*
-get_time_t (time_t *t, gboolean skip_midnight)
+get_time_t (CalendarModel *model, time_t *t, gboolean skip_midnight)
{
- static char buffer[32];
+ static char buffer[64];
struct tm *tmp_tm;
+ char *format;
if (*t <= 0) {
buffer[0] = '\0';
@@ -273,9 +278,18 @@ get_time_t (time_t *t, gboolean skip_midnight)
if (skip_midnight && tmp_tm->tm_hour == 0
&& tmp_tm->tm_min == 0 && tmp_tm->tm_sec == 0)
- strftime (buffer, 32, "%a %x", tmp_tm);
+ /* strftime format of a weekday and a date. */
+ format = _("%a %m/%d/%Y");
+ else if (model->priv->use_24_hour_format)
+ /* strftime format of a weekday, a date and a time,
+ in 24-hour format. */
+ format = _("%a %m/%d/%Y %H:%M:%S");
else
- strftime (buffer, 32, "%a %x %T", tmp_tm);
+ /* strftime format of a weekday, a date and a time,
+ in 12-hour format. */
+ format = _("%a %m/%d/%Y %I:%M:%S %p");
+
+ strftime (buffer, sizeof (buffer), format, tmp_tm);
}
return buffer;
@@ -346,7 +360,8 @@ get_classification (CalComponent *comp)
/* Builds a string for the COMPLETED property of a calendar component */
static char *
-get_completed (CalComponent *comp)
+get_completed (CalendarModel *model,
+ CalComponent *comp)
{
struct icaltimetype *completed;
time_t t;
@@ -360,12 +375,12 @@ get_completed (CalComponent *comp)
cal_component_free_icaltimetype (completed);
}
- return get_time_t (&t, FALSE);
+ return get_time_t (model, &t, FALSE);
}
/* Builds a string for and frees a date/time value */
static char *
-get_and_free_datetime (CalComponentDateTime dt)
+get_and_free_datetime (CalendarModel *model, CalComponentDateTime dt)
{
time_t t;
@@ -376,37 +391,37 @@ get_and_free_datetime (CalComponentDateTime dt)
cal_component_free_datetime (&dt);
- return get_time_t (&t, FALSE);
+ return get_time_t (model, &t, FALSE);
}
/* Builds a string for the DTEND property of a calendar component */
static char *
-get_dtend (CalComponent *comp)
+get_dtend (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_dtend (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the DTSTART property of a calendar component */
static char *
-get_dtstart (CalComponent *comp)
+get_dtstart (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_dtstart (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the DUE property of a calendar component */
static char *
-get_due (CalComponent *comp)
+get_due (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_due (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the GEO property of a calendar component */
@@ -546,8 +561,6 @@ get_is_complete (CalComponent *comp)
struct icaltimetype *t;
gboolean retval;
- /* May not be reliable, especially at the moment when
- we can't set a Completed Date to None. */
cal_component_get_completed (comp, &t);
retval = (t != NULL);
@@ -627,16 +640,16 @@ calendar_model_value_at (ETableModel *etm, int col, int row)
return get_classification (comp);
case CAL_COMPONENT_FIELD_COMPLETED:
- return get_completed (comp);
+ return get_completed (model, comp);
case CAL_COMPONENT_FIELD_DTEND:
- return get_dtend (comp);
+ return get_dtend (model, comp);
case CAL_COMPONENT_FIELD_DTSTART:
- return get_dtstart (comp);
+ return get_dtstart (model, comp);
case CAL_COMPONENT_FIELD_DUE:
- return get_due (comp);
+ return get_due (model, comp);
case CAL_COMPONENT_FIELD_GEO:
return get_geo (comp);
@@ -712,16 +725,24 @@ string_is_empty (const char *value)
/* FIXME: We need to set the "transient_for" property for the dialog, but
the model doesn't know anything about the windows. */
static void
-show_date_warning (void)
+show_date_warning (CalendarModel *model)
{
GtkWidget *dialog;
- char buffer[32], message[256];
+ char buffer[64], message[256], *format;
time_t t;
struct tm *tmp_tm;
t = time (NULL);
tmp_tm = localtime (&t);
- strftime (buffer, 32, "%a %x %T", tmp_tm);
+
+ if (model->priv->use_24_hour_format)
+ /* strftime format of a weekday, a date and a time, 24-hour. */
+ format = _("%a %m/%d/%Y %H:%M:%S");
+ else
+ /* strftime format of a weekday, a date and a time, 12-hour. */
+ format = _("%a %m/%d/%Y %I:%M:%S %p");
+
+ strftime (buffer, sizeof (buffer), format, tmp_tm);
g_snprintf (message, 256,
_("The date must be entered in the format: \n\n%s"),
@@ -801,62 +822,137 @@ set_categories (CalComponent *comp, const char *value)
static time_t
parse_time (const char *value)
{
- struct tm tmp_tm;
+ struct tm discard_tm, date_tm, time_tm;
struct tm *today_tm;
time_t t;
- const char *p;
+ const char *pos, *parse_end;
+ char *format[4];
+ gboolean parsed_date = FALSE, parsed_time = FALSE;
+ gint i;
if (string_is_empty (value))
return 0;
- /* Skip any weekday name. */
- p = strptime (value, "%a", &tmp_tm);
- if (!p)
- p = value;
+ pos = value;
- /* Try to match the full date & time, or without the seconds,
- or just the date, or just the time with/without seconds.
- The info pages say we should clear the tm before calling
- strptime. It also means that if we don't match a time we
- get 00:00:00 which is good. */
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %H:%M", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%H:%M", &tmp_tm))
- return -1; /* Could not parse it */
- }
-
- /* We only got a time, so we use the
- current day. */
- t = time (NULL);
- today_tm = localtime (&t);
- tmp_tm.tm_mday = today_tm->tm_mday;
- tmp_tm.tm_mon = today_tm->tm_mon;
- tmp_tm.tm_year = today_tm->tm_year;
- }
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* Skip any weekday name, full or abbreviated. */
+ parse_end = strptime (pos, "%a ", &discard_tm);
+ if (parse_end)
+ pos = parse_end;
+
+ memset (&date_tm, 0, sizeof (date_tm));
+ /* strptime format for a date. */
+ parse_end = strptime (pos, _("%m/%d/%Y"), &date_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_date = TRUE;
+ }
+
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* Skip any weekday name, full or abbreviated, again. */
+ parse_end = strptime (pos, "%a ", &discard_tm);
+ if (parse_end)
+ pos = parse_end;
+
+
+ /* strptime format for a time of day, in 12-hour format.
+ If it is is not appropriate in the locale set to an empty string. */
+ format[0] = _("%I:%M:%S %p%n");
+
+ /* strptime format for a time of day, in 24-hour format. */
+ format[1] = _("%H:%M:%S%n");
+
+ /* strptime format for time of day, without seconds, 12-hour format.
+ If it is is not appropriate in the locale set to an empty string. */
+ format[2] = _("%I:%M %p%n");
+
+ /* strptime format for time of day, without seconds 24-hour format. */
+ format[3] = _("%H:%M%n");
+
+ for (i = 0; i < sizeof (format) / sizeof (format[0]); i++) {
+ memset (&time_tm, 0, sizeof (time_tm));
+ parse_end = strptime (pos, format[i], &time_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_time = TRUE;
+ break;
+ }
+ }
+
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* If we haven't already parsed a date, try again. */
+ if (!parsed_date) {
+ memset (&date_tm, 0, sizeof (date_tm));
+ /* strptime format for a date. */
+ parse_end = strptime (pos, _("%m/%d/%Y"), &date_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_date = TRUE;
}
}
- tmp_tm.tm_isdst = -1;
- return mktime (&tmp_tm);
+ /* If we don't have a date or a time it must be invalid. */
+ if (!parsed_date && !parsed_time)
+ return -1;
+
+
+ if (parsed_date) {
+ /* If a 2-digit year was used we use the current century. */
+ if (date_tm.tm_year < 0) {
+ t = time (NULL);
+ today_tm = localtime (&t);
+
+ /* This should convert it into a value from 0 to 99. */
+ date_tm.tm_year += 1900;
+
+ /* Now add on the century. */
+ date_tm.tm_year += today_tm->tm_year
+ - (today_tm->tm_year % 100);
+ }
+ } else {
+ /* If we didn't get a date we use the current day. */
+ t = time (NULL);
+ today_tm = localtime (&t);
+ date_tm.tm_mday = today_tm->tm_mday;
+ date_tm.tm_mon = today_tm->tm_mon;
+ date_tm.tm_year = today_tm->tm_year;
+ }
+
+ if (parsed_time) {
+ date_tm.tm_hour = time_tm.tm_hour;
+ date_tm.tm_min = time_tm.tm_min;
+ date_tm.tm_sec = time_tm.tm_sec;
+ } else {
+ date_tm.tm_hour = 0;
+ date_tm.tm_min = 0;
+ date_tm.tm_sec = 0;
+ }
+
+
+ date_tm.tm_isdst = -1;
+ return mktime (&date_tm);
}
/* Called to set the "Date Completed" field. We also need to update the
Status and Percent fields to make sure they match. */
static void
-set_completed (CalComponent *comp, const char *value)
+set_completed (CalendarModel *model, CalComponent *comp, const char *value)
{
time_t t;
t = parse_time (value);
if (t == -1) {
- show_date_warning ();
+ show_date_warning (model);
} else if (t == 0) {
ensure_task_not_complete (comp);
} else {
@@ -866,14 +962,14 @@ set_completed (CalComponent *comp, const char *value)
/* Sets a CalComponentDateTime value */
static void
-set_datetime (CalComponent *comp, const char *value,
+set_datetime (CalendarModel *model, CalComponent *comp, const char *value,
void (* set_func) (CalComponent *comp, CalComponentDateTime *dt))
{
time_t t;
t = parse_time (value);
if (t == -1) {
- show_date_warning ();
+ show_date_warning (model);
return;
} else if (t == 0) {
(* set_func) (comp, NULL);
@@ -1073,21 +1169,21 @@ calendar_model_set_value_at (ETableModel *etm, int col, int row, const void *val
/* FIXME: CLASSIFICATION requires an option menu cell renderer */
case CAL_COMPONENT_FIELD_COMPLETED:
- set_completed (comp, value);
+ set_completed (model, comp, value);
break;
case CAL_COMPONENT_FIELD_DTEND:
/* FIXME: Need to reset dtstart if dtend happens before it */
- set_datetime (comp, value, cal_component_set_dtend);
+ set_datetime (model, comp, value, cal_component_set_dtend);
break;
case CAL_COMPONENT_FIELD_DTSTART:
/* FIXME: Need to reset dtend if dtstart happens after it */
- set_datetime (comp, value, cal_component_set_dtstart);
+ set_datetime (model, comp, value, cal_component_set_dtstart);
break;
case CAL_COMPONENT_FIELD_DUE:
- set_datetime (comp, value, cal_component_set_due);
+ set_datetime (model, comp, value, cal_component_set_due);
break;
case CAL_COMPONENT_FIELD_GEO:
@@ -1904,3 +2000,26 @@ ensure_task_not_complete (CalComponent *comp)
}
+/* Whether we use 24 hour format to display the times. */
+gboolean
+calendar_model_get_use_24_hour_format (CalendarModel *model)
+{
+ g_return_val_if_fail (IS_CALENDAR_MODEL (model), TRUE);
+
+ return model->priv->use_24_hour_format;
+}
+
+
+void
+calendar_model_set_use_24_hour_format (CalendarModel *model,
+ gboolean use_24_hour_format)
+{
+ g_return_if_fail (IS_CALENDAR_MODEL (model));
+
+ if (model->priv->use_24_hour_format != use_24_hour_format) {
+ model->priv->use_24_hour_format = use_24_hour_format;
+ /* Get the views to redraw themselves. */
+ e_table_model_changed (E_TABLE_MODEL (model));
+ }
+}
+
diff --git a/calendar/gui/calendar-model.h b/calendar/gui/calendar-model.h
index 3a1685e90c..ed04706090 100644
--- a/calendar/gui/calendar-model.h
+++ b/calendar/gui/calendar-model.h
@@ -70,6 +70,11 @@ void calendar_model_delete_task (CalendarModel *model,
CalComponent* calendar_model_get_cal_object (CalendarModel *model,
gint row);
+/* Whether we use 24 hour format to display the times. */
+gboolean calendar_model_get_use_24_hour_format (CalendarModel *model);
+void calendar_model_set_use_24_hour_format (CalendarModel *model,
+ gboolean use_24_hour_format);
+
END_GNOME_DECLS
diff --git a/calendar/gui/e-day-view-top-item.c b/calendar/gui/e-day-view-top-item.c
index b6b8a565b5..6b00f34a60 100644
--- a/calendar/gui/e-day-view-top-item.c
+++ b/calendar/gui/e-day-view-top-item.c
@@ -183,7 +183,7 @@ e_day_view_top_item_draw (GnomeCanvasItem *canvas_item,
EDayView *day_view;
GtkStyle *style;
GdkGC *fg_gc, *bg_gc, *light_gc, *dark_gc;
- gchar buffer[128];
+ gchar buffer[128], *format;
GdkRectangle clip_rect;
GdkFont *font;
gint canvas_width, canvas_height, left_edge, day, date_width, date_x;
@@ -256,12 +256,22 @@ e_day_view_top_item_draw (GnomeCanvasItem *canvas_item,
day_start = localtime (&day_view->day_starts[day]);
if (day_view->date_format == E_DAY_VIEW_DATE_FULL)
- strftime (buffer, 128, "%d %B", day_start);
+ /* strftime format %A = full weekday name, %d = day of month,
+ %B = full month name. Don't use any other specifiers. */
+ format = _("%A %d %B");
else if (day_view->date_format == E_DAY_VIEW_DATE_ABBREVIATED)
- strftime (buffer, 128, "%d %b", day_start);
+ /* strftime format %a = abbreviated weekday name, %d = day of month,
+ %b = abbreviated month name. Don't use any other specifiers. */
+ format = _("%a %d %b");
+ else if (day_view->date_format == E_DAY_VIEW_DATE_NO_WEEKDAY)
+ /* strftime format %d = day of month, %b = abbreviated month name.
+ Don't use any other specifiers. */
+ format = _("%d %b");
else
- strftime (buffer, 128, "%d", day_start);
+ format = "%d";
+ strftime (buffer, sizeof (buffer), format, day_start);
+
clip_rect.x = day_view->day_offsets[day] - x;
clip_rect.y = 2 - y;
clip_rect.width = day_view->day_widths[day];
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index af402722cd..76925be0bd 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -961,10 +961,12 @@ e_day_view_style_set (GtkWidget *widget,
EDayView *day_view;
GdkFont *font;
gint top_rows, top_canvas_height;
- gint month, max_month_width, max_abbr_month_width, number_width;
- gint hour, max_large_hour_width, month_width;
+ gint hour, max_large_hour_width;
gint minute, max_minute_width, i;
- GDate date;
+ gint month, day, width;
+ gint longest_month_width, longest_abbreviated_month_width;
+ gint longest_weekday_width, longest_abbreviated_weekday_width;
+ struct tm date_tm;
gchar buffer[128];
gint times_width;
@@ -975,7 +977,7 @@ e_day_view_style_set (GtkWidget *widget,
font = widget->style->font;
/* Recalculate the height of each row based on the font size. */
- day_view->row_height = font->ascent + font->descent + E_DAY_VIEW_EVENT_BORDER_HEIGHT * 2 + E_DAY_VIEW_EVENT_Y_PAD * 2 + 2 /* FIXME */;
+ day_view->row_height = font->ascent + font->descent + E_DAY_VIEW_EVENT_BORDER_HEIGHT + E_DAY_VIEW_EVENT_Y_PAD * 2 + 2 /* FIXME */;
day_view->row_height = MAX (day_view->row_height, E_DAY_VIEW_ICON_HEIGHT + E_DAY_VIEW_ICON_Y_PAD + 2);
GTK_LAYOUT (day_view->main_canvas)->vadjustment->step_increment = day_view->row_height;
@@ -988,27 +990,59 @@ e_day_view_style_set (GtkWidget *widget,
top_canvas_height = (top_rows + 2) * day_view->top_row_height;
gtk_widget_set_usize (day_view->top_canvas, -1, top_canvas_height);
- /* Find the biggest full month name. */
- g_date_clear (&date, 1);
- g_date_set_dmy (&date, 20, 1, 2000);
- max_month_width = 0;
- max_abbr_month_width = 0;
- for (month = 1; month <= 12; month++) {
- g_date_set_month (&date, month);
+ /* Find the longest full & abbreviated month names. */
+ memset (&date_tm, 0, sizeof (date_tm));
+ date_tm.tm_year = 100;
+ date_tm.tm_mday = 1;
+ date_tm.tm_isdst = -1;
+
+ longest_month_width = 0;
+ longest_abbreviated_month_width = 0;
+ for (month = 0; month < 12; month++) {
+ date_tm.tm_mon = month;
+
+ strftime (buffer, sizeof (buffer), "%B", &date_tm);
+ width = gdk_string_width (font, buffer);
+ if (width > longest_month_width) {
+ longest_month_width = width;
+ day_view->longest_month_name = month;
+ }
+
+ strftime (buffer, sizeof (buffer), "%b", &date_tm);
+ width = gdk_string_width (font, buffer);
+ if (width > longest_abbreviated_month_width) {
+ longest_abbreviated_month_width = width;
+ day_view->longest_abbreviated_month_name = month;
+ }
+ }
+
+ /* Find the longest full & abbreviated weekday names. */
+ memset (&date_tm, 0, sizeof (date_tm));
+ date_tm.tm_year = 100;
+ date_tm.tm_mon = 0;
+ date_tm.tm_isdst = -1;
+
+ longest_weekday_width = 0;
+ longest_abbreviated_weekday_width = 0;
+ for (day = 0; day < 7; day++) {
+ date_tm.tm_mday = 2 + day;
+ date_tm.tm_wday = day;
- g_date_strftime (buffer, 128, "%B", &date);
- month_width = gdk_string_width (font, buffer);
- max_month_width = MAX (max_month_width, month_width);
+ strftime (buffer, sizeof (buffer), "%A", &date_tm);
+ width = gdk_string_width (font, buffer);
+ if (width > longest_weekday_width) {
+ longest_weekday_width = width;
+ day_view->longest_weekday_name = day;
+ }
- g_date_strftime (buffer, 128, "%b", &date);
- month_width = gdk_string_width (font, buffer);
- max_abbr_month_width = MAX (max_abbr_month_width, month_width);
+ strftime (buffer, sizeof (buffer), "%a", &date_tm);
+ width = gdk_string_width (font, buffer);
+ if (width > longest_abbreviated_weekday_width) {
+ longest_abbreviated_weekday_width = width;
+ day_view->longest_abbreviated_weekday_name = day;
+ }
}
- number_width = gdk_string_width (font, "31 ");
- day_view->long_format_width = number_width + max_month_width
- + E_DAY_VIEW_DATE_X_PAD;
- day_view->abbreviated_format_width = number_width
- + max_abbr_month_width + E_DAY_VIEW_DATE_X_PAD;
+
/* Calculate the widths of all the time strings necessary. */
day_view->max_small_hour_width = 0;
@@ -1090,8 +1124,18 @@ e_day_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
static void
e_day_view_recalc_cell_sizes (EDayView *day_view)
{
+ /* An array of dates, one for each month in the year 2000. They must
+ all be Sundays. */
+ static const int days[12] = { 23, 20, 19, 23, 21, 18,
+ 23, 20, 17, 22, 19, 24 };
gfloat width, offset;
- gint day;
+ gint day, max_width;
+ struct tm date_tm;
+ GdkFont *font;
+ char buffer[128];
+
+ g_return_if_fail (((GtkWidget*)day_view)->style != NULL);
+ font = GTK_WIDGET (day_view)->style->font;
/* Calculate the column sizes, using floating point so that pixels
get divided evenly. Note that we use one more element than the
@@ -1109,11 +1153,53 @@ e_day_view_recalc_cell_sizes (EDayView *day_view)
day_view->day_widths[day] = day_view->day_offsets[day + 1] - day_view->day_offsets[day];
}
- /* Determine which date format to use, based on the column widths. */
- if (day_view->day_widths[0] > day_view->long_format_width)
+ /* Determine which date format to use, based on the column widths.
+ We want to check the widths using the longest full or abbreviated
+ month name and the longest full or abbreviated weekday name, as
+ appropriate. */
+ max_width = day_view->day_widths[0];
+
+ memset (&date_tm, 0, sizeof (date_tm));
+ date_tm.tm_year = 100;
+
+ /* Try "Thursday 21 January". */
+ date_tm.tm_mon = day_view->longest_month_name;
+ date_tm.tm_mday = days[date_tm.tm_mon]
+ + day_view->longest_weekday_name;
+ date_tm.tm_wday = day_view->longest_weekday_name;
+ date_tm.tm_isdst = -1;
+ /* strftime format %A = full weekday name, %d = day of month,
+ %B = full month name. Don't use any other specifiers. */
+ strftime (buffer, sizeof (buffer), _("%A %d %B"), &date_tm);
+ if (gdk_string_width (font, buffer) < max_width) {
day_view->date_format = E_DAY_VIEW_DATE_FULL;
- else if (day_view->day_widths[0] > day_view->abbreviated_format_width)
+ return;
+ }
+
+ /* Try "Thu 21 Jan". */
+ date_tm.tm_mon = day_view->longest_abbreviated_month_name;
+ date_tm.tm_mday = days[date_tm.tm_mon]
+ + day_view->longest_abbreviated_weekday_name;
+ date_tm.tm_wday = day_view->longest_abbreviated_weekday_name;
+ date_tm.tm_isdst = -1;
+ /* strftime format %a = abbreviated weekday name, %d = day of month,
+ %b = abbreviated month name. Don't use any other specifiers. */
+ strftime (buffer, sizeof (buffer), _("%a %d %b"), &date_tm);
+ if (gdk_string_width (font, buffer) < max_width) {
day_view->date_format = E_DAY_VIEW_DATE_ABBREVIATED;
+ return;
+ }
+
+ /* Try "23 Jan". */
+ date_tm.tm_mon = day_view->longest_abbreviated_month_name;
+ date_tm.tm_mday = 23;
+ date_tm.tm_wday = 0;
+ date_tm.tm_isdst = -1;
+ /* strftime format %d = day of month, %b = abbreviated month name.
+ Don't use any other specifiers. */
+ strftime (buffer, sizeof (buffer), _("%d %b"), &date_tm);
+ if (gdk_string_width (font, buffer) < max_width)
+ day_view->date_format = E_DAY_VIEW_DATE_NO_WEEKDAY;
else
day_view->date_format = E_DAY_VIEW_DATE_SHORT;
}
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index cfd11b057c..fda44c1289 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -118,13 +118,15 @@ typedef enum
} EDayViewBusyType;
/* This is used to specify the format used when displaying the dates.
- The full format is like 'September 12'. The abbreviated format is like
- 'Sep 12'. The short format is like '12'. The actual format used is
- determined in style_set(), once we know the font being used. */
+ The full format is like 'Thursday 12 September'. The abbreviated format is
+ like 'Thu 12 Sep'. The no weekday format is like '12 Sep'. The short format
+ is like '12'. The actual format used is determined in
+ e_day_view_recalc_cell_sizes(), once we know the font being used. */
typedef enum
{
E_DAY_VIEW_DATE_FULL,
E_DAY_VIEW_DATE_ABBREVIATED,
+ E_DAY_VIEW_DATE_NO_WEEKDAY,
E_DAY_VIEW_DATE_SHORT
} EDayViewDateFormat;
@@ -301,9 +303,12 @@ struct _EDayView
/* This specifies how we are displaying the dates at the top. */
EDayViewDateFormat date_format;
- /* These are the maximum widths of the different types of dates. */
- gint long_format_width;
- gint abbreviated_format_width;
+ /* These are the longest month & weekday names in the current font.
+ Months are 0 to 11. Weekdays are 0 (Sun) to 6 (Sat). */
+ gint longest_month_name;
+ gint longest_abbreviated_month_name;
+ gint longest_weekday_name;
+ gint longest_abbreviated_weekday_name;
/* The large font use to display the hours. I don't think we need a
fontset since we only display numbers. */
diff --git a/calendar/gui/e-week-view-main-item.c b/calendar/gui/e-week-view-main-item.c
index d30404305d..10990324ff 100644
--- a/calendar/gui/e-week-view-main-item.c
+++ b/calendar/gui/e-week-view-main-item.c
@@ -315,22 +315,41 @@ e_week_view_main_item_draw_day (EWeekViewMainItem *wvmitem,
max_width = width - 4;
format_string = NULL;
if (show_day_name) {
- if (week_view->max_abbr_day_width +
- week_view->digit_width * 2 + week_view->space_width * 2
+ if (week_view->max_day_width + week_view->digit_width * 2
+ + week_view->space_width * 2
+ week_view->month_widths[month - 1] < max_width)
- format_string = "%a %d %B";
+ /* strftime format %A = full weekday name, %d = day of
+ month, %B = full month name. You can change the
+ order but don't change the specifiers or add
+ anything. */
+ format_string = _("%A %d %B");
+ else if (week_view->max_abbr_day_width
+ + week_view->digit_width * 2
+ + week_view->space_width * 2
+ + week_view->abbr_month_widths[month - 1] < max_width)
+ /* strftime format %a = abbreviated weekday name,
+ %d = day of month, %b = abbreviated month name.
+ You can change the order but don't change the
+ specifiers or add anything. */
+ format_string = _("%a %d %b");
}
if (!format_string && show_month_name) {
if (week_view->digit_width * 2 + week_view->space_width
+ week_view->month_widths[month - 1] < max_width)
- format_string = "%d %B";
+ /* strftime format %d = day of month, %B = full
+ month name. You can change the order but don't
+ change the specifiers or add anything. */
+ format_string = _("%d %B");
else if (week_view->digit_width * 2 + week_view->space_width
+ week_view->abbr_month_widths[month - 1] < max_width)
- format_string = "%d %b";
+ /* strftime format %d = day of month, %b = abbreviated
+ month name. You can change the order but don't
+ change the specifiers or add anything. */
+ format_string = _("%d %b");
}
- g_date_strftime (buffer, 128, format_string ? format_string : "%d",
- date);
+ g_date_strftime (buffer, sizeof (buffer),
+ format_string ? format_string : "%d", date);
date_width = gdk_string_width (font, buffer);
date_x = x + width - date_width - E_WEEK_VIEW_DATE_R_PAD;
date_x = MAX (date_x, x + 1);