view src/protocols/qq/infodlg.c @ 13870:983fd420e86b

[gaim-migrate @ 16340] Performed minor cleanup of the OpenQ codebase and patched it into the Gaim trunk as a prpl, providing basic QQ functionality. committer: Tailor Script <tailor@pidgin.im>
author Mark Huetsch <markhuetsch>
date Mon, 26 Jun 2006 02:58:54 +0000
parents
children
line wrap: on
line source

/**
 * The QQ2003C protocol plugin
 *
 * for gaim
 *
 * Copyright (C) 2004 Puzzlebird
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// START OF FILE
/*****************************************************************************/
#include "debug.h"		// gaim_debug
#include "internal.h"		// strlen, _("get_text")
#include "notify.h"		// gaim_notify_error

#include "utils.h"		// get_face_gdkpixbuf
#include "char_conv.h"		// qq_to_utf8
#include "show.h"		// qq_show_get_image
#include "infodlg.h"

// must be defined after qq_infodlg.h to have <gtk/gtk.h>
#include "gtkdialogs.h"		// GAIM_DIALOG, mainwindow


// the follwoing definition is in UTF-8
const gint blood_types_count = 5;
const gchar *blood_types[] = {
	"其它", "A", "B", "O", "AB",
};

const gint country_names_count = 6;
const gchar *country_names[] = {
	"中国", "中国香港", "中国澳门", "中国台湾",
	"新加坡", "马来西亚", "美国",
};

const gint province_names_count = 34;
const gchar *province_names[] = {
	"北京", "天津", "上海", "重庆", "香港",
	"河北", "山西", "内蒙古", "辽宁", "吉林",
	"黑龙江", "江西", "浙江", "江苏", "安徽",
	"福建", "山东", "河南", "湖北", "湖南",
	"广东", "广西", "海南", "四川", "贵州",
	"云南", "西藏", "陕西", "甘肃", "宁夏",
	"青海", "新疆", "台湾", "澳门",
};

const gint zodiac_names_count = 13;
const gchar *zodiac_names[] = {
	"-", "鼠", "牛", "虎", "兔",
	"龙", "蛇", "马", "羊", "猴",
	"鸡", "狗", "猪",
};

const gint horoscope_names_count = 13;
const gchar *horoscope_names[] = {
	"-", "水瓶座", "双鱼座", "牡羊座", "金牛座",
	"双子座", "巨蟹座", "狮子座", "处女座", "天秤座",
	"天蝎座", "射手座", "魔羯座",
};

const gint occupation_names_count = 15;
const gchar *occupation_names[] = {
	"全职", "兼职", "制造业", "商业", "失业中",
	"学生", "工程师", "政府部门", "教育业", "服务行业",
	"老板", "计算机业", "退休", "金融业",
	"销售/广告/市场",
};

enum {
	QQ_CONTACT_OPEN = 0x00,
	QQ_CONTACT_ONLY_FRIENDS = 0x01,
	QQ_CONTACT_CLOSE = 0x02,
};


enum {
	QQ_AUTH_NO_AUTH = 0x00,
	QQ_AUTH_NEED_AUTH = 0x01,
	QQ_AUTH_NO_ADD = 0x02,
};

typedef struct _change_icon_widgets change_icon_widgets;

struct _change_icon_widgets {
	GtkWidget *dialog;	// dialog that shows all icons
	GtkWidget *face;	// the image widget we are going to change
};

/*****************************************************************************/
static void _window_deleteevent(GtkWidget * widget, GdkEvent * event, gpointer data) {
	gtk_widget_destroy(widget);	// this will call _window_destroy
}				// _window_deleteevent

/*****************************************************************************/
static void _window_close(GtkWidget * widget, gpointer data)
{
	// this will call _info_window_destroy if it is info-window
	gtk_widget_destroy(GTK_WIDGET(data));
}				// _window_close

/*****************************************************************************/
static void _no_edit(GtkWidget * w)
{
	gtk_editable_set_editable(GTK_EDITABLE(w), FALSE);
}				// _no_edit

/*****************************************************************************/
static GtkWidget *_qq_entry_new()
{
	GtkWidget *entry;
	entry = gtk_entry_new();
	gtk_entry_set_max_length(GTK_ENTRY(entry), 255);	// set the max length
	return entry;
}				// _qq_entry_new

