mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-12 16:50:19 +00:00
Added the new network-list SVG icon in both light and dark variants under data/icons/menu, so it comes from the same icon set as the rest of the menu icons.
Registered both new icon files in the compiled GResource manifest so they are available through the existing resource-loading path.
2973 lines
74 KiB
C
2973 lines
74 KiB
C
/* X-Chat
|
|
* Copyright (C) 1998-2007 Peter Zelezny.
|
|
*
|
|
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "fe-gtk.h"
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#include "../common/zoitechat.h"
|
|
#include "../common/zoitechatc.h"
|
|
#include "../common/cfgfiles.h"
|
|
#include "../common/outbound.h"
|
|
#include "../common/ignore.h"
|
|
#include "../common/fe.h"
|
|
#include "../common/server.h"
|
|
#include "../common/servlist.h"
|
|
#include "../common/notify.h"
|
|
#include "../common/util.h"
|
|
#include "../common/text.h"
|
|
#include "xtext.h"
|
|
#include "ascii.h"
|
|
#include "banlist.h"
|
|
#include "chanlist.h"
|
|
#include "editlist.h"
|
|
#include "fkeys.h"
|
|
#include "gtkutil.h"
|
|
#include "maingui.h"
|
|
#include "notifygui.h"
|
|
#include "pixmaps.h"
|
|
#include "rawlog.h"
|
|
#include "palette.h"
|
|
#include "plugingui.h"
|
|
#include "search.h"
|
|
#include "textgui.h"
|
|
#include "urlgrab.h"
|
|
#include "userlistgui.h"
|
|
#include "menu.h"
|
|
#include "servlistgui.h"
|
|
|
|
static GSList *submenu_list;
|
|
|
|
static GtkWidget *
|
|
menu_new (void)
|
|
{
|
|
GtkWidget *menu = gtk_menu_new ();
|
|
|
|
#if HAVE_GTK3
|
|
gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
|
|
#endif
|
|
|
|
return menu;
|
|
}
|
|
|
|
enum
|
|
{
|
|
M_MENUITEM,
|
|
M_NEWMENU,
|
|
M_END,
|
|
M_SEP,
|
|
M_MENUTOG,
|
|
M_MENURADIO,
|
|
M_MENUSTOCK,
|
|
M_MENUPIX,
|
|
M_MENUSUB
|
|
};
|
|
|
|
struct mymenu
|
|
{
|
|
char *text;
|
|
void *callback;
|
|
char *image;
|
|
unsigned char type; /* M_XXX */
|
|
unsigned char id; /* MENU_ID_XXX (menu.h) */
|
|
unsigned char state; /* ticked or not? */
|
|
unsigned char sensitive; /* shaded out? */
|
|
guint key; /* GDK_KEY_x */
|
|
};
|
|
|
|
#define XCMENU_DOLIST 1
|
|
#define XCMENU_SHADED 1
|
|
#define XCMENU_MARKUP 2
|
|
#define XCMENU_MNEMONIC 4
|
|
|
|
/* execute a userlistbutton/popupmenu command */
|
|
|
|
static void
|
|
nick_command (session * sess, char *cmd)
|
|
{
|
|
if (*cmd == '!')
|
|
zoitechat_exec (cmd + 1);
|
|
else
|
|
handle_command (sess, cmd, TRUE);
|
|
}
|
|
|
|
/* fill in the %a %s %n etc and execute the command */
|
|
|
|
void
|
|
nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
|
|
{
|
|
char *buf;
|
|
char *host = _("Host unknown");
|
|
char *account = _("Account unknown");
|
|
struct User *user;
|
|
int len;
|
|
|
|
/* if (sess->type == SESS_DIALOG)
|
|
{
|
|
buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
|
|
buf = strrchr (buf, '@');
|
|
if (buf)
|
|
host = buf + 1;
|
|
} else*/
|
|
{
|
|
user = userlist_find (sess, nick);
|
|
if (user)
|
|
{
|
|
if (user->hostname)
|
|
host = strchr (user->hostname, '@') + 1;
|
|
if (user->account)
|
|
account = user->account;
|
|
}
|
|
}
|
|
|
|
/* this can't overflow, since popup->cmd is only 256 */
|
|
len = strlen (cmd) + strlen (nick) + strlen (allnick) + 512;
|
|
buf = g_malloc (len);
|
|
|
|
auto_insert (buf, len, cmd, 0, 0, allnick, sess->channel, "",
|
|
server_get_network (sess->server, TRUE), host,
|
|
sess->server->nick, nick, account);
|
|
|
|
nick_command (sess, buf);
|
|
|
|
g_free (buf);
|
|
}
|
|
|
|
/* userlist button has been clicked */
|
|
|
|
void
|
|
userlist_button_cb (GtkWidget * button, char *cmd)
|
|
{
|
|
int i, num_sel, using_allnicks = FALSE;
|
|
char **nicks, *allnicks;
|
|
char *nick = NULL;
|
|
session *sess;
|
|
|
|
sess = current_sess;
|
|
|
|
if (strstr (cmd, "%a"))
|
|
using_allnicks = TRUE;
|
|
|
|
if (sess->type == SESS_DIALOG)
|
|
{
|
|
/* fake a selection */
|
|
nicks = g_new (char *, 2);
|
|
nicks[0] = g_strdup (sess->channel);
|
|
nicks[1] = NULL;
|
|
num_sel = 1;
|
|
}
|
|
else
|
|
{
|
|
/* find number of selected rows */
|
|
nicks = userlist_selection_list (sess->gui->user_tree, &num_sel);
|
|
if (num_sel < 1)
|
|
{
|
|
nick_command_parse (sess, cmd, "", "");
|
|
|
|
g_free (nicks);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* create "allnicks" string */
|
|
allnicks = g_malloc (((NICKLEN + 1) * num_sel) + 1);
|
|
*allnicks = 0;
|
|
|
|
i = 0;
|
|
while (nicks[i])
|
|
{
|
|
if (i > 0)
|
|
strcat (allnicks, " ");
|
|
strcat (allnicks, nicks[i]);
|
|
|
|
if (!nick)
|
|
nick = nicks[0];
|
|
|
|
/* if not using "%a", execute the command once for each nickname */
|
|
if (!using_allnicks)
|
|
nick_command_parse (sess, cmd, nicks[i], "");
|
|
|
|
i++;
|
|
}
|
|
|
|
if (using_allnicks)
|
|
{
|
|
if (!nick)
|
|
nick = "";
|
|
nick_command_parse (sess, cmd, nick, allnicks);
|
|
}
|
|
|
|
while (num_sel)
|
|
{
|
|
num_sel--;
|
|
g_free (nicks[num_sel]);
|
|
}
|
|
|
|
g_free (nicks);
|
|
g_free (allnicks);
|
|
}
|
|
|
|
/* a popup-menu-item has been selected */
|
|
|
|
static void
|
|
popup_menu_cb (GtkWidget * item, char *cmd)
|
|
{
|
|
char *nick;
|
|
|
|
/* the userdata is set in menu_quick_item() */
|
|
nick = g_object_get_data (G_OBJECT (item), "u");
|
|
|
|
if (!nick) /* userlist popup menu */
|
|
{
|
|
/* treat it just like a userlist button */
|
|
userlist_button_cb (NULL, cmd);
|
|
return;
|
|
}
|
|
|
|
if (!current_sess) /* for url grabber window */
|
|
nick_command_parse (sess_list->data, cmd, nick, nick);
|
|
else
|
|
nick_command_parse (current_sess, cmd, nick, nick);
|
|
}
|
|
|
|
GtkWidget *
|
|
menu_toggle_item (char *label, GtkWidget *menu, void *callback, void *userdata,
|
|
int state)
|
|
{
|
|
GtkWidget *item;
|
|
|
|
item = gtk_check_menu_item_new_with_mnemonic (label);
|
|
gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (callback), userdata);
|
|
gtk_widget_show (item);
|
|
|
|
return item;
|
|
}
|
|
|
|
#if HAVE_GTK3
|
|
static const char *menu_icon_theme_variant (void);
|
|
static GtkWidget *menu_icon_image_from_data_icons (const char *icon_name, const char *theme_variant);
|
|
#endif
|
|
|
|
GtkWidget *
|
|
menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
|
|
gpointer userdata, char *icon)
|
|
{
|
|
GtkWidget *img, *item;
|
|
char *path;
|
|
#if HAVE_GTK3
|
|
const char *icon_name = NULL;
|
|
const char *custom_icon = NULL;
|
|
GtkWidget *box;
|
|
GtkWidget *image = NULL;
|
|
GtkWidget *label_widget;
|
|
#endif
|
|
|
|
if (!label)
|
|
item = gtk_menu_item_new ();
|
|
else
|
|
{
|
|
if (icon)
|
|
{
|
|
/*if (flags & XCMENU_MARKUP)
|
|
item = gtk_image_menu_item_new_with_markup (label);
|
|
else*/
|
|
img = NULL;
|
|
if (access (icon, R_OK) == 0) /* try fullpath */
|
|
img = gtk_image_new_from_file (icon);
|
|
else
|
|
{
|
|
/* try relative to <xdir> */
|
|
path = g_build_filename (get_xdir (), icon, NULL);
|
|
if (access (path, R_OK) == 0)
|
|
img = gtk_image_new_from_file (path);
|
|
else
|
|
{
|
|
#if HAVE_GTK3
|
|
icon_name = gtkutil_icon_name_from_stock (icon);
|
|
if (!icon_name)
|
|
icon_name = icon;
|
|
if (g_str_has_prefix (icon_name, "zc-menu-"))
|
|
custom_icon = icon_name + strlen ("zc-menu-");
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
img = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
|
|
#endif
|
|
}
|
|
g_free (path);
|
|
}
|
|
|
|
#if HAVE_GTK3
|
|
item = gtk_menu_item_new ();
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
|
if (custom_icon)
|
|
image = menu_icon_image_from_data_icons (custom_icon, menu_icon_theme_variant ());
|
|
if (!image && icon_name)
|
|
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
|
|
else if (img)
|
|
image = img;
|
|
label_widget = gtk_label_new_with_mnemonic (label);
|
|
if (image)
|
|
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), label_widget, FALSE, FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (item), box);
|
|
#else
|
|
item = gtk_image_menu_item_new_with_mnemonic (label);
|
|
if (img)
|
|
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (flags & XCMENU_MARKUP)
|
|
{
|
|
item = gtk_menu_item_new_with_label ("");
|
|
if (flags & XCMENU_MNEMONIC)
|
|
{
|
|
#if HAVE_GTK3
|
|
gtk_label_set_markup_with_mnemonic (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))), label);
|
|
#else
|
|
gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item)->child), label);
|
|
#endif
|
|
} else
|
|
{
|
|
#if HAVE_GTK3
|
|
gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))), label);
|
|
#else
|
|
gtk_label_set_markup (GTK_LABEL (GTK_BIN (item)->child), label);
|
|
#endif
|
|
}
|
|
} else
|
|
{
|
|
if (flags & XCMENU_MNEMONIC)
|
|
item = gtk_menu_item_new_with_mnemonic (label);
|
|
else
|
|
item = gtk_menu_item_new_with_label (label);
|
|
}
|
|
}
|
|
}
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
g_object_set_data (G_OBJECT (item), "u", userdata);
|
|
if (cmd)
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (popup_menu_cb), cmd);
|
|
if (flags & XCMENU_SHADED)
|
|
gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
|
|
gtk_widget_show_all (item);
|
|
|
|
return item;
|
|
}
|
|
|
|
static void
|
|
menu_quick_item_with_callback (void *callback, char *label, GtkWidget * menu,
|
|
void *arg)
|
|
{
|
|
GtkWidget *item;
|
|
|
|
item = gtk_menu_item_new_with_label (label);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (callback), arg);
|
|
gtk_widget_show (item);
|
|
}
|
|
|
|
GtkWidget *
|
|
menu_quick_sub (char *name, GtkWidget *menu, GtkWidget **sub_item_ret, int flags, int pos)
|
|
{
|
|
GtkWidget *sub_menu;
|
|
GtkWidget *sub_item;
|
|
|
|
if (!name)
|
|
return menu;
|
|
|
|
/* Code to add a submenu */
|
|
sub_menu = menu_new ();
|
|
if (flags & XCMENU_MARKUP)
|
|
{
|
|
sub_item = gtk_menu_item_new_with_label ("");
|
|
#if HAVE_GTK3
|
|
gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (sub_item))), name);
|
|
#else
|
|
gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item)->child), name);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (flags & XCMENU_MNEMONIC)
|
|
sub_item = gtk_menu_item_new_with_mnemonic (name);
|
|
else
|
|
sub_item = gtk_menu_item_new_with_label (name);
|
|
}
|
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), sub_item, pos);
|
|
gtk_widget_show (sub_item);
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item), sub_menu);
|
|
|
|
if (sub_item_ret)
|
|
*sub_item_ret = sub_item;
|
|
|
|
if (flags & XCMENU_DOLIST)
|
|
/* We create a new element in the list */
|
|
submenu_list = g_slist_prepend (submenu_list, sub_menu);
|
|
return sub_menu;
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_quick_endsub (void)
|
|
{
|
|
/* Just delete the first element in the linked list pointed to by first */
|
|
if (submenu_list)
|
|
submenu_list = g_slist_remove (submenu_list, submenu_list->data);
|
|
|
|
if (submenu_list)
|
|
return (submenu_list->data);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
toggle_cb (GtkWidget *item, char *pref_name)
|
|
{
|
|
char buf[256];
|
|
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
g_snprintf (buf, sizeof (buf), "set %s 1", pref_name);
|
|
else
|
|
g_snprintf (buf, sizeof (buf), "set %s 0", pref_name);
|
|
|
|
handle_command (current_sess, buf, FALSE);
|
|
}
|
|
|
|
static int
|
|
is_in_path (char *cmd)
|
|
{
|
|
char *orig = g_strdup (cmd + 1); /* 1st char is "!" */
|
|
char *prog = orig;
|
|
char **argv;
|
|
int argc;
|
|
|
|
/* special-case these default entries. */
|
|
/* 123456789012345678 */
|
|
if (strncmp (prog, "gnome-terminal -x ", 18) == 0)
|
|
/* don't check for gnome-terminal, but the thing it's executing! */
|
|
prog += 18;
|
|
|
|
if (g_shell_parse_argv (prog, &argc, &argv, NULL))
|
|
{
|
|
char *path = g_find_program_in_path (argv[0]);
|
|
g_strfreev (argv);
|
|
if (path)
|
|
{
|
|
g_free (path);
|
|
g_free (orig);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
g_free (orig);
|
|
return 0;
|
|
}
|
|
|
|
/* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
|
|
|
|
static void
|
|
menu_extract_icon (char *name, char **label, char **icon)
|
|
{
|
|
char *p = name;
|
|
char *start = NULL;
|
|
char *end = NULL;
|
|
|
|
while (*p)
|
|
{
|
|
if (*p == '~')
|
|
{
|
|
/* escape \~ */
|
|
if (p == name || p[-1] != '\\')
|
|
{
|
|
if (!start)
|
|
start = p + 1;
|
|
else if (!end)
|
|
end = p + 1;
|
|
}
|
|
}
|
|
p++;
|
|
}
|
|
|
|
if (!end)
|
|
end = p;
|
|
|
|
if (start && start != end)
|
|
{
|
|
*label = g_strndup (name, (start - name) - 1);
|
|
*icon = g_strndup (start, (end - start) - 1);
|
|
}
|
|
else
|
|
{
|
|
*label = g_strdup (name);
|
|
*icon = NULL;
|
|
}
|
|
}
|
|
|
|
/* append items to "menu" using the (struct popup*) list provided */
|
|
|
|
void
|
|
menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
|
|
{
|
|
struct popup *pop;
|
|
GtkWidget *tempmenu = menu, *subitem = NULL;
|
|
int childcount = 0;
|
|
|
|
submenu_list = g_slist_prepend (0, menu);
|
|
while (list)
|
|
{
|
|
pop = (struct popup *) list->data;
|
|
|
|
if (!g_ascii_strncasecmp (pop->name, "SUB", 3))
|
|
{
|
|
childcount = 0;
|
|
tempmenu = menu_quick_sub (pop->cmd, tempmenu, &subitem, XCMENU_DOLIST|XCMENU_MNEMONIC, -1);
|
|
|
|
} else if (!g_ascii_strncasecmp (pop->name, "TOGGLE", 6))
|
|
{
|
|
childcount++;
|
|
menu_toggle_item (pop->name + 7, tempmenu, toggle_cb, pop->cmd,
|
|
cfg_get_bool (pop->cmd));
|
|
|
|
} else if (!g_ascii_strncasecmp (pop->name, "ENDSUB", 6))
|
|
{
|
|
/* empty sub menu due to no programs in PATH? */
|
|
if (check_path && childcount < 1)
|
|
gtk_widget_destroy (subitem);
|
|
subitem = NULL;
|
|
|
|
if (tempmenu != menu)
|
|
tempmenu = menu_quick_endsub ();
|
|
/* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
|
|
|
|
} else if (!g_ascii_strncasecmp (pop->name, "SEP", 3))
|
|
{
|
|
menu_quick_item (0, 0, tempmenu, XCMENU_SHADED, 0, 0);
|
|
|
|
} else
|
|
{
|
|
char *icon, *label;
|
|
|
|
/* default command in zoitechat.c */
|
|
if (pop->cmd[0] == 'n' && !strcmp (pop->cmd, "notify -n ASK %s"))
|
|
{
|
|
/* don't create this item if already in notify list */
|
|
if (!target || notify_is_in_list (current_sess->server, target))
|
|
{
|
|
list = list->next;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
menu_extract_icon (pop->name, &label, &icon);
|
|
|
|
if (!check_path || pop->cmd[0] != '!')
|
|
{
|
|
menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
|
|
/* check if the program is in path, if not, leave it out! */
|
|
} else if (is_in_path (pop->cmd))
|
|
{
|
|
childcount++;
|
|
menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
|
|
}
|
|
|
|
g_free (label);
|
|
g_free (icon);
|
|
}
|
|
|
|
list = list->next;
|
|
}
|
|
|
|
/* Let's clean up the linked list from mem */
|
|
while (submenu_list)
|
|
submenu_list = g_slist_remove (submenu_list, submenu_list->data);
|
|
}
|
|
|
|
static char *str_copy = NULL; /* for all pop-up menus */
|
|
static GtkWidget *nick_submenu = NULL; /* user info submenu */
|
|
|
|
static void
|
|
menu_destroy (GtkWidget *menu, gpointer objtounref)
|
|
{
|
|
gtk_widget_destroy (menu);
|
|
g_object_unref (menu);
|
|
if (objtounref)
|
|
g_object_unref (G_OBJECT (objtounref));
|
|
nick_submenu = NULL;
|
|
}
|
|
|
|
static void
|
|
menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
|
|
{
|
|
if (event && event->window)
|
|
gtk_menu_set_screen (GTK_MENU (menu), gdk_window_get_screen (event->window));
|
|
|
|
g_object_ref (menu);
|
|
g_object_ref_sink (menu);
|
|
g_object_unref (menu);
|
|
g_signal_connect (G_OBJECT (menu), "selection-done",
|
|
G_CALLBACK (menu_destroy), objtounref);
|
|
#if HAVE_GTK3
|
|
if (event)
|
|
{
|
|
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
|
|
}
|
|
else if (parent_window)
|
|
{
|
|
gtk_menu_popup_at_widget (GTK_MENU (menu), GTK_WIDGET (parent_window),
|
|
GDK_GRAVITY_SOUTH_WEST,
|
|
GDK_GRAVITY_NORTH_WEST,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
|
|
}
|
|
#else
|
|
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
|
|
0, event ? event->time : 0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
menu_nickinfo_cb (GtkWidget *menu, session *sess)
|
|
{
|
|
char buf[512];
|
|
|
|
if (!is_session (sess))
|
|
return;
|
|
|
|
/* issue a /WHOIS */
|
|
g_snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
|
|
handle_command (sess, buf, FALSE);
|
|
/* and hide the output */
|
|
sess->server->skip_next_whois = 1;
|
|
}
|
|
|
|
static void
|
|
copy_to_clipboard_cb (GtkWidget *item, char *url)
|
|
{
|
|
gtkutil_copy_to_clipboard (item, NULL, url);
|
|
}
|
|
|
|
/* returns boolean: Some data is missing */
|
|
|
|
static gboolean
|
|
menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
|
|
{
|
|
char buf[512];
|
|
char unknown[96];
|
|
char *real, *fmt, *users_country;
|
|
struct away_msg *away;
|
|
gboolean missing = FALSE;
|
|
GtkWidget *item;
|
|
|
|
/* let the translators tweak this if need be */
|
|
fmt = _("<tt><b>%-11s</b></tt> %s");
|
|
g_snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
|
|
|
|
if (user->realname)
|
|
{
|
|
real = strip_color (user->realname, -1, STRIP_ALL|STRIP_ESCMARKUP);
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
|
|
g_free (real);
|
|
} else
|
|
{
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
|
|
}
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb),
|
|
user->realname ? user->realname : unknown);
|
|
|
|
g_snprintf (buf, sizeof (buf), fmt, _("User:"),
|
|
user->hostname ? user->hostname : unknown);
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb),
|
|
user->hostname ? user->hostname : unknown);
|
|
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Account:"),
|
|
user->account ? user->account : unknown);
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb),
|
|
user->account ? user->account : unknown);
|
|
|
|
users_country = country (user->hostname);
|
|
if (users_country)
|
|
{
|
|
g_snprintf (buf, sizeof (buf), fmt, _ ("Country:"), users_country);
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb), users_country);
|
|
}
|
|
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Server:"),
|
|
user->servername ? user->servername : unknown);
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb),
|
|
user->servername ? user->servername : unknown);
|
|
|
|
if (user->lasttalk)
|
|
{
|
|
char min[96];
|
|
|
|
g_snprintf (min, sizeof (min), _("%u minutes ago"),
|
|
(unsigned int) ((time (0) - user->lasttalk) / 60));
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
|
|
} else
|
|
{
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
|
|
}
|
|
menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
|
|
if (user->away)
|
|
{
|
|
away = server_away_find_message (current_sess->server, user->nick);
|
|
if (away)
|
|
{
|
|
char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP);
|
|
g_snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
|
|
g_free (msg);
|
|
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (copy_to_clipboard_cb),
|
|
away->message ? away->message : unknown);
|
|
}
|
|
else
|
|
missing = TRUE;
|
|
}
|
|
|
|
return missing;
|
|
}
|
|
|
|
void
|
|
fe_userlist_update (session *sess, struct User *user)
|
|
{
|
|
GList *items, *next;
|
|
#if HAVE_GTK3
|
|
GList *iter;
|
|
#endif
|
|
|
|
if (!nick_submenu || !str_copy)
|
|
return;
|
|
|
|
/* not the same nick as the menu? */
|
|
if (sess->server->p_cmp (user->nick, str_copy))
|
|
return;
|
|
|
|
/* get rid of the "show" signal */
|
|
g_signal_handlers_disconnect_by_func (nick_submenu, menu_nickinfo_cb, sess);
|
|
|
|
/* destroy all the old items */
|
|
#if HAVE_GTK3
|
|
items = gtk_container_get_children (GTK_CONTAINER (nick_submenu));
|
|
iter = items;
|
|
while (iter)
|
|
{
|
|
next = iter->next;
|
|
gtk_widget_destroy (iter->data);
|
|
iter = next;
|
|
}
|
|
g_list_free (items);
|
|
#else
|
|
items = ((GtkMenuShell *) nick_submenu)->children;
|
|
while (items)
|
|
{
|
|
next = items->next;
|
|
gtk_widget_destroy (items->data);
|
|
items = next;
|
|
}
|
|
#endif
|
|
|
|
/* and re-create them with new info */
|
|
menu_create_nickinfo_menu (user, nick_submenu);
|
|
}
|
|
|
|
void
|
|
menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
|
|
{
|
|
char buf[512];
|
|
struct User *user;
|
|
GtkWidget *submenu, *menu = menu_new ();
|
|
|
|
g_free (str_copy);
|
|
str_copy = g_strdup (nick);
|
|
|
|
submenu_list = 0; /* first time through, might not be 0 */
|
|
|
|
/* more than 1 nick selected? */
|
|
if (num_sel > 1)
|
|
{
|
|
g_snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
|
|
menu_quick_item (0, buf, menu, 0, 0, 0);
|
|
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
|
|
} else
|
|
{
|
|
user = userlist_find (sess, nick); /* lasttalk is channel specific */
|
|
if (!user)
|
|
user = userlist_find_global (current_sess->server, nick);
|
|
if (user)
|
|
{
|
|
nick_submenu = submenu = menu_quick_sub (nick, menu, NULL, XCMENU_DOLIST, -1);
|
|
|
|
if (menu_create_nickinfo_menu (user, submenu) ||
|
|
!user->hostname || !user->realname || !user->servername)
|
|
{
|
|
g_signal_connect (G_OBJECT (submenu), "show", G_CALLBACK (menu_nickinfo_cb), sess);
|
|
}
|
|
|
|
menu_quick_endsub ();
|
|
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
|
|
}
|
|
}
|
|
|
|
if (num_sel > 1)
|
|
menu_create (menu, popup_list, NULL, FALSE);
|
|
else
|
|
menu_create (menu, popup_list, str_copy, FALSE);
|
|
|
|
if (num_sel == 0) /* xtext click */
|
|
menu_add_plugin_items (menu, "\x5$NICK", str_copy);
|
|
else /* userlist treeview click */
|
|
menu_add_plugin_items (menu, "\x5$NICK", NULL);
|
|
|
|
menu_popup (menu, event, NULL);
|
|
}
|
|
|
|
/* stuff for the View menu */
|
|
|
|
static void
|
|
menu_showhide_cb (session *sess)
|
|
{
|
|
if (prefs.hex_gui_hide_menu)
|
|
gtk_widget_hide (sess->gui->menu);
|
|
else
|
|
gtk_widget_show (sess->gui->menu);
|
|
}
|
|
|
|
static void
|
|
menu_topic_showhide_cb (session *sess)
|
|
{
|
|
if (prefs.hex_gui_topicbar)
|
|
gtk_widget_show (sess->gui->topic_bar);
|
|
else
|
|
gtk_widget_hide (sess->gui->topic_bar);
|
|
}
|
|
|
|
static void
|
|
menu_userlist_showhide_cb (session *sess)
|
|
{
|
|
mg_decide_userlist (sess, TRUE);
|
|
}
|
|
|
|
static void
|
|
menu_ulbuttons_showhide_cb (session *sess)
|
|
{
|
|
if (prefs.hex_gui_ulist_buttons)
|
|
gtk_widget_show (sess->gui->button_box);
|
|
else
|
|
gtk_widget_hide (sess->gui->button_box);
|
|
}
|
|
|
|
static void
|
|
menu_cmbuttons_showhide_cb (session *sess)
|
|
{
|
|
switch (sess->type)
|
|
{
|
|
case SESS_CHANNEL:
|
|
if (prefs.hex_gui_mode_buttons)
|
|
gtk_widget_show (sess->gui->topicbutton_box);
|
|
else
|
|
gtk_widget_hide (sess->gui->topicbutton_box);
|
|
break;
|
|
default:
|
|
gtk_widget_hide (sess->gui->topicbutton_box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_setting_foreach (void (*callback) (session *), int id, guint state)
|
|
{
|
|
session *sess;
|
|
GSList *list;
|
|
int maindone = FALSE; /* do it only once for EVERY tab */
|
|
|
|
list = sess_list;
|
|
while (list)
|
|
{
|
|
sess = list->data;
|
|
|
|
if (!sess->gui->is_tab || !maindone)
|
|
{
|
|
if (sess->gui->is_tab)
|
|
maindone = TRUE;
|
|
if (id != -1)
|
|
{
|
|
GtkWidget *menu_item = sess->gui->menu_item[id];
|
|
|
|
if (menu_item != NULL)
|
|
{
|
|
#if HAVE_GTK3
|
|
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), state);
|
|
#else
|
|
GTK_CHECK_MENU_ITEM (menu_item)->active = state;
|
|
#endif
|
|
}
|
|
}
|
|
if (callback)
|
|
callback (sess);
|
|
}
|
|
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
void
|
|
menu_bar_toggle (void)
|
|
{
|
|
prefs.hex_gui_hide_menu = !prefs.hex_gui_hide_menu;
|
|
menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hex_gui_hide_menu);
|
|
}
|
|
|
|
static void
|
|
menu_bar_toggle_cb (void)
|
|
{
|
|
menu_bar_toggle ();
|
|
if (prefs.hex_gui_hide_menu)
|
|
fe_message (_("The Menubar is now hidden. You can show it again"
|
|
" by pressing Control+F9 or right-clicking in a blank part of"
|
|
" the main text area."), FE_MSG_INFO);
|
|
}
|
|
|
|
static void
|
|
menu_topicbar_toggle (GtkWidget *wid, gpointer ud)
|
|
{
|
|
prefs.hex_gui_topicbar = !prefs.hex_gui_topicbar;
|
|
menu_setting_foreach (menu_topic_showhide_cb, MENU_ID_TOPICBAR,
|
|
prefs.hex_gui_topicbar);
|
|
}
|
|
|
|
static void
|
|
menu_userlist_toggle (GtkWidget *wid, gpointer ud)
|
|
{
|
|
prefs.hex_gui_ulist_hide = !prefs.hex_gui_ulist_hide;
|
|
menu_setting_foreach (menu_userlist_showhide_cb, MENU_ID_USERLIST,
|
|
!prefs.hex_gui_ulist_hide);
|
|
}
|
|
|
|
static void
|
|
menu_ulbuttons_toggle (GtkWidget *wid, gpointer ud)
|
|
{
|
|
prefs.hex_gui_ulist_buttons = !prefs.hex_gui_ulist_buttons;
|
|
menu_setting_foreach (menu_ulbuttons_showhide_cb, MENU_ID_ULBUTTONS,
|
|
prefs.hex_gui_ulist_buttons);
|
|
}
|
|
|
|
static void
|
|
menu_cmbuttons_toggle (GtkWidget *wid, gpointer ud)
|
|
{
|
|
prefs.hex_gui_mode_buttons = !prefs.hex_gui_mode_buttons;
|
|
menu_setting_foreach (menu_cmbuttons_showhide_cb, MENU_ID_MODEBUTTONS,
|
|
prefs.hex_gui_mode_buttons);
|
|
}
|
|
|
|
static void
|
|
menu_fullscreen_toggle (GtkWidget *wid, gpointer ud)
|
|
{
|
|
if (!prefs.hex_gui_win_fullscreen)
|
|
gtk_window_fullscreen (GTK_WINDOW(parent_window));
|
|
else
|
|
{
|
|
gtk_window_unfullscreen (GTK_WINDOW(parent_window));
|
|
|
|
#ifdef WIN32
|
|
if (!prefs.hex_gui_win_state) /* not maximized */
|
|
{
|
|
/* other window managers seem to handle this */
|
|
gtk_window_resize (GTK_WINDOW (parent_window),
|
|
prefs.hex_gui_win_width, prefs.hex_gui_win_height);
|
|
gtk_window_move (GTK_WINDOW (parent_window),
|
|
prefs.hex_gui_win_left, prefs.hex_gui_win_top);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
menu_middlemenu (session *sess, GdkEventButton *event)
|
|
{
|
|
GtkWidget *menu;
|
|
GtkAccelGroup *accel_group;
|
|
|
|
accel_group = gtk_accel_group_new ();
|
|
menu = menu_create_main (accel_group, FALSE, sess->server->is_away, !sess->gui->is_tab, NULL);
|
|
menu_popup (menu, event, accel_group);
|
|
}
|
|
|
|
static void
|
|
open_url_cb (GtkWidget *item, char *url)
|
|
{
|
|
char buf[512];
|
|
|
|
/* pass this to /URL so it can handle irc:// */
|
|
g_snprintf (buf, sizeof (buf), "URL %s", url);
|
|
handle_command (current_sess, buf, FALSE);
|
|
}
|
|
|
|
void
|
|
menu_urlmenu (GdkEventButton *event, char *url)
|
|
{
|
|
GtkWidget *menu;
|
|
char *tmp, *chop;
|
|
|
|
g_free (str_copy);
|
|
str_copy = g_strdup (url);
|
|
|
|
menu = menu_new ();
|
|
/* more than 51 chars? Chop it */
|
|
if (g_utf8_strlen (str_copy, -1) >= 52)
|
|
{
|
|
tmp = g_strdup (str_copy);
|
|
chop = g_utf8_offset_to_pointer (tmp, 48);
|
|
chop[0] = chop[1] = chop[2] = '.';
|
|
chop[3] = 0;
|
|
menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
|
|
g_free (tmp);
|
|
} else
|
|
{
|
|
menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
|
|
}
|
|
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
|
|
|
|
/* Two hardcoded entries */
|
|
if (strncmp (str_copy, "irc://", 6) == 0 ||
|
|
strncmp (str_copy, "ircs://",7) == 0)
|
|
menu_quick_item_with_callback (open_url_cb, _("Connect"), menu, str_copy);
|
|
else
|
|
menu_quick_item_with_callback (open_url_cb, _("Open Link in Browser"), menu, str_copy);
|
|
menu_quick_item_with_callback (copy_to_clipboard_cb, _("Copy Selected Link"), menu, str_copy);
|
|
/* custom ones from urlhandlers.conf */
|
|
menu_create (menu, urlhandler_list, str_copy, TRUE);
|
|
menu_add_plugin_items (menu, "\x4$URL", str_copy);
|
|
menu_popup (menu, event, NULL);
|
|
}
|
|
|
|
static void
|
|
menu_chan_cycle (GtkWidget * menu, char *chan)
|
|
{
|
|
char tbuf[256];
|
|
|
|
if (current_sess)
|
|
{
|
|
g_snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
|
|
handle_command (current_sess, tbuf, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_chan_part (GtkWidget * menu, char *chan)
|
|
{
|
|
char tbuf[256];
|
|
|
|
if (current_sess)
|
|
{
|
|
g_snprintf (tbuf, sizeof tbuf, "part %s", chan);
|
|
handle_command (current_sess, tbuf, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_chan_focus (GtkWidget * menu, char *chan)
|
|
{
|
|
char tbuf[256];
|
|
|
|
if (current_sess)
|
|
{
|
|
g_snprintf (tbuf, sizeof tbuf, "doat %s gui focus", chan);
|
|
handle_command (current_sess, tbuf, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_chan_join (GtkWidget * menu, char *chan)
|
|
{
|
|
char tbuf[256];
|
|
|
|
if (current_sess)
|
|
{
|
|
g_snprintf (tbuf, sizeof tbuf, "join %s", chan);
|
|
handle_command (current_sess, tbuf, FALSE);
|
|
}
|
|
}
|
|
|
|
void
|
|
menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
|
|
{
|
|
GtkWidget *menu;
|
|
int is_joined = FALSE;
|
|
session * chan_session;
|
|
|
|
chan_session = find_channel (sess->server, chan);
|
|
|
|
if (chan_session)
|
|
is_joined = TRUE;
|
|
|
|
g_free (str_copy);
|
|
str_copy = g_strdup (chan);
|
|
|
|
menu = menu_new ();
|
|
|
|
menu_quick_item (0, chan, menu, XCMENU_SHADED, str_copy, 0);
|
|
menu_quick_item (0, 0, menu, XCMENU_SHADED, str_copy, 0);
|
|
|
|
if (!is_joined)
|
|
menu_quick_item_with_callback (menu_chan_join, _("Join Channel"), menu,
|
|
str_copy);
|
|
else
|
|
{
|
|
if (chan_session != current_sess)
|
|
menu_quick_item_with_callback (menu_chan_focus, _("Focus Channel"), menu,
|
|
str_copy);
|
|
menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
|
|
str_copy);
|
|
menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
|
|
str_copy);
|
|
}
|
|
|
|
menu_addfavoritemenu (sess->server, menu, str_copy, FALSE);
|
|
|
|
menu_add_plugin_items (menu, "\x5$CHAN", str_copy);
|
|
menu_popup (menu, event, NULL);
|
|
}
|
|
|
|
static void
|
|
menu_delfav_cb (GtkWidget *item, server *serv)
|
|
{
|
|
servlist_autojoinedit (serv->network, str_copy, FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_addfav_cb (GtkWidget *item, server *serv)
|
|
{
|
|
servlist_autojoinedit (serv->network, str_copy, TRUE);
|
|
}
|
|
|
|
void
|
|
menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel, gboolean istree)
|
|
{
|
|
char *str;
|
|
|
|
if (!serv->network)
|
|
return;
|
|
|
|
if (channel != str_copy)
|
|
{
|
|
g_free (str_copy);
|
|
str_copy = g_strdup (channel);
|
|
}
|
|
|
|
if (istree)
|
|
str = _("_Autojoin");
|
|
else
|
|
str = _("Autojoin Channel");
|
|
|
|
if (joinlist_is_in_list (serv, channel))
|
|
{
|
|
menu_toggle_item (str, menu, menu_delfav_cb, serv, TRUE);
|
|
}
|
|
else
|
|
{
|
|
menu_toggle_item (str, menu, menu_addfav_cb, serv, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_delautoconn_cb (GtkWidget *item, server *serv)
|
|
{
|
|
((ircnet*)serv->network)->flags &= ~FLAG_AUTO_CONNECT;
|
|
servlist_save ();
|
|
}
|
|
|
|
static void
|
|
menu_addautoconn_cb (GtkWidget *item, server *serv)
|
|
{
|
|
((ircnet*)serv->network)->flags |= FLAG_AUTO_CONNECT;
|
|
servlist_save ();
|
|
}
|
|
|
|
void
|
|
menu_addconnectmenu (server *serv, GtkWidget *menu)
|
|
{
|
|
if (!serv->network)
|
|
return;
|
|
|
|
if (((ircnet*)serv->network)->flags & FLAG_AUTO_CONNECT)
|
|
{
|
|
menu_toggle_item (_("_Auto-Connect"), menu, menu_delautoconn_cb, serv, TRUE);
|
|
}
|
|
else
|
|
{
|
|
menu_toggle_item (_("_Auto-Connect"), menu, menu_addautoconn_cb, serv, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_open_server_list (GtkWidget *wid, gpointer none)
|
|
{
|
|
fe_serverlist_open (current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_settings (GtkWidget * wid, gpointer none)
|
|
{
|
|
extern void setup_open (void);
|
|
setup_open ();
|
|
}
|
|
|
|
static void
|
|
menu_usermenu (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("User menu - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, usermenu_list, buf, "usermenu", "usermenu.conf", 0);
|
|
}
|
|
|
|
static void
|
|
usermenu_create (GtkWidget *menu)
|
|
{
|
|
menu_create (menu, usermenu_list, "", FALSE);
|
|
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0); /* sep */
|
|
menu_quick_item_with_callback (menu_usermenu, _("Edit This Menu" ELLIPSIS), menu, 0);
|
|
}
|
|
|
|
static void
|
|
usermenu_destroy (GtkWidget * menu)
|
|
{
|
|
GList *items;
|
|
GList *next;
|
|
#if HAVE_GTK3
|
|
GList *iter;
|
|
|
|
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
|
iter = items;
|
|
while (iter)
|
|
{
|
|
next = iter->next;
|
|
gtk_widget_destroy (iter->data);
|
|
iter = next;
|
|
}
|
|
g_list_free (items);
|
|
#else
|
|
items = ((GtkMenuShell *) menu)->children;
|
|
|
|
while (items)
|
|
{
|
|
next = items->next;
|
|
gtk_widget_destroy (items->data);
|
|
items = next;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void
|
|
usermenu_update (void)
|
|
{
|
|
int done_main = FALSE;
|
|
GSList *list = sess_list;
|
|
session *sess;
|
|
GtkWidget *menu;
|
|
|
|
while (list)
|
|
{
|
|
sess = list->data;
|
|
menu = sess->gui->menu_item[MENU_ID_USERMENU];
|
|
if (sess->gui->is_tab)
|
|
{
|
|
if (!done_main && menu)
|
|
{
|
|
usermenu_destroy (menu);
|
|
usermenu_create (menu);
|
|
done_main = TRUE;
|
|
}
|
|
} else if (menu)
|
|
{
|
|
usermenu_destroy (menu);
|
|
usermenu_create (menu);
|
|
}
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_newserver_window (GtkWidget * wid, gpointer none)
|
|
{
|
|
int old = prefs.hex_gui_tab_chans;
|
|
|
|
prefs.hex_gui_tab_chans = 0;
|
|
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
|
|
prefs.hex_gui_tab_chans = old;
|
|
}
|
|
|
|
static void
|
|
menu_newchannel_window (GtkWidget * wid, gpointer none)
|
|
{
|
|
int old = prefs.hex_gui_tab_chans;
|
|
|
|
prefs.hex_gui_tab_chans = 0;
|
|
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
|
|
prefs.hex_gui_tab_chans = old;
|
|
}
|
|
|
|
static void
|
|
menu_newserver_tab (GtkWidget * wid, gpointer none)
|
|
{
|
|
int old = prefs.hex_gui_tab_chans;
|
|
int oldf = prefs.hex_gui_tab_newtofront;
|
|
|
|
prefs.hex_gui_tab_chans = 1;
|
|
/* force focus if setting is "only requested tabs" */
|
|
if (prefs.hex_gui_tab_newtofront == 2)
|
|
prefs.hex_gui_tab_newtofront = 1;
|
|
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
|
|
prefs.hex_gui_tab_chans = old;
|
|
prefs.hex_gui_tab_newtofront = oldf;
|
|
}
|
|
|
|
static void
|
|
menu_newchannel_tab (GtkWidget * wid, gpointer none)
|
|
{
|
|
int old = prefs.hex_gui_tab_chans;
|
|
|
|
prefs.hex_gui_tab_chans = 1;
|
|
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
|
|
prefs.hex_gui_tab_chans = old;
|
|
}
|
|
|
|
static void
|
|
menu_rawlog (GtkWidget * wid, gpointer none)
|
|
{
|
|
open_rawlog (current_sess->server);
|
|
}
|
|
|
|
static void
|
|
menu_detach (GtkWidget * wid, gpointer none)
|
|
{
|
|
mg_detach (current_sess, 0);
|
|
}
|
|
|
|
static void
|
|
menu_close (GtkWidget * wid, gpointer none)
|
|
{
|
|
mg_close_sess (current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_quit (GtkWidget * wid, gpointer none)
|
|
{
|
|
mg_open_quit_dialog (FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_search (void)
|
|
{
|
|
mg_search_toggle (current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_search_next (GtkWidget *wid)
|
|
{
|
|
mg_search_handle_next(wid, current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_search_prev (GtkWidget *wid)
|
|
{
|
|
mg_search_handle_previous(wid, current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_resetmarker (GtkWidget * wid, gpointer none)
|
|
{
|
|
gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
|
|
}
|
|
|
|
static void
|
|
menu_movetomarker (GtkWidget *wid, gpointer none)
|
|
{
|
|
marker_reset_reason reason;
|
|
char *str;
|
|
|
|
if (!prefs.hex_text_show_marker)
|
|
PrintText (current_sess, _("Marker line disabled."));
|
|
else
|
|
{
|
|
reason = gtk_xtext_moveto_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
|
|
switch (reason) {
|
|
case MARKER_WAS_NEVER_SET:
|
|
str = _("Marker line never set."); break;
|
|
case MARKER_IS_SET:
|
|
str = ""; break;
|
|
case MARKER_RESET_MANUALLY:
|
|
str = _("Marker line reset manually."); break;
|
|
case MARKER_RESET_BY_KILL:
|
|
str = _("Marker line reset because exceeded scrollback limit."); break;
|
|
case MARKER_RESET_BY_CLEAR:
|
|
str = _("Marker line reset by CLEAR command."); break;
|
|
default:
|
|
str = _("Marker line state unknown."); break;
|
|
}
|
|
if (str[0])
|
|
PrintText (current_sess, str);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_copy_selection (GtkWidget * wid, gpointer none)
|
|
{
|
|
gtk_xtext_copy_selection (GTK_XTEXT (current_sess->gui->xtext));
|
|
}
|
|
|
|
static void
|
|
menu_flushbuffer (GtkWidget * wid, gpointer none)
|
|
{
|
|
fe_text_clear (current_sess, 0);
|
|
}
|
|
|
|
static void
|
|
savebuffer_req_done (session *sess, char *file)
|
|
{
|
|
int fh;
|
|
|
|
if (!file)
|
|
return;
|
|
|
|
fh = g_open (file, O_TRUNC | O_WRONLY | O_CREAT, 0600);
|
|
if (fh != -1)
|
|
{
|
|
gtk_xtext_save (GTK_XTEXT (sess->gui->xtext), fh);
|
|
close (fh);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_savebuffer (GtkWidget * wid, gpointer none)
|
|
{
|
|
gtkutil_file_req (NULL, _("Select an output filename"), savebuffer_req_done,
|
|
current_sess, NULL, NULL, FRF_WRITE);
|
|
}
|
|
|
|
static void
|
|
menu_disconnect (GtkWidget * wid, gpointer none)
|
|
{
|
|
handle_command (current_sess, "DISCON", FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_reconnect (GtkWidget * wid, gpointer none)
|
|
{
|
|
if (current_sess->server->hostname[0])
|
|
handle_command (current_sess, "RECONNECT", FALSE);
|
|
else
|
|
fe_serverlist_open (current_sess);
|
|
}
|
|
|
|
static void
|
|
menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
|
|
{
|
|
switch (response)
|
|
{
|
|
case GTK_RESPONSE_ACCEPT:
|
|
#if HAVE_GTK3
|
|
menu_chan_join (NULL, (char *)gtk_entry_get_text (GTK_ENTRY (entry)));
|
|
#else
|
|
menu_chan_join (NULL, entry->text);
|
|
#endif
|
|
break;
|
|
|
|
case GTK_RESPONSE_HELP:
|
|
chanlist_opengui (current_sess->server, TRUE);
|
|
break;
|
|
}
|
|
|
|
gtk_widget_destroy (dialog);
|
|
}
|
|
|
|
static void
|
|
menu_join_entry_cb (GtkWidget *entry, GtkDialog *dialog)
|
|
{
|
|
gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
|
|
}
|
|
|
|
static void
|
|
menu_join (GtkWidget * wid, gpointer none)
|
|
{
|
|
GtkWidget *hbox, *dialog, *entry, *label;
|
|
#if HAVE_GTK3
|
|
GtkWidget *content_area;
|
|
#endif
|
|
|
|
#if HAVE_GTK3
|
|
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
|
|
GTK_WINDOW (parent_window), 0,
|
|
_("Retrieve channel list"), GTK_RESPONSE_HELP,
|
|
_("_Cancel"), GTK_RESPONSE_REJECT,
|
|
_("_OK"), GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
{
|
|
GtkWidget *button;
|
|
|
|
button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_HELP);
|
|
if (button)
|
|
gtk_button_set_image (GTK_BUTTON (button),
|
|
gtk_image_new_from_icon_name ("help-browser", GTK_ICON_SIZE_BUTTON));
|
|
|
|
button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
|
|
if (button)
|
|
gtk_button_set_image (GTK_BUTTON (button),
|
|
gtk_image_new_from_icon_name ("dialog-cancel", GTK_ICON_SIZE_BUTTON));
|
|
|
|
button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
|
if (button)
|
|
gtk_button_set_image (GTK_BUTTON (button),
|
|
gtk_image_new_from_icon_name ("dialog-ok", GTK_ICON_SIZE_BUTTON));
|
|
}
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
|
|
GTK_WINDOW (parent_window), 0,
|
|
_("Retrieve channel list"), GTK_RESPONSE_HELP,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
|
|
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
#endif
|
|
#if HAVE_GTK3
|
|
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
|
|
gtk_box_set_homogeneous (GTK_BOX (content_area), TRUE);
|
|
#else
|
|
gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
|
|
#endif
|
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
|
|
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, TRUE, 0);
|
|
|
|
entry = gtk_entry_new ();
|
|
#if HAVE_GTK3
|
|
gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE); /* avoid auto-selection */
|
|
#else
|
|
GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
|
|
#endif
|
|
gtk_entry_set_text (GTK_ENTRY (entry), "#");
|
|
g_signal_connect (G_OBJECT (entry), "activate",
|
|
G_CALLBACK (menu_join_entry_cb), dialog);
|
|
gtk_box_pack_end (GTK_BOX (hbox), entry, 0, 0, 0);
|
|
|
|
label = gtk_label_new (_("Enter Channel to Join:"));
|
|
gtk_box_pack_end (GTK_BOX (hbox), label, 0, 0, 0);
|
|
|
|
g_signal_connect (G_OBJECT (dialog), "response",
|
|
G_CALLBACK (menu_join_cb), entry);
|
|
|
|
#if HAVE_GTK3
|
|
gtk_container_add (GTK_CONTAINER (content_area), hbox);
|
|
#else
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
|
|
#endif
|
|
|
|
gtk_widget_show_all (dialog);
|
|
|
|
gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
|
|
gtk_editable_set_position (GTK_EDITABLE (entry), 1);
|
|
}
|
|
|
|
static void
|
|
menu_away (GtkCheckMenuItem *item, gpointer none)
|
|
{
|
|
handle_command (current_sess, gtk_check_menu_item_get_active (item) ? "away" : "back", FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_chanlist (GtkWidget * wid, gpointer none)
|
|
{
|
|
chanlist_opengui (current_sess->server, FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_banlist (GtkWidget * wid, gpointer none)
|
|
{
|
|
banlist_opengui (current_sess);
|
|
}
|
|
|
|
#ifdef USE_PLUGIN
|
|
|
|
static void
|
|
menu_loadplugin (void)
|
|
{
|
|
plugingui_load ();
|
|
}
|
|
|
|
static void
|
|
menu_pluginlist (void)
|
|
{
|
|
plugingui_open ();
|
|
}
|
|
|
|
#else
|
|
|
|
static void
|
|
menu_noplugin_info (void)
|
|
{
|
|
fe_message (_(DISPLAY_NAME " has been build without plugin support."), FE_MSG_INFO);
|
|
}
|
|
|
|
#define menu_loadplugin menu_noplugin_info
|
|
#define menu_pluginlist menu_noplugin_info
|
|
|
|
#endif
|
|
|
|
#define usercommands_help _("User Commands - Special codes:\n\n"\
|
|
"%c = current channel\n"\
|
|
"%e = current network name\n"\
|
|
"%m = machine info\n"\
|
|
"%n = your nick\n"\
|
|
"%t = time/date\n"\
|
|
"%v = ZoiteChat version\n"\
|
|
"%2 = word 2\n"\
|
|
"%3 = word 3\n"\
|
|
"&2 = word 2 to the end of line\n"\
|
|
"&3 = word 3 to the end of line\n\n"\
|
|
"eg:\n"\
|
|
"/cmd john hello\n\n"\
|
|
"%2 would be \042john\042\n"\
|
|
"&2 would be \042john hello\042.")
|
|
|
|
#define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
|
|
"%a = all selected nicks\n"\
|
|
"%c = current channel\n"\
|
|
"%e = current network name\n"\
|
|
"%h = selected nick's hostname\n"\
|
|
"%m = machine info\n"\
|
|
"%n = your nick\n"\
|
|
"%s = selected nick\n"\
|
|
"%t = time/date\n"\
|
|
"%u = selected users account")
|
|
|
|
#define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
|
|
"%a = all selected nicks\n"\
|
|
"%c = current channel\n"\
|
|
"%e = current network name\n"\
|
|
"%h = selected nick's hostname\n"\
|
|
"%m = machine info\n"\
|
|
"%n = your nick\n"\
|
|
"%s = selected nick\n"\
|
|
"%t = time/date\n"\
|
|
"%u = selected users account")
|
|
|
|
#define ctcp_help _("CTCP Replies - Special codes:\n\n"\
|
|
"%d = data (the whole ctcp)\n"\
|
|
"%e = current network name\n"\
|
|
"%m = machine info\n"\
|
|
"%s = nick who sent the ctcp\n"\
|
|
"%t = time/date\n"\
|
|
"%2 = word 2\n"\
|
|
"%3 = word 3\n"\
|
|
"&2 = word 2 to the end of line\n"\
|
|
"&3 = word 3 to the end of line\n\n")
|
|
|
|
#define url_help _("URL Handlers - Special codes:\n\n"\
|
|
"%s = the URL string\n\n"\
|
|
"Putting a ! in front of the command\n"\
|
|
"indicates it should be sent to a\n"\
|
|
"shell instead of ZoiteChat")
|
|
|
|
static void
|
|
menu_usercommands (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("User Defined Commands - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, command_list, buf, "commands", "commands.conf",
|
|
usercommands_help);
|
|
}
|
|
|
|
static void
|
|
menu_ulpopup (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("Userlist Popup menu - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, popup_list, buf, "popup", "popup.conf", ulbutton_help);
|
|
}
|
|
|
|
static void
|
|
menu_rpopup (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("Replace - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (_("Text"), _("Replace with"), replace_list, buf, "replace", "replace.conf", 0);
|
|
}
|
|
|
|
static void
|
|
menu_urlhandlers (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("URL Handlers - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, urlhandler_list, buf, "urlhandlers", "urlhandlers.conf", url_help);
|
|
}
|
|
|
|
static void
|
|
menu_evtpopup (void)
|
|
{
|
|
pevent_dialog_show ();
|
|
}
|
|
|
|
static void
|
|
menu_keypopup (void)
|
|
{
|
|
key_dialog_show ();
|
|
}
|
|
|
|
static void
|
|
menu_ulbuttons (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("Userlist buttons - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, button_list, buf, "buttons", "buttons.conf", ulbutton_help);
|
|
}
|
|
|
|
static void
|
|
menu_dlgbuttons (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("Dialog buttons - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, dlgbutton_list, buf, "dlgbuttons", "dlgbuttons.conf",
|
|
dlgbutton_help);
|
|
}
|
|
|
|
static void
|
|
menu_ctcpguiopen (void)
|
|
{
|
|
char buf[128];
|
|
g_snprintf(buf, sizeof(buf), _("CTCP Replies - %s"), _(DISPLAY_NAME));
|
|
editlist_gui_open (NULL, NULL, ctcp_list, buf, "ctcpreply", "ctcpreply.conf", ctcp_help);
|
|
}
|
|
|
|
static void
|
|
menu_docs (GtkWidget *wid, gpointer none)
|
|
{
|
|
fe_open_url ("http://zoitechat.zoite.net/docs");
|
|
}
|
|
|
|
/*static void
|
|
menu_webpage (GtkWidget *wid, gpointer none)
|
|
{
|
|
fe_open_url ("http://xchat.org");
|
|
}*/
|
|
|
|
static void
|
|
menu_dcc_win (GtkWidget *wid, gpointer none)
|
|
{
|
|
fe_dcc_open_recv_win (FALSE);
|
|
fe_dcc_open_send_win (FALSE);
|
|
}
|
|
|
|
static void
|
|
menu_dcc_chat_win (GtkWidget *wid, gpointer none)
|
|
{
|
|
fe_dcc_open_chat_win (FALSE);
|
|
}
|
|
|
|
void
|
|
menu_change_layout (void)
|
|
{
|
|
if (prefs.hex_gui_tab_layout == 0)
|
|
{
|
|
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 1);
|
|
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 0);
|
|
mg_change_layout (0);
|
|
} else
|
|
{
|
|
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 0);
|
|
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 1);
|
|
mg_change_layout (2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_layout_cb (GtkWidget *item, gpointer none)
|
|
{
|
|
prefs.hex_gui_tab_layout = 2;
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
prefs.hex_gui_tab_layout = 0;
|
|
|
|
menu_change_layout ();
|
|
}
|
|
|
|
static void
|
|
menu_apply_metres_cb (session *sess)
|
|
{
|
|
mg_update_meters (sess->gui);
|
|
}
|
|
|
|
static void
|
|
menu_metres_off (GtkWidget *item, gpointer none)
|
|
{
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
{
|
|
prefs.hex_gui_lagometer = 0;
|
|
prefs.hex_gui_throttlemeter = 0;
|
|
zoitechat_reinit_timers ();
|
|
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_metres_text (GtkWidget *item, gpointer none)
|
|
{
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
{
|
|
prefs.hex_gui_lagometer = 2;
|
|
prefs.hex_gui_throttlemeter = 2;
|
|
zoitechat_reinit_timers ();
|
|
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_metres_graph (GtkWidget *item, gpointer none)
|
|
{
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
{
|
|
prefs.hex_gui_lagometer = 1;
|
|
prefs.hex_gui_throttlemeter = 1;
|
|
zoitechat_reinit_timers ();
|
|
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_metres_both (GtkWidget *item, gpointer none)
|
|
{
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
|
|
#else
|
|
if (GTK_CHECK_MENU_ITEM (item)->active)
|
|
#endif
|
|
{
|
|
prefs.hex_gui_lagometer = 3;
|
|
prefs.hex_gui_throttlemeter = 3;
|
|
zoitechat_reinit_timers ();
|
|
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
about_dialog_close (GtkDialog *dialog, int response, gpointer data)
|
|
{
|
|
gtk_widget_destroy (GTK_WIDGET(dialog));
|
|
}
|
|
|
|
static gboolean
|
|
about_dialog_openurl (GtkAboutDialog *dialog, char *uri, gpointer data)
|
|
{
|
|
fe_open_url (uri);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
menu_about (GtkWidget *wid, gpointer sess)
|
|
{
|
|
GtkAboutDialog *dialog = GTK_ABOUT_DIALOG(gtk_about_dialog_new());
|
|
char comment[512];
|
|
char *license = "This program is free software; you can redistribute it and/or modify\n" \
|
|
"it under the terms of the GNU General Public License as published by\n" \
|
|
"the Free Software Foundation; version 2.\n\n" \
|
|
"This program is distributed in the hope that it will be useful,\n" \
|
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
|
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \
|
|
"GNU General Public License for more details.\n\n" \
|
|
"You should have received a copy of the GNU General Public License\n" \
|
|
"along with this program. If not, see <http://www.gnu.org/licenses/>";
|
|
|
|
g_snprintf (comment, sizeof(comment), ""
|
|
#ifdef WIN32
|
|
"Portable Mode: %s\n"
|
|
"Build Type: x%d\n"
|
|
#endif
|
|
"OS: %s",
|
|
#ifdef WIN32
|
|
(portable_mode () ? "Yes" : "No"),
|
|
get_cpu_arch (),
|
|
#endif
|
|
get_sys_str (0));
|
|
|
|
gtk_about_dialog_set_program_name (dialog, _(DISPLAY_NAME));
|
|
gtk_about_dialog_set_version (dialog, PACKAGE_VERSION);
|
|
#if HAVE_GTK3
|
|
gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG (dialog), GTK_LICENSE_GPL_2_0);
|
|
#else
|
|
gtk_about_dialog_set_license (dialog, license);
|
|
#endif
|
|
gtk_about_dialog_set_website (dialog, "http://zoitechat.zoite.net");
|
|
gtk_about_dialog_set_website_label (dialog, "Website");
|
|
gtk_about_dialog_set_logo (dialog, pix_zoitechat);
|
|
gtk_about_dialog_set_copyright (dialog, "\302\251 1998-2010 Peter \305\275elezn\303\275\n\302\251 2009-2014 Berke Viktor\n\302\251 2026 deepend");
|
|
gtk_about_dialog_set_comments (dialog, comment);
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(parent_window));
|
|
g_signal_connect (G_OBJECT(dialog), "response", G_CALLBACK(about_dialog_close), NULL);
|
|
g_signal_connect (G_OBJECT(dialog), "activate-link", G_CALLBACK(about_dialog_openurl), NULL);
|
|
|
|
gtk_widget_show_all (GTK_WIDGET(dialog));
|
|
}
|
|
|
|
#if HAVE_GTK3
|
|
#define ICON_NEW "zc-menu-new"
|
|
#define ICON_NETWORK_LIST "zc-menu-network-list"
|
|
#define ICON_LOAD_PLUGIN "zc-menu-load-plugin"
|
|
#define ICON_DETACH "zc-menu-detach"
|
|
#define ICON_CLOSE "zc-menu-close"
|
|
#define ICON_QUIT "zc-menu-quit"
|
|
#define ICON_DISCONNECT "zc-menu-disconnect"
|
|
#define ICON_CONNECT "zc-menu-connect"
|
|
#define ICON_JOIN "zc-menu-join"
|
|
#define ICON_CHANLIST "zc-menu-chanlist"
|
|
#define ICON_PREFERENCES "zc-menu-preferences"
|
|
#define ICON_CLEAR "zc-menu-clear"
|
|
#define ICON_SAVE "zc-menu-save"
|
|
#define ICON_SEARCH "zc-menu-search"
|
|
#define ICON_FIND "zc-menu-find"
|
|
#define ICON_HELP "zc-menu-help"
|
|
#define ICON_ABOUT "zc-menu-about"
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
#define ICON_NEW GTK_STOCK_NEW
|
|
#define ICON_NETWORK_LIST GTK_STOCK_INDEX
|
|
#define ICON_LOAD_PLUGIN GTK_STOCK_REVERT_TO_SAVED
|
|
#define ICON_DETACH GTK_STOCK_REDO
|
|
#define ICON_CLOSE GTK_STOCK_CLOSE
|
|
#define ICON_QUIT GTK_STOCK_QUIT
|
|
#define ICON_DISCONNECT GTK_STOCK_DISCONNECT
|
|
#define ICON_CONNECT GTK_STOCK_CONNECT
|
|
#define ICON_JOIN GTK_STOCK_JUMP_TO
|
|
#define ICON_CHANLIST GTK_STOCK_INDEX
|
|
#define ICON_PREFERENCES GTK_STOCK_PREFERENCES
|
|
#define ICON_CLEAR GTK_STOCK_CLEAR
|
|
#define ICON_SAVE GTK_STOCK_SAVE
|
|
#define ICON_SEARCH GTK_STOCK_JUSTIFY_LEFT
|
|
#define ICON_FIND GTK_STOCK_FIND
|
|
#define ICON_HELP GTK_STOCK_HELP
|
|
#define ICON_ABOUT GTK_STOCK_ABOUT
|
|
#endif
|
|
|
|
#if HAVE_GTK3
|
|
static const char *
|
|
menu_icon_theme_variant (void)
|
|
{
|
|
GtkSettings *settings;
|
|
gboolean prefer_dark = FALSE;
|
|
char *theme_name = NULL;
|
|
char *theme_name_lower = NULL;
|
|
const char *theme_variant = "light";
|
|
|
|
settings = gtk_settings_get_default ();
|
|
if (settings)
|
|
{
|
|
g_object_get (G_OBJECT (settings), "gtk-application-prefer-dark-theme", &prefer_dark, NULL);
|
|
g_object_get (G_OBJECT (settings), "gtk-theme-name", &theme_name, NULL);
|
|
}
|
|
|
|
if (theme_name)
|
|
theme_name_lower = g_ascii_strdown (theme_name, -1);
|
|
if (prefer_dark || (theme_name_lower && g_strrstr (theme_name_lower, "dark")))
|
|
theme_variant = "dark";
|
|
|
|
g_free (theme_name_lower);
|
|
g_free (theme_name);
|
|
|
|
return theme_variant;
|
|
}
|
|
|
|
#ifdef WIN32
|
|
static GtkWidget *
|
|
menu_icon_image_from_data_icons (const char *icon_name, const char *theme_variant)
|
|
{
|
|
GtkWidget *image = NULL;
|
|
GdkPixbuf *custom_pixbuf = NULL;
|
|
char *base_path = g_win32_get_package_installation_directory_of_module (NULL);
|
|
|
|
if (base_path)
|
|
{
|
|
char *icons_menu_path = g_build_filename (base_path, "share", "icons", "menu", theme_variant, NULL);
|
|
char *filename = g_strconcat (icon_name, ".svg", NULL);
|
|
char *icon_path = g_build_filename (icons_menu_path, filename, NULL);
|
|
|
|
if (g_file_test (icon_path, G_FILE_TEST_EXISTS))
|
|
{
|
|
custom_pixbuf = gdk_pixbuf_new_from_file (icon_path, NULL);
|
|
if (custom_pixbuf)
|
|
{
|
|
image = gtk_image_new_from_pixbuf (custom_pixbuf);
|
|
g_object_unref (custom_pixbuf);
|
|
}
|
|
}
|
|
|
|
g_free (icon_path);
|
|
g_free (filename);
|
|
g_free (icons_menu_path);
|
|
g_free (base_path);
|
|
}
|
|
|
|
return image;
|
|
}
|
|
#else
|
|
static GtkWidget *
|
|
menu_icon_image_from_data_icons (const char *icon_name, const char *theme_variant)
|
|
{
|
|
GtkWidget *image = NULL;
|
|
GdkPixbuf *custom_pixbuf;
|
|
char *resource_path = g_strdup_printf ("/icons/menu/%s/%s.svg", theme_variant, icon_name);
|
|
|
|
if (g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
|
|
{
|
|
custom_pixbuf = gdk_pixbuf_new_from_resource (resource_path, NULL);
|
|
if (custom_pixbuf)
|
|
{
|
|
image = gtk_image_new_from_pixbuf (custom_pixbuf);
|
|
g_object_unref (custom_pixbuf);
|
|
}
|
|
}
|
|
|
|
g_free (resource_path);
|
|
|
|
return image;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
static struct mymenu mymenu[] = {
|
|
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
|
|
{N_("Network Li_st"), menu_open_server_list, ICON_NETWORK_LIST, M_MENUSTOCK, 0, 0, 1, GDK_KEY_s},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
|
|
{N_("_New"), 0, ICON_NEW, M_MENUSUB, 0, 0, 1},
|
|
{N_("Server Tab"), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_t},
|
|
{N_("Channel Tab"), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Server Window"), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_n},
|
|
{N_("Channel Window"), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
|
|
{0, 0, 0, M_END, 0, 0, 0},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
|
|
{N_("_Load Plugin or Script" ELLIPSIS), menu_loadplugin, ICON_LOAD_PLUGIN, M_MENUSTOCK, 0, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
|
|
#define DETACH_OFFSET (12)
|
|
{0, menu_detach, ICON_DETACH, M_MENUSTOCK, 0, 0, 1}, /* 12 */
|
|
#define CLOSE_OFFSET (13)
|
|
{0, menu_close, ICON_CLOSE, M_MENUSTOCK, 0, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
{N_("_Quit"), menu_quit, ICON_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_KEY_q}, /* 15 */
|
|
|
|
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
|
|
#define MENUBAR_OFFSET (17)
|
|
{N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_KEY_F9},
|
|
{N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
|
|
{N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_KEY_F7},
|
|
{N_("U_ser List Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
|
|
{N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
{N_("_Channel Switcher"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 23 */
|
|
#define TABS_OFFSET (24)
|
|
{N_("_Tabs"), menu_layout_cb, 0, M_MENURADIO, MENU_ID_LAYOUT_TABS, 0, 1},
|
|
{N_("T_ree"), 0, 0, M_MENURADIO, MENU_ID_LAYOUT_TREE, 0, 1},
|
|
{0, 0, 0, M_END, 0, 0, 0},
|
|
{N_("_Network Meters"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 27 */
|
|
#define METRE_OFFSET (28)
|
|
{N_("Off"), menu_metres_off, 0, M_MENURADIO, 0, 0, 1},
|
|
{N_("Graph"), menu_metres_graph, 0, M_MENURADIO, 0, 0, 1},
|
|
{N_("Text"), menu_metres_text, 0, M_MENURADIO, 0, 0, 1},
|
|
{N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
|
|
{0, 0, 0, M_END, 0, 0, 0}, /* 32 */
|
|
{ 0, 0, 0, M_SEP, 0, 0, 0 },
|
|
{N_ ("_Fullscreen"), menu_fullscreen_toggle, 0, M_MENUTOG, MENU_ID_FULLSCREEN, 0, 1, GDK_KEY_F11},
|
|
|
|
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
|
|
{N_("_Disconnect"), menu_disconnect, ICON_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
|
|
{N_("_Reconnect"), menu_reconnect, ICON_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
|
|
{N_("_Join a Channel" ELLIPSIS), menu_join, ICON_JOIN, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
|
|
{N_("Channel _List"), menu_chanlist, ICON_CHANLIST, M_MENUSTOCK, 0, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
#define AWAY_OFFSET (41)
|
|
{N_("Marked _Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_KEY_a},
|
|
|
|
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
|
|
|
|
{N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
|
|
{N_("_Preferences"), menu_settings, ICON_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
{N_("Auto Replace"), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("CTCP Replies"), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Dialog Buttons"), menu_dlgbuttons, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Keyboard Shortcuts"), menu_keypopup, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Text Events"), menu_evtpopup, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("URL Handlers"), menu_urlhandlers, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("User Commands"), menu_usercommands, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("User List Buttons"), menu_ulbuttons, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("User List Popup"), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1}, /* 52 */
|
|
|
|
{N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
|
|
{N_("_Ban List"), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Character Chart"), ascii_open, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Direct Chat"), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("File _Transfers"), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Friends List"), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("Ignore List"), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("_Plugins and Scripts"), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
|
|
{N_("_Raw Log"), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 61 */
|
|
{N_("_URL Grabber"), url_opengui, 0, M_MENUITEM, 0, 0, 1},
|
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
|
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_m},
|
|
{N_("Move to Marker Line"), menu_movetomarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_M},
|
|
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_C},
|
|
{N_("C_lear Text"), menu_flushbuffer, ICON_CLEAR, M_MENUSTOCK, 0, 0, 1},
|
|
{N_("Save Text" ELLIPSIS), menu_savebuffer, ICON_SAVE, M_MENUSTOCK, 0, 0, 1},
|
|
#define SEARCH_OFFSET (70)
|
|
{N_("Search"), 0, ICON_SEARCH, M_MENUSUB, 0, 0, 1},
|
|
{N_("Search Text" ELLIPSIS), menu_search, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_f},
|
|
{N_("Search Next" ), menu_search_next, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_g},
|
|
{N_("Search Previous" ), menu_search_prev, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_G},
|
|
{0, 0, 0, M_END, 0, 0, 0},
|
|
|
|
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
|
|
{N_("_Contents"), menu_docs, ICON_HELP, M_MENUSTOCK, 0, 0, 1, GDK_KEY_F1},
|
|
{N_("_About"), menu_about, ICON_ABOUT, M_MENUSTOCK, 0, 0, 1},
|
|
|
|
{0, 0, 0, M_END, 0, 0, 0},
|
|
};
|
|
|
|
void
|
|
menu_set_away (session_gui *gui, int away)
|
|
{
|
|
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM (gui->menu_item[MENU_ID_AWAY]);
|
|
|
|
g_signal_handlers_block_by_func (G_OBJECT (item), menu_away, NULL);
|
|
gtk_check_menu_item_set_active (item, away);
|
|
g_signal_handlers_unblock_by_func (G_OBJECT (item), menu_away, NULL);
|
|
}
|
|
|
|
void
|
|
menu_set_fullscreen (session_gui *gui, int full)
|
|
{
|
|
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM (gui->menu_item[MENU_ID_FULLSCREEN]);
|
|
|
|
g_signal_handlers_block_by_func (G_OBJECT (item), menu_fullscreen_toggle, NULL);
|
|
gtk_check_menu_item_set_active (item, full);
|
|
g_signal_handlers_unblock_by_func (G_OBJECT (item), menu_fullscreen_toggle, NULL);
|
|
}
|
|
|
|
GtkWidget *
|
|
create_icon_menu (char *labeltext, void *stock_name, int is_stock)
|
|
{
|
|
GtkWidget *item;
|
|
#if HAVE_GTK3
|
|
GtkWidget *box;
|
|
GtkWidget *label_widget;
|
|
GtkWidget *image = NULL;
|
|
const char *icon_name;
|
|
const char *custom_icon = NULL;
|
|
const char *theme_variant = "light";
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
GtkWidget *img;
|
|
#endif
|
|
|
|
if (is_stock)
|
|
{
|
|
#if HAVE_GTK3
|
|
icon_name = stock_name;
|
|
if (g_str_has_prefix (icon_name, "zc-menu-"))
|
|
{
|
|
custom_icon = icon_name + strlen ("zc-menu-");
|
|
theme_variant = menu_icon_theme_variant ();
|
|
image = menu_icon_image_from_data_icons (custom_icon, theme_variant);
|
|
if (!image)
|
|
image = menu_icon_image_from_data_icons (custom_icon, "light");
|
|
}
|
|
|
|
if (!image)
|
|
{
|
|
icon_name = gtkutil_icon_name_from_stock (stock_name);
|
|
if (!icon_name)
|
|
icon_name = stock_name;
|
|
if (icon_name && !custom_icon)
|
|
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
|
|
}
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
img = gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if HAVE_GTK3
|
|
image = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
|
|
#endif
|
|
#if !HAVE_GTK3
|
|
img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
|
|
#endif
|
|
}
|
|
#if HAVE_GTK3
|
|
item = gtk_menu_item_new ();
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
|
label_widget = gtk_label_new_with_mnemonic (labeltext);
|
|
if (image)
|
|
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), label_widget, FALSE, FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (item), box);
|
|
if (image)
|
|
gtk_widget_show (image);
|
|
gtk_widget_show (label_widget);
|
|
gtk_widget_show (box);
|
|
#else
|
|
item = gtk_image_menu_item_new_with_mnemonic (labeltext);
|
|
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
|
|
gtk_widget_show (img);
|
|
#endif
|
|
|
|
return item;
|
|
}
|
|
|
|
/* Override the default GTK2.4 handler, which would make menu
|
|
bindings not work when the menu-bar is hidden. */
|
|
static gboolean
|
|
menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
|
|
{
|
|
/* GTK2.2 behaviour */
|
|
return gtk_widget_is_sensitive (widget);
|
|
}
|
|
|
|
/* === STUFF FOR /MENU === */
|
|
|
|
static GtkMenuItem *
|
|
menu_find_item (GtkWidget *menu, char *name)
|
|
{
|
|
GList *items;
|
|
#if HAVE_GTK3
|
|
GList *items_head;
|
|
#endif
|
|
GtkMenuItem *item;
|
|
GtkWidget *child;
|
|
const char *labeltext;
|
|
GtkMenuItem *found = NULL;
|
|
|
|
#if HAVE_GTK3
|
|
items_head = gtk_container_get_children (GTK_CONTAINER (menu));
|
|
items = items_head;
|
|
#else
|
|
items = ((GtkMenuShell *) menu)->children;
|
|
#endif
|
|
while (items)
|
|
{
|
|
item = items->data;
|
|
#if HAVE_GTK3
|
|
child = gtk_bin_get_child (GTK_BIN (item));
|
|
#else
|
|
child = GTK_BIN (item)->child;
|
|
#endif
|
|
if (child) /* separators arn't labels, skip them */
|
|
{
|
|
labeltext = g_object_get_data (G_OBJECT (item), "name");
|
|
if (!labeltext)
|
|
{
|
|
if (GTK_IS_LABEL (child))
|
|
labeltext = gtk_label_get_text (GTK_LABEL (child));
|
|
#ifdef HAVE_GTK3
|
|
else if (GTK_IS_CONTAINER (child))
|
|
{
|
|
GList *kids, *l;
|
|
kids = gtk_container_get_children (GTK_CONTAINER (child));
|
|
for (l = kids; l; l = l->next)
|
|
{
|
|
if (GTK_IS_LABEL (l->data))
|
|
{
|
|
labeltext = gtk_label_get_text (GTK_LABEL (l->data));
|
|
break;
|
|
}
|
|
}
|
|
g_list_free (kids);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (!menu_streq (labeltext, name, 1))
|
|
{
|
|
found = item;
|
|
break;
|
|
}
|
|
} else if (name == NULL)
|
|
{
|
|
found = item;
|
|
break;
|
|
}
|
|
items = items->next;
|
|
}
|
|
#if HAVE_GTK3
|
|
g_list_free (items_head);
|
|
#endif
|
|
|
|
return found;
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_find_path (GtkWidget *menu, char *path)
|
|
{
|
|
GtkMenuItem *item;
|
|
char *s;
|
|
char name[128];
|
|
int len;
|
|
|
|
/* grab the next part of the path */
|
|
s = strchr (path, '/');
|
|
len = s - path;
|
|
if (!s)
|
|
len = strlen (path);
|
|
len = MIN (len, sizeof (name) - 1);
|
|
memcpy (name, path, len);
|
|
name[len] = 0;
|
|
|
|
item = menu_find_item (menu, name);
|
|
if (!item)
|
|
return NULL;
|
|
|
|
menu = gtk_menu_item_get_submenu (item);
|
|
if (!menu)
|
|
return NULL;
|
|
|
|
path += len;
|
|
if (*path == 0)
|
|
return menu;
|
|
|
|
return menu_find_path (menu, path + 1);
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_find (GtkWidget *menu, char *path, char *label)
|
|
{
|
|
GtkWidget *item = NULL;
|
|
|
|
if (path[0] != 0)
|
|
menu = menu_find_path (menu, path);
|
|
if (menu)
|
|
item = (GtkWidget *)menu_find_item (menu, label);
|
|
return item;
|
|
}
|
|
|
|
static void
|
|
menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, char *))
|
|
{
|
|
GSList *list = sess_list;
|
|
int tabdone = FALSE;
|
|
session *sess;
|
|
|
|
if (!me->is_main)
|
|
return; /* not main menu */
|
|
|
|
while (list)
|
|
{
|
|
sess = list->data;
|
|
/* do it only once for tab sessions, since they share a GUI */
|
|
if (!sess->gui->is_tab || !tabdone)
|
|
{
|
|
callback (sess->gui->menu, me, NULL);
|
|
if (sess->gui->is_tab)
|
|
tabdone = TRUE;
|
|
}
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
|
|
{
|
|
GtkWidget *item;
|
|
|
|
item = menu_find (menu, me->path, me->label);
|
|
if (item)
|
|
{
|
|
gtk_widget_set_sensitive (item, me->enable);
|
|
/* must do it without triggering the callback */
|
|
if (GTK_IS_CHECK_MENU_ITEM (item))
|
|
#if HAVE_GTK3
|
|
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), me->state);
|
|
#else
|
|
GTK_CHECK_MENU_ITEM (item)->active = me->state;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* radio state changed via mouse click */
|
|
static void
|
|
menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
|
|
{
|
|
me->state = 0;
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (item))
|
|
#else
|
|
if (item->active)
|
|
#endif
|
|
me->state = 1;
|
|
|
|
/* update the state, incase this was changed via right-click. */
|
|
/* This will update all other windows and menu bars */
|
|
menu_foreach_gui (me, menu_update_cb);
|
|
|
|
if (me->state && me->cmd)
|
|
handle_command (current_sess, me->cmd, FALSE);
|
|
}
|
|
|
|
/* toggle state changed via mouse click */
|
|
static void
|
|
menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
|
|
{
|
|
me->state = 0;
|
|
#if HAVE_GTK3
|
|
if (gtk_check_menu_item_get_active (item))
|
|
#else
|
|
if (item->active)
|
|
#endif
|
|
me->state = 1;
|
|
|
|
/* update the state, incase this was changed via right-click. */
|
|
/* This will update all other windows and menu bars */
|
|
menu_foreach_gui (me, menu_update_cb);
|
|
|
|
if (me->state)
|
|
handle_command (current_sess, me->cmd, FALSE);
|
|
else
|
|
handle_command (current_sess, me->ucmd, FALSE);
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_radio_item (char *label, GtkWidget *menu, void *callback, void *userdata,
|
|
int state, char *groupname)
|
|
{
|
|
GtkWidget *item;
|
|
GtkMenuItem *parent;
|
|
GSList *grouplist = NULL;
|
|
|
|
parent = menu_find_item (menu, groupname);
|
|
if (parent)
|
|
grouplist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *)parent);
|
|
|
|
item = gtk_radio_menu_item_new_with_label (grouplist, label);
|
|
gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (callback), userdata);
|
|
gtk_widget_show (item);
|
|
|
|
return item;
|
|
}
|
|
|
|
static void
|
|
menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
|
|
{
|
|
if (pos == 0xffff) /* outbound.c uses this default */
|
|
return;
|
|
|
|
if (pos < 0) /* position offset from end/bottom */
|
|
#if HAVE_GTK3
|
|
{
|
|
GList *children = gtk_container_get_children (GTK_CONTAINER (menu));
|
|
int length = g_list_length (children);
|
|
|
|
g_list_free (children);
|
|
gtk_menu_reorder_child (menu, item, (length + pos) - 1);
|
|
}
|
|
#else
|
|
gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
|
|
#endif
|
|
else
|
|
gtk_menu_reorder_child (menu, item, pos);
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_add_radio (GtkWidget *menu, menu_entry *me)
|
|
{
|
|
GtkWidget *item = NULL;
|
|
char *path = me->path + me->root_offset;
|
|
|
|
if (path[0] != 0)
|
|
menu = menu_find_path (menu, path);
|
|
if (menu)
|
|
{
|
|
item = menu_radio_item (me->label, menu, menu_radio_cb, me, me->state, me->group);
|
|
menu_reorder (GTK_MENU (menu), item, me->pos);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_add_toggle (GtkWidget *menu, menu_entry *me)
|
|
{
|
|
GtkWidget *item = NULL;
|
|
char *path = me->path + me->root_offset;
|
|
|
|
if (path[0] != 0)
|
|
menu = menu_find_path (menu, path);
|
|
if (menu)
|
|
{
|
|
item = menu_toggle_item (me->label, menu, menu_toggle_cb, me, me->state);
|
|
menu_reorder (GTK_MENU (menu), item, me->pos);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_add_item (GtkWidget *menu, menu_entry *me, char *target)
|
|
{
|
|
GtkWidget *item = NULL;
|
|
char *path = me->path + me->root_offset;
|
|
|
|
if (path[0] != 0)
|
|
menu = menu_find_path (menu, path);
|
|
if (menu)
|
|
{
|
|
item = menu_quick_item (me->cmd, me->label, menu, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, target, me->icon);
|
|
menu_reorder (GTK_MENU (menu), item, me->pos);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
static GtkWidget *
|
|
menu_add_sub (GtkWidget *menu, menu_entry *me)
|
|
{
|
|
GtkWidget *item = NULL;
|
|
char *path = me->path + me->root_offset;
|
|
int pos;
|
|
|
|
if (path[0] != 0)
|
|
menu = menu_find_path (menu, path);
|
|
if (menu)
|
|
{
|
|
pos = me->pos;
|
|
if (pos < 0) /* position offset from end/bottom */
|
|
#if HAVE_GTK3
|
|
{
|
|
GList *children = gtk_container_get_children (GTK_CONTAINER (menu));
|
|
int length = g_list_length (children);
|
|
|
|
g_list_free (children);
|
|
pos = length + pos;
|
|
}
|
|
#else
|
|
pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
|
|
#endif
|
|
menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
static void
|
|
menu_del_cb (GtkWidget *menu, menu_entry *me, char *target)
|
|
{
|
|
GtkWidget *item = menu_find (menu, me->path + me->root_offset, me->label);
|
|
if (item)
|
|
gtk_widget_destroy (item);
|
|
}
|
|
|
|
static void
|
|
menu_add_cb (GtkWidget *menu, menu_entry *me, char *target)
|
|
{
|
|
GtkWidget *item;
|
|
GtkAccelGroup *accel_group;
|
|
|
|
if (me->group) /* have a group name? Must be a radio item */
|
|
item = menu_add_radio (menu, me);
|
|
else if (me->ucmd) /* have unselect-cmd? Must be a toggle item */
|
|
item = menu_add_toggle (menu, me);
|
|
else if (me->cmd || !me->label) /* label=NULL for separators */
|
|
item = menu_add_item (menu, me, target);
|
|
else
|
|
item = menu_add_sub (menu, me);
|
|
|
|
if (item)
|
|
{
|
|
gtk_widget_set_sensitive (item, me->enable);
|
|
if (me->key)
|
|
{
|
|
accel_group = g_object_get_data (G_OBJECT (menu), "accel");
|
|
if (accel_group) /* popup menus don't have them */
|
|
gtk_widget_add_accelerator (item, "activate", accel_group, me->key,
|
|
me->modifier, GTK_ACCEL_VISIBLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
char *
|
|
fe_menu_add (menu_entry *me)
|
|
{
|
|
char *text;
|
|
|
|
menu_foreach_gui (me, menu_add_cb);
|
|
|
|
if (!me->markup)
|
|
return NULL;
|
|
|
|
if (!pango_parse_markup (me->label, -1, 0, NULL, &text, NULL, NULL))
|
|
return NULL;
|
|
|
|
/* return the label with markup stripped */
|
|
return text;
|
|
}
|
|
|
|
void
|
|
fe_menu_del (menu_entry *me)
|
|
{
|
|
menu_foreach_gui (me, menu_del_cb);
|
|
}
|
|
|
|
void
|
|
fe_menu_update (menu_entry *me)
|
|
{
|
|
menu_foreach_gui (me, menu_update_cb);
|
|
}
|
|
|
|
/* used to add custom menus to the right-click menu */
|
|
|
|
static void
|
|
menu_add_plugin_mainmenu_items (GtkWidget *menu)
|
|
{
|
|
GSList *list;
|
|
menu_entry *me;
|
|
|
|
list = menu_list; /* outbound.c */
|
|
while (list)
|
|
{
|
|
me = list->data;
|
|
if (me->is_main)
|
|
menu_add_cb (menu, me, NULL);
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
void
|
|
menu_add_plugin_items (GtkWidget *menu, char *root, char *target)
|
|
{
|
|
GSList *list;
|
|
menu_entry *me;
|
|
|
|
list = menu_list; /* outbound.c */
|
|
while (list)
|
|
{
|
|
me = list->data;
|
|
if (!me->is_main && !strncmp (me->path, root + 1, root[0]))
|
|
menu_add_cb (menu, me, target);
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
/* === END STUFF FOR /MENU === */
|
|
|
|
GtkWidget *
|
|
menu_create_main (void *accel_group, int bar, int away, int toplevel,
|
|
GtkWidget **menu_widgets)
|
|
{
|
|
int i = 0;
|
|
GtkWidget *item;
|
|
GtkWidget *menu = 0;
|
|
GtkWidget *menu_item = 0;
|
|
GtkWidget *menu_bar;
|
|
GtkWidget *usermenu = 0;
|
|
GtkWidget *submenu = 0;
|
|
int close_mask = STATE_CTRL;
|
|
int away_mask = STATE_ALT;
|
|
char *key_theme = NULL;
|
|
GtkSettings *settings;
|
|
GSList *group = NULL;
|
|
#ifdef HAVE_GTK_MAC
|
|
int appmenu_offset = 1; /* 0 is for about */
|
|
#endif
|
|
|
|
if (bar)
|
|
{
|
|
menu_bar = gtk_menu_bar_new ();
|
|
#ifdef HAVE_GTK_MAC
|
|
gtkosx_application_set_menu_bar (osx_app, GTK_MENU_SHELL (menu_bar));
|
|
#endif
|
|
}
|
|
else
|
|
menu_bar = menu_new ();
|
|
|
|
/* /MENU needs to know this later */
|
|
g_object_set_data (G_OBJECT (menu_bar), "accel", accel_group);
|
|
|
|
g_signal_connect (G_OBJECT (menu_bar), "can-activate-accel",
|
|
G_CALLBACK (menu_canacaccel), 0);
|
|
|
|
/* set the initial state of toggles */
|
|
mymenu[MENUBAR_OFFSET].state = !prefs.hex_gui_hide_menu;
|
|
mymenu[MENUBAR_OFFSET+1].state = prefs.hex_gui_topicbar;
|
|
mymenu[MENUBAR_OFFSET+2].state = !prefs.hex_gui_ulist_hide;
|
|
mymenu[MENUBAR_OFFSET+3].state = prefs.hex_gui_ulist_buttons;
|
|
mymenu[MENUBAR_OFFSET+4].state = prefs.hex_gui_mode_buttons;
|
|
|
|
mymenu[AWAY_OFFSET].state = away;
|
|
|
|
switch (prefs.hex_gui_tab_layout)
|
|
{
|
|
case 0:
|
|
mymenu[TABS_OFFSET].state = 1;
|
|
mymenu[TABS_OFFSET+1].state = 0;
|
|
break;
|
|
default:
|
|
mymenu[TABS_OFFSET].state = 0;
|
|
mymenu[TABS_OFFSET+1].state = 1;
|
|
}
|
|
|
|
mymenu[METRE_OFFSET].state = 0;
|
|
mymenu[METRE_OFFSET+1].state = 0;
|
|
mymenu[METRE_OFFSET+2].state = 0;
|
|
mymenu[METRE_OFFSET+3].state = 0;
|
|
switch (prefs.hex_gui_lagometer)
|
|
{
|
|
case 0:
|
|
mymenu[METRE_OFFSET].state = 1;
|
|
break;
|
|
case 1:
|
|
mymenu[METRE_OFFSET+1].state = 1;
|
|
break;
|
|
case 2:
|
|
mymenu[METRE_OFFSET+2].state = 1;
|
|
break;
|
|
default:
|
|
mymenu[METRE_OFFSET+3].state = 1;
|
|
}
|
|
|
|
/* change Close binding to ctrl-shift-w when using emacs keys */
|
|
settings = gtk_widget_get_settings (menu_bar);
|
|
if (settings)
|
|
{
|
|
g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
|
|
if (key_theme)
|
|
{
|
|
if (!g_ascii_strcasecmp (key_theme, "Emacs"))
|
|
{
|
|
close_mask = STATE_SHIFT | STATE_CTRL;
|
|
mymenu[SEARCH_OFFSET].key = 0;
|
|
}
|
|
g_free (key_theme);
|
|
}
|
|
}
|
|
|
|
/* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
|
|
{
|
|
char *help = _("_Help");
|
|
char *under = strchr (help, '_');
|
|
if (under && (under[1] == 'a' || under[1] == 'A'))
|
|
away_mask = STATE_ALT | STATE_CTRL;
|
|
}
|
|
|
|
if (!toplevel)
|
|
{
|
|
mymenu[DETACH_OFFSET].text = N_("_Detach");
|
|
mymenu[CLOSE_OFFSET].text = N_("_Close");
|
|
}
|
|
else
|
|
{
|
|
mymenu[DETACH_OFFSET].text = N_("_Attach");
|
|
mymenu[CLOSE_OFFSET].text = N_("_Close");
|
|
}
|
|
|
|
while (1)
|
|
{
|
|
item = NULL;
|
|
if (mymenu[i].id == MENU_ID_USERMENU && !prefs.hex_gui_usermenu)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
switch (mymenu[i].type)
|
|
{
|
|
case M_NEWMENU:
|
|
if (menu)
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
|
|
item = menu = menu_new ();
|
|
if (mymenu[i].id == MENU_ID_USERMENU)
|
|
usermenu = menu;
|
|
menu_item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
|
/* record the English name for /menu */
|
|
g_object_set_data (G_OBJECT (menu_item), "name", mymenu[i].text);
|
|
#ifdef HAVE_GTK_MAC /* Added to app menu, see below */
|
|
if (!bar || mymenu[i].id != MENU_ID_ZOITECHAT)
|
|
#endif
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
|
|
gtk_widget_show (menu_item);
|
|
break;
|
|
|
|
case M_MENUPIX:
|
|
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, FALSE);
|
|
goto normalitem;
|
|
|
|
case M_MENUSTOCK:
|
|
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
|
|
goto normalitem;
|
|
|
|
case M_MENUITEM:
|
|
item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
|
normalitem:
|
|
if (mymenu[i].key != 0)
|
|
gtk_widget_add_accelerator (item, "activate", accel_group,
|
|
mymenu[i].key,
|
|
mymenu[i].key == GDK_KEY_F1 ? 0 :
|
|
mymenu[i].key == GDK_KEY_w ? close_mask :
|
|
(g_ascii_isupper (mymenu[i].key)) ?
|
|
STATE_SHIFT | STATE_CTRL :
|
|
STATE_CTRL,
|
|
GTK_ACCEL_VISIBLE);
|
|
if (mymenu[i].callback)
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (mymenu[i].callback), 0);
|
|
if (submenu)
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
|
|
else
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
gtk_widget_show (item);
|
|
break;
|
|
|
|
case M_MENUTOG:
|
|
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
|
togitem:
|
|
/* must avoid callback for Radio buttons */
|
|
#if HAVE_GTK3
|
|
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), mymenu[i].state);
|
|
#else
|
|
GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
|
|
#endif
|
|
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
|
|
mymenu[i].state);*/
|
|
if (mymenu[i].key != 0)
|
|
gtk_widget_add_accelerator (item, "activate", accel_group,
|
|
mymenu[i].key,
|
|
mymenu[i].id == MENU_ID_FULLSCREEN ? 0 :
|
|
mymenu[i].id == MENU_ID_AWAY ? away_mask :
|
|
STATE_CTRL, GTK_ACCEL_VISIBLE);
|
|
if (mymenu[i].callback)
|
|
g_signal_connect (G_OBJECT (item), "toggled",
|
|
G_CALLBACK (mymenu[i].callback), NULL);
|
|
|
|
if (submenu)
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
|
|
else
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
gtk_widget_show (item);
|
|
gtk_widget_set_sensitive (item, mymenu[i].sensitive);
|
|
break;
|
|
|
|
case M_MENURADIO:
|
|
item = gtk_radio_menu_item_new_with_mnemonic (group, _(mymenu[i].text));
|
|
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
|
|
goto togitem;
|
|
|
|
case M_SEP:
|
|
item = gtk_menu_item_new ();
|
|
gtk_widget_set_sensitive (item, FALSE);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
gtk_widget_show (item);
|
|
break;
|
|
|
|
case M_MENUSUB:
|
|
group = NULL;
|
|
submenu = menu_new ();
|
|
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
|
|
/* record the English name for /menu */
|
|
g_object_set_data (G_OBJECT (item), "name", mymenu[i].text);
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
gtk_widget_show (item);
|
|
break;
|
|
|
|
/*case M_END:*/ default:
|
|
if (!submenu)
|
|
{
|
|
if (menu)
|
|
{
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
|
|
menu_add_plugin_mainmenu_items (menu_bar);
|
|
}
|
|
if (usermenu)
|
|
usermenu_create (usermenu);
|
|
return (menu_bar);
|
|
}
|
|
submenu = NULL;
|
|
}
|
|
|
|
/* record this GtkWidget * so it's state might be changed later */
|
|
if (mymenu[i].id != 0 && menu_widgets)
|
|
/* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
|
|
menu_widgets[mymenu[i].id] = item;
|
|
|
|
#ifdef HAVE_GTK_MAC
|
|
/* We want ZoiteChat to be the app menu, not including Quit or ZoiteChat itself */
|
|
if (bar && item && i <= CLOSE_OFFSET + 1 && mymenu[i].id != MENU_ID_ZOITECHAT)
|
|
{
|
|
if (!submenu || mymenu[i].type == M_MENUSUB)
|
|
gtkosx_application_insert_app_menu_item (osx_app, item, appmenu_offset++);
|
|
}
|
|
#endif
|
|
|
|
i++;
|
|
}
|
|
}
|