Logo Search packages:      
Sourcecode: guifications version File versions  Download package

gf_action.c

/*
 * Guifications - The end all, be all, toaster popup plugin
 * Copyright (C) 2003-2004 Gary Kramlich
 *
 * 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 <account.h>
#include <blist.h>
#include <debug.h>
#include <gtkblist.h>
#include <gtkconv.h>
#include <gtkdialogs.h>
#include <gtklog.h>
#include <gtkpounce.h>
#include <gtkutils.h>
#include <plugin.h>
#include <version.h>

#if GAIM_VERSION_CHECK(2,0,0)
# include <gtkstock.h>
#else
# include <stock.h>
#endif

#include "gf_action.h"
#include "gf_compat.h"
#include "gf_display.h"
#include "gf_event.h"
#include "gf_event_info.h"
#include "gf_internal.h"
#include "gf_notification.h"
#include "gf_preferences.h"
#include "gf_utils.h"

struct _GfAction {
      gchar *name;
      gchar *i18n;
      GfActionFunc func;
};

static GList *actions = NULL;

/*******************************************************************************
 * API
 ******************************************************************************/
GfAction *
gf_action_new() {
      GfAction *action;
      
      action = g_new0(GfAction, 1);

      return action;
}

void
gf_action_destroy(GfAction *action) {
      g_return_if_fail(action);

      if(action->name)
            g_free(action->name);

      g_free(action);
      action = NULL;
}

void
gf_action_set_name(GfAction *action, const gchar *name) {
      g_return_if_fail(action);
      g_return_if_fail(name);

      if(action->name)
            g_free(action->name);

      action->name = g_strdup(name);
}

const gchar *
gf_action_get_name(GfAction *action) {
      g_return_val_if_fail(action, NULL);

      return action->name;
}

void
gf_action_set_i18n(GfAction *action, const gchar *i18n) {
      g_return_if_fail(action);
      g_return_if_fail(i18n);

      if(action->i18n)
            g_free(action->i18n);

      action->i18n = g_strdup(i18n);
}

const gchar *
gf_action_get_i18n(GfAction *action) {
      g_return_val_if_fail(action, NULL);

      return action->i18n;
}

void
gf_action_set_func(GfAction *action, GfActionFunc func) {
      g_return_if_fail(action);
      g_return_if_fail(func);

      action->func = func;
}

GfActionFunc
gf_action_get_func(GfAction *action) {
      g_return_val_if_fail(action, NULL);

      return action->func;
}

void
gf_action_execute(GfAction *action, GfDisplay *display, GdkEventButton *event) {
      g_return_if_fail(action);
      g_return_if_fail(display);

      action->func(display, event);
}

GfAction *
gf_action_find_with_name(const gchar *name) {
      GfAction *action;
      GList *l;

      g_return_val_if_fail(name, NULL);

      for(l = actions; l; l = l->next) {
            action = GF_ACTION(l->data);

            if(!g_ascii_strcasecmp(name, action->name))
                  return action;
      }

      return NULL;
}

GfAction *
gf_action_find_with_i18n(const gchar *i18n) {
      GfAction *action;
      GList *l;

      g_return_val_if_fail(i18n, NULL);

      for(l = actions; l; l = l->next) {
            action = GF_ACTION(l->data);

            if(!g_ascii_strcasecmp(i18n, action->i18n))
                  return action;
      }

      return NULL;
}

gint
gf_action_get_position(GfAction *action) {
      g_return_val_if_fail(action, -1);

      return g_list_index(actions, action);
}

/*******************************************************************************
 * Sub System
 ******************************************************************************/
static void
gf_action_add_default(const gchar *name, const gchar *i18n, GfActionFunc func) {
      GfAction *action;

      g_return_if_fail(name);
      g_return_if_fail(func);

      action = gf_action_new();
      gf_action_set_name(action, name);
      gf_action_set_i18n(action, i18n);
      gf_action_set_func(action, func);

      gf_actions_add_action(action);
}

void
gf_actions_init() {
      gf_action_add_default("close", _("Close"), gf_action_execute_close);
      gf_action_add_default("open", _("Open Conversation"),
                                      gf_action_execute_open_conv);
      gf_action_add_default("context", _("Context Menu"),
                                      gf_action_execute_context);
      gf_action_add_default("info", _("Get Info"), gf_action_execute_info);
      gf_action_add_default("log", _("Display Log"), gf_action_execute_log);
}

