Mercurial > pidgin
comparison src/log.c @ 12737:a1e241dd50b6
[gaim-migrate @ 15082]
Conversation and Logging Message Timestamp Formatting...
The idea here is that we should honor the user's locale for message timestamps in the conversation window and in the logs.
I've added a signal and created a plugin that allows one to override this. The plugin is named "Message Timestamp Formats". Enabling that will by default change the timestamps back to the format we had before this commit. (That is to say, it forces the old format and ignores the locale.) The plugin also has options to show dates in the timestamps "Always", "In Chats", or "For Delayed Messages" (the default behavior).
This addresses all requests for 12 hour timestamps, allows people to continue with the 24 hour timestamps we have, even if their locale says differently, enables plugin authors to override the message timestamp formats in any way they choose, and addresses requests for complete dates in logs.
To recap, if you don't like the format string your locale has, enabled the "Message Timestamp Formats" plugin.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Thu, 05 Jan 2006 20:17:36 +0000 |
parents | 4da7062a06c2 |
children | 4152c8f14a02 |
comparison
equal
deleted
inserted
replaced
12736:f49d49444c68 | 12737:a1e241dd50b6 |
---|---|
483 } | 483 } |
484 | 484 |
485 return g_list_sort(logs, gaim_log_compare); | 485 return g_list_sort(logs, gaim_log_compare); |
486 } | 486 } |
487 | 487 |
488 /**************************************************************************** | |
489 * LOG SUBSYSTEM ************************************************************ | |
490 ****************************************************************************/ | |
491 | |
492 void * | |
493 gaim_log_get_handle(void) | |
494 { | |
495 static int handle; | |
496 | |
497 return &handle; | |
498 } | |
499 | |
488 void gaim_log_init(void) | 500 void gaim_log_init(void) |
489 { | 501 { |
502 void *handle = gaim_log_get_handle(); | |
503 | |
490 gaim_prefs_add_none("/core/logging"); | 504 gaim_prefs_add_none("/core/logging"); |
491 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); | 505 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); |
492 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); | 506 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); |
493 gaim_prefs_add_bool("/core/logging/log_system", FALSE); | 507 gaim_prefs_add_bool("/core/logging/log_system", FALSE); |
494 | 508 |
495 gaim_prefs_add_string("/core/logging/format", "txt"); | 509 gaim_prefs_add_string("/core/logging/format", "txt"); |
496 gaim_prefs_add_bool("/core/logging/include_date_timestamps", FALSE); | |
497 | 510 |
498 html_logger = gaim_log_logger_new("html", _("HTML"), 8, | 511 html_logger = gaim_log_logger_new("html", _("HTML"), 8, |
499 NULL, | 512 NULL, |
500 html_logger_write, | 513 html_logger_write, |
501 html_logger_finalize, | 514 html_logger_finalize, |
527 old_logger_total_size, | 540 old_logger_total_size, |
528 NULL, | 541 NULL, |
529 old_logger_get_log_sets); | 542 old_logger_get_log_sets); |
530 gaim_log_logger_add(old_logger); | 543 gaim_log_logger_add(old_logger); |
531 | 544 |
545 gaim_signal_register(handle, "log-timestamp", | |
546 gaim_marshal_POINTER__POINTER_POINTER, | |
547 gaim_value_new(GAIM_TYPE_POINTER), 2, | |
548 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
549 GAIM_SUBTYPE_LOG), | |
550 gaim_value_new(GAIM_TYPE_POINTER)); | |
551 | |
532 gaim_prefs_connect_callback(NULL, "/core/logging/format", | 552 gaim_prefs_connect_callback(NULL, "/core/logging/format", |
533 logger_pref_cb, NULL); | 553 logger_pref_cb, NULL); |
534 gaim_prefs_trigger_callback("/core/logging/format"); | 554 gaim_prefs_trigger_callback("/core/logging/format"); |
535 | 555 |
536 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, | 556 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, |
537 (GEqualFunc)_gaim_logsize_user_equal, | 557 (GEqualFunc)_gaim_logsize_user_equal, |
538 (GDestroyNotify)_gaim_logsize_user_free_key, NULL); | 558 (GDestroyNotify)_gaim_logsize_user_free_key, NULL); |
539 } | 559 } |
540 | 560 |
561 void | |
562 gaim_log_uninit(void) | |
563 { | |
564 gaim_signals_unregister_by_instance(gaim_log_get_handle()); | |
565 } | |
566 | |
541 /**************************************************************************** | 567 /**************************************************************************** |
542 * LOGGERS ****************************************************************** | 568 * LOGGERS ****************************************************************** |
543 ****************************************************************************/ | 569 ****************************************************************************/ |
570 | |
571 static char *log_get_timestamp(GaimLog *log, time_t when) | |
572 { | |
573 char *date; | |
574 struct tm tm = *(localtime(&when)); | |
575 | |
576 date = gaim_signal_emit_return_1(gaim_log_get_handle(), | |
577 "log-timestamp", | |
578 log, &tm); | |
579 if (date == NULL) | |
580 { | |
581 char buf[64]; | |
582 | |
583 if (log->type == GAIM_LOG_SYSTEM || time(NULL) > when + 20*60) | |
584 strftime(buf, sizeof(buf), "%x %X", &tm); | |
585 else | |
586 strftime(buf, sizeof(buf), "%X", &tm); | |
587 | |
588 date = g_strdup(buf); | |
589 } | |
590 | |
591 return date; | |
592 } | |
544 | 593 |
545 void gaim_log_common_writer(GaimLog *log, const char *ext) | 594 void gaim_log_common_writer(GaimLog *log, const char *ext) |
546 { | 595 { |
547 char date[64]; | 596 char date[64]; |
548 GaimLogCommonLoggerData *data = log->logger_data; | 597 GaimLogCommonLoggerData *data = log->logger_data; |
762 | 811 |
763 static void xml_logger_write(GaimLog *log, | 812 static void xml_logger_write(GaimLog *log, |
764 GaimMessageFlags type, | 813 GaimMessageFlags type, |
765 const char *from, time_t time, const char *message) | 814 const char *from, time_t time, const char *message) |
766 { | 815 { |
767 char date[64]; | 816 char *date; |
768 char *xhtml = NULL; | 817 char *xhtml = NULL; |
769 | 818 |
770 if (!log->logger_data) { | 819 if (!log->logger_data) { |
771 /* This log is new. We could use the loggers 'new' function, but | 820 /* This log is new. We could use the loggers 'new' function, but |
772 * creating a new file there would result in empty files in the case | 821 * creating a new file there would result in empty files in the case |
773 * that you open a convo with someone, but don't say anything. | 822 * that you open a convo with someone, but don't say anything. |
774 */ | 823 */ |
824 char buf[64]; | |
775 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); | 825 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); |
776 FILE *file; | 826 FILE *file; |
777 | 827 |
778 if (dir == NULL) | 828 if (dir == NULL) |
779 return; | 829 return; |
780 | 830 |
781 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); | 831 strftime(buf, sizeof(buf), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
782 | 832 |
783 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | 833 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
784 | 834 |
785 char *filename = g_build_filename(dir, date, NULL); | 835 char *filename = g_build_filename(dir, buf, NULL); |
786 g_free(dir); | 836 g_free(dir); |
787 | 837 |
788 log->logger_data = g_fopen(filename, "a"); | 838 log->logger_data = g_fopen(filename, "a"); |
789 if (!log->logger_data) { | 839 if (!log->logger_data) { |
790 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | 840 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); |
793 } | 843 } |
794 g_free(filename); | 844 g_free(filename); |
795 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" | 845 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
796 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | 846 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); |
797 | 847 |
798 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | 848 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
799 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", | 849 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
800 date, log->name, prpl); | 850 date, log->name, prpl); |
801 } | 851 } |
802 | 852 |
803 /* if we can't write to the file, give up before we hurt ourselves */ | 853 /* if we can't write to the file, give up before we hurt ourselves */ |
804 if(!data->file) | 854 if(!data->file) |
805 return; | 855 return; |
806 | 856 |
807 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps")) | 857 date = log_get_timestamp(log, time); |
808 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); | |
809 else | |
810 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
811 | 858 |
812 gaim_markup_html_to_xhtml(message, &xhtml, NULL); | 859 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
813 if (from) | 860 if (from) |
814 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", | 861 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
815 str_from_msg_type(type), | 862 str_from_msg_type(type), |
821 str_from_msg_type(type), | 868 str_from_msg_type(type), |
822 type & GAIM_MESSAGE_SEND ? "direction='sent'" : | 869 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
823 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | 870 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", |
824 date, xhtml): | 871 date, xhtml): |
825 fflush(log->logger_data); | 872 fflush(log->logger_data); |
873 g_free(date); | |
826 g_free(xhtml); | 874 g_free(xhtml); |
827 } | 875 } |
828 | 876 |
829 static void xml_logger_finalize(GaimLog *log) | 877 static void xml_logger_finalize(GaimLog *log) |
830 { | 878 { |
858 | 906 |
859 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | 907 static void html_logger_write(GaimLog *log, GaimMessageFlags type, |
860 const char *from, time_t time, const char *message) | 908 const char *from, time_t time, const char *message) |
861 { | 909 { |
862 char *msg_fixed; | 910 char *msg_fixed; |
863 char date[64]; | 911 char *date; |
864 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); | 912 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
865 GaimLogCommonLoggerData *data = log->logger_data; | 913 GaimLogCommonLoggerData *data = log->logger_data; |
866 | 914 |
867 if(!data) { | 915 if(!data) { |
916 char buf[64]; | |
868 const char *prpl = | 917 const char *prpl = |
869 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | 918 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); |
870 gaim_log_common_writer(log, ".html"); | 919 gaim_log_common_writer(log, ".html"); |
871 | 920 |
872 data = log->logger_data; | 921 data = log->logger_data; |
873 | 922 |
874 /* if we can't write to the file, give up before we hurt ourselves */ | 923 /* if we can't write to the file, give up before we hurt ourselves */ |
875 if(!data->file) | 924 if(!data->file) |
876 return; | 925 return; |
877 | 926 |
878 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | 927 strftime(buf, sizeof(buf), "%c", localtime(&log->time)); |
879 fprintf(data->file, "<html><head>"); | 928 fprintf(data->file, "<html><head>"); |
880 fprintf(data->file, "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">"); | 929 fprintf(data->file, "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">"); |
881 fprintf(data->file, "<title>"); | 930 fprintf(data->file, "<title>"); |
882 fprintf(data->file, "Conversation with %s at %s on %s (%s)", | 931 fprintf(data->file, "Conversation with %s at %s on %s (%s)", |
883 log->name, date, gaim_account_get_username(log->account), prpl); | 932 log->name, buf, gaim_account_get_username(log->account), prpl); |
884 fprintf(data->file, "</title></head><body>"); | 933 fprintf(data->file, "</title></head><body>"); |
885 fprintf(data->file, | 934 fprintf(data->file, |
886 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", | 935 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
887 log->name, date, gaim_account_get_username(log->account), prpl); | 936 log->name, date, gaim_account_get_username(log->account), prpl); |
888 | |
889 } | 937 } |
890 | 938 |
891 /* if we can't write to the file, give up before we hurt ourselves */ | 939 /* if we can't write to the file, give up before we hurt ourselves */ |
892 if(!data->file) | 940 if(!data->file) |
893 return; | 941 return; |
894 | 942 |
895 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); | 943 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); |
944 date = log_get_timestamp(log, time); | |
896 | 945 |
897 if(log->type == GAIM_LOG_SYSTEM){ | 946 if(log->type == GAIM_LOG_SYSTEM){ |
898 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); | |
899 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date); | 947 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date); |
900 } else { | 948 } else { |
901 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps")) | |
902 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); | |
903 else | |
904 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
905 | |
906 if (type & GAIM_MESSAGE_SYSTEM) | 949 if (type & GAIM_MESSAGE_SYSTEM) |
907 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed); | 950 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed); |
908 else if (type & GAIM_MESSAGE_WHISPER) | 951 else if (type & GAIM_MESSAGE_WHISPER) |
909 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n", | 952 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n", |
910 date, from, msg_fixed); | 953 date, from, msg_fixed); |
927 else | 970 else |
928 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", | 971 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", |
929 date, from, msg_fixed); | 972 date, from, msg_fixed); |
930 } | 973 } |
931 } | 974 } |
932 | 975 g_free(date); |
933 g_free(msg_fixed); | 976 g_free(msg_fixed); |
934 fflush(data->file); | 977 fflush(data->file); |
935 } | 978 } |
936 | 979 |
937 static void html_logger_finalize(GaimLog *log) | 980 static void html_logger_finalize(GaimLog *log) |
984 | 1027 |
985 static void txt_logger_write(GaimLog *log, | 1028 static void txt_logger_write(GaimLog *log, |
986 GaimMessageFlags type, | 1029 GaimMessageFlags type, |
987 const char *from, time_t time, const char *message) | 1030 const char *from, time_t time, const char *message) |
988 { | 1031 { |
989 char date[64]; | 1032 char *date; |
990 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); | 1033 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
991 GaimLogCommonLoggerData *data = log->logger_data; | 1034 GaimLogCommonLoggerData *data = log->logger_data; |
992 char *stripped = NULL; | 1035 char *stripped = NULL; |
993 | 1036 |
994 if (data == NULL) { | 1037 if (data == NULL) { |
995 /* This log is new. We could use the loggers 'new' function, but | 1038 /* This log is new. We could use the loggers 'new' function, but |
996 * creating a new file there would result in empty files in the case | 1039 * creating a new file there would result in empty files in the case |
997 * that you open a convo with someone, but don't say anything. | 1040 * that you open a convo with someone, but don't say anything. |
998 */ | 1041 */ |
1042 char buf[64]; | |
999 const char *prpl = | 1043 const char *prpl = |
1000 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | 1044 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); |
1001 gaim_log_common_writer(log, ".txt"); | 1045 gaim_log_common_writer(log, ".txt"); |
1002 | 1046 |
1003 data = log->logger_data; | 1047 data = log->logger_data; |
1004 | 1048 |
1005 /* if we can't write to the file, give up before we hurt ourselves */ | 1049 /* if we can't write to the file, give up before we hurt ourselves */ |
1006 if(!data->file) | 1050 if(!data->file) |
1007 return; | 1051 return; |
1008 | 1052 |
1009 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | 1053 strftime(buf, sizeof(buf), "%c", localtime(&log->time)); |
1010 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", | 1054 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
1011 log->name, date, gaim_account_get_username(log->account), prpl); | 1055 log->name, buf, gaim_account_get_username(log->account), prpl); |
1012 } | 1056 } |
1013 | 1057 |
1014 /* if we can't write to the file, give up before we hurt ourselves */ | 1058 /* if we can't write to the file, give up before we hurt ourselves */ |
1015 if(!data->file) | 1059 if(!data->file) |
1016 return; | 1060 return; |
1017 | 1061 |
1018 stripped = gaim_markup_strip_html(message); | 1062 stripped = gaim_markup_strip_html(message); |
1019 | 1063 date = log_get_timestamp(log, time); |
1020 if(log->type == GAIM_LOG_SYSTEM){ | 1064 |
1021 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); | 1065 if(log->type == GAIM_LOG_SYSTEM){ |
1022 fprintf(data->file, "---- %s @ %s ----\n", stripped, date); | 1066 fprintf(data->file, "---- %s @ %s ----\n", stripped, date); |
1023 } else { | 1067 } else { |
1024 if (gaim_prefs_get_bool("/core/logging/include_date_timestamps")) | 1068 if (type & GAIM_MESSAGE_SEND || |
1025 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); | 1069 type & GAIM_MESSAGE_RECV) { |
1070 if (type & GAIM_MESSAGE_AUTO_RESP) { | |
1071 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, | |
1072 from, stripped); | |
1073 } else { | |
1074 if(gaim_message_meify(stripped, -1)) | |
1075 fprintf(data->file, "(%s) ***%s %s\n", date, from, | |
1076 stripped); | |
1077 else | |
1078 fprintf(data->file, "(%s) %s: %s\n", date, from, | |
1079 stripped); | |
1080 } | |
1081 } else if (type & GAIM_MESSAGE_SYSTEM) | |
1082 fprintf(data->file, "(%s) %s\n", date, stripped); | |
1083 else if (type & GAIM_MESSAGE_NO_LOG) { | |
1084 /* This shouldn't happen */ | |
1085 g_free(stripped); | |
1086 return; | |
1087 } else if (type & GAIM_MESSAGE_WHISPER) | |
1088 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); | |
1026 else | 1089 else |
1027 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | 1090 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", |
1028 | 1091 from ? ":" : "", stripped); |
1029 if (type & GAIM_MESSAGE_SEND || | 1092 } |
1030 type & GAIM_MESSAGE_RECV) { | 1093 g_free(date); |
1031 if (type & GAIM_MESSAGE_AUTO_RESP) { | 1094 g_free(stripped); |
1032 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, | 1095 fflush(data->file); |
1033 from, stripped); | |
1034 } else { | |
1035 if(gaim_message_meify(stripped, -1)) | |
1036 fprintf(data->file, "(%s) ***%s %s\n", date, from, | |
1037 stripped); | |
1038 else | |
1039 fprintf(data->file, "(%s) %s: %s\n", date, from, | |
1040 stripped); | |
1041 } | |
1042 } else if (type & GAIM_MESSAGE_SYSTEM) | |
1043 fprintf(data->file, "(%s) %s\n", date, stripped); | |
1044 else if (type & GAIM_MESSAGE_NO_LOG) { | |
1045 /* This shouldn't happen */ | |
1046 g_free(stripped); | |
1047 return; | |
1048 } else if (type & GAIM_MESSAGE_WHISPER) | |
1049 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); | |
1050 else | |
1051 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", | |
1052 from ? ":" : "", stripped); | |
1053 } | |
1054 | |
1055 fflush(data->file); | |
1056 g_free(stripped); | |
1057 } | 1096 } |
1058 | 1097 |
1059 static void txt_logger_finalize(GaimLog *log) | 1098 static void txt_logger_finalize(GaimLog *log) |
1060 { | 1099 { |
1061 GaimLogCommonLoggerData *data = log->logger_data; | 1100 GaimLogCommonLoggerData *data = log->logger_data; |