Ticket #1671: i18n_checktimelength may vary depending on the season

On some systems i18n_checktimelength may vary not only depending on the
locale but also on the current month. This patch introduces a cyclic
check that loops through all of the months to find out which one has the
longest name.

However, since this function is called on every pannel reload and now
makes 24 calls to str_term_width1 and strftime it makes sense to
introduce a cache for the resulting value.

Thanks to Sergey Fionov <fionov@gmail.com> for the initial patch.

Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
This commit is contained in:
Yury V. Zaytsev 2010-05-02 13:07:16 +02:00
parent 5ba9fde28c
commit 28eda66803

View File

@ -67,6 +67,13 @@ int kilobyte_si = 0;
char *user_recent_timeformat = NULL; /* time format string for recent dates */ char *user_recent_timeformat = NULL; /* time format string for recent dates */
char *user_old_timeformat = NULL; /* time format string for older dates */ char *user_old_timeformat = NULL; /* time format string for older dates */
/*
* Cache variable for the i18n_checktimelength function,
* initially set to a clearly invalid value to show that
* it hasn't been initialized yet.
*/
static size_t i18n_timelength_cache = MAX_I18NTIMELENGTH + 1;
extern void extern void
str_replace (char *s, char from, char to) str_replace (char *s, char from, char to)
{ {
@ -690,14 +697,17 @@ load_mc_home_file (const char *_mc_home, const char *_mc_home_alt, const char *f
} }
/* Check strftime() results. Some systems (i.e. Solaris) have different /* Check strftime() results. Some systems (i.e. Solaris) have different
short-month-name sizes for different locales */ short-month and month name sizes for different locales */
size_t size_t
i18n_checktimelength (void) i18n_checktimelength (void)
{ {
size_t length; size_t length = 0;
time_t testtime = time (NULL); const time_t testtime = time (NULL);
struct tm *lt = localtime (&testtime); struct tm *lt = localtime (&testtime);
if (i18n_timelength_cache <= MAX_I18NTIMELENGTH)
return i18n_timelength_cache;
if (lt == NULL) if (lt == NULL)
{ {
/* huh, localtime() doesnt seem to work ... falling back to "(invalid)" */ /* huh, localtime() doesnt seem to work ... falling back to "(invalid)" */
@ -706,14 +716,18 @@ i18n_checktimelength (void)
else else
{ {
char buf[MB_LEN_MAX * MAX_I18NTIMELENGTH + 1]; char buf[MB_LEN_MAX * MAX_I18NTIMELENGTH + 1];
size_t a, b;
strftime (buf, sizeof (buf) - 1, user_recent_timeformat, lt); /* We are interested in the longest possible date */
a = str_term_width1 (buf); lt->tm_sec = lt->tm_min = lt->tm_hour = lt->tm_mday = 10;
strftime (buf, sizeof (buf) - 1, user_old_timeformat, lt);
b = str_term_width1 (buf); /* Loop through all months to find out the longest one */
for (lt->tm_mon = 0; lt->tm_mon < 12; lt->tm_mon++) {
strftime (buf, sizeof(buf) - 1, user_recent_timeformat, lt);
length = max ((size_t) str_term_width1 (buf), length);
strftime (buf, sizeof(buf) - 1, user_old_timeformat, lt);
length = max ((size_t) str_term_width1 (buf), length);
}
length = max (a, b);
length = max ((size_t) str_term_width1 (_(INVALID_TIME_TEXT)), length); length = max ((size_t) str_term_width1 (_(INVALID_TIME_TEXT)), length);
} }
@ -721,7 +735,10 @@ i18n_checktimelength (void)
if (length > MAX_I18NTIMELENGTH || length < MIN_I18NTIMELENGTH) if (length > MAX_I18NTIMELENGTH || length < MIN_I18NTIMELENGTH)
length = STD_I18NTIMELENGTH; length = STD_I18NTIMELENGTH;
return length; /* Save obtained value to the cache */
i18n_timelength_cache = length;
return i18n_timelength_cache;
} }
const char * const char *