void
gf_actions_uninit() {
      GList *l, *ll;

      for(l = actions; l; l = ll) {
            ll = l->next;

            gf_actions_remove_action(GF_ACTION(l->data));
      }

      g_list_free(actions);
      actions = NULL;
}

void
gf_actions_add_action(GfAction *action) {
      g_return_if_fail(action);

      actions = g_list_append(actions, action);
}

void
gf_actions_remove_action(GfAction *action) {
      g_return_if_fail(action);

      actions = g_list_remove(actions, action);
}

gint
gf_actions_count() {
      return g_list_length(actions);
}

const gchar *
gf_actions_get_nth_name(gint nth) {
      GfAction *action;

      action = GF_ACTION(g_list_nth_data(actions, nth));

      return action->name;
}

const gchar *
gf_actions_get_nth_i18n(gint nth) {
      GfAction *action;

      action = GF_ACTION(g_list_nth_data(actions, nth));

      return action->i18n;
}

/*******************************************************************************
 * Action Functions
 ******************************************************************************/
void
gf_action_execute_close(GfDisplay *display, GdkEventButton *gdk_event) {
      g_return_if_fail(display);

      gf_display_destroy(display);
}

static gboolean
conversation_exists(GaimConversation *conv) {
      GaimConversation *lconv;
      GList *l;

      for(l = gaim_get_conversations(); l; l = l->next) {
            lconv = (GaimConversation *)l->data;

            if(conv == lconv)
                  return TRUE;
      }

      return FALSE;
}

void
gf_action_execute_open_conv(GfDisplay *display, GdkEventButton *gdk_event) {
      GfEvent *event;
      GfEventInfo *info;
      GaimAccount *account = NULL;
      GaimBuddy *buddy = NULL;
      GaimConversation *conv = NULL;
      GaimConvWindow *win = NULL;
      const GHashTable *components = NULL;
      const gchar *n_type, *target;

      g_return_if_fail(display);

      info = gf_display_get_event_info(display);
      event = gf_event_info_get_event(info);
      n_type = gf_event_get_notification_type(event);

      account = gf_event_info_get_account(info);
      buddy = gf_event_info_get_buddy(info);
      conv = gf_event_info_get_conversation(info);
      components = gf_event_info_get_components(info);
      target = gf_event_info_get_target(info);
      
      if(conv) { /* we have a conv */
            if(conversation_exists(conv)) {
                  win = gaim_conversation_get_window(conv);
            } else { /* the conv we have doesn't exist anymore.. */
                  const gchar *target;

                  target = gf_event_info_get_target(info);
                  conv = gf_find_conversation(GAIM_CONV_ANY, target, account);
                  if(conv)
                        win = gaim_conversation_get_window(conv);
            }
      } else if(components) { /* it's a chat invite */
            const gchar *extra = gf_event_info_get_extra(info);

            conv = gf_find_conversation(GAIM_CONV_CHAT, extra, account);
            if(!conv) {
                  serv_join_chat(account->gc, (GHashTable *)components);
                  gf_display_destroy(display);

                  return;
            }
      } else if (buddy) { /* we have a buddy or a target */
            conv = gf_find_conversation(GAIM_CONV_IM, buddy->name, account);
            if(!conv)
                  conv = gaim_conversation_new(GAIM_CONV_IM, account, buddy->name);

            if(conv)
                  win = gaim_conversation_get_window(conv);
      } else { /* the only thing that _should_ be left is warnings.. */
            if(target) {
                  conv = gf_find_conversation(GAIM_CONV_IM, target, account);

                  if(!conv)
                        conv = gaim_conversation_new(GAIM_CONV_IM, account, target);

                  if(conv)
                        win = gaim_conversation_get_window(conv);
            }
      }

      if(win && conv) {
            gaim_conv_window_raise(win);
            gf_conv_switch(win, conv);

            if(GAIM_IS_GTK_WINDOW(win))
                  gtk_window_present(GTK_WINDOW(GAIM_GTK_WINDOW(win)->window));

            gf_display_destroy(display);
      }
}

void
gf_action_execute_info(GfDisplay *display, GdkEventButton *gdk_event) {
      GfEventInfo *info;
      const gchar *target;
      GaimAccount *account;

      g_return_if_fail(display);

      info = gf_display_get_event_info(display);
      account = gf_event_info_get_account(info);
      target = gf_event_info_get_target(info);

      /* This covers everything.
       *
       * We used to make a distinction between event types, but since we store
       * the target for every event, and how you can't get info about a chat
       * we just use the target.  The target for a buddy event is the
       * buddy->name, in a warning event it's the screen name of the person
       * who warned you, and in a chat it's the person that said something.
       */
      if(target) {
            serv_get_info(account->gc, target);

            gf_display_destroy(display);
      }
}

