2
* Copyright (C) 1998-2007 Peter Zelezny.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
31
#include <gtk/gtkhbox.h>
32
#include <gtk/gtkcheckmenuitem.h>
33
#include <gtk/gtkentry.h>
34
#include <gtk/gtkimage.h>
35
#include <gtk/gtkimagemenuitem.h>
36
#include <gtk/gtkradiomenuitem.h>
37
#include <gtk/gtklabel.h>
38
#include <gtk/gtkmessagedialog.h>
39
#include <gtk/gtkmenu.h>
40
#include <gtk/gtkmenubar.h>
41
#include <gtk/gtkstock.h>
42
#include <gtk/gtkversion.h>
43
#include <gdk/gdkkeysyms.h>
45
#include "../common/xchat.h"
46
#include "../common/xchatc.h"
47
#include "../common/cfgfiles.h"
48
#include "../common/outbound.h"
49
#include "../common/ignore.h"
50
#include "../common/fe.h"
51
#include "../common/server.h"
52
#include "../common/servlist.h"
53
#include "../common/notify.h"
54
#include "../common/util.h"
64
#include "notifygui.h"
68
#include "plugingui.h"
72
#include "userlistgui.h"
75
static GSList *submenu_list;
95
unsigned char type; /* M_XXX */
96
unsigned char id; /* MENU_ID_XXX (menu.h) */
97
unsigned char state; /* ticked or not? */
98
unsigned char sensitive; /* shaded out? */
99
guint key; /* GDK_x */
102
#define XCMENU_DOLIST 1
103
#define XCMENU_SHADED 1
104
#define XCMENU_MARKUP 2
105
#define XCMENU_MNEMONIC 4
107
/* execute a userlistbutton/popupmenu command */
110
nick_command (session * sess, char *cmd)
113
xchat_exec (cmd + 1);
115
handle_command (sess, cmd, TRUE);
118
/* fill in the %a %s %n etc and execute the command */
121
nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
124
char *host = _("Host unknown");
128
/* if (sess->type == SESS_DIALOG)
130
buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
131
buf = strrchr (buf, '@');
136
user = userlist_find (sess, nick);
137
if (user && user->hostname)
138
host = strchr (user->hostname, '@') + 1;
141
/* this can't overflow, since popup->cmd is only 256 */
142
len = strlen (cmd) + strlen (nick) + strlen (allnick) + 512;
145
auto_insert (buf, len, cmd, 0, 0, allnick, sess->channel, "",
146
server_get_network (sess->server, TRUE), host,
147
sess->server->nick, nick);
149
nick_command (sess, buf);
154
/* userlist button has been clicked */
157
userlist_button_cb (GtkWidget * button, char *cmd)
159
int i, num_sel, using_allnicks = FALSE;
160
char **nicks, *allnicks;
166
if (strstr (cmd, "%a"))
167
using_allnicks = TRUE;
169
if (sess->type == SESS_DIALOG)
171
/* fake a selection */
172
nicks = malloc (sizeof (char *) * 2);
173
nicks[0] = g_strdup (sess->channel);
178
/* find number of selected rows */
179
nicks = userlist_selection_list (sess->gui->user_tree, &num_sel);
182
nick_command_parse (sess, cmd, "", "");
187
/* create "allnicks" string */
188
allnicks = malloc (((NICKLEN + 1) * num_sel) + 1);
195
strcat (allnicks, " ");
196
strcat (allnicks, nicks[i]);
201
/* if not using "%a", execute the command once for each nickname */
203
nick_command_parse (sess, cmd, nicks[i], "");
212
nick_command_parse (sess, cmd, nick, allnicks);
218
g_free (nicks[num_sel]);
225
/* a popup-menu-item has been selected */
228
popup_menu_cb (GtkWidget * item, char *cmd)
232
/* the userdata is set in menu_quick_item() */
233
nick = g_object_get_data (G_OBJECT (item), "u");
235
if (!nick) /* userlist popup menu */
237
/* treat it just like a userlist button */
238
userlist_button_cb (NULL, cmd);
242
if (!current_sess) /* for url grabber window */
243
nick_command_parse (sess_list->data, cmd, nick, nick);
245
nick_command_parse (current_sess, cmd, nick, nick);
249
menu_toggle_item (char *label, GtkWidget *menu, void *callback, void *userdata,
254
item = gtk_check_menu_item_new_with_mnemonic (label);
255
gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
256
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
257
g_signal_connect (G_OBJECT (item), "activate",
258
G_CALLBACK (callback), userdata);
259
gtk_widget_show (item);
265
menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
266
gpointer userdata, char *icon)
268
GtkWidget *img, *item;
272
item = gtk_menu_item_new ();
277
/*if (flags & XCMENU_MARKUP)
278
item = gtk_image_menu_item_new_with_markup (label);
280
item = gtk_image_menu_item_new_with_mnemonic (label);
282
if (access (icon, R_OK) == 0) /* try fullpath */
283
img = gtk_image_new_from_file (icon);
286
/* try relative to ~/.xchat2 */
287
path = g_strdup_printf ("%s/%s", get_xdir_fs (), icon);
288
if (access (path, R_OK) == 0)
289
img = gtk_image_new_from_file (path);
291
img = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
296
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
300
if (flags & XCMENU_MARKUP)
302
item = gtk_menu_item_new_with_label ("");
303
if (flags & XCMENU_MNEMONIC)
304
gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item)->child), label);
306
gtk_label_set_markup (GTK_LABEL (GTK_BIN (item)->child), label);
309
if (flags & XCMENU_MNEMONIC)
310
item = gtk_menu_item_new_with_mnemonic (label);
312
item = gtk_menu_item_new_with_label (label);
316
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
317
g_object_set_data (G_OBJECT (item), "u", userdata);
319
g_signal_connect (G_OBJECT (item), "activate",
320
G_CALLBACK (popup_menu_cb), cmd);
321
if (flags & XCMENU_SHADED)
322
gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
323
gtk_widget_show_all (item);
329
menu_quick_item_with_callback (void *callback, char *label, GtkWidget * menu,
334
item = gtk_menu_item_new_with_label (label);
335
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
336
g_signal_connect (G_OBJECT (item), "activate",
337
G_CALLBACK (callback), arg);
338
gtk_widget_show (item);
342
menu_quick_sub (char *name, GtkWidget *menu, GtkWidget **sub_item_ret, int flags, int pos)
350
/* Code to add a submenu */
351
sub_menu = gtk_menu_new ();
352
if (flags & XCMENU_MARKUP)
354
sub_item = gtk_menu_item_new_with_label ("");
355
gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item)->child), name);
359
if (flags & XCMENU_MNEMONIC)
360
sub_item = gtk_menu_item_new_with_mnemonic (name);
362
sub_item = gtk_menu_item_new_with_label (name);
364
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), sub_item, pos);
365
gtk_widget_show (sub_item);
366
gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item), sub_menu);
369
*sub_item_ret = sub_item;
371
if (flags & XCMENU_DOLIST)
372
/* We create a new element in the list */
373
submenu_list = g_slist_prepend (submenu_list, sub_menu);
380
/* Just delete the first element in the linked list pointed to by first */
382
submenu_list = g_slist_remove (submenu_list, submenu_list->data);
385
return (submenu_list->data);
391
toggle_cb (GtkWidget *item, char *pref_name)
395
if (GTK_CHECK_MENU_ITEM (item)->active)
396
snprintf (buf, sizeof (buf), "set %s 1", pref_name);
398
snprintf (buf, sizeof (buf), "set %s 0", pref_name);
400
handle_command (current_sess, buf, FALSE);
404
is_in_path (char *cmd)
406
char *prog = strdup (cmd + 1); /* 1st char is "!" */
407
char *space, *path, *orig;
409
orig = prog; /* save for free()ing */
410
/* special-case these default entries. */
411
/* 123456789012345678 */
412
if (strncmp (prog, "gnome-terminal -x ", 18) == 0)
413
/* don't check for gnome-terminal, but the thing it's executing! */
416
space = strchr (prog, ' '); /* this isn't 100% but good enuf */
420
path = g_find_program_in_path (prog);
432
/* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
435
menu_extract_icon (char *name, char **label, char **icon)
446
if (p == name || p[-1] != '\\')
460
if (start && start != end)
462
*label = g_strndup (name, (start - name) - 1);
463
*icon = g_strndup (start, (end - start) - 1);
467
*label = g_strdup (name);
472
/* append items to "menu" using the (struct popup*) list provided */
475
menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
478
GtkWidget *tempmenu = menu, *subitem = NULL;
481
submenu_list = g_slist_prepend (0, menu);
484
pop = (struct popup *) list->data;
486
if (!strncasecmp (pop->name, "SUB", 3))
489
tempmenu = menu_quick_sub (pop->cmd, tempmenu, &subitem, XCMENU_DOLIST|XCMENU_MNEMONIC, -1);
491
} else if (!strncasecmp (pop->name, "TOGGLE", 6))
494
menu_toggle_item (pop->name + 7, tempmenu, toggle_cb, pop->cmd,
495
cfg_get_bool (pop->cmd));
497
} else if (!strncasecmp (pop->name, "ENDSUB", 6))
499
/* empty sub menu due to no programs in PATH? */
500
if (check_path && childcount < 1)
501
gtk_widget_destroy (subitem);
504
if (tempmenu != menu)
505
tempmenu = menu_quick_endsub ();
506
/* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
508
} else if (!strncasecmp (pop->name, "SEP", 3))
510
menu_quick_item (0, 0, tempmenu, XCMENU_SHADED, 0, 0);
516
/* default command in xchat.c */
517
if (pop->cmd[0] == 'n' && !strcmp (pop->cmd, "notify -n ASK %s"))
519
/* don't create this item if already in notify list */
520
if (!target || notify_is_in_list (current_sess->server, target))
527
menu_extract_icon (pop->name, &label, &icon);
529
if (!check_path || pop->cmd[0] != '!')
531
menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
532
/* check if the program is in path, if not, leave it out! */
533
} else if (is_in_path (pop->cmd))
536
menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
546
/* Let's clean up the linked list from mem */
548
submenu_list = g_slist_remove (submenu_list, submenu_list->data);
551
static char *str_copy = NULL; /* for all pop-up menus */
552
static GtkWidget *nick_submenu = NULL; /* user info submenu */
555
menu_destroy (GtkWidget *menu, gpointer objtounref)
557
gtk_widget_destroy (menu);
558
g_object_unref (menu);
560
g_object_unref (G_OBJECT (objtounref));
565
menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
567
#if (GTK_MAJOR_VERSION != 2) || (GTK_MINOR_VERSION != 0)
568
if (event && event->window)
569
gtk_menu_set_screen (GTK_MENU (menu), gdk_drawable_get_screen (event->window));
573
g_object_ref_sink (menu);
574
g_object_unref (menu);
575
g_signal_connect (G_OBJECT (menu), "selection-done",
576
G_CALLBACK (menu_destroy), objtounref);
577
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
578
0, event ? event->time : 0);
582
menu_nickinfo_cb (GtkWidget *menu, session *sess)
586
if (!is_session (sess))
590
snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
591
handle_command (sess, buf, FALSE);
592
/* and hide the output */
593
sess->server->skip_next_whois = 1;
597
copy_to_clipboard_cb (GtkWidget *item, char *url)
599
gtkutil_copy_to_clipboard (item, NULL, url);
602
/* returns boolean: Some data is missing */
605
menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
610
struct away_msg *away;
611
gboolean missing = FALSE;
614
/* let the translators tweak this if need be */
615
fmt = _("<tt><b>%-11s</b></tt> %s");
616
snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
620
real = strip_color (user->realname, -1, STRIP_ALL|STRIP_ESCMARKUP);
621
snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
625
snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
627
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
628
g_signal_connect (G_OBJECT (item), "activate",
629
G_CALLBACK (copy_to_clipboard_cb),
630
user->realname ? user->realname : unknown);
632
snprintf (buf, sizeof (buf), fmt, _("User:"),
633
user->hostname ? user->hostname : unknown);
634
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
635
g_signal_connect (G_OBJECT (item), "activate",
636
G_CALLBACK (copy_to_clipboard_cb),
637
user->hostname ? user->hostname : unknown);
639
snprintf (buf, sizeof (buf), fmt, _("Country:"),
640
user->hostname ? country(user->hostname) : unknown);
641
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
642
g_signal_connect (G_OBJECT (item), "activate",
643
G_CALLBACK (copy_to_clipboard_cb),
644
user->hostname ? country(user->hostname) : unknown);
646
snprintf (buf, sizeof (buf), fmt, _("Server:"),
647
user->servername ? user->servername : unknown);
648
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
649
g_signal_connect (G_OBJECT (item), "activate",
650
G_CALLBACK (copy_to_clipboard_cb),
651
user->servername ? user->servername : unknown);
657
snprintf (min, sizeof (min), _("%u minutes ago"),
658
(unsigned int) ((time (0) - user->lasttalk) / 60));
659
snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
662
snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
664
menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
668
away = server_away_find_message (current_sess->server, user->nick);
671
char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP);
672
snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
674
item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
675
g_signal_connect (G_OBJECT (item), "activate",
676
G_CALLBACK (copy_to_clipboard_cb),
677
away->message ? away->message : unknown);
687
fe_userlist_update (session *sess, struct User *user)
691
if (!nick_submenu || !str_copy)
694
/* not the same nick as the menu? */
695
if (sess->server->p_cmp (user->nick, str_copy))
698
/* get rid of the "show" signal */
699
g_signal_handlers_disconnect_by_func (nick_submenu, menu_nickinfo_cb, sess);
701
/* destroy all the old items */
702
items = ((GtkMenuShell *) nick_submenu)->children;
706
gtk_widget_destroy (items->data);
710
/* and re-create them with new info */
711
menu_create_nickinfo_menu (user, nick_submenu);
715
menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
719
GtkWidget *submenu, *menu = gtk_menu_new ();
723
str_copy = strdup (nick);
725
submenu_list = 0; /* first time through, might not be 0 */
727
/* more than 1 nick selected? */
730
snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
731
menu_quick_item (0, buf, menu, 0, 0, 0);
732
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
735
user = userlist_find (sess, nick); /* lasttalk is channel specific */
737
user = userlist_find_global (current_sess->server, nick);
740
nick_submenu = submenu = menu_quick_sub (nick, menu, NULL, XCMENU_DOLIST, -1);
742
if (menu_create_nickinfo_menu (user, submenu) ||
743
!user->hostname || !user->realname || !user->servername)
745
g_signal_connect (G_OBJECT (submenu), "show", G_CALLBACK (menu_nickinfo_cb), sess);
748
menu_quick_endsub ();
749
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
754
menu_create (menu, popup_list, NULL, FALSE);
756
menu_create (menu, popup_list, str_copy, FALSE);
758
if (num_sel == 0) /* xtext click */
759
menu_add_plugin_items (menu, "\x5$NICK", str_copy);
760
else /* userlist treeview click */
761
menu_add_plugin_items (menu, "\x5$NICK", NULL);
763
menu_popup (menu, event, NULL);
766
/* stuff for the View menu */
769
menu_showhide_cb (session *sess)
772
gtk_widget_hide (sess->gui->menu);
774
gtk_widget_show (sess->gui->menu);
778
menu_topic_showhide_cb (session *sess)
781
gtk_widget_show (sess->gui->topic_bar);
783
gtk_widget_hide (sess->gui->topic_bar);
787
menu_userlist_showhide_cb (session *sess)
789
mg_decide_userlist (sess, TRUE);
793
menu_ulbuttons_showhide_cb (session *sess)
795
if (prefs.userlistbuttons)
796
gtk_widget_show (sess->gui->button_box);
798
gtk_widget_hide (sess->gui->button_box);
802
menu_cmbuttons_showhide_cb (session *sess)
807
if (prefs.chanmodebuttons)
808
gtk_widget_show (sess->gui->topicbutton_box);
810
gtk_widget_hide (sess->gui->topicbutton_box);
813
gtk_widget_hide (sess->gui->topicbutton_box);
818
menu_setting_foreach (void (*callback) (session *), int id, guint state)
822
int maindone = FALSE; /* do it only once for EVERY tab */
829
if (!sess->gui->is_tab || !maindone)
831
if (sess->gui->is_tab)
834
GTK_CHECK_MENU_ITEM (sess->gui->menu_item[id])->active = state;
844
menu_bar_toggle (void)
846
prefs.hidemenu = !prefs.hidemenu;
847
menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hidemenu);
851
menu_bar_toggle_cb (void)
855
fe_message (_("The Menubar is now hidden. You can show it again"
856
" by pressing F9 or right-clicking in a blank part of"
857
" the main text area."), FE_MSG_INFO);
861
menu_topicbar_toggle (GtkWidget *wid, gpointer ud)
863
prefs.topicbar = !prefs.topicbar;
864
menu_setting_foreach (menu_topic_showhide_cb, MENU_ID_TOPICBAR,
869
menu_userlist_toggle (GtkWidget *wid, gpointer ud)
871
prefs.hideuserlist = !prefs.hideuserlist;
872
menu_setting_foreach (menu_userlist_showhide_cb, MENU_ID_USERLIST,
873
!prefs.hideuserlist);
877
menu_ulbuttons_toggle (GtkWidget *wid, gpointer ud)
879
prefs.userlistbuttons = !prefs.userlistbuttons;
880
menu_setting_foreach (menu_ulbuttons_showhide_cb, MENU_ID_ULBUTTONS,
881
prefs.userlistbuttons);
885
menu_cmbuttons_toggle (GtkWidget *wid, gpointer ud)
887
prefs.chanmodebuttons = !prefs.chanmodebuttons;
888
menu_setting_foreach (menu_cmbuttons_showhide_cb, MENU_ID_MODEBUTTONS,
889
prefs.chanmodebuttons);
893
menu_middlemenu (session *sess, GdkEventButton *event)
896
GtkAccelGroup *accel_group;
898
accel_group = gtk_accel_group_new ();
899
menu = menu_create_main (accel_group, FALSE, sess->server->is_away, !sess->gui->is_tab, NULL);
900
menu_popup (menu, event, accel_group);
904
open_url_cb (GtkWidget *item, char *url)
908
/* pass this to /URL so it can handle irc:// */
909
snprintf (buf, sizeof (buf), "URL %s", url);
910
handle_command (current_sess, buf, FALSE);
914
menu_urlmenu (GdkEventButton *event, char *url)
921
str_copy = strdup (url);
923
menu = gtk_menu_new ();
924
/* more than 51 chars? Chop it */
925
if (g_utf8_strlen (str_copy, -1) >= 52)
927
tmp = strdup (str_copy);
928
chop = g_utf8_offset_to_pointer (tmp, 48);
929
chop[0] = chop[1] = chop[2] = '.';
931
menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
935
menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
937
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
939
/* Two hardcoded entries */
940
if (strncmp (str_copy, "irc://", 6) == 0 ||
941
strncmp (str_copy, "ircs://",7) == 0)
942
menu_quick_item_with_callback (open_url_cb, _("Connect"), menu, str_copy);
944
menu_quick_item_with_callback (open_url_cb, _("Open Link in Browser"), menu, str_copy);
945
menu_quick_item_with_callback (copy_to_clipboard_cb, _("Copy Selected Link"), menu, str_copy);
946
/* custom ones from urlhandlers.conf */
947
menu_create (menu, urlhandler_list, str_copy, TRUE);
948
menu_add_plugin_items (menu, "\x4$URL", str_copy);
949
menu_popup (menu, event, NULL);
953
menu_chan_cycle (GtkWidget * menu, char *chan)
959
snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
960
handle_command (current_sess, tbuf, FALSE);
965
menu_chan_part (GtkWidget * menu, char *chan)
971
snprintf (tbuf, sizeof tbuf, "part %s", chan);
972
handle_command (current_sess, tbuf, FALSE);
977
menu_chan_join (GtkWidget * menu, char *chan)
983
snprintf (tbuf, sizeof tbuf, "join %s", chan);
984
handle_command (current_sess, tbuf, FALSE);
989
menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
992
int is_joined = FALSE;
994
if (find_channel (sess->server, chan))
999
str_copy = strdup (chan);
1001
menu = gtk_menu_new ();
1003
menu_quick_item (0, chan, menu, XCMENU_SHADED, str_copy, 0);
1004
menu_quick_item (0, 0, menu, XCMENU_SHADED, str_copy, 0);
1007
menu_quick_item_with_callback (menu_chan_join, _("Join Channel"), menu,
1011
menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
1013
menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
1017
menu_addfavoritemenu (sess->server, menu, str_copy);
1019
menu_add_plugin_items (menu, "\x5$CHAN", str_copy);
1020
menu_popup (menu, event, NULL);
1024
menu_delfav_cb (GtkWidget *item, server *serv)
1026
servlist_autojoinedit (serv->network, str_copy, FALSE);
1030
menu_addfav_cb (GtkWidget *item, server *serv)
1032
servlist_autojoinedit (serv->network, str_copy, TRUE);
1036
menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel)
1041
if (channel != str_copy)
1045
str_copy = strdup (channel);
1048
if (joinlist_is_in_list (serv, channel))
1049
mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE, menu, menu_delfav_cb, serv);
1051
mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD, menu, menu_addfav_cb, serv);
1055
menu_open_server_list (GtkWidget *wid, gpointer none)
1057
fe_serverlist_open (current_sess);
1061
menu_settings (GtkWidget * wid, gpointer none)
1063
extern void setup_open (void);
1068
menu_usermenu (void)
1070
editlist_gui_open (NULL, NULL, usermenu_list, _("XChat: User menu"),
1071
"usermenu", "usermenu.conf", 0);
1075
usermenu_create (GtkWidget *menu)
1077
menu_create (menu, usermenu_list, "", FALSE);
1078
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0); /* sep */
1079
menu_quick_item_with_callback (menu_usermenu, _("Edit This Menu..."), menu, 0);
1083
usermenu_destroy (GtkWidget * menu)
1085
GList *items = ((GtkMenuShell *) menu)->children;
1091
gtk_widget_destroy (items->data);
1097
usermenu_update (void)
1099
int done_main = FALSE;
1100
GSList *list = sess_list;
1107
menu = sess->gui->menu_item[MENU_ID_USERMENU];
1108
if (sess->gui->is_tab)
1110
if (!done_main && menu)
1112
usermenu_destroy (menu);
1113
usermenu_create (menu);
1118
usermenu_destroy (menu);
1119
usermenu_create (menu);
1126
menu_newserver_window (GtkWidget * wid, gpointer none)
1128
int old = prefs.tabchannels;
1130
prefs.tabchannels = 0;
1131
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1132
prefs.tabchannels = old;
1136
menu_newchannel_window (GtkWidget * wid, gpointer none)
1138
int old = prefs.tabchannels;
1140
prefs.tabchannels = 0;
1141
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1142
prefs.tabchannels = old;
1146
menu_newserver_tab (GtkWidget * wid, gpointer none)
1148
int old = prefs.tabchannels;
1149
int oldf = prefs.newtabstofront;
1151
prefs.tabchannels = 1;
1152
/* force focus if setting is "only requested tabs" */
1153
if (prefs.newtabstofront == 2)
1154
prefs.newtabstofront = 1;
1155
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1156
prefs.tabchannels = old;
1157
prefs.newtabstofront = oldf;
1161
menu_newchannel_tab (GtkWidget * wid, gpointer none)
1163
int old = prefs.tabchannels;
1165
prefs.tabchannels = 1;
1166
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1167
prefs.tabchannels = old;
1171
menu_rawlog (GtkWidget * wid, gpointer none)
1173
open_rawlog (current_sess->server);
1177
menu_detach (GtkWidget * wid, gpointer none)
1179
mg_detach (current_sess, 0);
1183
menu_close (GtkWidget * wid, gpointer none)
1185
mg_close_sess (current_sess);
1189
menu_quit (GtkWidget * wid, gpointer none)
1191
mg_open_quit_dialog (FALSE);
1197
search_open (current_sess);
1201
menu_resetmarker (GtkWidget * wid, gpointer none)
1203
gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
1207
menu_flushbuffer (GtkWidget * wid, gpointer none)
1209
fe_text_clear (current_sess, 0);
1213
savebuffer_req_done (session *sess, char *file)
1220
fh = open (file, O_TRUNC | O_WRONLY | O_CREAT, 0600);
1223
gtk_xtext_save (GTK_XTEXT (sess->gui->xtext), fh);
1229
menu_savebuffer (GtkWidget * wid, gpointer none)
1231
gtkutil_file_req (_("Select an output filename"), savebuffer_req_done,
1232
current_sess, NULL, FRF_WRITE);
1236
menu_disconnect (GtkWidget * wid, gpointer none)
1238
handle_command (current_sess, "DISCON", FALSE);
1242
menu_reconnect (GtkWidget * wid, gpointer none)
1244
if (current_sess->server->hostname[0])
1245
handle_command (current_sess, "RECONNECT", FALSE);
1247
fe_serverlist_open (current_sess);
1251
menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
1255
case GTK_RESPONSE_ACCEPT:
1256
menu_chan_join (NULL, entry->text);
1259
case GTK_RESPONSE_HELP:
1260
chanlist_opengui (current_sess->server, TRUE);
1264
gtk_widget_destroy (dialog);
1268
menu_join_entry_cb (GtkWidget *entry, GtkDialog *dialog)
1270
gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
1274
menu_join (GtkWidget * wid, gpointer none)
1276
GtkWidget *hbox, *dialog, *entry, *label;
1278
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
1279
GTK_WINDOW (parent_window), 0,
1280
_("Retrieve channel list..."), GTK_RESPONSE_HELP,
1281
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1282
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1284
gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
1285
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1286
hbox = gtk_hbox_new (TRUE, 0);
1288
entry = gtk_entry_new ();
1289
GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
1290
gtk_entry_set_text (GTK_ENTRY (entry), "#");
1291
g_signal_connect (G_OBJECT (entry), "activate",
1292
G_CALLBACK (menu_join_entry_cb), dialog);
1293
gtk_box_pack_end (GTK_BOX (hbox), entry, 0, 0, 0);
1295
label = gtk_label_new (_("Enter Channel to Join:"));
1296
gtk_box_pack_end (GTK_BOX (hbox), label, 0, 0, 0);
1298
g_signal_connect (G_OBJECT (dialog), "response",
1299
G_CALLBACK (menu_join_cb), entry);
1301
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1303
gtk_widget_show_all (dialog);
1305
gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
1306
gtk_editable_set_position (GTK_EDITABLE (entry), 1);
1310
menu_away (GtkCheckMenuItem *item, gpointer none)
1312
handle_command (current_sess, item->active ? "away" : "back", FALSE);
1316
menu_chanlist (GtkWidget * wid, gpointer none)
1318
chanlist_opengui (current_sess->server, FALSE);
1322
menu_banlist (GtkWidget * wid, gpointer none)
1324
banlist_opengui (current_sess);
1330
menu_loadplugin (void)
1336
menu_pluginlist (void)
1343
#define menu_pluginlist 0
1344
#define menu_loadplugin 0
1348
#define usercommands_help _("User Commands - Special codes:\n\n"\
1349
"%c = current channel\n"\
1350
"%e = current network name\n"\
1351
"%m = machine info\n"\
1354
"%v = xchat version\n"\
1357
"&2 = word 2 to the end of line\n"\
1358
"&3 = word 3 to the end of line\n\n"\
1360
"/cmd john hello\n\n"\
1361
"%2 would be \042john\042\n"\
1362
"&2 would be \042john hello\042.")
1364
#define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1365
"%a = all selected nicks\n"\
1366
"%c = current channel\n"\
1367
"%e = current network name\n"\
1368
"%h = selected nick's hostname\n"\
1369
"%m = machine info\n"\
1371
"%s = selected nick\n"\
1374
#define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1375
"%a = all selected nicks\n"\
1376
"%c = current channel\n"\
1377
"%e = current network name\n"\
1378
"%h = selected nick's hostname\n"\
1379
"%m = machine info\n"\
1381
"%s = selected nick\n"\
1384
#define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1385
"%d = data (the whole ctcp)\n"\
1386
"%e = current network name\n"\
1387
"%m = machine info\n"\
1388
"%s = nick who sent the ctcp\n"\
1392
"&2 = word 2 to the end of line\n"\
1393
"&3 = word 3 to the end of line\n\n")
1395
#define url_help _("URL Handlers - Special codes:\n\n"\
1396
"%s = the URL string\n\n"\
1397
"Putting a ! infront of the command\n"\
1398
"indicates it should be sent to a\n"\
1399
"shell instead of XChat")
1402
menu_usercommands (void)
1404
editlist_gui_open (NULL, NULL, command_list, _("XChat: User Defined Commands"),
1405
"commands", "commands.conf", usercommands_help);
1411
editlist_gui_open (NULL, NULL, popup_list, _("XChat: Userlist Popup menu"), "popup",
1412
"popup.conf", ulbutton_help);
1418
editlist_gui_open (_("Text"), _("Replace with"), replace_list, _("XChat: Replace"), "replace",
1423
menu_urlhandlers (void)
1425
editlist_gui_open (NULL, NULL, urlhandler_list, _("XChat: URL Handlers"), "urlhandlers",
1426
"urlhandlers.conf", url_help);
1430
menu_evtpopup (void)
1432
pevent_dialog_show ();
1436
menu_keypopup (void)
1442
menu_ulbuttons (void)
1444
editlist_gui_open (NULL, NULL, button_list, _("XChat: Userlist buttons"), "buttons",
1445
"buttons.conf", ulbutton_help);
1449
menu_dlgbuttons (void)
1451
editlist_gui_open (NULL, NULL, dlgbutton_list, _("XChat: Dialog buttons"), "dlgbuttons",
1452
"dlgbuttons.conf", dlgbutton_help);
1456
menu_ctcpguiopen (void)
1458
editlist_gui_open (NULL, NULL, ctcp_list, _("XChat: CTCP Replies"), "ctcpreply",
1459
"ctcpreply.conf", ctcp_help);
1463
menu_docs (GtkWidget *wid, gpointer none)
1465
fe_open_url ("http://xchat.org/docs/");
1469
menu_webpage (GtkWidget *wid, gpointer none)
1471
fe_open_url ("http://xchat.org");
1475
menu_dcc_win (GtkWidget *wid, gpointer none)
1477
fe_dcc_open_recv_win (FALSE);
1478
fe_dcc_open_send_win (FALSE);
1482
menu_dcc_chat_win (GtkWidget *wid, gpointer none)
1484
fe_dcc_open_chat_win (FALSE);
1488
menu_change_layout (void)
1490
if (prefs.tab_layout == 0)
1492
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 1);
1493
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 0);
1494
mg_change_layout (0);
1497
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 0);
1498
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 1);
1499
mg_change_layout (2);
1504
menu_layout_cb (GtkWidget *item, gpointer none)
1506
prefs.tab_layout = 2;
1507
if (GTK_CHECK_MENU_ITEM (item)->active)
1508
prefs.tab_layout = 0;
1510
menu_change_layout ();
1514
menu_apply_metres_cb (session *sess)
1516
mg_update_meters (sess->gui);
1520
menu_metres_off (GtkWidget *item, gpointer none)
1522
if (GTK_CHECK_MENU_ITEM (item)->active)
1524
prefs.lagometer = 0;
1525
prefs.throttlemeter = 0;
1526
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1531
menu_metres_text (GtkWidget *item, gpointer none)
1533
if (GTK_CHECK_MENU_ITEM (item)->active)
1535
prefs.lagometer = 2;
1536
prefs.throttlemeter = 2;
1537
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1542
menu_metres_graph (GtkWidget *item, gpointer none)
1544
if (GTK_CHECK_MENU_ITEM (item)->active)
1546
prefs.lagometer = 1;
1547
prefs.throttlemeter = 1;
1548
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1553
menu_metres_both (GtkWidget *item, gpointer none)
1555
if (GTK_CHECK_MENU_ITEM (item)->active)
1557
prefs.lagometer = 3;
1558
prefs.throttlemeter = 3;
1559
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1563
static struct mymenu mymenu[] = {
1564
{N_("_XChat"), 0, 0, M_NEWMENU, 0, 0, 1},
1565
{N_("Network Li_st..."), menu_open_server_list, (char *)&pix_book, M_MENUPIX, 0, 0, 1, GDK_s},
1566
{0, 0, 0, M_SEP, 0, 0, 0},
1568
{N_("_New"), 0, GTK_STOCK_NEW, M_MENUSUB, 0, 0, 1},
1569
{N_("Server Tab..."), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_t},
1570
{N_("Channel Tab..."), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
1571
{N_("Server Window..."), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1},
1572
{N_("Channel Window..."), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
1573
{0, 0, 0, M_END, 0, 0, 0},
1574
{0, 0, 0, M_SEP, 0, 0, 0},
1577
{N_("_Load Plugin or Script..."), menu_loadplugin, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 1},
1579
{N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 0},
1581
{0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
1582
#define DETACH_OFFSET (12)
1583
{0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_I}, /* 12 */
1584
#define CLOSE_OFFSET (13)
1585
{0, menu_close, GTK_STOCK_CLOSE, M_MENUSTOCK, 0, 0, 1, GDK_w},
1586
{0, 0, 0, M_SEP, 0, 0, 0},
1587
{N_("_Quit"), menu_quit, GTK_STOCK_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_q}, /* 15 */
1589
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
1590
#define MENUBAR_OFFSET (17)
1591
{N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_F9},
1592
{N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
1593
{N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_F7},
1594
{N_("U_serlist Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
1595
{N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
1596
{0, 0, 0, M_SEP, 0, 0, 0},
1597
{N_("_Channel Switcher"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 23 */
1598
#define TABS_OFFSET (24)
1599
{N_("_Tabs"), menu_layout_cb, 0, M_MENURADIO, MENU_ID_LAYOUT_TABS, 0, 1},
1600
{N_("T_ree"), 0, 0, M_MENURADIO, MENU_ID_LAYOUT_TREE, 0, 1},
1601
{0, 0, 0, M_END, 0, 0, 0},
1602
{N_("_Network Meters"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 27 */
1603
#define METRE_OFFSET (28)
1604
{N_("Off"), menu_metres_off, 0, M_MENURADIO, 0, 0, 1},
1605
{N_("Graph"), menu_metres_graph, 0, M_MENURADIO, 0, 0, 1},
1606
{N_("Text"), menu_metres_text, 0, M_MENURADIO, 0, 0, 1},
1607
{N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
1608
{0, 0, 0, M_END, 0, 0, 0}, /* 32 */
1610
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
1611
{N_("_Disconnect"), menu_disconnect, GTK_STOCK_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
1612
{N_("_Reconnect"), menu_reconnect, GTK_STOCK_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
1613
{N_("Join a Channel..."), menu_join, GTK_STOCK_JUMP_TO, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
1614
{N_("List of Channels..."), menu_chanlist, GTK_STOCK_INDEX, M_MENUITEM, 0, 0, 1},
1615
{0, 0, 0, M_SEP, 0, 0, 0},
1616
#define AWAY_OFFSET (39)
1617
{N_("Marked Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_a},
1619
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
1621
{N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
1622
{N_("_Preferences"), menu_settings, GTK_STOCK_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
1624
{N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
1625
{N_("Auto Replace..."), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
1626
{N_("CTCP Replies..."), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
1627
{N_("Dialog Buttons..."), menu_dlgbuttons, 0, M_MENUITEM, 0, 0, 1},
1628
{N_("Keyboard Shortcuts..."), menu_keypopup, 0, M_MENUITEM, 0, 0, 1},
1629
{N_("Text Events..."), menu_evtpopup, 0, M_MENUITEM, 0, 0, 1},
1630
{N_("URL Handlers..."), menu_urlhandlers, 0, M_MENUITEM, 0, 0, 1},
1631
{N_("User Commands..."), menu_usercommands, 0, M_MENUITEM, 0, 0, 1},
1632
{N_("Userlist Buttons..."), menu_ulbuttons, 0, M_MENUITEM, 0, 0, 1},
1633
{N_("Userlist Popup..."), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1},
1634
{0, 0, 0, M_END, 0, 0, 0}, /* 53 */
1636
{N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
1637
{N_("Ban List..."), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
1638
{N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
1639
{N_("Direct Chat..."), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
1640
{N_("File Transfers..."), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
1641
{N_("Friends List..."), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
1642
{N_("Ignore List..."), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
1643
{N_("Plugins and Scripts..."), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
1644
{N_("Raw Log..."), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 62 */
1645
{N_("URL Grabber..."), url_opengui, 0, M_MENUITEM, 0, 0, 1},
1646
{0, 0, 0, M_SEP, 0, 0, 0},
1647
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
1648
{N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
1649
#define SEARCH_OFFSET 67
1650
{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
1651
{N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
1653
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 69 */
1654
{N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
1656
{N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},
1658
{N_("_About"), menu_about, GTK_STOCK_ABOUT, M_MENUSTOCK, 0, 0, 1},
1660
{0, 0, 0, M_END, 0, 0, 0},
1664
create_icon_menu (char *labeltext, void *stock_name, int is_stock)
1666
GtkWidget *item, *img;
1669
img = gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
1671
img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
1672
item = gtk_image_menu_item_new_with_mnemonic (labeltext);
1673
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
1674
gtk_widget_show (img);
1679
#if GTK_CHECK_VERSION(2,4,0)
1681
/* Override the default GTK2.4 handler, which would make menu
1682
bindings not work when the menu-bar is hidden. */
1684
menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
1686
/* GTK2.2 behaviour */
1687
#if GTK_CHECK_VERSION(2,20,0)
1688
return gtk_widget_is_sensitive (widget);
1690
return GTK_WIDGET_IS_SENSITIVE (widget);
1697
/* === STUFF FOR /MENU === */
1699
static GtkMenuItem *
1700
menu_find_item (GtkWidget *menu, char *name)
1702
GList *items = ((GtkMenuShell *) menu)->children;
1705
const char *labeltext;
1710
child = GTK_BIN (item)->child;
1711
if (child) /* separators arn't labels, skip them */
1713
labeltext = g_object_get_data (G_OBJECT (item), "name");
1715
labeltext = gtk_label_get_text (GTK_LABEL (child));
1716
if (!menu_streq (labeltext, name, 1))
1718
} else if (name == NULL)
1722
items = items->next;
1729
menu_find_path (GtkWidget *menu, char *path)
1736
/* grab the next part of the path */
1737
s = strchr (path, '/');
1740
len = strlen (path);
1741
len = MIN (len, sizeof (name) - 1);
1742
memcpy (name, path, len);
1745
item = menu_find_item (menu, name);
1749
menu = gtk_menu_item_get_submenu (item);
1757
return menu_find_path (menu, path + 1);
1761
menu_find (GtkWidget *menu, char *path, char *label)
1763
GtkWidget *item = NULL;
1766
menu = menu_find_path (menu, path);
1768
item = (GtkWidget *)menu_find_item (menu, label);
1773
menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, char *))
1775
GSList *list = sess_list;
1776
int tabdone = FALSE;
1780
return; /* not main menu */
1785
/* do it only once for tab sessions, since they share a GUI */
1786
if (!sess->gui->is_tab || !tabdone)
1788
callback (sess->gui->menu, me, NULL);
1789
if (sess->gui->is_tab)
1797
menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
1801
item = menu_find (menu, me->path, me->label);
1804
gtk_widget_set_sensitive (item, me->enable);
1805
/* must do it without triggering the callback */
1806
if (GTK_IS_CHECK_MENU_ITEM (item))
1807
GTK_CHECK_MENU_ITEM (item)->active = me->state;
1811
/* radio state changed via mouse click */
1813
menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
1819
/* update the state, incase this was changed via right-click. */
1820
/* This will update all other windows and menu bars */
1821
menu_foreach_gui (me, menu_update_cb);
1823
if (me->state && me->cmd)
1824
handle_command (current_sess, me->cmd, FALSE);
1827
/* toggle state changed via mouse click */
1829
menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
1835
/* update the state, incase this was changed via right-click. */
1836
/* This will update all other windows and menu bars */
1837
menu_foreach_gui (me, menu_update_cb);
1840
handle_command (current_sess, me->cmd, FALSE);
1842
handle_command (current_sess, me->ucmd, FALSE);
1846
menu_radio_item (char *label, GtkWidget *menu, void *callback, void *userdata,
1847
int state, char *groupname)
1850
GtkMenuItem *parent;
1851
GSList *grouplist = NULL;
1853
parent = menu_find_item (menu, groupname);
1855
grouplist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *)parent);
1857
item = gtk_radio_menu_item_new_with_label (grouplist, label);
1858
gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
1859
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1860
g_signal_connect (G_OBJECT (item), "activate",
1861
G_CALLBACK (callback), userdata);
1862
gtk_widget_show (item);
1868
menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
1870
if (pos == 0xffff) /* outbound.c uses this default */
1873
if (pos < 0) /* position offset from end/bottom */
1874
gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
1876
gtk_menu_reorder_child (menu, item, pos);
1880
menu_add_radio (GtkWidget *menu, menu_entry *me)
1882
GtkWidget *item = NULL;
1883
char *path = me->path + me->root_offset;
1886
menu = menu_find_path (menu, path);
1889
item = menu_radio_item (me->label, menu, menu_radio_cb, me, me->state, me->group);
1890
menu_reorder (GTK_MENU (menu), item, me->pos);
1896
menu_add_toggle (GtkWidget *menu, menu_entry *me)
1898
GtkWidget *item = NULL;
1899
char *path = me->path + me->root_offset;
1902
menu = menu_find_path (menu, path);
1905
item = menu_toggle_item (me->label, menu, menu_toggle_cb, me, me->state);
1906
menu_reorder (GTK_MENU (menu), item, me->pos);
1912
menu_add_item (GtkWidget *menu, menu_entry *me, char *target)
1914
GtkWidget *item = NULL;
1915
char *path = me->path + me->root_offset;
1918
menu = menu_find_path (menu, path);
1921
item = menu_quick_item (me->cmd, me->label, menu, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, target, me->icon);
1922
menu_reorder (GTK_MENU (menu), item, me->pos);
1928
menu_add_sub (GtkWidget *menu, menu_entry *me)
1930
GtkWidget *item = NULL;
1931
char *path = me->path + me->root_offset;
1935
menu = menu_find_path (menu, path);
1939
if (pos < 0) /* position offset from end/bottom */
1940
pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
1941
menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
1947
menu_del_cb (GtkWidget *menu, menu_entry *me, char *target)
1949
GtkWidget *item = menu_find (menu, me->path + me->root_offset, me->label);
1951
gtk_widget_destroy (item);
1955
menu_add_cb (GtkWidget *menu, menu_entry *me, char *target)
1958
GtkAccelGroup *accel_group;
1960
if (me->group) /* have a group name? Must be a radio item */
1961
item = menu_add_radio (menu, me);
1962
else if (me->ucmd) /* have unselect-cmd? Must be a toggle item */
1963
item = menu_add_toggle (menu, me);
1964
else if (me->cmd || !me->label) /* label=NULL for separators */
1965
item = menu_add_item (menu, me, target);
1967
item = menu_add_sub (menu, me);
1971
gtk_widget_set_sensitive (item, me->enable);
1974
accel_group = g_object_get_data (G_OBJECT (menu), "accel");
1975
if (accel_group) /* popup menus don't have them */
1976
gtk_widget_add_accelerator (item, "activate", accel_group, me->key,
1977
me->modifier, GTK_ACCEL_VISIBLE);
1983
fe_menu_add (menu_entry *me)
1987
menu_foreach_gui (me, menu_add_cb);
1992
if (!pango_parse_markup (me->label, -1, 0, NULL, &text, NULL, NULL))
1995
/* return the label with markup stripped */
2000
fe_menu_del (menu_entry *me)
2002
menu_foreach_gui (me, menu_del_cb);
2006
fe_menu_update (menu_entry *me)
2008
menu_foreach_gui (me, menu_update_cb);
2011
/* used to add custom menus to the right-click menu */
2014
menu_add_plugin_mainmenu_items (GtkWidget *menu)
2019
list = menu_list; /* outbound.c */
2024
menu_add_cb (menu, me, NULL);
2030
menu_add_plugin_items (GtkWidget *menu, char *root, char *target)
2035
list = menu_list; /* outbound.c */
2039
if (!me->is_main && !strncmp (me->path, root + 1, root[0]))
2040
menu_add_cb (menu, me, target);
2045
/* === END STUFF FOR /MENU === */
2048
menu_create_main (void *accel_group, int bar, int away, int toplevel,
2049
GtkWidget **menu_widgets)
2053
GtkWidget *menu = 0;
2054
GtkWidget *menu_item = 0;
2055
GtkWidget *menu_bar;
2056
GtkWidget *usermenu = 0;
2057
GtkWidget *submenu = 0;
2058
int close_mask = GDK_CONTROL_MASK;
2059
int away_mask = GDK_MOD1_MASK;
2060
char *key_theme = NULL;
2061
GtkSettings *settings;
2062
GSList *group = NULL;
2065
menu_bar = gtk_menu_bar_new ();
2067
menu_bar = gtk_menu_new ();
2069
/* /MENU needs to know this later */
2070
g_object_set_data (G_OBJECT (menu_bar), "accel", accel_group);
2072
#if GTK_CHECK_VERSION(2,4,0)
2073
g_signal_connect (G_OBJECT (menu_bar), "can-activate-accel",
2074
G_CALLBACK (menu_canacaccel), 0);
2077
/* set the initial state of toggles */
2078
mymenu[MENUBAR_OFFSET].state = !prefs.hidemenu;
2079
mymenu[MENUBAR_OFFSET+1].state = prefs.topicbar;
2080
mymenu[MENUBAR_OFFSET+2].state = !prefs.hideuserlist;
2081
mymenu[MENUBAR_OFFSET+3].state = prefs.userlistbuttons;
2082
mymenu[MENUBAR_OFFSET+4].state = prefs.chanmodebuttons;
2084
mymenu[AWAY_OFFSET].state = away;
2086
switch (prefs.tab_layout)
2089
mymenu[TABS_OFFSET].state = 1;
2090
mymenu[TABS_OFFSET+1].state = 0;
2093
mymenu[TABS_OFFSET].state = 0;
2094
mymenu[TABS_OFFSET+1].state = 1;
2097
mymenu[METRE_OFFSET].state = 0;
2098
mymenu[METRE_OFFSET+1].state = 0;
2099
mymenu[METRE_OFFSET+2].state = 0;
2100
mymenu[METRE_OFFSET+3].state = 0;
2101
switch (prefs.lagometer)
2104
mymenu[METRE_OFFSET].state = 1;
2107
mymenu[METRE_OFFSET+1].state = 1;
2110
mymenu[METRE_OFFSET+2].state = 1;
2113
mymenu[METRE_OFFSET+3].state = 1;
2116
/* change Close binding to ctrl-shift-w when using emacs keys */
2117
settings = gtk_widget_get_settings (menu_bar);
2120
g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
2123
if (!strcasecmp (key_theme, "Emacs"))
2125
close_mask = GDK_SHIFT_MASK | GDK_CONTROL_MASK;
2126
mymenu[SEARCH_OFFSET].key = 0;
2132
/* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2134
char *help = _("_Help");
2135
char *under = strchr (help, '_');
2136
if (under && (under[1] == 'a' || under[1] == 'A'))
2137
away_mask = GDK_MOD1_MASK | GDK_CONTROL_MASK;
2142
mymenu[DETACH_OFFSET].text = N_("_Detach");
2143
mymenu[CLOSE_OFFSET].text = N_("_Close");
2147
mymenu[DETACH_OFFSET].text = N_("_Attach");
2148
mymenu[CLOSE_OFFSET].text = N_("_Close");
2154
if (mymenu[i].id == MENU_ID_USERMENU && !prefs.gui_usermenu)
2160
switch (mymenu[i].type)
2164
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2165
item = menu = gtk_menu_new ();
2166
if (mymenu[i].id == MENU_ID_USERMENU)
2168
menu_item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2169
/* record the English name for /menu */
2170
g_object_set_data (G_OBJECT (menu_item), "name", mymenu[i].text);
2171
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
2172
gtk_widget_show (menu_item);
2176
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, FALSE);
2180
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2184
item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2186
if (mymenu[i].key != 0)
2187
gtk_widget_add_accelerator (item, "activate", accel_group,
2189
mymenu[i].key == GDK_F1 ? 0 :
2190
mymenu[i].key == GDK_w ? close_mask :
2193
if (mymenu[i].callback)
2194
g_signal_connect (G_OBJECT (item), "activate",
2195
G_CALLBACK (mymenu[i].callback), 0);
2197
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2199
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2200
gtk_widget_show (item);
2204
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
2206
/* must avoid callback for Radio buttons */
2207
GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
2208
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2210
if (mymenu[i].key != 0)
2211
gtk_widget_add_accelerator (item, "activate", accel_group,
2212
mymenu[i].key, mymenu[i].id == MENU_ID_AWAY ?
2213
away_mask : GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
2214
if (mymenu[i].callback)
2215
g_signal_connect (G_OBJECT (item), "toggled",
2216
G_CALLBACK (mymenu[i].callback), 0);
2218
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2220
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2221
gtk_widget_show (item);
2222
gtk_widget_set_sensitive (item, mymenu[i].sensitive);
2226
item = gtk_radio_menu_item_new_with_mnemonic (group, _(mymenu[i].text));
2227
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
2231
item = gtk_menu_item_new ();
2232
gtk_widget_set_sensitive (item, FALSE);
2233
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2234
gtk_widget_show (item);
2239
submenu = gtk_menu_new ();
2240
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2241
/* record the English name for /menu */
2242
g_object_set_data (G_OBJECT (item), "name", mymenu[i].text);
2243
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
2244
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2245
gtk_widget_show (item);
2248
/*case M_END:*/ default:
2253
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2254
menu_add_plugin_mainmenu_items (menu_bar);
2257
usermenu_create (usermenu);
2263
/* record this GtkWidget * so it's state might be changed later */
2264
if (mymenu[i].id != 0 && menu_widgets)
2265
/* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2266
menu_widgets[mymenu[i].id] = item;