/*****************************************************************************/
static void _qq_set_entry(GtkWidget * entry, gchar * text)
{
	gchar *text_utf8;

	text_utf8 = qq_to_utf8(text, QQ_CHARSET_DEFAULT);
	gtk_entry_set_text(GTK_ENTRY(entry), text_utf8);

	g_free(text_utf8);
}				// _qq_set_entry

/*****************************************************************************/
static gchar *_qq_get_entry(GtkWidget * entry)
{
	return utf8_to_qq(gtk_entry_get_text(GTK_ENTRY(entry)), QQ_CHARSET_DEFAULT);
}				// _qq_get_entry

/*****************************************************************************/
static void _qq_set_text(GtkWidget * entry, gchar * text)
{
	gchar *text_utf8;

	text_utf8 = qq_to_utf8(text, QQ_CHARSET_DEFAULT);
	gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), text_utf8, -1);

	g_free(text_utf8);
}				// _qq_set_text

/*****************************************************************************/
static gchar *_qq_get_text(GtkWidget * entry)
{
	gchar *str, *ret;
	GtkTextIter start, end;

	gtk_text_buffer_get_bounds(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), &start, &end);
	str = gtk_text_buffer_get_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), &start, &end, FALSE);
	ret = utf8_to_qq(str, QQ_CHARSET_DEFAULT);

	return ret;
}				// _qq_get_text

/*****************************************************************************/
static void _qq_set_image(GtkWidget * entry, gint index)
{
	GdkPixbuf *pixbuf;

	g_return_if_fail(entry != NULL && index >= 0);

	pixbuf = get_face_gdkpixbuf(index);
	gtk_image_set_from_pixbuf(GTK_IMAGE(entry), pixbuf);
	g_object_unref(pixbuf);
	g_object_set_data(G_OBJECT(entry), "user_data", GINT_TO_POINTER(index));
}				// _qq_set_image


/*****************************************************************************/
static void _qq_change_face(GtkWidget * w, gpointer * user_data)
{
	gint index;
	change_icon_widgets *change_icon;

	change_icon = (change_icon_widgets *) user_data;

	index = (gint) g_object_get_data(G_OBJECT(w), "user_data");

	_qq_set_image(change_icon->face, index);
	_window_close(NULL, change_icon->dialog);

	g_free(change_icon);

}				// _qq_change_face

/*****************************************************************************/
static GList *_get_list_by_array(gchar ** array, gint size)
{
	gint i;
	GList *cbitems;

	cbitems = NULL;
	for (i = 0; i < size; i++)
		cbitems = g_list_append(cbitems, array[i]);
	return cbitems;
}				// _get_list_by_array

/*****************************************************************************/
static void _qq_set_open_contact_radio(contact_info_window * info_window, gchar * is_open_contact) {
	gint open;
	GtkWidget **radio;

	open = atoi(is_open_contact);
	radio = info_window->open_contact_radio;

	if (open == QQ_CONTACT_OPEN)
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
	else if (open == QQ_CONTACT_ONLY_FRIENDS)
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[1]), TRUE);
	else
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[2]), TRUE);
}				// _qq_set_open_contact_radio

/*****************************************************************************/
static void _qq_set_auth_type_radio(contact_info_window * info_window, gchar * auth_type_str) {
	gint auth_type;
	GtkWidget **radio;

	auth_type = atoi(auth_type_str);
	radio = info_window->auth_radio;

	if (auth_type == QQ_AUTH_NO_AUTH)
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
	else if (auth_type == QQ_AUTH_NEED_AUTH)
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[1]), TRUE);
	else
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[2]), TRUE);
}				// _qq_set_auth_type_radio

/*****************************************************************************/
static void _info_window_destroy(GtkWidget * widget, gpointer data)
{
	GList *list;
	qq_data *qd;
	GaimConnection *gc;
	contact_info_window *info_window;

	gc = (GaimConnection *) data;

	g_return_if_fail(gc != NULL && gc->proto_data != NULL);

	if (QQ_DEBUG)
		gaim_debug(GAIM_DEBUG_INFO, "QQ", "Destroy info window.\n");
	qd = (qq_data *) gc->proto_data;
	list = qd->contact_info_window;

	while (list) {
		info_window = (contact_info_window *) (list->data);
		if (info_window->window != widget)
			list = list->next;
		else {
			if (info_window->old_info)
				g_strfreev((gchar **) info_window->old_info);
			qd->contact_info_window = g_list_remove(qd->contact_info_window, info_window);
			g_free(info_window);
			break;
		}
	}			// while
}				// _info_window_destory