void
gf_action_execute_log(GfDisplay *display, GdkEventButton *gdk_event) {
      GfEvent *event;
      GfEventInfo *info;
      GaimAccount *account;
      GaimConversation *conv;
      const gchar *n_type, *target;

      g_return_if_fail(display);

      info = gf_display_get_event_info(display);

      account = gf_event_info_get_account(info);
      event = gf_event_info_get_event(info);
      conv = gf_event_info_get_conversation(info);
      target = gf_event_info_get_target(info);

      n_type = gf_event_get_notification_type(event);

      if(conv) {
            GaimConversationType type;

            type = gaim_conversation_get_type(conv);
            if(type == GAIM_CONV_IM || type == GAIM_CONV_CHAT) {
                  gaim_gtk_log_show(type, (type == GAIM_CONV_IM) ? target : conv->name, account); 
                  gf_display_destroy(display);
            }
      } else if(target) {
            gaim_gtk_log_show(GAIM_CONV_IM, target, account);

            gf_display_destroy(display);
      }
}

/******************************************************************************
 * Context menu stuff
 *****************************************************************************/
static gboolean
gf_action_context_destroy_cb(gpointer data) {
      GfDisplay *display = GF_DISPLAY(data);

      gf_display_destroy(display);

      return FALSE;
}

static void
gf_action_context_hide_cb(GtkWidget *w, gpointer data) {
      GfDisplay *display = GF_DISPLAY(data);
      GfEventInfo *info = NULL;
      gint display_time;
      guint timeout_id;

      g_return_if_fail(display);

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      display_time = gaim_prefs_get_int(GF_PREF_BEHAVIOR_DISPLAY_TIME);
      timeout_id = g_timeout_add(display_time * 500,
                                             gf_action_context_destroy_cb, display);

      gf_event_info_set_timeout_id(info, timeout_id);
}

static void
gf_action_context_position(GtkMenu *menu, gint *x, gint *y, gboolean pushin,
                                       gpointer data)
{
/*    GfDisplay *display = GF_DISPLAY(data);*/
}

static void
gf_action_context_info_cb(GtkWidget *menuitem, GfDisplay *display) {
      gf_action_execute_info(display, NULL);
}

static void
gf_action_context_im_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info;
      GaimAccount *account;
      GaimConversation *conv = NULL;
      GaimConvWindow *win = NULL;
      const gchar *target;

      info = gf_display_get_event_info(display);

      account = gf_event_info_get_account(info);
      target = gf_event_info_get_target(info);

      conv = gf_find_conversation(GAIM_CONV_IM, target, account);
      if(!conv) {
            conv = gaim_conversation_new(GAIM_CONV_IM, account, target);
      }

      if(conv) {
            win = gaim_conversation_get_window(conv);
            if(!win) {
                  gf_display_destroy(display);
                  return;
            }
            
            gf_conv_switch(win, conv);

            if(GAIM_IS_GTK_WINDOW(win))
                  gtk_window_present(GTK_WINDOW(GAIM_GTK_WINDOW(win)->window));
      }
      
      gf_display_destroy(display);
}

static void
gf_action_context_pounce_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info;
      GaimAccount *account = NULL;
      GaimBuddy *buddy = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      buddy = gf_event_info_get_buddy(info);
      g_return_if_fail(buddy);

      gaim_gtkpounce_dialog_show(account, buddy->name, NULL);
}

static void
gf_action_context_log_buddy_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      const gchar *target = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      target = gf_event_info_get_target(info);
      g_return_if_fail(target);

      gaim_gtk_log_show(GAIM_LOG_IM, target, account);
}

static void
gf_action_context_log_chat_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimConversation *conv = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      conv = gf_event_info_get_conversation(info);
      g_return_if_fail(conv);

      gaim_gtk_log_show(GAIM_LOG_CHAT, conv->name, account);
}

static void
gf_action_context_alias_buddy_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimBuddy *buddy = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      buddy = gf_event_info_get_buddy(info);
      g_return_if_fail(buddy);

      gaim_gtkdialogs_alias_buddy(buddy);
}

static void
gf_action_context_alias_chat_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimChat *chat = NULL;
      GaimConversation *conv = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      conv = gf_event_info_get_conversation(info);
      g_return_if_fail(conv);

      chat = gaim_blist_find_chat(account, conv->name);
      g_return_if_fail(chat);

      gaim_gtkdialogs_alias_chat(chat);
}

