Mercurial > pidgin.yaz
comparison pidgin/gtkconv.c @ 26028:bcad7dc4b453
propagate from branch 'im.pidgin.pidgin' (head 633ffe234af48ead3631ae62e23840b4438fcf5f)
to branch 'im.pidgin.maiku.vv' (head 5585b8e919d9adb0eb491c714768027e81f1918c)
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Thu, 06 Nov 2008 03:20:05 +0000 |
parents | 8bfa1f01f035 8282911d5e17 |
children | adf153852bcf |
comparison
equal
deleted
inserted
replaced
26027:94224a5563db | 26028:bcad7dc4b453 |
---|---|
22 * You should have received a copy of the GNU General Public License | 22 * You should have received a copy of the GNU General Public License |
23 * along with this program; if not, write to the Free Software | 23 * along with this program; if not, write to the Free Software |
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA | 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
25 * | 25 * |
26 */ | 26 */ |
27 #define _PIDGIN_GTKCONV_C_ | |
28 | |
27 #include "internal.h" | 29 #include "internal.h" |
28 #include "pidgin.h" | 30 #include "pidgin.h" |
29 | 31 |
30 #ifndef _WIN32 | 32 #ifndef _WIN32 |
31 # include <X11/Xlib.h> | 33 # include <X11/Xlib.h> |
161 static void update_typing_message(PidginConversation *gtkconv, const char *message); | 163 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
162 static const char *item_factory_translate_func (const char *path, gpointer func_data); | 164 static const char *item_factory_translate_func (const char *path, gpointer func_data); |
163 gboolean pidgin_conv_has_focus(PurpleConversation *conv); | 165 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
164 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); | 166 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); |
165 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); | 167 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); |
166 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create); | 168 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create); |
167 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); | 169 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
168 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); | 170 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
169 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); | 171 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
170 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); | 172 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); |
171 static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); | 173 static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); |
172 | 174 |
173 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, | 175 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, |
174 int width, int height); | 176 int width, int height); |
175 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); | 177 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); |
176 | 178 |
177 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { | 179 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) |
180 { | |
178 static GdkColor col; | 181 static GdkColor col; |
179 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); | 182 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); |
180 float scale; | 183 float scale; |
181 | 184 |
182 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; | 185 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; |
1922 if (most_active != NULL && most_active != gtkconv) | 1925 if (most_active != NULL && most_active != gtkconv) |
1923 pidgin_conv_window_switch_gtkconv(win, most_active); | 1926 pidgin_conv_window_switch_gtkconv(win, most_active); |
1924 } | 1927 } |
1925 | 1928 |
1926 static gboolean | 1929 static gboolean |
1930 gtkconv_cycle_focus(PidginConversation *gtkconv, GtkDirectionType dir) | |
1931 { | |
1932 PurpleConversation *conv = gtkconv->active_conv; | |
1933 gboolean chat = purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT; | |
1934 GtkWidget *next = NULL; | |
1935 struct { | |
1936 GtkWidget *from; | |
1937 GtkWidget *to; | |
1938 } transitions[] = { | |
1939 {gtkconv->entry, gtkconv->imhtml}, | |
1940 {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, | |
1941 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, | |
1942 {NULL, NULL} | |
1943 }, *ptr; | |
1944 | |
1945 for (ptr = transitions; !next && ptr->from; ptr++) { | |
1946 GtkWidget *from, *to; | |
1947 if (dir == GTK_DIR_TAB_FORWARD) { | |
1948 from = ptr->from; | |
1949 to = ptr->to; | |
1950 } else { | |
1951 from = ptr->to; | |
1952 to = ptr->from; | |
1953 } | |
1954 if (gtk_widget_is_focus(from)) | |
1955 next = to; | |
1956 } | |
1957 | |
1958 if (next) | |
1959 gtk_widget_grab_focus(next); | |
1960 return !!next; | |
1961 } | |
1962 | |
1963 static gboolean | |
1927 conv_keypress_common(PidginConversation *gtkconv, GdkEventKey *event) | 1964 conv_keypress_common(PidginConversation *gtkconv, GdkEventKey *event) |
1928 { | 1965 { |
1929 PidginWindow *win; | 1966 PidginWindow *win; |
1930 PurpleConversation *conv; | 1967 PurpleConversation *conv; |
1931 int curconv; | 1968 int curconv; |
1982 #else | 2019 #else |
1983 (curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children)); | 2020 (curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children)); |
1984 #endif | 2021 #endif |
1985 return TRUE; | 2022 return TRUE; |
1986 break; | 2023 break; |
1987 | 2024 case GDK_F6: |
2025 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) | |
2026 return TRUE; | |
2027 break; | |
1988 } /* End of switch */ | 2028 } /* End of switch */ |
1989 } | 2029 } |
1990 | 2030 |
1991 /* If ALT (or whatever) was held down... */ | 2031 /* If ALT (or whatever) was held down... */ |
1992 else if (event->state & GDK_MOD1_MASK) | 2032 else if (event->state & GDK_MOD1_MASK) |
2008 case GDK_F2: | 2048 case GDK_F2: |
2009 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) { | 2049 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) { |
2010 infopane_entry_activate(gtkconv); | 2050 infopane_entry_activate(gtkconv); |
2011 return TRUE; | 2051 return TRUE; |
2012 } | 2052 } |
2053 break; | |
2054 case GDK_F6: | |
2055 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) | |
2056 return TRUE; | |
2013 break; | 2057 break; |
2014 } | 2058 } |
2015 } | 2059 } |
2016 return FALSE; | 2060 return FALSE; |
2017 } | 2061 } |
4458 | 4502 |
4459 g_free(normalized_name); | 4503 g_free(normalized_name); |
4460 | 4504 |
4461 blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv); | 4505 blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv); |
4462 | 4506 |
4463 texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), FALSE); /* XXX: do we want the normalized name? */ | 4507 texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), 0, FALSE); /* XXX: do we want the normalized name? */ |
4464 if (texttag) { | 4508 if (texttag) { |
4465 g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); | 4509 g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); |
4466 } | 4510 } |
4467 } | 4511 } |
4468 | 4512 |
5376 } | 5420 } |
5377 | 5421 |
5378 purple_conversation_write(conv, who, message, flags, mtime); | 5422 purple_conversation_write(conv, who, message, flags, mtime); |
5379 } | 5423 } |
5380 | 5424 |
5425 static const char * | |
5426 get_text_tag_color(GtkTextTag *tag) | |
5427 { | |
5428 GdkColor *color = NULL; | |
5429 gboolean set = FALSE; | |
5430 static char colcode[] = "#XXXXXX"; | |
5431 if (tag) | |
5432 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-gdk", &color, NULL); | |
5433 if (set && color) | |
5434 g_snprintf(colcode, sizeof(colcode), "#%02x%02x%02x", | |
5435 color->red >> 8, color->green >> 8, color->blue >> 8); | |
5436 else | |
5437 colcode[0] = '\0'; | |
5438 if (color) | |
5439 gdk_color_free(color); | |
5440 return colcode; | |
5441 } | |
5442 | |
5381 /* The callback for an event on a link tag. */ | 5443 /* The callback for an event on a link tag. */ |
5382 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, | 5444 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, |
5383 GdkEvent *event, GtkTextIter *arg2, gpointer data) { | 5445 GdkEvent *event, GtkTextIter *arg2, gpointer data) |
5446 { | |
5384 if (event->type == GDK_BUTTON_PRESS | 5447 if (event->type == GDK_BUTTON_PRESS |
5385 || event->type == GDK_2BUTTON_PRESS) { | 5448 || event->type == GDK_2BUTTON_PRESS) { |
5386 GdkEventButton *btn_event = (GdkEventButton*) event; | 5449 GdkEventButton *btn_event = (GdkEventButton*) event; |
5387 PurpleConversation *conv = data; | 5450 PurpleConversation *conv = data; |
5388 char *buddyname; | 5451 char *buddyname; |
5389 | 5452 |
5390 /* strlen("BUDDY ") == 6 */ | 5453 /* strlen("BUDDY " or "HILIT ") == 6 */ |
5391 g_return_val_if_fail((tag->name != NULL) | 5454 g_return_val_if_fail((tag->name != NULL) |
5392 && (strlen(tag->name) > 6), FALSE); | 5455 && (strlen(tag->name) > 6), FALSE); |
5393 | 5456 |
5394 buddyname = (tag->name) + 6; | 5457 buddyname = (tag->name) + 6; |
5395 | 5458 |
5425 } | 5488 } |
5426 | 5489 |
5427 return FALSE; | 5490 return FALSE; |
5428 } | 5491 } |
5429 | 5492 |
5430 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, gboolean create) | 5493 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, |
5494 gboolean create) | |
5431 { | 5495 { |
5432 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | 5496 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); |
5433 GtkTextTag *buddytag; | 5497 GtkTextTag *buddytag; |
5434 gchar *str; | 5498 gchar *str; |
5435 | 5499 gboolean highlight = (flag & PURPLE_MESSAGE_NICK); |
5436 str = g_strdup_printf("BUDDY %s", who); | 5500 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; |
5501 | |
5502 str = g_strdup_printf(highlight ? "HILIT %s" : "BUDDY %s", who); | |
5437 | 5503 |
5438 buddytag = gtk_text_tag_table_lookup( | 5504 buddytag = gtk_text_tag_table_lookup( |
5439 gtk_text_buffer_get_tag_table( | 5505 gtk_text_buffer_get_tag_table(buffer), str); |
5440 GTK_IMHTML(gtkconv->imhtml)->text_buffer), str); | |
5441 | 5506 |
5442 if (buddytag == NULL && create) { | 5507 if (buddytag == NULL && create) { |
5443 buddytag = gtk_text_buffer_create_tag( | 5508 if (highlight) |
5444 GTK_IMHTML(gtkconv->imhtml)->text_buffer, str, | 5509 buddytag = gtk_text_buffer_create_tag(buffer, str, |
5445 "foreground-gdk", get_nick_color(gtkconv, who), | 5510 "foreground", get_text_tag_color(gtk_text_tag_table_lookup( |
5446 "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, | 5511 gtk_text_buffer_get_tag_table(buffer), "highlight-name")), |
5447 NULL); | 5512 "weight", PANGO_WEIGHT_BOLD, |
5513 NULL); | |
5514 else | |
5515 buddytag = gtk_text_buffer_create_tag( | |
5516 buffer, str, | |
5517 "foreground-gdk", get_nick_color(gtkconv, who), | |
5518 "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, | |
5519 NULL); | |
5448 | 5520 |
5449 g_signal_connect(G_OBJECT(buddytag), "event", | 5521 g_signal_connect(G_OBJECT(buddytag), "event", |
5450 G_CALLBACK(buddytag_event), conv); | 5522 G_CALLBACK(buddytag_event), conv); |
5451 } | 5523 } |
5452 | 5524 |
5799 g_snprintf(str, 1024, "%s:", alias_escaped); | 5871 g_snprintf(str, 1024, "%s:", alias_escaped); |
5800 tag_end_offset = 1; | 5872 tag_end_offset = 1; |
5801 } | 5873 } |
5802 | 5874 |
5803 if (flags & PURPLE_MESSAGE_NICK) { | 5875 if (flags & PURPLE_MESSAGE_NICK) { |
5804 tagname = "highlight-name"; | 5876 if (type == PURPLE_CONV_TYPE_IM) { |
5877 tagname = "highlight-name"; | |
5878 } | |
5805 } else if (flags & PURPLE_MESSAGE_RECV) { | 5879 } else if (flags & PURPLE_MESSAGE_RECV) { |
5806 /* The tagname for chats is handled by get_buddy_tag */ | 5880 /* The tagname for chats is handled by get_buddy_tag */ |
5807 if (type == PURPLE_CONV_TYPE_IM) { | 5881 if (type == PURPLE_CONV_TYPE_IM) { |
5808 tagname = "receive-name"; | 5882 tagname = "receive-name"; |
5809 } | 5883 } |
5818 g_free(alias_escaped); | 5892 g_free(alias_escaped); |
5819 | 5893 |
5820 if (tagname) | 5894 if (tagname) |
5821 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); | 5895 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); |
5822 else | 5896 else |
5823 tag = get_buddy_tag(conv, name, TRUE); | 5897 tag = get_buddy_tag(conv, name, flags, TRUE); |
5824 | 5898 |
5825 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { | 5899 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { |
5826 /* The color for the timestamp has to be set in the font-tags, unfortunately. | 5900 /* The color for the timestamp has to be set in the font-tags, unfortunately. |
5827 * Applying the nick-tag to timestamps would work, but that can make it | 5901 * Applying the nick-tag to timestamps would work, but that can make it |
5828 * bold. I thought applying the "comment" tag again, which has "weight" set | 5902 * bold. I thought applying the "comment" tag again, which has "weight" set |
5829 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So | 5903 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So |
5830 * this will have to do. I don't terribly like it. -- sadrul */ | 5904 * this will have to do. I don't terribly like it. -- sadrul */ |
5831 GdkColor *color = NULL; | 5905 const char *color = get_text_tag_color(tag); |
5832 gboolean set = FALSE; | 5906 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>", |
5833 char colcode[] = "COLOR=\"#XXXXXX\""; | 5907 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); |
5834 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-gdk", &color, NULL); | |
5835 if (set && color) | |
5836 g_snprintf(colcode, sizeof(colcode), "COLOR=\"#%02x%02x%02x\"", | |
5837 color->red >> 8, color->green >> 8, color->blue >> 8); | |
5838 else | |
5839 colcode[0] = '\0'; | |
5840 g_snprintf(buf2, BUF_LONG, "<FONT %s SIZE=\"2\"><!--%s --></FONT>", colcode, mdate); | |
5841 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); | 5908 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); |
5842 if (color) | |
5843 gdk_color_free(color); | |
5844 } | 5909 } |
5845 | 5910 |
5846 gtk_text_buffer_get_end_iter(buffer, &end); | 5911 gtk_text_buffer_get_end_iter(buffer, &end); |
5847 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); | 5912 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); |
5848 | 5913 |