/*****************************************************************************/
void qq_contact_info_window_free(qq_data * qd)
{
	gint i;
	contact_info_window *info;

	g_return_if_fail(qd != NULL);

	i = 0;
	while (qd->contact_info_window) {
		info = (contact_info_window *) qd->contact_info_window->data;
		// remove the entry before free it
		// in some rare cases, system might automatically (stupidly) 
		// remove the entry from the list when user free the entry, 
		// then, qd->contact_info_window becomes NULL and it causes crash
		qd->contact_info_window = g_list_remove(qd->contact_info_window, info);
		if (info->window)
			gtk_widget_destroy(info->window);
		g_free(info);
		i++;
	}
	gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d conatct_info_window are freed\n", i);
}				// qq_contact_info_window_free

/*****************************************************************************/
static void _info_window_refresh(GtkWidget * widget, gpointer data)
{
	GaimConnection *gc;
	contact_info_window *info_window;

	gc = (GaimConnection *) data;
	info_window = (contact_info_window *)
	    g_object_get_data(G_OBJECT(widget), "user_data");

	qq_send_packet_get_info(gc, info_window->uid, TRUE);
	gtk_widget_set_sensitive(info_window->refresh_button, FALSE);
}				// _info_window_refresh

/*****************************************************************************/
static void _info_window_change(GtkWidget * widget, gpointer data)
{
	gchar *passwd[3];
	gboolean is_modify_passwd;
	guint8 icon, auth_type, open_contact;
	qq_data *qd;
	GaimAccount *a;
	GaimConnection *gc;
	contact_info *info;
	contact_info_window *info_window;

	gc = (GaimConnection *) data;
	a = gc->account;
	qd = gc->proto_data;
	info_window = (contact_info_window *)
	    g_object_get_data(G_OBJECT(widget), "user_data");
	info = info_window->old_info;

	is_modify_passwd = FALSE;
	passwd[0] = passwd[1] = passwd[2] = NULL;

	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->is_modify_passwd)))
		is_modify_passwd = TRUE;

	if (is_modify_passwd) {
		passwd[0] = _qq_get_entry(info_window->old_password);
		passwd[1] = _qq_get_entry(info_window->password[0]);
		passwd[2] = _qq_get_entry(info_window->password[1]);

		if (g_ascii_strcasecmp(a->password, passwd[0])) {
			gaim_notify_error(gc, _("Error"), _("Old password is wrong"), NULL);
			g_free(passwd[0]);
			g_free(passwd[1]);
			g_free(passwd[2]);
			return;
		}
		if (passwd[1][0] == '\0') {
			gaim_notify_error(gc, _("Error"), _("Password can not be empty"), NULL);
			g_free(passwd[0]);
			g_free(passwd[1]);
			g_free(passwd[2]);
			return;
		}
		if (g_ascii_strcasecmp(passwd[1], passwd[2])) {
			gaim_notify_error(gc, _("Error"),
					  _("Confirmed password is not the same as new password"), NULL);
			g_free(passwd[0]);
			g_free(passwd[1]);
			g_free(passwd[2]);
			return;
		}
		if (strlen(passwd[1]) > 16) {
			gaim_notify_error(gc, _("Error"), _("Password can not longer than 16 characters"), NULL);
			g_free(passwd[0]);
			g_free(passwd[1]);
			g_free(passwd[2]);
			return;
		}
	}			// if (is_modify_passwd)

	icon = (gint) g_object_get_data(G_OBJECT(info_window->face), "user_data");

	info->face = g_strdup_printf("%d", icon);
	info->nick = _qq_get_entry(info_window->nick);
	info->age = _qq_get_entry(info_window->age);
	info->gender = _qq_get_entry(info_window->gender);
	info->country = _qq_get_entry(info_window->country);
	info->province = _qq_get_entry(info_window->province);
	info->city = _qq_get_entry(info_window->city);
	info->email = _qq_get_entry(info_window->email);
	info->address = _qq_get_entry(info_window->address);
	info->zipcode = _qq_get_entry(info_window->zipcode);
	info->tel = _qq_get_entry(info_window->tel);
	info->name = _qq_get_entry(info_window->name);
	info->college = _qq_get_entry(info_window->college);
	info->occupation = _qq_get_entry(info_window->occupation);
	info->homepage = _qq_get_entry(info_window->homepage);
	info->intro = _qq_get_text(info_window->intro);

	info->blood =
	    get_index_str_by_name((gchar **) blood_types,
				  gtk_entry_get_text(GTK_ENTRY(info_window->blood)), blood_types_count);
	info->zodiac =
	    get_index_str_by_name((gchar **) zodiac_names,
				  gtk_entry_get_text(GTK_ENTRY(info_window->zodiac)), zodiac_names_count);
	info->horoscope =
	    get_index_str_by_name((gchar **) horoscope_names,
				  gtk_entry_get_text(GTK_ENTRY(info_window->horoscope)), horoscope_names_count);

	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->auth_radio[0])))
		auth_type = QQ_AUTH_NO_AUTH;
	else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->auth_radio[1])))
		auth_type = QQ_AUTH_NEED_AUTH;
	else
		auth_type = QQ_AUTH_NO_ADD;

	info->auth_type = g_strdup_printf("%d", auth_type);

	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->open_contact_radio[0])))
		open_contact = QQ_CONTACT_OPEN;
	else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->open_contact_radio[1])))
		open_contact = QQ_CONTACT_ONLY_FRIENDS;
	else
		open_contact = QQ_CONTACT_CLOSE;

	info->is_open_contact = g_strdup_printf("%d", open_contact);

	qq_send_packet_modify_info(gc, info, passwd[1]);
	qq_refresh_buddy_and_myself(info, gc);

	gtk_widget_destroy(info_window->window);	//close window
}

