Mercurial > pidgin.yaz
view src/pounce.c @ 4829:e7e45cee4265
[gaim-migrate @ 5154]
This does 3 things:
1) Removes the "Get Capabilities" option which I re-added a few hours
ago. We decided that it's pointless, since caps are in the tooltips.
It also needlessly complicates things.
2) Adds an "unable to add this buddy because you are over the limit"
message that is currently commented out. We have some sort of a
message like this right now, but it's less good. If you really want
to know why, ask me.
3) Adds a workaround for the bug where some users tooltips do not
show capabilities sometimes. This is really an AIM bug, honest.
Gaim is getting status updates for people that don't contain their
capabilities. I guess it's probably intentional. I imagine it
saves a bit o' bandwidth, since each capability is 16 bytes.
[Insert humorous phrase or catch song lyric here]
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 19 Mar 2003 02:52:42 +0000 |
parents | 677d3cb193a1 |
children | cb700c07ee07 |
line wrap: on
line source
/* * gaim * * Copyright (C) 1998-2003, 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 * */ #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include "gaim.h" #include "prpl.h" #include "pounce.h" GtkWidget *bpmenu = NULL; void rem_bp(GtkWidget *w, struct buddy_pounce *b) { buddy_pounces = g_list_remove(buddy_pounces, b); do_bp_menu(); save_prefs(); } void do_pounce(struct gaim_connection *gc, char *name, int when) { char *who; struct buddy_pounce *b; struct gaim_conversation *c; struct gaim_account *account; GList *bp = buddy_pounces; who = g_strdup(normalize (name)); while (bp) { b = (struct buddy_pounce *)bp->data; bp = bp->next; /* increment the list here because rem_bp can make our handle bad */ if (!(b->options & when)) continue; account = gaim_account_find(b->pouncer, b->protocol); /* find our user */ if (account == NULL) continue; /* check and see if we're signed on as the pouncer */ if (account->gc != gc) continue; if (!gaim_utf8_strcasecmp(who, normalize (b->name))) { /* find someone to pounce */ if (b->options & OPT_POUNCE_POPUP) { c = gaim_find_conversation(name); if (c == NULL) c = gaim_conversation_new(GAIM_CONV_IM, account, name); else gaim_conversation_set_account(c, account); } if (b->options & OPT_POUNCE_NOTIFY) { char tmp[1024]; /* I know the line below is really ugly. I only did it this way * because I thought it'd be funny :-) */ g_snprintf(tmp, sizeof(tmp), (when & OPT_POUNCE_TYPING) ? _("%s has started typing to you") : (when & OPT_POUNCE_SIGNON) ? _("%s has signed on") : (when & OPT_POUNCE_UNIDLE) ? _("%s has returned from being idle") : _("%s has returned from being away"), name); do_error_dialog(tmp, NULL, GAIM_INFO); } if (b->options & OPT_POUNCE_SEND_IM) { if (strlen(b->message) > 0) { c = gaim_find_conversation(name); if (c == NULL) c = gaim_conversation_new(GAIM_CONV_IM, account, name); else gaim_conversation_set_account(c, account); gaim_conversation_write(c, NULL, b->message, -1, WFLAG_SEND, time(NULL)); serv_send_im(account->gc, name, b->message, -1, 0); } } if (b->options & OPT_POUNCE_COMMAND) { #ifndef _WIN32 int pid = fork(); if (pid == 0) { char *args[4]; args[0] = "sh"; args[1] = "-c"; args[2] = b->command; args[3] = NULL; execvp(args[0], args); _exit(0); } #else STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); CreateProcess( NULL, b->command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); #endif /*_WIN32*/ } /* if (b->options & OPT_POUNCE_SOUND) { if (strlen(b->sound)) play_file(b->sound); else play_sound(SND_POUNCE_DEFAULT); }*/ if (!(b->options & OPT_POUNCE_SAVE)) rem_bp(NULL, b); } } g_free(who); } static void new_bp_callback(GtkWidget *w, struct buddy *b) { if (b) show_new_bp(b->name, b->account->gc, b->idle, b->uc & UC_UNAVAILABLE, NULL); else show_new_bp(NULL, NULL, 0, 0, NULL); } static void edit_bp_callback(GtkWidget *w, struct buddy_pounce *b) { show_new_bp(NULL, NULL, 0, 0, b); } static GtkTooltips *bp_tooltip = NULL; void do_bp_menu() { GtkWidget *menuitem, *mess, *messmenu; static GtkWidget *remmenu; GtkWidget *remitem; GtkWidget *sep; GList *l; struct buddy_pounce *b; GList *bp = buddy_pounces; /* Tooltip for editing bp's */ if(!bp_tooltip) bp_tooltip = gtk_tooltips_new(); l = gtk_container_get_children(GTK_CONTAINER(bpmenu)); while (l) { gtk_widget_destroy(GTK_WIDGET(l->data)); l = l->next; } remmenu = gtk_menu_new(); menuitem = gtk_menu_item_new_with_label(_("New Buddy Pounce")); gtk_menu_shell_append(GTK_MENU_SHELL(bpmenu), menuitem); gtk_widget_show(menuitem); g_signal_connect(GTK_OBJECT(menuitem), "activate", G_CALLBACK(new_bp_callback), NULL); while (bp) { b = (struct buddy_pounce *)bp->data; remitem = gtk_menu_item_new_with_label(b->name); gtk_menu_shell_append(GTK_MENU_SHELL(remmenu), remitem); gtk_widget_show(remitem); g_signal_connect(GTK_OBJECT(remitem), "activate", G_CALLBACK(rem_bp), b); bp = bp->next; } menuitem = gtk_menu_item_new_with_label(_("Remove Buddy Pounce")); gtk_menu_shell_append(GTK_MENU_SHELL(bpmenu), menuitem); gtk_widget_show(menuitem); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), remmenu); gtk_widget_show(remmenu); sep = gtk_hseparator_new(); menuitem = gtk_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(bpmenu), menuitem); gtk_container_add(GTK_CONTAINER(menuitem), sep); gtk_widget_set_sensitive(menuitem, FALSE); gtk_widget_show(menuitem); gtk_widget_show(sep); bp = buddy_pounces; while (bp) { b = (struct buddy_pounce *)bp->data; menuitem = gtk_menu_item_new_with_label(b->name); gtk_menu_shell_append(GTK_MENU_SHELL(bpmenu), menuitem); messmenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), messmenu); gtk_widget_show(menuitem); if (strlen(b->message)) mess = gtk_menu_item_new_with_label(b->message); else mess = gtk_menu_item_new_with_label(_("[no message]")); gtk_menu_shell_append(GTK_MENU_SHELL(messmenu), mess); gtk_tooltips_set_tip(bp_tooltip, GTK_WIDGET(mess), _("[Click to edit]"), NULL); gtk_widget_show(mess); g_signal_connect(GTK_OBJECT(mess), "activate", G_CALLBACK(edit_bp_callback), b); bp = bp->next; } } /*------------------------------------------------------------------------*/ /* The dialog for new buddy pounces */ /*------------------------------------------------------------------------*/ void do_new_bp(GtkWidget *w, struct addbp *b) { struct buddy_pounce *bp; if (strlen(gtk_entry_get_text(GTK_ENTRY(b->nameentry))) == 0) { do_error_dialog(_("Please enter a buddy to pounce."), NULL, GAIM_ERROR); return; } if(!b->buddy_pounce) bp = g_new0(struct buddy_pounce, 1); else bp = b->buddy_pounce; g_snprintf(bp->name, 80, "%s", gtk_entry_get_text(GTK_ENTRY(b->nameentry))); g_snprintf(bp->message, 2048, "%s", gtk_entry_get_text(GTK_ENTRY(b->messentry))); g_snprintf(bp->command, 2048, "%s", gtk_entry_get_text(GTK_ENTRY(b->commentry))); g_snprintf(bp->sound, 2048, "%s", gtk_entry_get_text(GTK_ENTRY(b->soundentry))); g_snprintf(bp->pouncer, 80, "%s", b->account->username); bp->protocol = b->account->protocol; bp->options = 0; if (GTK_TOGGLE_BUTTON(b->popupnotify)->active) bp->options |= OPT_POUNCE_NOTIFY; if (GTK_TOGGLE_BUTTON(b->openwindow)->active) bp->options |= OPT_POUNCE_POPUP; if (GTK_TOGGLE_BUTTON(b->sendim)->active) bp->options |= OPT_POUNCE_SEND_IM; if (GTK_TOGGLE_BUTTON(b->command)->active) bp->options |= OPT_POUNCE_COMMAND; if (GTK_TOGGLE_BUTTON(b->sound)->active) bp->options |= OPT_POUNCE_SOUND; if (GTK_TOGGLE_BUTTON(b->p_signon)->active) bp->options |= OPT_POUNCE_SIGNON; if (GTK_TOGGLE_BUTTON(b->p_unaway)->active) bp->options |= OPT_POUNCE_UNAWAY; if (GTK_TOGGLE_BUTTON(b->p_unidle)->active) bp->options |= OPT_POUNCE_UNIDLE; if (GTK_TOGGLE_BUTTON(b->p_typing)->active) bp->options |= OPT_POUNCE_TYPING; if (GTK_TOGGLE_BUTTON(b->save)->active) bp->options |= OPT_POUNCE_SAVE; if(!b->buddy_pounce) buddy_pounces = g_list_append(buddy_pounces, bp); do_bp_menu(); gtk_widget_destroy(b->window); save_prefs(); g_free(b); } static void pounce_choose(GtkWidget *opt, struct addbp *b) { struct gaim_account *account = g_object_get_data(G_OBJECT(opt), "gaim_account"); b->account = account; } static GtkWidget *pounce_user_menu(struct addbp *b, struct gaim_connection *gc) { GtkWidget *optmenu; GtkWidget *menu; GtkWidget *opt; GSList *u = gaim_accounts; struct gaim_account *account; struct prpl *p; int count = 0; int place = 0; char buf[2048]; optmenu = gtk_option_menu_new(); menu = gtk_menu_new(); while (u) { account = (struct gaim_account *)u->data; p = (struct prpl *)find_prpl(account->protocol); g_snprintf(buf, sizeof buf, "%s (%s)", account->username, (p && p->name)?p->name:_("Unknown")); opt = gtk_menu_item_new_with_label(buf); g_object_set_data(G_OBJECT(opt), "gaim_account", account); g_signal_connect(GTK_OBJECT(opt), "activate", G_CALLBACK(pounce_choose), b); gtk_menu_shell_append(GTK_MENU_SHELL(menu), opt); gtk_widget_show(opt); if (b->account == account) { gtk_menu_item_activate(GTK_MENU_ITEM(opt)); place = count; } count++; u = u->next; } gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), place); b->menu = optmenu; return optmenu; } void show_new_bp(char *name, struct gaim_connection *gc, int idle, int away, struct buddy_pounce *edit_bp) { GtkWidget *label; GtkWidget *bbox; GtkWidget *vbox; GtkWidget *button; GtkWidget *frame; GtkWidget *table; GtkWidget *optmenu; GtkWidget *sep; GtkSizeGroup *sg; struct addbp *b = g_new0(struct addbp, 1); if(edit_bp) { b->buddy_pounce = edit_bp; b->account = gaim_account_find(edit_bp->pouncer, edit_bp->protocol); } else { b->account = gc ? gc->account : gaim_accounts->data; b->buddy_pounce = NULL; } GAIM_DIALOG(b->window); gtk_window_set_resizable(GTK_WINDOW(b->window), TRUE); gtk_window_set_role(GTK_WINDOW(b->window), "new_bp"); gtk_window_set_title(GTK_WINDOW(b->window), _("New Buddy Pounce")); g_signal_connect(GTK_OBJECT(b->window), "destroy", G_CALLBACK(gtk_widget_destroy), b->window); gtk_widget_realize(b->window); vbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(b->window), vbox); gtk_widget_show(vbox); /* <pounce type="who"> */ frame = gtk_frame_new(_("Pounce Who")); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(frame)); table = gtk_table_new(2, 2, FALSE); gtk_container_add(GTK_CONTAINER(frame), table); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_widget_show(table); label = gtk_label_new(_("Account")); 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); gtk_widget_show(label); optmenu = pounce_user_menu(b, gc); gtk_table_attach(GTK_TABLE(table), optmenu, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_widget_show(optmenu); label = gtk_label_new(_("Buddy")); 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); gtk_widget_show(label); b->nameentry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), b->nameentry, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0); if (name !=NULL) gtk_entry_set_text(GTK_ENTRY(b->nameentry), name); else if(edit_bp) gtk_entry_set_text(GTK_ENTRY(b->nameentry), edit_bp->name); gtk_window_set_focus(GTK_WINDOW(b->window), b->nameentry); gtk_widget_show(b->nameentry); /* </pounce type="who"> */ /* <pounce type="when"> */ frame = gtk_frame_new(_("Pounce When")); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(frame)); table = gtk_table_new(2, 2, FALSE); gtk_container_add(GTK_CONTAINER(frame), table); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_widget_show(table); b->p_signon = gtk_check_button_new_with_label(_("Pounce on sign on")); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_signon), (edit_bp->options & OPT_POUNCE_SIGNON) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_signon), TRUE); gtk_table_attach(GTK_TABLE(table), b->p_signon, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); gtk_widget_show(b->p_signon); b->p_unaway = gtk_check_button_new_with_label(_("Pounce on return from away")); if (away) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_unaway), TRUE); else if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_unaway), (edit_bp->options & OPT_POUNCE_UNAWAY) ? TRUE : FALSE); gtk_table_attach(GTK_TABLE(table), b->p_unaway, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_widget_show(b->p_unaway); b->p_unidle = gtk_check_button_new_with_label(_("Pounce on return from idle")); if (idle) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_unidle), TRUE); else if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_unidle), (edit_bp->options & OPT_POUNCE_UNIDLE) ? TRUE : FALSE); gtk_table_attach(GTK_TABLE(table), b->p_unidle, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); gtk_widget_show(b->p_unidle); b->p_typing = gtk_check_button_new_with_label(_("Pounce when buddy is typing to you")); if (edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->p_typing), (edit_bp->options & OPT_POUNCE_TYPING) ? TRUE : FALSE); gtk_table_attach(GTK_TABLE(table), b->p_typing,1,2,1,2, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_widget_show(b->p_typing); /* </pounce type="when"> */ /* <pounce type="action"> */ frame = gtk_frame_new(_("Pounce Action")); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(frame)); table = gtk_table_new(4, 2, FALSE); gtk_container_add(GTK_CONTAINER(frame), table); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_widget_show(table); b->openwindow = gtk_check_button_new_with_label(_("Open IM Window")); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->openwindow), (edit_bp->options & OPT_POUNCE_POPUP) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->openwindow), FALSE); gtk_table_attach(GTK_TABLE(table), b->openwindow, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); gtk_widget_show(b->openwindow); b->popupnotify = gtk_check_button_new_with_label(_("Popup Notification")); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->popupnotify), (edit_bp->options & OPT_POUNCE_NOTIFY) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->popupnotify), FALSE); gtk_table_attach(GTK_TABLE(table), b->popupnotify, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); gtk_widget_show(b->popupnotify); b->sendim = gtk_check_button_new_with_label(_("Send Message")); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->sendim), (edit_bp->options & OPT_POUNCE_SEND_IM) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->sendim), TRUE); gtk_table_attach(GTK_TABLE(table), b->sendim, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); gtk_widget_show(b->sendim); b->messentry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), b->messentry, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0); g_signal_connect(GTK_OBJECT(b->messentry), "activate", G_CALLBACK(do_new_bp), b); if(edit_bp) { gtk_widget_set_sensitive(GTK_WIDGET(b->messentry), (edit_bp->options & OPT_POUNCE_SEND_IM) ? TRUE : FALSE); gtk_entry_set_text(GTK_ENTRY(b->messentry), edit_bp->message); } gtk_widget_show(b->messentry); g_signal_connect(GTK_OBJECT(b->sendim), "clicked", G_CALLBACK(gaim_gtk_toggle_sensitive), b->messentry); b->command = gtk_check_button_new_with_label(_("Execute command on pounce")); gtk_table_attach(GTK_TABLE(table), b->command, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->command), (edit_bp->options & OPT_POUNCE_COMMAND) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->command), FALSE); gtk_widget_show(b->command); b->commentry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), b->commentry, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0); g_signal_connect(GTK_OBJECT(b->commentry), "activate", G_CALLBACK(do_new_bp), b); if(edit_bp) { gtk_widget_set_sensitive(GTK_WIDGET(b->commentry), (edit_bp->options & OPT_POUNCE_COMMAND) ? TRUE : FALSE); gtk_entry_set_text(GTK_ENTRY(b->commentry), edit_bp->command); } else gtk_widget_set_sensitive(GTK_WIDGET(b->commentry), FALSE); gtk_widget_show(b->commentry); g_signal_connect(GTK_OBJECT(b->command), "clicked", G_CALLBACK(gaim_gtk_toggle_sensitive), b->commentry); b->sound = gtk_check_button_new_with_label(_("Play sound on pounce")); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->sound), (edit_bp->options & OPT_POUNCE_SOUND) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->sound), FALSE); gtk_table_attach(GTK_TABLE(table), b->sound, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); gtk_widget_show(b->sound); b->soundentry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), b->soundentry, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 0, 0); g_signal_connect(GTK_OBJECT(b->soundentry), "activate", G_CALLBACK(do_new_bp), b); if(edit_bp) { gtk_widget_set_sensitive(GTK_WIDGET(b->soundentry), (edit_bp->options & OPT_POUNCE_SOUND) ? TRUE : FALSE); gtk_entry_set_text(GTK_ENTRY(b->soundentry), edit_bp->sound); } else gtk_widget_set_sensitive(GTK_WIDGET(b->soundentry), FALSE); gtk_widget_show(b->soundentry); g_signal_connect(GTK_OBJECT(b->sound), "clicked", G_CALLBACK(gaim_gtk_toggle_sensitive), b->soundentry); /* </pounce type="action"> */ b->save = gtk_check_button_new_with_label(_("Save this pounce after activation")); gtk_container_set_border_width(GTK_CONTAINER(b->save), 7); if(edit_bp) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->save), (edit_bp->options & OPT_POUNCE_SAVE) ? TRUE : FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->save), FALSE); gtk_box_pack_start(GTK_BOX(vbox), b->save, FALSE, FALSE, 0); gtk_widget_show(b->save); sep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); gtk_widget_show(sep); bbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); gtk_widget_show(bbox); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); button = gaim_pixbuf_button_from_stock(_("_Save"), "gtk-execute", GAIM_BUTTON_HORIZONTAL); gtk_size_group_add_widget(sg, button); g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(do_new_bp), b); gtk_box_pack_end(GTK_BOX(bbox), button, FALSE, FALSE, 0); gtk_widget_show(button); button = gaim_pixbuf_button_from_stock(_("C_ancel"), "gtk-cancel", GAIM_BUTTON_HORIZONTAL); gtk_size_group_add_widget(sg, button); g_signal_connect_swapped(GTK_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), b->window); gtk_box_pack_end(GTK_BOX(bbox), button, FALSE, FALSE, 0); gtk_widget_show(button); gtk_widget_show(b->window); }