Mercurial > pidgin.yaz
comparison src/gtkconv.c @ 11581:9b3833da6840
[gaim-migrate @ 13851]
goodbye GaimConvWindow.
Still some problems with this patch:
- Scarey warnings console with gaim -d when closing tab
- I tried to seperate gtkconv and gtkconvwin, but failed,
as a result it has its own header, but the code is in the same
file, which is rather weird. Also some code got moved around
for no good reason. Feel free to move it back or reorganize it.
- I broke the gesters plugin, and just disabled it. Hopefully someone
with more time will fix it, it shouldn't take long, but I didn't
feel like bothering.
- This list is incomplete.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Sun, 02 Oct 2005 00:32:49 +0000 |
parents | 7fbf5e4e8f5f |
children | d35e4f1e9f43 |
comparison
equal
deleted
inserted
replaced
11580:24169af08585 | 11581:9b3833da6840 |
---|---|
50 #include "util.h" | 50 #include "util.h" |
51 | 51 |
52 #include "gtkdnd-hints.h" | 52 #include "gtkdnd-hints.h" |
53 #include "gtkblist.h" | 53 #include "gtkblist.h" |
54 #include "gtkconv.h" | 54 #include "gtkconv.h" |
55 #include "gtkconvwin.c" | |
55 #include "gtkdialogs.h" | 56 #include "gtkdialogs.h" |
56 #include "gtkimhtml.h" | 57 #include "gtkimhtml.h" |
57 #include "gtkimhtmltoolbar.h" | 58 #include "gtkimhtmltoolbar.h" |
58 #include "gtklog.h" | 59 #include "gtklog.h" |
59 #include "gtkmenutray.h" | 60 #include "gtkmenutray.h" |
98 {0, 9728, 50944, 9728} /* Accent Green Dark */ | 99 {0, 9728, 50944, 9728} /* Accent Green Dark */ |
99 }; | 100 }; |
100 | 101 |
101 #define NUM_NICK_COLORS (sizeof(nick_colors) / sizeof(*nick_colors)) | 102 #define NUM_NICK_COLORS (sizeof(nick_colors) / sizeof(*nick_colors)) |
102 | 103 |
103 typedef struct | 104 typedef struct { |
104 { | |
105 GtkWidget *window; | 105 GtkWidget *window; |
106 | 106 |
107 GtkWidget *entry; | 107 GtkWidget *entry; |
108 GtkWidget *message; | 108 GtkWidget *message; |
109 | 109 |
111 | 111 |
112 } InviteBuddyInfo; | 112 } InviteBuddyInfo; |
113 | 113 |
114 static GtkWidget *invite_dialog = NULL; | 114 static GtkWidget *invite_dialog = NULL; |
115 static GtkWidget *warn_close_dialog = NULL; | 115 static GtkWidget *warn_close_dialog = NULL; |
116 | |
117 static gboolean update_send_as_selection(GaimGtkWindow *win); | |
118 static void generate_send_as_items(GaimGtkWindow *win, GaimConversation *deleted_conv); | |
119 | |
120 | |
116 | 121 |
117 /* Prototypes. <-- because Paco-Paco hates this comment. */ | 122 /* Prototypes. <-- because Paco-Paco hates this comment. */ |
118 static void got_typing_keypress(GaimGtkConversation *gtkconv, gboolean first); | 123 static void got_typing_keypress(GaimGtkConversation *gtkconv, gboolean first); |
119 static GList *generate_invite_user_names(GaimConnection *gc); | 124 static GList *generate_invite_user_names(GaimConnection *gc); |
120 static void add_chat_buddy_common(GaimConversation *conv, const char *name, | 125 static void add_chat_buddy_common(GaimConversation *conv, const char *name, |
121 const char *alias, const char *old_name); | 126 const char *alias, const char *old_name); |
122 static gboolean tab_complete(GaimConversation *conv); | 127 static gboolean tab_complete(GaimConversation *conv); |
123 static void update_typing_icon(GaimGtkConversation *gtkconv); | 128 static void update_typing_icon(GaimGtkConversation *gtkconv); |
124 static gboolean update_send_as_selection(GaimConvWindow *win); | |
125 static char *item_factory_translate_func (const char *path, gpointer func_data); | 129 static char *item_factory_translate_func (const char *path, gpointer func_data); |
126 | 130 |
127 static GdkColor *get_nick_color(GaimGtkConversation *gtkconv, const char *name) { | 131 static GdkColor *get_nick_color(GaimGtkConversation *gtkconv, const char *name) { |
128 static GdkColor col; | 132 static GdkColor col; |
129 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); | 133 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); |
141 } | 145 } |
142 | 146 |
143 return &col; | 147 return &col; |
144 } | 148 } |
145 | 149 |
146 static void | |
147 do_close(GtkWidget *w, int resp, GaimConvWindow *win) | |
148 { | |
149 gtk_widget_destroy(warn_close_dialog); | |
150 warn_close_dialog = NULL; | |
151 | |
152 if (resp == GTK_RESPONSE_OK) | |
153 gaim_conv_window_destroy(win); | |
154 } | |
155 | |
156 static void build_warn_close_dialog(GaimConvWindow *win) | |
157 { | |
158 GaimGtkWindow *gtkwin; | |
159 GtkWidget *label; | |
160 GtkWidget *vbox, *hbox; | |
161 GtkWidget *img; | |
162 | |
163 g_return_if_fail(warn_close_dialog == NULL); | |
164 | |
165 gtkwin = GAIM_GTK_WINDOW(win); | |
166 | |
167 warn_close_dialog = gtk_dialog_new_with_buttons( | |
168 _("Confirm close"), | |
169 GTK_WINDOW(gtkwin->window), GTK_DIALOG_MODAL, | |
170 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
171 GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); | |
172 | |
173 gtk_dialog_set_default_response(GTK_DIALOG(warn_close_dialog), | |
174 GTK_RESPONSE_OK); | |
175 | |
176 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), | |
177 6); | |
178 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); | |
179 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), | |
180 FALSE); | |
181 | |
182 /* Setup the outside spacing. */ | |
183 vbox = GTK_DIALOG(warn_close_dialog)->vbox; | |
184 | |
185 gtk_box_set_spacing(GTK_BOX(vbox), 12); | |
186 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); | |
187 | |
188 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_WARNING, | |
189 GTK_ICON_SIZE_DIALOG); | |
190 /* Setup the inner hbox and put the dialog's icon in it. */ | |
191 hbox = gtk_hbox_new(FALSE, 12); | |
192 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
193 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
194 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
195 | |
196 /* Setup the right vbox. */ | |
197 vbox = gtk_vbox_new(FALSE, 12); | |
198 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
199 | |
200 label = gtk_label_new(_("You have unread messages. Are you sure you want to close the window?")); | |
201 gtk_widget_set_size_request(label, 350, -1); | |
202 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
203 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
204 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
205 | |
206 /* Connect the signals. */ | |
207 g_signal_connect(G_OBJECT(warn_close_dialog), "response", | |
208 G_CALLBACK(do_close), win); | |
209 | |
210 } | |
211 | |
212 /************************************************************************** | 150 /************************************************************************** |
213 * Callbacks | 151 * Callbacks |
214 **************************************************************************/ | 152 **************************************************************************/ |
215 static gboolean | |
216 close_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) | |
217 { | |
218 GaimConvWindow *win = (GaimConvWindow *)d; | |
219 GList *l; | |
220 | |
221 /* If there are unread messages then show a warning dialog */ | |
222 for (l = gaim_conv_window_get_conversations(win); | |
223 l != NULL; l = l->next) | |
224 { | |
225 GaimConversation *conv = l->data; | |
226 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM && | |
227 gaim_conversation_get_unseen(conv) == GAIM_UNSEEN_TEXT) | |
228 { | |
229 build_warn_close_dialog(win); | |
230 gtk_widget_show_all(warn_close_dialog); | |
231 | |
232 return TRUE; | |
233 } | |
234 } | |
235 | |
236 gaim_conv_window_destroy(win); | |
237 | |
238 return TRUE; | |
239 } | |
240 | |
241 /* | |
242 * When a conversation window is focused, we know the user | |
243 * has looked at it so we know there are no longer unseen | |
244 * messages. | |
245 */ | |
246 static gint | |
247 focus_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) | |
248 { | |
249 GaimConvWindow *win = (GaimConvWindow *)d; | |
250 GaimConversation *conv = gaim_conv_window_get_active_conversation(win); | |
251 | |
252 gaim_conversation_set_unseen(conv, GAIM_UNSEEN_NONE); | |
253 | |
254 return FALSE; | |
255 } | |
256 | 153 |
257 static gint | 154 static gint |
258 close_conv_cb(GtkWidget *w, GaimGtkConversation *gtkconv) | 155 close_conv_cb(GtkWidget *w, GaimGtkConversation *gtkconv) |
259 { | 156 { |
260 GList *list = g_list_copy(gtkconv->convs), *l; | 157 GList *list = g_list_copy(gtkconv->convs), *l; |
304 if (w == gtkconv->entry) | 201 if (w == gtkconv->entry) |
305 gaim_prefs_set_int("/gaim/gtk/conversations/chat/entry_height", allocation->height); | 202 gaim_prefs_set_int("/gaim/gtk/conversations/chat/entry_height", allocation->height); |
306 } | 203 } |
307 | 204 |
308 return FALSE; | 205 return FALSE; |
309 } | |
310 | |
311 /* Courtesy of Galeon! */ | |
312 static void | |
313 tab_close_button_state_changed_cb(GtkWidget *widget, GtkStateType prev_state) | |
314 { | |
315 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE) | |
316 gtk_widget_set_state(widget, GTK_STATE_NORMAL); | |
317 } | 206 } |
318 | 207 |
319 static void | 208 static void |
320 default_formatize(GaimGtkConversation *c) | 209 default_formatize(GaimGtkConversation *c) |
321 { | 210 { |
857 GaimConversation *conv = gtkconv->active_conv; | 746 GaimConversation *conv = gtkconv->active_conv; |
858 InviteBuddyInfo *info = NULL; | 747 InviteBuddyInfo *info = NULL; |
859 | 748 |
860 if (invite_dialog == NULL) { | 749 if (invite_dialog == NULL) { |
861 GaimConnection *gc; | 750 GaimConnection *gc; |
862 GaimConvWindow *win; | |
863 GaimGtkWindow *gtkwin; | 751 GaimGtkWindow *gtkwin; |
864 GtkWidget *label; | 752 GtkWidget *label; |
865 GtkWidget *vbox, *hbox; | 753 GtkWidget *vbox, *hbox; |
866 GtkWidget *table; | 754 GtkWidget *table; |
867 GtkWidget *img; | 755 GtkWidget *img; |
868 | 756 |
869 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | 757 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
870 GTK_ICON_SIZE_DIALOG); | 758 GTK_ICON_SIZE_DIALOG); |
871 | 759 |
872 info = g_new0(InviteBuddyInfo, 1); | 760 info = g_new0(InviteBuddyInfo, 1); |
873 info->conv = conv; | 761 info->conv = conv; |
874 | 762 |
875 gc = gaim_conversation_get_gc(conv); | 763 gc = gaim_conversation_get_gc(conv); |
876 win = gaim_conversation_get_window(conv); | 764 gtkwin = gaim_gtkconv_get_window(gtkconv); |
877 gtkwin = GAIM_GTK_WINDOW(win); | |
878 | 765 |
879 /* Create the new dialog. */ | 766 /* Create the new dialog. */ |
880 invite_dialog = gtk_dialog_new_with_buttons( | 767 invite_dialog = gtk_dialog_new_with_buttons( |
881 _("Invite Buddy Into Chat Room"), | 768 _("Invite Buddy Into Chat Room"), |
882 GTK_WINDOW(gtkwin->window), 0, | 769 GTK_WINDOW(gtkwin->window), 0, |
883 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 770 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
884 GAIM_STOCK_INVITE, GTK_RESPONSE_OK, NULL); | 771 GAIM_STOCK_INVITE, GTK_RESPONSE_OK, NULL); |
885 | 772 |
886 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog), | 773 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog), |
887 GTK_RESPONSE_OK); | 774 GTK_RESPONSE_OK); |
888 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), GAIM_HIG_BOX_SPACE); | 775 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), GAIM_HIG_BOX_SPACE); |
889 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); | 776 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); |
890 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); | 777 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); |
891 | 778 |
892 info->window = GTK_WIDGET(invite_dialog); | 779 info->window = GTK_WIDGET(invite_dialog); |
1028 * plaintext v. HTML file. | 915 * plaintext v. HTML file. |
1029 */ | 916 */ |
1030 static void | 917 static void |
1031 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) | 918 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) |
1032 { | 919 { |
1033 GaimConvWindow *win = (GaimConvWindow *)data; | 920 GaimGtkWindow *win = data; |
1034 GaimConversation *conv = gaim_conv_window_get_active_conversation(win); | 921 GaimConversation *conv = gaim_gtk_conv_window_get_active_conversation(win); |
1035 gchar *buf; | 922 gchar *buf; |
1036 | 923 |
1037 buf = g_strdup_printf("%s.html", gaim_normalize(conv->account, conv->name)); | 924 buf = g_strdup_printf("%s.html", gaim_normalize(conv->account, conv->name)); |
1038 | 925 |
1039 gaim_request_file(conv, _("Save Conversation"), gaim_escape_filename(buf), | 926 gaim_request_file(conv, _("Save Conversation"), gaim_escape_filename(buf), |
1043 } | 930 } |
1044 | 931 |
1045 static void | 932 static void |
1046 menu_view_log_cb(gpointer data, guint action, GtkWidget *widget) | 933 menu_view_log_cb(gpointer data, guint action, GtkWidget *widget) |
1047 { | 934 { |
1048 GaimConvWindow *win = (GaimConvWindow *)data; | 935 GaimGtkWindow *win = data; |
1049 GaimConversation *conv; | 936 GaimConversation *conv; |
1050 GaimLogType type; | 937 GaimLogType type; |
1051 const char *name; | 938 const char *name; |
1052 GaimAccount *account; | 939 GaimAccount *account; |
1053 GSList *buddies, *cur; | 940 GSList *buddies, *cur; |
1054 | 941 |
1055 conv = gaim_conv_window_get_active_conversation(win); | 942 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1056 | 943 |
1057 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | 944 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) |
1058 type = GAIM_LOG_IM; | 945 type = GAIM_LOG_IM; |
1059 else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) | 946 else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) |
1060 type = GAIM_LOG_CHAT; | 947 type = GAIM_LOG_CHAT; |
1081 } | 968 } |
1082 | 969 |
1083 static void | 970 static void |
1084 menu_clear_cb(gpointer data, guint action, GtkWidget *widget) | 971 menu_clear_cb(gpointer data, guint action, GtkWidget *widget) |
1085 { | 972 { |
1086 GaimConvWindow *win = (GaimConvWindow *)data; | 973 GaimGtkWindow *win = data; |
1087 GaimConversation *conv; | 974 GaimConversation *conv; |
1088 GaimGtkConversation *gtkconv; | 975 GaimGtkConversation *gtkconv; |
1089 | 976 |
1090 conv = gaim_conv_window_get_active_conversation(win); | 977 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1091 gtkconv = GAIM_GTK_CONVERSATION(conv); | 978 gtkconv = GAIM_GTK_CONVERSATION(conv); |
1092 | 979 |
1093 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); | 980 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); |
1094 } | 981 } |
1095 | 982 |
1117 } | 1004 } |
1118 | 1005 |
1119 static void | 1006 static void |
1120 menu_find_cb(gpointer data, guint action, GtkWidget *widget) | 1007 menu_find_cb(gpointer data, guint action, GtkWidget *widget) |
1121 { | 1008 { |
1122 GaimConvWindow *win = (GaimConvWindow *)data; | 1009 GaimGtkWindow *gtkwin = data; |
1123 GaimConversation *conv = gaim_conv_window_get_active_conversation(win); | 1010 GaimConversation *conv = gaim_gtk_conv_window_get_active_conversation(gtkwin); |
1124 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win); | |
1125 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); | 1011 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); |
1126 GtkWidget *hbox; | 1012 GtkWidget *hbox; |
1127 GtkWidget *img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | 1013 GtkWidget *img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
1128 GTK_ICON_SIZE_DIALOG); | 1014 GTK_ICON_SIZE_DIALOG); |
1129 GtkWidget *label; | 1015 GtkWidget *label; |
1179 } | 1065 } |
1180 | 1066 |
1181 static void | 1067 static void |
1182 menu_send_file_cb(gpointer data, guint action, GtkWidget *widget) | 1068 menu_send_file_cb(gpointer data, guint action, GtkWidget *widget) |
1183 { | 1069 { |
1184 GaimConvWindow *win = (GaimConvWindow *)data; | 1070 GaimGtkWindow *win = data; |
1185 GaimConversation *conv = gaim_conv_window_get_active_conversation(win); | 1071 GaimConversation *conv = gaim_gtk_conv_window_get_active_conversation(win); |
1186 | 1072 |
1187 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | 1073 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { |
1188 serv_send_file(gaim_conversation_get_gc(conv), gaim_conversation_get_name(conv), NULL); | 1074 serv_send_file(gaim_conversation_get_gc(conv), gaim_conversation_get_name(conv), NULL); |
1189 } | 1075 } |
1190 | 1076 |
1191 } | 1077 } |
1192 | 1078 |
1193 static void | 1079 static void |
1194 menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget) | 1080 menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget) |
1195 { | 1081 { |
1196 GaimConvWindow *win = (GaimConvWindow *)data; | 1082 GaimGtkWindow *win = data; |
1197 GaimConversation *conv; | 1083 GaimConversation *conv; |
1198 | 1084 |
1199 conv = gaim_conv_window_get_active_conversation(win); | 1085 conv = gaim_gtk_conv_window_get_active_gtkconv(win)->active_conv; |
1200 | 1086 |
1201 gaim_gtkpounce_dialog_show(gaim_conversation_get_account(conv), | 1087 gaim_gtkpounce_dialog_show(gaim_conversation_get_account(conv), |
1202 gaim_conversation_get_name(conv), NULL); | 1088 gaim_conversation_get_name(conv), NULL); |
1203 } | 1089 } |
1204 | 1090 |
1205 static void | 1091 static void |
1206 menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) | 1092 menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) |
1207 { | 1093 { |
1208 GaimConvWindow *win = (GaimConvWindow *)data; | 1094 GaimGtkWindow *win = data; |
1095 GaimGtkConversation *gtkconv; | |
1096 GtkIMHtmlToolbar *toolbar; | |
1097 | |
1098 gtkconv = gaim_gtk_conv_window_get_active_gtkconv(win); | |
1099 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); | |
1100 | |
1101 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link), | |
1102 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link))); | |
1103 } | |
1104 | |
1105 static void | |
1106 menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) | |
1107 { | |
1108 GaimGtkWindow *win = data; | |
1209 GaimConversation *conv; | 1109 GaimConversation *conv; |
1210 GaimGtkConversation *gtkconv; | 1110 GaimGtkConversation *gtkconv; |
1211 GtkIMHtmlToolbar *toolbar; | 1111 GtkIMHtmlToolbar *toolbar; |
1212 | 1112 |
1213 conv = gaim_conv_window_get_active_conversation(win); | 1113 gtkconv = gaim_gtk_conv_window_get_active_gtkconv(win); |
1214 gtkconv = GAIM_GTK_CONVERSATION(conv); | 1114 conv = gtkconv->active_conv; |
1215 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); | |
1216 | |
1217 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link), | |
1218 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link))); | |
1219 } | |
1220 | |
1221 static void | |
1222 menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) | |
1223 { | |
1224 GaimConvWindow *win = (GaimConvWindow *)data; | |
1225 GaimConversation *conv; | |
1226 GaimGtkConversation *gtkconv; | |
1227 GtkIMHtmlToolbar *toolbar; | |
1228 | |
1229 conv = gaim_conv_window_get_active_conversation(win); | |
1230 gtkconv = GAIM_GTK_CONVERSATION(gaim_conv_window_get_active_conversation(win)); | |
1231 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); | 1115 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); |
1232 | 1116 |
1233 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image), | 1117 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image), |
1234 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image))); | 1118 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image))); |
1235 } | 1119 } |
1236 | 1120 |
1237 static void | 1121 static void |
1238 menu_alias_cb(gpointer data, guint action, GtkWidget *widget) | 1122 menu_alias_cb(gpointer data, guint action, GtkWidget *widget) |
1239 { | 1123 { |
1240 GaimConvWindow *win = (GaimConvWindow *)data; | 1124 GaimGtkWindow *win = data; |
1241 GaimConversation *conv; | 1125 GaimConversation *conv; |
1242 GaimAccount *account; | 1126 GaimAccount *account; |
1243 const char *name; | 1127 const char *name; |
1244 | 1128 |
1245 conv = gaim_conv_window_get_active_conversation(win); | 1129 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1246 account = gaim_conversation_get_account(conv); | 1130 account = gaim_conversation_get_account(conv); |
1247 name = gaim_conversation_get_name(conv); | 1131 name = gaim_conversation_get_name(conv); |
1248 | 1132 |
1249 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | 1133 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { |
1250 GaimBuddy *b; | 1134 GaimBuddy *b; |
1262 } | 1146 } |
1263 | 1147 |
1264 static void | 1148 static void |
1265 menu_get_info_cb(gpointer data, guint action, GtkWidget *widget) | 1149 menu_get_info_cb(gpointer data, guint action, GtkWidget *widget) |
1266 { | 1150 { |
1267 GaimConvWindow *win = (GaimConvWindow *)data; | 1151 GaimGtkWindow *win = data; |
1268 GaimConversation *conv; | 1152 GaimConversation *conv; |
1269 | 1153 |
1270 conv = gaim_conv_window_get_active_conversation(win); | 1154 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1271 | 1155 |
1272 info_cb(NULL, GAIM_GTK_CONVERSATION(conv)); | 1156 info_cb(NULL, GAIM_GTK_CONVERSATION(conv)); |
1273 } | 1157 } |
1274 | 1158 |
1275 static void | 1159 static void |
1276 menu_invite_cb(gpointer data, guint action, GtkWidget *widget) | 1160 menu_invite_cb(gpointer data, guint action, GtkWidget *widget) |
1277 { | 1161 { |
1278 GaimConvWindow *win = (GaimConvWindow *)data; | 1162 GaimGtkWindow *win = data; |
1279 GaimConversation *conv; | 1163 GaimConversation *conv; |
1280 | 1164 |
1281 conv = gaim_conv_window_get_active_conversation(win); | 1165 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1282 | 1166 |
1283 invite_cb(NULL, GAIM_GTK_CONVERSATION(conv)); | 1167 invite_cb(NULL, GAIM_GTK_CONVERSATION(conv)); |
1284 } | 1168 } |
1285 | 1169 |
1286 static void | 1170 static void |
1287 menu_block_cb(gpointer data, guint action, GtkWidget *widget) | 1171 menu_block_cb(gpointer data, guint action, GtkWidget *widget) |
1288 { | 1172 { |
1289 GaimConvWindow *win = (GaimConvWindow *)data; | 1173 GaimGtkWindow *win = data; |
1290 GaimConversation *conv; | 1174 GaimConversation *conv; |
1291 | 1175 |
1292 conv = gaim_conv_window_get_active_conversation(win); | 1176 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1293 | 1177 |
1294 block_cb(NULL, GAIM_GTK_CONVERSATION(conv)); | 1178 block_cb(NULL, GAIM_GTK_CONVERSATION(conv)); |
1295 } | 1179 } |
1296 | 1180 |
1297 static void | 1181 static void |
1298 menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget) | 1182 menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget) |
1299 { | 1183 { |
1300 GaimConvWindow *win = (GaimConvWindow *)data; | 1184 GaimGtkWindow *win = data; |
1301 GaimConversation *conv; | 1185 GaimConversation *conv; |
1302 | 1186 |
1303 conv = gaim_conv_window_get_active_conversation(win); | 1187 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1304 | 1188 |
1305 add_remove_cb(NULL, GAIM_GTK_CONVERSATION(conv)); | 1189 add_remove_cb(NULL, GAIM_GTK_CONVERSATION(conv)); |
1306 } | 1190 } |
1307 | 1191 |
1308 static void | 1192 static void |
1309 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) | 1193 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) |
1310 { | 1194 { |
1311 GaimConvWindow *win = (GaimConvWindow *)data; | 1195 GaimGtkWindow *win = data; |
1312 | 1196 |
1313 close_conv_cb(NULL, GAIM_GTK_CONVERSATION(gaim_conv_window_get_active_conversation(win))); | 1197 close_conv_cb(NULL, GAIM_GTK_CONVERSATION(gaim_gtk_conv_window_get_active_conversation(win))); |
1314 } | 1198 } |
1315 | 1199 |
1316 static void | 1200 static void |
1317 menu_logging_cb(gpointer data, guint action, GtkWidget *widget) | 1201 menu_logging_cb(gpointer data, guint action, GtkWidget *widget) |
1318 { | 1202 { |
1319 GaimConvWindow *win = (GaimConvWindow *)data; | 1203 GaimGtkWindow *win = data; |
1320 GaimConversation *conv; | 1204 GaimConversation *conv; |
1321 | 1205 |
1322 conv = gaim_conv_window_get_active_conversation(win); | 1206 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1323 | 1207 |
1324 if (conv == NULL) | 1208 if (conv == NULL) |
1325 return; | 1209 return; |
1326 | 1210 |
1327 gaim_conversation_set_logging(conv, | 1211 gaim_conversation_set_logging(conv, |
1328 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); | 1212 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); |
1329 } | 1213 } |
1330 | 1214 |
1331 static void | 1215 static void |
1332 menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget) | 1216 menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget) |
1333 { | 1217 { |
1334 GaimConvWindow *win = (GaimConvWindow *)data; | 1218 GaimGtkWindow *win = data; |
1335 GaimConversation *conv; | 1219 GaimConversation *conv; |
1336 GaimGtkConversation *gtkconv; | 1220 GaimGtkConversation *gtkconv; |
1337 | 1221 |
1338 conv = gaim_conv_window_get_active_conversation(win); | 1222 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1339 | 1223 |
1340 if (conv == NULL) | 1224 if (conv == NULL) |
1341 return; | 1225 return; |
1342 | 1226 |
1343 gtkconv = GAIM_GTK_CONVERSATION(conv); | 1227 gtkconv = GAIM_GTK_CONVERSATION(conv); |
1344 | 1228 |
1345 gaim_prefs_set_bool("/gaim/gtk/conversations/show_formatting_toolbar", | 1229 gaim_prefs_set_bool("/gaim/gtk/conversations/show_formatting_toolbar", |
1346 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); | 1230 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); |
1347 } | 1231 } |
1348 | 1232 |
1349 static void | 1233 static void |
1350 menu_sounds_cb(gpointer data, guint action, GtkWidget *widget) | 1234 menu_sounds_cb(gpointer data, guint action, GtkWidget *widget) |
1351 { | 1235 { |
1352 GaimConvWindow *win = (GaimConvWindow *)data; | 1236 GaimGtkWindow *win = data; |
1353 GaimConversation *conv; | 1237 GaimConversation *conv; |
1354 GaimGtkConversation *gtkconv; | 1238 GaimGtkConversation *gtkconv; |
1355 | 1239 |
1356 conv = gaim_conv_window_get_active_conversation(win); | 1240 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1357 | 1241 |
1358 if (!conv) | 1242 if (!conv) |
1359 return; | 1243 return; |
1360 | 1244 |
1361 gtkconv = GAIM_GTK_CONVERSATION(conv); | 1245 gtkconv = GAIM_GTK_CONVERSATION(conv); |
1365 } | 1249 } |
1366 | 1250 |
1367 static void | 1251 static void |
1368 menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget) | 1252 menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget) |
1369 { | 1253 { |
1370 GaimConvWindow *win = (GaimConvWindow *)data; | 1254 GaimGtkWindow *win = data; |
1371 GaimConversation *conv; | 1255 GaimConversation *conv; |
1372 GaimGtkConversation *gtkconv; | 1256 GaimGtkConversation *gtkconv; |
1373 | 1257 |
1374 conv = gaim_conv_window_get_active_conversation(win); | 1258 conv = gaim_gtk_conv_window_get_active_conversation(win); |
1375 | 1259 |
1376 if (!conv) | 1260 if (!conv) |
1377 return; | 1261 return; |
1378 | 1262 |
1379 gtkconv = GAIM_GTK_CONVERSATION(conv); | 1263 gtkconv = GAIM_GTK_CONVERSATION(conv); |
1711 | 1595 |
1712 static void | 1596 static void |
1713 move_to_next_unread_tab(GaimGtkConversation *gtkconv, gboolean forward) | 1597 move_to_next_unread_tab(GaimGtkConversation *gtkconv, gboolean forward) |
1714 { | 1598 { |
1715 GaimGtkConversation *next_gtkconv = NULL; | 1599 GaimGtkConversation *next_gtkconv = NULL; |
1716 GaimConvWindow *win; | 1600 GaimGtkWindow *win; |
1717 GList *l; | 1601 GList *l; |
1718 int index, i, total, found = 0; | 1602 int index, i, total, found = 0; |
1719 | 1603 |
1720 win = gaim_conversation_get_window(gtkconv->active_conv); | 1604 win = gtkconv->win; |
1721 index = gtk_notebook_page_num(GTK_NOTEBOOK(GAIM_GTK_WINDOW(win)->notebook), gtkconv->tab_cont); | 1605 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); |
1722 total = gaim_conv_window_get_conversation_count(win); | 1606 total = gaim_gtk_conv_window_get_gtkconv_count(win); |
1723 | 1607 |
1724 /* First check the tabs after (forward) or before (!forward) this position. */ | 1608 /* First check the tabs after (forward) or before (!forward) this position. */ |
1725 for (i = index; | 1609 for (i = index; |
1726 !found && (next_gtkconv = gaim_gtk_get_gtkconv_at_index(win, i)); | 1610 !found && (next_gtkconv = gaim_gtk_conv_window_get_gtkconv_at_index(win, i)); |
1727 forward ? i++ : i--) { | 1611 forward ? i++ : i--) { |
1728 if (i == -1) { | 1612 if (i == -1) { |
1729 break; | 1613 break; |
1730 } | 1614 } |
1731 for (l = next_gtkconv->convs; l; l = forward ? l->next : l->prev) { | 1615 for (l = next_gtkconv->convs; l; l = forward ? l->next : l->prev) { |
1739 } | 1623 } |
1740 | 1624 |
1741 if (!found) { | 1625 if (!found) { |
1742 /* Now check from the beginning up to (forward) or end back to (!forward) this position. */ | 1626 /* Now check from the beginning up to (forward) or end back to (!forward) this position. */ |
1743 for (i = forward ? 0 : total - 1; | 1627 for (i = forward ? 0 : total - 1; |
1744 !found && (forward ? i < index : i >= 0) && (next_gtkconv = gaim_gtk_get_gtkconv_at_index(win, i)); | 1628 !found && (forward ? i < index : i >= 0) && (next_gtkconv = gaim_gtk_conv_window_get_gtkconv_at_index(win, i)); |
1745 forward ? i++ : i--) { | 1629 forward ? i++ : i--) { |
1746 for (l = next_gtkconv->convs; l; l = forward ? l->next : l->prev) { | 1630 for (l = next_gtkconv->convs; l; l = forward ? l->next : l->prev) { |
1747 GaimConversation *c = l->data; | 1631 GaimConversation *c = l->data; |
1748 if (gaim_conversation_get_unseen(c) > 0) { | 1632 if (gaim_conversation_get_unseen(c) > 0) { |
1749 found = 1; | 1633 found = 1; |
1758 index++; | 1642 index++; |
1759 } | 1643 } |
1760 else { | 1644 else { |
1761 index = (index == 0) ? total - 1 : index - 1; | 1645 index = (index == 0) ? total - 1 : index - 1; |
1762 } | 1646 } |
1763 if (!(next_gtkconv = gaim_gtk_get_gtkconv_at_index(win, index))) | 1647 if (!(next_gtkconv = gaim_gtk_conv_window_get_gtkconv_at_index(win, index))) |
1764 next_gtkconv = gaim_gtk_get_gtkconv_at_index(win, 0); | 1648 next_gtkconv = gaim_gtk_conv_window_get_gtkconv_at_index(win, 0); |
1765 } | 1649 } |
1766 } | 1650 } |
1767 | 1651 |
1768 if (next_gtkconv != NULL && next_gtkconv != gtkconv) | 1652 if (next_gtkconv != NULL && next_gtkconv != gtkconv) |
1769 gaim_conv_window_switch_conversation(win,next_gtkconv->active_conv); | 1653 gaim_gtk_conv_window_switch_gtkconv(win, next_gtkconv); |
1770 } | 1654 } |
1771 | 1655 |
1772 static gboolean | 1656 static gboolean |
1773 entry_key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer data) | 1657 entry_key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer data) |
1774 { | 1658 { |
1775 GaimConvWindow *win; | 1659 GaimGtkWindow *win; |
1776 GaimConversation *conv; | 1660 GaimConversation *conv; |
1777 GaimGtkConversation *gtkconv; | 1661 GaimGtkConversation *gtkconv; |
1778 GaimGtkWindow *gtkwin; | |
1779 int curconv; | 1662 int curconv; |
1780 | 1663 |
1781 gtkconv = (GaimGtkConversation *)data; | 1664 gtkconv = (GaimGtkConversation *)data; |
1782 conv = gtkconv->active_conv; | 1665 conv = gtkconv->active_conv; |
1783 win = gaim_conversation_get_window(conv); | 1666 win = gtkconv->win; |
1784 gtkwin = GAIM_GTK_WINDOW(win); | 1667 curconv = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook)); |
1785 curconv = gtk_notebook_get_current_page(GTK_NOTEBOOK(gtkwin->notebook)); | |
1786 | 1668 |
1787 /* If CTRL was held down... */ | 1669 /* If CTRL was held down... */ |
1788 if (event->state & GDK_CONTROL_MASK) { | 1670 if (event->state & GDK_CONTROL_MASK) { |
1789 switch (event->keyval) { | 1671 switch (event->keyval) { |
1790 case GDK_Up: | 1672 case GDK_Up: |
1876 return TRUE; | 1758 return TRUE; |
1877 break; | 1759 break; |
1878 | 1760 |
1879 case GDK_Page_Down: | 1761 case GDK_Page_Down: |
1880 case ']': | 1762 case ']': |
1881 if (!gaim_gtk_get_gtkconv_at_index(win, curconv + 1)) | 1763 if (!gaim_gtk_conv_window_get_gtkconv_at_index(win, curconv + 1)) |
1882 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), 0); | 1764 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); |
1883 else | 1765 else |
1884 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), curconv + 1); | 1766 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv + 1); |
1885 return TRUE; | 1767 return TRUE; |
1886 break; | 1768 break; |
1887 | 1769 |
1888 case GDK_Page_Up: | 1770 case GDK_Page_Up: |
1889 case '[': | 1771 case '[': |
1890 if (!gaim_gtk_get_gtkconv_at_index(win, curconv - 1)) | 1772 if (!gaim_gtk_conv_window_get_gtkconv_at_index(win, curconv - 1)) |
1891 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), -1); | 1773 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1); |
1892 else | 1774 else |
1893 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), curconv - 1); | 1775 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv - 1); |
1894 return TRUE; | 1776 return TRUE; |
1895 break; | 1777 break; |
1896 | 1778 |
1897 case GDK_Tab: | 1779 case GDK_Tab: |
1898 case GDK_ISO_Left_Tab: | 1780 case GDK_ISO_Left_Tab: |
1904 | 1786 |
1905 return TRUE; | 1787 return TRUE; |
1906 break; | 1788 break; |
1907 | 1789 |
1908 case GDK_comma: | 1790 case GDK_comma: |
1909 gtk_notebook_reorder_child(GTK_NOTEBOOK(gtkwin->notebook), | 1791 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), |
1910 gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), curconv), | 1792 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), |
1911 curconv - 1); | 1793 curconv - 1); |
1912 break; | 1794 break; |
1913 | 1795 |
1914 case GDK_period: | 1796 case GDK_period: |
1915 gtk_notebook_reorder_child(GTK_NOTEBOOK(gtkwin->notebook), | 1797 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), |
1916 gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), curconv), | 1798 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), |
1917 (curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(gtkwin->notebook))); | 1799 (curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook))); |
1918 break; | 1800 break; |
1919 | 1801 |
1920 } /* End of switch */ | 1802 } /* End of switch */ |
1921 } | 1803 } |
1922 | 1804 |
1924 else if (event->state & GDK_MOD1_MASK) | 1806 else if (event->state & GDK_MOD1_MASK) |
1925 { | 1807 { |
1926 if (event->keyval > '0' && event->keyval <= '9') | 1808 if (event->keyval > '0' && event->keyval <= '9') |
1927 { | 1809 { |
1928 int switchto = event->keyval - '1'; | 1810 int switchto = event->keyval - '1'; |
1929 if (switchto < gaim_conv_window_get_conversation_count(win)) | 1811 if (switchto < gaim_gtk_conv_window_get_gtkconv_count(win)) |
1930 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), switchto); | 1812 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), switchto); |
1931 | 1813 |
1932 return TRUE; | 1814 return TRUE; |
1933 } | 1815 } |
1934 } | 1816 } |
1935 | 1817 |
2014 } | 1896 } |
2015 | 1897 |
2016 static void | 1898 static void |
2017 menu_conv_sel_send_cb(GObject *m, gpointer data) | 1899 menu_conv_sel_send_cb(GObject *m, gpointer data) |
2018 { | 1900 { |
2019 GaimConvWindow *win = g_object_get_data(m, "user_data"); | 1901 GaimGtkWindow *win = g_object_get_data(m, "user_data"); |
2020 GaimAccount *account = g_object_get_data(m, "gaim_account"); | 1902 GaimAccount *account = g_object_get_data(m, "gaim_account"); |
2021 GaimConversation *conv; | 1903 GaimConversation *conv; |
2022 GaimGtkConversation *gtkconv; | 1904 GaimGtkConversation *gtkconv; |
2023 | 1905 |
2024 if (gtk_check_menu_item_get_active((GtkCheckMenuItem*) m) == FALSE) | 1906 if (gtk_check_menu_item_get_active((GtkCheckMenuItem*) m) == FALSE) |
2025 return; | 1907 return; |
2026 | 1908 |
2027 conv = gaim_conv_window_get_active_conversation(win); | 1909 conv = gaim_gtk_conv_window_get_active_conversation(win); |
2028 | 1910 |
2029 gaim_conversation_set_account(conv, account); | 1911 gaim_conversation_set_account(conv, account); |
2030 | 1912 |
2031 gtkconv = GAIM_GTK_CONVERSATION(conv); | 1913 gtkconv = GAIM_GTK_CONVERSATION(conv); |
2032 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), | 1914 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), |
2082 /* We're deleting, but not all of it, so it counts as typing. */ | 1964 /* We're deleting, but not all of it, so it counts as typing. */ |
2083 got_typing_keypress(gtkconv, FALSE); | 1965 got_typing_keypress(gtkconv, FALSE); |
2084 } | 1966 } |
2085 } | 1967 } |
2086 | 1968 |
2087 static void | |
2088 notebook_init_grab(GaimGtkWindow *gtkwin, GtkWidget *widget) | |
2089 { | |
2090 static GdkCursor *cursor = NULL; | |
2091 | |
2092 gtkwin->in_drag = TRUE; | |
2093 | |
2094 if (gtkwin->drag_leave_signal) { | |
2095 g_signal_handler_disconnect(G_OBJECT(widget), | |
2096 gtkwin->drag_leave_signal); | |
2097 | |
2098 gtkwin->drag_leave_signal = 0; | |
2099 } | |
2100 | |
2101 if (cursor == NULL) | |
2102 cursor = gdk_cursor_new(GDK_FLEUR); | |
2103 | |
2104 /* Grab the pointer */ | |
2105 gtk_grab_add(gtkwin->notebook); | |
2106 #ifndef _WIN32 | |
2107 /* Currently for win32 GTK+ (as of 2.2.1), gdk_pointer_is_grabbed will | |
2108 always be true after a button press. */ | |
2109 if (!gdk_pointer_is_grabbed()) | |
2110 #endif | |
2111 gdk_pointer_grab(gtkwin->notebook->window, FALSE, | |
2112 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, | |
2113 NULL, cursor, GDK_CURRENT_TIME); | |
2114 } | |
2115 | |
2116 static gboolean | |
2117 notebook_motion_cb(GtkWidget *widget, GdkEventButton *e, GaimConvWindow *win) | |
2118 { | |
2119 GaimGtkWindow *gtkwin; | |
2120 | |
2121 gtkwin = GAIM_GTK_WINDOW(win); | |
2122 | |
2123 /* | |
2124 * Make sure the user moved the mouse far enough for the | |
2125 * drag to be initiated. | |
2126 */ | |
2127 if (gtkwin->in_predrag) { | |
2128 if (e->x_root < gtkwin->drag_min_x || | |
2129 e->x_root >= gtkwin->drag_max_x || | |
2130 e->y_root < gtkwin->drag_min_y || | |
2131 e->y_root >= gtkwin->drag_max_y) { | |
2132 | |
2133 gtkwin->in_predrag = FALSE; | |
2134 notebook_init_grab(gtkwin, widget); | |
2135 } | |
2136 } | |
2137 else { /* Otherwise, draw the arrows. */ | |
2138 GaimConvWindow *dest_win; | |
2139 GaimGtkWindow *dest_gtkwin; | |
2140 GtkNotebook *dest_notebook; | |
2141 GtkWidget *tab; | |
2142 gint nb_x, nb_y, page_num; | |
2143 gint arrow1_x, arrow1_y, arrow2_x, arrow2_y; | |
2144 gboolean horiz_tabs = FALSE; | |
2145 | |
2146 /* Get the window that the cursor is over. */ | |
2147 dest_win = gaim_gtkwin_get_at_xy(e->x_root, e->y_root); | |
2148 | |
2149 if (dest_win == NULL) { | |
2150 dnd_hints_hide_all(); | |
2151 | |
2152 return TRUE; | |
2153 } | |
2154 | |
2155 dest_gtkwin = GAIM_GTK_WINDOW(dest_win); | |
2156 | |
2157 dest_notebook = GTK_NOTEBOOK(dest_gtkwin->notebook); | |
2158 | |
2159 gdk_window_get_origin(GTK_WIDGET(dest_notebook)->window, &nb_x, &nb_y); | |
2160 | |
2161 arrow1_x = arrow2_x = nb_x; | |
2162 arrow1_y = arrow2_y = nb_y; | |
2163 | |
2164 page_num = gaim_gtkconv_get_tab_at_xy(dest_win, | |
2165 e->x_root, e->y_root); | |
2166 | |
2167 if (gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_TOP || | |
2168 gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { | |
2169 | |
2170 horiz_tabs = TRUE; | |
2171 } | |
2172 | |
2173 tab = gaim_gtk_get_gtkconv_at_index(dest_win, page_num)->tabby; | |
2174 | |
2175 if (horiz_tabs) { | |
2176 arrow1_x = arrow2_x = nb_x + tab->allocation.x; | |
2177 | |
2178 if ((gpointer)gtkwin == (gpointer)dest_gtkwin && gtkwin->drag_tab < page_num) { | |
2179 arrow1_x += tab->allocation.width; | |
2180 arrow2_x += tab->allocation.width; | |
2181 } | |
2182 | |
2183 arrow1_y = nb_y + tab->allocation.y; | |
2184 arrow2_y = nb_y + tab->allocation.y + | |
2185 tab->allocation.height; | |
2186 } | |
2187 else { | |
2188 arrow1_x = nb_x + tab->allocation.x; | |
2189 arrow2_x = nb_x + tab->allocation.x + | |
2190 tab->allocation.width; | |
2191 arrow1_y = arrow2_y = nb_y + tab->allocation.y + tab->allocation.height/2; | |
2192 | |
2193 if ((gpointer)gtkwin == (gpointer)dest_win && gtkwin->drag_tab < page_num) { | |
2194 arrow1_y += tab->allocation.height; | |
2195 arrow2_y += tab->allocation.height; | |
2196 } | |
2197 } | |
2198 | |
2199 if (horiz_tabs) { | |
2200 dnd_hints_show(HINT_ARROW_DOWN, arrow1_x, arrow1_y); | |
2201 dnd_hints_show(HINT_ARROW_UP, arrow2_x, arrow2_y); | |
2202 } | |
2203 else { | |
2204 dnd_hints_show(HINT_ARROW_RIGHT, arrow1_x, arrow1_y); | |
2205 dnd_hints_show(HINT_ARROW_LEFT, arrow2_x, arrow2_y); | |
2206 } | |
2207 } | |
2208 | |
2209 return TRUE; | |
2210 } | |
2211 | |
2212 static gboolean | |
2213 notebook_leave_cb(GtkWidget *widget, GdkEventCrossing *e, GaimConvWindow *win) | |
2214 { | |
2215 GaimGtkWindow *gtkwin; | |
2216 | |
2217 gtkwin = GAIM_GTK_WINDOW(win); | |
2218 | |
2219 if (gtkwin->in_drag) | |
2220 return FALSE; | |
2221 | |
2222 if (e->x_root < gtkwin->drag_min_x || | |
2223 e->x_root >= gtkwin->drag_max_x || | |
2224 e->y_root < gtkwin->drag_min_y || | |
2225 e->y_root >= gtkwin->drag_max_y) { | |
2226 | |
2227 gtkwin->in_predrag = FALSE; | |
2228 notebook_init_grab(gtkwin, widget); | |
2229 } | |
2230 | |
2231 return TRUE; | |
2232 } | |
2233 | |
2234 /* | |
2235 * THANK YOU GALEON! | |
2236 */ | |
2237 static gboolean | |
2238 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, GaimConvWindow *win) | |
2239 { | |
2240 GaimGtkWindow *gtkwin; | |
2241 gint nb_x, nb_y, x_rel, y_rel; | |
2242 int tab_clicked; | |
2243 GtkWidget *page; | |
2244 GtkWidget *tab; | |
2245 | |
2246 if (e->button != 1 || e->type != GDK_BUTTON_PRESS) | |
2247 return FALSE; | |
2248 | |
2249 gtkwin = GAIM_GTK_WINDOW(win); | |
2250 | |
2251 if (gtkwin->in_drag) { | |
2252 gaim_debug(GAIM_DEBUG_WARNING, "gtkconv", | |
2253 "Already in the middle of a window drag at tab_press_cb\n"); | |
2254 return TRUE; | |
2255 } | |
2256 | |
2257 /* | |
2258 * Make sure a tab was actually clicked. The arrow buttons | |
2259 * mess things up. | |
2260 */ | |
2261 tab_clicked = gaim_gtkconv_get_tab_at_xy(win, e->x_root, e->y_root); | |
2262 | |
2263 if (tab_clicked == -1) | |
2264 return FALSE; | |
2265 | |
2266 /* | |
2267 * Get the relative position of the press event, with regards to | |
2268 * the position of the notebook. | |
2269 */ | |
2270 gdk_window_get_origin(gtkwin->notebook->window, &nb_x, &nb_y); | |
2271 | |
2272 x_rel = e->x_root - nb_x; | |
2273 y_rel = e->y_root - nb_y; | |
2274 | |
2275 /* Reset the min/max x/y */ | |
2276 gtkwin->drag_min_x = 0; | |
2277 gtkwin->drag_min_y = 0; | |
2278 gtkwin->drag_max_x = 0; | |
2279 gtkwin->drag_max_y = 0; | |
2280 | |
2281 /* Find out which tab was dragged. */ | |
2282 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), tab_clicked); | |
2283 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(gtkwin->notebook), page); | |
2284 | |
2285 gtkwin->drag_min_x = tab->allocation.x + nb_x; | |
2286 gtkwin->drag_min_y = tab->allocation.y + nb_y; | |
2287 gtkwin->drag_max_x = tab->allocation.width + gtkwin->drag_min_x; | |
2288 gtkwin->drag_max_y = tab->allocation.height + gtkwin->drag_min_y; | |
2289 | |
2290 /* Make sure the click occurred in the tab. */ | |
2291 if (e->x_root < gtkwin->drag_min_x || | |
2292 e->x_root >= gtkwin->drag_max_x || | |
2293 e->y_root < gtkwin->drag_min_y || | |
2294 e->y_root >= gtkwin->drag_max_y) { | |
2295 | |
2296 return FALSE; | |
2297 } | |
2298 | |
2299 gtkwin->in_predrag = TRUE; | |
2300 gtkwin->drag_tab = tab_clicked; | |
2301 | |
2302 /* Connect the new motion signals. */ | |
2303 gtkwin->drag_motion_signal = | |
2304 g_signal_connect(G_OBJECT(widget), "motion_notify_event", | |
2305 G_CALLBACK(notebook_motion_cb), win); | |
2306 | |
2307 gtkwin->drag_leave_signal = | |
2308 g_signal_connect(G_OBJECT(widget), "leave_notify_event", | |
2309 G_CALLBACK(notebook_leave_cb), win); | |
2310 | |
2311 return FALSE; | |
2312 } | |
2313 | |
2314 static gboolean | |
2315 notebook_release_cb(GtkWidget *widget, GdkEventButton *e, GaimConvWindow *win) | |
2316 { | |
2317 GaimConvWindow *dest_win; | |
2318 GaimGtkWindow *gtkwin; | |
2319 GaimConversation *conv; | |
2320 GaimGtkConversation *gtkconv; | |
2321 gint dest_page_num = 0; | |
2322 gboolean new_window = FALSE; | |
2323 | |
2324 /* | |
2325 * Don't check to make sure that the event's window matches the | |
2326 * widget's, because we may be getting an event passed on from the | |
2327 * close button. | |
2328 */ | |
2329 if (e->button != 1 && e->type != GDK_BUTTON_RELEASE) | |
2330 return FALSE; | |
2331 | |
2332 if (gdk_pointer_is_grabbed()) { | |
2333 gdk_pointer_ungrab(GDK_CURRENT_TIME); | |
2334 gtk_grab_remove(widget); | |
2335 } | |
2336 | |
2337 gtkwin = GAIM_GTK_WINDOW(win); | |
2338 | |
2339 if (!gtkwin->in_predrag && !gtkwin->in_drag) | |
2340 return FALSE; | |
2341 | |
2342 /* Disconnect the motion signal. */ | |
2343 if (gtkwin->drag_motion_signal) { | |
2344 g_signal_handler_disconnect(G_OBJECT(widget), | |
2345 gtkwin->drag_motion_signal); | |
2346 | |
2347 gtkwin->drag_motion_signal = 0; | |
2348 } | |
2349 | |
2350 /* | |
2351 * If we're in a pre-drag, we'll also need to disconnect the leave | |
2352 * signal. | |
2353 */ | |
2354 if (gtkwin->in_predrag) { | |
2355 gtkwin->in_predrag = FALSE; | |
2356 | |
2357 if (gtkwin->drag_leave_signal) { | |
2358 g_signal_handler_disconnect(G_OBJECT(widget), | |
2359 gtkwin->drag_leave_signal); | |
2360 | |
2361 gtkwin->drag_leave_signal = 0; | |
2362 } | |
2363 } | |
2364 | |
2365 /* If we're not in drag... */ | |
2366 /* We're perfectly normal people! */ | |
2367 if (!gtkwin->in_drag) | |
2368 return FALSE; | |
2369 | |
2370 gtkwin->in_drag = FALSE; | |
2371 | |
2372 dnd_hints_hide_all(); | |
2373 | |
2374 dest_win = gaim_gtkwin_get_at_xy(e->x_root, e->y_root); | |
2375 | |
2376 conv = gaim_conv_window_get_active_conversation(win); | |
2377 | |
2378 if (dest_win == NULL) { | |
2379 /* If the current window doesn't have any other conversations, | |
2380 * there isn't much point transferring the conv to a new window. */ | |
2381 if (gaim_conv_window_get_conversation_count(win) > 1) { | |
2382 /* Make a new window to stick this to. */ | |
2383 dest_win = gaim_conv_window_new(); | |
2384 new_window = TRUE; | |
2385 } | |
2386 } | |
2387 | |
2388 if (dest_win == NULL) | |
2389 return FALSE; | |
2390 | |
2391 gaim_signal_emit(gaim_gtk_conversations_get_handle(), | |
2392 "conversation-dragging", win, dest_win); | |
2393 | |
2394 /* Get the destination page number. */ | |
2395 if (!new_window) | |
2396 dest_page_num = gaim_gtkconv_get_tab_at_xy(dest_win, | |
2397 e->x_root, e->y_root); | |
2398 | |
2399 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
2400 | |
2401 if (win == dest_win) { | |
2402 gtk_notebook_reorder_child(GTK_NOTEBOOK(gtkwin->notebook), gtkconv->tab_cont, dest_page_num); | |
2403 } | |
2404 else { | |
2405 gaim_conv_window_remove_conversation(win, conv); | |
2406 gaim_conv_window_add_conversation(dest_win, conv); | |
2407 gtk_notebook_reorder_child(GTK_NOTEBOOK(GAIM_GTK_WINDOW(dest_win)->notebook), gtkconv->tab_cont, dest_page_num); | |
2408 gaim_conv_window_switch_conversation(dest_win, conv); | |
2409 if (new_window) { | |
2410 GaimGtkWindow *dest_gtkwin = GAIM_GTK_WINDOW(dest_win); | |
2411 gint win_width, win_height; | |
2412 | |
2413 gtk_window_get_size(GTK_WINDOW(dest_gtkwin->window), | |
2414 &win_width, &win_height); | |
2415 | |
2416 gtk_window_move(GTK_WINDOW(dest_gtkwin->window), | |
2417 e->x_root - (win_width / 2), | |
2418 e->y_root - (win_height / 2)); | |
2419 | |
2420 gaim_conv_window_show(dest_win); | |
2421 } | |
2422 } | |
2423 | |
2424 gtk_widget_grab_focus(GAIM_GTK_CONVERSATION(conv)->entry); | |
2425 | |
2426 return TRUE; | |
2427 } | |
2428 | |
2429 /************************************************************************** | 1969 /************************************************************************** |
2430 * A bunch of buddy icon functions | 1970 * A bunch of buddy icon functions |
2431 **************************************************************************/ | 1971 **************************************************************************/ |
2432 static GdkPixbuf * | 1972 GdkPixbuf * |
2433 get_tab_icon(GaimConversation *conv, gboolean small_icon) | 1973 gaim_gtkconv_get_tab_icon(GaimConversation *conv, gboolean small_icon) |
2434 { | 1974 { |
2435 GaimAccount *account = NULL; | 1975 GaimAccount *account = NULL; |
2436 const char *name = NULL; | 1976 const char *name = NULL; |
2437 GdkPixbuf *status = NULL; | 1977 GdkPixbuf *status = NULL; |
2438 | 1978 |
2470 | 2010 |
2471 static void | 2011 static void |
2472 update_tab_icon(GaimConversation *conv) | 2012 update_tab_icon(GaimConversation *conv) |
2473 { | 2013 { |
2474 GaimGtkConversation *gtkconv; | 2014 GaimGtkConversation *gtkconv; |
2475 GaimConvWindow *win = gaim_conversation_get_window(conv); | 2015 GaimGtkWindow *win; |
2476 GaimAccount *account; | 2016 GaimAccount *account; |
2477 const char *name; | 2017 const char *name; |
2478 GdkPixbuf *status = NULL; | 2018 GdkPixbuf *status = NULL; |
2479 | 2019 |
2480 g_return_if_fail(conv != NULL); | 2020 g_return_if_fail(conv != NULL); |
2481 | 2021 |
2482 gtkconv = GAIM_GTK_CONVERSATION(conv); | 2022 gtkconv = GAIM_GTK_CONVERSATION(conv); |
2023 win = gtkconv->win; | |
2483 name = gaim_conversation_get_name(conv); | 2024 name = gaim_conversation_get_name(conv); |
2484 account = gaim_conversation_get_account(conv); | 2025 account = gaim_conversation_get_account(conv); |
2485 | 2026 |
2486 status = get_tab_icon(conv, TRUE); | 2027 status = gaim_gtkconv_get_tab_icon(conv, TRUE); |
2487 | 2028 |
2488 g_return_if_fail(status != NULL); | 2029 g_return_if_fail(status != NULL); |
2489 | 2030 |
2490 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); | 2031 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); |
2491 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); | 2032 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); |
2492 | 2033 |
2493 if (status != NULL) | 2034 if (status != NULL) |
2494 g_object_unref(status); | 2035 g_object_unref(status); |
2495 | 2036 |
2496 if (gaim_conv_window_get_active_conversation(win) == conv && | 2037 if (gaim_gtk_conv_window_get_active_conversation(win) == conv && |
2497 (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_IM || | 2038 (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_IM || |
2498 gtkconv->u.im->anim == NULL)) | 2039 gtkconv->u.im->anim == NULL)) |
2499 { | 2040 { |
2500 status = get_tab_icon(conv, FALSE); | 2041 status = gaim_gtkconv_get_tab_icon(conv, FALSE); |
2501 | 2042 |
2502 gtk_window_set_icon(GTK_WINDOW(GAIM_GTK_WINDOW(win)->window), status); | 2043 gtk_window_set_icon(GTK_WINDOW(win->window), status); |
2503 | 2044 |
2504 if (status != NULL) | 2045 if (status != NULL) |
2505 g_object_unref(status); | 2046 g_object_unref(status); |
2506 } | 2047 } |
2507 } | 2048 } |
2588 | 2129 |
2589 gtkconv->u.im->icon_timer = g_timeout_add(delay, redraw_icon, conv); | 2130 gtkconv->u.im->icon_timer = g_timeout_add(delay, redraw_icon, conv); |
2590 } | 2131 } |
2591 | 2132 |
2592 static void | 2133 static void |
2593 stop_anim(GtkObject *obj, GaimGtkConversation *gtkconv) | |
2594 { | |
2595 if (gtkconv->u.im->icon_timer != 0) | |
2596 g_source_remove(gtkconv->u.im->icon_timer); | |
2597 | |
2598 gtkconv->u.im->icon_timer = 0; | |
2599 } | |
2600 | |
2601 static void | |
2602 toggle_icon_animate_cb(GtkWidget *w, GaimGtkConversation *gtkconv) | |
2603 { | |
2604 gtkconv->u.im->animate = | |
2605 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); | |
2606 | |
2607 if (gtkconv->u.im->animate) | |
2608 start_anim(NULL, gtkconv); | |
2609 else | |
2610 stop_anim(NULL, gtkconv); | |
2611 } | |
2612 | |
2613 static void | |
2614 remove_icon(GaimGtkConversation *gtkconv) | 2134 remove_icon(GaimGtkConversation *gtkconv) |
2615 { | 2135 { |
2616 GaimConversation *conv = gtkconv->active_conv; | 2136 GaimConversation *conv = gtkconv->active_conv; |
2617 GaimGtkWindow *gtkwin; | 2137 GaimGtkWindow *gtkwin; |
2618 | 2138 |
2635 gtkconv->u.im->anim = NULL; | 2155 gtkconv->u.im->anim = NULL; |
2636 gtkconv->u.im->iter = NULL; | 2156 gtkconv->u.im->iter = NULL; |
2637 gtkconv->u.im->icon_container = NULL; | 2157 gtkconv->u.im->icon_container = NULL; |
2638 gtkconv->u.im->show_icon = FALSE; | 2158 gtkconv->u.im->show_icon = FALSE; |
2639 | 2159 |
2640 gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(conv)); | 2160 gtkwin = gtkconv->win; |
2641 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.show_icon), FALSE); | 2161 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.show_icon), FALSE); |
2642 } | 2162 } |
2643 | 2163 |
2644 static void | 2164 static void |
2645 saveicon_writefile_cb(void *user_data, const char *filename) | 2165 saveicon_writefile_cb(void *user_data, const char *filename) |
2687 G_CALLBACK(saveicon_writefile_cb), NULL, conv); | 2207 G_CALLBACK(saveicon_writefile_cb), NULL, conv); |
2688 | 2208 |
2689 g_free(buf); | 2209 g_free(buf); |
2690 } | 2210 } |
2691 | 2211 |
2212 static void | |
2213 stop_anim(GtkObject *obj, GaimGtkConversation *gtkconv) | |
2214 { | |
2215 if (gtkconv->u.im->icon_timer != 0) | |
2216 g_source_remove(gtkconv->u.im->icon_timer); | |
2217 | |
2218 gtkconv->u.im->icon_timer = 0; | |
2219 } | |
2220 | |
2221 | |
2222 static void | |
2223 toggle_icon_animate_cb(GtkWidget *w, GaimGtkConversation *gtkconv) | |
2224 { | |
2225 gtkconv->u.im->animate = | |
2226 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); | |
2227 | |
2228 if (gtkconv->u.im->animate) | |
2229 start_anim(NULL, gtkconv); | |
2230 else | |
2231 stop_anim(NULL, gtkconv); | |
2232 } | |
2233 | |
2692 static gboolean | 2234 static gboolean |
2693 icon_menu(GtkObject *obj, GdkEventButton *e, GaimGtkConversation *gtkconv) | 2235 icon_menu(GtkObject *obj, GdkEventButton *e, GaimGtkConversation *gtkconv) |
2694 { | 2236 { |
2695 GaimConversation *conv = gtkconv->active_conv; | 2237 GaimConversation *conv = gtkconv->active_conv; |
2696 static GtkWidget *menu = NULL; | 2238 static GtkWidget *menu = NULL; |
2732 } | 2274 } |
2733 | 2275 |
2734 static void | 2276 static void |
2735 menu_buddyicon_cb(gpointer data, guint action, GtkWidget *widget) | 2277 menu_buddyicon_cb(gpointer data, guint action, GtkWidget *widget) |
2736 { | 2278 { |
2737 GaimConvWindow *win = (GaimConvWindow *)data; | 2279 GaimGtkWindow *win = data; |
2738 GaimConversation *conv; | 2280 GaimConversation *conv; |
2739 GaimGtkConversation *gtkconv; | 2281 GaimGtkConversation *gtkconv; |
2740 gboolean active; | 2282 gboolean active; |
2741 | 2283 |
2742 conv = gaim_conv_window_get_active_conversation(win); | 2284 conv = gaim_gtk_conv_window_get_active_conversation(win); |
2743 | 2285 |
2744 if (!conv) | 2286 if (!conv) |
2745 return; | 2287 return; |
2746 | 2288 |
2747 g_return_if_fail(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM); | 2289 g_return_if_fail(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM); |
2758 | 2300 |
2759 /************************************************************************** | 2301 /************************************************************************** |
2760 * End of the bunch of buddy icon functions | 2302 * End of the bunch of buddy icon functions |
2761 **************************************************************************/ | 2303 **************************************************************************/ |
2762 | 2304 |
2763 | 2305 GaimGtkWindow * |
2764 /* | 2306 gaim_gtkconv_get_window(GaimGtkConversation *gtkconv) |
2765 * Makes sure all the menu items and all the buttons are hidden/shown and | 2307 { |
2766 * sensitive/insensitive. This is called after changing tabs and when an | 2308 g_return_val_if_fail(gtkconv != NULL, NULL); |
2767 * account signs on or off. | 2309 return gtkconv->win; |
2768 */ | 2310 } |
2769 static void | 2311 |
2770 gray_stuff_out(GaimGtkConversation *gtkconv) | 2312 static GtkItemFactoryEntry menu_items[] = |
2771 { | 2313 { |
2772 GaimConvWindow *win; | 2314 /* Conversation menu */ |
2773 GaimGtkWindow *gtkwin; | 2315 { N_("/_Conversation"), NULL, NULL, 0, "<Branch>" }, |
2774 GaimConversation *conv = gtkconv->active_conv; | 2316 |
2775 GaimConnection *gc; | 2317 { N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb, |
2776 GaimPluginProtocolInfo *prpl_info = NULL; | 2318 0, "<StockItem>", GAIM_STOCK_IM }, |
2777 GdkPixbuf *window_icon = NULL; | 2319 |
2778 GtkIMHtmlButtons buttons; | 2320 { "/Conversation/sep0", NULL, NULL, 0, "<Separator>" }, |
2779 GaimAccount *account; | 2321 |
2780 | 2322 { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, |
2781 win = gaim_conversation_get_window(conv); | 2323 "<StockItem>", GTK_STOCK_FIND }, |
2782 gtkwin = GAIM_GTK_WINDOW(win); | 2324 { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, NULL }, |
2783 gtkconv = GAIM_GTK_CONVERSATION(conv); | 2325 { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0, |
2784 gc = gaim_conversation_get_gc(conv); | 2326 "<StockItem>", GTK_STOCK_SAVE_AS }, |
2785 account = gaim_conversation_get_account(conv); | 2327 { N_("/Conversation/Clear"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR }, |
2786 | 2328 |
2787 if (gc != NULL) | 2329 { "/Conversation/sep1", NULL, NULL, 0, "<Separator>" }, |
2788 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | 2330 |
2789 | 2331 { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, |
2790 if (gtkwin->menu.send_as != NULL) | 2332 { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, |
2791 g_timeout_add(0, (GSourceFunc)update_send_as_selection, win); | 2333 0, NULL }, |
2792 | 2334 { N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0, |
2793 /* | 2335 "<StockItem>", GAIM_STOCK_INFO }, |
2794 * Handle hiding and showing stuff based on what type of conv this is. | 2336 { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, |
2795 * Stuff that Gaim IMs support in general should be shown for IM | 2337 "<StockItem>", GAIM_STOCK_INVITE }, |
2796 * conversations. Stuff that Gaim chats support in general should be | 2338 |
2797 * shown for chat conversations. It doesn't matter whether the PRPL | 2339 { "/Conversation/sep2", NULL, NULL, 0, "<Separator>" }, |
2798 * supports it or not--that only affects if the button or menu item | 2340 |
2799 * is sensitive or not. | 2341 { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0, |
2800 */ | 2342 "<StockItem>", GAIM_STOCK_EDIT }, |
2801 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | 2343 { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0, |
2802 /* Show stuff that applies to IMs, hide stuff that applies to chats */ | 2344 "<StockItem>", GAIM_STOCK_BLOCK }, |
2803 | 2345 { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0, |
2804 /* Deal with menu items */ | 2346 "<StockItem>", GTK_STOCK_ADD }, |
2805 gtk_widget_show(gtkwin->menu.view_log); | 2347 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, |
2806 gtk_widget_show(gtkwin->menu.send_file); | 2348 "<StockItem>", GTK_STOCK_REMOVE }, |
2807 gtk_widget_show(gtkwin->menu.add_pounce); | 2349 |
2808 gtk_widget_show(gtkwin->menu.get_info); | 2350 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>" }, |
2809 gtk_widget_hide(gtkwin->menu.invite); | 2351 |
2810 gtk_widget_show(gtkwin->menu.alias); | 2352 { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, |
2811 gtk_widget_show(gtkwin->menu.block); | 2353 "<StockItem>", GAIM_STOCK_LINK }, |
2812 | 2354 { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, |
2813 if (gaim_find_buddy(account, gaim_conversation_get_name(conv)) == NULL) { | 2355 "<StockItem>", GAIM_STOCK_IMAGE }, |
2814 gtk_widget_show(gtkwin->menu.add); | 2356 |
2815 gtk_widget_hide(gtkwin->menu.remove); | 2357 { "/Conversation/sep4", NULL, NULL, 0, "<Separator>" }, |
2816 } else { | 2358 |
2817 gtk_widget_show(gtkwin->menu.remove); | 2359 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, |
2818 gtk_widget_hide(gtkwin->menu.add); | 2360 "<StockItem>", GTK_STOCK_CLOSE }, |
2819 } | 2361 |
2820 | 2362 /* Options */ |
2821 gtk_widget_show(gtkwin->menu.insert_link); | 2363 { N_("/_Options"), NULL, NULL, 0, "<Branch>" }, |
2822 gtk_widget_show(gtkwin->menu.insert_image); | 2364 { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>" }, |
2823 gtk_widget_show(gtkwin->menu.show_icon); | 2365 { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>" }, |
2824 } else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | 2366 { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>" }, |
2825 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ | 2367 { N_("/Options/Show Ti_mestamps"), "F2", menu_timestamps_cb, 0, "<CheckItem>" }, |
2826 | 2368 { N_("/Options/Show Buddy _Icon"), NULL, menu_buddyicon_cb, 0, "<CheckItem>" }, |
2827 /* Deal with menu items */ | 2369 }; |
2828 gtk_widget_show(gtkwin->menu.view_log); | 2370 |
2829 gtk_widget_hide(gtkwin->menu.send_file); | 2371 static const int menu_item_count = |
2830 gtk_widget_hide(gtkwin->menu.add_pounce); | 2372 sizeof(menu_items) / sizeof(*menu_items); |
2831 gtk_widget_hide(gtkwin->menu.get_info); | 2373 |
2832 gtk_widget_show(gtkwin->menu.invite); | 2374 static char * |
2833 gtk_widget_show(gtkwin->menu.alias); | 2375 item_factory_translate_func (const char *path, gpointer func_data) |
2834 gtk_widget_hide(gtkwin->menu.block); | 2376 { |
2835 gtk_widget_hide(gtkwin->menu.show_icon); | 2377 return _((char *)path); |
2836 | 2378 } |
2837 if (gaim_blist_find_chat(account, gaim_conversation_get_name(conv)) == NULL) { | 2379 |
2838 /* If the chat is NOT in the buddy list */ | 2380 static GtkWidget * |
2839 gtk_widget_show(gtkwin->menu.add); | 2381 setup_menubar(GaimGtkWindow *win) |
2840 gtk_widget_hide(gtkwin->menu.remove); | 2382 { |
2841 } else { | 2383 GtkAccelGroup *accel_group; |
2842 /* If the chat IS in the buddy list */ | 2384 |
2843 gtk_widget_hide(gtkwin->menu.add); | 2385 accel_group = gtk_accel_group_new (); |
2844 gtk_widget_show(gtkwin->menu.remove); | 2386 gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group); |
2845 } | 2387 g_object_unref(accel_group); |
2846 | 2388 |
2847 gtk_widget_show(gtkwin->menu.insert_link); | 2389 win->menu.item_factory = |
2848 gtk_widget_hide(gtkwin->menu.insert_image); | 2390 gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group); |
2849 } | 2391 |
2850 | 2392 gtk_item_factory_set_translate_func(win->menu.item_factory, |
2851 /* | 2393 item_factory_translate_func, |
2852 * Handle graying stuff out based on whether an account is connected | 2394 NULL, NULL); |
2853 * and what features that account supports. | 2395 |
2854 */ | 2396 gtk_item_factory_create_items(win->menu.item_factory, menu_item_count, |
2855 if ((gc != NULL) && | 2397 menu_items, win); |
2856 ( (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_CHAT) || | 2398 g_signal_connect(G_OBJECT(accel_group), "accel-changed", |
2857 !gaim_conv_chat_has_left(GAIM_CONV_CHAT(conv)) )) { | 2399 G_CALLBACK(gaim_gtk_save_accels_cb), NULL); |
2858 /* Account is online */ | 2400 |
2859 /* Deal with the toolbar */ | 2401 |
2860 if (conv->features & GAIM_CONNECTION_HTML) { | 2402 win->menu.menubar = |
2861 buttons = GTK_IMHTML_ALL; /* Everything on */ | 2403 gtk_item_factory_get_widget(win->menu.item_factory, "<main>"); |
2862 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) || | 2404 |
2863 conv->features & GAIM_CONNECTION_NO_IMAGES) | 2405 |
2864 buttons &= ~GTK_IMHTML_IMAGE; | 2406 win->menu.view_log = |
2865 if (conv->features & GAIM_CONNECTION_NO_BGCOLOR) | 2407 gtk_item_factory_get_widget(win->menu.item_factory, |
2866 buttons &= ~GTK_IMHTML_BACKCOLOR; | 2408 N_("/Conversation/View Log")); |
2867 if (conv->features & GAIM_CONNECTION_NO_FONTSIZE) { | 2409 |
2868 buttons &= ~GTK_IMHTML_GROW; | 2410 /* --- */ |
2869 buttons &= ~GTK_IMHTML_SHRINK; | 2411 |
2870 } | 2412 win->menu.send_file = |
2871 if (conv->features & GAIM_CONNECTION_NO_URLDESC) | 2413 gtk_item_factory_get_widget(win->menu.item_factory, |
2872 buttons &= ~GTK_IMHTML_LINKDESC; | 2414 N_("/Conversation/Send File...")); |
2873 } else { | 2415 |
2874 buttons = GTK_IMHTML_SMILEY; | 2416 win->menu.add_pounce = |
2875 } | 2417 gtk_item_factory_get_widget(win->menu.item_factory, |
2876 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); | 2418 N_("/Conversation/Add Buddy Pounce...")); |
2877 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), gaim_account_get_protocol_id(account)); | 2419 |
2878 | 2420 /* --- */ |
2879 /* Deal with menu items */ | 2421 |
2880 gtk_widget_set_sensitive(gtkwin->menu.view_log, TRUE); | 2422 win->menu.get_info = |
2881 gtk_widget_set_sensitive(gtkwin->menu.add_pounce, TRUE); | 2423 gtk_item_factory_get_widget(win->menu.item_factory, |
2882 gtk_widget_set_sensitive(gtkwin->menu.get_info, (prpl_info->get_info != NULL)); | 2424 N_("/Conversation/Get Info")); |
2883 gtk_widget_set_sensitive(gtkwin->menu.invite, (prpl_info->chat_invite != NULL)); | 2425 |
2884 gtk_widget_set_sensitive(gtkwin->menu.block, (prpl_info->add_deny != NULL)); | 2426 win->menu.invite = |
2885 gtk_widget_set_sensitive(gtkwin->menu.insert_link, (conv->features & GAIM_CONNECTION_HTML)); | 2427 gtk_item_factory_get_widget(win->menu.item_factory, |
2886 gtk_widget_set_sensitive(gtkwin->menu.insert_image, (prpl_info->options & OPT_PROTO_IM_IMAGE)); | 2428 N_("/Conversation/Invite...")); |
2887 | 2429 |
2888 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | 2430 /* --- */ |
2889 gtk_widget_set_sensitive(gtkwin->menu.add, (prpl_info->add_buddy != NULL)); | 2431 |
2890 gtk_widget_set_sensitive(gtkwin->menu.remove, (prpl_info->remove_buddy != NULL)); | 2432 win->menu.alias = |
2891 gtk_widget_set_sensitive(gtkwin->menu.send_file, | 2433 gtk_item_factory_get_widget(win->menu.item_factory, |
2892 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || | 2434 N_("/Conversation/Alias...")); |
2893 prpl_info->can_receive_file(gc, gaim_conversation_get_name(conv))))); | 2435 |
2894 gtk_widget_set_sensitive(gtkwin->menu.alias, | 2436 win->menu.block = |
2895 (gaim_find_buddy(account, gaim_conversation_get_name(conv)) != NULL)); | 2437 gtk_item_factory_get_widget(win->menu.item_factory, |
2896 } else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | 2438 N_("/Conversation/Block...")); |
2897 gtk_widget_set_sensitive(gtkwin->menu.add, (prpl_info->join_chat != NULL)); | 2439 |
2898 gtk_widget_set_sensitive(gtkwin->menu.remove, (prpl_info->join_chat != NULL)); | 2440 win->menu.add = |
2899 gtk_widget_set_sensitive(gtkwin->menu.alias, | 2441 gtk_item_factory_get_widget(win->menu.item_factory, |
2900 (gaim_blist_find_chat(account, gaim_conversation_get_name(conv)) != NULL)); | 2442 N_("/Conversation/Add...")); |
2901 } | 2443 |
2902 | 2444 win->menu.remove = |
2903 /* Deal with chat userlist buttons */ | 2445 gtk_item_factory_get_widget(win->menu.item_factory, |
2904 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) | 2446 N_("/Conversation/Remove...")); |
2905 { | 2447 |
2906 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_im, TRUE); | 2448 /* --- */ |
2907 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_ignore, TRUE); | 2449 |
2908 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_info, (prpl_info->get_info != NULL)); | 2450 win->menu.insert_link = |
2909 } | 2451 gtk_item_factory_get_widget(win->menu.item_factory, |
2910 } else { | 2452 N_("/Conversation/Insert Link...")); |
2911 /* Account is offline */ | 2453 |
2912 /* Or it's a chat that we've left. */ | 2454 win->menu.insert_image = |
2913 | 2455 gtk_item_factory_get_widget(win->menu.item_factory, |
2914 /* Then deal with menu items */ | 2456 N_("/Conversation/Insert Image...")); |
2915 gtk_widget_set_sensitive(gtkwin->menu.view_log, TRUE); | 2457 |
2916 gtk_widget_set_sensitive(gtkwin->menu.send_file, FALSE); | 2458 /* --- */ |
2917 gtk_widget_set_sensitive(gtkwin->menu.add_pounce, TRUE); | 2459 |
2918 gtk_widget_set_sensitive(gtkwin->menu.get_info, FALSE); | 2460 win->menu.logging = |
2919 gtk_widget_set_sensitive(gtkwin->menu.invite, FALSE); | 2461 gtk_item_factory_get_widget(win->menu.item_factory, |
2920 gtk_widget_set_sensitive(gtkwin->menu.alias, FALSE); | 2462 N_("/Options/Enable Logging")); |
2921 gtk_widget_set_sensitive(gtkwin->menu.block, FALSE); | 2463 win->menu.sounds = |
2922 gtk_widget_set_sensitive(gtkwin->menu.add, FALSE); | 2464 gtk_item_factory_get_widget(win->menu.item_factory, |
2923 gtk_widget_set_sensitive(gtkwin->menu.remove, FALSE); | 2465 N_("/Options/Enable Sounds")); |
2924 gtk_widget_set_sensitive(gtkwin->menu.insert_link, TRUE); | 2466 win->menu.show_formatting_toolbar = |
2925 gtk_widget_set_sensitive(gtkwin->menu.insert_image, FALSE); | 2467 gtk_item_factory_get_widget(win->menu.item_factory, |
2926 | 2468 N_("/Options/Show Formatting Toolbars")); |
2927 /* Deal with chat userlist buttons */ | 2469 win->menu.show_timestamps = |
2928 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) | 2470 gtk_item_factory_get_widget(win->menu.item_factory, |
2929 { | 2471 N_("/Options/Show Timestamps")); |
2930 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_im, FALSE); | 2472 win->menu.show_icon = |
2931 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_ignore, FALSE); | 2473 gtk_item_factory_get_widget(win->menu.item_factory, |
2932 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_info, FALSE); | 2474 N_("/Options/Show Buddy Icon")); |
2933 } | 2475 |
2934 } | 2476 generate_send_as_items(win, NULL); |
2935 | 2477 |
2936 /* | 2478 win->menu.tray = gaim_gtk_menu_tray_new(); |
2937 * Update the window's icon | 2479 gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar), |
2938 */ | 2480 win->menu.tray); |
2939 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) && | 2481 gtk_widget_show(win->menu.tray); |
2940 (gtkconv->u.im->anim)) | 2482 |
2941 { | 2483 gtk_widget_show(win->menu.menubar); |
2942 window_icon = | 2484 |
2943 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); | 2485 return win->menu.menubar; |
2944 g_object_ref(window_icon); | 2486 } |
2945 } else { | 2487 |
2946 window_icon = get_tab_icon(conv, FALSE); | |
2947 } | |
2948 gtk_window_set_icon(GTK_WINDOW(gtkwin->window), window_icon); | |
2949 if (window_icon != NULL) | |
2950 g_object_unref(G_OBJECT(window_icon)); | |
2951 } | |
2952 | |
2953 static void | |
2954 before_switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, | |
2955 gpointer user_data) | |
2956 { | |
2957 GaimConvWindow *win; | |
2958 GaimConversation *conv; | |
2959 GaimGtkConversation *gtkconv; | |
2960 | |
2961 win = (GaimConvWindow *)user_data; | |
2962 conv = gaim_conv_window_get_active_conversation(win); | |
2963 | |
2964 g_return_if_fail(conv != NULL); | |
2965 | |
2966 if (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_IM) | |
2967 return; | |
2968 | |
2969 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
2970 | |
2971 stop_anim(NULL, gtkconv); | |
2972 } | |
2973 | |
2974 static void | |
2975 switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, | |
2976 gpointer user_data) | |
2977 { | |
2978 GaimConvWindow *win; | |
2979 GaimConversation *conv; | |
2980 GaimGtkConversation *gtkconv; | |
2981 GaimGtkWindow *gtkwin; | |
2982 | |
2983 win = (GaimConvWindow *)user_data; | |
2984 gtkconv = gaim_gtk_get_gtkconv_at_index(win, page_num); | |
2985 conv = gtkconv->active_conv; | |
2986 | |
2987 g_return_if_fail(conv != NULL); | |
2988 | |
2989 gtkwin = GAIM_GTK_WINDOW(win); | |
2990 | |
2991 /* | |
2992 * Only set "unseen" to "none" if the window has focus | |
2993 */ | |
2994 if (gaim_conv_window_has_focus(win)) | |
2995 gaim_conversation_set_unseen(conv, GAIM_UNSEEN_NONE); | |
2996 | |
2997 /* Update the menubar */ | |
2998 gray_stuff_out(gtkconv); | |
2999 | |
3000 update_typing_icon(gtkconv); | |
3001 | |
3002 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.logging), | |
3003 gaim_conversation_is_logging(conv)); | |
3004 | |
3005 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.sounds), | |
3006 gtkconv->make_sound); | |
3007 | |
3008 gtk_check_menu_item_set_active( | |
3009 GTK_CHECK_MENU_ITEM(gtkwin->menu.show_formatting_toolbar), | |
3010 gaim_prefs_get_bool("/gaim/gtk/conversations/show_formatting_toolbar")); | |
3011 | |
3012 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.show_timestamps), | |
3013 gtkconv->show_timestamps); | |
3014 | |
3015 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | |
3016 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.show_icon), | |
3017 gtkconv->u.im->show_icon); | |
3018 /* | |
3019 * We pause icons when they are not visible. If this icon should | |
3020 * be animated then start it back up again. | |
3021 */ | |
3022 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) && | |
3023 (gtkconv->u.im->animate)) | |
3024 start_anim(NULL, gtkconv); | |
3025 | |
3026 gtk_window_set_title(GTK_WINDOW(gtkwin->window), | |
3027 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); | |
3028 } | |
3029 | 2488 |
3030 /************************************************************************** | 2489 /************************************************************************** |
3031 * Utility functions | 2490 * Utility functions |
3032 **************************************************************************/ | 2491 **************************************************************************/ |
3033 | 2492 |
3068 { | 2527 { |
3069 GaimGtkWindow *gtkwin; | 2528 GaimGtkWindow *gtkwin; |
3070 GaimConvIm *im = NULL; | 2529 GaimConvIm *im = NULL; |
3071 GaimConversation *conv = gtkconv->active_conv; | 2530 GaimConversation *conv = gtkconv->active_conv; |
3072 | 2531 |
3073 gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(conv)); | 2532 gtkwin = gtkconv->win; |
3074 | 2533 |
3075 if(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | 2534 if(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) |
3076 im = GAIM_CONV_IM(conv); | 2535 im = GAIM_CONV_IM(conv); |
3077 | 2536 |
3078 if(gtkwin->menu.typing_icon) { | 2537 if(gtkwin->menu.typing_icon) { |
3097 gtkwin->menu.typing_icon); | 2556 gtkwin->menu.typing_icon); |
3098 } | 2557 } |
3099 } | 2558 } |
3100 | 2559 |
3101 static gboolean | 2560 static gboolean |
3102 update_send_as_selection(GaimConvWindow *win) | 2561 update_send_as_selection(GaimGtkWindow *win) |
3103 { | 2562 { |
3104 GaimAccount *account; | 2563 GaimAccount *account; |
3105 GaimConversation *conv; | 2564 GaimConversation *conv; |
3106 GaimGtkWindow *gtkwin; | |
3107 GtkWidget *menu; | 2565 GtkWidget *menu; |
3108 GList *child; | 2566 GList *child; |
3109 | 2567 |
3110 if (g_list_find(gaim_get_windows(), win) == NULL) | 2568 /* what does this do again? */ |
2569 /* | |
2570 if (g_list_find(gaim_gtk_get_windows(), win) == NULL) | |
3111 return FALSE; | 2571 return FALSE; |
3112 | 2572 */ |
3113 conv = gaim_conv_window_get_active_conversation(win); | 2573 |
2574 conv = gaim_gtk_conv_window_get_active_conversation(win); | |
3114 | 2575 |
3115 if (conv == NULL) | 2576 if (conv == NULL) |
3116 return FALSE; | 2577 return FALSE; |
3117 | 2578 |
3118 account = gaim_conversation_get_account(conv); | 2579 account = gaim_conversation_get_account(conv); |
3119 gtkwin = GAIM_GTK_WINDOW(win); | 2580 |
3120 | 2581 if (win->menu.send_as == NULL) |
3121 if (gtkwin->menu.send_as == NULL) | |
3122 return FALSE; | 2582 return FALSE; |
3123 | 2583 |
3124 gtk_widget_show(gtkwin->menu.send_as); | 2584 gtk_widget_show(win->menu.send_as); |
3125 | 2585 |
3126 menu = gtk_menu_item_get_submenu( | 2586 menu = gtk_menu_item_get_submenu( |
3127 GTK_MENU_ITEM(gtkwin->menu.send_as)); | 2587 GTK_MENU_ITEM(win->menu.send_as)); |
3128 | 2588 |
3129 for (child = gtk_container_get_children(GTK_CONTAINER(menu)); | 2589 for (child = gtk_container_get_children(GTK_CONTAINER(menu)); |
3130 child != NULL; | 2590 child != NULL; |
3131 child = child->next) { | 2591 child = child->next) { |
3132 | 2592 |
3142 | 2602 |
3143 return FALSE; | 2603 return FALSE; |
3144 } | 2604 } |
3145 | 2605 |
3146 static void | 2606 static void |
3147 generate_send_as_items(GaimConvWindow *win, GaimConversation *deleted_conv) | 2607 generate_send_as_items(GaimGtkWindow *win, GaimConversation *deleted_conv) |
3148 { | 2608 { |
3149 GaimGtkWindow *gtkwin; | |
3150 GtkWidget *menu; | 2609 GtkWidget *menu; |
3151 GtkWidget *menuitem; | 2610 GtkWidget *menuitem; |
3152 GList *gcs; | 2611 GList *gcs; |
3153 GList *convs; | 2612 GList *convs; |
3154 GSList *group = NULL; | 2613 GSList *group = NULL; |
3155 gboolean first_offline = TRUE; | 2614 gboolean first_offline = TRUE; |
3156 gboolean found_online = FALSE; | 2615 gboolean found_online = FALSE; |
3157 GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | 2616 GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
3158 | 2617 |
3159 gtkwin = GAIM_GTK_WINDOW(win); | 2618 if (win->menu.send_as != NULL) |
3160 | 2619 gtk_widget_destroy(win->menu.send_as); |
3161 if (gtkwin->menu.send_as != NULL) | |
3162 gtk_widget_destroy(gtkwin->menu.send_as); | |
3163 | 2620 |
3164 /* See if we have > 1 connection active. */ | 2621 /* See if we have > 1 connection active. */ |
3165 if (g_list_length(gaim_connections_get_all()) < 2) { | 2622 if (g_list_length(gaim_connections_get_all()) < 2) { |
3166 /* Now make sure we don't have any Offline entries. */ | 2623 /* Now make sure we don't have any Offline entries. */ |
3167 gboolean found_offline = FALSE; | 2624 gboolean found_offline = FALSE; |
3168 | 2625 |
3169 for (convs = gaim_get_conversations(); | 2626 for (convs = gaim_get_conversations(); |
3170 convs != NULL; | 2627 convs != NULL; |
3171 convs = convs->next) { | 2628 convs = convs->next) { |
3172 | 2629 |
3173 GaimConversation *conv; | 2630 GaimConversation *conv; |
3174 GaimAccount *account; | 2631 GaimAccount *account; |
3175 | 2632 |
3176 conv = (GaimConversation *)convs->data; | 2633 conv = (GaimConversation *)convs->data; |
3181 break; | 2638 break; |
3182 } | 2639 } |
3183 } | 2640 } |
3184 | 2641 |
3185 if (!found_offline) { | 2642 if (!found_offline) { |
3186 gtkwin->menu.send_as = NULL; | 2643 win->menu.send_as = NULL; |
3187 return; | 2644 return; |
3188 } | 2645 } |
3189 } | 2646 } |
3190 | 2647 |
3191 /* Build the Send As menu */ | 2648 /* Build the Send As menu */ |
3192 gtkwin->menu.send_as = gtk_menu_item_new_with_mnemonic(_("_Send As")); | 2649 win->menu.send_as = gtk_menu_item_new_with_mnemonic(_("_Send As")); |
3193 gtk_widget_show(gtkwin->menu.send_as); | 2650 gtk_widget_show(win->menu.send_as); |
3194 | 2651 |
3195 menu = gtk_menu_new(); | 2652 menu = gtk_menu_new(); |
3196 gtk_menu_shell_insert(GTK_MENU_SHELL(gtkwin->menu.menubar), | 2653 gtk_menu_shell_insert(GTK_MENU_SHELL(win->menu.menubar), |
3197 gtkwin->menu.send_as, 2); | 2654 win->menu.send_as, 2); |
3198 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtkwin->menu.send_as), menu); | 2655 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_as), menu); |
3199 | 2656 |
3200 gtk_widget_show(menu); | 2657 gtk_widget_show(menu); |
3201 | 2658 |
3202 /* Fill it with entries. */ | 2659 /* Fill it with entries. */ |
3203 for (gcs = gaim_connections_get_all(); gcs != NULL; gcs = gcs->next) { | 2660 for (gcs = gaim_connections_get_all(); gcs != NULL; gcs = gcs->next) { |
3346 } | 2803 } |
3347 } | 2804 } |
3348 | 2805 |
3349 g_object_unref(sg); | 2806 g_object_unref(sg); |
3350 | 2807 |
3351 gtk_widget_show(gtkwin->menu.send_as); | 2808 gtk_widget_show(win->menu.send_as); |
3352 update_send_as_selection(win); | 2809 update_send_as_selection(win); |
3353 } | 2810 } |
3354 | 2811 |
3355 static GList * | 2812 static GList * |
3356 generate_invite_user_names(GaimConnection *gc) | 2813 generate_invite_user_names(GaimConnection *gc) |
3687 | 3144 |
3688 g_free(entered); | 3145 g_free(entered); |
3689 g_free(partial); | 3146 g_free(partial); |
3690 | 3147 |
3691 return TRUE; | 3148 return TRUE; |
3692 } | |
3693 | |
3694 static GtkItemFactoryEntry menu_items[] = | |
3695 { | |
3696 /* Conversation menu */ | |
3697 { N_("/_Conversation"), NULL, NULL, 0, "<Branch>" }, | |
3698 | |
3699 { N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb, | |
3700 0, "<StockItem>", GAIM_STOCK_IM }, | |
3701 | |
3702 { "/Conversation/sep0", NULL, NULL, 0, "<Separator>" }, | |
3703 | |
3704 { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, | |
3705 "<StockItem>", GTK_STOCK_FIND }, | |
3706 { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, NULL }, | |
3707 { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0, | |
3708 "<StockItem>", GTK_STOCK_SAVE_AS }, | |
3709 { N_("/Conversation/Clear"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR }, | |
3710 | |
3711 { "/Conversation/sep1", NULL, NULL, 0, "<Separator>" }, | |
3712 | |
3713 { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, | |
3714 { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, | |
3715 0, NULL }, | |
3716 { N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0, | |
3717 "<StockItem>", GAIM_STOCK_INFO }, | |
3718 { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, | |
3719 "<StockItem>", GAIM_STOCK_INVITE }, | |
3720 | |
3721 { "/Conversation/sep2", NULL, NULL, 0, "<Separator>" }, | |
3722 | |
3723 { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0, | |
3724 "<StockItem>", GAIM_STOCK_EDIT }, | |
3725 { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0, | |
3726 "<StockItem>", GAIM_STOCK_BLOCK }, | |
3727 { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0, | |
3728 "<StockItem>", GTK_STOCK_ADD }, | |
3729 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, | |
3730 "<StockItem>", GTK_STOCK_REMOVE }, | |
3731 | |
3732 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>" }, | |
3733 | |
3734 { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, | |
3735 "<StockItem>", GAIM_STOCK_LINK }, | |
3736 { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, | |
3737 "<StockItem>", GAIM_STOCK_IMAGE }, | |
3738 | |
3739 { "/Conversation/sep4", NULL, NULL, 0, "<Separator>" }, | |
3740 | |
3741 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, | |
3742 "<StockItem>", GTK_STOCK_CLOSE }, | |
3743 | |
3744 /* Options */ | |
3745 { N_("/_Options"), NULL, NULL, 0, "<Branch>" }, | |
3746 { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>" }, | |
3747 { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>" }, | |
3748 { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>" }, | |
3749 { N_("/Options/Show Ti_mestamps"), "F2", menu_timestamps_cb, 0, "<CheckItem>" }, | |
3750 { N_("/Options/Show Buddy _Icon"), NULL, menu_buddyicon_cb, 0, "<CheckItem>" }, | |
3751 }; | |
3752 | |
3753 static const int menu_item_count = | |
3754 sizeof(menu_items) / sizeof(*menu_items); | |
3755 | |
3756 static char * | |
3757 item_factory_translate_func (const char *path, gpointer func_data) | |
3758 { | |
3759 return _((char *)path); | |
3760 } | |
3761 | |
3762 static GtkWidget * | |
3763 setup_menubar(GaimConvWindow *win) | |
3764 { | |
3765 GaimGtkWindow *gtkwin; | |
3766 GtkAccelGroup *accel_group; | |
3767 | |
3768 gtkwin = GAIM_GTK_WINDOW(win); | |
3769 | |
3770 accel_group = gtk_accel_group_new (); | |
3771 gtk_window_add_accel_group (GTK_WINDOW (gtkwin->window), accel_group); | |
3772 g_object_unref (accel_group); | |
3773 | |
3774 gtkwin->menu.item_factory = | |
3775 gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group); | |
3776 | |
3777 gtk_item_factory_set_translate_func(gtkwin->menu.item_factory, | |
3778 item_factory_translate_func, | |
3779 NULL, NULL); | |
3780 | |
3781 gtk_item_factory_create_items(gtkwin->menu.item_factory, menu_item_count, | |
3782 menu_items, win); | |
3783 g_signal_connect(G_OBJECT(accel_group), "accel-changed", | |
3784 G_CALLBACK(gaim_gtk_save_accels_cb), NULL); | |
3785 | |
3786 | |
3787 gtkwin->menu.menubar = | |
3788 gtk_item_factory_get_widget(gtkwin->menu.item_factory, "<main>"); | |
3789 | |
3790 | |
3791 gtkwin->menu.view_log = | |
3792 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3793 N_("/Conversation/View Log")); | |
3794 | |
3795 /* --- */ | |
3796 | |
3797 gtkwin->menu.send_file = | |
3798 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3799 N_("/Conversation/Send File...")); | |
3800 | |
3801 gtkwin->menu.add_pounce = | |
3802 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3803 N_("/Conversation/Add Buddy Pounce...")); | |
3804 | |
3805 /* --- */ | |
3806 | |
3807 gtkwin->menu.get_info = | |
3808 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3809 N_("/Conversation/Get Info")); | |
3810 | |
3811 gtkwin->menu.invite = | |
3812 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3813 N_("/Conversation/Invite...")); | |
3814 | |
3815 /* --- */ | |
3816 | |
3817 gtkwin->menu.alias = | |
3818 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3819 N_("/Conversation/Alias...")); | |
3820 | |
3821 gtkwin->menu.block = | |
3822 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3823 N_("/Conversation/Block...")); | |
3824 | |
3825 gtkwin->menu.add = | |
3826 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3827 N_("/Conversation/Add...")); | |
3828 | |
3829 gtkwin->menu.remove = | |
3830 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3831 N_("/Conversation/Remove...")); | |
3832 | |
3833 /* --- */ | |
3834 | |
3835 gtkwin->menu.insert_link = | |
3836 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3837 N_("/Conversation/Insert Link...")); | |
3838 | |
3839 gtkwin->menu.insert_image = | |
3840 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3841 N_("/Conversation/Insert Image...")); | |
3842 | |
3843 /* --- */ | |
3844 | |
3845 gtkwin->menu.logging = | |
3846 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3847 N_("/Options/Enable Logging")); | |
3848 gtkwin->menu.sounds = | |
3849 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3850 N_("/Options/Enable Sounds")); | |
3851 gtkwin->menu.show_formatting_toolbar = | |
3852 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3853 N_("/Options/Show Formatting Toolbars")); | |
3854 gtkwin->menu.show_timestamps = | |
3855 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3856 N_("/Options/Show Timestamps")); | |
3857 gtkwin->menu.show_icon = | |
3858 gtk_item_factory_get_widget(gtkwin->menu.item_factory, | |
3859 N_("/Options/Show Buddy Icon")); | |
3860 | |
3861 generate_send_as_items(win, NULL); | |
3862 | |
3863 gtkwin->menu.tray = gaim_gtk_menu_tray_new(); | |
3864 gtk_menu_shell_append(GTK_MENU_SHELL(gtkwin->menu.menubar), | |
3865 gtkwin->menu.tray); | |
3866 gtk_widget_show(gtkwin->menu.tray); | |
3867 | |
3868 gtk_widget_show(gtkwin->menu.menubar); | |
3869 | |
3870 return gtkwin->menu.menubar; | |
3871 } | 3149 } |
3872 | 3150 |
3873 static void topic_callback(GtkWidget *w, GaimGtkConversation *gtkconv) | 3151 static void topic_callback(GtkWidget *w, GaimGtkConversation *gtkconv) |
3874 { | 3152 { |
3875 GaimPluginProtocolInfo *prpl_info = NULL; | 3153 GaimPluginProtocolInfo *prpl_info = NULL; |
4436 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | 3714 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, |
4437 GtkSelectionData *sd, guint info, guint t, | 3715 GtkSelectionData *sd, guint info, guint t, |
4438 GaimGtkConversation *gtkconv) | 3716 GaimGtkConversation *gtkconv) |
4439 { | 3717 { |
4440 GaimConversation *conv = gtkconv->active_conv; | 3718 GaimConversation *conv = gtkconv->active_conv; |
4441 GaimConvWindow *win = conv->window; | 3719 GaimGtkWindow *win = gtkconv->win; |
4442 GaimConversation *c; | 3720 GaimConversation *c; |
4443 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) | 3721 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) |
4444 { | 3722 { |
4445 GaimBlistNode *n = NULL; | 3723 GaimBlistNode *n = NULL; |
4446 GaimBuddy *b; | 3724 GaimBuddy *b; |
3725 GaimGtkConversation *gtkconv = NULL; | |
4447 | 3726 |
4448 memcpy(&n, sd->data, sizeof(n)); | 3727 memcpy(&n, sd->data, sizeof(n)); |
4449 | 3728 |
4450 if (GAIM_BLIST_NODE_IS_CONTACT(n)) | 3729 if (GAIM_BLIST_NODE_IS_CONTACT(n)) |
4451 b = gaim_contact_get_priority_buddy((GaimContact*)n); | 3730 b = gaim_contact_get_priority_buddy((GaimContact*)n); |
4459 * just move the conv to this window. Otherwise, create a new | 3738 * just move the conv to this window. Otherwise, create a new |
4460 * conv and add it to this window. | 3739 * conv and add it to this window. |
4461 */ | 3740 */ |
4462 c = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, b->name, b->account); | 3741 c = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, b->name, b->account); |
4463 if (c != NULL) { | 3742 if (c != NULL) { |
4464 GaimConvWindow *oldwin; | 3743 GaimGtkWindow *oldwin; |
4465 oldwin = gaim_conversation_get_window(c); | 3744 gtkconv = GAIM_GTK_CONVERSATION(c); |
3745 oldwin = gtkconv->win; | |
4466 if (oldwin != win) { | 3746 if (oldwin != win) { |
4467 gaim_conv_window_remove_conversation(oldwin, c); | 3747 gaim_gtk_conv_window_remove_gtkconv(oldwin, gtkconv); |
4468 gaim_conv_window_add_conversation(win, c); | 3748 gaim_gtk_conv_window_add_gtkconv(win, gtkconv); |
4469 } | 3749 } |
4470 } else { | 3750 } else { |
4471 c = gaim_conversation_new(GAIM_CONV_TYPE_IM, b->account, b->name); | 3751 c = gaim_conversation_new(GAIM_CONV_TYPE_IM, b->account, b->name); |
4472 gaim_conv_window_add_conversation(win, c); | 3752 gtkconv = GAIM_GTK_CONVERSATION(c); |
3753 gaim_gtk_conv_window_add_gtkconv(win, gtkconv); | |
4473 } | 3754 } |
4474 | 3755 |
4475 /* Make this conversation the active conversation */ | 3756 /* Make this conversation the active conversation */ |
4476 gaim_conv_window_switch_conversation(win, c); | 3757 gaim_gtk_conv_window_switch_gtkconv(win, gtkconv); |
4477 | 3758 |
4478 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | 3759 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); |
4479 } | 3760 } |
4480 else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE)) | 3761 else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE)) |
4481 { | 3762 { |
4482 char *protocol = NULL; | 3763 char *protocol = NULL; |
4483 char *username = NULL; | 3764 char *username = NULL; |
4484 GaimAccount *account; | 3765 GaimAccount *account; |
3766 GaimGtkConversation *gtkconv; | |
4485 | 3767 |
4486 if (gaim_gtk_parse_x_im_contact((const char *)sd->data, FALSE, &account, | 3768 if (gaim_gtk_parse_x_im_contact((const char *)sd->data, FALSE, &account, |
4487 &protocol, &username, NULL)) | 3769 &protocol, &username, NULL)) |
4488 { | 3770 { |
4489 if (account == NULL) | 3771 if (account == NULL) |
4493 "can add that buddy."), NULL); | 3775 "can add that buddy."), NULL); |
4494 } | 3776 } |
4495 else | 3777 else |
4496 { | 3778 { |
4497 c = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, username); | 3779 c = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, username); |
4498 gaim_conv_window_add_conversation(win, c); | 3780 gtkconv = GAIM_GTK_CONVERSATION(c); |
3781 gaim_gtk_conv_window_add_gtkconv(win, gtkconv); | |
4499 } | 3782 } |
4500 } | 3783 } |
4501 | 3784 |
4502 if (username != NULL) g_free(username); | 3785 if (username != NULL) g_free(username); |
4503 if (protocol != NULL) g_free(protocol); | 3786 if (protocol != NULL) g_free(protocol); |
4511 } | 3794 } |
4512 else | 3795 else |
4513 gtk_drag_finish(dc, FALSE, FALSE, t); | 3796 gtk_drag_finish(dc, FALSE, FALSE, t); |
4514 } | 3797 } |
4515 | 3798 |
4516 /************************************************************************** | |
4517 * GTK+ window ops | |
4518 **************************************************************************/ | |
4519 static void | |
4520 gaim_gtk_new_window(GaimConvWindow *win) | |
4521 { | |
4522 GaimGtkWindow *gtkwin; | |
4523 GtkPositionType pos; | |
4524 GtkWidget *testidea; | |
4525 GtkWidget *menubar; | |
4526 | |
4527 gtkwin = g_malloc0(sizeof(GaimGtkWindow)); | |
4528 | |
4529 win->ui_data = gtkwin; | |
4530 | |
4531 /* Create the window. */ | |
4532 gtkwin->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
4533 gtk_window_set_role(GTK_WINDOW(gtkwin->window), "conversation"); | |
4534 gtk_window_set_resizable(GTK_WINDOW(gtkwin->window), TRUE); | |
4535 gtk_container_set_border_width(GTK_CONTAINER(gtkwin->window), 0); | |
4536 GTK_WINDOW(gtkwin->window)->allow_shrink = TRUE; | |
4537 | |
4538 g_signal_connect(G_OBJECT(gtkwin->window), "delete_event", | |
4539 G_CALLBACK(close_win_cb), win); | |
4540 | |
4541 g_signal_connect(G_OBJECT(gtkwin->window), "focus_in_event", | |
4542 G_CALLBACK(focus_win_cb), win); | |
4543 | |
4544 /* Create the notebook. */ | |
4545 gtkwin->notebook = gtk_notebook_new(); | |
4546 | |
4547 pos = gaim_prefs_get_int("/gaim/gtk/conversations/tab_side"); | |
4548 | |
4549 #if 0 | |
4550 gtk_notebook_set_tab_hborder(GTK_NOTEBOOK(gtkwin->notebook), 0); | |
4551 gtk_notebook_set_tab_vborder(GTK_NOTEBOOK(gtkwin->notebook), 0); | |
4552 #endif | |
4553 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkwin->notebook), pos); | |
4554 gtk_notebook_set_scrollable(GTK_NOTEBOOK(gtkwin->notebook), TRUE); | |
4555 gtk_notebook_popup_enable(GTK_NOTEBOOK(gtkwin->notebook)); | |
4556 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkwin->notebook), FALSE); | |
4557 gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkwin->notebook), FALSE); | |
4558 | |
4559 gtk_widget_show(gtkwin->notebook); | |
4560 | |
4561 g_signal_connect(G_OBJECT(gtkwin->notebook), "switch_page", | |
4562 G_CALLBACK(before_switch_conv_cb), win); | |
4563 g_signal_connect_after(G_OBJECT(gtkwin->notebook), "switch_page", | |
4564 G_CALLBACK(switch_conv_cb), win); | |
4565 | |
4566 /* Setup the tab drag and drop signals. */ | |
4567 gtk_widget_add_events(gtkwin->notebook, | |
4568 GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); | |
4569 g_signal_connect(G_OBJECT(gtkwin->notebook), "button_press_event", | |
4570 G_CALLBACK(notebook_press_cb), win); | |
4571 g_signal_connect(G_OBJECT(gtkwin->notebook), "button_release_event", | |
4572 G_CALLBACK(notebook_release_cb), win); | |
4573 | |
4574 testidea = gtk_vbox_new(FALSE, 0); | |
4575 | |
4576 /* Setup the menubar. */ | |
4577 menubar = setup_menubar(win); | |
4578 gtk_box_pack_start(GTK_BOX(testidea), menubar, FALSE, TRUE, 0); | |
4579 | |
4580 gtk_box_pack_start(GTK_BOX(testidea), gtkwin->notebook, TRUE, TRUE, 0); | |
4581 | |
4582 gtk_container_add(GTK_CONTAINER(gtkwin->window), testidea); | |
4583 | |
4584 gtk_widget_show(testidea); | |
4585 } | |
4586 | |
4587 static void | |
4588 gaim_gtk_destroy_window(GaimConvWindow *win) | |
4589 { | |
4590 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win); | |
4591 | |
4592 gtk_widget_destroy(gtkwin->window); | |
4593 | |
4594 g_object_unref(G_OBJECT(gtkwin->menu.item_factory)); | |
4595 | |
4596 g_free(gtkwin); | |
4597 win->ui_data = NULL; | |
4598 } | |
4599 | |
4600 static void | |
4601 gaim_gtk_show(GaimConvWindow *win) | |
4602 { | |
4603 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win); | |
4604 | |
4605 gtk_widget_show(gtkwin->window); | |
4606 } | |
4607 | |
4608 static void | |
4609 gaim_gtk_hide(GaimConvWindow *win) | |
4610 { | |
4611 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win); | |
4612 | |
4613 gtk_widget_hide(gtkwin->window); | |
4614 } | |
4615 | |
4616 static void | |
4617 gaim_gtk_raise(GaimConvWindow *win) | |
4618 { | |
4619 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win); | |
4620 | |
4621 gtk_widget_show(gtkwin->window); | |
4622 gtk_window_deiconify(GTK_WINDOW(gtkwin->window)); | |
4623 gdk_window_raise(gtkwin->window->window); | |
4624 } | |
4625 | |
4626 static void | |
4627 gaim_gtk_switch_conversation(GaimConvWindow *win, GaimConversation *conv) | |
4628 { | |
4629 GaimGtkWindow *gtkwin; | |
4630 GaimGtkConversation *gtkconv = conv->ui_data; | |
4631 | |
4632 gtkwin = GAIM_GTK_WINDOW(win); | |
4633 | |
4634 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), gtk_notebook_page_num(GTK_NOTEBOOK(gtkwin->notebook), gtkconv->tab_cont)); | |
4635 } | |
4636 | 3799 |
4637 static const GtkTargetEntry te[] = | 3800 static const GtkTargetEntry te[] = |
4638 { | 3801 { |
4639 GTK_IMHTML_DND_TARGETS, | 3802 GTK_IMHTML_DND_TARGETS, |
4640 {"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, GTK_IMHTML_DRAG_NUM}, | 3803 {"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, GTK_IMHTML_DRAG_NUM}, |
4664 } | 3827 } |
4665 | 3828 |
4666 return NULL; | 3829 return NULL; |
4667 } | 3830 } |
4668 | 3831 |
4669 static void | 3832 /************************************************************************** |
4670 gaim_gtk_add_conversation(GaimConvWindow *win, GaimConversation *conv) | 3833 * Conversation UI operations |
4671 { | 3834 **************************************************************************/ |
4672 GaimGtkWindow *gtkwin; | 3835 void |
4673 GaimGtkConversation *gtkconv, *focus_gtkconv; | 3836 gaim_gtkconv_new(GaimConversation *conv) |
4674 GaimConversation *focus_conv; | 3837 { |
3838 GaimGtkConversation *gtkconv; | |
3839 GaimConversationType conv_type = gaim_conversation_get_type(conv); | |
4675 GtkWidget *pane = NULL; | 3840 GtkWidget *pane = NULL; |
4676 GtkWidget *tab_cont; | 3841 GtkWidget *tab_cont; |
4677 GtkWidget *tabby, *menu_tabby; | 3842 |
4678 GtkWidget *close_image; | 3843 if (conv_type == GAIM_CONV_TYPE_IM && (gtkconv = gaim_gtk_conv_find_gtkconv(conv))) { |
4679 gboolean new_ui; | |
4680 GaimConversationType conv_type; | |
4681 const char *name; | |
4682 const gchar *tmp_lab; | |
4683 gint close_button_width, close_button_height, focus_width, focus_pad; | |
4684 | |
4685 name = gaim_conversation_get_name(conv); | |
4686 conv_type = gaim_conversation_get_type(conv); | |
4687 gtkwin = GAIM_GTK_WINDOW(win); | |
4688 | |
4689 if (conv->ui_data != NULL) { | |
4690 gtkconv = (GaimGtkConversation *)conv->ui_data; | |
4691 | |
4692 tab_cont = gtkconv->tab_cont; | |
4693 | |
4694 new_ui = FALSE; | |
4695 } else if (conv_type == GAIM_CONV_TYPE_IM && (gtkconv = gaim_gtk_conv_find_gtkconv(conv))) { | |
4696 conv->ui_data = gtkconv; | 3844 conv->ui_data = gtkconv; |
4697 gtkconv->active_conv = conv; | 3845 gtkconv->active_conv = conv; |
4698 if (!g_list_find(gtkconv->convs, conv)) | 3846 if (!g_list_find(gtkconv->convs, conv)) |
4699 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); | 3847 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); |
4700 return; | 3848 return; |
4701 } else { | 3849 } |
4702 gtkconv = g_malloc0(sizeof(GaimGtkConversation)); | 3850 |
4703 conv->ui_data = gtkconv; | 3851 gtkconv = g_new0(GaimGtkConversation, 1); |
4704 gtkconv->active_conv = conv; | 3852 conv->ui_data = gtkconv; |
4705 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); | 3853 gtkconv->active_conv = conv; |
4706 | 3854 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); |
4707 /* Setup some initial variables. */ | 3855 |
4708 gtkconv->sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | 3856 /* Setup some initial variables. */ |
4709 gtkconv->tooltips = gtk_tooltips_new(); | 3857 gtkconv->sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); |
4710 | 3858 gtkconv->tooltips = gtk_tooltips_new(); |
4711 if (conv_type == GAIM_CONV_TYPE_IM) { | 3859 |
4712 gtkconv->u.im = g_malloc0(sizeof(GaimGtkImPane)); | 3860 if (conv_type == GAIM_CONV_TYPE_IM) { |
4713 gtkconv->u.im->a_virgin = TRUE; | 3861 gtkconv->u.im = g_malloc0(sizeof(GaimGtkImPane)); |
4714 | 3862 gtkconv->u.im->a_virgin = TRUE; |
4715 pane = setup_im_pane(gtkconv); | 3863 |
4716 } | 3864 pane = setup_im_pane(gtkconv); |
4717 else if (conv_type == GAIM_CONV_TYPE_CHAT) { | 3865 } else if (conv_type == GAIM_CONV_TYPE_CHAT) { |
4718 gtkconv->u.chat = g_malloc0(sizeof(GaimGtkChatPane)); | 3866 gtkconv->u.chat = g_malloc0(sizeof(GaimGtkChatPane)); |
4719 | 3867 pane = setup_chat_pane(gtkconv); |
4720 pane = setup_chat_pane(gtkconv); | 3868 } |
4721 } | 3869 |
4722 | 3870 if (pane == NULL) { |
4723 if (pane == NULL) { | 3871 if (conv_type == GAIM_CONV_TYPE_CHAT) |
4724 if (conv_type == GAIM_CONV_TYPE_CHAT) g_free(gtkconv->u.chat); | 3872 g_free(gtkconv->u.chat); |
4725 else if (conv_type == GAIM_CONV_TYPE_IM) g_free(gtkconv->u.im); | 3873 else if (conv_type == GAIM_CONV_TYPE_IM) |
4726 | 3874 g_free(gtkconv->u.im); |
4727 g_free(gtkconv); | 3875 |
4728 conv->ui_data = NULL; | 3876 g_free(gtkconv); |
4729 | 3877 conv->ui_data = NULL; |
4730 return; | 3878 return; |
4731 } | 3879 } |
4732 | 3880 |
4733 /* Setup drag-and-drop */ | 3881 /* Setup drag-and-drop */ |
4734 gtk_drag_dest_set(pane, | 3882 gtk_drag_dest_set(pane, |
4735 GTK_DEST_DEFAULT_MOTION | | 3883 GTK_DEST_DEFAULT_MOTION | |
4736 GTK_DEST_DEFAULT_DROP, | 3884 GTK_DEST_DEFAULT_DROP, |
4737 te, sizeof(te) / sizeof(GtkTargetEntry), | 3885 te, sizeof(te) / sizeof(GtkTargetEntry), |
4738 GDK_ACTION_COPY); | 3886 GDK_ACTION_COPY); |
4739 gtk_drag_dest_set(pane, | 3887 gtk_drag_dest_set(pane, |
4740 GTK_DEST_DEFAULT_MOTION | | 3888 GTK_DEST_DEFAULT_MOTION | |
4741 GTK_DEST_DEFAULT_DROP, | 3889 GTK_DEST_DEFAULT_DROP, |
4742 te, sizeof(te) / sizeof(GtkTargetEntry), | 3890 te, sizeof(te) / sizeof(GtkTargetEntry), |
4743 GDK_ACTION_COPY); | 3891 GDK_ACTION_COPY); |
4744 gtk_drag_dest_set(gtkconv->imhtml, 0, | 3892 gtk_drag_dest_set(gtkconv->imhtml, 0, |
4745 te, sizeof(te) / sizeof(GtkTargetEntry), | 3893 te, sizeof(te) / sizeof(GtkTargetEntry), |
4746 GDK_ACTION_COPY); | 3894 GDK_ACTION_COPY); |
4747 | 3895 |
4748 gtk_drag_dest_set(gtkconv->entry, 0, | 3896 gtk_drag_dest_set(gtkconv->entry, 0, |
4749 te, sizeof(te) / sizeof(GtkTargetEntry), | 3897 te, sizeof(te) / sizeof(GtkTargetEntry), |
4750 GDK_ACTION_COPY); | 3898 GDK_ACTION_COPY); |
4751 | 3899 |
4752 g_signal_connect(G_OBJECT(pane), "drag_data_received", | 3900 g_signal_connect(G_OBJECT(pane), "drag_data_received", |
4753 G_CALLBACK(conv_dnd_recv), gtkconv); | 3901 G_CALLBACK(conv_dnd_recv), gtkconv); |
4754 g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", | 3902 g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", |
4755 G_CALLBACK(conv_dnd_recv), gtkconv); | 3903 G_CALLBACK(conv_dnd_recv), gtkconv); |
4756 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", | 3904 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", |
4757 G_CALLBACK(conv_dnd_recv), gtkconv); | 3905 G_CALLBACK(conv_dnd_recv), gtkconv); |
4758 | 3906 |
4759 /* Setup the container for the tab. */ | 3907 /* Setup the container for the tab. */ |
4760 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); | 3908 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
4761 g_object_set_data(G_OBJECT(tab_cont), "GaimGtkConversation", gtkconv); | 3909 g_object_set_data(G_OBJECT(tab_cont), "GaimGtkConversation", gtkconv); |
4762 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), GAIM_HIG_BOX_SPACE); | 3910 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), GAIM_HIG_BOX_SPACE); |
4763 gtk_container_add(GTK_CONTAINER(tab_cont), pane); | 3911 gtk_container_add(GTK_CONTAINER(tab_cont), pane); |
4764 gtk_widget_show(pane); | 3912 gtk_widget_show(pane); |
4765 | 3913 |
4766 new_ui = TRUE; | 3914 gtkconv->make_sound = TRUE; |
4767 | 3915 |
4768 gtkconv->make_sound = TRUE; | 3916 if (gaim_prefs_get_bool("/gaim/gtk/conversations/show_formatting_toolbar")) |
4769 | 3917 gtk_widget_show(gtkconv->toolbar); |
4770 if (gaim_prefs_get_bool("/gaim/gtk/conversations/show_formatting_toolbar")) | |
4771 gtk_widget_show(gtkconv->toolbar); | |
4772 else | |
4773 gtk_widget_hide(gtkconv->toolbar); | |
4774 | |
4775 gtkconv->show_timestamps = TRUE; | |
4776 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); | |
4777 | |
4778 g_signal_connect_swapped(G_OBJECT(pane), "focus", | |
4779 G_CALLBACK(gtk_widget_grab_focus), | |
4780 gtkconv->entry); | |
4781 } | |
4782 | |
4783 gtkconv->tabby = tabby = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
4784 gtkconv->menu_tabby = menu_tabby = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
4785 | |
4786 /* Close button. */ | |
4787 gtkconv->close = gtk_button_new(); | |
4788 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &close_button_width, &close_button_height); | |
4789 if (gtk_check_version(2, 4, 2) == NULL) | |
4790 { | |
4791 /* Need to account for extra padding around the gtkbutton */ | |
4792 gtk_widget_style_get(GTK_WIDGET(gtkconv->close), | |
4793 "focus-line-width", &focus_width, | |
4794 "focus-padding", &focus_pad, | |
4795 NULL); | |
4796 close_button_width += (focus_width + focus_pad) * 2; | |
4797 close_button_height += (focus_width + focus_pad) * 2; | |
4798 } | |
4799 gtk_widget_set_size_request(GTK_WIDGET(gtkconv->close), | |
4800 close_button_width, close_button_height); | |
4801 | |
4802 gtk_button_set_relief(GTK_BUTTON(gtkconv->close), GTK_RELIEF_NONE); | |
4803 close_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); | |
4804 gtk_widget_show(close_image); | |
4805 gtk_container_add(GTK_CONTAINER(gtkconv->close), close_image); | |
4806 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, | |
4807 _("Close conversation"), NULL); | |
4808 | |
4809 g_signal_connect(G_OBJECT(gtkconv->close), "clicked", | |
4810 G_CALLBACK(close_conv_cb), gtkconv); | |
4811 | |
4812 /* | |
4813 * I love Galeon. They have a fix for that stupid annoying visible | |
4814 * border bug. I love you guys! -- ChipX86 | |
4815 */ | |
4816 g_signal_connect(G_OBJECT(gtkconv->close), "state_changed", | |
4817 G_CALLBACK(tab_close_button_state_changed_cb), NULL); | |
4818 | |
4819 /* Status icon. */ | |
4820 gtkconv->icon = gtk_image_new(); | |
4821 gtkconv->menu_icon = gtk_image_new(); | |
4822 update_tab_icon(conv); | |
4823 | |
4824 /* Tab label. */ | |
4825 gtkconv->tab_label = gtk_label_new(tmp_lab = gaim_conversation_get_title(conv)); | |
4826 #if GTK_CHECK_VERSION(2,6,0) | |
4827 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); | |
4828 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); | |
4829 #endif | |
4830 gtkconv->menu_label = gtk_label_new(gaim_conversation_get_title(conv)); | |
4831 #if 0 | |
4832 gtk_misc_set_alignment(GTK_MISC(gtkconv->tab_label), 0.00, 0.5); | |
4833 gtk_misc_set_padding(GTK_MISC(gtkconv->tab_label), 4, 0); | |
4834 #endif | |
4835 | |
4836 /* Pack it all together. */ | |
4837 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->icon, FALSE, FALSE, 0); | |
4838 gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_icon, | |
4839 FALSE, FALSE, 0); | |
4840 | |
4841 gtk_widget_show_all(gtkconv->icon); | |
4842 gtk_widget_show_all(gtkconv->menu_icon); | |
4843 | |
4844 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->tab_label, TRUE, TRUE, 0); | |
4845 gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0); | |
4846 gtk_widget_show(gtkconv->tab_label); | |
4847 gtk_widget_show(gtkconv->menu_label); | |
4848 gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0); | |
4849 | |
4850 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->close, FALSE, FALSE, 0); | |
4851 if (gaim_prefs_get_bool("/gaim/gtk/conversations/close_on_tabs")) | |
4852 gtk_widget_show(gtkconv->close); | |
4853 | |
4854 gtk_widget_show(tabby); | |
4855 gtk_widget_show(menu_tabby); | |
4856 | |
4857 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | |
4858 gaim_gtkconv_update_buddy_icon(conv); | |
4859 | |
4860 /* Add this pane to the conversation's notebook. */ | |
4861 gtk_notebook_append_page_menu(GTK_NOTEBOOK(gtkwin->notebook), tab_cont, tabby, menu_tabby); | |
4862 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(gtkwin->notebook), tab_cont, TRUE, TRUE, GTK_PACK_START); | |
4863 | |
4864 | |
4865 gtk_widget_show(tab_cont); | |
4866 | |
4867 if (gaim_conv_window_get_conversation_count(win) == 1) { | |
4868 /* Er, bug in notebooks? Switch to the page manually. */ | |
4869 gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkwin->notebook), 0); | |
4870 | |
4871 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkwin->notebook), | |
4872 gaim_prefs_get_bool("/gaim/gtk/conversations/tabs")); | |
4873 } | |
4874 else | 3918 else |
4875 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkwin->notebook), TRUE); | 3919 gtk_widget_hide(gtkconv->toolbar); |
4876 | 3920 |
4877 focus_conv = g_list_nth_data(gaim_conv_window_get_conversations(win), | 3921 gtkconv->show_timestamps = TRUE; |
4878 gtk_notebook_get_current_page(GTK_NOTEBOOK(gtkwin->notebook))); | 3922 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); |
4879 focus_gtkconv = GAIM_GTK_CONVERSATION(focus_conv); | 3923 |
4880 gtk_widget_grab_focus(focus_gtkconv->entry); | 3924 g_signal_connect_swapped(G_OBJECT(pane), "focus", |
4881 | 3925 G_CALLBACK(gtk_widget_grab_focus), |
4882 if (!new_ui) | 3926 gtkconv->entry); |
4883 g_object_unref(gtkconv->tab_cont); | 3927 |
4884 | 3928 gaim_gtkconv_placement_place(gtkconv); |
4885 if (gaim_conv_window_get_conversation_count(win) == 1) | 3929 } |
4886 g_timeout_add(0, (GSourceFunc)update_send_as_selection, win); | 3930 |
4887 } | |
4888 | |
4889 static void | |
4890 gaim_gtk_remove_conversation(GaimConvWindow *win, GaimConversation *conv) | |
4891 { | |
4892 GaimGtkWindow *gtkwin; | |
4893 GaimGtkConversation *gtkconv; | |
4894 unsigned int index; | |
4895 GaimConversationType conv_type; | |
4896 | |
4897 conv_type = gaim_conversation_get_type(conv); | |
4898 gtkwin = GAIM_GTK_WINDOW(win); | |
4899 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
4900 index = gtk_notebook_page_num(GTK_NOTEBOOK(gtkwin->notebook), gtkconv->tab_cont); | |
4901 | |
4902 g_object_ref(gtkconv->tab_cont); | |
4903 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); | |
4904 | |
4905 gtk_notebook_remove_page(GTK_NOTEBOOK(gtkwin->notebook), index); | |
4906 | |
4907 /* go back to tabless if need be */ | |
4908 if (gaim_conv_window_get_conversation_count(win) <= 2) { | |
4909 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkwin->notebook), | |
4910 gaim_prefs_get_bool("/gaim/gtk/conversations/tabs")); | |
4911 } | |
4912 | |
4913 | |
4914 /* If this window is setup with an inactive gc, regenerate the menu. */ | |
4915 if (conv_type == GAIM_CONV_TYPE_IM && | |
4916 gaim_conversation_get_gc(conv) == NULL) { | |
4917 | |
4918 generate_send_as_items(win, conv); | |
4919 } | |
4920 } | |
4921 | |
4922 GaimGtkConversation * | |
4923 gaim_gtk_get_gtkconv_at_index(const GaimConvWindow *win, int index) | |
4924 { | |
4925 GaimGtkWindow *gtkwin; | |
4926 GtkWidget *tab_cont; | |
4927 | |
4928 gtkwin = GAIM_GTK_WINDOW(win); | |
4929 | |
4930 if (index == -1) | |
4931 index = 0; | |
4932 tab_cont = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), index); | |
4933 return g_object_get_data(G_OBJECT(tab_cont), "GaimGtkConversation"); | |
4934 } | |
4935 | |
4936 static GaimConversation * | |
4937 gaim_gtk_get_active_conversation(const GaimConvWindow *win) | |
4938 { | |
4939 GaimGtkWindow *gtkwin; | |
4940 GaimGtkConversation *gtkconv; | |
4941 int index; | |
4942 GtkWidget *tab_cont; | |
4943 | |
4944 gtkwin = GAIM_GTK_WINDOW(win); | |
4945 | |
4946 index = gtk_notebook_get_current_page(GTK_NOTEBOOK(gtkwin->notebook)); | |
4947 if (index == -1) | |
4948 index = 0; | |
4949 tab_cont = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), index); | |
4950 if (!tab_cont) | |
4951 return NULL; | |
4952 gtkconv = g_object_get_data(G_OBJECT(tab_cont), "GaimGtkConversation"); | |
4953 return gtkconv->active_conv; | |
4954 } | |
4955 | |
4956 static gboolean | |
4957 gaim_gtk_has_focus(GaimConvWindow *win) | |
4958 { | |
4959 GaimGtkWindow *gtkwin; | |
4960 gboolean has_focus = FALSE; | |
4961 | |
4962 gtkwin = GAIM_GTK_WINDOW(win); | |
4963 g_object_get(G_OBJECT(gtkwin->window), "has-toplevel-focus", &has_focus, NULL); | |
4964 | |
4965 return has_focus; | |
4966 } | |
4967 | |
4968 static GaimConvWindowUiOps window_ui_ops = | |
4969 { | |
4970 gaim_gtk_conversations_get_conv_ui_ops, | |
4971 gaim_gtk_new_window, | |
4972 gaim_gtk_destroy_window, | |
4973 gaim_gtk_show, | |
4974 gaim_gtk_hide, | |
4975 gaim_gtk_raise, | |
4976 gaim_gtk_switch_conversation, | |
4977 gaim_gtk_add_conversation, | |
4978 gaim_gtk_remove_conversation, | |
4979 gaim_gtk_get_active_conversation, | |
4980 gaim_gtk_has_focus | |
4981 }; | |
4982 | |
4983 GaimConvWindowUiOps * | |
4984 gaim_gtk_conversations_get_win_ui_ops(void) | |
4985 { | |
4986 return &window_ui_ops; | |
4987 } | |
4988 | |
4989 /************************************************************************** | |
4990 * Conversation UI operations | |
4991 **************************************************************************/ | |
4992 static void | 3931 static void |
4993 gaim_gtkconv_destroy(GaimConversation *conv) | 3932 gaim_gtkconv_destroy(GaimConversation *conv) |
4994 { | 3933 { |
4995 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); | 3934 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); |
4996 | 3935 |
4997 gtkconv->convs = g_list_remove(gtkconv->convs, conv); | 3936 gtkconv->convs = g_list_remove(gtkconv->convs, conv); |
4998 /* Don't destroy ourselves until all our convos are gone */ | 3937 /* Don't destroy ourselves until all our convos are gone */ |
4999 if (gtkconv->convs) | 3938 if (gtkconv->convs) |
5000 return; | 3939 return; |
5001 | 3940 |
3941 gaim_gtk_conv_window_remove_gtkconv(gtkconv->win, gtkconv); | |
3942 /* should we be doing this here or in gaim_gtk_conv_window_remove_gtkconv()? */ | |
3943 if (!gtkconv->win->gtkconvs) | |
3944 gaim_gtk_conv_window_destroy(gtkconv->win); | |
3945 | |
5002 /* If the "Save Conversation" or "Save Icon" dialogs are open then close them */ | 3946 /* If the "Save Conversation" or "Save Icon" dialogs are open then close them */ |
5003 gaim_request_close_with_handle(conv); | 3947 gaim_request_close_with_handle(conv); |
5004 | 3948 |
5005 gtk_widget_destroy(gtkconv->tab_cont); | 3949 gtk_widget_destroy(gtkconv->tab_cont); |
5006 g_object_unref(gtkconv->tab_cont); | 3950 g_object_unref(gtkconv->tab_cont); |
5011 | 3955 |
5012 if (gtkconv->u.im->anim != NULL) | 3956 if (gtkconv->u.im->anim != NULL) |
5013 g_object_unref(G_OBJECT(gtkconv->u.im->anim)); | 3957 g_object_unref(G_OBJECT(gtkconv->u.im->anim)); |
5014 | 3958 |
5015 g_free(gtkconv->u.im); | 3959 g_free(gtkconv->u.im); |
5016 } | 3960 } else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { |
5017 else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | |
5018 gaim_signals_disconnect_by_handle(gtkconv->u.chat); | 3961 gaim_signals_disconnect_by_handle(gtkconv->u.chat); |
5019 g_free(gtkconv->u.chat); | 3962 g_free(gtkconv->u.chat); |
5020 } | 3963 } |
5021 | 3964 |
5022 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); | 3965 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); |
5136 gaim_gtkconv_write_conv(GaimConversation *conv, const char *name, const char *alias, | 4079 gaim_gtkconv_write_conv(GaimConversation *conv, const char *name, const char *alias, |
5137 const char *message, GaimMessageFlags flags, | 4080 const char *message, GaimMessageFlags flags, |
5138 time_t mtime) | 4081 time_t mtime) |
5139 { | 4082 { |
5140 GaimGtkConversation *gtkconv; | 4083 GaimGtkConversation *gtkconv; |
5141 GaimConvWindow *win; | 4084 GaimGtkWindow *win; |
5142 GaimConnection *gc; | 4085 GaimConnection *gc; |
5143 GaimAccount *account; | 4086 GaimAccount *account; |
5144 GaimPluginProtocolInfo *prpl_info; | 4087 GaimPluginProtocolInfo *prpl_info; |
5145 int gtk_font_options = 0; | 4088 int gtk_font_options = 0; |
5146 int max_scrollback_lines = gaim_prefs_get_int( | 4089 int max_scrollback_lines = gaim_prefs_get_int( |
5153 char *with_font_tag; | 4096 char *with_font_tag; |
5154 char *sml_attrib = NULL; | 4097 char *sml_attrib = NULL; |
5155 size_t length = strlen(message) + 1; | 4098 size_t length = strlen(message) + 1; |
5156 | 4099 |
5157 gtkconv = GAIM_GTK_CONVERSATION(conv); | 4100 gtkconv = GAIM_GTK_CONVERSATION(conv); |
4101 | |
4102 /* Set the active conversation to the one that just messaged us. */ | |
4103 /* TODO: consider not doing this if the account is offline or something */ | |
5158 gtkconv->active_conv = conv; | 4104 gtkconv->active_conv = conv; |
4105 | |
5159 gc = gaim_conversation_get_gc(conv); | 4106 gc = gaim_conversation_get_gc(conv); |
5160 account = gaim_conversation_get_account(conv); | 4107 account = gaim_conversation_get_account(conv); |
5161 win = gaim_conversation_get_window(conv); | 4108 win = gtkconv->win; |
5162 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | 4109 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); |
5163 | 4110 |
5164 line_count = gtk_text_buffer_get_line_count( | 4111 line_count = gtk_text_buffer_get_line_count( |
5165 gtk_text_view_get_buffer(GTK_TEXT_VIEW( | 4112 gtk_text_view_get_buffer(GTK_TEXT_VIEW( |
5166 gtkconv->imhtml))); | 4113 gtkconv->imhtml))); |
5303 /* Are we in a chat where we can tell which users are buddies? */ | 4250 /* Are we in a chat where we can tell which users are buddies? */ |
5304 if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) && | 4251 if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) && |
5305 gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | 4252 gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { |
5306 | 4253 |
5307 /* Bold buddies to make them stand out from non-buddies. */ | 4254 /* Bold buddies to make them stand out from non-buddies. */ |
5308 if (flags & GAIM_MESSAGE_SEND || | 4255 if (flags & GAIM_MESSAGE_SEND || |
5309 flags & GAIM_MESSAGE_NICK || | 4256 flags & GAIM_MESSAGE_NICK || |
5310 gaim_find_buddy(account, name) != NULL) { | 4257 gaim_find_buddy(account, name) != NULL) { |
5311 g_snprintf(buf2, BUF_LONG, | 4258 g_snprintf(buf2, BUF_LONG, |
5312 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--(%s) --></FONT>" | 4259 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--(%s) --></FONT>" |
5313 "<B>%s</B></FONT> ", | 4260 "<B>%s</B></FONT> ", |
5608 | 4555 |
5609 add_chat_buddy_common(conv, user, alias, NULL); | 4556 add_chat_buddy_common(conv, user, alias, NULL); |
5610 g_free(alias); | 4557 g_free(alias); |
5611 } | 4558 } |
5612 | 4559 |
5613 static gboolean | 4560 gboolean |
5614 gaim_gtkconv_has_focus(GaimConversation *conv) | 4561 gaim_gtkconv_has_focus(GaimConversation *conv) |
5615 { | 4562 { |
5616 GaimConvWindow *win; | 4563 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); |
5617 GaimGtkWindow *gtkwin; | 4564 GaimGtkWindow *win; |
5618 gboolean has_focus; | 4565 gboolean has_focus; |
5619 | 4566 |
5620 win = gaim_conversation_get_window(conv); | 4567 win = gtkconv->win; |
5621 gtkwin = GAIM_GTK_WINDOW(win); | 4568 |
5622 | 4569 g_object_get(G_OBJECT(win->window), "has-toplevel-focus", &has_focus, NULL); |
5623 g_object_get(G_OBJECT(gtkwin->window), "has-toplevel-focus", &has_focus, NULL); | |
5624 | 4570 |
5625 return has_focus; | 4571 return has_focus; |
5626 } | 4572 } |
5627 | 4573 |
5628 static gboolean | 4574 static gboolean |
5782 gdk_pixbuf_loader_close(loader, NULL); | 4728 gdk_pixbuf_loader_close(loader, NULL); |
5783 g_object_unref(G_OBJECT(loader)); | 4729 g_object_unref(G_OBJECT(loader)); |
5784 smiley->loader = NULL; | 4730 smiley->loader = NULL; |
5785 } | 4731 } |
5786 | 4732 |
4733 /* | |
4734 * Makes sure all the menu items and all the buttons are hidden/shown and | |
4735 * sensitive/insensitive. This is called after changing tabs and when an | |
4736 * account signs on or off. | |
4737 */ | |
4738 static void | |
4739 gray_stuff_out(GaimGtkConversation *gtkconv) | |
4740 { | |
4741 GaimGtkWindow *win; | |
4742 GaimConversation *conv = gtkconv->active_conv; | |
4743 GaimConnection *gc; | |
4744 GaimPluginProtocolInfo *prpl_info = NULL; | |
4745 GdkPixbuf *window_icon = NULL; | |
4746 GtkIMHtmlButtons buttons; | |
4747 GaimAccount *account; | |
4748 | |
4749 win = gaim_gtkconv_get_window(gtkconv); | |
4750 gc = gaim_conversation_get_gc(conv); | |
4751 account = gaim_conversation_get_account(conv); | |
4752 | |
4753 if (gc != NULL) | |
4754 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
4755 | |
4756 if (win->menu.send_as != NULL) | |
4757 g_timeout_add(0, (GSourceFunc)update_send_as_selection, win); | |
4758 | |
4759 /* | |
4760 * Handle hiding and showing stuff based on what type of conv this is. | |
4761 * Stuff that Gaim IMs support in general should be shown for IM | |
4762 * conversations. Stuff that Gaim chats support in general should be | |
4763 * shown for chat conversations. It doesn't matter whether the PRPL | |
4764 * supports it or not--that only affects if the button or menu item | |
4765 * is sensitive or not. | |
4766 */ | |
4767 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | |
4768 /* Show stuff that applies to IMs, hide stuff that applies to chats */ | |
4769 | |
4770 /* Deal with menu items */ | |
4771 gtk_widget_show(win->menu.view_log); | |
4772 gtk_widget_show(win->menu.send_file); | |
4773 gtk_widget_show(win->menu.add_pounce); | |
4774 gtk_widget_show(win->menu.get_info); | |
4775 gtk_widget_hide(win->menu.invite); | |
4776 gtk_widget_show(win->menu.alias); | |
4777 gtk_widget_show(win->menu.block); | |
4778 | |
4779 if (gaim_find_buddy(account, gaim_conversation_get_name(conv)) == NULL) { | |
4780 gtk_widget_show(win->menu.add); | |
4781 gtk_widget_hide(win->menu.remove); | |
4782 } else { | |
4783 gtk_widget_show(win->menu.remove); | |
4784 gtk_widget_hide(win->menu.add); | |
4785 } | |
4786 | |
4787 gtk_widget_show(win->menu.insert_link); | |
4788 gtk_widget_show(win->menu.insert_image); | |
4789 gtk_widget_show(win->menu.show_icon); | |
4790 } else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | |
4791 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ | |
4792 | |
4793 /* Deal with menu items */ | |
4794 gtk_widget_show(win->menu.view_log); | |
4795 gtk_widget_hide(win->menu.send_file); | |
4796 gtk_widget_hide(win->menu.add_pounce); | |
4797 gtk_widget_hide(win->menu.get_info); | |
4798 gtk_widget_show(win->menu.invite); | |
4799 gtk_widget_show(win->menu.alias); | |
4800 gtk_widget_hide(win->menu.block); | |
4801 gtk_widget_hide(win->menu.show_icon); | |
4802 | |
4803 if (gaim_blist_find_chat(account, gaim_conversation_get_name(conv)) == NULL) { | |
4804 /* If the chat is NOT in the buddy list */ | |
4805 gtk_widget_show(win->menu.add); | |
4806 gtk_widget_hide(win->menu.remove); | |
4807 } else { | |
4808 /* If the chat IS in the buddy list */ | |
4809 gtk_widget_hide(win->menu.add); | |
4810 gtk_widget_show(win->menu.remove); | |
4811 } | |
4812 | |
4813 gtk_widget_show(win->menu.insert_link); | |
4814 gtk_widget_hide(win->menu.insert_image); | |
4815 } | |
4816 | |
4817 /* | |
4818 * Handle graying stuff out based on whether an account is connected | |
4819 * and what features that account supports. | |
4820 */ | |
4821 if ((gc != NULL) && | |
4822 ( (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_CHAT) || | |
4823 !gaim_conv_chat_has_left(GAIM_CONV_CHAT(conv)) )) { | |
4824 /* Account is online */ | |
4825 /* Deal with the toolbar */ | |
4826 if (conv->features & GAIM_CONNECTION_HTML) { | |
4827 buttons = GTK_IMHTML_ALL; /* Everything on */ | |
4828 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) || | |
4829 conv->features & GAIM_CONNECTION_NO_IMAGES) | |
4830 buttons &= ~GTK_IMHTML_IMAGE; | |
4831 if (conv->features & GAIM_CONNECTION_NO_BGCOLOR) | |
4832 buttons &= ~GTK_IMHTML_BACKCOLOR; | |
4833 if (conv->features & GAIM_CONNECTION_NO_FONTSIZE) { | |
4834 buttons &= ~GTK_IMHTML_GROW; | |
4835 buttons &= ~GTK_IMHTML_SHRINK; | |
4836 } | |
4837 if (conv->features & GAIM_CONNECTION_NO_URLDESC) | |
4838 buttons &= ~GTK_IMHTML_LINKDESC; | |
4839 } else { | |
4840 buttons = GTK_IMHTML_SMILEY; | |
4841 } | |
4842 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); | |
4843 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), gaim_account_get_protocol_id(account)); | |
4844 | |
4845 /* Deal with menu items */ | |
4846 gtk_widget_set_sensitive(win->menu.view_log, TRUE); | |
4847 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); | |
4848 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); | |
4849 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); | |
4850 gtk_widget_set_sensitive(win->menu.block, (prpl_info->add_deny != NULL)); | |
4851 gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & GAIM_CONNECTION_HTML)); | |
4852 gtk_widget_set_sensitive(win->menu.insert_image, (prpl_info->options & OPT_PROTO_IM_IMAGE)); | |
4853 | |
4854 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) { | |
4855 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); | |
4856 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); | |
4857 gtk_widget_set_sensitive(win->menu.send_file, | |
4858 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || | |
4859 prpl_info->can_receive_file(gc, gaim_conversation_get_name(conv))))); | |
4860 gtk_widget_set_sensitive(win->menu.alias, | |
4861 (gaim_find_buddy(account, gaim_conversation_get_name(conv)) != NULL)); | |
4862 } else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) { | |
4863 gtk_widget_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); | |
4864 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); | |
4865 gtk_widget_set_sensitive(win->menu.alias, | |
4866 (gaim_blist_find_chat(account, gaim_conversation_get_name(conv)) != NULL)); | |
4867 } | |
4868 | |
4869 /* Deal with chat userlist buttons */ | |
4870 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) | |
4871 { | |
4872 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_im, TRUE); | |
4873 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_ignore, TRUE); | |
4874 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_info, (prpl_info->get_info != NULL)); | |
4875 } | |
4876 } else { | |
4877 /* Account is offline */ | |
4878 /* Or it's a chat that we've left. */ | |
4879 | |
4880 /* Then deal with menu items */ | |
4881 gtk_widget_set_sensitive(win->menu.view_log, TRUE); | |
4882 gtk_widget_set_sensitive(win->menu.send_file, FALSE); | |
4883 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); | |
4884 gtk_widget_set_sensitive(win->menu.get_info, FALSE); | |
4885 gtk_widget_set_sensitive(win->menu.invite, FALSE); | |
4886 gtk_widget_set_sensitive(win->menu.alias, FALSE); | |
4887 gtk_widget_set_sensitive(win->menu.block, FALSE); | |
4888 gtk_widget_set_sensitive(win->menu.add, FALSE); | |
4889 gtk_widget_set_sensitive(win->menu.remove, FALSE); | |
4890 gtk_widget_set_sensitive(win->menu.insert_link, TRUE); | |
4891 gtk_widget_set_sensitive(win->menu.insert_image, FALSE); | |
4892 | |
4893 /* Deal with chat userlist buttons */ | |
4894 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) | |
4895 { | |
4896 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_im, FALSE); | |
4897 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_ignore, FALSE); | |
4898 gtk_widget_set_sensitive(gtkconv->u.chat->userlist_info, FALSE); | |
4899 } | |
4900 } | |
4901 | |
4902 /* | |
4903 * Update the window's icon | |
4904 */ | |
4905 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) && | |
4906 (gtkconv->u.im->anim)) | |
4907 { | |
4908 window_icon = | |
4909 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); | |
4910 g_object_ref(window_icon); | |
4911 } else { | |
4912 window_icon = gaim_gtkconv_get_tab_icon(conv, FALSE); | |
4913 } | |
4914 gtk_window_set_icon(GTK_WINDOW(win->window), window_icon); | |
4915 if (window_icon != NULL) | |
4916 g_object_unref(G_OBJECT(window_icon)); | |
4917 } | |
4918 | |
5787 | 4919 |
5788 static void | 4920 static void |
5789 gaim_gtkconv_updated(GaimConversation *conv, GaimConvUpdateType type) | 4921 gaim_gtkconv_updated(GaimConversation *conv, GaimConvUpdateType type) |
5790 { | 4922 { |
5791 GaimConvWindow *win; | 4923 GaimGtkWindow *win; |
5792 GaimGtkWindow *gtkwin; | |
5793 GaimGtkConversation *gtkconv; | 4924 GaimGtkConversation *gtkconv; |
5794 GaimGtkChatPane *gtkchat; | 4925 GaimGtkChatPane *gtkchat; |
5795 GaimConvChat *chat; | 4926 GaimConvChat *chat; |
5796 | 4927 |
5797 g_return_if_fail(conv != NULL); | 4928 g_return_if_fail(conv != NULL); |
5798 | 4929 |
5799 win = gaim_conversation_get_window(conv); | |
5800 gtkwin = GAIM_GTK_WINDOW(win); | |
5801 gtkconv = GAIM_GTK_CONVERSATION(conv); | 4930 gtkconv = GAIM_GTK_CONVERSATION(conv); |
4931 win = gtkconv->win; | |
5802 conv = gtkconv->active_conv; /* Gross hack */ | 4932 conv = gtkconv->active_conv; /* Gross hack */ |
4933 /* Maybe we should just ignore it if conv != gtkconv->active_conv, | |
4934 * instead of the gross hack? | |
4935 */ | |
5803 | 4936 |
5804 if (type == GAIM_CONV_UPDATE_ACCOUNT) | 4937 if (type == GAIM_CONV_UPDATE_ACCOUNT) |
5805 { | 4938 { |
5806 gaim_conversation_autoset_title(conv); | 4939 gaim_conversation_autoset_title(conv); |
5807 | 4940 |
5874 g_free(label); | 5007 g_free(label); |
5875 } | 5008 } |
5876 else | 5009 else |
5877 gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); | 5010 gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); |
5878 | 5011 |
5879 if (conv == gaim_conv_window_get_active_conversation(win)) | 5012 if (conv == gaim_gtk_conv_window_get_active_conversation(win)) |
5880 update_typing_icon(gtkconv); | 5013 update_typing_icon(gtkconv); |
5881 | 5014 |
5882 if (type == GAIM_CONV_UPDATE_TITLE) { | 5015 if (type == GAIM_CONV_UPDATE_TITLE) { |
5883 gtk_label_set_text(GTK_LABEL(gtkconv->menu_label), title); | 5016 gtk_label_set_text(GTK_LABEL(gtkconv->menu_label), title); |
5884 if (conv == gaim_conv_window_get_active_conversation(win)) | 5017 if (conv == gaim_gtk_conv_window_get_active_conversation(win)) |
5885 gtk_window_set_title(GTK_WINDOW(gtkwin->window), title); | 5018 gtk_window_set_title(GTK_WINDOW(win->window), title); |
5886 } | 5019 } |
5887 | 5020 |
5888 g_free(title); | 5021 g_free(title); |
5889 } | 5022 } |
5890 else if (type == GAIM_CONV_UPDATE_TOPIC) | 5023 else if (type == GAIM_CONV_UPDATE_TOPIC) |
5900 topic ? topic : "", NULL); | 5033 topic ? topic : "", NULL); |
5901 } | 5034 } |
5902 else if (type == GAIM_CONV_ACCOUNT_ONLINE || | 5035 else if (type == GAIM_CONV_ACCOUNT_ONLINE || |
5903 type == GAIM_CONV_ACCOUNT_OFFLINE) | 5036 type == GAIM_CONV_ACCOUNT_OFFLINE) |
5904 { | 5037 { |
5905 gray_stuff_out(GAIM_GTK_CONVERSATION(gaim_conv_window_get_active_conversation(win))); | 5038 gray_stuff_out(GAIM_GTK_CONVERSATION(gaim_gtk_conv_window_get_active_conversation(win))); |
5906 generate_send_as_items(win, NULL); | 5039 generate_send_as_items(win, NULL); |
5907 update_tab_icon(conv); | 5040 update_tab_icon(conv); |
5908 gaim_conversation_autoset_title(conv); | 5041 gaim_conversation_autoset_title(conv); |
5909 } | 5042 } |
5910 else if (type == GAIM_CONV_UPDATE_AWAY) | 5043 else if (type == GAIM_CONV_UPDATE_AWAY) |
5927 } | 5060 } |
5928 } | 5061 } |
5929 | 5062 |
5930 static GaimConversationUiOps conversation_ui_ops = | 5063 static GaimConversationUiOps conversation_ui_ops = |
5931 { | 5064 { |
5065 gaim_gtkconv_new, | |
5932 gaim_gtkconv_destroy, /* destroy_conversation */ | 5066 gaim_gtkconv_destroy, /* destroy_conversation */ |
5933 gaim_gtkconv_write_chat, /* write_chat */ | 5067 gaim_gtkconv_write_chat, /* write_chat */ |
5934 gaim_gtkconv_write_im, /* write_im */ | 5068 gaim_gtkconv_write_im, /* write_im */ |
5935 gaim_gtkconv_write_conv, /* write_conv */ | 5069 gaim_gtkconv_write_conv, /* write_conv */ |
5936 gaim_gtkconv_chat_add_users, /* chat_add_users */ | 5070 gaim_gtkconv_chat_add_users, /* chat_add_users */ |
5937 gaim_gtkconv_chat_rename_user, /* chat_rename_user */ | 5071 gaim_gtkconv_chat_rename_user, /* chat_rename_user */ |
5938 gaim_gtkconv_chat_remove_user, /* chat_remove_user */ | 5072 gaim_gtkconv_chat_remove_user, /* chat_remove_user */ |
5939 gaim_gtkconv_chat_remove_users, /* chat_remove_users */ | 5073 gaim_gtkconv_chat_remove_users, /* chat_remove_users */ |
5940 gaim_gtkconv_chat_update_user, /* chat_update_user */ | 5074 gaim_gtkconv_chat_update_user, /* chat_update_user */ |
5941 NULL, /* update_progress */ | |
5942 gaim_gtkconv_has_focus, /* has_focus */ | 5075 gaim_gtkconv_has_focus, /* has_focus */ |
5943 gaim_gtkconv_custom_smiley_add, /* custom_smiley_add */ | 5076 gaim_gtkconv_custom_smiley_add, /* custom_smiley_add */ |
5944 gaim_gtkconv_custom_smiley_write, /* custom_smiley_write */ | 5077 gaim_gtkconv_custom_smiley_write, /* custom_smiley_write */ |
5945 gaim_gtkconv_custom_smiley_close, /* custom_smiley_close */ | 5078 gaim_gtkconv_custom_smiley_close, /* custom_smiley_close */ |
5946 gaim_gtkconv_updated /* updated */ | 5079 gaim_gtkconv_updated /* updated */ |
5957 **************************************************************************/ | 5090 **************************************************************************/ |
5958 void | 5091 void |
5959 gaim_gtkconv_update_buddy_icon(GaimConversation *conv) | 5092 gaim_gtkconv_update_buddy_icon(GaimConversation *conv) |
5960 { | 5093 { |
5961 GaimGtkConversation *gtkconv; | 5094 GaimGtkConversation *gtkconv; |
5962 GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(conv)); | 5095 GaimGtkWindow *win; |
5963 | 5096 |
5964 GdkPixbufLoader *loader; | 5097 GdkPixbufLoader *loader; |
5965 GdkPixbufAnimation *anim; | 5098 GdkPixbufAnimation *anim; |
5966 GError *err = NULL; | 5099 GError *err = NULL; |
5967 | 5100 |
5985 g_return_if_fail(conv != NULL); | 5118 g_return_if_fail(conv != NULL); |
5986 g_return_if_fail(GAIM_IS_GTK_CONVERSATION(conv)); | 5119 g_return_if_fail(GAIM_IS_GTK_CONVERSATION(conv)); |
5987 g_return_if_fail(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM); | 5120 g_return_if_fail(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM); |
5988 | 5121 |
5989 gtkconv = GAIM_GTK_CONVERSATION(conv); | 5122 gtkconv = GAIM_GTK_CONVERSATION(conv); |
5123 win = gtkconv->win; | |
5990 | 5124 |
5991 if (!gtkconv->u.im->show_icon) | 5125 if (!gtkconv->u.im->show_icon) |
5992 return; | 5126 return; |
5993 | 5127 |
5994 account = gaim_conversation_get_account(conv); | 5128 account = gaim_conversation_get_account(conv); |
6103 gtk_widget_show(gtkconv->u.im->icon_container); | 5237 gtk_widget_show(gtkconv->u.im->icon_container); |
6104 gtk_widget_show(frame); | 5238 gtk_widget_show(frame); |
6105 | 5239 |
6106 /* The buddy icon code needs badly to be fixed. */ | 5240 /* The buddy icon code needs badly to be fixed. */ |
6107 buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); | 5241 buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); |
6108 if(conv == gaim_conv_window_get_active_conversation(gaim_conversation_get_window(conv))) | 5242 if(conv == gaim_gtk_conv_window_get_active_conversation(gtkconv->win)) |
6109 gtk_window_set_icon(GTK_WINDOW(gtkwin->window), buf); | 5243 gtk_window_set_icon(GTK_WINDOW(win->window), buf); |
6110 } | 5244 } |
6111 | 5245 |
6112 void | 5246 void |
6113 gaim_gtkconv_update_buttons_by_protocol(GaimConversation *conv) | 5247 gaim_gtkconv_update_buttons_by_protocol(GaimConversation *conv) |
6114 { | 5248 { |
6115 GaimConvWindow *win; | 5249 GaimGtkWindow *win; |
6116 | 5250 |
6117 if (!GAIM_IS_GTK_CONVERSATION(conv)) | 5251 if (!GAIM_IS_GTK_CONVERSATION(conv)) |
6118 return; | 5252 return; |
6119 | 5253 |
6120 win = gaim_conversation_get_window(conv); | 5254 win = GAIM_GTK_CONVERSATION(conv)->win; |
6121 | 5255 |
6122 if (win != NULL && gaim_conv_window_get_active_conversation(win) == conv) | 5256 if (win != NULL && gaim_gtk_conv_window_is_active_conversation(conv)) |
6123 gray_stuff_out(GAIM_GTK_CONVERSATION(conv)); | 5257 gray_stuff_out(GAIM_GTK_CONVERSATION(conv)); |
6124 } | 5258 } |
6125 | 5259 |
6126 GaimConvWindow * | |
6127 gaim_gtkwin_get_at_xy(int x, int y) | |
6128 { | |
6129 GaimConvWindow *win = NULL; | |
6130 GaimGtkWindow *gtkwin; | |
6131 GdkWindow *gdkwin; | |
6132 GList *l; | |
6133 | |
6134 gdkwin = gdk_window_at_pointer(&x, &y); | |
6135 | |
6136 if (gdkwin) | |
6137 gdkwin = gdk_window_get_toplevel(gdkwin); | |
6138 | |
6139 for (l = gaim_get_windows(); l != NULL; l = l->next) { | |
6140 win = (GaimConvWindow *)l->data; | |
6141 | |
6142 if (!GAIM_IS_GTK_WINDOW(win)) | |
6143 continue; | |
6144 | |
6145 gtkwin = GAIM_GTK_WINDOW(win); | |
6146 | |
6147 if (gdkwin == gtkwin->window->window) | |
6148 return win; | |
6149 } | |
6150 | |
6151 return NULL; | |
6152 } | |
6153 | |
6154 int | 5260 int |
6155 gaim_gtkconv_get_tab_at_xy(GaimConvWindow *win, int x, int y) | 5261 gaim_gtkconv_get_tab_at_xy(GaimGtkWindow *win, int x, int y) |
6156 { | 5262 { |
6157 GaimGtkWindow *gtkwin; | |
6158 gint nb_x, nb_y, x_rel, y_rel; | 5263 gint nb_x, nb_y, x_rel, y_rel; |
6159 GtkNotebook *notebook; | 5264 GtkNotebook *notebook; |
6160 GtkWidget *page, *tab; | 5265 GtkWidget *page, *tab; |
6161 gint i, page_num = -1; | 5266 gint i, page_num = -1; |
6162 gint count; | 5267 gint count; |
6163 gboolean horiz; | 5268 gboolean horiz; |
6164 | 5269 |
6165 if (!GAIM_IS_GTK_WINDOW(win)) | 5270 notebook = GTK_NOTEBOOK(win->notebook); |
6166 return -1; | 5271 |
6167 | 5272 gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y); |
6168 gtkwin = GAIM_GTK_WINDOW(win); | |
6169 notebook = GTK_NOTEBOOK(gtkwin->notebook); | |
6170 | |
6171 gdk_window_get_origin(gtkwin->notebook->window, &nb_x, &nb_y); | |
6172 x_rel = x - nb_x; | 5273 x_rel = x - nb_x; |
6173 y_rel = y - nb_y; | 5274 y_rel = y - nb_y; |
6174 | 5275 |
6175 horiz = (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP || | 5276 horiz = (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP || |
6176 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM); | 5277 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM); |
6256 tab_side_pref_cb(const char *name, GaimPrefType type, gpointer value, | 5357 tab_side_pref_cb(const char *name, GaimPrefType type, gpointer value, |
6257 gpointer data) | 5358 gpointer data) |
6258 { | 5359 { |
6259 GList *l; | 5360 GList *l; |
6260 GtkPositionType pos; | 5361 GtkPositionType pos; |
6261 GaimConvWindow *win; | 5362 GaimGtkWindow *win; |
6262 GaimGtkWindow *gtkwin; | |
6263 | 5363 |
6264 pos = GPOINTER_TO_INT(value); | 5364 pos = GPOINTER_TO_INT(value); |
6265 | 5365 |
6266 for (l = gaim_get_windows(); l != NULL; l = l->next) { | 5366 for (l = gaim_gtk_conv_windows_get_list(); l != NULL; l = l->next) { |
6267 win = (GaimConvWindow *)l->data; | 5367 win = l->data; |
6268 | 5368 |
6269 if (!GAIM_IS_GTK_WINDOW(win)) | 5369 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos); |
6270 continue; | |
6271 | |
6272 gtkwin = GAIM_GTK_WINDOW(win); | |
6273 | |
6274 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkwin->notebook), pos); | |
6275 } | 5370 } |
6276 } | 5371 } |
6277 | 5372 |
6278 static void | 5373 static void |
6279 show_formatting_toolbar_pref_cb(const char *name, GaimPrefType type, | 5374 show_formatting_toolbar_pref_cb(const char *name, GaimPrefType type, |
6280 gpointer value, gpointer data) | 5375 gpointer value, gpointer data) |
6281 { | 5376 { |
6282 GList *l; | 5377 GList *l; |
6283 GaimConversation *conv; | 5378 GaimConversation *conv; |
6284 GaimGtkConversation *gtkconv; | 5379 GaimGtkConversation *gtkconv; |
6285 GaimConvWindow *win; | 5380 GaimGtkWindow *win; |
6286 GaimGtkWindow *gtkwin; | |
6287 | 5381 |
6288 for (l = gaim_get_conversations(); l != NULL; l = l->next) | 5382 for (l = gaim_get_conversations(); l != NULL; l = l->next) |
6289 { | 5383 { |
6290 conv = (GaimConversation *)l->data; | 5384 conv = (GaimConversation *)l->data; |
6291 | 5385 |
6292 if (!GAIM_IS_GTK_CONVERSATION(conv)) | 5386 if (!GAIM_IS_GTK_CONVERSATION(conv)) |
6293 continue; | 5387 continue; |
6294 | 5388 |
6295 gtkconv = GAIM_GTK_CONVERSATION(conv); | 5389 gtkconv = GAIM_GTK_CONVERSATION(conv); |
6296 win = gaim_conversation_get_window(conv); | 5390 win = gtkconv->win; |
6297 gtkwin = GAIM_GTK_WINDOW(win); | |
6298 | 5391 |
6299 gtk_check_menu_item_set_active( | 5392 gtk_check_menu_item_set_active( |
6300 GTK_CHECK_MENU_ITEM(gtkwin->menu.show_formatting_toolbar), | 5393 GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), |
6301 (gboolean)GPOINTER_TO_INT(value)); | 5394 (gboolean)GPOINTER_TO_INT(value)); |
6302 | 5395 |
6303 if ((gboolean)GPOINTER_TO_INT(value)) | 5396 if ((gboolean)GPOINTER_TO_INT(value)) |
6304 gtk_widget_show(gtkconv->toolbar); | 5397 gtk_widget_show(gtkconv->toolbar); |
6305 else | 5398 else |
6306 gtk_widget_hide(gtkconv->toolbar); | 5399 gtk_widget_hide(gtkconv->toolbar); |
6312 gpointer value, gpointer data) | 5405 gpointer value, gpointer data) |
6313 { | 5406 { |
6314 GList *l; | 5407 GList *l; |
6315 GaimConversation *conv; | 5408 GaimConversation *conv; |
6316 GaimGtkConversation *gtkconv; | 5409 GaimGtkConversation *gtkconv; |
6317 GaimConvWindow *win; | 5410 GaimGtkWindow *win; |
6318 | 5411 |
6319 if (!gaim_prefs_get_bool("/gaim/gtk/conversations/im/show_buddy_icons")) | 5412 if (!gaim_prefs_get_bool("/gaim/gtk/conversations/im/show_buddy_icons")) |
6320 return; | 5413 return; |
6321 | 5414 |
6322 /* Set the "animate" flag for each icon based on the new preference */ | 5415 /* Set the "animate" flag for each icon based on the new preference */ |
6325 gtkconv = GAIM_GTK_CONVERSATION(conv); | 5418 gtkconv = GAIM_GTK_CONVERSATION(conv); |
6326 gtkconv->u.im->animate = GPOINTER_TO_INT(value); | 5419 gtkconv->u.im->animate = GPOINTER_TO_INT(value); |
6327 } | 5420 } |
6328 | 5421 |
6329 /* Now either stop or start animation for the active conversation in each window */ | 5422 /* Now either stop or start animation for the active conversation in each window */ |
6330 for (l = gaim_get_windows(); l != NULL; l = l->next) { | 5423 for (l = gaim_gtk_conv_windows_get_list(); l != NULL; l = l->next) { |
6331 win = (GaimConvWindow *)l->data; | 5424 win = l->data; |
6332 conv = gaim_conv_window_get_active_conversation(win); | 5425 conv = gaim_gtk_conv_window_get_active_conversation(win); |
6333 gaim_gtkconv_update_buddy_icon(conv); | 5426 gaim_gtkconv_update_buddy_icon(conv); |
6334 } | 5427 } |
6335 } | 5428 } |
6336 | 5429 |
6337 static void | 5430 static void |
6355 GaimConvPlacementFunc func; | 5448 GaimConvPlacementFunc func; |
6356 | 5449 |
6357 if (strcmp(name, "/gaim/gtk/conversations/placement")) | 5450 if (strcmp(name, "/gaim/gtk/conversations/placement")) |
6358 return; | 5451 return; |
6359 | 5452 |
6360 func = gaim_conv_placement_get_fnc(value); | 5453 func = gaim_gtkconv_placement_get_fnc(value); |
6361 | 5454 |
6362 if (func == NULL) | 5455 if (func == NULL) |
6363 return; | 5456 return; |
6364 | 5457 |
6365 gaim_conv_placement_set_current_func(func); | 5458 gaim_gtkconv_placement_set_current_func(func); |
6366 } | 5459 } |
6367 | 5460 |
6368 void * | 5461 void * |
6369 gaim_gtk_conversations_get_handle(void) | 5462 gaim_gtk_conversations_get_handle(void) |
6370 { | 5463 { |
6463 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, | 5556 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, |
6464 clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); | 5557 clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); |
6465 gaim_cmd_register("help", "w", GAIM_CMD_P_DEFAULT, | 5558 gaim_cmd_register("help", "w", GAIM_CMD_P_DEFAULT, |
6466 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, | 5559 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, |
6467 help_command_cb, _("help <command>: Help on a specific command."), NULL); | 5560 help_command_cb, _("help <command>: Help on a specific command."), NULL); |
5561 | |
5562 gaim_conversations_set_ui_ops(&conversation_ui_ops); | |
6468 } | 5563 } |
6469 | 5564 |
6470 void | 5565 void |
6471 gaim_gtk_conversations_uninit(void) | 5566 gaim_gtk_conversations_uninit(void) |
6472 { | 5567 { |
6473 gaim_prefs_disconnect_by_handle(gaim_gtk_conversations_get_handle()); | 5568 gaim_prefs_disconnect_by_handle(gaim_gtk_conversations_get_handle()); |
6474 gaim_signals_unregister_by_instance(gaim_gtk_conversations_get_handle()); | 5569 gaim_signals_unregister_by_instance(gaim_gtk_conversations_get_handle()); |
6475 } | 5570 } |
5571 | |
5572 | |
5573 | |
5574 | |
5575 | |
5576 | |
5577 | |
5578 | |
5579 | |
5580 | |
5581 | |
5582 | |
5583 | |
5584 | |
5585 | |
5586 | |
5587 /* down here is where gtkconvwin.c ought to start. except they share like every freaking function, | |
5588 * and touch each others' private members all day long */ | |
5589 | |
5590 /** | |
5591 * @file gtkconvwin.c GTK+ Conversation Window API | |
5592 * @ingroup gtkui | |
5593 * | |
5594 * gaim | |
5595 * | |
5596 * Gaim is the legal property of its developers, whose names are too numerous | |
5597 * to list here. Please refer to the COPYRIGHT file distributed with this | |
5598 * source distribution. | |
5599 * | |
5600 * This program is free software; you can redistribute it and/or modify | |
5601 * it under the terms of the GNU General Public License as published by | |
5602 * the Free Software Foundation; either version 2 of the License, or | |
5603 * (at your option) any later version. | |
5604 * | |
5605 * This program is distributed in the hope that it will be useful, | |
5606 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
5607 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
5608 * GNU General Public License for more details. | |
5609 * | |
5610 * You should have received a copy of the GNU General Public License | |
5611 * along with this program; if not, write to the Free Software | |
5612 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5613 * | |
5614 */ | |
5615 #include "internal.h" | |
5616 #include "gtkgaim.h" | |
5617 | |
5618 | |
5619 #include <gdk/gdkkeysyms.h> | |
5620 | |
5621 #include "account.h" | |
5622 #include "cmds.h" | |
5623 #include "debug.h" | |
5624 #include "imgstore.h" | |
5625 #include "log.h" | |
5626 #include "notify.h" | |
5627 #include "prpl.h" | |
5628 #include "request.h" | |
5629 #include "util.h" | |
5630 | |
5631 #include "gtkdnd-hints.h" | |
5632 #include "gtkblist.h" | |
5633 #include "gtkconv.h" | |
5634 #include "gtkdialogs.h" | |
5635 #include "gtkmenutray.h" | |
5636 #include "gtkpounce.h" | |
5637 #include "gtkprefs.h" | |
5638 #include "gtkprivacy.h" | |
5639 #include "gtkutils.h" | |
5640 #include "gtkstock.h" | |
5641 #include "gtkimhtml.h" | |
5642 #include "gtkimhtmltoolbar.h" | |
5643 | |
5644 | |
5645 | |
5646 | |
5647 | |
5648 static void | |
5649 do_close(GtkWidget *w, int resp, GaimGtkWindow *win) | |
5650 { | |
5651 gtk_widget_destroy(warn_close_dialog); | |
5652 warn_close_dialog = NULL; | |
5653 | |
5654 if (resp == GTK_RESPONSE_OK) | |
5655 gaim_gtk_conv_window_destroy(win); | |
5656 } | |
5657 | |
5658 static void | |
5659 build_warn_close_dialog(GaimGtkWindow *gtkwin) | |
5660 { | |
5661 GtkWidget *label; | |
5662 GtkWidget *vbox, *hbox; | |
5663 GtkWidget *img; | |
5664 | |
5665 g_return_if_fail(warn_close_dialog == NULL); | |
5666 | |
5667 | |
5668 warn_close_dialog = gtk_dialog_new_with_buttons( | |
5669 _("Confirm close"), | |
5670 GTK_WINDOW(gtkwin->window), GTK_DIALOG_MODAL, | |
5671 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
5672 GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); | |
5673 | |
5674 gtk_dialog_set_default_response(GTK_DIALOG(warn_close_dialog), | |
5675 GTK_RESPONSE_OK); | |
5676 | |
5677 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), | |
5678 6); | |
5679 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); | |
5680 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), | |
5681 FALSE); | |
5682 | |
5683 /* Setup the outside spacing. */ | |
5684 vbox = GTK_DIALOG(warn_close_dialog)->vbox; | |
5685 | |
5686 gtk_box_set_spacing(GTK_BOX(vbox), 12); | |
5687 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); | |
5688 | |
5689 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_WARNING, | |
5690 GTK_ICON_SIZE_DIALOG); | |
5691 /* Setup the inner hbox and put the dialog's icon in it. */ | |
5692 hbox = gtk_hbox_new(FALSE, 12); | |
5693 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
5694 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
5695 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
5696 | |
5697 /* Setup the right vbox. */ | |
5698 vbox = gtk_vbox_new(FALSE, 12); | |
5699 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
5700 | |
5701 label = gtk_label_new(_("You have unread messages. Are you sure you want to close the window?")); | |
5702 gtk_widget_set_size_request(label, 350, -1); | |
5703 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
5704 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
5705 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
5706 | |
5707 /* Connect the signals. */ | |
5708 g_signal_connect(G_OBJECT(warn_close_dialog), "response", | |
5709 G_CALLBACK(do_close), gtkwin); | |
5710 | |
5711 } | |
5712 | |
5713 /************************************************************************** | |
5714 * Callbacks | |
5715 **************************************************************************/ | |
5716 | |
5717 static gboolean | |
5718 close_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) | |
5719 { | |
5720 GaimGtkWindow *win = d; | |
5721 GList *l, *j; | |
5722 | |
5723 /* If there are unread messages then show a warning dialog */ | |
5724 for (l = gaim_gtk_conv_window_get_gtkconvs(win); | |
5725 l != NULL; l = l->next) | |
5726 { | |
5727 GaimGtkConversation *gtkconv = l->data; | |
5728 | |
5729 for (j = gtkconv->convs; j != NULL; j = j->next) { | |
5730 GaimConversation *conv = j->data; | |
5731 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM && | |
5732 gaim_conversation_get_unseen(conv) == GAIM_UNSEEN_TEXT) | |
5733 { | |
5734 build_warn_close_dialog(win); | |
5735 gtk_widget_show_all(warn_close_dialog); | |
5736 | |
5737 return TRUE; | |
5738 } | |
5739 } | |
5740 } | |
5741 | |
5742 gaim_gtk_conv_window_destroy(win); | |
5743 | |
5744 return TRUE; | |
5745 } | |
5746 | |
5747 /* | |
5748 * When a conversation window is focused, we know the user | |
5749 * has looked at it so we know there are no longer unseen | |
5750 * messages. | |
5751 */ | |
5752 static gint | |
5753 focus_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) | |
5754 { | |
5755 GaimGtkWindow *win = d; | |
5756 GaimConversation *conv = gaim_gtk_conv_window_get_active_conversation(win); | |
5757 | |
5758 gaim_conversation_set_unseen(conv, GAIM_UNSEEN_NONE); | |
5759 | |
5760 return FALSE; | |
5761 } | |
5762 | |
5763 /* Courtesy of Galeon! */ | |
5764 static void | |
5765 tab_close_button_state_changed_cb(GtkWidget *widget, GtkStateType prev_state) | |
5766 { | |
5767 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE) | |
5768 gtk_widget_set_state(widget, GTK_STATE_NORMAL); | |
5769 } | |
5770 | |
5771 | |
5772 | |
5773 | |
5774 static void | |
5775 notebook_init_grab(GaimGtkWindow *gtkwin, GtkWidget *widget) | |
5776 { | |
5777 static GdkCursor *cursor = NULL; | |
5778 | |
5779 gtkwin->in_drag = TRUE; | |
5780 | |
5781 if (gtkwin->drag_leave_signal) { | |
5782 g_signal_handler_disconnect(G_OBJECT(widget), | |
5783 gtkwin->drag_leave_signal); | |
5784 gtkwin->drag_leave_signal = 0; | |
5785 } | |
5786 | |
5787 if (cursor == NULL) | |
5788 cursor = gdk_cursor_new(GDK_FLEUR); | |
5789 | |
5790 /* Grab the pointer */ | |
5791 gtk_grab_add(gtkwin->notebook); | |
5792 #ifndef _WIN32 | |
5793 /* Currently for win32 GTK+ (as of 2.2.1), gdk_pointer_is_grabbed will | |
5794 always be true after a button press. */ | |
5795 if (!gdk_pointer_is_grabbed()) | |
5796 #endif | |
5797 gdk_pointer_grab(gtkwin->notebook->window, FALSE, | |
5798 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, | |
5799 NULL, cursor, GDK_CURRENT_TIME); | |
5800 } | |
5801 | |
5802 static gboolean | |
5803 notebook_motion_cb(GtkWidget *widget, GdkEventButton *e, GaimGtkWindow *win) | |
5804 { | |
5805 | |
5806 /* | |
5807 * Make sure the user moved the mouse far enough for the | |
5808 * drag to be initiated. | |
5809 */ | |
5810 if (win->in_predrag) { | |
5811 if (e->x_root < win->drag_min_x || | |
5812 e->x_root >= win->drag_max_x || | |
5813 e->y_root < win->drag_min_y || | |
5814 e->y_root >= win->drag_max_y) { | |
5815 | |
5816 win->in_predrag = FALSE; | |
5817 notebook_init_grab(win, widget); | |
5818 } | |
5819 } | |
5820 else { /* Otherwise, draw the arrows. */ | |
5821 GaimGtkWindow *dest_win; | |
5822 GtkNotebook *dest_notebook; | |
5823 GtkWidget *tab; | |
5824 gint nb_x, nb_y, page_num; | |
5825 gint arrow1_x, arrow1_y, arrow2_x, arrow2_y; | |
5826 gboolean horiz_tabs = FALSE; | |
5827 | |
5828 /* Get the window that the cursor is over. */ | |
5829 dest_win = gaim_gtk_conv_window_get_at_xy(e->x_root, e->y_root); | |
5830 | |
5831 if (dest_win == NULL) { | |
5832 dnd_hints_hide_all(); | |
5833 | |
5834 return TRUE; | |
5835 } | |
5836 | |
5837 | |
5838 dest_notebook = GTK_NOTEBOOK(dest_win->notebook); | |
5839 | |
5840 gdk_window_get_origin(GTK_WIDGET(dest_notebook)->window, &nb_x, &nb_y); | |
5841 | |
5842 arrow1_x = arrow2_x = nb_x; | |
5843 arrow1_y = arrow2_y = nb_y; | |
5844 | |
5845 page_num = gaim_gtkconv_get_tab_at_xy(dest_win, | |
5846 e->x_root, e->y_root); | |
5847 | |
5848 if (gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_TOP || | |
5849 gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { | |
5850 | |
5851 horiz_tabs = TRUE; | |
5852 } | |
5853 | |
5854 tab = gaim_gtk_conv_window_get_gtkconv_at_index(dest_win, page_num)->tabby; | |
5855 | |
5856 if (horiz_tabs) { | |
5857 arrow1_x = arrow2_x = nb_x + tab->allocation.x; | |
5858 | |
5859 if ((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) { | |
5860 arrow1_x += tab->allocation.width; | |
5861 arrow2_x += tab->allocation.width; | |
5862 } | |
5863 | |
5864 arrow1_y = nb_y + tab->allocation.y; | |
5865 arrow2_y = nb_y + tab->allocation.y + | |
5866 tab->allocation.height; | |
5867 } else { | |
5868 arrow1_x = nb_x + tab->allocation.x; | |
5869 arrow2_x = nb_x + tab->allocation.x + | |
5870 tab->allocation.width; | |
5871 arrow1_y = arrow2_y = nb_y + tab->allocation.y + tab->allocation.height/2; | |
5872 | |
5873 if ((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) { | |
5874 arrow1_y += tab->allocation.height; | |
5875 arrow2_y += tab->allocation.height; | |
5876 } | |
5877 } | |
5878 | |
5879 if (horiz_tabs) { | |
5880 dnd_hints_show(HINT_ARROW_DOWN, arrow1_x, arrow1_y); | |
5881 dnd_hints_show(HINT_ARROW_UP, arrow2_x, arrow2_y); | |
5882 } else { | |
5883 dnd_hints_show(HINT_ARROW_RIGHT, arrow1_x, arrow1_y); | |
5884 dnd_hints_show(HINT_ARROW_LEFT, arrow2_x, arrow2_y); | |
5885 } | |
5886 } | |
5887 | |
5888 return TRUE; | |
5889 } | |
5890 | |
5891 static gboolean | |
5892 notebook_leave_cb(GtkWidget *widget, GdkEventCrossing *e, GaimGtkWindow *win) | |
5893 { | |
5894 if (win->in_drag) | |
5895 return FALSE; | |
5896 | |
5897 if (e->x_root < win->drag_min_x || | |
5898 e->x_root >= win->drag_max_x || | |
5899 e->y_root < win->drag_min_y || | |
5900 e->y_root >= win->drag_max_y) { | |
5901 | |
5902 win->in_predrag = FALSE; | |
5903 notebook_init_grab(win, widget); | |
5904 } | |
5905 | |
5906 return TRUE; | |
5907 } | |
5908 | |
5909 /* | |
5910 * THANK YOU GALEON! | |
5911 */ | |
5912 static gboolean | |
5913 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, GaimGtkWindow *win) | |
5914 { | |
5915 gint nb_x, nb_y, x_rel, y_rel; | |
5916 int tab_clicked; | |
5917 GtkWidget *page; | |
5918 GtkWidget *tab; | |
5919 | |
5920 if (e->button != 1 || e->type != GDK_BUTTON_PRESS) | |
5921 return FALSE; | |
5922 | |
5923 | |
5924 if (win->in_drag) { | |
5925 gaim_debug(GAIM_DEBUG_WARNING, "gtkconv", | |
5926 "Already in the middle of a window drag at tab_press_cb\n"); | |
5927 return TRUE; | |
5928 } | |
5929 | |
5930 /* | |
5931 * Make sure a tab was actually clicked. The arrow buttons | |
5932 * mess things up. | |
5933 */ | |
5934 tab_clicked = gaim_gtkconv_get_tab_at_xy(win, e->x_root, e->y_root); | |
5935 | |
5936 if (tab_clicked == -1) | |
5937 return FALSE; | |
5938 | |
5939 /* | |
5940 * Get the relative position of the press event, with regards to | |
5941 * the position of the notebook. | |
5942 */ | |
5943 gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y); | |
5944 | |
5945 x_rel = e->x_root - nb_x; | |
5946 y_rel = e->y_root - nb_y; | |
5947 | |
5948 /* Reset the min/max x/y */ | |
5949 win->drag_min_x = 0; | |
5950 win->drag_min_y = 0; | |
5951 win->drag_max_x = 0; | |
5952 win->drag_max_y = 0; | |
5953 | |
5954 /* Find out which tab was dragged. */ | |
5955 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), tab_clicked); | |
5956 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(win->notebook), page); | |
5957 | |
5958 win->drag_min_x = tab->allocation.x + nb_x; | |
5959 win->drag_min_y = tab->allocation.y + nb_y; | |
5960 win->drag_max_x = tab->allocation.width + win->drag_min_x; | |
5961 win->drag_max_y = tab->allocation.height + win->drag_min_y; | |
5962 | |
5963 /* Make sure the click occurred in the tab. */ | |
5964 if (e->x_root < win->drag_min_x || | |
5965 e->x_root >= win->drag_max_x || | |
5966 e->y_root < win->drag_min_y || | |
5967 e->y_root >= win->drag_max_y) { | |
5968 | |
5969 return FALSE; | |
5970 } | |
5971 | |
5972 win->in_predrag = TRUE; | |
5973 win->drag_tab = tab_clicked; | |
5974 | |
5975 /* Connect the new motion signals. */ | |
5976 win->drag_motion_signal = | |
5977 g_signal_connect(G_OBJECT(widget), "motion_notify_event", | |
5978 G_CALLBACK(notebook_motion_cb), win); | |
5979 | |
5980 win->drag_leave_signal = | |
5981 g_signal_connect(G_OBJECT(widget), "leave_notify_event", | |
5982 G_CALLBACK(notebook_leave_cb), win); | |
5983 | |
5984 return FALSE; | |
5985 } | |
5986 | |
5987 static gboolean | |
5988 notebook_release_cb(GtkWidget *widget, GdkEventButton *e, GaimGtkWindow *win) | |
5989 { | |
5990 GaimGtkWindow *dest_win; | |
5991 GaimConversation *conv; | |
5992 GaimGtkConversation *gtkconv; | |
5993 gint dest_page_num = 0; | |
5994 gboolean new_window = FALSE; | |
5995 | |
5996 /* | |
5997 * Don't check to make sure that the event's window matches the | |
5998 * widget's, because we may be getting an event passed on from the | |
5999 * close button. | |
6000 */ | |
6001 if (e->button != 1 && e->type != GDK_BUTTON_RELEASE) | |
6002 return FALSE; | |
6003 | |
6004 if (gdk_pointer_is_grabbed()) { | |
6005 gdk_pointer_ungrab(GDK_CURRENT_TIME); | |
6006 gtk_grab_remove(widget); | |
6007 } | |
6008 | |
6009 if (!win->in_predrag && !win->in_drag) | |
6010 return FALSE; | |
6011 | |
6012 /* Disconnect the motion signal. */ | |
6013 if (win->drag_motion_signal) { | |
6014 g_signal_handler_disconnect(G_OBJECT(widget), | |
6015 win->drag_motion_signal); | |
6016 | |
6017 win->drag_motion_signal = 0; | |
6018 } | |
6019 | |
6020 /* | |
6021 * If we're in a pre-drag, we'll also need to disconnect the leave | |
6022 * signal. | |
6023 */ | |
6024 if (win->in_predrag) { | |
6025 win->in_predrag = FALSE; | |
6026 | |
6027 if (win->drag_leave_signal) { | |
6028 g_signal_handler_disconnect(G_OBJECT(widget), | |
6029 win->drag_leave_signal); | |
6030 | |
6031 win->drag_leave_signal = 0; | |
6032 } | |
6033 } | |
6034 | |
6035 /* If we're not in drag... */ | |
6036 /* We're perfectly normal people! */ | |
6037 if (!win->in_drag) | |
6038 return FALSE; | |
6039 | |
6040 win->in_drag = FALSE; | |
6041 | |
6042 dnd_hints_hide_all(); | |
6043 | |
6044 dest_win = gaim_gtk_conv_window_get_at_xy(e->x_root, e->y_root); | |
6045 | |
6046 conv = gaim_gtk_conv_window_get_active_conversation(win); | |
6047 | |
6048 if (dest_win == NULL) { | |
6049 /* If the current window doesn't have any other conversations, | |
6050 * there isn't much point transferring the conv to a new window. */ | |
6051 if (gaim_gtk_conv_window_get_gtkconv_count(win) > 1) { | |
6052 /* Make a new window to stick this to. */ | |
6053 dest_win = gaim_gtk_conv_window_new(); | |
6054 new_window = TRUE; | |
6055 } | |
6056 } | |
6057 | |
6058 if (dest_win == NULL) | |
6059 return FALSE; | |
6060 | |
6061 gaim_signal_emit(gaim_gtk_conversations_get_handle(), | |
6062 "conversation-dragging", win, dest_win); | |
6063 | |
6064 /* Get the destination page number. */ | |
6065 if (!new_window) | |
6066 dest_page_num = gaim_gtkconv_get_tab_at_xy(dest_win, | |
6067 e->x_root, e->y_root); | |
6068 | |
6069 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
6070 | |
6071 if (win == dest_win) { | |
6072 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, dest_page_num); | |
6073 } else { | |
6074 gaim_gtk_conv_window_remove_gtkconv(win, gtkconv); | |
6075 gaim_gtk_conv_window_add_gtkconv(dest_win, gtkconv); | |
6076 gtk_notebook_reorder_child(GTK_NOTEBOOK(dest_win->notebook), gtkconv->tab_cont, dest_page_num); | |
6077 gaim_gtk_conv_window_switch_gtkconv(dest_win, gtkconv); | |
6078 if (new_window) { | |
6079 gint win_width, win_height; | |
6080 | |
6081 gtk_window_get_size(GTK_WINDOW(dest_win->window), | |
6082 &win_width, &win_height); | |
6083 | |
6084 gtk_window_move(GTK_WINDOW(dest_win->window), | |
6085 e->x_root - (win_width / 2), | |
6086 e->y_root - (win_height / 2)); | |
6087 | |
6088 gaim_gtk_conv_window_show(dest_win); | |
6089 } | |
6090 } | |
6091 | |
6092 gtk_widget_grab_focus(GAIM_GTK_CONVERSATION(conv)->entry); | |
6093 | |
6094 return TRUE; | |
6095 } | |
6096 | |
6097 | |
6098 static void | |
6099 before_switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, | |
6100 gpointer user_data) | |
6101 { | |
6102 GaimGtkWindow *win; | |
6103 GaimConversation *conv; | |
6104 GaimGtkConversation *gtkconv; | |
6105 | |
6106 win = user_data; | |
6107 conv = gaim_gtk_conv_window_get_active_conversation(win); | |
6108 | |
6109 g_return_if_fail(conv != NULL); | |
6110 | |
6111 if (gaim_conversation_get_type(conv) != GAIM_CONV_TYPE_IM) | |
6112 return; | |
6113 | |
6114 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
6115 | |
6116 stop_anim(NULL, gtkconv); | |
6117 } | |
6118 | |
6119 static void | |
6120 switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, | |
6121 gpointer user_data) | |
6122 { | |
6123 GaimGtkWindow *win; | |
6124 GaimConversation *conv; | |
6125 GaimGtkConversation *gtkconv; | |
6126 | |
6127 win = user_data; | |
6128 gtkconv = gaim_gtk_conv_window_get_gtkconv_at_index(win, page_num); | |
6129 conv = gtkconv->active_conv; | |
6130 | |
6131 g_return_if_fail(conv != NULL); | |
6132 | |
6133 /* | |
6134 * Only set "unseen" to "none" if the window has focus | |
6135 */ | |
6136 if (gaim_gtk_conv_window_has_focus(win)) | |
6137 gaim_conversation_set_unseen(conv, GAIM_UNSEEN_NONE); | |
6138 | |
6139 /* Update the menubar */ | |
6140 gray_stuff_out(gtkconv); | |
6141 | |
6142 update_typing_icon(gtkconv); | |
6143 | |
6144 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.logging), | |
6145 gaim_conversation_is_logging(conv)); | |
6146 | |
6147 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), | |
6148 gtkconv->make_sound); | |
6149 | |
6150 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), | |
6151 gaim_prefs_get_bool("/gaim/gtk/conversations/show_formatting_toolbar")); | |
6152 | |
6153 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), | |
6154 gtkconv->show_timestamps); | |
6155 | |
6156 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | |
6157 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_icon), | |
6158 gtkconv->u.im->show_icon); | |
6159 /* | |
6160 * We pause icons when they are not visible. If this icon should | |
6161 * be animated then start it back up again. | |
6162 */ | |
6163 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) && | |
6164 (gtkconv->u.im->animate)) | |
6165 start_anim(NULL, gtkconv); | |
6166 | |
6167 gtk_window_set_title(GTK_WINDOW(win->window), | |
6168 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); | |
6169 } | |
6170 | |
6171 /************************************************************************** | |
6172 * GTK+ window ops | |
6173 **************************************************************************/ | |
6174 | |
6175 static GList *window_list = NULL; | |
6176 | |
6177 GList * | |
6178 gaim_gtk_conv_windows_get_list() | |
6179 { | |
6180 return window_list; | |
6181 } | |
6182 | |
6183 GaimGtkWindow * | |
6184 gaim_gtk_conv_window_new() | |
6185 { | |
6186 GaimGtkWindow *win; | |
6187 GtkPositionType pos; | |
6188 GtkWidget *testidea; | |
6189 GtkWidget *menubar; | |
6190 | |
6191 win = g_malloc0(sizeof(GaimGtkWindow)); | |
6192 | |
6193 window_list = g_list_append(window_list, win); | |
6194 | |
6195 /* Create the window. */ | |
6196 win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
6197 gtk_window_set_role(GTK_WINDOW(win->window), "conversation"); | |
6198 gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE); | |
6199 gtk_container_set_border_width(GTK_CONTAINER(win->window), 0); | |
6200 GTK_WINDOW(win->window)->allow_shrink = TRUE; | |
6201 | |
6202 g_signal_connect(G_OBJECT(win->window), "delete_event", | |
6203 G_CALLBACK(close_win_cb), win); | |
6204 | |
6205 g_signal_connect(G_OBJECT(win->window), "focus_in_event", | |
6206 G_CALLBACK(focus_win_cb), win); | |
6207 | |
6208 /* Create the notebook. */ | |
6209 win->notebook = gtk_notebook_new(); | |
6210 | |
6211 pos = gaim_prefs_get_int("/gaim/gtk/conversations/tab_side"); | |
6212 | |
6213 #if 0 | |
6214 gtk_notebook_set_tab_hborder(GTK_NOTEBOOK(win->notebook), 0); | |
6215 gtk_notebook_set_tab_vborder(GTK_NOTEBOOK(win->notebook), 0); | |
6216 #endif | |
6217 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos); | |
6218 gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE); | |
6219 gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook)); | |
6220 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); | |
6221 gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), FALSE); | |
6222 | |
6223 gtk_widget_show(win->notebook); | |
6224 | |
6225 g_signal_connect(G_OBJECT(win->notebook), "switch_page", | |
6226 G_CALLBACK(before_switch_conv_cb), win); | |
6227 g_signal_connect_after(G_OBJECT(win->notebook), "switch_page", | |
6228 G_CALLBACK(switch_conv_cb), win); | |
6229 | |
6230 /* Setup the tab drag and drop signals. */ | |
6231 gtk_widget_add_events(win->notebook, | |
6232 GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); | |
6233 g_signal_connect(G_OBJECT(win->notebook), "button_press_event", | |
6234 G_CALLBACK(notebook_press_cb), win); | |
6235 g_signal_connect(G_OBJECT(win->notebook), "button_release_event", | |
6236 G_CALLBACK(notebook_release_cb), win); | |
6237 | |
6238 testidea = gtk_vbox_new(FALSE, 0); | |
6239 | |
6240 /* Setup the menubar. */ | |
6241 menubar = setup_menubar(win); | |
6242 gtk_box_pack_start(GTK_BOX(testidea), menubar, FALSE, TRUE, 0); | |
6243 | |
6244 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); | |
6245 | |
6246 gtk_container_add(GTK_CONTAINER(win->window), testidea); | |
6247 | |
6248 gtk_widget_show(testidea); | |
6249 | |
6250 return win; | |
6251 } | |
6252 | |
6253 void | |
6254 gaim_gtk_conv_window_destroy(GaimGtkWindow *win) | |
6255 { | |
6256 window_list = g_list_remove(window_list, win); | |
6257 | |
6258 gtk_widget_destroy(win->window); | |
6259 | |
6260 g_object_unref(G_OBJECT(win->menu.item_factory)); | |
6261 | |
6262 g_free(win); | |
6263 } | |
6264 | |
6265 void | |
6266 gaim_gtk_conv_window_show(GaimGtkWindow *win) | |
6267 { | |
6268 gtk_widget_show(win->window); | |
6269 } | |
6270 | |
6271 void | |
6272 gaim_gtk_conv_window_hide(GaimGtkWindow *win) | |
6273 { | |
6274 gtk_widget_hide(win->window); | |
6275 } | |
6276 | |
6277 void | |
6278 gaim_gtk_conv_window_raise(GaimGtkWindow *win) | |
6279 { | |
6280 gtk_widget_show(win->window); | |
6281 gtk_window_deiconify(GTK_WINDOW(win->window)); | |
6282 gdk_window_raise(win->window->window); | |
6283 } | |
6284 | |
6285 void | |
6286 gaim_gtk_conv_window_switch_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv) | |
6287 { | |
6288 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), | |
6289 gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), | |
6290 gtkconv->tab_cont)); | |
6291 } | |
6292 | |
6293 void | |
6294 gaim_gtk_conv_window_add_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv) | |
6295 { | |
6296 GaimConversation *conv = gtkconv->active_conv; | |
6297 GaimGtkConversation *focus_gtkconv; | |
6298 GtkWidget *tabby, *menu_tabby; | |
6299 GtkWidget *tab_cont = gtkconv->tab_cont; | |
6300 GtkWidget *close_image; | |
6301 GaimConversationType conv_type; | |
6302 const char *name; | |
6303 const gchar *tmp_lab; | |
6304 gint close_button_width, close_button_height, focus_width, focus_pad; | |
6305 | |
6306 name = gaim_conversation_get_name(conv); | |
6307 conv_type = gaim_conversation_get_type(conv); | |
6308 | |
6309 | |
6310 win->gtkconvs = g_list_append(win->gtkconvs, gtkconv); | |
6311 gtkconv->win = win; | |
6312 | |
6313 gtkconv->tabby = tabby = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
6314 gtkconv->menu_tabby = menu_tabby = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
6315 | |
6316 /* Close button. */ | |
6317 gtkconv->close = gtk_button_new(); | |
6318 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &close_button_width, &close_button_height); | |
6319 if (gtk_check_version(2, 4, 2) == NULL) { | |
6320 /* Need to account for extra padding around the gtkbutton */ | |
6321 gtk_widget_style_get(GTK_WIDGET(gtkconv->close), | |
6322 "focus-line-width", &focus_width, | |
6323 "focus-padding", &focus_pad, | |
6324 NULL); | |
6325 close_button_width += (focus_width + focus_pad) * 2; | |
6326 close_button_height += (focus_width + focus_pad) * 2; | |
6327 } | |
6328 gtk_widget_set_size_request(GTK_WIDGET(gtkconv->close), | |
6329 close_button_width, close_button_height); | |
6330 | |
6331 gtk_button_set_relief(GTK_BUTTON(gtkconv->close), GTK_RELIEF_NONE); | |
6332 close_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); | |
6333 gtk_widget_show(close_image); | |
6334 gtk_container_add(GTK_CONTAINER(gtkconv->close), close_image); | |
6335 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, | |
6336 _("Close conversation"), NULL); | |
6337 | |
6338 g_signal_connect(G_OBJECT(gtkconv->close), "clicked", | |
6339 G_CALLBACK(close_conv_cb), gtkconv); | |
6340 | |
6341 /* | |
6342 * I love Galeon. They have a fix for that stupid annoying visible | |
6343 * border bug. I love you guys! -- ChipX86 | |
6344 */ | |
6345 g_signal_connect(G_OBJECT(gtkconv->close), "state_changed", | |
6346 G_CALLBACK(tab_close_button_state_changed_cb), NULL); | |
6347 | |
6348 /* Status icon. */ | |
6349 gtkconv->icon = gtk_image_new(); | |
6350 gtkconv->menu_icon = gtk_image_new(); | |
6351 update_tab_icon(conv); | |
6352 | |
6353 /* Tab label. */ | |
6354 gtkconv->tab_label = gtk_label_new(tmp_lab = gaim_conversation_get_title(conv)); | |
6355 #if GTK_CHECK_VERSION(2,6,0) | |
6356 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); | |
6357 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); | |
6358 #endif | |
6359 gtkconv->menu_label = gtk_label_new(gaim_conversation_get_title(conv)); | |
6360 #if 0 | |
6361 gtk_misc_set_alignment(GTK_MISC(gtkconv->tab_label), 0.00, 0.5); | |
6362 gtk_misc_set_padding(GTK_MISC(gtkconv->tab_label), 4, 0); | |
6363 #endif | |
6364 | |
6365 /* Pack it all together. */ | |
6366 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->icon, FALSE, FALSE, 0); | |
6367 gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_icon, | |
6368 FALSE, FALSE, 0); | |
6369 | |
6370 gtk_widget_show_all(gtkconv->icon); | |
6371 gtk_widget_show_all(gtkconv->menu_icon); | |
6372 | |
6373 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->tab_label, TRUE, TRUE, 0); | |
6374 gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0); | |
6375 gtk_widget_show(gtkconv->tab_label); | |
6376 gtk_widget_show(gtkconv->menu_label); | |
6377 gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0); | |
6378 | |
6379 gtk_box_pack_start(GTK_BOX(tabby), gtkconv->close, FALSE, FALSE, 0); | |
6380 if (gaim_prefs_get_bool("/gaim/gtk/conversations/close_on_tabs")) | |
6381 gtk_widget_show(gtkconv->close); | |
6382 | |
6383 gtk_widget_show(tabby); | |
6384 gtk_widget_show(menu_tabby); | |
6385 | |
6386 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) | |
6387 gaim_gtkconv_update_buddy_icon(conv); | |
6388 | |
6389 /* Add this pane to the conversation's notebook. */ | |
6390 gtk_notebook_append_page_menu(GTK_NOTEBOOK(win->notebook), tab_cont, tabby, menu_tabby); | |
6391 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), tab_cont, TRUE, TRUE, GTK_PACK_START); | |
6392 | |
6393 | |
6394 gtk_widget_show(tab_cont); | |
6395 | |
6396 if (gaim_gtk_conv_window_get_gtkconv_count(win) == 1) { | |
6397 /* Er, bug in notebooks? Switch to the page manually. */ | |
6398 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); | |
6399 | |
6400 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), | |
6401 gaim_prefs_get_bool("/gaim/gtk/conversations/tabs")); | |
6402 } else | |
6403 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE); | |
6404 | |
6405 focus_gtkconv = g_list_nth_data(gaim_gtk_conv_window_get_gtkconvs(win), | |
6406 gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook))); | |
6407 gtk_widget_grab_focus(focus_gtkconv->entry); | |
6408 | |
6409 if (gaim_gtk_conv_window_get_gtkconv_count(win) == 1) | |
6410 g_timeout_add(0, (GSourceFunc)update_send_as_selection, win); | |
6411 } | |
6412 | |
6413 void | |
6414 gaim_gtk_conv_window_remove_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv) | |
6415 { | |
6416 unsigned int index; | |
6417 GaimConversationType conv_type; | |
6418 | |
6419 conv_type = gaim_conversation_get_type(gtkconv->active_conv); | |
6420 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); | |
6421 | |
6422 g_object_ref(gtkconv->tab_cont); | |
6423 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); | |
6424 | |
6425 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); | |
6426 | |
6427 /* go back to tabless if need be */ | |
6428 if (gaim_gtk_conv_window_get_gtkconv_count(win) <= 2) { | |
6429 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), | |
6430 gaim_prefs_get_bool("/gaim/gtk/conversations/tabs")); | |
6431 } | |
6432 | |
6433 | |
6434 /* If this window is setup with an inactive gc, regenerate the menu. */ | |
6435 | |
6436 if (conv_type == GAIM_CONV_TYPE_IM && | |
6437 gaim_conversation_get_gc(gtkconv->active_conv) == NULL) { | |
6438 generate_send_as_items(win, gtkconv->active_conv); | |
6439 } | |
6440 | |
6441 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); | |
6442 } | |
6443 | |
6444 GaimGtkConversation * | |
6445 gaim_gtk_conv_window_get_gtkconv_at_index(const GaimGtkWindow *win, int index) | |
6446 { | |
6447 GtkWidget *tab_cont; | |
6448 | |
6449 if (index == -1) | |
6450 index = 0; | |
6451 tab_cont = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), index); | |
6452 return g_object_get_data(G_OBJECT(tab_cont), "GaimGtkConversation"); | |
6453 } | |
6454 | |
6455 GaimGtkConversation * | |
6456 gaim_gtk_conv_window_get_active_gtkconv(const GaimGtkWindow *win) | |
6457 { | |
6458 int index; | |
6459 GtkWidget *tab_cont; | |
6460 | |
6461 index = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook)); | |
6462 if (index == -1) | |
6463 index = 0; | |
6464 tab_cont = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), index); | |
6465 if (!tab_cont) | |
6466 return NULL; | |
6467 return g_object_get_data(G_OBJECT(tab_cont), "GaimGtkConversation"); | |
6468 } | |
6469 | |
6470 | |
6471 GaimConversation * | |
6472 gaim_gtk_conv_window_get_active_conversation(const GaimGtkWindow *win) | |
6473 { | |
6474 GaimGtkConversation *gtkconv; | |
6475 | |
6476 gtkconv = gaim_gtk_conv_window_get_active_gtkconv(win); | |
6477 return gtkconv ? gtkconv->active_conv : NULL; | |
6478 } | |
6479 | |
6480 gboolean | |
6481 gaim_gtk_conv_window_is_active_conversation(const GaimConversation *conv) | |
6482 { | |
6483 return conv == gaim_gtk_conv_window_get_active_conversation(GAIM_GTK_CONVERSATION(conv)->win); | |
6484 } | |
6485 | |
6486 gboolean | |
6487 gaim_gtk_conv_window_has_focus(GaimGtkWindow *win) | |
6488 { | |
6489 gboolean has_focus = FALSE; | |
6490 | |
6491 g_object_get(G_OBJECT(win->window), "has-toplevel-focus", &has_focus, NULL); | |
6492 | |
6493 return has_focus; | |
6494 } | |
6495 | |
6496 GaimGtkWindow * | |
6497 gaim_gtk_conv_window_get_at_xy(int x, int y) | |
6498 { | |
6499 GaimGtkWindow *win; | |
6500 GdkWindow *gdkwin; | |
6501 GList *l; | |
6502 | |
6503 gdkwin = gdk_window_at_pointer(&x, &y); | |
6504 | |
6505 if (gdkwin) | |
6506 gdkwin = gdk_window_get_toplevel(gdkwin); | |
6507 | |
6508 for (l = gaim_gtk_conv_windows_get_list(); l != NULL; l = l->next) { | |
6509 win = l->data; | |
6510 | |
6511 if (gdkwin == win->window->window) | |
6512 return win; | |
6513 } | |
6514 | |
6515 return NULL; | |
6516 } | |
6517 | |
6518 GList * | |
6519 gaim_gtk_conv_window_get_gtkconvs(GaimGtkWindow *win) | |
6520 { | |
6521 return win->gtkconvs; | |
6522 } | |
6523 | |
6524 guint | |
6525 gaim_gtk_conv_window_get_gtkconv_count(GaimGtkWindow *win) | |
6526 { | |
6527 return g_list_length(win->gtkconvs); | |
6528 } | |
6529 | |
6530 GaimGtkWindow * | |
6531 gaim_gtk_conv_window_first_with_type(GaimConversationType type) | |
6532 { | |
6533 GList *wins, *convs; | |
6534 GaimGtkWindow *win; | |
6535 GaimGtkConversation *conv; | |
6536 | |
6537 if (type == GAIM_CONV_TYPE_UNKNOWN) | |
6538 return NULL; | |
6539 | |
6540 for (wins = gaim_gtk_conv_windows_get_list(); wins != NULL; wins = wins->next) { | |
6541 win = wins->data; | |
6542 | |
6543 for (convs = win->gtkconvs; | |
6544 convs != NULL; | |
6545 convs = convs->next) { | |
6546 | |
6547 conv = convs->data; | |
6548 | |
6549 if (gaim_conversation_get_type(conv->active_conv) == type) | |
6550 return win; | |
6551 } | |
6552 } | |
6553 | |
6554 return NULL; | |
6555 } | |
6556 | |
6557 GaimGtkWindow * | |
6558 gaim_gtk_conv_window_last_with_type(GaimConversationType type) | |
6559 { | |
6560 GList *wins, *convs; | |
6561 GaimGtkWindow *win; | |
6562 GaimGtkConversation *conv; | |
6563 | |
6564 if (type == GAIM_CONV_TYPE_UNKNOWN) | |
6565 return NULL; | |
6566 | |
6567 for (wins = g_list_last(gaim_gtk_conv_windows_get_list()); | |
6568 wins != NULL; | |
6569 wins = wins->prev) { | |
6570 | |
6571 win = wins->data; | |
6572 | |
6573 for (convs = win->gtkconvs; | |
6574 convs != NULL; | |
6575 convs = convs->next) { | |
6576 | |
6577 conv = convs->data; | |
6578 | |
6579 if (gaim_conversation_get_type(conv->active_conv) == type) | |
6580 return win; | |
6581 } | |
6582 } | |
6583 | |
6584 return NULL; | |
6585 } | |
6586 | |
6587 | |
6588 /************************************************************************** | |
6589 * Conversation placement functions | |
6590 **************************************************************************/ | |
6591 typedef struct | |
6592 { | |
6593 char *id; | |
6594 char *name; | |
6595 GaimConvPlacementFunc fnc; | |
6596 | |
6597 } ConvPlacementData; | |
6598 | |
6599 static GList *conv_placement_fncs = NULL; | |
6600 static GaimConvPlacementFunc place_conv = NULL; | |
6601 | |
6602 /* This one places conversations in the last made window. */ | |
6603 static void | |
6604 conv_placement_last_created_win(GaimGtkConversation *conv) | |
6605 { | |
6606 GaimGtkWindow *win; | |
6607 | |
6608 GList *l = g_list_last(gaim_gtk_conv_windows_get_list()); | |
6609 win = l ? l->data : NULL;; | |
6610 | |
6611 if (win == NULL) { | |
6612 win = gaim_gtk_conv_window_new(); | |
6613 | |
6614 gaim_gtk_conv_window_add_gtkconv(win, conv); | |
6615 gaim_gtk_conv_window_show(win); | |
6616 } else { | |
6617 gaim_gtk_conv_window_add_gtkconv(win, conv); | |
6618 } | |
6619 } | |
6620 | |
6621 /* This one places conversations in the last made window of the same type. */ | |
6622 static void | |
6623 conv_placement_last_created_win_type(GaimGtkConversation *conv) | |
6624 { | |
6625 GaimGtkWindow *win; | |
6626 | |
6627 win = gaim_gtk_conv_window_last_with_type(gaim_conversation_get_type(conv->active_conv)); | |
6628 | |
6629 if (win == NULL) { | |
6630 win = gaim_gtk_conv_window_new(); | |
6631 | |
6632 gaim_gtk_conv_window_add_gtkconv(win, conv); | |
6633 gaim_gtk_conv_window_show(win); | |
6634 } else | |
6635 gaim_gtk_conv_window_add_gtkconv(win, conv); | |
6636 } | |
6637 | |
6638 /* This one places each conversation in its own window. */ | |
6639 static void | |
6640 conv_placement_new_window(GaimGtkConversation *conv) | |
6641 { | |
6642 GaimGtkWindow *win; | |
6643 | |
6644 win = gaim_gtk_conv_window_new(); | |
6645 | |
6646 gaim_gtk_conv_window_add_gtkconv(win, conv); | |
6647 | |
6648 gaim_gtk_conv_window_show(win); | |
6649 } | |
6650 | |
6651 static GaimGroup * | |
6652 conv_get_group(GaimGtkConversation *conv) | |
6653 { | |
6654 GaimGroup *group = NULL; | |
6655 | |
6656 if (gaim_conversation_get_type(conv->active_conv) == GAIM_CONV_TYPE_IM) { | |
6657 GaimBuddy *buddy; | |
6658 | |
6659 buddy = gaim_find_buddy(gaim_conversation_get_account(conv->active_conv), | |
6660 gaim_conversation_get_name(conv->active_conv)); | |
6661 | |
6662 if (buddy != NULL) | |
6663 group = gaim_find_buddys_group(buddy); | |
6664 | |
6665 } else if (gaim_conversation_get_type(conv->active_conv) == GAIM_CONV_TYPE_CHAT) { | |
6666 GaimChat *chat; | |
6667 | |
6668 chat = gaim_blist_find_chat(gaim_conversation_get_account(conv->active_conv), | |
6669 gaim_conversation_get_name(conv->active_conv)); | |
6670 | |
6671 if (chat != NULL) | |
6672 group = gaim_chat_get_group(chat); | |
6673 } | |
6674 | |
6675 return group; | |
6676 } | |
6677 | |
6678 /* | |
6679 * This groups things by, well, group. Buddies from groups will always be | |
6680 * grouped together, and a buddy from a group not belonging to any currently | |
6681 * open windows will get a new window. | |
6682 */ | |
6683 static void | |
6684 conv_placement_by_group(GaimGtkConversation *conv) | |
6685 { | |
6686 GaimConversationType type; | |
6687 GaimGroup *group = NULL; | |
6688 GList *wl, *cl; | |
6689 | |
6690 type = gaim_conversation_get_type(conv->active_conv); | |
6691 | |
6692 group = conv_get_group(conv); | |
6693 | |
6694 /* Go through the list of IMs and find one with this group. */ | |
6695 for (wl = gaim_gtk_conv_windows_get_list(); wl != NULL; wl = wl->next) { | |
6696 GaimGtkWindow *win2; | |
6697 GaimGtkConversation *conv2; | |
6698 GaimGroup *group2 = NULL; | |
6699 | |
6700 win2 = wl->data; | |
6701 | |
6702 for (cl = win2->gtkconvs; | |
6703 cl != NULL; | |
6704 cl = cl->next) { | |
6705 conv2 = cl->data; | |
6706 | |
6707 group2 = conv_get_group(conv2); | |
6708 | |
6709 if (group == group2) { | |
6710 gaim_gtk_conv_window_add_gtkconv(win2, conv); | |
6711 | |
6712 return; | |
6713 } | |
6714 } | |
6715 } | |
6716 | |
6717 /* Make a new window. */ | |
6718 conv_placement_new_window(conv); | |
6719 } | |
6720 | |
6721 /* This groups things by account. Otherwise, the same semantics as above */ | |
6722 static void | |
6723 conv_placement_by_account(GaimGtkConversation *conv) | |
6724 { | |
6725 GaimConversationType type; | |
6726 GList *wins, *convs; | |
6727 GaimAccount *account; | |
6728 | |
6729 account = gaim_conversation_get_account(conv->active_conv); | |
6730 type = gaim_conversation_get_type(conv->active_conv); | |
6731 | |
6732 /* Go through the list of IMs and find one with this group. */ | |
6733 for (wins = gaim_gtk_conv_windows_get_list(); wins != NULL; wins = wins->next) { | |
6734 GaimGtkWindow *win2; | |
6735 GaimGtkConversation *conv2; | |
6736 | |
6737 win2 = wins->data; | |
6738 | |
6739 for (convs = win2->gtkconvs; | |
6740 convs != NULL; | |
6741 convs = convs->next) { | |
6742 conv2 = convs->data; | |
6743 | |
6744 if (account == gaim_conversation_get_account(conv2->active_conv)) { | |
6745 gaim_gtk_conv_window_add_gtkconv(win2, conv); | |
6746 return; | |
6747 } | |
6748 } | |
6749 } | |
6750 | |
6751 /* Make a new window. */ | |
6752 conv_placement_new_window(conv); | |
6753 } | |
6754 | |
6755 static ConvPlacementData * | |
6756 get_conv_placement_data(const char *id) | |
6757 { | |
6758 ConvPlacementData *data = NULL; | |
6759 GList *n; | |
6760 | |
6761 for (n = conv_placement_fncs; n; n = n->next) { | |
6762 data = n->data; | |
6763 if (!strcmp(data->id, id)) | |
6764 return data; | |
6765 } | |
6766 | |
6767 return NULL; | |
6768 } | |
6769 | |
6770 static void | |
6771 add_conv_placement_fnc(const char *id, const char *name, | |
6772 GaimConvPlacementFunc fnc) | |
6773 { | |
6774 ConvPlacementData *data; | |
6775 | |
6776 data = g_new(ConvPlacementData, 1); | |
6777 | |
6778 data->id = g_strdup(id); | |
6779 data->name = g_strdup(name); | |
6780 data->fnc = fnc; | |
6781 | |
6782 conv_placement_fncs = g_list_append(conv_placement_fncs, data); | |
6783 } | |
6784 | |
6785 static void | |
6786 ensure_default_funcs(void) | |
6787 { | |
6788 if (conv_placement_fncs == NULL) { | |
6789 add_conv_placement_fnc("last", _("Last created window"), | |
6790 conv_placement_last_created_win); | |
6791 add_conv_placement_fnc("im_chat", _("Separate IM and Chat windows"), | |
6792 conv_placement_last_created_win_type); | |
6793 add_conv_placement_fnc("new", _("New window"), | |
6794 conv_placement_new_window); | |
6795 add_conv_placement_fnc("group", _("By group"), | |
6796 conv_placement_by_group); | |
6797 add_conv_placement_fnc("account", _("By account"), | |
6798 conv_placement_by_account); | |
6799 } | |
6800 } | |
6801 | |
6802 GList * | |
6803 gaim_gtkconv_placement_get_options(void) | |
6804 { | |
6805 GList *n, *list = NULL; | |
6806 ConvPlacementData *data; | |
6807 | |
6808 ensure_default_funcs(); | |
6809 | |
6810 for (n = conv_placement_fncs; n; n = n->next) { | |
6811 data = n->data; | |
6812 list = g_list_append(list, data->name); | |
6813 list = g_list_append(list, data->id); | |
6814 } | |
6815 | |
6816 return list; | |
6817 } | |
6818 | |
6819 | |
6820 void | |
6821 gaim_gtkconv_placement_add_fnc(const char *id, const char *name, | |
6822 GaimConvPlacementFunc fnc) | |
6823 { | |
6824 g_return_if_fail(id != NULL); | |
6825 g_return_if_fail(name != NULL); | |
6826 g_return_if_fail(fnc != NULL); | |
6827 | |
6828 ensure_default_funcs(); | |
6829 | |
6830 add_conv_placement_fnc(id, name, fnc); | |
6831 } | |
6832 | |
6833 void | |
6834 gaim_gtkconv_placement_remove_fnc(const char *id) | |
6835 { | |
6836 ConvPlacementData *data = get_conv_placement_data(id); | |
6837 | |
6838 if (data == NULL) | |
6839 return; | |
6840 | |
6841 conv_placement_fncs = g_list_remove(conv_placement_fncs, data); | |
6842 | |
6843 g_free(data->id); | |
6844 g_free(data->name); | |
6845 g_free(data); | |
6846 } | |
6847 | |
6848 const char * | |
6849 gaim_gtkconv_placement_get_name(const char *id) | |
6850 { | |
6851 ConvPlacementData *data; | |
6852 | |
6853 ensure_default_funcs(); | |
6854 | |
6855 data = get_conv_placement_data(id); | |
6856 | |
6857 if (data == NULL) | |
6858 return NULL; | |
6859 | |
6860 return data->name; | |
6861 } | |
6862 | |
6863 GaimConvPlacementFunc | |
6864 gaim_gtkconv_placement_get_fnc(const char *id) | |
6865 { | |
6866 ConvPlacementData *data; | |
6867 | |
6868 ensure_default_funcs(); | |
6869 | |
6870 data = get_conv_placement_data(id); | |
6871 | |
6872 if (data == NULL) | |
6873 return NULL; | |
6874 | |
6875 return data->fnc; | |
6876 } | |
6877 | |
6878 void | |
6879 gaim_gtkconv_placement_set_current_func(GaimConvPlacementFunc func) | |
6880 { | |
6881 g_return_if_fail(func != NULL); | |
6882 | |
6883 place_conv = func; | |
6884 } | |
6885 | |
6886 GaimConvPlacementFunc | |
6887 gaim_gtkconv_placement_get_current_func(void) | |
6888 { | |
6889 return place_conv; | |
6890 } | |
6891 | |
6892 void | |
6893 gaim_gtkconv_placement_place(GaimGtkConversation *gtkconv) | |
6894 { | |
6895 if (place_conv) | |
6896 place_conv(gtkconv); | |
6897 } |