pidgin/gtkconv.c

changeset 41323
21185b889103
parent 41319
04d027ed3d63
child 41378
14cda54c3fbf
equal deleted inserted replaced
41321:97b0dbc1873f 41323:21185b889103
60 /* 60 /*
61 * A GTK Instant Message pane. 61 * A GTK Instant Message pane.
62 */ 62 */
63 struct _PidginImPane 63 struct _PidginImPane
64 { 64 {
65 GtkWidget *block;
66 GtkWidget *send_file;
67 GtkWidget *sep1;
68 GtkWidget *sep2;
69 GtkWidget *check;
70 GtkWidget *progress;
71 guint32 typing_timer; 65 guint32 typing_timer;
72
73 GtkWidget *avatar;
74 }; 66 };
75 67
76 /* 68 /*
77 * GTK Chat panes. 69 * GTK Chat panes.
78 */ 70 */
100 92
101 static GtkWidget *invite_dialog = NULL; 93 static GtkWidget *invite_dialog = NULL;
102 94
103 /* Prototypes. <-- because Paco-Paco hates this comment. */ 95 /* Prototypes. <-- because Paco-Paco hates this comment. */
104 static void got_typing_keypress(PidginConversation *gtkconv, gboolean first); 96 static void got_typing_keypress(PidginConversation *gtkconv, gboolean first);
105 static void gray_stuff_out(PidginConversation *gtkconv);
106 static void add_chat_user_common(PurpleChatConversation *chat, PurpleChatUser *cb, const char *old_name); 97 static void add_chat_user_common(PurpleChatConversation *chat, PurpleChatUser *cb, const char *old_name);
107 static void pidgin_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type); 98 static void pidgin_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type);
108 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state);
109 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state);
110 static void update_typing_icon(PidginConversation *gtkconv); 99 static void update_typing_icon(PidginConversation *gtkconv);
111 gboolean pidgin_conv_has_focus(PurpleConversation *conv); 100 gboolean pidgin_conv_has_focus(PurpleConversation *conv);
112 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); 101 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields);
113 102
114 static void pidgin_conv_placement_place(PidginConversation *conv); 103 static void pidgin_conv_placement_place(PidginConversation *conv);
150 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", allocation->width == 1 ? 0 : allocation->width); 139 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", allocation->width == 1 ? 0 : allocation->width);
151 140
152 return FALSE; 141 return FALSE;
153 } 142 }
154 143
155 static const char *
156 pidgin_get_cmd_prefix(void)
157 {
158 return "/";
159 }
160
161
162 static void clear_conversation_scrollback_cb(PurpleConversation *conv,
163 void *data)
164 {
165 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
166
167 if (PIDGIN_CONVERSATION(conv)) {
168 gtkconv->last_flags = 0;
169 }
170 }
171
172 static void 144 static void
173 send_history_add(PidginConversation *gtkconv, const char *message) 145 send_history_add(PidginConversation *gtkconv, const char *message)
174 { 146 {
175 GList *first; 147 GList *first;
176 148
189 gchar *cmd; 161 gchar *cmd;
190 const gchar *prefix; 162 const gchar *prefix;
191 gboolean retval = FALSE; 163 gboolean retval = FALSE;
192 164
193 gtkconv = PIDGIN_CONVERSATION(conv); 165 gtkconv = PIDGIN_CONVERSATION(conv);
194 prefix = pidgin_get_cmd_prefix(); 166 prefix = "/";
195 167
196 input = talkatu_editor_get_input(TALKATU_EDITOR(gtkconv->editor)); 168 input = talkatu_editor_get_input(TALKATU_EDITOR(gtkconv->editor));
197 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(input)); 169 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(input));
198 170
199 cmd = talkatu_buffer_get_plain_text(TALKATU_BUFFER(buffer)); 171 cmd = talkatu_buffer_get_plain_text(TALKATU_BUFFER(buffer));
333 purple_conversation_send_with_flags(conv, content, flags); 305 purple_conversation_send_with_flags(conv, content, flags);
334 306
335 g_free(content); 307 g_free(content);
336 308
337 talkatu_buffer_clear(TALKATU_BUFFER(buffer)); 309 talkatu_buffer_clear(TALKATU_BUFFER(buffer));
338 gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE);
339 } 310 }
340 311
341 static void 312 static void
342 add_remove_cb(GtkWidget *widget, PidginConversation *gtkconv) 313 add_remove_cb(GtkWidget *widget, PidginConversation *gtkconv)
343 { 314 {
1195 1166
1196 gtkconv->active_conv = conv; 1167 gtkconv->active_conv = conv;
1197 1168
1198 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); 1169 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
1199 1170
1200 gray_stuff_out(gtkconv);
1201 update_typing_icon(gtkconv); 1171 update_typing_icon(gtkconv);
1202 g_object_set_data(G_OBJECT(gtkconv->entry), "transient_buddy", NULL); 1172 g_object_set_data(G_OBJECT(gtkconv->entry), "transient_buddy", NULL);
1203 }
1204
1205 void
1206 pidgin_conv_present_conversation(PurpleConversation *conv)
1207 {
1208 #if 0
1209 PidginConversation *gtkconv;
1210 GdkModifierType state;
1211
1212 pidgin_conv_attach_to_conversation(conv);
1213 gtkconv = PIDGIN_CONVERSATION(conv);
1214
1215 pidgin_conv_switch_active_conversation(conv);
1216 /* Switch the tab only if the user initiated the event by pressing
1217 * a button or hitting a key. */
1218 if (gtk_get_current_event_state(&state))
1219 pidgin_conv_window_switch_gtkconv(gtkconv->win, gtkconv);
1220 gtk_window_present(GTK_WINDOW(gtkconv->win->window));
1221 #endif
1222 }
1223
1224 static GList *
1225 pidgin_conversations_get_unseen(GList *l,
1226 PidginUnseenState min_state,
1227 guint max_count)
1228 {
1229 GList *r = NULL;
1230 guint c = 0;
1231
1232 for (; l != NULL && (max_count == 0 || c < max_count); l = l->next) {
1233 PurpleConversation *conv = (PurpleConversation*)l->data;
1234 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
1235
1236 if(gtkconv == NULL || gtkconv->active_conv != conv) {
1237 continue;
1238 }
1239
1240 if (gtkconv->unseen_state >= min_state) {
1241 r = g_list_prepend(r, conv);
1242 c++;
1243 }
1244 }
1245
1246 return r;
1247 }
1248
1249 GList *
1250 pidgin_conversations_get_unseen_all(PidginUnseenState min_state,
1251 guint max_count)
1252 {
1253 PurpleConversationManager *manager;
1254 GList *list, *ret = NULL;
1255
1256 manager = purple_conversation_manager_get_default();
1257 list = purple_conversation_manager_get_all(manager);
1258
1259 ret = pidgin_conversations_get_unseen(list, min_state, max_count);
1260 g_list_free(list);
1261
1262 return ret;
1263 } 1173 }
1264 1174
1265 static GtkActionEntry menu_entries[] = 1175 static GtkActionEntry menu_entries[] =
1266 /* TODO: fill out tooltips... */ 1176 /* TODO: fill out tooltips... */
1267 { 1177 {
2022 g_object_set_data(G_OBJECT(conv), "pidgin", gtkconv); 1932 g_object_set_data(G_OBJECT(conv), "pidgin", gtkconv);
2023 gtkconv->active_conv = conv; 1933 gtkconv->active_conv = conv;
2024 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 1934 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
2025 gtkconv->send_history = g_list_append(NULL, NULL); 1935 gtkconv->send_history = g_list_append(NULL, NULL);
2026 1936
2027 /* Setup some initial variables. */
2028 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
2029 gtkconv->unseen_count = 0;
2030 gtkconv->last_flags = 0;
2031
2032 if (PURPLE_IS_IM_CONVERSATION(conv)) { 1937 if (PURPLE_IS_IM_CONVERSATION(conv)) {
2033 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 1938 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
2034 } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { 1939 } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
2035 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 1940 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
2036 } 1941 }
2067 gtkconv->editor); 1972 gtkconv->editor);
2068 1973
2069 pidgin_conv_placement_place(gtkconv); 1974 pidgin_conv_placement_place(gtkconv);
2070 } 1975 }
2071 1976
2072 void 1977 static void
2073 pidgin_conv_new(PurpleConversation *conv) 1978 pidgin_conv_new(PurpleConversation *conv)
2074 { 1979 {
2075 private_gtkconv_new(conv, FALSE); 1980 private_gtkconv_new(conv, FALSE);
2076 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) 1981 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv))
2077 purple_signal_emit(pidgin_conversations_get_handle(), 1982 purple_signal_emit(pidgin_conversations_get_handle(),
2214 pidgin_msg = pidgin_message_new(pmsg); 2119 pidgin_msg = pidgin_message_new(pmsg);
2215 talkatu_history_write_message( 2120 talkatu_history_write_message(
2216 TALKATU_HISTORY(gtkconv->history), 2121 TALKATU_HISTORY(gtkconv->history),
2217 TALKATU_MESSAGE(pidgin_msg) 2122 TALKATU_MESSAGE(pidgin_msg)
2218 ); 2123 );
2219
2220 /* Tab highlighting stuff */
2221 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
2222 {
2223 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
2224
2225 if ((flags & PURPLE_MESSAGE_NICK) == PURPLE_MESSAGE_NICK)
2226 unseen = PIDGIN_UNSEEN_NICK;
2227 else if (((flags & PURPLE_MESSAGE_SYSTEM) == PURPLE_MESSAGE_SYSTEM) ||
2228 ((flags & PURPLE_MESSAGE_ERROR) == PURPLE_MESSAGE_ERROR))
2229 unseen = PIDGIN_UNSEEN_EVENT;
2230 else if ((flags & PURPLE_MESSAGE_NO_LOG) == PURPLE_MESSAGE_NO_LOG)
2231 unseen = PIDGIN_UNSEEN_NO_LOG;
2232 else
2233 unseen = PIDGIN_UNSEEN_TEXT;
2234
2235 gtkconv_set_unseen(gtkconv, unseen);
2236 }
2237 2124
2238 purple_signal_emit(pidgin_conversations_get_handle(), 2125 purple_signal_emit(pidgin_conversations_get_handle(),
2239 (PURPLE_IS_IM_CONVERSATION(conv) ? "displayed-im-msg" : "displayed-chat-msg"), 2126 (PURPLE_IS_IM_CONVERSATION(conv) ? "displayed-im-msg" : "displayed-chat-msg"),
2240 conv, pmsg); 2127 conv, pmsg);
2241 } 2128 }
2432 } 2319 }
2433 2320
2434 return FALSE; 2321 return FALSE;
2435 } 2322 }
2436 2323
2437 /*
2438 * Makes sure all the menu items and all the buttons are hidden/shown and
2439 * sensitive/insensitive. This is called after changing tabs and when an
2440 * account signs on or off.
2441 */
2442 static void
2443 gray_stuff_out(PidginConversation *gtkconv)
2444 {
2445 /* This will be replaced by managing an action group in the new conversation
2446 * window.
2447 */
2448 #if 0
2449 PidginConvWindow *win;
2450 PurpleConversation *conv = gtkconv->active_conv;
2451 PurpleConnection *gc;
2452 PurpleProtocol *protocol = NULL;
2453 PurpleAccount *account;
2454
2455 win = pidgin_conv_get_window(gtkconv);
2456 gc = purple_conversation_get_connection(conv);
2457 account = purple_conversation_get_account(conv);
2458
2459 if (gc != NULL)
2460 protocol = purple_connection_get_protocol(gc);
2461
2462 /*
2463 * Handle hiding and showing stuff based on what type of conv this is.
2464 * Stuff that Purple IMs support in general should be shown for IM
2465 * conversations. Stuff that Purple chats support in general should be
2466 * shown for chat conversations. It doesn't matter whether the protocol
2467 * supports it or not--that only affects if the button or menu item
2468 * is sensitive or not.
2469 */
2470 if (PURPLE_IS_IM_CONVERSATION(conv)) {
2471 /* Show stuff that applies to IMs, hide stuff that applies to chats */
2472
2473 /* Deal with menu items */
2474 gtk_action_set_visible(win->menu->view_log, TRUE);
2475 gtk_action_set_visible(win->menu->send_file, TRUE);
2476 gtk_action_set_visible(win->menu->get_info, TRUE);
2477 gtk_action_set_visible(win->menu->invite, FALSE);
2478 gtk_action_set_visible(win->menu->alias, TRUE);
2479 if (purple_account_privacy_check(account, purple_conversation_get_name(conv))) {
2480 gtk_action_set_visible(win->menu->unblock, FALSE);
2481 gtk_action_set_visible(win->menu->block, TRUE);
2482 } else {
2483 gtk_action_set_visible(win->menu->block, FALSE);
2484 gtk_action_set_visible(win->menu->unblock, TRUE);
2485 }
2486
2487 if (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) == NULL) {
2488 gtk_action_set_visible(win->menu->add, TRUE);
2489 gtk_action_set_visible(win->menu->remove, FALSE);
2490 } else {
2491 gtk_action_set_visible(win->menu->remove, TRUE);
2492 gtk_action_set_visible(win->menu->add, FALSE);
2493 }
2494
2495 gtk_action_set_visible(win->menu->insert_link, TRUE);
2496 gtk_action_set_visible(win->menu->insert_image, TRUE);
2497 } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
2498 /* Show stuff that applies to Chats, hide stuff that applies to IMs */
2499
2500 /* Deal with menu items */
2501 gtk_action_set_visible(win->menu->view_log, TRUE);
2502 gtk_action_set_visible(win->menu->send_file, FALSE);
2503 gtk_action_set_visible(win->menu->get_info, FALSE);
2504 gtk_action_set_visible(win->menu->invite, TRUE);
2505 gtk_action_set_visible(win->menu->alias, TRUE);
2506 gtk_action_set_visible(win->menu->block, FALSE);
2507 gtk_action_set_visible(win->menu->unblock, FALSE);
2508
2509 if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) {
2510 /* If the chat is NOT in the buddy list */
2511 gtk_action_set_visible(win->menu->add, TRUE);
2512 gtk_action_set_visible(win->menu->remove, FALSE);
2513 } else {
2514 /* If the chat IS in the buddy list */
2515 gtk_action_set_visible(win->menu->add, FALSE);
2516 gtk_action_set_visible(win->menu->remove, TRUE);
2517 }
2518
2519 gtk_action_set_visible(win->menu->insert_link, TRUE);
2520 gtk_action_set_visible(win->menu->insert_image, TRUE);
2521 }
2522
2523 /*
2524 * Handle graying stuff out based on whether an account is connected
2525 * and what features that account supports.
2526 */
2527 if ((gc != NULL) &&
2528 (!PURPLE_IS_CHAT_CONVERSATION(conv) ||
2529 !purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv)) ))
2530 {
2531 PurpleConnectionFlags features = purple_conversation_get_features(conv);
2532 /* Account is online */
2533
2534 /* Deal with menu items */
2535 gtk_action_set_sensitive(win->menu->view_log, TRUE);
2536 gtk_action_set_sensitive(win->menu->get_info, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, get_info)));
2537 gtk_action_set_sensitive(win->menu->invite, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, invite)));
2538 gtk_action_set_sensitive(win->menu->insert_link, (features & PURPLE_CONNECTION_FLAG_HTML));
2539 gtk_action_set_sensitive(win->menu->insert_image, !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES));
2540
2541 if (PURPLE_IS_IM_CONVERSATION(conv))
2542 {
2543 gboolean can_send_file = FALSE;
2544 const gchar *name = purple_conversation_get_name(conv);
2545
2546 if (PURPLE_IS_PROTOCOL_XFER(protocol) &&
2547 purple_protocol_xfer_can_receive(PURPLE_PROTOCOL_XFER(protocol), gc, name)
2548 ) {
2549 can_send_file = TRUE;
2550 }
2551
2552 gtk_action_set_sensitive(win->menu->add, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, add_buddy)));
2553 gtk_action_set_sensitive(win->menu->remove, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, remove_buddy)));
2554 gtk_action_set_sensitive(win->menu->send_file, can_send_file);
2555 gtk_action_set_sensitive(win->menu->alias,
2556 (account != NULL) &&
2557 (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
2558 }
2559 else if (PURPLE_IS_CHAT_CONVERSATION(conv))
2560 {
2561 gtk_action_set_sensitive(win->menu->add, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, join)));
2562 gtk_action_set_sensitive(win->menu->remove, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, join)));
2563 gtk_action_set_sensitive(win->menu->alias,
2564 (account != NULL) &&
2565 (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL));
2566 }
2567
2568 } else {
2569 /* Account is offline */
2570 /* Or it's a chat that we've left. */
2571
2572 /* Then deal with menu items */
2573 gtk_action_set_sensitive(win->menu->view_log, TRUE);
2574 gtk_action_set_sensitive(win->menu->send_file, FALSE);
2575 gtk_action_set_sensitive(win->menu->get_info, FALSE);
2576 gtk_action_set_sensitive(win->menu->invite, FALSE);
2577 gtk_action_set_sensitive(win->menu->alias, FALSE);
2578 gtk_action_set_sensitive(win->menu->add, FALSE);
2579 gtk_action_set_sensitive(win->menu->remove, FALSE);
2580 gtk_action_set_sensitive(win->menu->insert_link, TRUE);
2581 gtk_action_set_sensitive(win->menu->insert_image, FALSE);
2582 }
2583 #endif
2584 }
2585
2586 static void 2324 static void
2587 pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) 2325 pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields)
2588 { 2326 {
2589 PidginConversation *gtkconv; 2327 PidginConversation *gtkconv;
2590 PidginConversationWindow *convwin; 2328 PidginConversationWindow *convwin;
2598 convwin = PIDGIN_CONVERSATION_WINDOW(win); 2336 convwin = PIDGIN_CONVERSATION_WINDOW(win);
2599 2337
2600 if (fields & PIDGIN_CONV_SET_TITLE) 2338 if (fields & PIDGIN_CONV_SET_TITLE)
2601 { 2339 {
2602 purple_conversation_autoset_title(conv); 2340 purple_conversation_autoset_title(conv);
2603 }
2604
2605 if (fields & PIDGIN_CONV_MENU)
2606 {
2607 gray_stuff_out(PIDGIN_CONVERSATION(conv));
2608 } 2341 }
2609 2342
2610 if ((fields & PIDGIN_CONV_TOPIC) && 2343 if ((fields & PIDGIN_CONV_TOPIC) &&
2611 PURPLE_IS_CHAT_CONVERSATION(conv)) 2344 PURPLE_IS_CHAT_CONVERSATION(conv))
2612 { 2345 {
2675 } 2408 }
2676 2409
2677 if (title != markup) 2410 if (title != markup)
2678 g_free(markup); 2411 g_free(markup);
2679 2412
2680 #if 0
2681 if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT ||
2682 gtkconv->unseen_state == PIDGIN_UNSEEN_NICK ||
2683 gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) {
2684 PangoAttrList *list = pango_attr_list_new();
2685 PangoAttribute *attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
2686 attr->start_index = 0;
2687 attr->end_index = -1;
2688 pango_attr_list_insert(list, attr);
2689 gtk_label_set_attributes(GTK_LABEL(gtkconv->tab_label), list);
2690 pango_attr_list_unref(list);
2691 } else
2692 gtk_label_set_attributes(GTK_LABEL(gtkconv->tab_label), NULL);
2693 #endif
2694
2695 if (pidgin_conversation_window_conversation_is_selected(convwin, conv)) { 2413 if (pidgin_conversation_window_conversation_is_selected(convwin, conv)) {
2696 const char* current_title = gtk_window_get_title(GTK_WINDOW(win)); 2414 const char* current_title = gtk_window_get_title(GTK_WINDOW(win));
2697 if (current_title == NULL || !purple_strequal(current_title, title)) { 2415 if (current_title == NULL || !purple_strequal(current_title, title)) {
2698 gtk_window_set_title(GTK_WINDOW(win), title); 2416 gtk_window_set_title(GTK_WINDOW(win), title);
2699 } 2417 }
2751 } 2469 }
2752 2470
2753 pidgin_conv_update_fields(conv, flags); 2471 pidgin_conv_update_fields(conv, flags);
2754 } 2472 }
2755 2473
2756 static void
2757 wrote_msg_update_unseen_cb(PurpleConversation *conv, PurpleMessage *msg,
2758 gpointer _unused)
2759 {
2760 PurpleMessageFlags flags;
2761 if (conv == NULL)
2762 return;
2763 flags = purple_message_get_flags(msg);
2764 if (flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) {
2765 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
2766
2767 if ((flags & PURPLE_MESSAGE_NICK) == PURPLE_MESSAGE_NICK)
2768 unseen = PIDGIN_UNSEEN_NICK;
2769 else if (((flags & PURPLE_MESSAGE_SYSTEM) == PURPLE_MESSAGE_SYSTEM) ||
2770 ((flags & PURPLE_MESSAGE_ERROR) == PURPLE_MESSAGE_ERROR))
2771 unseen = PIDGIN_UNSEEN_EVENT;
2772 else if ((flags & PURPLE_MESSAGE_NO_LOG) == PURPLE_MESSAGE_NO_LOG)
2773 unseen = PIDGIN_UNSEEN_NO_LOG;
2774 else
2775 unseen = PIDGIN_UNSEEN_TEXT;
2776
2777 conv_set_unseen(conv, unseen);
2778 }
2779 }
2780
2781 static PurpleConversationUiOps conversation_ui_ops = 2474 static PurpleConversationUiOps conversation_ui_ops =
2782 { 2475 {
2783 pidgin_conv_new, 2476 .create_conversation = pidgin_conv_new,
2784 pidgin_conv_destroy, /* destroy_conversation */ 2477 .destroy_conversation = pidgin_conv_destroy,
2785 NULL, /* write_chat */ 2478 .write_conv = pidgin_conv_write_conv,
2786 NULL, /* write_im */ 2479 .chat_add_users = pidgin_conv_chat_add_users,
2787 pidgin_conv_write_conv, /* write_conv */ 2480 .chat_rename_user = pidgin_conv_chat_rename_user,
2788 pidgin_conv_chat_add_users, /* chat_add_users */ 2481 .chat_remove_users = pidgin_conv_chat_remove_users,
2789 pidgin_conv_chat_rename_user, /* chat_rename_user */ 2482 .chat_update_user = pidgin_conv_chat_update_user,
2790 pidgin_conv_chat_remove_users, /* chat_remove_users */ 2483 .has_focus = pidgin_conv_has_focus,
2791 pidgin_conv_chat_update_user, /* chat_update_user */
2792 pidgin_conv_present_conversation, /* present */
2793 pidgin_conv_has_focus, /* has_focus */
2794 NULL, /* send_confirm */
2795 NULL,
2796 NULL,
2797 NULL,
2798 NULL
2799 }; 2484 };
2800 2485
2801 PurpleConversationUiOps * 2486 PurpleConversationUiOps *
2802 pidgin_conversations_get_conv_ui_ops(void) 2487 pidgin_conversations_get_conv_ui_ops(void)
2803 { 2488 {
2805 } 2490 }
2806 2491
2807 /************************************************************************** 2492 /**************************************************************************
2808 * Public conversation utility functions 2493 * Public conversation utility functions
2809 **************************************************************************/ 2494 **************************************************************************/
2810 void
2811 pidgin_conv_update_buttons_by_protocol(PurpleConversation *conv)
2812 {
2813 PidginConversation *gtkconv;
2814 GtkWidget *win;
2815
2816 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
2817 return;
2818
2819 gtkconv = PIDGIN_CONVERSATION(conv);
2820 win = gtk_widget_get_toplevel(gtkconv->tab_cont);
2821
2822 if(PIDGIN_IS_CONVERSATION_WINDOW(win)) {
2823 PidginConversationWindow *convwin = PIDGIN_CONVERSATION_WINDOW(win);
2824
2825 if(pidgin_conversation_window_conversation_is_selected(convwin, conv)) {
2826 gray_stuff_out(PIDGIN_CONVERSATION(conv));
2827 }
2828 }
2829 }
2830
2831 static void 2495 static void
2832 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, 2496 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
2833 gconstpointer value, gpointer data) 2497 gconstpointer value, gpointer data)
2834 { 2498 {
2835 GList *list; 2499 GList *list;
2848 2512
2849 continue; 2513 continue;
2850 } 2514 }
2851 2515
2852 gtkconv = PIDGIN_CONVERSATION(conv); 2516 gtkconv = PIDGIN_CONVERSATION(conv);
2853
2854 #if 0
2855 gtk_toggle_action_set_active(
2856 GTK_TOGGLE_ACTION(win->menu->show_formatting_toolbar),
2857 visible
2858 );
2859 #endif
2860 2517
2861 talkatu_editor_set_toolbar_visible(TALKATU_EDITOR(gtkconv->editor), visible); 2518 talkatu_editor_set_toolbar_visible(TALKATU_EDITOR(gtkconv->editor), visible);
2862 2519
2863 list = g_list_delete_link(list, list); 2520 list = g_list_delete_link(list, list);
2864 } 2521 }
3164 2821
3165 static void 2822 static void
3166 pidgin_conv_attach(PurpleConversation *conv) 2823 pidgin_conv_attach(PurpleConversation *conv)
3167 { 2824 {
3168 int timer; 2825 int timer;
3169 g_object_set_data(G_OBJECT(conv), "unseen-count", NULL);
3170 g_object_set_data(G_OBJECT(conv), "unseen-state", NULL);
3171 purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); 2826 purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops());
3172 if (!PIDGIN_CONVERSATION(conv)) 2827 if (!PIDGIN_CONVERSATION(conv))
3173 private_gtkconv_new(conv, FALSE); 2828 private_gtkconv_new(conv, FALSE);
3174 timer = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "close-timer")); 2829 timer = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "close-timer"));
3175 if (timer) { 2830 if (timer) {
3271 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/font_face", ""); 2926 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/font_face", "");
3272 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/font_size", 3); 2927 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/font_size", 3);
3273 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000); 2928 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000);
3274 2929
3275 /* Conversations -> Chat */ 2930 /* Conversations -> Chat */
3276 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat"); 2931 purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/chat");
3277 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", 54);
3278 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", 80);
3279 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", 0);
3280 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", 0);
3281 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", 340);
3282 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/height", 390);
3283 2932
3284 /* Conversations -> IM */ 2933 /* Conversations -> IM */
3285 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/im"); 2934 purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/im");
3286 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/x", 0);
3287 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/y", 0);
3288 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/width", 340);
3289 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/height", 390);
3290
3291 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 54);
3292 2935
3293 /* Connect callbacks. */ 2936 /* Connect callbacks. */
3294 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", 2937 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
3295 show_formatting_toolbar_pref_cb, NULL); 2938 show_formatting_toolbar_pref_cb, NULL);
3296 2939
3352 handle, G_CALLBACK(writing_msg), NULL); 2995 handle, G_CALLBACK(writing_msg), NULL);
3353 purple_signal_connect(purple_conversations_get_handle(), "writing-chat-msg", 2996 purple_signal_connect(purple_conversations_get_handle(), "writing-chat-msg",
3354 handle, G_CALLBACK(writing_msg), NULL); 2997 handle, G_CALLBACK(writing_msg), NULL);
3355 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", 2998 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg",
3356 handle, G_CALLBACK(received_im_msg_cb), NULL); 2999 handle, G_CALLBACK(received_im_msg_cb), NULL);
3357 purple_signal_connect(purple_conversations_get_handle(), "cleared-message-history",
3358 handle, G_CALLBACK(clear_conversation_scrollback_cb), NULL);
3359 3000
3360 purple_conversations_set_ui_ops(&conversation_ui_ops); 3001 purple_conversations_set_ui_ops(&conversation_ui_ops);
3361 3002
3362 /* Callbacks to update a conversation */ 3003 /* Callbacks to update a conversation */
3363 purple_signal_connect(blist_handle, "buddy-signed-on", 3004 purple_signal_connect(blist_handle, "buddy-signed-on",
3385 purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", handle, 3026 purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", handle,
3386 G_CALLBACK(update_chat_topic), NULL); 3027 G_CALLBACK(update_chat_topic), NULL);
3387 purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle, 3028 purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle,
3388 G_CALLBACK(pidgin_conv_updated), NULL, 3029 G_CALLBACK(pidgin_conv_updated), NULL,
3389 PURPLE_SIGNAL_PRIORITY_LOWEST); 3030 PURPLE_SIGNAL_PRIORITY_LOWEST);
3390 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle,
3391 G_CALLBACK(wrote_msg_update_unseen_cb), NULL);
3392 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle,
3393 G_CALLBACK(wrote_msg_update_unseen_cb), NULL);
3394 } 3031 }
3395 3032
3396 void 3033 void
3397 pidgin_conversations_uninit(void) 3034 pidgin_conversations_uninit(void)
3398 { 3035 {
3399 purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle()); 3036 purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle());
3400 purple_signals_disconnect_by_handle(pidgin_conversations_get_handle()); 3037 purple_signals_disconnect_by_handle(pidgin_conversations_get_handle());
3401 purple_signals_unregister_by_instance(pidgin_conversations_get_handle()); 3038 purple_signals_unregister_by_instance(pidgin_conversations_get_handle());
3402 } 3039 }
3403 3040
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417 /* down here is where gtkconvwin.c ought to start. except they share like every freaking function,
3418 * and touch each others' private members all day long */
3419
3420 /* pidgin
3421 *
3422 * Pidgin is the legal property of its developers, whose names are too numerous
3423 * to list here. Please refer to the COPYRIGHT file distributed with this
3424 * source distribution.
3425 *
3426 * This program is free software; you can redistribute it and/or modify
3427 * it under the terms of the GNU General Public License as published by
3428 * the Free Software Foundation; either version 2 of the License, or
3429 * (at your option) any later version.
3430 *
3431 * This program is distributed in the hope that it will be useful,
3432 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3433 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3434 * GNU General Public License for more details.
3435 *
3436 * You should have received a copy of the GNU General Public License
3437 * along with this program; if not, write to the Free Software
3438 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
3439 *
3440 */
3441
3442 #include <gdk/gdkkeysyms.h>
3443
3444 #include <purple.h>
3445
3446 #include "gtkblist.h"
3447 #include "gtkconv.h"
3448 #include "gtkdialogs.h"
3449 #include "gtkprivacy.h"
3450 #include "gtkutils.h"
3451
3452 /**************************************************************************
3453 * Callbacks
3454 **************************************************************************/
3455
3456 static void
3457 conv_set_unseen(PurpleConversation *conv, PidginUnseenState state)
3458 {
3459 int unseen_count = 0;
3460 PidginUnseenState unseen_state = PIDGIN_UNSEEN_NONE;
3461
3462 if(g_object_get_data(G_OBJECT(conv), "unseen-count"))
3463 unseen_count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-count"));
3464
3465 if(g_object_get_data(G_OBJECT(conv), "unseen-state"))
3466 unseen_state = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-state"));
3467
3468 if (state == PIDGIN_UNSEEN_NONE)
3469 {
3470 unseen_count = 0;
3471 unseen_state = PIDGIN_UNSEEN_NONE;
3472 }
3473 else
3474 {
3475 if (state >= PIDGIN_UNSEEN_TEXT)
3476 unseen_count++;
3477
3478 if (state > unseen_state)
3479 unseen_state = state;
3480 }
3481
3482 g_object_set_data(G_OBJECT(conv), "unseen-count", GINT_TO_POINTER(unseen_count));
3483 g_object_set_data(G_OBJECT(conv), "unseen-state", GINT_TO_POINTER(unseen_state));
3484
3485 purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_UNSEEN);
3486 }
3487
3488 static void
3489 gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state)
3490 {
3491 if (state == PIDGIN_UNSEEN_NONE)
3492 {
3493 gtkconv->unseen_count = 0;
3494 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
3495 }
3496 else
3497 {
3498 if (state >= PIDGIN_UNSEEN_TEXT)
3499 gtkconv->unseen_count++;
3500
3501 if (state > gtkconv->unseen_state)
3502 gtkconv->unseen_state = state;
3503 }
3504
3505 g_object_set_data(G_OBJECT(gtkconv->active_conv), "unseen-count", GINT_TO_POINTER(gtkconv->unseen_count));
3506 g_object_set_data(G_OBJECT(gtkconv->active_conv), "unseen-state", GINT_TO_POINTER(gtkconv->unseen_state));
3507
3508 purple_conversation_update(gtkconv->active_conv, PURPLE_CONVERSATION_UPDATE_UNSEEN);
3509 }
3510
3511 /************************************************************************** 3041 /**************************************************************************
3512 * GTK window ops 3042 * GTK window ops
3513 **************************************************************************/ 3043 **************************************************************************/
3514 static void 3044 static void
3515 pidgin_conv_placement_place(PidginConversation *conv) { 3045 pidgin_conv_placement_place(PidginConversation *conv) {

mercurial