Mercurial > pidgin
changeset 23003:f11fc3fb5b8c
Use text-tags to set the weight/color of the nick in conversations. This
simplifies pidgin_conv_write_conv a bit, I think. This also has the added
benefit that the colors in an existing conversation are changed to the
new color retroactively when the colors are changed using the
theme-control plugin.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 19 May 2008 18:23:25 +0000 |
parents | d03b32530854 |
children | a544f4ad00c5 |
files | pidgin/gtkconv.c pidgin/gtkimhtml.c |
diffstat | 2 files changed, 158 insertions(+), 177 deletions(-) [+] |
line wrap: on
line diff
--- a/pidgin/gtkconv.c Sun May 18 21:22:38 2008 +0000 +++ b/pidgin/gtkconv.c Mon May 19 18:23:25 2008 +0000 @@ -96,10 +96,10 @@ #define PIDGIN_CONV_ALL ((1 << 7) - 1) +/* XXX: These color defines shouldn't really be here. But the nick-color + * generation algorithm uses them, so keeping these around until we fix that. */ #define DEFAULT_SEND_COLOR "#204a87" -#define DEFAULT_RECV_COLOR "#cc0000" #define DEFAULT_HIGHLIGHT_COLOR "#AF7F00" -#define DEFAULT_ACTION_COLOR "#062585" #define BUDDYICON_SIZE_MIN 32 #define BUDDYICON_SIZE_MAX 96 @@ -163,6 +163,7 @@ static void pidgin_conv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data); static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); +static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create); static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); @@ -3875,6 +3876,7 @@ gboolean is_buddy; gchar *tmp, *alias_key, *name, *alias; int flags; + GdkColor *color = NULL; alias = cb->alias; name = cb->name; @@ -3901,71 +3903,50 @@ alias_key = g_utf8_collate_key(tmp, -1); g_free(tmp); - if (is_me) - { - GdkColor send_color; - gdk_color_parse(DEFAULT_SEND_COLOR, &send_color); + if (is_me) { + GtkTextTag *tag = gtk_text_tag_table_lookup( + gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), + "send-name"); + g_object_get(tag, "foreground-gdk", &color, NULL); + } else { + color = (GdkColor*)get_nick_color(gtkconv, name); + } #if GTK_CHECK_VERSION(2,6,0) - gtk_list_store_insert_with_values(ls, &iter, + gtk_list_store_insert_with_values(ls, &iter, /* - * The GTK docs are mute about the effects of the "row" value for performance. - * X-Chat hardcodes their value to 0 (prepend) and -1 (append), so we will too. - * It *might* be faster to search the gtk_list_store and set row accurately, - * but no one in #gtk+ seems to know anything about it either. - * Inserting in the "wrong" location has no visible ill effects. - F.P. - */ - -1, /* "row" */ - CHAT_USERS_ICON_COLUMN, pixbuf, - CHAT_USERS_ALIAS_COLUMN, alias, - CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, - CHAT_USERS_NAME_COLUMN, name, - CHAT_USERS_FLAGS_COLUMN, flags, - CHAT_USERS_COLOR_COLUMN, &send_color, - CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, - -1); - } - else - { - gtk_list_store_insert_with_values(ls, &iter, - -1, /* "row" */ - CHAT_USERS_ICON_COLUMN, pixbuf, - CHAT_USERS_ALIAS_COLUMN, alias, - CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, - CHAT_USERS_NAME_COLUMN, name, - CHAT_USERS_FLAGS_COLUMN, flags, - CHAT_USERS_COLOR_COLUMN, get_nick_color(gtkconv, name), - CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, - -1); +* The GTK docs are mute about the effects of the "row" value for performance. +* X-Chat hardcodes their value to 0 (prepend) and -1 (append), so we will too. +* It *might* be faster to search the gtk_list_store and set row accurately, +* but no one in #gtk+ seems to know anything about it either. +* Inserting in the "wrong" location has no visible ill effects. - F.P. +*/ + -1, /* "row" */ + CHAT_USERS_ICON_COLUMN, pixbuf, + CHAT_USERS_ALIAS_COLUMN, alias, + CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, + CHAT_USERS_NAME_COLUMN, name, + CHAT_USERS_FLAGS_COLUMN, flags, + CHAT_USERS_COLOR_COLUMN, color, + CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, + -1); #else - gtk_list_store_append(ls, &iter); - gtk_list_store_set(ls, &iter, - CHAT_USERS_ICON_COLUMN, pixbuf, - CHAT_USERS_ALIAS_COLUMN, alias, - CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, - CHAT_USERS_NAME_COLUMN, name, - CHAT_USERS_FLAGS_COLUMN, flags, - CHAT_USERS_COLOR_COLUMN, &send_color, - CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, - -1); - } - else - { - gtk_list_store_append(ls, &iter); - gtk_list_store_set(ls, &iter, - CHAT_USERS_ICON_COLUMN, pixbuf, - CHAT_USERS_ALIAS_COLUMN, alias, - CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, - CHAT_USERS_NAME_COLUMN, name, - CHAT_USERS_FLAGS_COLUMN, flags, - CHAT_USERS_COLOR_COLUMN, get_nick_color(gtkconv, name), - CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, - -1); + gtk_list_store_append(ls, &iter); + gtk_list_store_set(ls, &iter, + CHAT_USERS_ICON_COLUMN, pixbuf, + CHAT_USERS_ALIAS_COLUMN, alias, + CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, + CHAT_USERS_NAME_COLUMN, name, + CHAT_USERS_FLAGS_COLUMN, flags, + CHAT_USERS_COLOR_COLUMN, color, + CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, + -1); #endif - } if (pixbuf) g_object_unref(pixbuf); + if (is_me && color) + gdk_color_free(color); g_free(alias_key); } @@ -4359,6 +4340,7 @@ GtkTreeModel *model; char *normalized_name; GtkTreeIter iter; + GtkTextTag *texttag; int f; g_return_if_fail(buddy != NULL); @@ -4396,6 +4378,11 @@ g_free(normalized_name); blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv); + + texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), FALSE); /* XXX: do we want the normalized name? */ + if (texttag) { + g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); + } } static void @@ -5356,7 +5343,8 @@ return FALSE; } -static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who) { +static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create) +{ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); GtkTextTag *buddytag; gchar *str; @@ -5367,9 +5355,12 @@ gtk_text_buffer_get_tag_table( GTK_IMHTML(gtkconv->imhtml)->text_buffer), str); - if (buddytag == NULL) { + if (buddytag == NULL && create) { buddytag = gtk_text_buffer_create_tag( - GTK_IMHTML(gtkconv->imhtml)->text_buffer, str, NULL); + GTK_IMHTML(gtkconv->imhtml)->text_buffer, str, + "foreground-gdk", get_nick_color(gtkconv, who), + "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, + NULL); g_signal_connect(G_OBJECT(buddytag), "event", G_CALLBACK(buddytag_event), conv); @@ -5475,7 +5466,6 @@ char buf2[BUF_LONG]; gboolean show_date; char *mdate; - char color[10]; char *str; char *with_font_tag; char *sml_attrib = NULL; @@ -5686,32 +5676,28 @@ * escaped entities making the string longer */ int tag_start_offset = alias ? (strlen(alias_escaped) - strlen(alias)) : 0; int tag_end_offset = 0; + const char *tagname = NULL; /* Enforce direction on alias */ if (is_rtl_message) str_embed_direction_chars(&alias_escaped); + str = g_malloc(1024); if (flags & PURPLE_MESSAGE_WHISPER) { - str = g_malloc(1024); - /* If we're whispering, it's not an autoresponse. */ if (purple_message_meify(new_message, -1 )) { g_snprintf(str, 1024, "***%s", alias_escaped); - strcpy(color, "#6C2585"); tag_start_offset += 3; + tagname = "whisper-action-name"; } else { g_snprintf(str, 1024, "*%s*:", alias_escaped); tag_start_offset += 1; tag_end_offset = 2; - strcpy(color, "#00FF00"); + tagname = "whisper-name"; } - } - else { + } else { if (purple_message_meify(new_message, -1)) { - GdkColor *col; - str = g_malloc(1024); - if (flags & PURPLE_MESSAGE_AUTO_RESP) { g_snprintf(str, 1024, "%s ***%s", AUTO_RESPONSE, alias_escaped); tag_start_offset += 4 @@ -5722,23 +5708,10 @@ } if (flags & PURPLE_MESSAGE_NICK) - gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "highlight-name-color", &col, NULL); + tagname = "highlight-name"; else - gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "action-name-color", &col, NULL); - - if(col) { - g_snprintf(color, sizeof(color), "#%02X%02X%02X", - col->red >> 8, col->green >> 8, col->blue >> 8); - gdk_color_free(col); - } else { - if (flags & PURPLE_MESSAGE_NICK) - strcpy(color, DEFAULT_HIGHLIGHT_COLOR); - else - strcpy(color, DEFAULT_ACTION_COLOR); - } - } - else { - str = g_malloc(1024); + tagname = "action-name"; + } else { if (flags & PURPLE_MESSAGE_AUTO_RESP) { g_snprintf(str, 1024, "%s %s", alias_escaped, AUTO_RESPONSE); tag_start_offset += 1 @@ -5747,105 +5720,48 @@ g_snprintf(str, 1024, "%s:", alias_escaped); tag_end_offset = 1; } + if (flags & PURPLE_MESSAGE_NICK) { - GdkColor *col; - gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "highlight-name-color", &col, NULL); - if(col) { - g_snprintf(color, sizeof(color), "#%02X%02X%02X", - col->red >> 8, col->green >> 8, col->blue >> 8); - gdk_color_free(col); - } else { - strcpy(color, DEFAULT_HIGHLIGHT_COLOR); + tagname = "highlight-name"; + } else if (flags & PURPLE_MESSAGE_RECV) { + /* The tagname and color is handled by get_buddy_tag */ + if (type == PURPLE_CONV_TYPE_IM) { + tagname = "receive-name"; } - } - else if (flags & PURPLE_MESSAGE_RECV) { - if (type == PURPLE_CONV_TYPE_CHAT) { - const GdkColor *col = get_nick_color(gtkconv, name); - - g_snprintf(color, sizeof(color), "#%02X%02X%02X", - col->red >> 8, col->green >> 8, col->blue >> 8); - } else { - GdkColor *col; - gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "receive-name-color", &col, NULL); - if(col) { - g_snprintf(color, sizeof(color), "#%02X%02X%02X", - col->red >> 8, col->green >> 8, col->blue >> 8); - gdk_color_free(col); - } else { - strcpy(color, DEFAULT_RECV_COLOR); - } - } - } - else if (flags & PURPLE_MESSAGE_SEND) { - GdkColor *col; - gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "send-name-color", &col, NULL); - if(col) { - g_snprintf(color, sizeof(color), "#%02X%02X%02X", - col->red >> 8, col->green >> 8, col->blue >> 8); - gdk_color_free(col); - } else { - strcpy(color, DEFAULT_SEND_COLOR); - } - } - else { + } else if (flags & PURPLE_MESSAGE_SEND) { + tagname = "send-name"; + } else { purple_debug_error("gtkconv", "message missing flags\n"); - strcpy(color, "#000000"); } } } g_free(alias_escaped); - /* Are we in a chat where we can tell which users are buddies? */ - if (prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) && - purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - - /* Bold buddies to make them stand out from non-buddies. */ - if (flags & PURPLE_MESSAGE_SEND || - flags & PURPLE_MESSAGE_NICK || - purple_find_buddy(account, name) != NULL) { - g_snprintf(buf2, BUF_LONG, - "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" - "<B>%s</B></FONT> ", - color, sml_attrib ? sml_attrib : "", mdate, str); - } else { - g_snprintf(buf2, BUF_LONG, - "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" - "%s</FONT> ", - color, sml_attrib ? sml_attrib : "", mdate, str); - - } - } else { - /* Bold everyone's name to make the name stand out from the message. */ - g_snprintf(buf2, BUF_LONG, - "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" - "<B>%s</B></FONT> ", - color, sml_attrib ? sml_attrib : "", mdate, str); - } - + g_snprintf(buf2, BUF_LONG, + "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT>%s</FONT> ", + sml_attrib ? sml_attrib : "", mdate, str); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && - !(flags & PURPLE_MESSAGE_SEND)) { - + if (tagname || + (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + !(flags & PURPLE_MESSAGE_SEND))) { GtkTextIter start, end; - GtkTextTag *buddytag = get_buddy_tag(conv, name); - - gtk_text_buffer_get_end_iter( - GTK_IMHTML(gtkconv->imhtml)->text_buffer, - &end); - gtk_text_iter_backward_chars(&end, - tag_end_offset + 1); - - gtk_text_buffer_get_end_iter( - GTK_IMHTML(gtkconv->imhtml)->text_buffer, - &start); - gtk_text_iter_backward_chars(&start, - strlen(str) + 1 - tag_start_offset); - - gtk_text_buffer_apply_tag( - GTK_IMHTML(gtkconv->imhtml)->text_buffer, - buddytag, &start, &end); + GtkTextTag *tag; + GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; + + if (tagname) + tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); + else + tag = get_buddy_tag(conv, name, TRUE); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_iter_backward_chars(&end, tag_end_offset + 1); + + gtk_text_buffer_get_end_iter(buffer, &start); + gtk_text_iter_backward_chars(&start, strlen(str) + 1 - tag_start_offset); + + gtk_text_buffer_apply_tag(buffer, tag, &start, &end); } g_free(str); @@ -5864,8 +5780,7 @@ length += pre_len + post_len; g_free(pre); - } - else + } else with_font_tag = g_memdup(new_message, length); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml),
--- a/pidgin/gtkimhtml.c Sun May 18 21:22:38 2008 +0000 +++ b/pidgin/gtkimhtml.c Mon May 19 18:23:25 2008 +0000 @@ -393,6 +393,55 @@ gtk_imhtml_scroll_to_end(imhtml, FALSE); } +#define DEFAULT_SEND_COLOR "#204a87" +#define DEFAULT_RECV_COLOR "#cc0000" +#define DEFAULT_HIGHLIGHT_COLOR "#AF7F00" +#define DEFAULT_ACTION_COLOR "#062585" +#define DEFAULT_WHISPER_ACTION_COLOR "#6C2585" +#define DEFAULT_WHISPER_COLOR "#00FF00" + +static void (*parent_style_set)(GtkWidget *widget, GtkStyle *prev_style); + +static void +gtk_imhtml_style_set(GtkWidget *widget, GtkStyle *prev_style) +{ + int i; + struct { + const char *tag; + const char *color; + const char *def; + } styles[] = { + {"send-name", "send-name-color", DEFAULT_SEND_COLOR}, + {"receive-name", "receive-name-color", DEFAULT_RECV_COLOR}, + {"highlight-name", "highlight-name-color", DEFAULT_HIGHLIGHT_COLOR}, + {"action-name", "action-name-color", DEFAULT_ACTION_COLOR}, + {"whisper-action-name", "whisper-action-name-color", DEFAULT_WHISPER_ACTION_COLOR}, + {"whisper-name", "whisper-name-color", DEFAULT_WHISPER_COLOR}, + {NULL, NULL, NULL} + }; + GtkIMHtml *imhtml = GTK_IMHTML(widget); + GtkTextTagTable *table = gtk_text_buffer_get_tag_table(imhtml->text_buffer); + + for (i = 0; styles[i].tag; i++) { + GdkColor *color = NULL; + GtkTextTag *tag = gtk_text_tag_table_lookup(table, styles[i].tag); + if (!tag) { + purple_debug_warning("gtkimhtml", "Cannot find tag '%s'. This should never happen. Please file a bug.\n", styles[i].tag); + continue; + } + gtk_widget_style_get(widget, styles[i].color, &color, NULL); + if (color) { + g_object_set(tag, "foreground-gdk", color, NULL); + gdk_color_free(color); + } else { + GdkColor defcolor; + gdk_color_parse(styles[i].def, &defcolor); + g_object_set(tag, "foreground-gdk", &defcolor, NULL); + } + } + parent_style_set(widget, prev_style); +} + static gint gtk_imhtml_tip_paint (GtkIMHtml *imhtml) { @@ -1425,6 +1474,8 @@ widget_class->expose_event = gtk_imhtml_expose_event; parent_size_allocate = widget_class->size_allocate; widget_class->size_allocate = gtk_imhtml_size_allocate; + parent_style_set = widget_class->style_set; + widget_class->style_set = gtk_imhtml_style_set; gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-color", _("Hyperlink color"), @@ -1450,6 +1501,14 @@ _("Action Message Name Color"), _("Color to draw the name of an action message."), GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("whisper-action-name-color", + _("Action Message Name Color for Whispered Message"), + _("Color to draw the name of an action message."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("whisper-name-color", + _("Whisper Message Name Color"), + _("Color to draw the name of an action message."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); /* Customizable typing notification ... sort of. Example: * GtkIMHtml::typing-notification-font = "monospace italic light 8.0" @@ -1515,6 +1574,13 @@ gtk_text_buffer_create_tag(imhtml->text_buffer, "comment", "invisible", FALSE, NULL); #endif + gtk_text_buffer_create_tag(imhtml->text_buffer, "send-name", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "receive-name", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "highlight-name", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "action-name", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "whisper-action-name", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "whisper-name", "weight", PANGO_WEIGHT_BOLD, NULL); + /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);