static void
gf_action_context_add_buddy_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      const gchar *target = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      target = gf_event_info_get_target(info);
      g_return_if_fail(target);

      gaim_blist_request_add_buddy(account, target, NULL, NULL);
}

static void
gf_action_context_add_chat_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimConversation *conv = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      conv = gf_event_info_get_conversation(info);
      g_return_if_fail(conv);

      gaim_blist_request_add_chat(account, NULL, NULL, conv->name);
}

static void
gf_action_context_remove_buddy_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimBuddy *buddy = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      buddy = gf_event_info_get_buddy(info);
      g_return_if_fail(buddy);

      gaim_gtkdialogs_remove_buddy(buddy);
}

static void
gf_action_context_remove_chat_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimChat *chat = NULL;
      GaimConversation *conv = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      conv = gf_event_info_get_conversation(info);
      g_return_if_fail(conv);

      chat = gaim_blist_find_chat(account, conv->name);
      g_return_if_fail(chat);

      gaim_gtkdialogs_remove_chat(chat);
}

static void
gf_action_context_join_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      const GHashTable *components = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      components = gf_event_info_get_components(info);
      g_return_if_fail(components);

      serv_join_chat(account->gc, (GHashTable *)components);
}

static void
gf_action_context_autojoin_cb(GtkWidget *menuitem, GfDisplay *display) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimChat *chat = NULL;
      GaimConversation *conv = NULL;

      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      conv = gf_event_info_get_conversation(info);
      g_return_if_fail(conv);

      chat = gaim_blist_find_chat(account, conv->name);
      g_return_if_fail(chat);

      gaim_blist_node_set_bool((GaimBlistNode *)chat, "gtk-autojoin",
                  gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)));
}

/* This function has come from hell.. I summoned it last time I sent a wicked
 * soul to it's external resting place.
 */