/*****************************************************************************/
static void _info_window_change_face(GtkWidget * widget, GdkEvent * event, contact_info_window * info_window) {
	gint i;
	GdkPixbuf *pixbuf;
	GtkWidget *dialog, *image, *button, *vbox, *smiley_box;
	change_icon_widgets *change_icon;

	change_icon = g_new0(change_icon_widgets, 1);

	smiley_box = NULL;
	GAIM_DIALOG(dialog);	// learned from gtkimhtmltoolbar.c
	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
	gtk_window_set_modal(GTK_WINDOW(dialog), FALSE);

	g_signal_connect(G_OBJECT(dialog), "delete_event", G_CALLBACK(_window_deleteevent), NULL);

	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);

	change_icon->dialog = dialog;
	change_icon->face = info_window->face;

	vbox = gtk_vbox_new(TRUE, 5);

	for (i = 0; i < 85; i++) {
		if (i % 8 == 0) {
			smiley_box = gtk_toolbar_new();
			gtk_box_pack_start(GTK_BOX(vbox), smiley_box, TRUE, TRUE, 0);
		}
		pixbuf = get_face_gdkpixbuf(i * 3);
		image = gtk_image_new_from_pixbuf(pixbuf);
		g_object_unref(pixbuf);
		button = gtk_toolbar_append_item(GTK_TOOLBAR(smiley_box),
						 NULL, NULL, NULL, image, G_CALLBACK(_qq_change_face), change_icon);
		g_object_set_data(G_OBJECT(button), "user_data", GINT_TO_POINTER(i * 3));
		gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
	}			// for i

	gtk_container_add(GTK_CONTAINER(dialog), vbox);
	gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
	gtk_window_set_title(GTK_WINDOW(dialog), _("Choose my head icon"));
	gtk_widget_show_all(dialog);
}				// _info_window_change_face

/*****************************************************************************/
static void _change_passwd_checkbutton_callback(GtkWidget * widget, contact_info_window * info_window) {
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
		gtk_widget_set_sensitive(info_window->old_password, TRUE);
		gtk_widget_set_sensitive(info_window->password[0], TRUE);
		gtk_widget_set_sensitive(info_window->password[1], TRUE);
	} else {
		gtk_widget_set_sensitive(info_window->old_password, FALSE);
		gtk_widget_set_sensitive(info_window->password[0], FALSE);
		gtk_widget_set_sensitive(info_window->password[1], FALSE);
	}
}				// _change_passwd_checkbutton_callback

