void hybrid_conv_clear_input(HybridAccount *account, const gchar *buddy_id) { HybridBuddy *buddy; HybridChatWindow *chat; g_return_if_fail(account != NULL); g_return_if_fail(buddy_id != NULL); if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("conv", "buddy doesn't exist."); return; } if (!(chat = hybrid_conv_find_chat(buddy_id))) { return; } if (chat->input_source) { g_source_remove(chat->input_source); } text_ops->notify(chat->textview, "" , MSG_NOTIFICATION_INPUT); }
void fetion_update_portrait(fetion_account *ac, fetion_buddy *buddy) { portrait_data *data; HybridBuddy *hybrid_buddy; const gchar *checksum; g_return_if_fail(ac != NULL); g_return_if_fail(buddy != NULL); data = g_new0(portrait_data, 1); data->buddy = buddy; data->ac = ac; data->portrait_type = PORTRAIT_TYPE_BUDDY; if (!(hybrid_buddy = hybrid_blist_find_buddy(ac->account, buddy->userid))) { hybrid_debug_error("fetion", "FATAL, update portrait," " unable to find a buddy."); return; } checksum = hybrid_blist_get_buddy_checksum(hybrid_buddy); if (checksum != NULL && g_strcmp0(checksum, buddy->portrait_crc) == 0) { hybrid_debug_info("fetion", "portrait for %s(%s) up to date", buddy->nickname && *(buddy->nickname) != '\0' ? buddy->nickname : buddy->userid, buddy->portrait_crc); return; } hybrid_proxy_connect(ac->portrait_host_name, 80, portrait_conn_cb, data); }
void hybrid_conv_got_status(HybridAccount *account, const gchar *buddy_id, const gchar *text, gint type) { HybridChatWindow *chat; HybridBuddy *buddy; g_return_if_fail(account != NULL); g_return_if_fail(buddy_id != NULL); if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("conv", "buddy doesn't exist."); return; } if (!(chat = hybrid_conv_find_chat(buddy_id))) { /* * Well, we haven't find an existing chat panel so far, check the type * to determine whether to create a new one. */ if (type == MSG_NOTIFICATION_INPUT) { return; } else { chat = hybrid_chat_window_create(account, buddy->id, HYBRID_CHAT_PANEL_SYSTEM); } } if (type == MSG_NOTIFICATION_INPUT) { text_ops->notify(chat->textview, text, MSG_NOTIFICATION_INPUT); } }
/** * Process the synchronization message, when the contact list or the personal info * changed, the server will push this message to tell the client to update its * local cache file, well, we will not update the local cache file, we keep the * old version numbers, and reload it after the next logining. */ static void process_sync_info(fetion_account *ac, const gchar *sipmsg) { GSList *list; gchar *sid; fetion_buddy *buddy; HybridBuddy *hb; hybrid_debug_info("fetion", "sync info,recv:\n%s", sipmsg); if (!(list = sip_parse_sync(ac, sipmsg))) { return; } while (list) { buddy = (fetion_buddy*)list->data; list = g_slist_remove(list, buddy); if (buddy->status == 0) { continue; } if (!(hb = hybrid_blist_find_buddy(ac->account, buddy->userid))) { continue; } if (buddy->status == 1) { hybrid_blist_set_buddy_status(hb, TRUE); } else { hybrid_blist_set_buddy_status(hb, FALSE); } sid = get_sid_from_sipuri(buddy->sipuri); hybrid_message_box_show(HYBRID_MESSAGE_INFO, _("Buddy <b>%s</b> has %s your add-buddy request."), buddy->localname && *(buddy->localname) != '\0' ? buddy->localname : sid, buddy->status == 1 ? _("accepted") : _("declined")); } }
/** * Process "presence changed" message. */ static void process_presence(fetion_account *ac, const gchar *sipmsg) { GSList *list; GSList *pos; fetion_buddy *buddy; HybridBuddy *imbuddy; list = sip_parse_presence(ac, sipmsg); for (pos = list; pos; pos = pos->next) { buddy = (fetion_buddy*)pos->data; imbuddy = hybrid_blist_find_buddy(ac->account, buddy->userid); if (buddy->localname && *(buddy->localname) != '\0') { hybrid_blist_set_buddy_name(imbuddy, buddy->localname); } hybrid_blist_set_buddy_mood(imbuddy, buddy->mood_phrase); switch (buddy->state) { case P_ONLINE: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_ONLINE); break; case P_OFFLINE: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_OFFLINE); break; case P_INVISIBLE: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_OFFLINE); break; case P_AWAY: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_AWAY); break; case P_BUSY: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_BUSY); break; default: hybrid_blist_set_buddy_state(imbuddy, HYBRID_STATE_AWAY); break; } fetion_update_portrait(ac, buddy); } }
void hybrid_conv_got_input(HybridAccount *account, const gchar *buddy_id, gboolean auto_stop) { HybridBuddy *buddy; HybridChatWindow *chat; gchar *text; g_return_if_fail(account != NULL); g_return_if_fail(buddy_id != NULL); if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("conv", "buddy doesn't exist."); return; } if (!(chat = hybrid_conv_find_chat(buddy_id))) { return; } text = g_strdup_printf(_(" %s is typing..."), buddy->name); text_ops->notify(chat->textview, text , MSG_NOTIFICATION_INPUT); g_free(text); if (!auto_stop) { return; } if (chat->input_source) { g_source_remove(chat->input_source); } chat->input_source = g_timeout_add_seconds(4, (GSourceFunc)(input_finished_cb), chat); }
void hybrid_conv_stop_input(HybridAccount *account, const gchar *buddy_id) { HybridBuddy *buddy; HybridChatWindow *chat; gchar *text; g_return_if_fail(account != NULL); g_return_if_fail(buddy_id != NULL); if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("conv", "buddy doesn't exist."); return; } if (!(chat = hybrid_conv_find_chat(buddy_id))) { return; } text = g_strdup_printf(_(" %s stopped typing"), buddy->name); text_ops->notify(chat->textview, text , MSG_NOTIFICATION_INPUT); g_free(text); }
void hybrid_conv_got_message(HybridAccount *account, const gchar *buddy_id, const gchar *message, time_t time) { HybridConversation *conv; HybridChatWindow *chat; HybridBuddy *buddy; gchar *msg; gchar *notify_msg; GdkPixbuf *pixbuf; gint current_page; gint chat_page; msg = hybrid_strip_html(message); g_return_if_fail(account != NULL); g_return_if_fail(buddy_id != NULL); g_return_if_fail(message != NULL); if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("conv", "buddy doesn't exist."); g_free(msg); return; } if (!(chat = hybrid_conv_find_chat(buddy_id))) { /* Well, we haven't find an existing chat panel so far, so create one. */ chat = hybrid_chat_window_create(account, buddy->id, HYBRID_CHAT_PANEL_SYSTEM); } /* check whether the chat window is active. */ conv = chat->parent; if (gtk_window_is_active(GTK_WINDOW(conv->window))) { current_page = gtk_notebook_current_page(GTK_NOTEBOOK(conv->notebook)); chat_page = gtk_notebook_page_num(GTK_NOTEBOOK(conv->notebook), chat->vbox); if (current_page == chat_page) { goto just_show_msg; } } /* change the callback function of the status icon's activate signal. */ hybrid_status_icon_blinking(buddy); /* notify. */ notify_msg = g_strdup_printf(_("%s said:"), buddy->name && *buddy->name ? buddy->name : buddy->id); pixbuf = hybrid_create_round_pixbuf(buddy->icon_data, buddy->icon_data_length, 48); hybrid_notify_popup(pixbuf, notify_msg, msg); g_object_unref(pixbuf); g_free(notify_msg); chat->unread ++; hybrid_chat_window_update_tips(chat); just_show_msg: hybrid_sound_play_file(SOUND_DIR"newmessage.wav"); text_ops->append(chat->textview, buddy->account, buddy, msg, time); hybrid_logs_write(chat->logs, buddy->name, msg, FALSE); g_free(msg); }
HybridChatWindow* hybrid_chat_window_create(HybridAccount *account, const gchar *id, HybridChatWindowType type) { HybridChatWindow *chat = NULL; HybridConversation *conv = NULL; HybridBuddy *buddy; HybridModule *proto; HybridIMOps *ops; g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(id != NULL, NULL); if (type == HYBRID_CHAT_PANEL_SYSTEM) { if (!(buddy = (hybrid_blist_find_buddy(account, id)))) { hybrid_debug_error("conv", "FATAL, can't find buddy"); return NULL; } proto = account->proto; ops = proto->info->im_ops; /* we will check whether the protocol allows this buddy to be activated. */ if (ops->chat_start) { if (!ops->chat_start(account, buddy)) { return NULL; } } } if ((chat = hybrid_conv_find_chat(id))) { conv = chat->parent; goto found; } /* * Whether to show the chat dialog in a single window. */ if (hybrid_pref_get_boolean(NULL, "single_chat_window")) { if (!conv_list) { conv = hybrid_conv_create(); conv_list = g_slist_append(conv_list, conv); } else { conv = conv_list->data; } } else { conv = hybrid_conv_create(); conv_list = g_slist_append(conv_list, conv); } chat = g_new0(HybridChatWindow, 1); chat->id = g_strdup(id); chat->parent = conv; chat->account = account; chat->type = type; chat->logs = hybrid_logs_create(account, id); if (type == HYBRID_CHAT_PANEL_SYSTEM) { chat->data = buddy; } conv->chat_buddies = g_slist_append(conv->chat_buddies, chat); init_chat_window(chat); return chat; found: gtk_notebook_set_current_page(GTK_NOTEBOOK(conv->notebook), gtk_notebook_page_num(GTK_NOTEBOOK(conv->notebook), chat->vbox)); /* focus the send textview */ gtk_widget_grab_focus(chat->sendtext); gtk_window_present(GTK_WINDOW(chat->parent->window)); return chat; }
void hybrid_info_notify(HybridAccount *account, HybridNotifyInfo *info, const gchar *buddy_id) { GtkTreeIter iter; GtkTreeModel *model; HybridBuddy *buddy; HybridInfo *info_panel; HybridInfoItem *item; GSList *info_pos; GSList *pos; gchar *name_markup; gchar *name_escaped; gchar *value_escaped; g_return_if_fail(info != NULL); for (info_pos = info_list; info_pos; info_pos = info_pos->next) { info_panel = (HybridInfo*)info_pos->data; if (g_strcmp0(info_panel->buddy->id, buddy_id) == 0) { goto buddy_ok; } } if (!(buddy = hybrid_blist_find_buddy(account, buddy_id))) { hybrid_debug_error("info", "can not find buddy with id :\'%s\'", buddy_id); return; } info_panel = hybrid_info_create(buddy); buddy_ok: model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_panel->treeview)); for (pos = info->item_list; pos; pos = pos->next) { item = (HybridInfoItem*)pos->data; name_escaped = g_markup_escape_text(item->name, -1); if (item->value) { value_escaped = g_markup_escape_text(item->value, -1); } else { value_escaped = NULL; } name_markup = g_strdup_printf("<b>%s:</b>", name_escaped); gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, HYBRID_INFO_NAME_COLUMN, name_markup, HYBRID_INFO_VALUE_COLUMN, value_escaped, HYBRID_INFO_PIXBUF_COLUMN, item->pixbuf, HYBRID_INFO_VALUE_COLUMN_VISIBLE, item->type == HYBRID_INFO_ITEM_TYPE_TEXT ? TRUE : FALSE, HYBRID_INFO_PIXBUF_COLUMN_VISIBLE, item->type == HYBRID_INFO_ITEM_TYPE_PIXBUF ? TRUE : FALSE, -1); g_free(name_markup); g_free(name_escaped); g_free(value_escaped); } }
/** * Callback function to handle the portrait receive event. */ static gboolean portrait_recv_cb(gint sk, gpointer user_data) { gchar buf[BUF_LENGTH]; gint n; gchar *pos; HybridBuddy *imbuddy; portrait_trans *trans = (portrait_trans*)user_data; if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) { hybrid_debug_error("fetion", "get portrait for \'%s\':%s", trans->buddy ? trans->buddy->sid : trans->ac->sid, strerror(errno)); return FALSE; } buf[n] = '\0'; if (n == 0) { if (trans->portrait_type == PORTRAIT_TYPE_BUDDY) { imbuddy = hybrid_blist_find_buddy(trans->ac->account, trans->buddy->userid); } if (hybrid_get_http_code(trans->data) != 200) { /* * Note that we got no portrait, but we still need * to set buddy icon, just for the portrait checksum, we * set it default to "0" instead of leaving it NULL, * so that in the next login, we just check the changes * of the buddy's checksum to determine whether to fetch a * portrait from the server. */ if (trans->portrait_type == PORTRAIT_TYPE_BUDDY) { hybrid_blist_set_buddy_icon(imbuddy, NULL, 0, trans->buddy->portrait_crc); } else { hybrid_account_set_icon(trans->ac->account, NULL, 0, trans->ac->portrait_crc); } goto pt_fin; } trans->data_len = hybrid_get_http_length(trans->data); if (!(pos = strstr(trans->data, "\r\n\r\n"))) { goto pt_fin; } pos += 4; if (trans->portrait_type == PORTRAIT_TYPE_BUDDY) { /**< buddy portrait */ hybrid_blist_set_buddy_icon(imbuddy, (guchar*)pos, trans->data_len, trans->buddy->portrait_crc); } else { hybrid_account_set_icon(trans->ac->account, (guchar*)pos, trans->data_len, trans->ac->portrait_crc); } goto pt_fin; } else { trans->data = realloc(trans->data, trans->data_size + n); memcpy(trans->data + trans->data_size, buf, n); trans->data_size += n; } return TRUE; pt_fin: g_free(trans->data); g_free(trans); return FALSE; }
/** * Callback function for the get_info transaction. */ static gint get_info_cb(fetion_account *ac, const gchar *sipmsg, fetion_transaction *trans) { HybridNotifyInfo *info; HybridBuddy *hybrid_buddy; fetion_buddy *buddy; gchar *province; gchar *city; GdkPixbuf *pixbuf = NULL; //info = (HybridInfo*)trans->data; if (!(buddy = fetion_buddy_parse_info(ac, trans->userid, sipmsg))) { /* TODO show an error msg in the get-info box. */ return HYBRID_ERROR; } province = buddy->province && *(buddy->province) != '\0' ? get_province_name(buddy->province) : g_strdup(_("Unknown")); city = buddy->city && *(buddy->city) != '\0' ? get_city_name(buddy->province, buddy->city) : g_strdup(_("Unknown")); info = hybrid_notify_info_create(); hybrid_info_add_pair(info, _("Nickname"), buddy->nickname); if (*buddy->localname) { hybrid_info_add_pair(info, _("Localname"), buddy->localname); } hybrid_info_add_pair(info, _("Fetion-no"), buddy->sid); if (buddy->mobileno && *buddy->mobileno) { hybrid_info_add_pair(info, _("Mobile-no"), buddy->mobileno); } hybrid_info_add_pair(info, _("Gender"), buddy->gender == 1 ? _("Male") : (buddy->gender == 2 ? _("Female") : _("Secrecy"))); if (*buddy->mood_phrase) { hybrid_info_add_pair(info, _("Mood"), buddy->mood_phrase); } hybrid_info_add_pair(info, _("Country"), !buddy->country || g_strcmp0(buddy->country, "CN") == 0 || !*buddy->country ? "China" : buddy->country); hybrid_info_add_pair(info, _("Province"), province); hybrid_info_add_pair(info, _("City"), city); if ((hybrid_buddy = hybrid_blist_find_buddy(ac->account, buddy->userid))) { if (hybrid_buddy->icon_data) { pixbuf = hybrid_create_pixbuf(hybrid_buddy->icon_data, hybrid_buddy->icon_data_length); hybrid_info_add_pixbuf_pair(info, _("Photo"), pixbuf); if (pixbuf) { g_object_unref(pixbuf); } } } g_free(province); g_free(city); hybrid_info_notify(ac->account, info, buddy->userid); hybrid_notify_info_destroy(info); return HYBRID_OK; }