Mercurial > pidgin
view src/buddy_chat.c @ 1985:008a4cc4a82c
[gaim-migrate @ 1995]
hi.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Mon, 11 Jun 2001 09:21:18 +0000 |
parents | 352bd24e03ef |
children | eee309c0de93 |
line wrap: on
line source
/* * gaim * * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * * 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 * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include <string.h> #include <sys/time.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <gtk/gtk.h> #include "gtkimhtml.h" #include "gtkspell.h" #include <gdk/gdkkeysyms.h> #include "convo.h" #include "prpl.h" #include "pixmaps/tb_forward.xpm" #include "pixmaps/join.xpm" #include "pixmaps/close.xpm" GtkWidget *joinchat; static struct gaim_connection *joinchatgc; static GtkWidget *entry; static GtkWidget *invite; static GtkWidget *inviteentry; static GtkWidget *invitemess; static GtkWidget *jc_vbox = NULL; extern int state_lock; GList *chats = NULL; GtkWidget *all_chats = NULL; GtkWidget *chat_notebook = NULL; static void destroy_prev_jc() { if (!jc_vbox) return; while (GTK_BOX(jc_vbox)->children) gtk_container_remove(GTK_CONTAINER(jc_vbox), ((GtkBoxChild *)GTK_BOX(jc_vbox)->children->data)->widget); } static void destroy_join_chat() { if (joinchat) gtk_widget_destroy(joinchat); joinchat = NULL; } static void destroy_invite() { if (invite) gtk_widget_destroy(invite); invite = NULL; } void do_join_chat() { if (joinchat) { if (joinchatgc->prpl->draw_join_chat) serv_join_chat(joinchatgc, 0, NULL); else serv_join_chat(joinchatgc, 0, gtk_entry_get_text(GTK_ENTRY(entry))); gtk_widget_destroy(joinchat); } joinchat = NULL; } static void default_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) { GtkWidget *label; GtkWidget *rowbox; if (!joinchat || !fbox) return; rowbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); gtk_widget_show(rowbox); label = gtk_label_new(_("Join what group:")); gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(rowbox), entry, TRUE, TRUE, 0); gtk_widget_grab_focus(entry); gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL); gtk_widget_show(entry); } static void rebuild_jc() { if (!joinchatgc) return; destroy_prev_jc(); if (joinchatgc->prpl->draw_join_chat) (*joinchatgc->prpl->draw_join_chat)(joinchatgc, jc_vbox); else default_draw_join_chat(joinchatgc, jc_vbox); } static void joinchat_choose(GtkWidget *w, struct gaim_connection *g) { if (joinchatgc == g) return; joinchatgc = g; rebuild_jc(); } static void create_joinchat_menu(GtkWidget *box) { GtkWidget *optmenu; GtkWidget *menu; GtkWidget *opt; GSList *c = connections; struct gaim_connection *g; char buf[2048]; optmenu = gtk_option_menu_new(); gtk_box_pack_start(GTK_BOX(box), optmenu, FALSE, FALSE, 0); menu = gtk_menu_new(); joinchatgc = NULL; while (c) { g = (struct gaim_connection *)c->data; c = c->next; if (!g->prpl->join_chat) continue; if (!joinchatgc) joinchatgc = g; g_snprintf(buf, sizeof buf, "%s (%s)", g->username, (*g->prpl->name)()); opt = gtk_menu_item_new_with_label(buf); gtk_object_set_user_data(GTK_OBJECT(opt), g); gtk_signal_connect(GTK_OBJECT(opt), "activate", GTK_SIGNAL_FUNC(joinchat_choose), g); gtk_menu_append(GTK_MENU(menu), opt); gtk_widget_show(opt); } gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), 0); } void join_chat() { GtkWidget *mainbox; GtkWidget *frame; GtkWidget *fbox; GtkWidget *rowbox; GtkWidget *bbox; GtkWidget *join; GtkWidget *cancel; GtkWidget *label; GSList *c = connections; struct gaim_connection *gc = NULL; while (c) { gc = c->data; if (gc->prpl->join_chat) break; gc = NULL; c = c->next; } if (gc == NULL) { do_error_dialog("You are not currently signed on with any protocols that have " "the ability to chat.", "Unable to chat"); return; } if (!joinchat) { joinchat = gtk_window_new(GTK_WINDOW_DIALOG); gtk_window_set_wmclass(GTK_WINDOW(joinchat), "joinchat", "Gaim"); gtk_window_set_policy(GTK_WINDOW(joinchat), FALSE, TRUE, TRUE); gtk_widget_realize(joinchat); gtk_signal_connect(GTK_OBJECT(joinchat), "delete_event", GTK_SIGNAL_FUNC(destroy_join_chat), joinchat); gtk_window_set_title(GTK_WINDOW(joinchat), _("Join Chat")); aol_icon(joinchat->window); mainbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(mainbox), 5); gtk_container_add(GTK_CONTAINER(joinchat), mainbox); frame = gtk_frame_new(_("Buddy Chat")); gtk_box_pack_start(GTK_BOX(mainbox), frame, TRUE, TRUE, 0); fbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(fbox), 5); gtk_container_add(GTK_CONTAINER(frame), fbox); #ifndef NO_MULTI rowbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0); label = gtk_label_new(_("Join Chat As:")); gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); create_joinchat_menu(rowbox); { GtkWidget *tmp = fbox; fbox = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(tmp), fbox); gtk_container_set_border_width(GTK_CONTAINER(fbox), 0); jc_vbox = fbox; } #else joinchatgc = connections->data; #endif rebuild_jc(); /* buttons */ bbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(mainbox), bbox, FALSE, FALSE, 0); cancel = picture_button(joinchat, _("Cancel"), cancel_xpm); gtk_box_pack_end(GTK_BOX(bbox), cancel, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(destroy_join_chat), joinchat); join = picture_button(joinchat, _("Join"), join_xpm); gtk_box_pack_end(GTK_BOX(bbox), join, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(join), "clicked", GTK_SIGNAL_FUNC(do_join_chat), NULL); } gtk_widget_show_all(joinchat); } static void do_invite(GtkWidget *w, struct conversation *b) { char *buddy; char *mess; if (!b->is_chat) { debug_printf("do_invite: expecting chat, got IM\n"); return; } buddy = gtk_entry_get_text(GTK_ENTRY(inviteentry)); mess = gtk_entry_get_text(GTK_ENTRY(invitemess)); if (invite) { serv_chat_invite(b->gc, b->id, mess, buddy); gtk_widget_destroy(invite); } invite = NULL; } void invite_callback(GtkWidget *w, struct conversation *b) { GtkWidget *cancel; GtkWidget *invite_btn; GtkWidget *label; GtkWidget *bbox; GtkWidget *vbox; GtkWidget *topbox; if (!invite) { invite = gtk_window_new(GTK_WINDOW_DIALOG); cancel = gtk_button_new_with_label(_("Cancel")); invite_btn = gtk_button_new_with_label(_("Invite")); bbox = gtk_hbox_new(TRUE, 10); topbox = gtk_hbox_new(FALSE, 5); vbox = gtk_vbox_new(FALSE, 5); inviteentry = gtk_entry_new(); invitemess = gtk_entry_new(); if (display_options & OPT_DISP_COOL_LOOK) { gtk_button_set_relief(GTK_BUTTON(cancel), GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(invite_btn), GTK_RELIEF_NONE); } /* Put the buttons in the box */ gtk_box_pack_start(GTK_BOX(bbox), invite_btn, TRUE, TRUE, 10); gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 10); label = gtk_label_new(_("Invite who?")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(topbox), label, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(topbox), inviteentry, FALSE, FALSE, 5); label = gtk_label_new(_("With message:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(topbox), label, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(topbox), invitemess, FALSE, FALSE, 5); /* And the boxes in the box */ gtk_box_pack_start(GTK_BOX(vbox), topbox, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 5); /* Handle closes right */ gtk_signal_connect(GTK_OBJECT(invite), "delete_event", GTK_SIGNAL_FUNC(destroy_invite), invite); gtk_signal_connect(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(destroy_invite), b); gtk_signal_connect(GTK_OBJECT(invite_btn), "clicked", GTK_SIGNAL_FUNC(do_invite), b); gtk_signal_connect(GTK_OBJECT(inviteentry), "activate", GTK_SIGNAL_FUNC(do_invite), b); /* Finish up */ gtk_widget_show(invite_btn); gtk_widget_show(cancel); gtk_widget_show(inviteentry); gtk_widget_show(invitemess); gtk_widget_show(topbox); gtk_widget_show(bbox); gtk_widget_show(vbox); gtk_window_set_title(GTK_WINDOW(invite), _("Invite to Buddy Chat")); gtk_window_set_focus(GTK_WINDOW(invite), inviteentry); gtk_container_add(GTK_CONTAINER(invite), vbox); gtk_widget_realize(invite); aol_icon(invite->window); } gtk_widget_show(invite); } gboolean meify(char *message) { /* read /me-ify : if the message (post-HTML) starts with /me, remove * the "/me " part of it (including that space) and return TRUE */ char *c = message; int inside_HTML = 0; /* i really don't like descriptive names */ if (!c) return FALSE; /* um... this would be very bad if this happens */ while (*c) { if (inside_HTML) { if (*c == '>') inside_HTML = 0; } else { if (*c == '<') inside_HTML = 1; else break; } c++; /* i really don't like c++ either */ } /* k, so now we've gotten past all the HTML crap. */ if (!*c) return FALSE; if (!strncasecmp(c, "/me ", 4)) { sprintf(c, "%s", c + 4); return TRUE; } else return FALSE; } void chat_write(struct conversation *b, char *who, int flag, char *message, time_t mtime) { GList *ignore = b->ignored; char *str; if (!b->is_chat) { debug_printf("chat_write: expecting chat, got IM\n"); return; } while (ignore) { if (!strcasecmp(who, ignore->data)) return; ignore = ignore->next; } if (!(flag & WFLAG_WHISPER)) { str = g_strdup(normalize(who)); if (!strcasecmp(str, normalize(b->gc->username))) { debug_printf("%s %s\n", normalize(who), normalize(b->gc->username)); if (b->makesound && (sound_options & OPT_SOUND_CHAT_YOU_SAY)) play_sound(CHAT_YOU_SAY); flag |= WFLAG_SEND; } else { if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY)) play_sound(CHAT_SAY); flag |= WFLAG_RECV; } g_free(str); } write_to_conv(b, message, flag, who, mtime); } void whisper_callback(GtkWidget *widget, struct conversation *b) { char buf[BUF_LEN * 4]; char buf2[BUF_LONG]; GList *selected; char *who; strncpy(buf, gtk_editable_get_chars(GTK_EDITABLE(b->entry), 0, -1), sizeof(buf) / 2); if (!strlen(buf)) return; selected = GTK_LIST(b->list)->selection; if (!selected) return; who = GTK_LABEL(gtk_container_children(GTK_CONTAINER(selected->data))->data)->label; if (!who) return; gtk_editable_delete_text(GTK_EDITABLE(b->entry), 0, -1); escape_text(buf); /* it's ok to leave this here because oscar can't whisper */ serv_chat_whisper(b->gc, b->id, who, buf); g_snprintf(buf2, sizeof(buf2), "%s->%s", b->gc->username, who); chat_write(b, buf2, WFLAG_WHISPER, buf, time((time_t)NULL)); gtk_widget_grab_focus(GTK_WIDGET(b->entry)); } void topic_callback(GtkWidget *widget, struct conversation *b) { char *buf = gtk_entry_get_text(GTK_ENTRY(widget));; serv_chat_set_topic(b->gc, b->id, buf); g_free(buf); } static gint insertname(gconstpointer one, gconstpointer two) { const char *a = (const char *)one; const char *b = (const char *)two; if (*a == '@') { if (*b != '@') return -1; return (strcmp(a + 1, b + 1)); } else if (*a == '+') { if (*b == '@') return 1; if (*b != '+') return -1; return (strcmp(a + 1, b + 1)); } else { if (*b == '@' || *b == '+') return 1; return strcmp(a, b); } } static void chat_press_im(GtkObject *obj, struct conversation *b) { struct conversation *c; c = find_conversation(gtk_object_get_user_data(obj)); if (c != NULL) gdk_window_show(c->window->window); else { c = new_conversation(gtk_object_get_user_data(obj)); set_convo_gc(c, b->gc); } } static void chat_press_ign(GtkWidget *obj, struct conversation *b) { gtk_list_select_child(GTK_LIST(b->list), gtk_object_get_user_data(GTK_OBJECT(obj))); ignore_callback(obj, b); } static void chat_press_info(GtkObject *obj, struct conversation *b) { (*b->gc->prpl->get_info)(b->gc, gtk_object_get_user_data(obj)); } static gint right_click_chat(GtkObject *obj, GdkEventButton *event, struct conversation *b) { if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkWidget *menu; GtkWidget *button; menu = gtk_menu_new(); button = gtk_menu_item_new_with_label(_("IM")); gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(chat_press_im), b); gtk_object_set_user_data(GTK_OBJECT(button), gtk_object_get_user_data(obj)); gtk_menu_append(GTK_MENU(menu), button); gtk_widget_show(button); button = gtk_menu_item_new_with_label(_("Ignore")); gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(chat_press_ign), b); gtk_object_set_user_data(GTK_OBJECT(button), obj); gtk_menu_append(GTK_MENU(menu), button); gtk_widget_show(button); if (b->gc->prpl->get_info) { button = gtk_menu_item_new_with_label(_("Info")); gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(chat_press_info), b); gtk_object_set_user_data(GTK_OBJECT(button), gtk_object_get_user_data(obj)); gtk_menu_append(GTK_MENU(menu), button); gtk_widget_show(button); } gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return TRUE; } void add_chat_buddy(struct conversation *b, char *buddy) { char *name = g_strdup(buddy); char tmp[BUF_LONG]; GtkWidget *list_item; int pos; GList *ignored; plugin_event(event_chat_buddy_join, b->gc, b->name, name, 0); b->in_room = g_list_insert_sorted(b->in_room, name, insertname); pos = g_list_index(b->in_room, name); ignored = b->ignored; while (ignored) { if (!strcasecmp(name, ignored->data)) break; ignored = ignored->next; } if (ignored) { g_snprintf(tmp, sizeof(tmp), "X %s", name); list_item = gtk_list_item_new_with_label(tmp); } else list_item = gtk_list_item_new_with_label(name); gtk_object_set_user_data(GTK_OBJECT(list_item), name); gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", GTK_SIGNAL_FUNC(right_click_chat), b); gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); gtk_widget_show(list_item); g_snprintf(tmp, sizeof(tmp), _("%d %s in room"), g_list_length(b->in_room), g_list_length(b->in_room) == 1 ? "person" : "people"); gtk_label_set_text(GTK_LABEL(b->count), tmp); if (b->makesound && (sound_options & OPT_SOUND_CHAT_JOIN)) play_sound(CHAT_JOIN); if (display_options & OPT_DISP_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s entered the room."), name); write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time((time_t)NULL)); } } void rename_chat_buddy(struct conversation *b, char *old, char *new) { GList *names = b->in_room; GList *items = GTK_LIST(b->list)->children; char *name = g_strdup(new); GtkWidget *list_item; int pos; GList *ignored = b->ignored; char tmp[BUF_LONG]; while (names) { if (!strcasecmp((char *)names->data, old)) { char *tmp2 = names->data; b->in_room = g_list_remove(b->in_room, names->data); while (items) { if (tmp2 == gtk_object_get_user_data(items->data)) { gtk_list_remove_items(GTK_LIST(b->list), g_list_append(NULL, items->data)); break; } items = items->next; } g_free(tmp2); break; } names = names->next; } if (!names) return; b->in_room = g_list_insert_sorted(b->in_room, name, insertname); pos = g_list_index(b->in_room, name); while (ignored) { if (!strcasecmp(old, ignored->data)) break; ignored = ignored->next; } if (ignored) { b->ignored = g_list_remove(b->ignored, ignored->data); b->ignored = g_list_append(b->ignored, name); g_snprintf(tmp, sizeof(tmp), "X %s", name); list_item = gtk_list_item_new_with_label(tmp); } else list_item = gtk_list_item_new_with_label(name); gtk_object_set_user_data(GTK_OBJECT(list_item), name); gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", GTK_SIGNAL_FUNC(right_click_chat), b); gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); gtk_widget_show(list_item); if (display_options & OPT_DISP_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s is now known as %s"), old, new); write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time((time_t)NULL)); } } void remove_chat_buddy(struct conversation *b, char *buddy) { GList *names = b->in_room; GList *items = GTK_LIST(b->list)->children; char tmp[BUF_LONG]; plugin_event(event_chat_buddy_leave, b->gc, b->name, buddy, 0); while (names) { if (!strcasecmp((char *)names->data, buddy)) { char *tmp = names->data; b->in_room = g_list_remove(b->in_room, names->data); while (items) { if (tmp == gtk_object_get_user_data(items->data)) { gtk_list_remove_items(GTK_LIST(b->list), g_list_append(NULL, items->data)); break; } items = items->next; } g_free(tmp); break; } names = names->next; } if (!names) return; g_snprintf(tmp, sizeof(tmp), _("%d %s in room"), g_list_length(b->in_room), g_list_length(b->in_room) == 1 ? "person" : "people"); gtk_label_set_text(GTK_LABEL(b->count), tmp); if (b->makesound && (sound_options & OPT_SOUND_CHAT_PART)) play_sound(CHAT_LEAVE); if (display_options & OPT_DISP_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s left the room."), buddy); write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time((time_t)NULL)); } } void im_callback(GtkWidget *w, struct conversation *b) { char *name; GList *i; struct conversation *c; i = GTK_LIST(b->list)->selection; if (i) name = (char *)gtk_object_get_user_data(GTK_OBJECT(i->data)); else return; c = find_conversation(name); if (c != NULL) { gdk_window_raise(c->window->window); } else { c = new_conversation(name); } } void ignore_callback(GtkWidget *w, struct conversation *b) { char *name; GList *i, *ignored; int pos; GtkWidget *list_item; char tmp[80]; i = GTK_LIST(b->list)->selection; if (i) name = (char *)gtk_object_get_user_data(GTK_OBJECT(i->data)); else return; pos = gtk_list_child_position(GTK_LIST(b->list), i->data); ignored = b->ignored; while (ignored) { if (!strcasecmp(name, ignored->data)) break; ignored = ignored->next; } if (ignored) { b->ignored = g_list_remove(b->ignored, ignored->data); g_snprintf(tmp, sizeof tmp, "%s", name); } else { b->ignored = g_list_append(b->ignored, g_strdup(name)); g_snprintf(tmp, sizeof tmp, "X %s", name); } list_item = gtk_list_item_new_with_label(tmp); gtk_object_set_user_data(GTK_OBJECT(list_item), name); gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); gtk_widget_destroy(i->data); gtk_widget_show(list_item); } static gint delete_all_chats(GtkWidget *w, GdkEventAny *e, gpointer d) { while (chats) { struct conversation *c = chats->data; close_callback(c->close, c); } return FALSE; } static void chat_switch(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer data) { GtkWidget *label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(chat_notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(chat_notebook), page_num)); GtkStyle *style; struct conversation *b = g_list_nth_data(chats, page_num); if (b && b->window && b->entry) gtk_window_set_focus(GTK_WINDOW(b->window), b->entry); if (!GTK_WIDGET_REALIZED(label)) return; style = gtk_style_new(); gdk_font_unref(style->font); style->font = gdk_font_ref(label->style->font); gtk_widget_set_style(label, style); gtk_style_unref(style); b->unseen = FALSE; } void show_new_buddy_chat(struct conversation *b) { GtkWidget *win; GtkWidget *cont; GtkWidget *text; GtkWidget *send; GtkWidget *list; GtkWidget *invite_btn; GtkWidget *whisper; GtkWidget *close; GtkWidget *chatentry; GtkWidget *lbox; GtkWidget *bbox; GtkWidget *bbox2; GtkWidget *im, *ignore, *info; GtkWidget *sw; GtkWidget *sw2; GtkWidget *vbox; GtkWidget *vpaned; GtkWidget *hpaned; GtkWidget *toolbar; char buf[BUF_LONG]; int dispstyle = set_dispstyle(1); if (display_options & OPT_DISP_ONE_CHAT_WINDOW) { if (!all_chats) { win = all_chats = b->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_wmclass(GTK_WINDOW(win), "buddy_chat", "Gaim"); gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE); gtk_container_border_width(GTK_CONTAINER(win), 0); gtk_widget_realize(win); aol_icon(win->window); gtk_window_set_title(GTK_WINDOW(win), _("Gaim - Group Chats")); gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(delete_all_chats), NULL); chat_notebook = gtk_notebook_new(); if (display_options & OPT_DISP_CHAT_SIDE_TAB) { if (display_options & OPT_DISP_CHAT_BR_TAB) { gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook), GTK_POS_RIGHT); } else { gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook), GTK_POS_LEFT); } } else { if (display_options & OPT_DISP_CHAT_BR_TAB) { gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook), GTK_POS_BOTTOM); } else { gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook), GTK_POS_TOP); } } gtk_notebook_set_scrollable(GTK_NOTEBOOK(chat_notebook), TRUE); gtk_notebook_popup_enable(GTK_NOTEBOOK(chat_notebook)); gtk_container_add(GTK_CONTAINER(win), chat_notebook); gtk_signal_connect(GTK_OBJECT(chat_notebook), "switch-page", GTK_SIGNAL_FUNC(chat_switch), NULL); gtk_widget_show(chat_notebook); } else win = b->window = all_chats; cont = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(cont), 5); gtk_notebook_append_page(GTK_NOTEBOOK(chat_notebook), cont, gtk_label_new(b->name)); gtk_widget_show(cont); } else { win = gtk_window_new(GTK_WINDOW_TOPLEVEL); b->window = win; gtk_object_set_user_data(GTK_OBJECT(win), b); gtk_window_set_wmclass(GTK_WINDOW(win), "buddy_chat", "Gaim"); gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE); gtk_container_border_width(GTK_CONTAINER(win), 10); gtk_widget_realize(win); aol_icon(win->window); g_snprintf(buf, sizeof(buf), "Gaim - %s (chat)", b->name); gtk_window_set_title(GTK_WINDOW(win), buf); gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(close_callback), b); cont = gtk_vbox_new(FALSE,5); gtk_container_add(GTK_CONTAINER(win), cont); gtk_widget_show(cont); } if (b->gc->prpl->options & OPT_PROTO_CHAT_TOPIC) { GtkWidget *hbox; GtkWidget *label; hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(cont), hbox, FALSE, FALSE, 5); gtk_widget_show(hbox); label = gtk_label_new(_("Topic:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); gtk_widget_show(label); b->topic_text = gtk_entry_new(); gtk_signal_connect(GTK_OBJECT(b->topic_text), "activate", GTK_SIGNAL_FUNC(topic_callback), b); gtk_box_pack_start(GTK_BOX(hbox), b->topic_text, TRUE, TRUE, 5); gtk_widget_show(b->topic_text); } vpaned = gtk_vpaned_new(); gtk_paned_set_gutter_size(GTK_PANED(vpaned), 15); gtk_container_add(GTK_CONTAINER(cont), vpaned); gtk_widget_show(vpaned); hpaned = gtk_hpaned_new(); gtk_paned_set_gutter_size(GTK_PANED(hpaned), 15); gtk_paned_pack1(GTK_PANED(vpaned), hpaned, TRUE, FALSE); gtk_widget_show(hpaned); sw = gtk_scrolled_window_new(NULL, NULL); b->sw = sw; gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_paned_pack1(GTK_PANED(hpaned), sw, TRUE, TRUE); gtk_widget_set_usize(sw, buddy_chat_size.width, buddy_chat_size.height); gtk_widget_show(sw); text = gtk_imhtml_new(NULL, NULL); b->text = text; gtk_container_add(GTK_CONTAINER(sw), text); GTK_LAYOUT(text)->hadjustment->step_increment = 10.0; GTK_LAYOUT(text)->vadjustment->step_increment = 10.0; if (display_options & OPT_DISP_SHOW_TIME) gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE); gaim_setup_imhtml(text); gtk_widget_show(text); lbox = gtk_vbox_new(FALSE, 5); gtk_paned_pack2(GTK_PANED(hpaned), lbox, TRUE, TRUE); gtk_widget_show(lbox); b->count = gtk_label_new(_("0 people in room")); gtk_box_pack_start(GTK_BOX(lbox), b->count, FALSE, FALSE, 0); gtk_widget_show(b->count); sw2 = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(lbox), sw2, TRUE, TRUE, 0); gtk_widget_show(sw2); list = gtk_list_new(); b->list = list; gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), list); gtk_widget_set_usize(list, 150, -1); gtk_widget_show(list); bbox2 = gtk_hbox_new(TRUE, 5); gtk_box_pack_start(GTK_BOX(lbox), bbox2, FALSE, FALSE, 0); gtk_widget_show(bbox2); im = picture_button2(win, _("IM"), tmp_send_xpm, FALSE); gtk_box_pack_start(GTK_BOX(bbox2), im, dispstyle, dispstyle, 0); gtk_signal_connect(GTK_OBJECT(im), "clicked", GTK_SIGNAL_FUNC(im_callback), b); ignore = picture_button2(win, _("Ignore"), close_xpm, FALSE); gtk_box_pack_start(GTK_BOX(bbox2), ignore, dispstyle, dispstyle, 0); gtk_signal_connect(GTK_OBJECT(ignore), "clicked", GTK_SIGNAL_FUNC(ignore_callback), b); info = picture_button2(win, _("Info"), tb_search_xpm, FALSE); gtk_box_pack_start(GTK_BOX(bbox2), info, dispstyle, dispstyle, 0); gtk_signal_connect(GTK_OBJECT(info), "clicked", GTK_SIGNAL_FUNC(info_callback), b); b->info = info; vbox = gtk_vbox_new(FALSE, 5); gtk_paned_pack2(GTK_PANED(vpaned), vbox, TRUE, FALSE); gtk_widget_show(vbox); chatentry = gtk_text_new(NULL, NULL); b->entry = chatentry; if (!(display_options & OPT_DISP_ONE_CHAT_WINDOW)) gtk_window_set_focus(GTK_WINDOW(b->window), b->entry); toolbar = build_conv_toolbar(b); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); gtk_object_set_user_data(GTK_OBJECT(chatentry), b); gtk_text_set_editable(GTK_TEXT(chatentry), TRUE); gtk_text_set_word_wrap(GTK_TEXT(chatentry), TRUE); gtk_signal_connect(GTK_OBJECT(chatentry), "activate", GTK_SIGNAL_FUNC(send_callback), b); gtk_signal_connect(GTK_OBJECT(chatentry), "key_press_event", GTK_SIGNAL_FUNC(keypress_callback), b); gtk_signal_connect(GTK_OBJECT(chatentry), "key_press_event", GTK_SIGNAL_FUNC(entry_key_pressed), chatentry); if (general_options & OPT_GEN_CHECK_SPELLING) gtkspell_attach(GTK_TEXT(chatentry)); gtk_box_pack_start(GTK_BOX(vbox), chatentry, TRUE, TRUE, 0); gtk_widget_set_usize(chatentry, buddy_chat_size.width, buddy_chat_size.entry_height); gtk_window_set_focus(GTK_WINDOW(win), chatentry); gtk_widget_show(chatentry); bbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); gtk_widget_show(bbox); close = picture_button2(win, _("Close"), cancel_xpm, dispstyle); b->close = close; gtk_object_set_user_data(GTK_OBJECT(close), b); gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(close_callback), b); gtk_box_pack_end(GTK_BOX(bbox), close, dispstyle, dispstyle, 0); invite_btn = picture_button2(win, _("Invite"), join_xpm, dispstyle); b->invite = invite_btn; gtk_signal_connect(GTK_OBJECT(invite_btn), "clicked", GTK_SIGNAL_FUNC(invite_callback), b); gtk_box_pack_end(GTK_BOX(bbox), invite_btn, dispstyle, dispstyle, 0); whisper = picture_button2(win, _("Whisper"), tb_forward_xpm, dispstyle); b->whisper = whisper; gtk_signal_connect(GTK_OBJECT(whisper), "clicked", GTK_SIGNAL_FUNC(whisper_callback), b); gtk_box_pack_end(GTK_BOX(bbox), whisper, dispstyle, dispstyle, 0); send = picture_button2(win, _("Send"), tmp_send_xpm, dispstyle); b->send = send; gtk_signal_connect(GTK_OBJECT(send), "clicked", GTK_SIGNAL_FUNC(send_callback), b); gtk_box_pack_end(GTK_BOX(bbox), send, dispstyle, dispstyle, 0); b->font_dialog = NULL; b->fg_color_dialog = NULL; b->bg_color_dialog = NULL; b->smiley_dialog = NULL; b->link_dialog = NULL; b->log_dialog = NULL; sprintf(b->fontface, "%s", fontface); b->hasfont = 0; b->fontsize = fontsize; b->hassize = 0; b->bgcol = bgcolor; b->hasbg = 0; b->fgcol = fgcolor; b->hasfg = 0; update_buttons_by_protocol(b); gtk_widget_show(win); } void chat_set_topic(struct conversation *b, char* who, char* topic) { gtk_entry_set_text(GTK_ENTRY(b->topic_text), topic); } void handle_click_chat(GtkWidget *widget, GdkEventButton * event, struct chat_room *cr) { if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { /* FIXME : double click on chat in buddy list */ serv_join_chat(connections->data, cr->exchange, cr->name); } } void setup_buddy_chats() { GList *list; struct chat_room *cr; GList *crs = chat_rooms; GtkWidget *w; GtkWidget *item; GtkWidget *tree; if (buddies == NULL) return; list = GTK_TREE(buddies)->children; while (list) { w = (GtkWidget *)list->data; if (!strcmp(GTK_LABEL(GTK_BIN(w)->child)->label, _("Buddy Chat"))) { gtk_tree_remove_items(GTK_TREE(buddies), list); list = GTK_TREE(buddies)->children; if (!list) break; } list = list->next; } if (crs == NULL) return; item = gtk_tree_item_new_with_label(_("Buddy Chat")); tree = gtk_tree_new(); gtk_widget_show(item); gtk_widget_show(tree); gtk_tree_append(GTK_TREE(buddies), item); gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), tree); gtk_tree_item_expand(GTK_TREE_ITEM(item)); while (crs) { cr = (struct chat_room *)crs->data; item = gtk_tree_item_new_with_label(cr->name); gtk_object_set_user_data(GTK_OBJECT(item), cr); gtk_tree_append(GTK_TREE(tree), item); gtk_widget_show(item); gtk_signal_connect(GTK_OBJECT(item), "button_press_event", GTK_SIGNAL_FUNC(handle_click_chat), cr); crs = crs->next; } } static GtkWidget *change_text(GtkWidget *win, char *text, GtkWidget *button, char **xpm, int chat) { int dispstyle = set_dispstyle(chat); GtkWidget *parent = button->parent; gtk_widget_destroy(button); button = picture_button2(win, text, xpm, dispstyle); if (chat == 1) gtk_box_pack_start(GTK_BOX(parent), button, dispstyle, dispstyle, 5); else gtk_box_pack_end(GTK_BOX(parent), button, dispstyle, dispstyle, 0); gtk_widget_show(button); return button; } void update_chat_button_pix() { GSList *C = connections; struct gaim_connection *g; while (C) { GSList *bcs; struct conversation *c; int opt = 1; g = (struct gaim_connection *)C->data; bcs = g->buddy_chats; while (bcs) { c = (struct conversation *)bcs->data; c->send = change_text(c->window, _("Send"), c->send, tmp_send_xpm, opt); c->whisper = change_text(c->window, _("Whisper"), c->whisper, tb_forward_xpm, opt); c->invite = change_text(c->window, _("Invite"), c->invite, join_xpm, opt); c->close = change_text(c->window, _("Close"), c->close, cancel_xpm, opt); gtk_object_set_user_data(GTK_OBJECT(c->close), c); gtk_signal_connect(GTK_OBJECT(c->close), "clicked", GTK_SIGNAL_FUNC(close_callback), c); gtk_signal_connect(GTK_OBJECT(c->send), "clicked", GTK_SIGNAL_FUNC(send_callback), c); gtk_signal_connect(GTK_OBJECT(c->invite), "clicked", GTK_SIGNAL_FUNC(invite_callback), c); gtk_signal_connect(GTK_OBJECT(c->whisper), "clicked", GTK_SIGNAL_FUNC(whisper_callback), c); bcs = bcs->next; } C = C->next; } } void update_im_button_pix() { GList *bcs = conversations; struct conversation *c; GtkWidget *parent; int opt = 0; int dispstyle = set_dispstyle(0); while (bcs) { c = (struct conversation *)bcs->data; parent = c->close->parent; c->close = change_text(c->window, _("Close"), c->close, cancel_xpm, opt); gtk_box_reorder_child(GTK_BOX(parent), c->close, 0); gtk_box_set_child_packing(GTK_BOX(parent), c->sep1, dispstyle, dispstyle, 0, GTK_PACK_END); if (find_buddy(c->gc, c->name) == NULL) c->add = change_text(c->window, _("Add"), c->add, gnome_add_xpm, opt); else c->add = change_text(c->window, _("Remove"), c->add, gnome_remove_xpm, opt); gtk_box_reorder_child(GTK_BOX(parent), c->add, 2); c->block = change_text(c->window, _("Block"), c->block, block_xpm, opt); gtk_box_reorder_child(GTK_BOX(parent), c->block, 3); c->warn = change_text(c->window, _("Warn"), c->warn, warn_xpm, opt); gtk_box_reorder_child(GTK_BOX(parent), c->warn, 4); c->info = change_text(c->window, _("Info"), c->info, tb_search_xpm, opt); gtk_box_reorder_child(GTK_BOX(parent), c->info, 5); c->send = change_text(c->window, _("Send"), c->send, tmp_send_xpm, opt); gtk_box_set_child_packing(GTK_BOX(parent), c->sep2, dispstyle, dispstyle, 0, GTK_PACK_END); gtk_box_reorder_child(GTK_BOX(parent), c->send, 7); gtk_object_set_user_data(GTK_OBJECT(c->close), c); gtk_signal_connect(GTK_OBJECT(c->close), "clicked", GTK_SIGNAL_FUNC(close_callback), c); gtk_signal_connect(GTK_OBJECT(c->send), "clicked", GTK_SIGNAL_FUNC(send_callback), c); gtk_signal_connect(GTK_OBJECT(c->add), "clicked", GTK_SIGNAL_FUNC(add_callback), c); gtk_signal_connect(GTK_OBJECT(c->info), "clicked", GTK_SIGNAL_FUNC(info_callback), c); gtk_signal_connect(GTK_OBJECT(c->warn), "clicked", GTK_SIGNAL_FUNC(warn_callback), c); gtk_signal_connect(GTK_OBJECT(c->block), "clicked", GTK_SIGNAL_FUNC(block_callback), c); bcs = bcs->next; } } void chat_tabize() { /* evil, evil i tell you! evil! */ if (display_options & OPT_DISP_ONE_CHAT_WINDOW) { GList *x = chats; while (x) { struct conversation *c = x->data; GtkWidget *imhtml, *win; imhtml = c->text; win = c->window; show_new_buddy_chat(c); gtk_widget_destroy(c->text); gtk_widget_reparent(imhtml, c->sw); c->text = imhtml; gtk_signal_disconnect_by_func(GTK_OBJECT(win), GTK_SIGNAL_FUNC(close_callback), c); gtk_widget_destroy(win); x = x->next; } } else { GList *x, *m; x = m = chats; chats = NULL; while (x) { struct conversation *c = x->data; GtkWidget *imhtml; imhtml = c->text; show_new_buddy_chat(c); gtk_widget_destroy(c->text); gtk_widget_reparent(imhtml, c->sw); c->text = imhtml; x = x->next; } if (all_chats) gtk_widget_destroy(all_chats); all_chats = NULL; chat_notebook = NULL; chats = m; } }