/*****************************************************************************/
static GtkWidget *_create_page_basic
    (gint is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) {
	GdkPixbuf *pixbuf;
	GList *cbitems;
	GtkWidget *hbox, *pixmap, *frame, *label, *table;
	GtkWidget *entry, *combo, *alignment;
	GtkWidget *event_box, *qq_show;
	GtkTooltips *tooltips;

	tooltips = gtk_tooltips_new();

	cbitems = NULL;

	hbox = gtk_hbox_new(FALSE, 0);
	frame = gtk_frame_new("");
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);

	table = gtk_table_new(7, 3, FALSE);
	gtk_table_set_row_spacings(GTK_TABLE(table), 2);
	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
	gtk_container_add(GTK_CONTAINER(frame), table);

	pixbuf = get_face_gdkpixbuf((guint8) strtol(info->face, NULL, 10));
	pixmap = gtk_image_new_from_pixbuf(pixbuf);
	info_window->face = pixmap;

	alignment = gtk_alignment_new(0.25, 0, 0, 0);

	// set up icon
	if (is_myself) {
		g_object_set_data(G_OBJECT(info_window->face), "user_data",
				  GINT_TO_POINTER(strtol(info->face, NULL, 10)));
		event_box = gtk_event_box_new();
		g_signal_connect(G_OBJECT(event_box), "button_press_event",
				 G_CALLBACK(_info_window_change_face), info_window);
		gtk_container_add(GTK_CONTAINER(event_box), pixmap);
		gtk_container_add(GTK_CONTAINER(alignment), event_box);
		gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), event_box, _("Click to change icon"), NULL);
	} else
		gtk_container_add(GTK_CONTAINER(alignment), pixmap);

	gtk_table_attach(GTK_TABLE(table), alignment, 2, 3, 0, 2, GTK_FILL, 0, 0, 0);

	// set up qq_show image and event
	qq_show = qq_show_default(info);
	g_object_set_data(G_OBJECT(qq_show), "user_data", GINT_TO_POINTER((gint) atoi(info->uid)));

	frame = gtk_frame_new("");
	gtk_container_set_border_width(GTK_CONTAINER(frame), 0);

	if (strtol(info->qq_show, NULL, 10) != 0) {	// buddy has qq_show
		event_box = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(frame), event_box);
		gtk_container_add(GTK_CONTAINER(event_box), qq_show);
		g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(qq_show_get_image), qq_show);
		gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), event_box, _("Click to refresh"), NULL);
	} else			// no event_box
		gtk_container_add(GTK_CONTAINER(frame), qq_show);

	gtk_table_attach(GTK_TABLE(table), frame, 2, 3, 2, 7, GTK_EXPAND, 0, 0, 0);

	label = gtk_label_new(_("QQid"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Nickname"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->uid_entry = entry;
	_qq_set_entry(info_window->uid_entry, info->uid);
	gtk_widget_set_size_request(entry, 120, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->nick = entry;
	_qq_set_entry(info_window->nick, info->nick);
	gtk_widget_set_size_request(entry, 120, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Age"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Gender"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Country/Region"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, 0, 0, 0);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) country_names, country_names_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->country = GTK_COMBO(combo)->entry;
	_qq_set_entry(info_window->country, info->country);
	gtk_widget_set_size_request(combo, 150, -1);
	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 4, 5, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	entry = _qq_entry_new();
	info_window->age = entry;
	_qq_set_entry(info_window->age, info->age);
	gtk_widget_set_size_request(entry, 40, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);

	combo = gtk_combo_new();
	cbitems = g_list_append(cbitems, (char *)_("Male"));
	cbitems = g_list_append(cbitems, (char *)_("Female"));
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->gender = GTK_COMBO(combo)->entry;
	gtk_widget_set_size_request(combo, 60, -1);
	_qq_set_entry(info_window->gender, info->gender);
	gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE);
	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	label = gtk_label_new(_("Province"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("City"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7, GTK_FILL, 0, 0, 0);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) province_names, province_names_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->province = GTK_COMBO(combo)->entry;
	_qq_set_entry(info_window->province, info->province);
	gtk_widget_set_size_request(combo, 150, -1);
	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 5, 6, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	entry = _qq_entry_new();
	info_window->city = entry;
	gtk_widget_set_size_request(entry, 120, -1);
	_qq_set_entry(info_window->city, info->city);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 6, 7, GTK_FILL, 0, 0, 0);

	return hbox;
}				// _create_page_basic

/*****************************************************************************/
static GtkWidget *_create_page_contact
    (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) {
	GtkWidget *vbox1, *frame;
	GtkWidget *hbox1, *entry, *label;
	GtkWidget *hbox, *radio, *table;

	hbox = gtk_hbox_new(FALSE, 0);
	vbox1 = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);

	frame = gtk_frame_new("");
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	gtk_box_pack_start(GTK_BOX(vbox1), frame, TRUE, TRUE, 0);

	table = gtk_table_new(2, 5, FALSE);
	gtk_table_set_row_spacings(GTK_TABLE(table), 2);
	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
	gtk_container_add(GTK_CONTAINER(frame), table);

	label = gtk_label_new(_("Email"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Address"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Zipcode"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Tel"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Homepage"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->email = entry;
	gtk_widget_set_size_request(entry, 240, -1);
	_qq_set_entry(info_window->email, info->email);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->address = entry;
	_qq_set_entry(info_window->address, info->address);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->zipcode = entry;
	_qq_set_entry(info_window->zipcode, info->zipcode);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->tel = entry;
	_qq_set_entry(info_window->tel, info->tel);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->homepage = entry;
	_qq_set_entry(info_window->homepage, info->homepage);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 4, 5, GTK_FILL, 0, 0, 0);

	frame = gtk_frame_new(_("Above infomation"));
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	if (!is_myself)
		gtk_widget_set_sensitive(frame, FALSE);
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);

	hbox1 = gtk_hbox_new(FALSE, 5);
	gtk_container_add(GTK_CONTAINER(frame), hbox1);

	radio = gtk_radio_button_new_with_label(NULL, _("Open to all"));
	info_window->open_contact_radio[0] = radio;
	gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0);

	radio = gtk_radio_button_new_with_label_from_widget
	    (GTK_RADIO_BUTTON(radio), _("Only accessible by my frineds"));
	info_window->open_contact_radio[1] = radio;
	gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0);

	radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Close to all"));
	info_window->open_contact_radio[2] = radio;
	gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0);

	_qq_set_open_contact_radio(info_window, info->is_open_contact);

	return hbox;
}				// _create_page_contact

