# HG changeset patch # User Richard Laager # Date 1138909851 0 # Node ID e1e5462b7d8185d42c5e05136f2164d696031ebf # Parent a6811e213977e3c2d07c44addf07eee2303fcbbf [gaim-migrate @ 15466] Rework lots of date parsing. I either introduced a whole lot of bugs, or I've made sure all dates are localized properly now. Only time will tell which it is... ;) committer: Tailor Script diff -r a6811e213977 -r e1e5462b7d81 plugins/ChangeLog.API --- a/plugins/ChangeLog.API Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/ChangeLog.API Thu Feb 02 19:50:51 2006 +0000 @@ -95,6 +95,8 @@ may now pass NULL if you're not interested in a specific formatting. * Smiley Themes: Backslashes must be backslash-escaped. * Plugins: Depedencies are now honored when unloading plugins. + * gaim_markup_extract_info_field(): Added format_cb parameter. + * gaim_str_to_time(): Added support for parsing the MM/DD/YYYY format. Removed: * gaim_gtk_sound_{get,set}_mute() (replaced by the /gaim/gtk/sound/mute @@ -148,7 +150,8 @@ now, so this would always be TRUE now. * gaim_blist_node_action_new(); use gaim_menu_action_new() instead * gaim_date() - * gaim_date_full() + * gaim_date_full(): See gaim_date_format_full() + * gaim_strftime(): See gaim_utf8_strftime() Added: * gaim_prefs_disconnect_by_handle() @@ -245,6 +248,12 @@ * gaim_url_fetch_request() * gaim_menu_action_new() * gaim_menu_action_free() + * GaimInfoFieldFormatCallback + * gaim_utf8_strftime() + * gaim_date_format_short() + * gaim_date_format_long() + * gaim_date_format_full() + * gaim_time_format() Signals - Changed: (See the Doxygen docs for details on all signals.) * Signal propagation now stops after a handler returns a non-NULL value. diff -r a6811e213977 -r e1e5462b7d81 plugins/history.c --- a/plugins/history.c Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/history.c Thu Feb 02 19:50:51 2006 +0000 @@ -40,8 +40,6 @@ char *history; GaimGtkConversation *gtkconv; GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; - time_t tm; - char day[64]; char *header; char *protocol; @@ -116,9 +114,8 @@ gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), gaim_account_get_protocol_name(((GaimLog*)logs->data)->account)); - tm = ((GaimLog *)logs->data)->time; - gaim_strftime(day, sizeof(day), "%c", localtime(&tm)); - header = g_strdup_printf("Conversation with %s on %s:
", alias, day); + header = g_strdup_printf("Conversation with %s on %s:
", alias, + gaim_date_format_full(((GaimLog *)logs->data)->time)); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options); g_free(header); diff -r a6811e213977 -r e1e5462b7d81 plugins/perl/common/Util.xs --- a/plugins/perl/common/Util.xs Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/perl/common/Util.xs Thu Feb 02 19:50:51 2006 +0000 @@ -51,6 +51,18 @@ const char *path int mode +const char * +gaim_date_format_full(time) + time_t time + +const char * +gaim_date_format_long(tm) + const struct tm *tm + +const char * +gaim_date_format_short(tm) + const struct tm *tm + gboolean gaim_email_is_valid(address) const char *address @@ -67,7 +79,7 @@ gaim_home_dir() gboolean -gaim_markup_extract_info_field(str, len, dest, start_token, skip, end_token, check_value, no_value_token, display_name, is_link, link_prefix) +gaim_markup_extract_info_field(str, len, dest, start_token, skip, end_token, check_value, no_value_token, display_name, is_link, link_prefix, format_cb) const char *str int len GString *dest @@ -79,6 +91,7 @@ const char *display_name gboolean is_link const char *link_prefix + Gaim::Util::InfoFieldFormatCallback format_cb gboolean gaim_markup_find_tag(needle, haystack, start, end, attributes) @@ -188,13 +201,6 @@ gaim_strdup_withhtml(src) const gchar *src -size_t -gaim_strftime(s, max, format, tm) - char *s - size_t max - const char *format - const struct tm *tm - gchar * gaim_strreplace(string, delimiter, replacement) const char *string @@ -215,6 +221,10 @@ int sec const char * +gaim_time_format(tm) + const struct tm *tm + +const char * gaim_unescape_filename(str) const char *str @@ -242,6 +252,9 @@ const char * gaim_user_dir() +const char * +gaim_utf8_strftime(const char *format, const struct tm *tm); + void gaim_util_set_user_dir(dir) const char *dir diff -r a6811e213977 -r e1e5462b7d81 plugins/perl/common/module.h --- a/plugins/perl/common/module.h Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/perl/common/module.h Thu Feb 02 19:50:51 2006 +0000 @@ -247,6 +247,7 @@ typedef GaimStringref * Gaim__Stringref; /* util.h */ +typedef GaimInfoFieldFormatCallback Gaim__Util__InfoFieldFormatCallback; typedef GaimMenuAction * Gaim__Menu__Action; /* value.h */ diff -r a6811e213977 -r e1e5462b7d81 plugins/perl/common/typemap --- a/plugins/perl/common/typemap Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/perl/common/typemap Thu Feb 02 19:50:51 2006 +0000 @@ -155,6 +155,7 @@ Gaim::StoredImage T_GaimObj Gaim::Stringref T_GaimObj +Gaim::Util::InfoFieldFormatCallback T_PTR Gaim::Value T_GaimObj Gaim::Xfer T_GaimObj diff -r a6811e213977 -r e1e5462b7d81 plugins/timestamp.c --- a/plugins/timestamp.c Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/timestamp.c Thu Feb 02 19:50:51 2006 +0000 @@ -45,7 +45,7 @@ GaimConversation *c = (GaimConversation *)data; GaimGtkConversation *conv = GAIM_GTK_CONVERSATION(c); GtkTextIter iter; - char mdate[7]; + const char *mdate; int is_conversation_active; time_t tim = time(NULL); @@ -63,7 +63,7 @@ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)); gtk_text_buffer_get_end_iter(buffer, &iter); gaim_conversation_set_data(c, "timestamp-conv-active", GINT_TO_POINTER(FALSE)); - strftime(mdate, sizeof(mdate), "\n%H:%M", localtime(&tim)); + mdate = gaim_utf8_strftime("\n%H:%M", localtime(&tim)); gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); if(((y + height) - (rect.y + rect.height)) > height diff -r a6811e213977 -r e1e5462b7d81 plugins/timestamp_format.c --- a/plugins/timestamp_format.c Thu Feb 02 19:39:12 2006 +0000 +++ b/plugins/timestamp_format.c Thu Feb 02 19:50:51 2006 +0000 @@ -3,6 +3,7 @@ #include "debug.h" #include "log.h" #include "plugin.h" +#include "util.h" #include "version.h" #include "gtkconv.h" @@ -55,8 +56,6 @@ gboolean force, const char *dates) { - char buf[64]; - g_return_val_if_fail(conv != NULL, NULL); g_return_val_if_fail(tm != NULL, NULL); g_return_val_if_fail(dates != NULL, NULL); @@ -67,18 +66,13 @@ (time(NULL) > (mktime((struct tm *)tm) + 20*60))) { if (force) - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); + return g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", tm)); else - strftime(buf, sizeof(buf), "%x %X", tm); - - return g_strdup(buf); + return g_strdup(gaim_date_format_long(tm)); } if (force) - { - strftime(buf, sizeof(buf), "%H:%M:%S", tm); - return g_strdup(buf); - } + return g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", tm)); return NULL; } @@ -111,11 +105,7 @@ if (log->type == GAIM_LOG_SYSTEM) { if (force) - { - char buf[64]; - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); - return g_strdup(buf); - } + return g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", tm)); else return NULL; } diff -r a6811e213977 -r e1e5462b7d81 src/debug.c --- a/src/debug.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/debug.c Thu Feb 02 19:50:51 2006 +0000 @@ -25,6 +25,7 @@ #include "debug.h" #include "internal.h" #include "prefs.h" +#include "util.h" static GaimDebugUiOps *debug_ui_ops = NULL; @@ -57,10 +58,10 @@ if ((category != NULL) && (gaim_prefs_exists("/core/debug/timestamps")) && (gaim_prefs_get_bool("/core/debug/timestamps"))) { - gchar mdate[64]; + const char *mdate; time_t mtime = time(NULL); - strftime(mdate, sizeof(mdate), "%H:%M:%S", localtime(&mtime)); + mdate = gaim_utf8_strftime("%H:%M:%S", localtime(&mtime)); ts_s = g_strdup_printf("(%s) ", mdate); } else { ts_s = g_strdup(""); diff -r a6811e213977 -r e1e5462b7d81 src/gtkconv.c --- a/src/gtkconv.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/gtkconv.c Thu Feb 02 19:50:51 2006 +0000 @@ -4666,14 +4666,10 @@ conv, &tm); if (mdate == NULL) { - char buf[64]; - if (time(NULL) > mtime + 20*60) /* show date if older than 20 minutes */ - strftime(buf, sizeof(buf), "%x %X", &tm); + mdate = g_strdup(gaim_date_format_long(&tm)); else - strftime(buf, sizeof(buf), "%X", &tm); - - mdate = g_strdup(buf); + mdate = g_strdup(gaim_time_format(&tm)); } if(gc) diff -r a6811e213977 -r e1e5462b7d81 src/gtkdebug.c --- a/src/gtkdebug.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/gtkdebug.c Thu Feb 02 19:50:51 2006 +0000 @@ -212,8 +212,6 @@ DebugWindow *win = (DebugWindow *)user_data; FILE *fp; char *tmp; - time_t now = time(NULL); - char date[64]; if ((fp = g_fopen(filename, "w+")) == NULL) { gaim_notify_error(win, NULL, _("Unable to open file."), NULL); @@ -221,8 +219,7 @@ } tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL); - strftime(date, sizeof(date), "%c", localtime(&now)); - fprintf(fp, "Gaim Debug Log : %s\n", date); + fprintf(fp, "Gaim Debug Log : %s\n", gaim_date_format_full(time(NULL))); fprintf(fp, "%s", tmp); g_free(tmp); @@ -958,10 +955,10 @@ * not NULL. Why the hell do we do that? --Mark */ if ((category != NULL) && (timestamps)) { - gchar mdate[64]; + const char *mdate; time_t mtime = time(NULL); - strftime(mdate, sizeof(mdate), "%H:%M:%S", localtime(&mtime)); + mdate = gaim_utf8_strftime("%H:%M:%S", localtime(&mtime)); ts_s = g_strdup_printf("(%s) ", mdate); } else { ts_s = g_strdup(""); diff -r a6811e213977 -r e1e5462b7d81 src/gtklog.c --- a/src/gtklog.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/gtklog.c Thu Feb 02 19:50:51 2006 +0000 @@ -114,17 +114,10 @@ if (read && *read && gaim_strcasestr(read, search_term)) { GtkTreeIter iter; GaimLog *log = logs->data; - char title[64]; - char *title_utf8; /* temporary variable for utf8 conversion */ - - gaim_strftime(title, sizeof(title), "%c", localtime(&log->time)); - title_utf8 = gaim_utf8_try_convert(title); - strncpy(title, title_utf8, sizeof(title)); - g_free(title_utf8); gtk_tree_store_append (lv->treestore, &iter, NULL); gtk_tree_store_set(lv->treestore, &iter, - 0, title, + 0, gaim_date_format_full(log->time), 1, log, -1); } g_free(read); @@ -181,7 +174,6 @@ GdkCursor *cursor; GaimLogReadFlags flags; char *read = NULL; - char time[64]; if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return; @@ -206,20 +198,12 @@ if (log->type != GAIM_LOG_SYSTEM) { char *title; - char *title_utf8; /* temporary variable for utf8 conversion */ - - gaim_strftime(time, sizeof(time), "%c", localtime(&log->time)); - if (log->type == GAIM_LOG_CHAT) - title = g_strdup_printf(_("Conversation in %s on %s"), log->name, time); + title = g_strdup_printf(_("Conversation in %s on %s"), + log->name, gaim_date_format_full(log->time)); else - title = g_strdup_printf(_("Conversation with %s on %s"), log->name, time); - - title_utf8 = gaim_utf8_try_convert(title); - g_free(title); - - title = g_strdup_printf("%s", title_utf8); - g_free(title_utf8); + title = g_strdup_printf(_("Conversation with %s on %s"), + log->name, gaim_date_format_full(log->time)); gtk_label_set_markup(GTK_LABEL(viewer->label), title); g_free(title); @@ -259,28 +243,18 @@ /* Logs are made from trees in real life. This is a tree made from logs */ { - char month[30]; - char title[64]; + const char *month; char prev_top_month[30] = ""; - char *utf8_tmp; /* temporary variable for utf8 conversion */ GtkTreeIter toplevel, child; GList *logs = lv->logs; while (logs != NULL) { GaimLog *log = logs->data; - gaim_strftime(month, sizeof(month), "%B %Y", localtime(&log->time)); - gaim_strftime(title, sizeof(title), "%c", localtime(&log->time)); + month = gaim_utf8_strftime(_("%B %Y"), localtime(&log->time)); - /* do utf8 conversions */ - utf8_tmp = gaim_utf8_try_convert(month); - strncpy(month, utf8_tmp, sizeof(month)); - g_free(utf8_tmp); - utf8_tmp = gaim_utf8_try_convert(title); - strncpy(title, utf8_tmp, sizeof(title)); - g_free(utf8_tmp); - - if (strncmp(month, prev_top_month, sizeof(month)) != 0) { + if (strcmp(month, prev_top_month) != 0) + { /* top level */ gtk_tree_store_append(lv->treestore, &toplevel, NULL); gtk_tree_store_set(lv->treestore, &toplevel, 0, month, 1, NULL, -1); @@ -290,7 +264,10 @@ /* sub */ gtk_tree_store_append(lv->treestore, &child, &toplevel); - gtk_tree_store_set(lv->treestore, &child, 0, title, 1, log, -1); + gtk_tree_store_set(lv->treestore, &child, + 0, gaim_date_format_full(log->time), + 1, log, + -1); logs = logs->next; } diff -r a6811e213977 -r e1e5462b7d81 src/gtkpounce.c --- a/src/gtkpounce.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/gtkpounce.c Thu Feb 02 19:50:51 2006 +0000 @@ -1431,8 +1431,6 @@ if (gaim_pounce_action_is_enabled(pounce, "popup-notify")) { - time_t now = time(NULL); - char date[64]; char *tmp; const char *name_shown; const char *reason; @@ -1473,12 +1471,11 @@ if ((name_shown = gaim_account_get_alias(account)) == NULL) name_shown = gaim_account_get_username(account); - strftime(date, sizeof(date), "%c", localtime(&now)); if (reason == NULL) - gaim_notify_info(NULL, name_shown, tmp, date); + gaim_notify_info(NULL, name_shown, tmp, gaim_date_format_full(time(NULL))); else { - char *tmp2 = g_strdup_printf("%s\n\n%s", reason, date); + char *tmp2 = g_strdup_printf("%s\n\n%s", reason, gaim_date_format_full(time(NULL))); gaim_notify_info(NULL, name_shown, tmp, tmp2); g_free(tmp2); } diff -r a6811e213977 -r e1e5462b7d81 src/internal.h --- a/src/internal.h Thu Feb 02 19:39:12 2006 +0000 +++ b/src/internal.h Thu Feb 02 19:50:51 2006 +0000 @@ -162,6 +162,12 @@ # endif #endif +/* Safer ways to work with static buffers. When using non-static + * buffers, either use g_strdup_* functions (preferred) or use + * g_strlcpy/g_strlcpy directly. */ +#define gaim_strlcpy(dest, src) g_strlcpy(dest, src, sizeof(dest)) +#define gaim_strlcat(dest, src) g_strlcat(dest, src, sizeof(dest)) + #define GAIM_WEBSITE "http://gaim.sourceforge.net/" #ifndef _WIN32 diff -r a6811e213977 -r e1e5462b7d81 src/log.c --- a/src/log.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/log.c Thu Feb 02 19:50:51 2006 +0000 @@ -585,30 +585,26 @@ date = gaim_signal_emit_return_1(gaim_log_get_handle(), "log-timestamp", log, &tm); - if (date == NULL) - { - char buf[64]; + if (date != NULL) + return date; - if (log->type == GAIM_LOG_SYSTEM || time(NULL) > when + 20*60) - strftime(buf, sizeof(buf), "%x %X", &tm); - else - strftime(buf, sizeof(buf), "%X", &tm); - - date = g_strdup(buf); - } - - return date; + if (log->type == GAIM_LOG_SYSTEM || time(NULL) > when + 20*60) + return g_strdup(gaim_date_format_long(&tm)); + else + return g_strdup(gaim_time_format(&tm)); } void gaim_log_common_writer(GaimLog *log, const char *ext) { - char date[64]; GaimLogCommonLoggerData *data = log->logger_data; if (data == NULL) { /* This log is new */ - char *dir, *filename, *path; + char *dir; + const char *date; + char *filename; + char *path; dir = gaim_log_get_log_dir(log->type, log->name, log->account); if (dir == NULL) @@ -616,7 +612,7 @@ gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); - strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S", localtime(&log->time)); + date = gaim_utf8_strftime("%Y-%m-%d.%H%M%S", localtime(&log->time)); filename = g_strdup_printf("%s%s", date, ext ? ext : ""); @@ -825,7 +821,6 @@ GaimMessageFlags type, const char *from, time_t time, const char *message) { - char *date; char *xhtml = NULL; if (!log->logger_data) { @@ -833,18 +828,18 @@ * creating a new file there would result in empty files in the case * that you open a convo with someone, but don't say anything. */ - char buf[64]; + const char *date; char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); FILE *file; if (dir == NULL) return; - strftime(buf, sizeof(buf), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); + date = gaim_utf8_strftime("%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); - char *filename = g_build_filename(dir, buf, NULL); + char *filename = g_build_filename(dir, date, NULL); g_free(dir); log->logger_data = g_fopen(filename, "a"); @@ -857,7 +852,7 @@ fprintf(log->logger_data, "\n" "\n"); - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); + date = gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", localtime(&log->time)); fprintf(log->logger_data, "\n", date, log->name, prpl); } @@ -926,9 +921,9 @@ gsize written = 0; if(!data) { - char buf[64]; const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); + const char *date; gaim_log_common_writer(log, ".html"); data = log->logger_data; @@ -937,16 +932,17 @@ if(!data->file) return 0; - strftime(buf, sizeof(buf), "%c", localtime(&log->time)); + date = gaim_date_format_full(log->time); + written += fprintf(data->file, ""); written += fprintf(data->file, ""); written += fprintf(data->file, ""); written += fprintf(data->file, "Conversation with %s at %s on %s (%s)", - log->name, buf, gaim_account_get_username(log->account), prpl); + log->name, date, gaim_account_get_username(log->account), prpl); written += fprintf(data->file, ""); written += fprintf(data->file, "

