Mercurial > pidgin
changeset 21227:059d6deebee7
propagate from branch 'org.maemo.garage.pidgin.pidgin.dialog-transience' (head 49d0219884ede2c6c571f2df73e29dffa86f54ad)
to branch 'im.pidgin.pidgin.next.minor' (head 6f090c623ea4e9357e5b4238348a888b4c869ab7)
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sat, 13 Oct 2007 23:32:54 +0000 |
parents | 5e46cdf9ef2b (diff) 308857bded25 (current diff) |
children | cc8bdfb16ddf 6c4de0d24eff |
files | COPYRIGHT ChangeLog configure.ac pidgin/gtkblist.c pidgin/gtkconv.c pidgin/gtkdialogs.c pidgin/gtknotify.c pidgin/gtkplugin.c |
diffstat | 34 files changed, 772 insertions(+), 124 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Sat Oct 13 00:22:20 2007 +0000 +++ b/COPYRIGHT Sat Oct 13 23:32:54 2007 +0000 @@ -196,6 +196,7 @@ Akuke Kok Konstantin Korikov Cole Kowalski +Matt Kramer Gary Kramlich Jan Kratochvil Andrej Krivulčík
--- a/ChangeLog Sat Oct 13 00:22:20 2007 +0000 +++ b/ChangeLog Sat Oct 13 23:32:54 2007 +0000 @@ -50,6 +50,8 @@ * Pidgin's display is now saved with the command line for session restoration. (David Mohr) * ICQ Birthday notifications are shown as buddy list emblems. + * Plugin actions are now available from the docklet context menu + in addition to the Tool menu of the buddy list. version 2.2.1 (09/29/2007): http://developer.pidgin.im/query?status=closed&milestone=2.2.1
--- a/Doxyfile.in Sat Oct 13 00:22:20 2007 +0000 +++ b/Doxyfile.in Sat Oct 13 23:32:54 2007 +0000 @@ -457,7 +457,8 @@ # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = libpurple/purple-client.h \ + libpurple/purple-client-bindings.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. @@ -857,7 +858,7 @@ # feature is still experimental and incomplete at the # moment. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be @@ -1160,7 +1161,7 @@ # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. -MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_DEPTH = 2 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background.
--- a/Makefile.am Sat Oct 13 00:22:20 2007 +0000 +++ b/Makefile.am Sat Oct 13 23:32:54 2007 +0000 @@ -48,6 +48,13 @@ if HAVE_DOXYGEN @echo "Running doxygen..." @doxygen +if HAVE_XSLTPROC + @echo "Generating devhelp index..." + @xsltproc doxy2devhelp.xsl doc/xml/index.xml > doc/html/pidgin.devhelp + @echo "(Symlink doc/html to ~/.local/share/gtk-doc/html/pidgin to make devhelp see the documentation)" +else + @echo "Not generating devhelp index: xsltproc was not found by configure" +endif else @echo "doxygen was not found during configure. Aborting." @echo;
--- a/configure.ac Sat Oct 13 00:22:20 2007 +0000 +++ b/configure.ac Sat Oct 13 23:32:54 2007 +0000 @@ -2101,6 +2101,10 @@ [AC_HELP_STRING([--enable-dot], [enable graphs in doxygen via 'dot'])], enable_dot="$enableval", enable_dot="yes") +AC_ARG_ENABLE(devhelp, + [AC_HELP_STRING([--enable-devhelp], + [enable building index for devhelp documentation browser])], + enable_devhelp="$enableval", enable_devhelp="yes") if test "x$enable_doxygen" = xyes; then AC_CHECK_PROG(DOXYGEN, doxygen, true, false) @@ -2120,14 +2124,28 @@ AC_DEFINE_UNQUOTED(HAVE_DOT, 1, [whether or not we have dot]) fi fi + + if test "x$enable_devhelp" = "xyes"; then + AC_CHECK_PROG(XSLTPROC, xsltproc, true, false) + + if test $XSLTPROC = false; then + enable_devhelp="no"; + AC_MSG_WARN([*** xsltproc not found; devhelp index will not be created]) + else + AC_DEFINE_UNQUOTED(HAVE_XSLTPROC, 1, [whether or not we have xsltproc for devhelp index]) + fi + fi fi else enable_dot="no" + enable_devhelp="no" fi AC_SUBST(enable_doxygen) AC_SUBST(enable_dot) +AC_SUBST(enable_devhelp) AM_CONDITIONAL(HAVE_DOXYGEN, test "x$enable_doxygen" = "xyes") +AM_CONDITIONAL(HAVE_XSLTPROC, test "x$enable_devhelp" = "xyes") AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [compile with debugging support])], , enable_debug=no)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxy2devhelp.xsl Sat Oct 13 23:32:54 2007 +0000 @@ -0,0 +1,98 @@ +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fo="http://www.w3.org/1999/XSL/Format" + version="1.0"> + +<!-- Based on http://bur.st/~eleusis/devhelp/doxy2devhelp.xsl + (http://bur.st/~eleusis/devhelp/README) + which is based on http://bugzilla.gnome.org/show_bug.cgi?id=122450 +--> + +<xsl:output method="xml" version="1.0" indent="yes"/> + +<xsl:param name="reference_prefix"></xsl:param> + +<xsl:template match="/"> + <book title="Pidgin Documentation" + name="pidgin" + link="{$reference_prefix}main.html"> + <chapters> + <sub name="Modules" link="{$reference_prefix}modules.html"> + <xsl:apply-templates select="doxygenindex/compound[@kind='group']"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> + <!-- annotated.html has the short descriptions beside each struct. is + that more useful than being grouped alphabetically? + --> + <sub name="Structs" link="{$reference_prefix}classes.html"> + <xsl:apply-templates select="doxygenindex/compound[@kind='struct']"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> + <!-- This is redundant given Modules --> + <!-- + <sub name="Directories" link="{$reference_prefix}dirs.html"> + <xsl:apply-templates select="doxygenindex/compound[@kind='dir']"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> + --> + <!-- FIXME: Some files show up here but are broken links; mostly + files that are under pages... + --> + <sub name="Files" link="{$reference_prefix}files.html"> + <xsl:apply-templates select="doxygenindex/compound[@kind='file']"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> + <sub name="Signals, HOWTOs, Other" link="{$reference_prefix}pages.html"> + <xsl:apply-templates select="doxygenindex/compound[@kind='page']"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> + </chapters> + + <functions> + <!-- @todo: maybe select only the real functions, ie those with kind=="function"? --> + <xsl:apply-templates select="doxygenindex/compound/member" mode="as-function"/> + </functions> + </book> +</xsl:template> + +<xsl:template match="compound"> + <xsl:param name="name"><xsl:value-of select="name"/></xsl:param> + <xsl:param name="link"><xsl:value-of select="@refid"/>.html</xsl:param> + <sub name="{$name}" link="{$reference_prefix}{$link}"> + <xsl:apply-templates select="member" mode="as-sub"> + <xsl:sort select="."/> + </xsl:apply-templates> + </sub> +</xsl:template> + +<xsl:template match="member" mode="as-function"> + <!-- + <function name="atk_set_value" link="atk-atkvalue.html#ATK-SET-VALUE"/> + --> + <xsl:param name="name"><xsl:value-of select="name"/></xsl:param> + <!-- Link is refid attribute of parent element + "#" + diff between refid of parent and own refid --> + <xsl:param name="refid_parent"><xsl:value-of select="parent::node()/@refid"/></xsl:param> + <xsl:param name="own_refid"><xsl:value-of select="@refid"/></xsl:param> + <xsl:param name="offset"><xsl:value-of select="string-length($refid_parent) + 3"/></xsl:param> + <xsl:param name="ref_diff"><xsl:value-of select="substring($own_refid, $offset, 33)"/></xsl:param> + <xsl:param name="link"><xsl:value-of select="$refid_parent"/>.html#<xsl:value-of select="$ref_diff"/></xsl:param> + <function name="{$name}" link="{$reference_prefix}{$link}"/> +</xsl:template> + +<xsl:template match="member" mode="as-sub"> + <xsl:param name="name"><xsl:value-of select="name"/></xsl:param> + <!-- Link is refid attribute of parent element + "#" + diff between refid of parent and own refid --> + <xsl:param name="refid_parent"><xsl:value-of select="parent::node()/@refid"/></xsl:param> + <xsl:param name="own_refid"><xsl:value-of select="@refid"/></xsl:param> + <xsl:param name="offset"><xsl:value-of select="string-length($refid_parent) + 3"/></xsl:param> + <xsl:param name="ref_diff"><xsl:value-of select="substring($own_refid, $offset, 33)"/></xsl:param> + <xsl:param name="link"><xsl:value-of select="$refid_parent"/>.html#<xsl:value-of select="$ref_diff"/></xsl:param> + <sub name="{$name}" link="{$reference_prefix}{$link}"/> +</xsl:template> + +</xsl:stylesheet>
--- a/finch/gntnotify.c Sat Oct 13 00:22:20 2007 +0000 +++ b/finch/gntnotify.c Sat Oct 13 23:32:54 2007 +0000 @@ -194,6 +194,7 @@ PurpleAccount *account = purple_connection_get_account(gc); GString *message = g_string_new(NULL); void *ret; + static int key = 0; if (!detailed) { @@ -212,7 +213,7 @@ to = g_strdup_printf("%s (%s)", tos ? *tos : purple_account_get_username(account), purple_account_get_protocol_name(account)); - gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)), + gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(++key), gnt_tree_create_row(GNT_TREE(emaildialog.tree), to, froms ? *froms : "[Unknown sender]", *subjects), @@ -360,7 +361,8 @@ i = 0; for (iter = results->columns; iter; iter = iter->next) { - gnt_tree_set_column_title(GNT_TREE(tree), i, iter->data); + PurpleNotifySearchColumn *column = iter->data; + gnt_tree_set_column_title(GNT_TREE(tree), i, column->title); i++; }
--- a/libpurple/plugins/log_reader.c Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/plugins/log_reader.c Sat Oct 13 23:32:54 2007 +0000 @@ -28,6 +28,19 @@ NAME_GUESS_THEM }; +/* Some common functions. */ +static int get_month(const char *month) +{ + int iter; + const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; + for (iter = 0; months[iter]; iter++) { + if (strcmp(month, months[iter]) == 0) + break; + } + return iter; +} + /***************************************************************************** * Adium Logger * @@ -103,9 +116,10 @@ } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); - char *contents; + char contents[57]; /* XXX: This is really inflexible. */ char *contents2; struct adium_logger_data *data; + size_t rd; PurpleLog *log; if (!handle) { @@ -113,11 +127,9 @@ continue; } - /* XXX: This is really inflexible. */ - contents = g_malloc(57); - fread(contents, 56, 1, handle); + rd = fread(contents, 1, 56, handle) == 0; fclose(handle); - contents[56] = '\0'; + contents[rd] = '\0'; /* XXX: This is fairly inflexible. */ contents2 = contents; @@ -135,11 +147,9 @@ purple_debug_error("Adium log parse", "Contents timestamp parsing error\n"); - g_free(contents); g_free(filename); continue; } - g_free(contents); data = g_new0(struct adium_logger_data, 1); data->path = filename; @@ -168,21 +178,20 @@ } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); - char *contents; + char contents[14]; /* XXX: This is really inflexible. */ char *contents2; struct adium_logger_data *data; PurpleLog *log; + size_t rd; if (!handle) { g_free(filename); continue; } - /* XXX: This is really inflexible. */ - contents = g_malloc(14); - fread(contents, 13, 1, handle); + rd = fread(contents, 1, 13, handle); fclose(handle); - contents[13] = '\0'; + contents[rd] = '\0'; contents2 = contents; while (*contents2 && *contents2 != '(') @@ -195,13 +204,10 @@ purple_debug_error("Adium log parse", "Contents timestamp parsing error\n"); - g_free(contents); g_free(filename); continue; } - g_free(contents); - tm.tm_year -= 1900; tm.tm_mon -= 1; @@ -1355,36 +1361,7 @@ * daylight savings time. */ tm.tm_isdst = -1; - - /* Ugly hack, in case current locale - * is not English. This code is taken - * from log.c. - */ - if (strcmp(month, "Jan") == 0) { - tm.tm_mon= 0; - } else if (strcmp(month, "Feb") == 0) { - tm.tm_mon = 1; - } else if (strcmp(month, "Mar") == 0) { - tm.tm_mon = 2; - } else if (strcmp(month, "Apr") == 0) { - tm.tm_mon = 3; - } else if (strcmp(month, "May") == 0) { - tm.tm_mon = 4; - } else if (strcmp(month, "Jun") == 0) { - tm.tm_mon = 5; - } else if (strcmp(month, "Jul") == 0) { - tm.tm_mon = 6; - } else if (strcmp(month, "Aug") == 0) { - tm.tm_mon = 7; - } else if (strcmp(month, "Sep") == 0) { - tm.tm_mon = 8; - } else if (strcmp(month, "Oct") == 0) { - tm.tm_mon = 9; - } else if (strcmp(month, "Nov") == 0) { - tm.tm_mon = 10; - } else if (strcmp(month, "Dec") == 0) { - tm.tm_mon = 11; - } + tm.tm_mon = get_month(month); data = g_new0( struct trillian_logger_data, 1); @@ -1446,7 +1423,7 @@ file = g_fopen(data->path, "rb"); fseek(file, data->offset, SEEK_SET); - fread(read, data->length, 1, file); + data->length = fread(read, 1, data->length, file); fclose(file); if (read[data->length-1] == '\n') { @@ -1945,7 +1922,7 @@ contents = g_malloc(data->length + 2); fseek(file, data->offset, SEEK_SET); - fread(contents, data->length, 1, file); + data->length = fread(contents, 1, data->length, file); fclose(file); contents[data->length] = '\n'; @@ -2098,6 +2075,347 @@ g_free(data); } +/************************************************************************* + * aMSN Logger * + *************************************************************************/ + +/* The aMSN logger doesn't write logs, only reads them. This is to include + * aMSN logs in the log viewer transparently. + */ + +static PurpleLogLogger *amsn_logger; + +struct amsn_logger_data { + char *path; + int offset; + int length; +}; + +#define AMSN_LOG_CONV_START "|\"LRED[Conversation started on " +#define AMSN_LOG_CONV_END "|\"LRED[You have closed the window on " +#define AMSN_LOG_CONV_EXTRA "01 Aug 2001 00:00:00]" + +static GList *amsn_logger_parse_file(char *filename, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + GError *error; + char *contents; + struct amsn_logger_data *data; + PurpleLog *log; + + purple_debug_info("aMSN logger", "Reading %s\n", filename); + error = NULL; + if (!g_file_get_contents(filename, &contents, NULL, &error)) { + purple_debug_error("aMSN logger", + "Couldn't read file %s: %s \n", filename, + (error && error->message) ? + error->message : "Unknown error"); + if (error) + g_error_free(error); + } else { + char *c = contents; + gboolean found_start = FALSE; + char *start_log = c; + int offset = 0; + struct tm tm; + while (c && *c) { + if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { + char month[4]; + if (sscanf(c + strlen(AMSN_LOG_CONV_START), + "%u %3s %u %u:%u:%u", + &tm.tm_mday, (char*)&month, &tm.tm_year, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + found_start = FALSE; + purple_debug_error("aMSN logger", + "Error parsing start date for %s\n", + filename); + } else { + tm.tm_year -= 1900; + + /* Let the C library deal with + * daylight savings time. + */ + tm.tm_isdst = -1; + tm.tm_mon = get_month(month); + + found_start = TRUE; + offset = c - contents; + start_log = c; + } + } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { + data = g_new0(struct amsn_logger_data, 1); + data->path = g_strdup(filename); + data->offset = offset; + data->length = c - start_log + + strlen(AMSN_LOG_CONV_END) + + strlen(AMSN_LOG_CONV_EXTRA); + log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); + log->logger = amsn_logger; + log->logger_data = data; + list = g_list_prepend(list, log); + found_start = FALSE; + + purple_debug_info("aMSN logger", + "Found log for %s:" + " path = (%s)," + " offset = (%d)," + " length = (%d)\n", + sn, data->path, data->offset, data->length); + } + c = strstr(c, "\n"); + c++; + } + + /* I've seen the file end without the AMSN_LOG_CONV_END bit */ + if (found_start) { + data = g_new0(struct amsn_logger_data, 1); + data->path = g_strdup(filename); + data->offset = offset; + data->length = c - start_log + + strlen(AMSN_LOG_CONV_END) + + strlen(AMSN_LOG_CONV_EXTRA); + log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); + log->logger = amsn_logger; + log->logger_data = data; + list = g_list_prepend(list, log); + found_start = FALSE; + + purple_debug_info("aMSN logger", + "Found log for %s:" + " path = (%s)," + " offset = (%d)," + " length = (%d)\n", + sn, data->path, data->offset, data->length); + } + g_free(contents); + } + + return list; +} + +/* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ +/* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ +static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + const char *logdir; + char *username; + char *log_path; + char *buddy_log; + char *filename; + GDir *dir; + const char *name; + + logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); + + /* By clearing the log directory path, this logger can be (effectively) disabled. */ + if (!logdir || !*logdir) + return NULL; + + /* aMSN only works with MSN/WLM */ + if (strcmp(account->protocol_id, "prpl-msn")) + return NULL; + + username = g_strdup(purple_normalize(account, account->username)); + buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = amsn_logger_parse_file(filename, sn, account); + else + g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); + } + + g_free(log_path); + + /* New versions use 'friendlier' directory names */ + purple_util_chrreplace(username, '@', '_'); + purple_util_chrreplace(username, '.', '_'); + + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); + } + + g_free(log_path); + g_free(username); + g_free(buddy_log); + + return list; +} + +/* Really it's |"L, but the string's been escaped */ +#define AMSN_LOG_FORMAT_TAG "|"L" + +static char *amsn_logger_read(PurpleLog *log, PurpleLogReadFlags *flags) +{ + struct amsn_logger_data *data; + FILE *file; + char *contents; + char *escaped; + GString *formatted; + char *start; + gboolean in_span = FALSE; + + if (flags != NULL) + *flags = PURPLE_LOG_READ_NO_NEWLINE; + + g_return_val_if_fail(log != NULL, g_strdup("")); + + data = log->logger_data; + + g_return_val_if_fail(data->path != NULL, g_strdup("")); + g_return_val_if_fail(data->length > 0, g_strdup("")); + + contents = g_malloc(data->length + 2); + + file = g_fopen(data->path, "rb"); + g_return_val_if_fail(file != NULL, g_strdup("")); + + fseek(file, data->offset, SEEK_SET); + data->length = fread(contents, 1, data->length, file); + fclose(file); + + contents[data->length] = '\n'; + contents[data->length + 1] = '\0'; + + escaped = g_markup_escape_text(contents, -1); + g_free(contents); + contents = escaped; + + formatted = g_string_sized_new(data->length + 2); + + start = contents; + while (start && *start) { + char *end; + char *old_tag; + char *tag; + end = strstr(start, "\n"); + if (!end) + break; + *end = '\0'; + if (purple_str_has_prefix(start, AMSN_LOG_FORMAT_TAG) && in_span) { + /* New format for this line */ + g_string_append(formatted, "</span><br>"); + in_span = FALSE; + } else if (start != contents) { + /* Continue format from previous line */ + g_string_append(formatted, "<br>"); + } + old_tag = start; + tag = strstr(start, AMSN_LOG_FORMAT_TAG); + while (tag) { + g_string_append_len(formatted, old_tag, tag - old_tag); + tag += strlen(AMSN_LOG_FORMAT_TAG); + if (in_span) { + g_string_append(formatted, "</span>"); + in_span = FALSE; + } + if (*tag == 'C') { + /* |"LCxxxxxx is a hex colour */ + char colour[7]; + strncpy(colour, tag + 1, 6); + colour[6] = '\0'; + g_string_append_printf(formatted, "<span style=\"color: #%s;\">", colour); + /* This doesn't appear to work? */ + /* g_string_append_printf(formatted, "<span style=\"color: #%6s;\">", tag + 1); */ + in_span = TRUE; + old_tag = tag + 7; /* C + xxxxxx */ + } else { + /* |"Lxxx is a 3-digit colour code */ + if (purple_str_has_prefix(tag, "RED")) { + g_string_append(formatted, "<span style=\"color: red;\">"); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "GRA")) { + g_string_append(formatted, "<span style=\"color: gray;\">"); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "NOR")) { + g_string_append(formatted, "<span style=\"color: black;\">"); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "ITA")) { + g_string_append(formatted, "<span style=\"color: blue;\">"); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "GRE")) { + g_string_append(formatted, "<span style=\"color: darkgreen;\">"); + in_span = TRUE; + } else { + purple_debug_info("aMSN logger", "Unknown colour format: %3s\n", tag); + } + old_tag = tag + 3; + } + tag = strstr(tag, AMSN_LOG_FORMAT_TAG); + } + g_string_append(formatted, old_tag); + start = end + 1; + } + if (in_span) + g_string_append(formatted, "</span>"); + + g_free(contents); + + return g_string_free(formatted, FALSE); +} + +static int amsn_logger_size(PurpleLog *log) +{ + struct amsn_logger_data *data; + char *text; + int size; + + g_return_val_if_fail(log != NULL, 0); + + data = log->logger_data; + + if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) { + return data ? data->length : 0; + } + + text = amsn_logger_read(log, NULL); + size = strlen(text); + g_free(text); + + return size; +} + +static void amsn_logger_finalize(PurpleLog *log) +{ + struct amsn_logger_data *data; + + g_return_if_fail(log != NULL); + + data = log->logger_data; + g_free(data->path); + g_free(data); +} + /***************************************************************************** * Plugin Code * *****************************************************************************/ @@ -2347,6 +2665,19 @@ #endif purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path ? path : ""); g_free(path); + + /* Add aMSN Messenger log directory preference. */ + purple_prefs_add_none("/plugins/core/log_reader/amsn"); + + /* Calculate default aMSN log directory. */ +#ifdef _WIN32 + folder = wpurple_get_special_folder(CSIDL_PROFILE); /* Silly aMSN, not using CSIDL_APPDATA */ + path = g_build_filename(folder, "amsn", NULL); +#else + path = g_build_filename(purple_home_dir(), ".amsn", NULL); +#endif + purple_prefs_add_string("/plugins/core/log_reader/amsn/log_directory", path); + g_free(path); } static gboolean @@ -2429,6 +2760,18 @@ trillian_logger_size); purple_log_logger_add(trillian_logger); + /* The names of IM clients are marked for translation at the request of + translators who wanted to transliterate them. Many translators + choose to leave them alone. Choose what's best for your language. */ + amsn_logger = purple_log_logger_new("amsn", _("aMSN"), 6, + NULL, + NULL, + amsn_logger_finalize, + amsn_logger_list, + amsn_logger_read, + amsn_logger_size); + purple_log_logger_add(amsn_logger); + return TRUE; } @@ -2445,6 +2788,7 @@ purple_log_logger_remove(msn_logger); purple_log_logger_remove(trillian_logger); purple_log_logger_remove(qip_logger); + purple_log_logger_remove(amsn_logger); return TRUE; } @@ -2505,6 +2849,10 @@ "/plugins/core/log_reader/trillian/log_directory", _("Trillian")); purple_plugin_pref_frame_add(frame, ppref); + ppref = purple_plugin_pref_new_with_name_and_label( + "/plugins/core/log_reader/amsn/log_directory", _("aMSN")); + purple_plugin_pref_frame_add(frame, ppref); + return frame; }
--- a/libpurple/protocols/bonjour/buddy.c Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Sat Oct 13 23:32:54 2007 +0000 @@ -62,9 +62,11 @@ } void -set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, uint32_t len){ +set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, guint32 len){ gchar **fld = NULL; + g_return_if_fail(record_key != NULL); + if (!strcmp(record_key, "1st")) fld = &buddy->first; else if(!strcmp(record_key, "email"))
--- a/libpurple/protocols/bonjour/buddy.h Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.h Sat Oct 13 23:32:54 2007 +0000 @@ -83,7 +83,7 @@ /** * Sets a value in the BonjourBuddy struct, destroying the old value */ -void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, uint32_t len); +void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, guint32 len); /** * Check if all the compulsory buddy data is present.
--- a/libpurple/protocols/simple/simple.c Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Sat Oct 13 23:32:54 2007 +0000 @@ -80,14 +80,15 @@ static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); static void send_notify(struct simple_account_data *sip, struct simple_watcher *); -static void send_publish(struct simple_account_data *sip); +static void send_open_publish(struct simple_account_data *sip); +static void send_closed_publish(struct simple_account_data *sip); static void do_notifies(struct simple_account_data *sip) { GSList *tmp = sip->watcher; purple_debug_info("simple", "do_notifies()\n"); if((sip->republish != -1) || sip->republish < time(NULL)) { if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } @@ -1020,7 +1021,7 @@ case 200: if(sip->registerstatus < SIMPLE_REGISTER_COMPLETE) { /* registered */ if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } sip->registerstatus = SIMPLE_REGISTER_COMPLETE; @@ -1072,7 +1073,7 @@ static void process_incoming_notify(struct simple_account_data *sip, struct sipmsg *msg) { gchar *from; gchar *fromhdr; - gchar *tmp2; + gchar *basicstatus_data; xmlnode *pidf; xmlnode *basicstatus = NULL, *tuple, *status; gboolean isonline = FALSE; @@ -1085,8 +1086,9 @@ if(!pidf) { purple_debug_info("simple", "process_incoming_notify: no parseable pidf\n"); + purple_prpl_got_user_status(sip->account, from, "offline", NULL); + send_sip_response(sip->gc, msg, 200, "OK", NULL); g_free(from); - send_sip_response(sip->gc, msg, 200, "OK", NULL); return; } @@ -1101,27 +1103,28 @@ return; } - tmp2 = xmlnode_get_data(basicstatus); + basicstatus_data = xmlnode_get_data(basicstatus); - if(!tmp2) { + if(!basicstatus_data) { purple_debug_info("simple", "process_incoming_notify: no basic data found\n"); xmlnode_free(pidf); g_free(from); return; } - if(strstr(tmp2, "open")) { + if(strstr(basicstatus_data, "open")) isonline = TRUE; - } + - g_free(tmp2); - - if(isonline) purple_prpl_got_user_status(sip->account, from, "available", NULL); - else purple_prpl_got_user_status(sip->account, from, "offline", NULL); + if(isonline) + purple_prpl_got_user_status(sip->account, from, "available", NULL); + else + purple_prpl_got_user_status(sip->account, from, "offline", NULL); xmlnode_free(pidf); + g_free(from); + g_free(basicstatus_data); - g_free(from); send_sip_response(sip->gc, msg, 200, "OK", NULL); } @@ -1188,28 +1191,27 @@ return doc; } - - -static gchar* gen_pidf(struct simple_account_data *sip) { +static gchar* gen_pidf(struct simple_account_data *sip, gboolean open) { gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n" "xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"\n" "entity=\"sip:%s@%s\">\n" "<tuple id=\"bs35r9f\">\n" "<status>\n" - "<basic>open</basic>\n" + "<basic>%s</basic>\n" "</status>\n" "<note>%s</note>\n" "</tuple>\n" "</presence>", sip->username, sip->servername, - sip->status); + (open == TRUE) ? "open" : "closed", + (open == TRUE) ? sip->status : ""); return doc; } static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) { - gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip); + gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip, TRUE); gchar *hdr = watcher->needsxpidf ? "Event: presence\r\nContent-Type: application/xpidf+xml\r\n" : "Event: presence\r\nContent-Type: application/pidf+xml\r\n"; send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, hdr, doc, &watcher->dialog, NULL); g_free(doc); @@ -1223,9 +1225,9 @@ return TRUE; } -static void send_publish(struct simple_account_data *sip) { +static void send_open_publish(struct simple_account_data *sip) { gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); - gchar *doc = gen_pidf(sip); + gchar *doc = gen_pidf(sip, TRUE); send_sip_request(sip->gc, "PUBLISH", uri, uri, "Expires: 600\r\nEvent: presence\r\n" "Content-Type: application/pidf+xml\r\n", @@ -1235,6 +1237,18 @@ g_free(doc); } +static void send_closed_publish(struct simple_account_data *sip) { + gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); + gchar *doc = gen_pidf(sip, FALSE); + send_sip_request(sip->gc, "PUBLISH", uri, uri, + "Expires: 600\r\nEvent: presence\r\n" + "Content-Type: application/pidf+xml\r\n", + doc, NULL, process_publish_response); + /*sip->republish = time(NULL) + 500;*/ + g_free(uri); + g_free(doc); +} + static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { const char *from_hdr = sipmsg_find_header(msg, "From"); gchar *from = parse_from(from_hdr); @@ -1738,7 +1752,14 @@ if(sip) { /* unregister */ if (sip->registerstatus == SIMPLE_REGISTER_COMPLETE) + { + if(purple_account_get_bool(sip->account, + "dopublish", + TRUE)) + send_closed_publish(sip); + do_register_exp(sip, 0); + } connection_free_all(sip); if (sip->query_data != NULL)
--- a/libpurple/prpl.h Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/prpl.h Sat Oct 13 23:32:54 2007 +0000 @@ -226,11 +226,17 @@ void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); /** - * This must be implemented, and must add at least the offline - * and online states. + * Returns a list of #PurpleStatusType which exist for this account; + * this must be implemented, and must add at least the offline and + * online states. */ GList *(*status_types)(PurpleAccount *account); + /** + * Returns a list of #PurpleMenuAction structs, which represent extra + * actions to be shown in (for example) the right-click menu for @a + * node. + */ GList *(*blist_node_menu)(PurpleBlistNode *node); GList *(*chat_info)(PurpleConnection *); GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name); @@ -258,6 +264,10 @@ void (*set_info)(PurpleConnection *, const char *info); unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleTypingState state); + /** + * Should arrange for purple_notify_userinfo() to be called with + * @a who's user info. + */ void (*get_info)(PurpleConnection *, const char *who); void (*set_status)(PurpleAccount *account, PurpleStatus *status); @@ -287,8 +297,13 @@ /** new user registration */ void (*register_user)(PurpleAccount *); - /* get "chat buddy" info and away message */ + /** Deprecated and vestigal; use #get_cb_real_name and #get_info + * instead. + */ void (*get_cb_info)(PurpleConnection *, int, const char *who); + /** Also deprecated and vestigal; use #get_cb_real_name and + * #status_text instead. + */ void (*get_cb_away)(PurpleConnection *, int, const char *who); /** save/store buddy's alias on server list/roster */ @@ -348,9 +363,12 @@ /* room list serialize */ char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room); - /* Remove the user from the server. (This is only at the bottom to keep binary compatibility.) - * The account can either be connected or disconnected. After the removal is finished, - * the connection will stay open and has to be closed! + /** Remove the user from the server. The account can either be + * connected or disconnected. After the removal is finished, the + * connection will stay open and has to be closed! + */ + /* This is here rather than next to register_user for API compatibility + * reasons. */ void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data);
--- a/libpurple/util.c Sat Oct 13 00:22:20 2007 +0000 +++ b/libpurple/util.c Sat Oct 13 23:32:54 2007 +0000 @@ -2565,6 +2565,8 @@ purple_debug_info("util", "Writing file %s\n", filename_full); + g_return_val_if_fail((size >= -1), FALSE); + filename_temp = g_strdup_printf("%s.save", filename_full); /* Remove an old temporary file, if one exists */ @@ -2590,7 +2592,7 @@ } /* Write to file */ - real_size = (size == -1) ? strlen(data) : size; + real_size = (size == -1) ? strlen(data) : (size_t) size; byteswritten = fwrite(data, 1, real_size, file); /* Close file */
--- a/pidgin/gtkblist.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkblist.c Sat Oct 13 23:32:54 2007 +0000 @@ -617,7 +617,7 @@ static void gtk_blist_menu_bp_cb(GtkWidget *w, PurpleBuddy *b) { - pidgin_pounce_editor_show(b->account, b->name, NULL); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(gtkblist->window), b->account, b->name, NULL); } static void gtk_blist_menu_showlog_cb(GtkWidget *w, PurpleBlistNode *node) @@ -643,7 +643,7 @@ name = prpl_info->get_chat_name(c->components); } } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - pidgin_log_show_contact((PurpleContact *)node); + pidgin_log_show_contact_with_parent(GTK_WINDOW(gtkblist->window), (PurpleContact *)node); pidgin_clear_cursor(gtkblist->window); return; } else { @@ -655,7 +655,7 @@ } if (name && account) { - pidgin_log_show(type, name, account); + pidgin_log_show_with_parent(GTK_WINDOW(gtkblist->window), type, name, account); g_free(name); pidgin_clear_cursor(gtkblist->window); @@ -682,11 +682,6 @@ pidgin_blist_update(purple_get_blist(), node); } -static void gtk_blist_show_systemlog_cb() -{ - pidgin_syslog_show(); -} - static void gtk_blist_show_onlinehelp_cb() { purple_notify_uri(NULL, PURPLE_WEBSITE "documentation"); @@ -3057,6 +3052,11 @@ !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled")); } +static void +pidgin_blist_show_with_parent(gpointer data1, void (*callback)(GtkWindow *parent), gpointer data3) +{ + callback(GTK_WINDOW(gtkblist->window)); +} /*************************************************** * Crap * @@ -3090,15 +3090,15 @@ /* Tools */ { N_("/_Tools"), NULL, NULL, 0, "<Branch>", NULL }, - { N_("/Tools/Buddy _Pounces"), NULL, pidgin_pounces_manager_show, 0, "<Item>", NULL }, + { N_("/Tools/Buddy _Pounces"), NULL, pidgin_blist_show_with_parent, (int)pidgin_pounces_manager_show_with_parent, "<Item>", NULL }, { N_("/Tools/_Certificates"), NULL, pidgin_certmgr_show, 0, "<Item>", NULL }, - { N_("/Tools/Plu_gins"), "<CTL>U", pidgin_plugin_dialog_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_PLUGINS }, + { N_("/Tools/Plu_gins"), "<CTL>U", pidgin_blist_show_with_parent, (int)pidgin_plugin_dialog_show_with_parent, "<StockItem>", PIDGIN_STOCK_TOOLBAR_PLUGINS }, { N_("/Tools/Pr_eferences"), "<CTL>P", pidgin_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, { N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "<Item>", NULL }, { "/Tools/sep2", NULL, NULL, 0, "<Separator>", NULL }, { N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL }, { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL }, - { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL }, + { N_("/Tools/System _Log"), NULL, pidgin_blist_show_with_parent, (int)pidgin_syslog_show_with_parent, "<Item>", NULL }, { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL }, { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL }, /* Help */ @@ -3106,9 +3106,9 @@ { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, #if GTK_CHECK_VERSION(2,6,0) - { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<StockItem>", GTK_STOCK_ABOUT }, + { N_("/Help/_About"), NULL, pidgin_blist_show_with_parent, (int)pidgin_dialogs_about_with_parent, "<StockItem>", GTK_STOCK_ABOUT }, #else - { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL }, + { N_("/Help/_About"), NULL, pidgin_blist_show_with_parent, (int)pidgin_dialogs_about_with_parent, "<Item>", NULL }, #endif };
--- a/pidgin/gtkconv.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkconv.c Sat Oct 13 23:32:54 2007 +0000 @@ -6519,6 +6519,7 @@ AtkObject *accessibility_obj; /* I think this is a little longer than it needs to be but I'm lazy. */ char *style; + gboolean bold = FALSE; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) im = PURPLE_CONV_IM(conv); @@ -6552,7 +6553,7 @@ gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), CONV_TEXT_COLUMN, markup, -1); /* XXX seanegan Why do I have to do this? */ - gtk_widget_queue_draw(gtkconv->infopane); + gtk_widget_queue_draw(gtkconv->infopane); if (title != markup) g_free(markup); @@ -6571,31 +6572,41 @@ style = "color=\"#c4a000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { atk_object_set_description(accessibility_obj, _("Nick Said")); - style = "color=\"#204a87\" weight=\"bold\""; + style = "color=\"#cc0000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - style = "color=\"#cc0000\" weight=\"bold\""; + if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) + style = "color=\"#204a87\" weight=\"bold\""; + else + style = "color=\"#cc0000\" weight=\"bold\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { atk_object_set_description(accessibility_obj, _("New Event")); - style = "color=\"#888a85\" weight=\"bold\""; + style = "color=\"#888a85\""; } else { - style = ""; - } + style = NULL; + } + + if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT || + gtkconv->unseen_state == PIDGIN_UNSEEN_NICK || + gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) + bold = TRUE; - if (*style != '\0') + if (style || bold) { char *html_title,*label; html_title = g_markup_escape_text(title, -1); - label = g_strdup_printf("<span %s>%s</span>", - style, html_title); + label = g_strdup_printf("<span %s %s>%s</span>", + style ? style : "", + bold ? "weight=\"bold\"" : "", + html_title); g_free(html_title); gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); g_free(label); } else gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); - + if (pidgin_conv_window_is_active_conversation(conv)) update_typing_icon(gtkconv);
--- a/pidgin/gtkdebug.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkdebug.c Sat Oct 13 23:32:54 2007 +0000 @@ -36,6 +36,7 @@ #include "gtkimhtml.h" #include "gtkutils.h" #include "pidginstock.h" +#include "gtkblist.h" #ifdef HAVE_REGEX_H # include <regex.h> @@ -673,6 +674,7 @@ static DebugWindow * debug_window_new(void) { + PidginBuddyList *blist; DebugWindow *win; GtkWidget *vbox; GtkWidget *toolbar; @@ -687,6 +689,9 @@ height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/height"); PIDGIN_DIALOG(win->window); + if ((blist = pidgin_blist_get_default_gtk_blist()) != NULL) + if (blist->window) + gtk_window_set_transient_for(GTK_WINDOW(win->window), GTK_WINDOW(blist->window)); purple_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", width, height);
--- a/pidgin/gtkdialogs.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkdialogs.c Sat Oct 13 23:32:54 2007 +0000 @@ -334,6 +334,13 @@ void pidgin_dialogs_about() { + PidginBuddyList *blist = pidgin_blist_get_default_gtk_blist(); + + pidgin_dialogs_about_with_parent(blist ? GTK_WINDOW(blist->window) : NULL); +} + +void pidgin_dialogs_about_with_parent(GtkWindow *parent) +{ GtkWidget *hbox; GtkWidget *vbox; GtkWidget *logo; @@ -349,11 +356,15 @@ GdkPixbuf *pixbuf; if (about != NULL) { + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(about), parent); gtk_window_present(GTK_WINDOW(about)); return; } PIDGIN_DIALOG(about); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(about), parent); tmp = g_strdup_printf(_("About %s"), PIDGIN_NAME); gtk_window_set_title(GTK_WINDOW(about), tmp); g_free(tmp);
--- a/pidgin/gtkdialogs.h Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkdialogs.h Sat Oct 13 23:32:54 2007 +0000 @@ -33,6 +33,7 @@ /* Functions in gtkdialogs.c (these should actually stay in this file) */ void pidgin_dialogs_destroy_all(void); void pidgin_dialogs_about(void); +void pidgin_dialogs_about_with_parent(GtkWindow *parent); void pidgin_dialogs_im(void); void pidgin_dialogs_im_with_user(PurpleAccount *, const char *); void pidgin_dialogs_info(void);
--- a/pidgin/gtkdocklet.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkdocklet.c Sat Oct 13 23:32:54 2007 +0000 @@ -407,7 +407,7 @@ GdkPixbuf *pixbuf; GtkWidget *image; - menuitem = gtk_image_menu_item_new_with_mnemonic(str); + menuitem = gtk_image_menu_item_new_with_label(str); if (menu) gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); @@ -474,6 +474,7 @@ } + static void plugin_act(GtkObject *obj, PurplePluginAction *pam) { @@ -553,7 +554,6 @@ pidgin_separator(menu); } - static void docklet_menu() { static GtkWidget *menu = NULL;
--- a/pidgin/gtkimhtmltoolbar.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Sat Oct 13 23:32:54 2007 +0000 @@ -184,6 +184,8 @@ g_signal_connect_after(G_OBJECT(toolbar->font_dialog), "realize", G_CALLBACK(realize_toolbar_font), toolbar); } + gtk_window_set_transient_for(GTK_WINDOW(toolbar->font_dialog), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)))); gtk_window_present(GTK_WINDOW(toolbar->font_dialog)); } else { cancel_toolbar_font(font, toolbar); @@ -709,6 +711,8 @@ gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_window_set_role(GTK_WINDOW(dialog), "smiley_dialog"); gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)))); if (unique_smileys != NULL) { struct smiley_button_list *ls, *it, *it_tmp;
--- a/pidgin/gtklog.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtklog.c Sat Oct 13 23:32:54 2007 +0000 @@ -523,7 +523,7 @@ } } -static PidginLogViewer *display_log_viewer(struct log_viewer_hash_t *ht, GList *logs, +static PidginLogViewer *display_log_viewer(GtkWindow *parent, struct log_viewer_hash_t *ht, GList *logs, const char *title, GtkWidget *icon, int log_size) { PidginLogViewer *lv; @@ -569,7 +569,7 @@ g_hash_table_insert(log_viewers, ht, lv); /* Window ***********/ - lv->window = gtk_dialog_new_with_buttons(title, NULL, 0, + lv->window = gtk_dialog_new_with_buttons(title, parent, 0, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); #ifdef _WIN32 /* Steal the "HELP" response and use it to trigger browsing to the logs folder */ @@ -676,6 +676,10 @@ } void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account) { + pidgin_log_show_with_parent(NULL, type, screenname, account); +} + +void pidgin_log_show_with_parent(GtkWindow *parent, PurpleLogType type, const char *screenname, PurpleAccount *account) { struct log_viewer_hash_t *ht; PidginLogViewer *lv = NULL; const char *name = screenname; @@ -720,7 +724,7 @@ prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); - display_log_viewer(ht, purple_log_get_logs(type, screenname, account), + display_log_viewer(parent, ht, purple_log_get_logs(type, screenname, account), title, gtk_image_new_from_pixbuf(prpl_icon), purple_log_get_total_size(type, screenname, account)); @@ -730,6 +734,10 @@ } void pidgin_log_show_contact(PurpleContact *contact) { + pidgin_log_show_contact_with_parent(NULL, contact); +} + +void pidgin_log_show_contact_with_parent(GtkWindow *parent, PurpleContact *contact) { struct log_viewer_hash_t *ht = g_new0(struct log_viewer_hash_t, 1); PurpleBlistNode *child; PidginLogViewer *lv = NULL; @@ -783,11 +791,16 @@ } title = g_strdup_printf(_("Conversations with %s"), name); - display_log_viewer(ht, logs, title, image, total_log_size); + display_log_viewer(parent, ht, logs, title, image, total_log_size); g_free(title); } -void pidgin_syslog_show() +void pidgin_syslog_show(void) +{ + pidgin_syslog_show_with_parent(NULL); +} + +void pidgin_syslog_show_with_parent(GtkWindow *parent) { GList *accounts = NULL; GList *logs = NULL; @@ -807,7 +820,7 @@ } logs = g_list_sort(logs, purple_log_compare); - syslog_viewer = display_log_viewer(NULL, logs, _("System Log"), NULL, 0); + syslog_viewer = display_log_viewer(parent, NULL, logs, _("System Log"), NULL, 0); } /****************************************************************************
--- a/pidgin/gtklog.h Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtklog.h Sat Oct 13 23:32:54 2007 +0000 @@ -54,9 +54,12 @@ void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account); +void pidgin_log_show_with_parent(GtkWindow *parent, PurpleLogType type, const char *screenname, PurpleAccount *account); void pidgin_log_show_contact(PurpleContact *contact); +void pidgin_log_show_contact_with_parent(GtkWindow *parent, PurpleContact *contact); void pidgin_syslog_show(void); +void pidgin_syslog_show_with_parent(GtkWindow *parent); /**************************************************************************/ /** @name GTK+ Log Subsystem */
--- a/pidgin/gtknotify.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtknotify.c Sat Oct 13 23:32:54 2007 +0000 @@ -741,7 +741,7 @@ GtkListStore *model; GtkCellRenderer *renderer; guint col_num; - GList *column; + GList *columniter; guint i; GtkWidget *vbox; @@ -825,11 +825,12 @@ -1, "", renderer, "pixbuf", 0, NULL); i = 1; - for (column = results->columns; column != NULL; column = column->next) { + for (columniter = results->columns; columniter != NULL; columniter = columniter->next) { + PurpleNotifySearchColumn *column = columniter->data; renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, - column->data, renderer, "text", i, NULL); + column->title, renderer, "text", i, NULL); i++; }
--- a/pidgin/gtkplugin.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkplugin.c Sat Oct 13 23:32:54 2007 +0000 @@ -533,6 +533,11 @@ void pidgin_plugin_dialog_show() { + pidgin_plugin_dialog_show_with_parent(NULL); +} + +void pidgin_plugin_dialog_show_with_parent(GtkWindow *parent) +{ GtkWidget *sw; GtkWidget *event_view; GtkListStore *ls; @@ -541,6 +546,8 @@ GtkTreeSelection *sel; if (plugin_dialog != NULL) { + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(plugin_dialog), parent); gtk_window_present(GTK_WINDOW(plugin_dialog)); return; } @@ -549,6 +556,8 @@ NULL, GTK_DIALOG_NO_SEPARATOR, NULL); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(plugin_dialog), parent); pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), _("Configure Pl_ugin"), PIDGIN_RESPONSE_CONFIGURE); gtk_dialog_add_button(GTK_DIALOG(plugin_dialog),
--- a/pidgin/gtkplugin.h Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkplugin.h Sat Oct 13 23:32:54 2007 +0000 @@ -77,4 +77,9 @@ */ void pidgin_plugin_dialog_show(void); +/** + * Shows the Plugins dialog, transient to a parent window + */ +void pidgin_plugin_dialog_show_with_parent(GtkWindow *parent); + #endif /* _PIDGINPLUGIN_H_ */
--- a/pidgin/gtkpounce.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkpounce.c Sat Oct 13 23:32:54 2007 +0000 @@ -472,6 +472,13 @@ pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurplePounce *cur_pounce) { + pidgin_pounce_editor_show_with_parent(NULL, account, name, cur_pounce); +} + +void +pidgin_pounce_editor_show_with_parent(GtkWindow *parent, PurpleAccount *account, const char *name, + PurplePounce *cur_pounce) +{ PidginPounceDialog *dialog; GtkWidget *window; GtkWidget *label; @@ -1050,7 +1057,7 @@ static void pounces_manager_add_cb(GtkButton *button, gpointer user_data) { - pidgin_pounce_editor_show(NULL, NULL, NULL); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, NULL); } static void @@ -1060,7 +1067,7 @@ PurplePounce *pounce; gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &pounce, -1); - pidgin_pounce_editor_show(NULL, NULL, pounce); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, pounce); } static void @@ -1160,7 +1167,7 @@ if ((pounce != NULL) && (event->button == 1) && (event->type == GDK_2BUTTON_PRESS)) { - pidgin_pounce_editor_show(NULL, NULL, pounce); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, pounce); return TRUE; } @@ -1311,6 +1318,12 @@ void pidgin_pounces_manager_show(void) { + pidgin_pounces_manager_show_with_parent(NULL); +} + +void +pidgin_pounces_manager_show_with_parent(GtkWindow *parent) +{ PouncesManager *dialog; GtkWidget *bbox; GtkWidget *button; @@ -1321,6 +1334,7 @@ if (pounces_manager != NULL) { gtk_window_present(GTK_WINDOW(pounces_manager->window)); + gtk_window_set_transient_for(GTK_WINDOW(pounces_manager->window), parent); return; } @@ -1331,6 +1345,7 @@ dialog->window = win = pidgin_create_window(_("Buddy Pounces"), PIDGIN_HIG_BORDER, "pounces", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); + gtk_window_set_transient_for(GTK_WINDOW(win), parent); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(pounces_manager_destroy_cb), dialog);
--- a/pidgin/gtkpounce.h Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkpounce.h Sat Oct 13 23:32:54 2007 +0000 @@ -31,16 +31,28 @@ /** * Displays a New Buddy Pounce or Edit Buddy Pounce dialog. * + * @param parent The parent window. * @param account The optional account to use. * @param name The optional name to pounce on. * @param cur_pounce The current buddy pounce, if editing an existing one. */ +void pidgin_pounce_editor_show_with_parent(GtkWindow *parent, PurpleAccount *account, const char *name, + PurplePounce *cur_pounce); + +/** + * @deprecated Please use pidgin_pounce_editor_show_with_parent + */ void pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurplePounce *cur_pounce); /** * Shows the pounces manager window. */ +void pidgin_pounces_manager_show_with_parent(GtkWindow *parent); + +/** + * @deprecated Please use pidgin_pounces_manager_show_with_parent + */ void pidgin_pounces_manager_show(void); /**
--- a/pidgin/gtksound.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtksound.c Sat Oct 13 23:32:54 2007 +0000 @@ -118,12 +118,9 @@ if (conv != NULL && PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { PidginConversation *gtkconv; - PidginWindow *win; gboolean has_focus; gtkconv = PIDGIN_CONVERSATION(conv); - win = gtkconv->win; - has_focus = purple_conversation_has_focus(conv); if (!gtkconv->make_sound ||
--- a/pidgin/gtkutils.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/gtkutils.c Sat Oct 13 23:32:54 2007 +0000 @@ -1526,6 +1526,8 @@ if (prpl_info && prpl_info->can_receive_file) ft = prpl_info->can_receive_file(gc, who); + else if (prpl_info && prpl_info->send_file) + ft = TRUE; if (im && ft) purple_request_choice(NULL, NULL, @@ -1559,6 +1561,7 @@ _("Set as buddy icon"), DND_BUDDY_ICON, (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), NULL); + gdk_pixbuf_unref(pb); return; }
--- a/pidgin/plugins/history.c Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/plugins/history.c Sat Oct 13 23:32:54 2007 +0000 @@ -42,6 +42,7 @@ GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; char *header; char *protocol; + char *escaped_alias; convtype = purple_conversation_get_type(c); gtkconv = PIDGIN_CONVERSATION(c); @@ -120,10 +121,12 @@ if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", options); - header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias, + escaped_alias = g_markup_escape_text(alias, -1); + header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), escaped_alias, purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options); g_free(header); + g_free(escaped_alias); g_strchomp(history); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), history, options);
--- a/pidgin/plugins/perl/common/GtkDialogs.xs Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkDialogs.xs Sat Oct 13 23:32:54 2007 +0000 @@ -10,6 +10,10 @@ pidgin_dialogs_about() void +pidgin_dialogs_about_with_parent(parent) + void * parent + +void pidgin_dialogs_im() void
--- a/pidgin/plugins/perl/common/GtkLog.xs Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkLog.xs Sat Oct 13 23:32:54 2007 +0000 @@ -13,11 +13,27 @@ Purple::Account account void +pidgin_log_show_with_parent(parent, type, screenname, account) + void * parent + Purple::LogType type + const char * screenname + Purple::Account account + +void pidgin_log_show_contact(contact) Purple::BuddyList::Contact contact +void +pidgin_log_show_contact_with_parent(parent, contact) + void * parent + Purple::BuddyList::Contact contact + MODULE = Pidgin::Log PACKAGE = Pidgin::SysLog PREFIX = pidgin_syslog_ PROTOTYPES: ENABLE void pidgin_syslog_show() + +void +pidgin_syslog_show_with_parent(parent) + void * parent
--- a/pidgin/plugins/perl/common/GtkPlugin.xs Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkPlugin.xs Sat Oct 13 23:32:54 2007 +0000 @@ -11,3 +11,7 @@ void pidgin_plugin_dialog_show() + +void +pidgin_plugin_dialog_show_with_parent(parent) + void * parent
--- a/pidgin/plugins/perl/common/GtkPounce.xs Sat Oct 13 00:22:20 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkPounce.xs Sat Oct 13 23:32:54 2007 +0000 @@ -9,6 +9,13 @@ const char * name Purple::Pounce cur_pounce +void +pidgin_pounce_editor_show_with_parent(parent, account, name, cur_pounce) + void * parent + Purple::Account account + const char * name + Purple::Pounce cur_pounce + MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces PREFIX = pidgin_pounces_ PROTOTYPES: ENABLE @@ -22,4 +29,8 @@ pidgin_pounces_manager_show() void +pidgin_pounces_manager_show_with_parent(parent) + void * parent + +void pidgin_pounces_manager_hide()