From: Bostjan L. <bos...@us...> - 2002-11-30 00:50:43
|
Update of /cvsroot/licq/jons-gtk2-gui/src In directory sc8-pr-cvs1:/tmp/cvs-serv4309/src Added Files: Makefile.am about_window.cpp add_user_window.cpp auth_user_window.cpp away_window.cpp chat_window.cpp contact_list.cpp convo.cpp eggtrayicon.c eggtrayicon.h event_description.cpp event_description.h extras.cpp file_window.cpp history_window.cpp key_request.cpp licq_gtk.h log_window.cpp main.cpp main_window.cpp menu.cpp more_window.cpp option_window.cpp pipe.cpp plugin_window.cpp random_chat.cpp register_user.cpp search_user_window.cpp security_window.cpp stats_window.cpp status.cpp system_message.cpp system_status.cpp tray.cpp user_info_window.cpp user_menu.cpp Log Message: final proper import of jons-gtk2-gui --- NEW FILE: Makefile.am --- #hack, fix this in a clean manner libdir = $(prefix)/lib/licq INCLUDES = -Wall -D_REENTRANT \ -I$(LICQ_INCLUDES) -DG_LOG_DOMAIN=\"licq_jons-gtk2-gui\" \ `pkg-config --cflags gtk+-2.0` lib_LTLIBRARIES = licq_jons-gtk2-gui.la noinst_HEADERS = licq_gtk.h licq_jons_gtk2_gui_la_SOURCES = about_window.cpp \ add_user_window.cpp \ auth_user_window.cpp \ away_window.cpp \ chat_window.cpp \ contact_list.cpp \ convo.cpp \ event_description.cpp \ extras.cpp \ file_window.cpp \ history_window.cpp \ key_request.cpp \ log_window.cpp \ main.cpp \ main_window.cpp \ menu.cpp \ more_window.cpp \ option_window.cpp \ pipe.cpp \ plugin_window.cpp \ random_chat.cpp \ register_user.cpp \ search_user_window.cpp \ security_window.cpp \ stats_window.cpp \ status.cpp \ system_message.cpp \ system_status.cpp \ user_menu.cpp \ user_info_window.cpp \ tray.cpp \ eggtrayicon.c licq_jons_gtk2_gui_la_LDFLAGS = -s -module -avoid-version -rpath $(libdir) \ `pkg-config --libs gtk+-2.0` --- NEW FILE: about_window.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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 "licq_gtk.h" #include "licq_icqd.h" #include <sys/utsname.h> GtkWidget *about_window = 0; void create_about_window() { // Only one about window if(about_window != 0) { gdk_window_raise(about_window->window); return; } // Make the window now about_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(about_window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(about_window), "About Licq"); // Window delete event g_signal_connect(GTK_OBJECT(about_window), "destroy", G_CALLBACK(close_about_window), 0); // A vertical box for the label and ok button GtkWidget *v_box = gtk_vbox_new(false, 5); gtk_container_add(GTK_CONTAINER(about_window), v_box); ICQOwner *o = gUserManager.FetchOwner(LOCK_R); struct utsname un; uname(&un); // A label to be in the box.. with centered text GtkWidget *label = gtk_label_new( g_strdup_printf("Licq Version: %s\n" "Jon's GTK2 GUI Version: %s\n" "GTK+ Version: %d.%d.%d\n" "Compiled On: %s\n" "Currently Running On: %s %s [%s]\n\n" "Author: Jon Keating <jo...@li...>\n" "http://jons-gtk-gui.sourceforge.net\n\n" "%s (%ld)\n" "%d Contacts", icq_daemon->Version(), VERSION, gtk_major_version, gtk_minor_version, gtk_micro_version, __DATE__, un.sysname, un.release, un.machine, o->GetAlias(), o->Uin(), gUserManager.NumUsers())); gUserManager.DropOwner(); gtk_box_pack_start(GTK_BOX(v_box), label, false, false, 0); GtkWidget *ok = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect(GTK_OBJECT(ok), "clicked", G_CALLBACK(close_about_window), 0); gtk_box_pack_start(GTK_BOX(v_box), ok, true, true, 0); gtk_widget_show_all(about_window); } void close_about_window(GtkWidget *widget, gpointer data) { gtk_widget_destroy(about_window); about_window = 0; } --- NEW FILE: add_user_window.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ #include <stdlib.h> #include <gtk/gtk.h> #include "licq_icqd.h" #include "licq_gtk.h" void menu_system_add_user(GtkWidget *window, gpointer data) { GtkWidget *ok; GtkWidget *cancel; GtkWidget *label; GtkWidget *h_box; GtkWidget *v_box; struct add_user *a = g_new0(struct add_user, 1); /* Make up the window for adding users */ a->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(a->window), "Licq - Add User"); gtk_window_set_position(GTK_WINDOW(a->window), GTK_WIN_POS_CENTER); /* The main box */ v_box = gtk_vbox_new(FALSE, 5); /* Work on the first hbox */ h_box = gtk_hbox_new(FALSE, 5); label = gtk_label_new("Add Uin: "); a->entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(a->entry), MAX_LENGTH_UIN); gtk_box_pack_start(GTK_BOX(h_box), label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(h_box), a->entry, TRUE, TRUE, 0); /* Accept only numbers in the a->entry */ g_signal_connect(G_OBJECT(a->entry), "insert-text", G_CALLBACK(verify_numbers), 0); /* Add the first hbox to the top of the vbox */ gtk_box_pack_start(GTK_BOX(v_box), h_box, TRUE, TRUE, 5); /* Work on the send hbox */ h_box = gtk_hbox_new(FALSE, 0); a->check_box = gtk_check_button_new_with_label("Alert User"); gtk_box_pack_start(GTK_BOX(h_box), a->check_box, TRUE, TRUE, 0); /* Add the second hbox to the vbox */ gtk_box_pack_start(GTK_BOX(v_box), h_box, TRUE, TRUE, 0); /* Work on the third hbox, with the buttons */ h_box = gtk_hbox_new(FALSE, 5); ok = gtk_button_new_with_mnemonic("_Add"); gtk_box_pack_start(GTK_BOX(h_box), ok, TRUE, TRUE, 10); cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_start(GTK_BOX(h_box), cancel, TRUE, TRUE, 10); /* Add the third and final hbox to the vbox */ gtk_box_pack_start(GTK_BOX(v_box), h_box, TRUE, TRUE, 5); /* Connect all the signals to functions */ g_signal_connect(G_OBJECT(cancel), "clicked", G_CALLBACK(dialog_close), a->window); g_signal_connect(G_OBJECT(a->window), "destroy", G_CALLBACK(dialog_close), a->window); g_signal_connect(G_OBJECT(ok), "clicked", G_CALLBACK(add_user_callback), a); /* Show the widgets and grab the focus */ gtk_container_add(GTK_CONTAINER(a->window), v_box); gtk_widget_show_all(a->window); gtk_window_set_focus(GTK_WINDOW(a->window), a->entry); } void add_user_callback(GtkWidget *widget, struct add_user *a) { unsigned long uin = atol((const char *)gtk_entry_get_text(GTK_ENTRY(a->entry))); icq_daemon->AddUserToList(uin); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(a->check_box))) icq_daemon->icqAlertUser(uin); gtk_widget_destroy(a->window); } void dialog_close(GtkWidget *widget, GtkWidget *destroy) { gtk_widget_destroy(destroy); } --- NEW FILE: auth_user_window.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ #include <gtk/gtk.h> #include "licq_icqd.h" #include "licq_gtk.h" void menu_system_auth_user(GtkWidget *widget, const unsigned long uin) { GtkWidget *label; GtkWidget *scroll; GtkWidget *ok; GtkWidget *cancel; GtkWidget *refuse; GtkWidget *h_box; GtkWidget *v_box; struct auth_user *au = g_new0(struct auth_user, 1); /* Create the window */ au->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(au->window), "Licq - Authorize User"); /* Make the boxes */ h_box = gtk_hbox_new(FALSE, 5); v_box = gtk_vbox_new(FALSE, 5); /* Make the label and entry and pack them */ label = gtk_label_new("Authorize UIN:"); au->entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(au->entry), MAX_LENGTH_UIN); gtk_box_pack_start(GTK_BOX(h_box), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(h_box), au->entry, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 5); /* Accept only numbers in au->entry */ g_signal_connect(G_OBJECT(au->entry), "insert-text", G_CALLBACK(verify_numbers), 0); /* Make the scrolled text box */ au->text = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(au->text), TRUE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(au->text), GTK_WRAP_WORD); scroll = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scroll), au->text); gtk_box_pack_start(GTK_BOX(v_box), scroll, FALSE, FALSE, 5); /* Make the buttons and pack them */ h_box = gtk_hbox_new(FALSE, 5); ok = gtk_button_new_from_stock(GTK_STOCK_OK); refuse = gtk_button_new_with_mnemonic("_Refuse"); cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_start(GTK_BOX(h_box), ok, TRUE, TRUE, 15); gtk_box_pack_start(GTK_BOX(h_box), refuse, TRUE, TRUE, 15); gtk_box_pack_start(GTK_BOX(h_box), cancel, TRUE, TRUE, 15); gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 5); /* Connect the signals */ g_signal_connect(G_OBJECT(cancel), "clicked", G_CALLBACK(dialog_close), au->window); g_signal_connect(G_OBJECT(au->window), "destroy", G_CALLBACK(dialog_close), au->window); g_signal_connect(G_OBJECT(ok), "clicked", G_CALLBACK(auth_user_grant), au); g_signal_connect(G_OBJECT(refuse), "clicked", G_CALLBACK(auth_user_refuse), au); /* Show the window */ gtk_container_add(GTK_CONTAINER(au->window), v_box); gtk_widget_show_all(au->window); gtk_window_set_focus(GTK_WINDOW(au->window), au->entry); if(uin != 0) { const gchar *s_uin = g_strdup_printf("%ld", uin); gtk_entry_set_text(GTK_ENTRY(au->entry), s_uin); } } void auth_user_grant(GtkWidget *widget, struct auth_user *au) { gulong uin = atol((const char *)gtk_editable_get_chars(GTK_EDITABLE( au->entry), 0, -1)); gchar *reason = gtk_editable_get_chars(GTK_EDITABLE(au->text), 0, -1); icq_daemon->icqAuthorizeGrant(uin, reason); dialog_close(au->window, au->window); } void auth_user_refuse(GtkWidget *widget, struct auth_user *au) { gulong uin = atol((const char *)gtk_editable_get_chars(GTK_EDITABLE( au->entry), 0, -1)); gchar *reason = gtk_editable_get_chars(GTK_EDITABLE(au->text), 0, -1); /* Refuse it */ icq_daemon->icqAuthorizeRefuse(uin, reason); dialog_close(au->window, au->window); } --- NEW FILE: away_window.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ #include <gtk/gtk.h> #include "licq_icqd.h" #include "licq_gtk.h" GSList *uaw_list; void away_msg_window(gushort status) { struct away_dialog *away_d = g_new0(struct away_dialog, 1); GtkWidget *ok; GtkWidget *cancel; GtkWidget *h_box; GtkWidget *v_box; const gchar *title = g_strdup_printf("Set %s Response", ICQUser::StatusToStatusStr(status, FALSE)); /* Make the main window */ away_d->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(away_d->window), title); gtk_window_set_position(GTK_WINDOW(away_d->window), GTK_WIN_POS_CENTER); /* The text box */ away_d->text = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(away_d->text), TRUE); gtk_widget_set_size_request(GTK_WIDGET(away_d->text), 300, 100); /* The boxes */ h_box = gtk_hbox_new(TRUE, 5); v_box = gtk_vbox_new(FALSE, 5); /* Pack the text box into the v_box */ gtk_box_pack_start(GTK_BOX(v_box), away_d->text, TRUE, TRUE, 0); /* Make the buttons now */ ok = gtk_button_new_from_stock(GTK_STOCK_OK); cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); /* Pack the buttons */ gtk_box_pack_start(GTK_BOX(h_box), ok, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(h_box), cancel, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 0); /* Connect the signals now */ g_signal_connect(G_OBJECT(cancel), "clicked", G_CALLBACK(away_close), away_d->window); g_signal_connect(G_OBJECT(away_d->window), "destroy", G_CALLBACK(away_close), away_d->window); g_signal_connect(G_OBJECT(ok), "clicked", G_CALLBACK(set_away_msg), away_d); /* Get the window ready to be shown, show it, and set is_shown */ gtk_container_add(GTK_CONTAINER(away_d->window), v_box); gtk_widget_show_all(away_d->window); gtk_window_set_focus(GTK_WINDOW(away_d->window), away_d->text); gtk_grab_add(away_d->window); } void set_away_msg(GtkWidget *widget, struct away_dialog *away_d) { ICQOwner *owner = gUserManager.FetchOwner(LOCK_W); GtkTextIter s, e; GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(away_d->text)); gtk_text_buffer_get_start_iter(tb, &s); gtk_text_buffer_get_end_iter(tb, &e); gchar *txt = gtk_text_buffer_get_text(tb, &s, &e, FALSE); owner->SetAutoResponse(txt); g_free(txt); gUserManager.DropOwner(); gtk_grab_remove(away_d->window); gtk_widget_destroy(away_d->window); } void away_close(GtkWidget *widget, GtkWidget *window) { gtk_grab_remove(window); gtk_widget_destroy(window); } void list_read_message(GtkWidget *widget, ICQUser *user) { struct user_away_window *uaw = uaw_find(user->Uin()); if(uaw != 0) return; uaw = uaw_new(user); GtkWidget *h_box; GtkWidget *v_box; GtkWidget *scroll; GtkWidget *close; const gchar *title = g_strdup_printf("Auto Response for %s", user->GetAlias()); struct e_tag_data *etd = g_new0(struct e_tag_data, 1); uaw->user = user; uaw->etag = etd; /* Make the window */ uaw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(uaw->window), title); gtk_window_set_position(GTK_WINDOW(uaw->window), GTK_WIN_POS_CENTER); g_signal_connect(G_OBJECT(uaw->window), "destroy", G_CALLBACK(close_away_window), uaw); /* Make the boxes */ h_box = gtk_hbox_new(FALSE, 5); v_box = gtk_vbox_new(FALSE, 5); /* The scrolling window */ scroll = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); /* The text box */ uaw->text_box = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(uaw->text_box), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(uaw->text_box), GTK_WRAP_WORD); gtk_widget_set_size_request(uaw->text_box, 235, 60); /* Add the text box to the scrolling window */ gtk_container_add(GTK_CONTAINER(scroll), uaw->text_box); /* Pack the scrolled window into the v_box */ gtk_box_pack_start(GTK_BOX(v_box), scroll, TRUE, TRUE, 5); /* The Show Again check button */ uaw->show_again = gtk_check_button_new_with_label("Show Again"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(uaw->show_again), user->ShowAwayMsg()); /* The close button */ close = gtk_button_new_from_stock(GTK_STOCK_CLOSE); g_signal_connect(G_OBJECT(close), "clicked", G_CALLBACK(close_away_window), uaw); /* Pack everything */ gtk_box_pack_start(GTK_BOX(h_box), uaw->show_again, TRUE, TRUE, 10); gtk_box_pack_start(GTK_BOX(h_box), close, TRUE, TRUE, 10); gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 5); /* The progress bar */ uaw->progress = gtk_statusbar_new(); strcpy(uaw->buffer, "Checking Response ... "); guint id = gtk_statusbar_get_context_id(GTK_STATUSBAR(uaw->progress), "prog"); gtk_statusbar_pop(GTK_STATUSBAR(uaw->progress), id); gtk_statusbar_push(GTK_STATUSBAR(uaw->progress), id, uaw->buffer); /* Pack the progress bar */ gtk_box_pack_start(GTK_BOX(v_box), uaw->progress, FALSE, FALSE, 5); gtk_container_add(GTK_CONTAINER(uaw->window), v_box); gtk_widget_show_all(uaw->window); /* etd stuff */ uaw->etag->statusbar = uaw->progress; strcpy(uaw->etag->buf, uaw->buffer); /* Get the response */ uaw->etag->e_tag = icq_daemon->icqFetchAutoResponse(user->Uin()); /* Append it to gslist */ catcher = g_slist_append(catcher, uaw->etag); g_free(const_cast<char *>(title)); } void close_away_window(GtkWidget *widget, struct user_away_window *uaw) { uaw->user->SetShowAwayMsg(gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(uaw->show_again))); uaw_list = g_slist_remove(uaw_list, uaw); catcher = g_slist_remove(catcher, uaw->etag); dialog_close(0, uaw->window); } /* The following will ensure only one window is open and that when the * ** Auto Response is received, it pops up in the box there. Now the * ** status of the connection will be brought back to this window */ struct user_away_window *uaw_new(ICQUser *u) { struct user_away_window *uaw; /* Does it exist already? */ uaw = uaw_find(u->Uin()); /* If it does, return it, if not, make one */ if(uaw != 0) return uaw; uaw = g_new0(struct user_away_window, 1); uaw->user = u; uaw_list = g_slist_append(uaw_list, uaw); // list_read_message(0, uaw->user); return uaw; } struct user_away_window *uaw_find(unsigned long uin) { struct user_away_window *uaw; GSList *temp_uaw_list = uaw_list; while(temp_uaw_list) { uaw = (struct user_away_window *)temp_uaw_list->data; if(uaw->user->Uin() == uin) return uaw; temp_uaw_list = temp_uaw_list->next; } /* It wasn't found, return null */ return 0; } --- NEW FILE: chat_window.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ [...1411 lines suppressed...] if(len < 45) strncpy(cw->l_font_name, tmp, len); else strncpy(cw->l_font_name, "clean", 6); g_print("Final: %s\n", cw->l_font_name); cw->chatman->ChangeFontFamily(cw->l_font_name); } gchar *fname = gtk_font_selection_dialog_get_font_name( GTK_FONT_SELECTION_DIALOG(cw->font_sel_dlg)); if (fname != 0) cw->l_font = pango_font_description_from_string(fname); g_free(fname); // Ok, close it now gtk_widget_destroy(cw->font_sel_dlg); } --- NEW FILE: contact_list.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ #include "licq_gtk.h" #include "licq_icqd.h" #include "licq_user.h" #include <string.h> #include <gtk/gtk.h> #include <sys/time.h> #include <list> using namespace std; gboolean bFlashOn = false; gint nToFlash = -1; GdkColor *red, *blue, *online_color, *offline_color, *away_color; GdkPixbuf *online, *offline, *away, *na, *dnd, *occ, *ffc, *invisible, *message_icon, *file_icon, *chat_icon, *url_icon, *secure_icon, *birthday_icon, *securebday_icon, *blank_icon; list<unsigned long> AutoSecureList; list<SFlash *> FlashList; enum { COL_SORT, COL_STATUS_IMAGE, COL_ALIAS, COL_ALIAS_COLOR, COL_SSL_IMAGE, COL_PUSER, N_COLS }; GtkWidget *contact_list_new(gint height, gint width) { GtkWidget *_contact_l; /* Create the contact list using a 6 column clist */ GtkListStore *store = gtk_list_store_new(N_COLS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_COLOR, GDK_TYPE_PIXBUF, G_TYPE_POINTER); _contact_l = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COL_SORT, GTK_SORT_ASCENDING); g_object_unref(G_OBJECT(store)); GtkCellRenderer *r_text = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(r_text), "ypad", 0, NULL); GtkCellRenderer *r_pic = gtk_cell_renderer_pixbuf_new(); g_object_set(G_OBJECT(r_pic), "ypad", 0, NULL); GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes("Pic", r_pic, "pixbuf", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(_contact_l), col); // Here we'll need 2 renderers - one for text and one for a pic // for a possible ssl icon col = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(col, r_text, FALSE); gtk_tree_view_column_pack_start(col, r_pic, FALSE); gtk_tree_view_column_add_attribute(col, r_text, "text", COL_ALIAS); gtk_tree_view_column_add_attribute(col, r_text, "foreground-gdk", COL_ALIAS_COLOR); gtk_tree_view_column_add_attribute(col, r_pic, "pixbuf", COL_SSL_IMAGE); gtk_tree_view_append_column(GTK_TREE_VIEW(_contact_l), col); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(_contact_l), FALSE); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(_contact_l)); /* Size the contact list */ //gtk_widget_set_size_request(_contact_l, width, height); /* A double click on a user name */ g_signal_connect(G_OBJECT(_contact_l), "button_press_event", G_CALLBACK(contact_list_click), 0); // gtk_clist_set_button_actions(GTK_CLIST(_contact_l), 0, GTK_BUTTON_IGNORED); return _contact_l; } gint flash_icons(gpointer data) { // If we aren't supposed to flash or there are no things to flash if(!flash_events || (nToFlash < 0)) return -1; GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(contact_list))); list<SFlash *>::iterator it; for(it = FlashList.begin(); it != FlashList.end(); it++) { GtkTreeIter iter; if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, (*it)->path)) continue; if(!(*it)->bFlashOn) { (*it)->bFlashOn = true; gtk_list_store_set(store, &iter, COL_STATUS_IMAGE, blank_icon, -1); } else { (*it)->bFlashOn = false; gtk_list_store_set(store, &iter, COL_STATUS_IMAGE, (*it)->icon, -1); } } return -1; } void contact_list_refresh() { gint num_users = 0; nToFlash = -1; GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(contact_list))); gtk_list_store_clear(store); GtkTreeIter iter; /* Now go through all the users */ FOR_EACH_USER_START(LOCK_R) { /* If they are on the ignore list and the user has the option * "Show ignored users" diabled, then don't show them */ if(pUser->IgnoreList() && !show_ignored_users) { FOR_EACH_USER_CONTINUE } /* If they are offline and we do not want to see offline users, * just keep oin going! */ if(pUser->Status() == ICQ_STATUS_OFFLINE && !show_offline_users) { FOR_EACH_USER_CONTINUE } /* Make an empty row first */ gtk_list_store_append(store, &iter); /* Get the status of the user */ gulong user_status = pUser->StatusFull(); // The icon to set if(pUser->NewMessages() > 0) { CUserEvent *ue = pUser->EventPeekFirst(); GdkPixbuf *icon; switch(ue->SubCommand()) { case ICQ_CMDxSUB_MSG: icon = message_icon; break; case ICQ_CMDxSUB_URL: icon = url_icon; break; case ICQ_CMDxSUB_FILE: icon = file_icon; break; case ICQ_CMDxSUB_CHAT: icon = chat_icon; break; default: icon = message_icon; break; } gtk_list_store_set(store, &iter, COL_SORT, 1, COL_STATUS_IMAGE, icon, -1); if(flash_events) { struct SFlash *flash = g_new0(struct SFlash, 1); flash->path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); flash->icon = icon; flash->bFlashOn = false; flash->nUin = pUser->Uin(); FlashList.push_back(flash); ++nToFlash; } } else { GdkPixbuf *cur_icon = offline; if((gushort)user_status != ICQ_STATUS_OFFLINE && (user_status & ICQ_STATUS_FxPRIVATE)) { cur_icon = invisible; gtk_list_store_set(store, &iter, COL_SORT, ",", -1); } else if((gushort)user_status == ICQ_STATUS_OFFLINE) { cur_icon = offline; gtk_list_store_set(store, &iter, COL_SORT, 100, -1); //"~", -1); } else if(user_status & ICQ_STATUS_DND) { cur_icon = dnd; gtk_list_store_set(store, &iter, COL_SORT, 50, -1); //"X", -1); } else if(user_status & ICQ_STATUS_OCCUPIED) { cur_icon = occ; gtk_list_store_set(store, &iter, COL_SORT, 60, -1); //"x", -1); } else if(user_status & ICQ_STATUS_NA) { cur_icon = na; gtk_list_store_set(store, &iter, COL_SORT, 40, -1); //"N", -1); } else if(user_status & ICQ_STATUS_AWAY) { cur_icon = away; gtk_list_store_set(store, &iter, COL_SORT, 30, -1); //"A", -1); } else if(user_status & ICQ_STATUS_FREEFORCHAT) { cur_icon = ffc; gtk_list_store_set(store, &iter, COL_SORT, 20, -1); //"*", -1); } else if(user_status & ICQ_STATUS_OCCUPIED) { cur_icon = occ; gtk_list_store_set(store, &iter, COL_SORT, 60, -1); //"x", -1); } else { cur_icon = online; gtk_list_store_set(store, &iter, COL_SORT, 10, -1); // "+", -1); } gtk_list_store_set(store, &iter, COL_STATUS_IMAGE, cur_icon, -1); } // else gtk_list_store_set(store, &iter, COL_ALIAS_COLOR, get_status_color(user_status), -1); // See if they are not offline and want to be auto secured if(pUser->Status() != ICQ_STATUS_OFFLINE && pUser->AutoSecure()) { // Ok, now *can* they be auto secured? if((pUser->SecureChannelSupport() == SECURE_CHANNEL_SUPPORTED) && !pUser->Secure()) AutoSecureList.push_back(pUser->Uin()); } gtk_list_store_set(store, &iter, COL_ALIAS, pUser->GetAlias(), -1); if(pUser->Secure() && (pUser->Birthday() == 0)) { gtk_list_store_set(store, &iter, COL_SSL_IMAGE, securebday_icon, -1); } else if(pUser->Secure()) { gtk_list_store_set(store, &iter, COL_SSL_IMAGE, secure_icon, -1); } else if(pUser->Birthday() == 0) { gtk_list_store_set(store, &iter, COL_SSL_IMAGE, birthday_icon, -1); } gtk_list_store_set(store, &iter, COL_PUSER, (gpointer)pUser, -1); num_users++; FOR_EACH_USER_CONTINUE } FOR_EACH_USER_END // Now do the auto secure stuff list<unsigned long>::iterator it; for(it = AutoSecureList.begin(); it != AutoSecureList.end(); it++) { icq_daemon->icqOpenSecureChannel(*it); } AutoSecureList.clear(); } GdkColor *get_status_color(unsigned long nStatus) { if (nStatus == ICQ_STATUS_OFFLINE) return offline_color; if ((nStatus & ICQ_STATUS_AWAY) || (nStatus & ICQ_STATUS_NA) || (nStatus & ICQ_STATUS_DND) || (nStatus & ICQ_STATUS_OCCUPIED)) return away_color; return online_color; } gboolean contact_list_click(GtkWidget *contact_list, GdkEventButton *event, gpointer data) { gchar str_status[30]; ICQUser *user = 0; struct conversation *c = 0; struct timeval check_timer; GtkTreeIter iter; GtkTreeView *tv = GTK_TREE_VIEW(contact_list); GtkTreePath *path; if (!gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL)) return FALSE; gtk_tree_model_get_iter(gtk_tree_view_get_model(tv), &iter, path); gtk_tree_model_get(gtk_tree_view_get_model(tv), &iter, COL_PUSER, &user, -1); /* No user was clicked on */ if(user == 0) return FALSE; /* A left mouse click */ if(event->button == 1) { /* Fix the stupid contact list double click problem */ gettimeofday(&check_timer, 0); if(!((check_timer.tv_sec == timer.tv_sec) && (check_timer.tv_usec - timer.tv_usec) < 2000)) { timer.tv_sec = check_timer.tv_sec; timer.tv_usec = check_timer.tv_usec; return FALSE; } timer.tv_sec = 0; timer.tv_usec = 0; c = convo_find(user->Uin()); if(c != 0) gdk_window_raise(c->window->window); else { if(user->NewMessages() > 0) c = convo_new(user, TRUE); else c = convo_new(user, FALSE); contact_list_refresh(); system_status_refresh(); } } /* A right click.. make the popup menu */ else if(event->type == GDK_BUTTON_PRESS && event->button == 3) { GtkWidget *_menu; GtkWidget *item; GtkWidget *separator; _menu = gtk_menu_new(); /* The non-sensitive user name as a title */ item = gtk_menu_item_new_with_label(user->GetAlias()); gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item); gtk_widget_set_sensitive(item, FALSE); gtk_widget_show(item); /* A separator */ separator = gtk_hseparator_new(); item = gtk_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item); gtk_container_add(GTK_CONTAINER(item), separator); gtk_widget_set_sensitive(item, FALSE); gtk_widget_show_all(item); add_to_popup("Start Conversation", _menu, GTK_SIGNAL_FUNC(list_start_convo), user); add_to_popup("Send URL", _menu, GTK_SIGNAL_FUNC(list_send_url), user); add_to_popup("Send Chat Request", _menu, GTK_SIGNAL_FUNC(list_request_chat), user); add_to_popup("Send File Request", _menu, GTK_SIGNAL_FUNC(list_request_file), user); if(user->Secure()) add_to_popup("Close Secure Channel", _menu, GTK_SIGNAL_FUNC(create_key_request_window), user); else add_to_popup("Request Secure Channel", _menu, GTK_SIGNAL_FUNC(create_key_request_window), user); /* A separator */ separator = gtk_hseparator_new(); item = gtk_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item); gtk_container_add(GTK_CONTAINER(item), separator); gtk_widget_set_sensitive(item, FALSE); gtk_widget_show_all(item); if(user->Status() != ICQ_STATUS_ONLINE && user->Status() != ICQ_STATUS_OFFLINE) { strcpy(str_status, "Read "); strcat(str_status, user->StatusStrShort()); strcat(str_status, " Message"); add_to_popup(str_status, _menu, GTK_SIGNAL_FUNC(list_read_message), user); } add_to_popup("Info", _menu, GTK_SIGNAL_FUNC(list_info_user), user); add_to_popup("History", _menu, GTK_SIGNAL_FUNC(list_history), user); add_to_popup("More...", _menu, GTK_SIGNAL_FUNC(list_more_window), user); add_to_popup("Delete User", _menu, GTK_SIGNAL_FUNC(list_delete_user), user); gtk_menu_popup(GTK_MENU(_menu), 0, 0, 0, 0, event->button, event->time); } return FALSE; } void add_to_popup(const gchar *label, GtkWidget *menu, GtkSignalFunc func, ICQUser *user) { GtkWidget *item = gtk_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(func), user); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show(item); } --- NEW FILE: convo.cpp --- /* * Licq GTK GUI Plugin * * Copyright (C) 2000, Jon Keating <jo...@li...> * * 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. */ #include "licq_gtk.h" #include "licq_color.h" #include "licq_icqd.h" #include "licq_user.h" #include <string.h> #include <time.h> #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> using namespace std; // for std::list GSList *cnv; struct conversation *convo_new(ICQUser *u, gboolean events) { struct conversation *c; if(!events) { c = convo_find(u->Uin()); if(c != 0) { if(u->Status() == ICQ_STATUS_OFFLINE) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(c->send_server), true); return c; } } c = g_new0(struct conversation, 1); c->user = u; c->clrBack = new GdkColor; c->clrFore = new GdkColor; c->for_user = 0; cnv = g_slist_append(cnv, c); if(events) { convo_show(c); while(c->user->NewMessages() > 0) convo_recv(c->user->Uin()); } else convo_show(c); if(u->Status() == ICQ_STATUS_OFFLINE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->send_server), true); return c; } struct conversation *convo_find(unsigned long uin) { struct conversation *c; GSList *conversations = cnv; while(conversations) { c = (struct conversation *)conversations->data; if(c->user->Uin() == uin) { return c; } conversations = conversations->next; } return 0; } void toggle_close_cancel(struct conversation *c, int which) { if (which == 1) gtk_button_set_label(GTK_BUTTON(c->cancel), GTK_STOCK_CLOSE); else gtk_button_set_label(GTK_BUTTON(c->cancel), GTK_STOCK_CANCEL); } void convo_close_or_cancel(GtkWidget *widget, struct conversation *c) { if (strcmp(gtk_button_get_label(GTK_BUTTON(widget)), GTK_STOCK_CANCEL) == 0) convo_cancel(widget, c); else convo_close(widget, c); } void convo_show(struct conversation *c) { GtkWidget *scroll; GtkWidget *button_box; GtkWidget *options_box; GtkWidget *vertical_box; /* Handle the etag stuff */ c->etag = g_new0(struct e_tag_data, 1); /* Make the convo window */ c->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable(GTK_WINDOW(c->window), TRUE); gtk_widget_realize(c->window); /* Make new buttons with labels */ c->send = gtk_button_new_with_mnemonic("_Send"); c->cancel = gtk_button_new_from_stock(GTK_STOCK_CLOSE); /* Set cancel to grayed out at first */ //gtk_widget_set_sensitive(c->cancel, FALSE); /* Make the boxes */ button_box = gtk_hbox_new(TRUE, 0); vertical_box = gtk_vbox_new(FALSE, 0); options_box = gtk_hbox_new(FALSE, 5); /* The entry box */ c->entry = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(c->entry), TRUE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(c->entry), GTK_WRAP_WORD); g_signal_connect(G_OBJECT(c->entry), "key_press_event", G_CALLBACK(key_press_convo), (gpointer)c); gtk_widget_set_size_request(c->entry, 320, 75); GtkWidget *frame1 = gtk_frame_new(0); gtk_frame_set_shadow_type(GTK_FRAME(frame1), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(frame1), c->entry); gtk_widget_show(frame1); /* The viewing messages box area */ c->text = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(c->text), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(c->text), GTK_WRAP_WORD); /* Scroll bar for the messages that are being viewed */ scroll = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_widget_show(scroll); gtk_container_add(GTK_CONTAINER(scroll), c->text); gtk_widget_show(c->text); gtk_widget_set_size_request(scroll, 320, 150); GtkWidget *frame = gtk_frame_new(0); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_widget_show(frame); gtk_container_add(GTK_CONTAINER(frame), scroll); /* Get the signals connected for the buttons */ g_signal_connect(G_OBJECT(c->cancel), "clicked", G_CALLBACK(convo_close_or_cancel), c); g_signal_connect(G_OBJECT(c->send), "clicked", G_CALLBACK(convo_send), (gpointer)c); gtk_box_pack_start(GTK_BOX(button_box), c->cancel, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(button_box), c->send, TRUE, TRUE, 5); /* Take care of the rest of the widgets */ gtk_box_pack_start(GTK_BOX(vertical_box), frame, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vertical_box), frame1, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vertical_box), button_box, FALSE, FALSE, 5); /* Add the send through server button */ c->send_server = gtk_check_button_new_with_mnemonic("Se_nd through server"); /* Send the message normal */ c->send_normal = gtk_radio_button_new_with_label(0, "Normal"); /* Send the message urgently */ c->send_urgent = gtk_radio_button_new_with_mnemonic_from_widget( GTK_RADIO_BUTTON(c->send_normal), "U_rgent"); /* Send the message to contact list */ c->send_list = gtk_radio_button_new_with_mnemonic_from_widget( GTK_RADIO_BUTTON(c->send_normal), "To Contact _List"); /* Let's pack them now! */ gtk_box_pack_start(GTK_BOX(options_box), c->send_server, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(options_box), c->send_normal, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(options_box), c->send_urgent, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(options_box), c->send_list, FALSE, FALSE, 0); /* Now pack the options_box */ gtk_box_pack_start(GTK_BOX(vertical_box), options_box, FALSE, FALSE, 5); /* If the user is in occupied or dnd mode, set the urgent button */ if(c->user->Status() == ICQ_STATUS_DND || c->user->Status() == ICQ_STATUS_OCCUPIED) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->send_urgent), TRUE); /* Progress of message */ c->progress = gtk_statusbar_new(); g_signal_connect(G_OBJECT(c->progress), "text-pushed", G_CALLBACK(verify_convo_send), c); /* Pack it */ gtk_box_pack_start(GTK_BOX(vertical_box), c->progress, FALSE, FALSE, 5); /* Add the main box into the window */ gtk_container_add(GTK_CONTAINER(c->window), vertical_box); gtk_container_set_border_width(GTK_CONTAINER(c->window), 10); /* Set the title of the window */ gchar *temp = c->user->GetAlias(); const gchar *win_title = g_strdup_printf("Conversation with %s", temp); gtk_window_set_title(GTK_WINDOW(c->window), win_title); /* Set the focus of the window */ gtk_window_set_focus(GTK_WINDOW(c->window), c->entry); /* Don't forget the delete_event signal */ g_signal_connect(G_OBJECT(c->window), "delete_event", G_CALLBACK(convo_delete), c); /* More e_tag_data stuff */ c->etag->statusbar = c->progress; strcpy(c->etag->buf, c->prog_buf); gtk_widget_show_all(c->window); // Stop the flashing if necessary if((c->user->NewMessages() > 0) && flash_events) { // Stop the flashing for this user nToFlash--; list<SFlash *>::iterator it; int x = 0; for(it = FlashList.begin(); it != FlashList.end(); it++) { x++; if((*it)->nUin == c->user->Uin()) { gtk_tree_path_free((*it)->path); g_free(*it); FlashList.erase(it); break; } } } // Clear the flash list else if((c->user->NewMessages() > 0) && !flash_events) { nToFlash = -1; FlashList.clear(); } } gboolean key_press_convo(GtkWidget *entry, GdkEventKey *eventkey, gpointer data) { struct conversation *c = (struct conversation *)data; guint state; state = eventkey->state; if(eventkey->keyval == GDK_Return) { if(!enter_sends && (state & GDK_SHIFT_MASK)) convo_send(0, (gpointer)c); if(enter_sends && !(state & GDK_SHIFT_MASK) && !(state & GDK_CONTROL_MASK)) { convo_send(0, (gpointer)c); return TRUE; } } return FALSE; } void convo_nick_timestamp(GtkWidget *text, const char *nick, time_t message_time, GdkColor *color) { GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); bool addnl = (gtk_text_buffer_get_char_count(tb) > 0); // How about their alias and an optional timestamp? if (show_convo_timestamp) { char szTime[26]; struct tm *_tm = localtime(&message_time); strftime(szTime, 26, timestamp_format, _tm); szTime[25] = '\0'; char *szTempStamp = g_strdup_printf("[%s] ", szTime); GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); if (addnl) { gtk_text_buffer_insert(tb, &iter, "\n", 1); addnl = false; gtk_text_buffer_get_end_iter(tb, &iter); } gtk_text_buffer_insert(tb, &iter, szTempStamp, -1); g_free(szTempStamp); } GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); if (addnl) { gtk_text_buffer_insert(tb, &iter, "\n", 1); gtk_text_buffer_get_end_iter(tb, &iter); } GtkTextTag *color_tag = gtk_text_buffer_create_tag(tb, NULL, "foreground-gdk", color, NULL); gtk_text_buffer_insert_with_tags(tb, &iter, nick, -1, color_tag, NULL); gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert_with_tags(tb, &iter, " : ", 3, color_tag, NULL); } void convo_send(GtkWidget *widget, gpointer _c) { struct conversation *c = (struct conversation *)_c; /* Set the 2 button widgets */ if(GTK_WIDGET_IS_SENSITIVE(c->send)) gtk_widget_set_sensitive(c->send, false); toggle_close_cancel(c, 2); gchar *buf; gboolean urgent = FALSE; GtkTextIter start, end; GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(c->entry)); gtk_text_buffer_get_start_iter(tb, &start); gtk_text_buffer_get_end_iter(tb, &end); buf = gtk_text_buffer_get_text(tb, &start, &end, FALSE); const gchar *message = buf; if (c->for_user != 0) g_free(c->for_user); c->for_user = buf; c->user->SetSendServer(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_server))); /* I don't like those popups to send urgent... so just send it ** ** urgently unless the user says to send it to the contact list*/ if((c->user->Status() == ICQ_STATUS_DND || c->user->Status() == ICQ_STATUS_OCCUPIED) && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_normal))) urgent = TRUE; strcpy(c->prog_buf, "Sending message "); if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_server))) strcat(c->prog_buf, "directly ... "); else strcat(c->prog_buf, "through server ... "); /* Send the message */ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_urgent)) || urgent) { c->etag->e_tag = icq_daemon->icqSendMessage(c->user->Uin(), message, (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_server))), ICQ_TCPxMSG_URGENT); } /* Send to contact list */ else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_list))) { c->etag->e_tag = icq_daemon->icqSendMessage(c->user->Uin(), message, (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_server))), ICQ_TCPxMSG_LIST); } else /* Just send it normally */ { c->etag->e_tag = icq_daemon->icqSendMessage(c->user->Uin(), message, (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->send_server))), ICQ_TCPxMSG_NORMAL); } guint id = gtk_statusbar_get_context_id(GTK_STATUSBAR(c->progress), "prog"); gtk_statusbar_pop(GTK_STATUSBAR(c->progress), id); gtk_statusbar_push(GTK_STATUSBAR(c->progress), id, c->prog_buf); /* Take care of the etd buffer and add it to the slist */ memcpy(c->etag->buf, c->prog_buf, 60); catcher = g_slist_append(catcher, c->etag); } void verify_convo_send(GtkWidget *widget, guint id, gchar *text, struct conversation *c) { gchar temp[60]; strcpy(temp, text); g_strreverse(temp); if(strncmp(temp, " ...", 4) == 0) return; else { gtk_widget_set_sensitive(c->send, TRUE); toggle_close_cancel(c, 1); } } void convo_cancel(GtkWidget *widget, struct conversation *c) { /* Set the buttons sensitivity accordingly */ gtk_widget_set_sensitive(c->send, TRUE); toggle_close_cancel(c, 1); /* Actually cancel this event */ icq_daemon->CancelEvent(c->etag->e_tag); /* Remove the event from the slist */ catcher = g_slist_remove(catcher, c->etag); } void convo_recv(gulong uin) { struct conversation *c; c = convo_find(uin); /* If the window doesn't exist, don't show anything */ if(c == 0) { system_status_refresh(); return; } CUserEvent *u_event = c->user->EventPop(); /* Make sure we really have an event */ if(u_event == 0) { return; } // Use theme colors if it is black on white bool bIgnoreBW = false; // Get the color that it was sent in if it's wanted if (recv_colors) { if (!c->clrBack) { c->clrBack = new GdkColor; } if (!c->clrFore) { c->clrFore = new GdkColor; } CICQColor *pIcqColor = u_event->Color(); if (pIcqColor->Foreground() == 0x00000000 && pIcqColor->Background() == 0x00FFFFFF) { bIgnoreBW = true; } else { c->clrFore->red = pIcqColor->ForeRed() * 257; c->clrFore->green = pIcqColor->ForeGreen() * 257; c->clrFore->blue = pIcqColor->ForeBlue() * 257; c->clrFore->pixel = 255; c->clrBack->red = pIcqColor->BackRed() * 257; c->clrBack->green = pIcqColor->BackGreen() * 257; c->clrBack->blue = pIcqColor->BackBlue() * 257; c->clrBack->pixel = 255; } } else { if (c->clrFore) { delete c->clrFore; c->clrFore = 0; } if (c->clrBack) { delete c->clrBack; c->clrBack = 0; } } // How about their alias and an optional timestamp? GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(c->text)); convo_nick_timestamp(c->text, c->user->GetAlias(), u_event->Time(), red); switch (u_event->SubCommand()) { case ICQ_CMDxSUB_MSG: { GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); if (!bIgnoreBW) { GtkTextTag *tag = gtk_text_buffer_create_tag(tb, NULL, "foreground-gdk", c->clrFore, "background-gdk", c->clrBack, NULL); gtk_text_buffer_insert_with_tags(tb, &iter, u_event->Text(), -1, tag, NULL); } else gtk_text_buffer_insert(tb, &iter, u_event->Text(), -1); gtk_text_buffer_get_end_iter(tb, &iter); GtkTextMark *mark = gtk_text_buffer_create_mark(tb, NULL, &iter, TRUE); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(c->text), mark, 0, FALSE, 0, 0); break; } case ICQ_CMDxSUB_URL: { const gchar *for_user_u = g_strdup_printf("\n%s has sent you a URL!\n%s\n", c->user->GetAlias(), u_event->Text()); GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert(tb, &iter, for_user_u, -1); g_free(const_cast<char *>(for_user_u)); break; } case ICQ_CMDxSUB_CHAT: { const gchar *chat_d = u_event->Text(); if(u_event->IsCancelled()) { GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert(tb, &iter, chat_d, -1); } else { const gchar *for_user_c = g_strdup_printf("\n%s requests to chat with you!\n%s\n", c->user->GetAlias(), chat_d); GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert(tb, &iter, for_user_c, -1); CEventChat *c_event = (CEventChat *)u_event; chat_accept_window(c_event, uin); } break; } case ICQ_CMDxSUB_FILE: { const gchar *file_d = u_event->Text(); if(u_event->IsCancelled()) { GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert(tb, &iter, file_d, -1); } else { const gchar *for_user_f = g_strdup_printf("\n%s requests to send you a file!\n%s\n", c->user->GetAlias(), file_d); GtkTextIter iter; gtk_text_buffer_get_end_iter(tb, &iter); gtk_text_buffer_insert(tb, &iter, for_user_f, -1); file_accept_window(c->user, u_event); } break; } default: // Not good break; } // switch } gboolean convo_delete(GtkWidget *widget, GdkEvent *event, struct conversation *c) { convo_close(0, c); return false; } void convo_close(GtkWidget *widget, struct conversation *c) { if (c->clrBack) delete (c->clrBack); if (c->clrFore) delete (c->clrFore); cnv = g_slist_remove(cnv, c); catcher = g_slist_remove(catcher, c->etag); gtk_widget_destroy(c->window); if (c->for_user != 0) g_free(c->for_user); g_free(c->etag); g_free(c); } --- NEW FILE: eggtrayicon.c --- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* eggtrayicon.c * Copyright (C) 2002 Anders Carlsson <and...@gn...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include <string.h> #include <gdk/gdkx.h> #include "eggtrayicon.h" #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 static GtkPlugClass *parent_class = NULL; static void egg_tray_icon_init (EggTrayIcon *icon); static void egg_tray_icon_class_init (EggTrayIconClass *klass); static void egg_tray_icon_update_manager_window (EggTrayIcon *icon); GType egg_tray_icon_get_type (void) { static GType our_type = 0; if (our_type == 0) { static const GTypeInfo our_info = { sizeof (EggTrayIconClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) egg_tray_icon_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (EggTrayIcon), 0, /* n_preallocs */ (GInstanceInitFunc) egg_tray_icon_init }; our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); } return our_type; } static void egg_tray_icon_init (EggTrayIcon *icon) { icon->stamp = 1; gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); } static void egg_tray_icon_class_init (EggTrayIconClass *klass) { parent_class = g_type_class_peek_parent (klass); } static GdkFilterReturn egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) { EggTrayIcon *icon = user_data; XEvent *xev = (XEvent *)xevent; if (xev->xany.type == ClientMessage && xev->xclient.message_type == icon->manager_atom && xev->xclient.data.l[1] == icon->selection_atom) { egg_tray_icon_update_manager_window (icon); } else if (xev->xany.window == icon->manager_window) { if (xev->xany.type == DestroyNotify) { egg_tray_icon_update_manager_window (icon); } } return GDK_FILTER_CONTINUE; } static void egg_tray_icon_send_manager_message (EggTrayIcon *icon, long message, Window window, long data1, long data2, long data3) { XClientMessageEvent ev; Display *display; ev.type = ClientMessage; ev.window = window; ev.message_type = icon->system_tray_opcode_atom; ev.format = 32; ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); ev.data.l[1] = message; ev.data.l[2] = data1; ev.data.l[3] = data2; ev.data.l[4] = data3; #if HAVE_GTK_MULTIHEAD display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else display = gdk_display; #endif gdk_error_trap_push (); XSendEvent (display, icon->manager_window, False, NoEventMask, (XEvent *)&ev); XSync (display, False); gdk_error_trap_pop (); } static void egg_tray_icon_send_dock_request (EggTrayIcon *icon) { egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_REQUEST_DOCK, icon->manager_window, gtk_plug_get_id (GTK_PLUG (icon)), 0, 0); } static void egg_tray_icon_update_manager_window (EggTrayIcon *icon) { Display *xdisplay; #if HAVE_GTK_MULTIHEAD xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else xdisplay = gdk_display; #endif if (icon->manager_window != None) { GdkWindow *gdkwin; #if HAVE_GTK_MULTIHEAD gdkwin = gdk_window_lookup_for_display (display, icon->manager_window); #else gdkwin = gdk_window_lookup (icon->manager_window); #endif gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); } XGrabServer (xdisplay); icon->manager_window = XGetSelectionOwner (xdisplay, icon->selection_atom); if (icon->manager_window != None) XSelectInput (xdisplay, icon->manager_window, StructureNotifyMask); XUngrabServer (xdisplay); XFlush (xdisplay); if (icon->manager_window != None) { GdkWindow *gdkwin; #if HAVE_GTK_MULTIHEAD gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), icon->manager_window); #else gdkwin = gdk_window_lookup (icon->manager_window); #endif gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); /* Send a request that we'd like to dock */ egg_tray_icon_send_dock_request (icon); } } EggTrayIcon * egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name) { EggTrayIcon *icon; char buffer[256]; GdkWindow *root_window; g_return_val_if_fail (xscreen != NULL, NULL); icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL); gtk_window_set_title (GTK_WINDOW (icon), name); #if HAVE_GTK_MULTIHEAD gtk_plug_construct_for_display (GTK_PLUG (icon), gdk_screen_get_display (screen), 0); #else gtk_plug_construct (GTK_PLUG (icon), 0); #endif gtk_widget_realize (GTK_WIDGET (icon)); /* Now see if there's a manager window around */ g_snprintf (buffer, sizeof (buffer), "_NET_SYSTEM_TRAY_S%d", XScreenNumberOfScreen (xscreen)); icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen), buffer, False); icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen), "MANAGER", False); icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen), "_NET_SYSTEM_TRAY_OPCODE", False); egg_tray_icon_update_manager_window (icon); #if HAVE_GTK_MULTIHEAD root_window = gdk_screen_get_root_window (screen); #else root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); #endif /* Add a root window filter so that we get changes on MANAGER */ gdk_window_add_filter (root_window, egg_tray_icon_manager_filter, icon); return icon; } #if HAVE_GTK_MULTIHEAD EggTrayIcon * egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) { EggTrayIcon *icon; char buffer[256]; g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name); } #endif EggTrayIcon* egg_tray_icon_new (const gchar *name) { return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name); } guint egg_tray_icon_send_message (EggTrayIcon *icon, gint timeout, const gchar *message, gint len) { guint stamp; g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); g_return_val_if_fail (timeout >= 0, 0); g_return_val_if_fail (message != NULL, 0); if (icon->manager_window == None) return 0; if (len < 0) len = strlen (message); stamp = icon->stamp++; /* Get ready to send the message */ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), timeout, len, stamp); /* Now to send the actual message */ gdk_error_trap_push (); while (len > 0) { XClientMessageEvent ev; Display *xdisplay; #if HAVE_GTK_MULTIHEAD xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else xdisplay = gdk_display; #endif ev.type = ClientMessage; ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); ev.format = 8; ev.message_type = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); if (len > 20) { memcpy (&ev.data, message, 20); len -= 20; message += 20; } else { memcpy (&ev.data, message, len); len = 0; } XSendEvent (xdisplay, icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev); XSync (xdisplay, False); } gdk_error_trap_pop (); return stamp; } void egg_tray_icon_cancel_message (EggTrayIcon *icon, guint id) { g_return_if_fail (EGG_IS_TRAY_ICON (icon)); g_return_if_fail (id > 0); egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), id, 0, 0); } --- NEW FILE: eggtrayicon.h --- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* eggtrayicon.h * Copyright (C) 2002 Anders Carlsson <and...@gn...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __EGG_TRAY_ICON_H__ #define __EGG_TRAY_ICON_H__ #include <gtk/gtkplug.h> #include <gdk/gdkx.h> G_BEGIN_DECLS #define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ()) #define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon)) #define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) #define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON)) #define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_C... [truncated message content] |