pidgin/gtkconv.c

changeset 24547
e3be19b1b3e5
parent 24543
324d12c36342
child 24569
5dbd0617a27d
equal deleted inserted replaced
24531:76e72697f7d6 24547:e3be19b1b3e5
159 static void update_typing_message(PidginConversation *gtkconv, const char *message); 159 static void update_typing_message(PidginConversation *gtkconv, const char *message);
160 static const char *item_factory_translate_func (const char *path, gpointer func_data); 160 static const char *item_factory_translate_func (const char *path, gpointer func_data);
161 gboolean pidgin_conv_has_focus(PurpleConversation *conv); 161 gboolean pidgin_conv_has_focus(PurpleConversation *conv);
162 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); 162 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background);
163 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); 163 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast);
164 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create); 164 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create);
165 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); 165 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields);
166 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); 166 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win);
167 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); 167 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv);
168 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); 168 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv);
169 static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); 169 static void hide_conv(PidginConversation *gtkconv, gboolean closetimer);
170 170
171 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, 171 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y,
172 int width, int height); 172 int width, int height);
173 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); 173 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y);
174 174
175 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { 175 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name)
176 {
176 static GdkColor col; 177 static GdkColor col;
177 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); 178 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml);
178 float scale; 179 float scale;
179 180
180 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; 181 col = nick_colors[g_str_hash(name) % nbr_nick_colors];
1908 if (most_active != NULL && most_active != gtkconv) 1909 if (most_active != NULL && most_active != gtkconv)
1909 pidgin_conv_window_switch_gtkconv(win, most_active); 1910 pidgin_conv_window_switch_gtkconv(win, most_active);
1910 } 1911 }
1911 1912
1912 static gboolean 1913 static gboolean
1914 gtkconv_cycle_focus(PidginConversation *gtkconv, GtkDirectionType dir)
1915 {
1916 PurpleConversation *conv = gtkconv->active_conv;
1917 gboolean chat = purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT;
1918 GtkWidget *next = NULL;
1919 struct {
1920 GtkWidget *from;
1921 GtkWidget *to;
1922 } transitions[] = {
1923 {gtkconv->entry, gtkconv->imhtml},
1924 {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry},
1925 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry},
1926 {NULL, NULL}
1927 }, *ptr;
1928
1929 for (ptr = transitions; !next && ptr->from; ptr++) {
1930 GtkWidget *from, *to;
1931 if (dir == GTK_DIR_TAB_FORWARD) {
1932 from = ptr->from;
1933 to = ptr->to;
1934 } else {
1935 from = ptr->to;
1936 to = ptr->from;
1937 }
1938 if (gtk_widget_is_focus(from))
1939 next = to;
1940 }
1941
1942 if (next)
1943 gtk_widget_grab_focus(next);
1944 return !!next;
1945 }
1946
1947 static gboolean
1913 conv_keypress_common(PidginConversation *gtkconv, GdkEventKey *event) 1948 conv_keypress_common(PidginConversation *gtkconv, GdkEventKey *event)
1914 { 1949 {
1915 PidginWindow *win; 1950 PidginWindow *win;
1916 PurpleConversation *conv; 1951 PurpleConversation *conv;
1917 int curconv; 1952 int curconv;
1968 #else 2003 #else
1969 (curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children)); 2004 (curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children));
1970 #endif 2005 #endif
1971 return TRUE; 2006 return TRUE;
1972 break; 2007 break;
1973 2008 case GDK_F6:
2009 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
2010 return TRUE;
2011 break;
1974 } /* End of switch */ 2012 } /* End of switch */
1975 } 2013 }
1976 2014
1977 /* If ALT (or whatever) was held down... */ 2015 /* If ALT (or whatever) was held down... */
1978 else if (event->state & GDK_MOD1_MASK) 2016 else if (event->state & GDK_MOD1_MASK)
1994 case GDK_F2: 2032 case GDK_F2:
1995 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) { 2033 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) {
1996 infopane_entry_activate(gtkconv); 2034 infopane_entry_activate(gtkconv);
1997 return TRUE; 2035 return TRUE;
1998 } 2036 }
2037 break;
2038 case GDK_F6:
2039 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
2040 return TRUE;
1999 break; 2041 break;
2000 } 2042 }
2001 } 2043 }
2002 return FALSE; 2044 return FALSE;
2003 } 2045 }
4421 4463
4422 g_free(normalized_name); 4464 g_free(normalized_name);
4423 4465
4424 blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv); 4466 blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv);
4425 4467
4426 texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), FALSE); /* XXX: do we want the normalized name? */ 4468 texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), 0, FALSE); /* XXX: do we want the normalized name? */
4427 if (texttag) { 4469 if (texttag) {
4428 g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); 4470 g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL);
4429 } 4471 }
4430 } 4472 }
4431 4473
5341 } 5383 }
5342 5384
5343 purple_conversation_write(conv, who, message, flags, mtime); 5385 purple_conversation_write(conv, who, message, flags, mtime);
5344 } 5386 }
5345 5387
5388 static const char *
5389 get_text_tag_color(GtkTextTag *tag)
5390 {
5391 GdkColor *color = NULL;
5392 gboolean set = FALSE;
5393 static char colcode[] = "#XXXXXX";
5394 if (tag)
5395 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-gdk", &color, NULL);
5396 if (set && color)
5397 g_snprintf(colcode, sizeof(colcode), "#%02x%02x%02x",
5398 color->red >> 8, color->green >> 8, color->blue >> 8);
5399 else
5400 colcode[0] = '\0';
5401 if (color)
5402 gdk_color_free(color);
5403 return colcode;
5404 }
5405
5346 /* The callback for an event on a link tag. */ 5406 /* The callback for an event on a link tag. */
5347 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, 5407 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml,
5348 GdkEvent *event, GtkTextIter *arg2, gpointer data) { 5408 GdkEvent *event, GtkTextIter *arg2, gpointer data)
5409 {
5349 if (event->type == GDK_BUTTON_PRESS 5410 if (event->type == GDK_BUTTON_PRESS
5350 || event->type == GDK_2BUTTON_PRESS) { 5411 || event->type == GDK_2BUTTON_PRESS) {
5351 GdkEventButton *btn_event = (GdkEventButton*) event; 5412 GdkEventButton *btn_event = (GdkEventButton*) event;
5352 PurpleConversation *conv = data; 5413 PurpleConversation *conv = data;
5353 char *buddyname; 5414 char *buddyname;
5354 5415
5355 /* strlen("BUDDY ") == 6 */ 5416 /* strlen("BUDDY " or "HILIT ") == 6 */
5356 g_return_val_if_fail((tag->name != NULL) 5417 g_return_val_if_fail((tag->name != NULL)
5357 && (strlen(tag->name) > 6), FALSE); 5418 && (strlen(tag->name) > 6), FALSE);
5358 5419
5359 buddyname = (tag->name) + 6; 5420 buddyname = (tag->name) + 6;
5360 5421
5390 } 5451 }
5391 5452
5392 return FALSE; 5453 return FALSE;
5393 } 5454 }
5394 5455
5395 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create) 5456 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag,
5457 gboolean create)
5396 { 5458 {
5397 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 5459 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
5398 GtkTextTag *buddytag; 5460 GtkTextTag *buddytag;
5399 gchar *str; 5461 gchar *str;
5400 5462 gboolean highlight = (flag & PURPLE_MESSAGE_NICK);
5401 str = g_strdup_printf("BUDDY %s", who); 5463 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
5464
5465 str = g_strdup_printf(highlight ? "HILIT %s" : "BUDDY %s", who);
5402 5466
5403 buddytag = gtk_text_tag_table_lookup( 5467 buddytag = gtk_text_tag_table_lookup(
5404 gtk_text_buffer_get_tag_table( 5468 gtk_text_buffer_get_tag_table(buffer), str);
5405 GTK_IMHTML(gtkconv->imhtml)->text_buffer), str);
5406 5469
5407 if (buddytag == NULL && create) { 5470 if (buddytag == NULL && create) {
5408 buddytag = gtk_text_buffer_create_tag( 5471 if (highlight)
5409 GTK_IMHTML(gtkconv->imhtml)->text_buffer, str, 5472 buddytag = gtk_text_buffer_create_tag(buffer, str,
5410 "foreground-gdk", get_nick_color(gtkconv, who), 5473 "foreground", get_text_tag_color(gtk_text_tag_table_lookup(
5411 "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, 5474 gtk_text_buffer_get_tag_table(buffer), "highlight-name")),
5412 NULL); 5475 "weight", PANGO_WEIGHT_BOLD,
5476 NULL);
5477 else
5478 buddytag = gtk_text_buffer_create_tag(
5479 buffer, str,
5480 "foreground-gdk", get_nick_color(gtkconv, who),
5481 "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
5482 NULL);
5413 5483
5414 g_signal_connect(G_OBJECT(buddytag), "event", 5484 g_signal_connect(G_OBJECT(buddytag), "event",
5415 G_CALLBACK(buddytag_event), conv); 5485 G_CALLBACK(buddytag_event), conv);
5416 } 5486 }
5417 5487
5764 g_snprintf(str, 1024, "%s:", alias_escaped); 5834 g_snprintf(str, 1024, "%s:", alias_escaped);
5765 tag_end_offset = 1; 5835 tag_end_offset = 1;
5766 } 5836 }
5767 5837
5768 if (flags & PURPLE_MESSAGE_NICK) { 5838 if (flags & PURPLE_MESSAGE_NICK) {
5769 tagname = "highlight-name"; 5839 if (type == PURPLE_CONV_TYPE_IM) {
5840 tagname = "highlight-name";
5841 }
5770 } else if (flags & PURPLE_MESSAGE_RECV) { 5842 } else if (flags & PURPLE_MESSAGE_RECV) {
5771 /* The tagname for chats is handled by get_buddy_tag */ 5843 /* The tagname for chats is handled by get_buddy_tag */
5772 if (type == PURPLE_CONV_TYPE_IM) { 5844 if (type == PURPLE_CONV_TYPE_IM) {
5773 tagname = "receive-name"; 5845 tagname = "receive-name";
5774 } 5846 }
5783 g_free(alias_escaped); 5855 g_free(alias_escaped);
5784 5856
5785 if (tagname) 5857 if (tagname)
5786 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); 5858 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname);
5787 else 5859 else
5788 tag = get_buddy_tag(conv, name, TRUE); 5860 tag = get_buddy_tag(conv, name, flags, TRUE);
5789 5861
5790 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { 5862 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) {
5791 /* The color for the timestamp has to be set in the font-tags, unfortunately. 5863 /* The color for the timestamp has to be set in the font-tags, unfortunately.
5792 * Applying the nick-tag to timestamps would work, but that can make it 5864 * Applying the nick-tag to timestamps would work, but that can make it
5793 * bold. I thought applying the "comment" tag again, which has "weight" set 5865 * bold. I thought applying the "comment" tag again, which has "weight" set
5794 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So 5866 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So
5795 * this will have to do. I don't terribly like it. -- sadrul */ 5867 * this will have to do. I don't terribly like it. -- sadrul */
5796 GdkColor *color = NULL; 5868 const char *color = get_text_tag_color(tag);
5797 gboolean set = FALSE; 5869 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>",
5798 char colcode[] = "COLOR=\"#XXXXXX\""; 5870 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate);
5799 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-gdk", &color, NULL);
5800 if (set && color)
5801 g_snprintf(colcode, sizeof(colcode), "COLOR=\"#%02x%02x%02x\"",
5802 color->red >> 8, color->green >> 8, color->blue >> 8);
5803 else
5804 colcode[0] = '\0';
5805 g_snprintf(buf2, BUF_LONG, "<FONT %s SIZE=\"2\"><!--%s --></FONT>", colcode, mdate);
5806 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); 5871 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
5807 if (color)
5808 gdk_color_free(color);
5809 } 5872 }
5810 5873
5811 gtk_text_buffer_get_end_iter(buffer, &end); 5874 gtk_text_buffer_get_end_iter(buffer, &end);
5812 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); 5875 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE);
5813 5876

mercurial