/*****************************************************************************/
static GtkWidget *_create_page_details
    (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) {
	GList *cbitems;
	GtkWidget *text, *hbox, *frame;
	GtkWidget *combo, *table, *label, *entry, *scrolled_window;

	cbitems = NULL;

	hbox = gtk_hbox_new(FALSE, 0);
	frame = gtk_frame_new("");
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);

	table = gtk_table_new(4, 4, FALSE);
	gtk_table_set_row_spacings(GTK_TABLE(table), 2);
	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
	gtk_container_add(GTK_CONTAINER(frame), table);

	label = gtk_label_new(_("Real Name"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_(" Zodiac"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_(" Blood Type"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_(" Horoscope"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 2, 3, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("College"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Career"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Intro"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->name = entry;
	gtk_widget_set_size_request(entry, 120, -1);
	_qq_set_entry(info_window->name, info->name);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	info_window->college = entry;
	gtk_widget_set_size_request(entry, 120, -1);
	_qq_set_entry(info_window->college, info->college);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) zodiac_names, zodiac_names_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->zodiac = GTK_COMBO(combo)->entry;
	gtk_entry_set_text(GTK_ENTRY(info_window->zodiac),
			   get_name_by_index_str((gchar **) zodiac_names, info->zodiac, zodiac_names_count));
	gtk_widget_set_size_request(combo, 70, -1);
	gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE);
	gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 0, 1, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) blood_types, blood_types_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->blood = GTK_COMBO(combo)->entry;
	gtk_entry_set_text(GTK_ENTRY(info_window->blood),
			   get_name_by_index_str((gchar **) blood_types, info->blood, blood_types_count));
	gtk_widget_set_size_request(combo, 70, -1);
	gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE);
	gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 1, 2, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) horoscope_names, horoscope_names_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->horoscope = GTK_COMBO(combo)->entry;
	gtk_entry_set_text(GTK_ENTRY(info_window->horoscope), get_name_by_index_str((gchar **)
										    horoscope_names,
										    info->horoscope,
										    horoscope_names_count));
	gtk_widget_set_size_request(combo, 70, -1);
	gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE);
	gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 2, 3, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	combo = gtk_combo_new();
	cbitems = _get_list_by_array((gchar **) occupation_names, occupation_names_count);
	gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems);
	g_list_free(cbitems);
	cbitems = NULL;
	info_window->occupation = GTK_COMBO(combo)->entry;
	_qq_set_entry(info_window->occupation, info->occupation);
	gtk_widget_set_size_request(combo, 120, -1);
	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);
	if (!is_myself)
		gtk_widget_set_sensitive(combo, FALSE);

	text = gtk_text_view_new();
	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
	info_window->intro = text;
	gtk_widget_set_size_request(text, -1, 90);
	_qq_set_text(info_window->intro, info->intro);

	scrolled_window = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	gtk_container_add(GTK_CONTAINER(scrolled_window), text);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2);
	gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2);

	gtk_table_attach(GTK_TABLE(table), scrolled_window, 1, 4, 3, 4, GTK_FILL, 0, 0, 0);
	return hbox;
}				// _create_page_details