Conversation with %s at %s on %s (%s)

\n", - log->name, buf, gaim_account_get_username(log->account), prpl); + log->name, date, gaim_account_get_username(log->account), prpl); } /* if we can't write to the file, give up before we hurt ourselves */ @@ -1064,7 +1060,6 @@ * creating a new file there would result in empty files in the case * that you open a convo with someone, but don't say anything. */ - char buf[64]; const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); gaim_log_common_writer(log, ".txt"); @@ -1075,9 +1070,9 @@ if(!data->file) return 0; - strftime(buf, sizeof(buf), "%c", localtime(&log->time)); written += fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", - log->name, buf, gaim_account_get_username(log->account), prpl); + log->name, gaim_date_format_full(log->time), + gaim_account_get_username(log->account), prpl); } /* if we can't write to the file, give up before we hurt ourselves */ diff -r a6811e213977 -r e1e5462b7d81 src/protocols/irc/msgs.c --- a/src/protocols/irc/msgs.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/irc/msgs.c Thu Feb 02 19:50:51 2006 +0000 @@ -241,7 +241,7 @@ gchar *timex = gaim_str_seconds_to_string(irc->whois.idle); g_string_append_printf(info, _("Idle for: %s
"), timex); g_free(timex); - g_string_append_printf(info, _("%s: %s"), _("Online since"), ctime(&irc->whois.signon)); + g_string_append_printf(info, _("%s: %s"), _("Online since"), gaim_date_format_full(irc->whois.signon)); } if (!strcmp(irc->whois.nick, "Paco-Paco")) { g_string_append_printf(info, _("
Defining adjective: Glorious
")); diff -r a6811e213977 -r e1e5462b7d81 src/protocols/jabber/iq.c --- a/src/protocols/jabber/iq.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/jabber/iq.c Thu Feb 02 19:50:51 2006 +0000 @@ -167,7 +167,6 @@ { const char *type, *from, *id; JabberIq *iq; - char buf[1024]; xmlnode *query; time_t now_t; struct tm *now; @@ -180,7 +179,7 @@ id = xmlnode_get_attrib(packet, "id"); if(type && !strcmp(type, "get")) { - char *utf8; + const char *date; iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:time"); jabber_iq_set_id(iq, id); @@ -188,20 +187,14 @@ query = xmlnode_get_child(iq->node, "query"); - strftime(buf, sizeof(buf), "%Y%m%dT%T", now); - xmlnode_insert_data(xmlnode_new_child(query, "utc"), buf, -1); + date = gaim_utf8_strftime("%Y%m%dT%T", now); + xmlnode_insert_data(xmlnode_new_child(query, "utc"), date, -1); - strftime(buf, sizeof(buf), "%Z", now); - if((utf8 = gaim_utf8_try_convert(buf))) { - xmlnode_insert_data(xmlnode_new_child(query, "tz"), utf8, -1); - g_free(utf8); - } + date = gaim_utf8_strftime("%Z", now); + xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1); - strftime(buf, sizeof(buf), "%d %b %Y %T", now); - if((utf8 = gaim_utf8_try_convert(buf))) { - xmlnode_insert_data(xmlnode_new_child(query, "display"), utf8, -1); - g_free(utf8); - } + date = gaim_utf8_strftime("%d %b %Y %T", now); + xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); jabber_iq_send(iq); } diff -r a6811e213977 -r e1e5462b7d81 src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/msn/msn.c Thu Feb 02 19:50:51 2006 +0000 @@ -1422,6 +1422,15 @@ #endif +static char *msn_info_date_reformat(const char *field, size_t len) +{ + char *tmp = g_strndup(field, len); + time_t t = gaim_str_to_time(tmp, FALSE); + + g_free(tmp); + return g_strdup(gaim_date_format_short(localtime(&t))); +} + static void msn_got_info(void *data, const char *url_text, size_t len) { @@ -1512,14 +1521,14 @@ /* Extract their Name and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\nName\n", 0, "\t", 0, "Undisclosed", _("Name"), 0, NULL); + "\nName\n", 0, "\t", 0, "Undisclosed", _("Name"), 0, NULL, NULL); if (found) has_info = TRUE; /* Extract their Age and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tAge\n", 0, "\n", 0, "Undisclosed", _("Age"), 0, NULL); + "\tAge\n", 0, "\n", 0, "Undisclosed", _("Age"), 0, NULL, NULL); if (found) has_info = TRUE; @@ -1527,7 +1536,7 @@ /* Extract their Gender and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, "\nGender\n", 0, "\t", 0, "Undisclosed", _("Gender"), 0, - NULL); + NULL, NULL); if (found) has_info = TRUE; @@ -1535,7 +1544,7 @@ /* Extract their MaritalStatus and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, "\tMarital Status\n", 0, "\n", 0, "Undisclosed", - _("Marital Status"), 0, NULL); + _("Marital Status"), 0, NULL, NULL); if (found) has_info = TRUE; @@ -1543,7 +1552,7 @@ /* Extract their Location and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, "\nLocation\n", 0, "\n", 0, "Undisclosed", _("Location"), 0, - NULL); + NULL, NULL); if (found) has_info = TRUE; @@ -1551,7 +1560,7 @@ /* Extract their Occupation and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Occupation\n", 6, "\n", 0, "Undisclosed", _("Occupation"), - 0, NULL); + 0, NULL, NULL); if (found) has_info = TRUE; @@ -1567,20 +1576,20 @@ /* Check if they have A Little About Me */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL, - _("A Little About Me"), 0, NULL); + _("A Little About Me"), 0, NULL, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, " A Little About Me \n\n", 0, "Hobbies and Interests", '\n', - NULL, _("A Little About Me"), 0, NULL); + NULL, _("A Little About Me"), 0, NULL, NULL); } if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL, - _("A Little About Me"), 0, NULL); + _("A Little About Me"), 0, NULL, NULL); } if (!found) @@ -1588,14 +1597,14 @@ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " A Little About Me \n\n", 0, "My Homepage \n\nTake a look", '\n', - NULL, _("A Little About Me"), 0, NULL); + NULL, _("A Little About Me"), 0, NULL, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, " A Little About Me \n\n", 0, "last updated", '\n', NULL, - _("A Little About Me"), 0, NULL); + _("A Little About Me"), 0, NULL, NULL); } if (found) @@ -1604,27 +1613,27 @@ /* Check if they have Favorite Things */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL, - _("Favorite Things"), 0, NULL); + _("Favorite Things"), 0, NULL, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL, - _("Favorite Things"), 0, NULL); + _("Favorite Things"), 0, NULL, NULL); } if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n', - NULL, _("Favorite Things"), 0, NULL); + NULL, _("Favorite Things"), 0, NULL, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, " Favorite Things \n\n", 0, "last updated", '\n', NULL, - _("Favorite Things"), 0, NULL); + _("Favorite Things"), 0, NULL, NULL); } if (found) @@ -1633,20 +1642,20 @@ /* Check if they have Hobbies and Interests */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL, - _("Hobbies and Interests"), 0, NULL); + _("Hobbies and Interests"), 0, NULL, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look", - '\n', NULL, _("Hobbies and Interests"), 0, NULL); + '\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL, - _("Hobbies and Interests"), 0, NULL); + _("Hobbies and Interests"), 0, NULL, NULL); } if (found) @@ -1655,13 +1664,13 @@ /* Check if they have Favorite Quote */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, - _("Favorite Quote"), 0, NULL); + _("Favorite Quote"), 0, NULL, NULL); if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, "Favorite Quote \n\n", 0, "last updated", '\n', NULL, - _("Favorite Quote"), 0, NULL); + _("Favorite Quote"), 0, NULL, NULL); } if (found) @@ -1670,7 +1679,7 @@ /* Extract the last updated date and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0, - NULL); + NULL, msn_info_date_reformat); if (found) has_info = TRUE; diff -r a6811e213977 -r e1e5462b7d81 src/protocols/novell/novell.c --- a/src/protocols/novell/novell.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/novell/novell.c Thu Feb 02 19:50:51 2006 +0000 @@ -1903,7 +1903,7 @@ gmt = nm_event_get_gmt(event); title = _("Invitation to Conversation"); primary = g_strdup_printf(_("Invitation from: %s\n\nSent: %s"), - name, asctime(localtime(&gmt))); + name, gaim_date_format_full(gmt)); secondary = _("Would you like to join the conversation?"); /* Set up parms list for the callbacks diff -r a6811e213977 -r e1e5462b7d81 src/protocols/oscar/icq.c --- a/src/protocols/oscar/icq.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/oscar/icq.c Thu Feb 02 19:50:51 2006 +0000 @@ -354,7 +354,8 @@ aim_frame_t *fr; aim_snacid_t snacid; int bslen, xmllen; - char *xml, timestr[30]; + char *xml; + const char *timestr; time_t t; struct tm *tm; @@ -366,7 +367,7 @@ time(&t); tm = gmtime(&t); - strftime(timestr, 30, "%a, %d %b %Y %T %Z", tm); + timestr = gaim_utf8_strftime("%a, %d %b %Y %T %Z", tm); /* The length of xml included the null terminating character */ xmllen = 225 + strlen(name) + strlen(msg) + strlen(sess->sn) + strlen(alias) + strlen(timestr) + 1; diff -r a6811e213977 -r e1e5462b7d81 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/oscar/oscar.c Thu Feb 02 19:50:51 2006 +0000 @@ -619,7 +619,7 @@ static gchar *oscar_caps_to_string(guint caps) { GString *str; - gchar *tmp; + const gchar *tmp; guint bit = 1; str = g_string_new(""); @@ -5166,12 +5166,12 @@ if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) { time_t t = userinfo->onlinesince - od->timeoffset; - oscar_string_append(gc->account, str, "\n
", _("Online Since"), ctime(&t)); + oscar_string_append(gc->account, str, "\n
", _("Online Since"), gaim_date_format_full(t)); } if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) { time_t t = userinfo->membersince - od->timeoffset; - oscar_string_append(gc->account, str, "\n
", _("Member Since"), ctime(&t)); + oscar_string_append(gc->account, str, "\n
", _("Member Since"), gaim_date_format_full(t)); } if (userinfo->capabilities != 0) { @@ -6055,53 +6055,6 @@ return 1; } -#if 0 -/* - * Update, 2003-11-09: - * Joseph S. Myers, a gcc dude, fixed this for gcc 3.4! Rock on! - * - * It may not be my place to do this, but... - * I feel pretty strongly that the "last 2 digits" warning is ridiculously - * stupid, and should not exist for % switches (%x in our case) that request - * a year in the preferred representation for the current locale. For that - * reason I've chosen to not use this workaround (n., see kluge). - * - * I have a date. I want to show it to the user in the "preferred" way. - * Whether that displays a 2 digit year is perfectly fine--after all, it's - * what the locale wanted. - * - * If I have a necessity for a full representation of the year in the current - * locale, then I'll use a switch that returns a full representation of the - * year. - * - * If you think the preferred locale should show 4 digits instead of 2 digits - * (because you're anal, or whatever), then change the f***ing locale. - * - * I guess the bottom line is--I'm trying to show a date to the user how they - * prefer to see it, why the hell does gcc want me to change that? - * - * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3190 - * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8714 - */ - -/* - * This function was recommended by the STRFTIME(3) man page to remove the - * "last 2 digits" warning. - */ -static size_t my_strftime(char *s, size_t max, const char *fmt, - const struct tm *tm) -{ - return strftime(s, max, fmt, tm); -} - -/* - * Before even realizing this was here, I went and did the same thing in util.c. - * - * Use gaim_strftime() - */ - -#endif - static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) { GaimConnection *gc = sess->aux_data; @@ -6158,13 +6111,12 @@ if (info->gender != 0) oscar_string_append(gc->account, str, "\n
", _("Gender"), info->gender == 1 ? _("Female") : _("Male")); if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) { - char date[30]; struct tm tm; tm.tm_mday = (int)info->birthday; tm.tm_mon = (int)info->birthmonth-1; tm.tm_year = (int)info->birthyear-1900; - gaim_strftime(date, sizeof(date), "%x", &tm); - oscar_string_append(gc->account, str, "\n
", _("Birthday"), date); + oscar_string_append(gc->account, str, "\n
", _("Birthday"), + gaim_date_format_short(&tm)); } if ((info->age > 0) && (info->age < 255)) { char age[5]; diff -r a6811e213977 -r e1e5462b7d81 src/protocols/yahoo/yahoo_profile.c --- a/src/protocols/yahoo/yahoo_profile.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/protocols/yahoo/yahoo_profile.c Thu Feb 02 19:50:51 2006 +0000 @@ -647,6 +647,15 @@ }, }; +static char *yahoo_info_date_reformat(const char *field, size_t len) +{ + char *tmp = g_strndup(field, len); + time_t t = gaim_str_to_time(tmp, FALSE); + + g_free(tmp); + return g_strdup(gaim_date_format_short(localtime(&t))); +} + static char *yahoo_remove_nonbreaking_spaces(char *str) { char *p; @@ -994,7 +1003,7 @@ * true, since the Yahoo! ID will always be there */ if (!gaim_markup_extract_info_field(stripped, stripped_len, s, strings->yahoo_id_string, 10, "\n", 0, - NULL, _("Yahoo! ID"), 0, NULL)) + NULL, _("Yahoo! ID"), 0, NULL, NULL)) ; #endif @@ -1018,42 +1027,42 @@ /* extract their Email address and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->my_email_string, 1, " ", 0, - strings->private_string, _("Email"), 0, NULL); + strings->private_string, _("Email"), 0, NULL, NULL); /* extract the Nickname if it exists */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, "Nickname:", 1, "\n", '\n', - NULL, _("Nickname"), 0, NULL); + NULL, _("Nickname"), 0, NULL, NULL); /* extract their RealName and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->realname_string, 1, "\n", '\n', - NULL, _("Realname"), 0, NULL); + NULL, _("Realname"), 0, NULL, NULL); /* extract their Location and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->location_string, 2, "\n", '\n', - NULL, _("Location"), 0, NULL); + NULL, _("Location"), 0, NULL, NULL); /* extract their Age and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->age_string, 3, "\n", '\n', - NULL, _("Age"), 0, NULL); + NULL, _("Age"), 0, NULL, NULL); /* extract their MaritalStatus and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->maritalstatus_string, 3, "\n", '\n', - strings->no_answer_string, _("Marital Status"), 0, NULL); + strings->no_answer_string, _("Marital Status"), 0, NULL, NULL); /* extract their Gender and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->gender_string, 3, "\n", '\n', - strings->no_answer_string, _("Gender"), 0, NULL); + strings->no_answer_string, _("Gender"), 0, NULL, NULL); /* extract their Occupation and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->occupation_string, 2, "\n", '\n', - NULL, _("Occupation"), 0, NULL); + NULL, _("Occupation"), 0, NULL, NULL); /* Hobbies, Latest News, and Favorite Quote are a bit different, since * the values can contain embedded newlines... but any or all of them @@ -1066,15 +1075,15 @@ if (!gaim_markup_extract_info_field(stripped, stripped_len, s, strings->hobbies_string, 1, strings->latest_news_string, - '\n', "\n", _("Hobbies"), 0, NULL)) + '\n', "\n", _("Hobbies"), 0, NULL, NULL)) { if (!gaim_markup_extract_info_field(stripped, stripped_len, s, strings->hobbies_string, 1, strings->favorite_quote_string, - '\n', "\n", _("Hobbies"), 0, NULL)) + '\n', "\n", _("Hobbies"), 0, NULL, NULL)) { found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->hobbies_string, 1, strings->links_string, - '\n', "\n", _("Hobbies"), 0, NULL); + '\n', "\n", _("Hobbies"), 0, NULL, NULL); } else found = TRUE; @@ -1084,18 +1093,18 @@ if (!gaim_markup_extract_info_field(stripped, stripped_len, s, strings->latest_news_string, 1, strings->favorite_quote_string, - '\n', "\n", _("Latest News"), 0, NULL)) + '\n', "\n", _("Latest News"), 0, NULL, NULL)) { found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->latest_news_string, 1, strings->links_string, - '\n', "\n", _("Latest News"), 0, NULL); + '\n', "\n", _("Latest News"), 0, NULL, NULL); } else found = TRUE; found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->favorite_quote_string, 1, strings->links_string, - '\n', "\n", _("Favorite Quote"), 0, NULL); + '\n', "\n", _("Favorite Quote"), 0, NULL, NULL); /* Home Page will either be "No home page specified", * or "Home Page: " and a link. @@ -1109,7 +1118,7 @@ { found |= gaim_markup_extract_info_field(stripped, stripped_len, s, strings->home_page_string, 1, "\n", 0, NULL, - _("Home Page"), 1, NULL); + _("Home Page"), 1, NULL, NULL); } } @@ -1124,16 +1133,16 @@ { if (gaim_markup_extract_info_field(stripped, stripped_len, s, strings->cool_link_1_string, 1, "\n", 0, NULL, - _("Cool Link 1"), 1, NULL)) + _("Cool Link 1"), 1, NULL, NULL)) { found = TRUE; if (gaim_markup_extract_info_field(stripped, stripped_len, s, strings->cool_link_2_string, 1, "\n", 0, NULL, - _("Cool Link 2"), 1, NULL)) + _("Cool Link 2"), 1, NULL, NULL)) { gaim_markup_extract_info_field(stripped, stripped_len, s, strings->cool_link_3_string, 1, "\n", 0, NULL, - _("Cool Link 3"), 1, NULL); + _("Cool Link 3"), 1, NULL, NULL); } } } @@ -1141,12 +1150,12 @@ /* see if Member Since is there, and if so, extract it. */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, "Member Since:", 1, last_updated_utf8_string, - '\n', NULL, _("Member Since"), 0, NULL); + '\n', NULL, _("Member Since"), 0, NULL, yahoo_info_date_reformat); /* extract the Last Updated date and put it in */ found |= gaim_markup_extract_info_field(stripped, stripped_len, s, last_updated_utf8_string, 1, " ", '\n', NULL, - _("Last Update"), 0, NULL); + _("Last Update"), 0, NULL, yahoo_info_date_reformat); } /* if (profile_state == PROFILE_STATE_DEFAULT) */ if(!found) diff -r a6811e213977 -r e1e5462b7d81 src/util.c --- a/src/util.c Thu Feb 02 19:39:12 2006 +0000 +++ b/src/util.c Thu Feb 02 19:50:51 2006 +0000 @@ -484,6 +484,46 @@ /************************************************************************** * Date/Time Functions **************************************************************************/ +const char * +gaim_utf8_strftime(const char *format, const struct tm *tm) +{ + static char buf[128]; + char *utf8; + + strftime(buf, sizeof(buf), format, tm); + + if ((utf8 = gaim_utf8_try_convert(buf))) + { + gaim_strlcpy(buf, utf8); + g_free(utf8); + } + + return buf; +} + +const char * +gaim_date_format_short(const struct tm *tm) +{ + return gaim_utf8_strftime("%x", tm); +} + +const char * +gaim_date_format_long(const struct tm *tm) +{ + return gaim_utf8_strftime(_("%x %X"), tm); +} + +const char * +gaim_date_format_full(time_t time) +{ + return gaim_utf8_strftime("%c", localtime(&time)); +} + +const char * +gaim_time_format(const struct tm *tm) +{ + return gaim_utf8_strftime("%X", tm); +} time_t gaim_time_build(int year, int month, int day, int hour, int min, int sec) @@ -507,6 +547,7 @@ struct tm *t; char buf[32]; char *c; + int year = 0; int tzoff = 0; time(&retval); @@ -516,25 +557,35 @@ c = buf; /* 4 digit year */ - if (!sscanf(c, "%04d", &t->tm_year)) return 0; - c += 4; - if (*c == '-') - c++; - - t->tm_year -= 1900; + if (sscanf(c, "%04d", &year) && year > 1900) + { + c += 4; + if (*c == '-') + c++; + t->tm_year -= 1900; + } /* 2 digit month */ - if (!sscanf(c, "%02d", &t->tm_mon)) return 0; + if (!sscanf(c, "%02d", &t->tm_mon)) + return 0; c += 2; - if (*c == '-') + if (*c == '-' || *c == '/') c++; - t->tm_mon -= 1; /* 2 digit day */ - if (!sscanf(c, "%02d", &t->tm_mday)) return 0; + if (!sscanf(c, "%02d", &t->tm_mday)) + return 0; c += 2; - if (*c == 'T' || *c == '.') { /* we have more than a date, keep going */ + if (*c == '/') + { + c++; + + if (!sscanf(c, "%04d", &t->tm_year)) + return 0; + t->tm_year -= 1900; + } + else if (*c == 'T' || *c == '.') { /* we have more than a date, keep going */ c++; /* skip the "T" */ /* 2 digit hour */ @@ -585,10 +636,6 @@ return retval; } -size_t gaim_strftime(char *s, size_t max, const char *format, const struct tm *tm) -{ - return strftime(s, max, format, tm); -} /************************************************************************** * Markup Functions @@ -753,7 +800,8 @@ const char *end_token, char check_value, const char *no_value_token, const char *display_name, gboolean is_link, - const char *link_prefix) + const char *link_prefix, + GaimInfoFieldFormatCallback format_cb) { const char *p, *q; @@ -805,7 +853,14 @@ if (link_prefix) g_string_append(dest, link_prefix); - g_string_append_len(dest, p, q - p); + if (format_cb != NULL) + { + char *reformatted = format_cb(p, q - p); + g_string_append(dest, reformatted); + g_free(reformatted); + } + else + g_string_append_len(dest, p, q - p); g_string_append(dest, "\">"); if (link_prefix) @@ -816,7 +871,14 @@ } else { - g_string_append_len(dest, p, q - p); + if (format_cb != NULL) + { + char *reformatted = format_cb(p, q - p); + g_string_append(dest, reformatted); + g_free(reformatted); + } + else + g_string_append_len(dest, p, q - p); } g_string_append(dest, "
\n"); diff -r a6811e213977 -r e1e5462b7d81 src/util.h --- a/src/util.h Thu Feb 02 19:39:12 2006 +0000 +++ b/src/util.h Thu Feb 02 19:50:51 2006 +0000 @@ -45,6 +45,8 @@ GList *children; } GaimMenuAction; +typedef char *(*GaimInfoFieldFormatCallback)(const char *field, size_t len); + /** * A key-value pair. * @@ -209,6 +211,62 @@ /*@{*/ /** + * Formats a time into the specified format. + * + * This is essentially strftime(), but it has a static buffer + * and handles the UTF-8 conversion for the caller. + */ +const char *gaim_utf8_strftime(const char *format, const struct tm *tm); + +/** + * Formats a time into the user's preferred short date format. + * + * The returned string is stored in a static buffer, so the result + * should be g_strdup()'d if it's going to be kept. + * + * @param time The time value to format (in local time). + * + * @return The date, formatted as per the user's settings. + */ +const char *gaim_date_format_short(const struct tm *tm); + +/** + * Formats a time into the user's preferred short date plus time format. + * + * The returned string is stored in a static buffer, so the result + * should be g_strdup()'d if it's going to be kept. + * + * @param time The time value to format (in local time). + * + * @return The timestamp, formatted as per the user's settings. + */ +const char *gaim_date_format_long(const struct tm *tm); + +/** + * Formats a time into the user's preferred full date and time format. + * + * The returned string is stored in a static buffer, so the result + * should be g_strdup()'d if it's going to be kept. + * + * @param time The time value to format (in local time). + * + * @return The date and time, formatted as per the user's settings. + */ +const char *gaim_date_format_full(time_t time); + +/** + * Formats a time into the user's preferred time format. + * + * The returned string is stored in a static buffer, so the result + * should be g_strdup()'d if it's going to be kept. + * + * @param time The time value to format (in local time). + * + * @return The time, formatted as per the user's settings. + */ +const char *gaim_time_format(const struct tm *tm); + +/** * Builds a time_t from the supplied information. * * @param year The year. @@ -224,7 +282,8 @@ int min, int sec); /** - * Parses a timestamp in jabber or ISO8601 format and returns a time_t. + * Parses a timestamp in jabber, ISO8601, or MM/DD/YYYY format and returns + * a time_t. * * @param timestamp The timestamp * @param utc Assume UTC if no timezone specified @@ -233,17 +292,6 @@ */ time_t gaim_str_to_time(const char *timestamp, gboolean utc); -/** - * Creates a string according to a time and format string - * - * This function just calls strftime. The only advantage to using it - * is that gcc won't give a warning if you use %c - * - * TODO: The warning is gone in gcc4, and this function can - * eventually be removed. - */ -size_t gaim_strftime(char *s, size_t max, const char *format, const struct tm *tm); - /*@}*/ @@ -289,6 +337,7 @@ * @param display_name The short descriptive name to display for this token. * @param is_link TRUE if this should be a link, or FALSE otherwise. * @param link_prefix The prefix for the link. + * @param format_cb A callback to format the value before adding it. * * @return TRUE if successful, or FALSE otherwise. */ @@ -297,7 +346,8 @@ const char *end_token, char check_value, const char *no_value_token, const char *display_name, gboolean is_link, - const char *link_prefix); + const char *link_prefix, + GaimInfoFieldFormatCallback format_cb); /** * Converts HTML markup to XHTML.