void
gf_action_execute_context(GfDisplay *display, GdkEventButton *gdk_event) {
      GfEventInfo *info = NULL;
      GaimAccount *account = NULL;
      GaimBuddy *buddy = NULL;
      GaimChat *chat = NULL;
      GaimConversation *conv = NULL;
      GaimPlugin *prpl = NULL;
      GaimPluginProtocolInfo *prpl_info = NULL;
      GtkWidget *menu;
      const gchar *target = NULL;
      gboolean chat_sep_added = FALSE;
      guint timeout_id;

      g_return_if_fail(display);

      /* grab the stuff we need from the display and event info */
      info = gf_display_get_event_info(display);
      g_return_if_fail(info);

      /* get the gaim stuff we need */
      account = gf_event_info_get_account(info);
      g_return_if_fail(account);

      /* we're going to show the menu as long as the timeout is removed.
       * We need to remove it otherwise the display get's destroyed when
       * the menu is shown, or it'll leak if we don't clean it up later.
       */
      timeout_id = gf_event_info_get_timeout_id(info);
      g_return_if_fail(g_source_remove(timeout_id));

      buddy = gf_event_info_get_buddy(info);
      conv = gf_event_info_get_conversation(info);
      target = gf_event_info_get_target(info);

      if(conv)
            chat = gaim_blist_find_chat(account, conv->name);

      /* find the prpl and it's info */
      prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
      if(prpl)
            prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);

      /* create the menu */
      menu = gtk_menu_new();
      g_signal_connect(G_OBJECT(menu), "hide",
                               G_CALLBACK(gf_action_context_hide_cb), display);
      gtk_widget_show(menu);

      if(buddy || target) {
            /* add get info if the prpl supports it */
            if(prpl_info && prpl_info->get_info) {
                  gaim_new_item_from_stock(menu, _("Get Info"), GAIM_STOCK_INFO,
                                                      G_CALLBACK(gf_action_context_info_cb),
                                                      display, 0, 0, NULL);
            }

            /* we can im anyone.. so..  */
            gaim_new_item_from_stock(menu, _("IM"), GAIM_STOCK_IM,
                                 G_CALLBACK(gf_action_context_im_cb),
                                                 display, 0, 0, NULL);

      }

      /* It's pointless to add a buddy pounce for someone that isn't a buddy...
       * Conversations currently allow this.. but that's because I haven't
       * written a patch yet..
       */
      if(buddy) {
            gaim_new_item_from_stock(menu, _("Add Buddy Pounce"), NULL,
                                                 G_CALLBACK(gf_action_context_pounce_cb),
                                                 display, 0, 0, NULL);
      }

      if(!buddy && target)
            buddy = gaim_find_buddy(account, target);
      
      if(buddy) {
            gaim_new_item_from_stock(menu, _("View IM log"), NULL,
                                                 G_CALLBACK(gf_action_context_log_buddy_cb),
                                                 display, 0, 0, NULL);

            /* add the protocol menu */
            gaim_gtk_append_blist_node_proto_menu(menu, account->gc,
                                                                    (GaimBlistNode *)buddy);

            /* and now the extended menu */
            gaim_gtk_append_blist_node_extended_menu(menu, (GaimBlistNode*)buddy);

            /* separate it! */
            gaim_separator(menu);
      }

      /* we can't alias a non buddy, and we can't remove them either..  But if 
       * they're not a buddy we can add them!
       */
      if(buddy) {
            /* add the alias and remove button */
            gaim_new_item_from_stock(menu, _("Alias Buddy"), GAIM_STOCK_ALIAS,
                                                 G_CALLBACK(gf_action_context_alias_buddy_cb),
                                                 display, 0, 0, NULL);
            gaim_new_item_from_stock(menu, _("Remove Buddy"), GTK_STOCK_REMOVE,
                                                 G_CALLBACK(gf_action_context_remove_buddy_cb),
                                                 display, 0, 0, NULL);
      } else if(target) {
            gaim_new_item_from_stock(menu, _("Add Buddy"), GTK_STOCK_ADD,
                                                 G_CALLBACK(gf_action_context_add_buddy_cb),
                                                 display, 0, 0, NULL);
      }

      /* Add a separtor if we have a buddy or target, and we have a chat */
      if((buddy || target) && chat) {
            gaim_separator(menu);
            chat_sep_added = TRUE;
      }

      if(chat) {
            GaimBlistNode *node = (GaimBlistNode *)chat;
            gboolean checked;

            checked = (gaim_blist_node_get_bool(node, "gtk-autojoin") ||
                          (gaim_blist_node_get_string(node, "gtk-autojoin") != NULL));

            /* add the join item, possibly redundant.. */
            gaim_new_item_from_stock(menu, _("Join"), GAIM_STOCK_CHAT,
                                                 G_CALLBACK(gf_action_context_join_cb),
                                                 display, 0, 0, NULL);

            gaim_new_check_item(menu, _("Auto-join"),
                                          G_CALLBACK(gf_action_context_autojoin_cb),
                                          display, checked);

            
      }

      /* if we have a conversation and it's a chat, we show the view log for it.
       * if we don't do this check we end up with two menu items to view the
       * same log..
       */
      if(conv && conv->type == GAIM_CONV_CHAT) {
            if(!chat_sep_added) {
                  gaim_separator(menu);
                  chat_sep_added = TRUE;
            }

            gaim_new_item_from_stock(menu, _("View Chat Log"), NULL,
                                                 G_CALLBACK(gf_action_context_log_chat_cb),
                                                 display, 0, 0, NULL);
      }

      if(chat) {
            /* add the proto menu for the chat */
            gaim_gtk_append_blist_node_proto_menu(menu, account->gc,
                                                                    (GaimBlistNode *)chat);

            /* add the extended menu for the chat */
            gaim_gtk_append_blist_node_extended_menu(menu, (GaimBlistNode *)chat);

            /* add the alias and remove buttons */
            gaim_new_item_from_stock(menu, _("Alias Chat"), GAIM_STOCK_ALIAS,
                                                 G_CALLBACK(gf_action_context_alias_chat_cb),
                                                 display, 0, 0, NULL);

            gaim_new_item_from_stock(menu, _("Remove Chat"), GTK_STOCK_REMOVE,
                                                 G_CALLBACK(gf_action_context_remove_chat_cb),
                                                 display, 0, 0, NULL);
      }

      /* add the add chat item if it's not on our blist.. */
      if(!chat && conv && conv->type == GAIM_CONV_CHAT) {
            gaim_new_item_from_stock(menu, _("Add Chat"), GTK_STOCK_ADD,
                                                 G_CALLBACK(gf_action_context_add_chat_cb),
                                                 display, 0, 0, NULL);
      }

      /* show it already */
      gtk_widget_show_all(menu);
      gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
                           (GtkMenuPositionFunc)gf_action_context_position, display,
                           gdk_event->button, gdk_event->time);
}

Generated by  Doxygen 1.6.0   Back to index