/*****************************************************************************/
static GtkWidget *_create_page_security
    (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) {
	GtkWidget *hbox, *frame, *vbox1, *vbox2;
	GtkWidget *entry, *table, *label, *check_button;
	GtkWidget *radio, *alignment;

	hbox = gtk_hbox_new(FALSE, 0);
	vbox1 = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);

	frame = gtk_frame_new(_("Change Password"));
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);

	table = gtk_table_new(3, 3, FALSE);
	gtk_table_set_row_spacings(GTK_TABLE(table), 2);
	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
	gtk_container_add(GTK_CONTAINER(frame), table);

	label = gtk_label_new(_("Old Passwd"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);

	check_button = gtk_check_button_new_with_label(_("I wanna change"));
	info_window->is_modify_passwd = check_button;
	g_signal_connect(G_OBJECT(check_button), "toggled",
			 G_CALLBACK(_change_passwd_checkbutton_callback), info_window);
	gtk_table_attach(GTK_TABLE(table), check_button, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("New Passwd"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("(less than 16 char)"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0);

	label = gtk_label_new(_("Confirm"));
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
	gtk_widget_set_sensitive(entry, FALSE);
	info_window->old_password = entry;
	gtk_widget_set_size_request(entry, 160, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
	gtk_widget_set_sensitive(entry, FALSE);
	info_window->password[0] = entry;
	gtk_widget_set_size_request(entry, 160, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);

	entry = _qq_entry_new();
	gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
	gtk_widget_set_sensitive(entry, FALSE);
	info_window->password[1] = entry;
	gtk_widget_set_size_request(entry, 160, -1);
	gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);

	alignment = gtk_alignment_new(0, 0, 0, 0);
	gtk_widget_set_size_request(alignment, -1, 5);
	gtk_box_pack_start(GTK_BOX(vbox1), alignment, FALSE, FALSE, 0);

	frame = gtk_frame_new(_("Authentication"));
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);

	vbox2 = gtk_vbox_new(FALSE, 1);
	gtk_container_add(GTK_CONTAINER(frame), vbox2);

	radio = gtk_radio_button_new_with_label(NULL, _("Anyone can add me"));
	info_window->auth_radio[0] = radio;
	gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0);

	radio = gtk_radio_button_new_with_label_from_widget
	    (GTK_RADIO_BUTTON(radio), _("User needs to be authenticated to add me"));
	info_window->auth_radio[1] = radio;
	gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0);

	radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Nobody can add me"));
	info_window->auth_radio[2] = radio;
	gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0);

	_qq_set_auth_type_radio(info_window, info->auth_type);

	return hbox;
}				// _create_page_security 

/*****************************************************************************/
void qq_show_contact_info_dialog(contact_info * info, GaimConnection * gc, contact_info_window * info_window) {

	GaimAccount *a = gc->account;
	gboolean is_myself;
	GtkWidget *label, *window, *notebook, *vbox, *bbox, *button;

	is_myself = (!strcmp(info->uid, a->username));
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
//	gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(mainwindow));  //by gfhuang
	info_window->window = window;

	// we need to duplicate here, 
	// as the passed-in info structure will be freed in his function
	info_window->old_info = (contact_info *) g_strdupv((gchar **) info);

	/* When the window is given the "delete_event" signal (this is given
	 * by the window manager, usually by the "close" option, or on the
	 * titlebar), we ask it to call the delete_event () function
	 * as defined above. The data passed to the callback  
	 * function is NULL and is ignored in the callback function. 
	 */
	g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(_window_deleteevent), NULL);

	/* Here we connect the "destroy" event to a signal handler.  
	 * This event occurs when we call gtk_widget_destroy() on the window,
	 * or if we return FALSE in the "delete_event" callback. 
	 */
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(_info_window_destroy), gc);

	gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

	if (is_myself)
		gtk_window_set_title(GTK_WINDOW(window), _("My Information"));
	else
		gtk_window_set_title(GTK_WINDOW(window), _("My Buddy's Information"));
	gtk_container_set_border_width(GTK_CONTAINER(window), 5);

	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(window), vbox);

	notebook = gtk_notebook_new();
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);

	label = gtk_label_new(_("Basic"));
	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_basic(is_myself, info, gc, info_window), label);

	label = gtk_label_new(_("Contact"));
	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_contact(is_myself, info, gc, info_window), label);

	label = gtk_label_new(_("Details"));
	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_details(is_myself, info, gc, info_window), label);

	if (is_myself) {
		label = gtk_label_new(_("Security"));
		gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
					 _create_page_security(is_myself, info, gc, info_window), label);
	}

	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);

	bbox = gtk_hbutton_box_new();
	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
	gtk_box_set_spacing(GTK_BOX(bbox), 10);

	button = gtk_button_new_with_label(_("Modify"));
	g_object_set_data(G_OBJECT(button), "user_data", (gpointer) info_window);
	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_info_window_change), gc);
	gtk_container_add(GTK_CONTAINER(bbox), button);

	if (is_myself)
		gtk_widget_set_sensitive(button, TRUE);
	else
		gtk_widget_set_sensitive(button, FALSE);

	button = gtk_button_new_with_label(_("Refresh"));
	info_window->refresh_button = button;
	g_object_set_data(G_OBJECT(button), "user_data", (gpointer) info_window);
	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_info_window_refresh), gc);
	gtk_container_add(GTK_CONTAINER(bbox), button);

	button = gtk_button_new_with_label(_("Close"));
	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_window_close), info_window->window);
	gtk_container_add(GTK_CONTAINER(bbox), button);

	gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5);

	_no_edit(info_window->uid_entry);	// uid entry cannot be changed
	if (!is_myself) {
		_no_edit(info_window->nick);
		_no_edit(info_window->country);
		_no_edit(info_window->age);
		_no_edit(info_window->gender);
		_no_edit(info_window->province);
		_no_edit(info_window->city);
		_no_edit(info_window->email);
		_no_edit(info_window->address);
		_no_edit(info_window->zipcode);
		_no_edit(info_window->tel);
		_no_edit(info_window->name);
		_no_edit(info_window->blood);
		_no_edit(info_window->college);
		_no_edit(info_window->occupation);
		_no_edit(info_window->zodiac);
		_no_edit(info_window->horoscope);
		_no_edit(info_window->homepage);
		gtk_text_view_set_editable(GTK_TEXT_VIEW(info_window->intro), FALSE);
	}
	gtk_widget_show_all(window);
}				// qq_show_contact_info_dialog

/*****************************************************************************/
void qq_refresh_contact_info_dialog(contact_info * new_info, GaimConnection * gc, contact_info_window * info_window) {
	GaimAccount *a;
	gboolean is_myself;
	contact_info *info;
	a = gc->account;

	if (info_window->old_info)
		g_strfreev((gchar **) info_window->old_info);

	// we need to duplicate here, 
	// as the passed-in info structure will be freed in his function
	info = (contact_info *) g_strdupv((gchar **) new_info);
	info_window->old_info = info;

	is_myself = !(g_ascii_strcasecmp(info->uid, a->username));
	gtk_widget_set_sensitive(info_window->refresh_button, TRUE);

	if (is_myself) {
		_qq_set_auth_type_radio(info_window, info->auth_type);
		_qq_set_open_contact_radio(info_window, info->is_open_contact);
	}

	_qq_set_entry(info_window->uid_entry, info->uid);
	_qq_set_entry(info_window->nick, info->nick);
	_qq_set_entry(info_window->country, info->country);
	_qq_set_entry(info_window->age, info->age);
	_qq_set_entry(info_window->gender, info->gender);
	_qq_set_entry(info_window->province, info->province);
	_qq_set_entry(info_window->city, info->city);
	_qq_set_entry(info_window->email, info->email);
	_qq_set_entry(info_window->address, info->address);
	_qq_set_entry(info_window->zipcode, info->zipcode);
	_qq_set_entry(info_window->tel, info->tel);
	_qq_set_entry(info_window->name, info->name);
	gtk_entry_set_text(GTK_ENTRY(info_window->zodiac),
			   get_name_by_index_str((gchar **) zodiac_names, info->zodiac, zodiac_names_count));
	gtk_entry_set_text(GTK_ENTRY(info_window->horoscope), get_name_by_index_str((gchar **)
										    horoscope_names,
										    info->horoscope,
										    horoscope_names_count));
	gtk_entry_set_text(GTK_ENTRY(info_window->blood),
			   get_name_by_index_str((gchar **) blood_types, info->blood, blood_types_count));
	_qq_set_entry(info_window->college, info->college);
	_qq_set_entry(info_window->occupation, info->occupation);
	_qq_set_entry(info_window->homepage, info->homepage);

	_qq_set_image(info_window->face, (guint8) atoi(info->face));

	_qq_set_text(info_window->intro, info->intro);
}				// qq_refresh_contact_info_dialog

/*****************************************************************************/
// END OF FILE