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
27 #include <gtk/gtkhbox.h>
28 #include <gtk/gtkcheckmenuitem.h>
29 #include <gtk/gtkentry.h>
30 #include <gtk/gtkimage.h>
31 #include <gtk/gtkimagemenuitem.h>
32 #include <gtk/gtkradiomenuitem.h>
33 #include <gtk/gtklabel.h>
34 #include <gtk/gtkmessagedialog.h>
35 #include <gtk/gtkmenu.h>
36 #include <gtk/gtkmenubar.h>
37 #include <gtk/gtkstock.h>
38 #include <gtk/gtkversion.h>
39 #include <gdk/gdkkeysyms.h>
41 #include "../common/xchat.h"
42 #include "../common/xchatc.h"
43 #include "../common/cfgfiles.h"
44 #include "../common/outbound.h"
45 #include "../common/ignore.h"
46 #include "../common/fe.h"
47 #include "../common/server.h"
48 #include "../common/servlist.h"
49 #include "../common/notify.h"
50 #include "../common/util.h"
60 #include "notifygui.h"
64 #include "plugingui.h"
68 #include "userlistgui.h"
70 #include "servlistgui.h"
72 static GSList
*submenu_list
;
92 unsigned char type
; /* M_XXX */
93 unsigned char id
; /* MENU_ID_XXX (menu.h) */
94 unsigned char state
; /* ticked or not? */
95 unsigned char sensitive
; /* shaded out? */
96 guint key
; /* GDK_x */
99 #define XCMENU_DOLIST 1
100 #define XCMENU_SHADED 1
101 #define XCMENU_MARKUP 2
102 #define XCMENU_MNEMONIC 4
104 /* execute a userlistbutton/popupmenu command */
107 nick_command (session
* sess
, char *cmd
)
110 xchat_exec (cmd
+ 1);
112 handle_command (sess
, cmd
, TRUE
);
115 /* fill in the %a %s %n etc and execute the command */
118 nick_command_parse (session
*sess
, char *cmd
, char *nick
, char *allnick
)
121 char *host
= _("Host unknown");
125 /* if (sess->type == SESS_DIALOG)
127 buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
128 buf = strrchr (buf, '@');
133 user
= userlist_find (sess
, nick
);
134 if (user
&& user
->hostname
)
135 host
= strchr (user
->hostname
, '@') + 1;
138 /* this can't overflow, since popup->cmd is only 256 */
139 len
= strlen (cmd
) + strlen (nick
) + strlen (allnick
) + 512;
142 auto_insert (buf
, len
, cmd
, 0, 0, allnick
, sess
->channel
, "",
143 server_get_network (sess
->server
, TRUE
), host
,
144 sess
->server
->nick
, nick
);
146 nick_command (sess
, buf
);
151 /* userlist button has been clicked */
154 userlist_button_cb (GtkWidget
* button
, char *cmd
)
156 int i
, num_sel
, using_allnicks
= FALSE
;
157 char **nicks
, *allnicks
;
163 if (strstr (cmd
, "%a"))
164 using_allnicks
= TRUE
;
166 if (sess
->type
== SESS_DIALOG
)
168 /* fake a selection */
169 nicks
= malloc (sizeof (char *) * 2);
170 nicks
[0] = g_strdup (sess
->channel
);
175 /* find number of selected rows */
176 nicks
= userlist_selection_list (sess
->gui
->user_tree
, &num_sel
);
179 nick_command_parse (sess
, cmd
, "", "");
184 /* create "allnicks" string */
185 allnicks
= malloc (((NICKLEN
+ 1) * num_sel
) + 1);
192 strcat (allnicks
, " ");
193 strcat (allnicks
, nicks
[i
]);
198 /* if not using "%a", execute the command once for each nickname */
200 nick_command_parse (sess
, cmd
, nicks
[i
], "");
209 nick_command_parse (sess
, cmd
, nick
, allnicks
);
215 g_free (nicks
[num_sel
]);
222 /* a popup-menu-item has been selected */
225 popup_menu_cb (GtkWidget
* item
, char *cmd
)
229 /* the userdata is set in menu_quick_item() */
230 nick
= g_object_get_data (G_OBJECT (item
), "u");
232 if (!nick
) /* userlist popup menu */
234 /* treat it just like a userlist button */
235 userlist_button_cb (NULL
, cmd
);
239 if (!current_sess
) /* for url grabber window */
240 nick_command_parse (sess_list
->data
, cmd
, nick
, nick
);
242 nick_command_parse (current_sess
, cmd
, nick
, nick
);
246 menu_toggle_item (char *label
, GtkWidget
*menu
, void *callback
, void *userdata
,
251 item
= gtk_check_menu_item_new_with_mnemonic (label
);
252 gtk_check_menu_item_set_active ((GtkCheckMenuItem
*)item
, state
);
253 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
254 g_signal_connect (G_OBJECT (item
), "activate",
255 G_CALLBACK (callback
), userdata
);
256 gtk_widget_show (item
);
262 menu_quick_item (char *cmd
, char *label
, GtkWidget
* menu
, int flags
,
263 gpointer userdata
, char *icon
)
265 GtkWidget
*img
, *item
;
269 item
= gtk_menu_item_new ();
274 /*if (flags & XCMENU_MARKUP)
275 item = gtk_image_menu_item_new_with_markup (label);
277 item
= gtk_image_menu_item_new_with_mnemonic (label
);
279 if (access (icon
, R_OK
) == 0) /* try fullpath */
280 img
= gtk_image_new_from_file (icon
);
283 /* try relative to ~/.xchat2 */
284 path
= g_strdup_printf ("%s/%s", get_xdir_fs (), icon
);
285 if (access (path
, R_OK
) == 0)
286 img
= gtk_image_new_from_file (path
);
288 img
= gtk_image_new_from_stock (icon
, GTK_ICON_SIZE_MENU
);
293 gtk_image_menu_item_set_image ((GtkImageMenuItem
*)item
, img
);
297 if (flags
& XCMENU_MARKUP
)
299 item
= gtk_menu_item_new_with_label ("");
300 if (flags
& XCMENU_MNEMONIC
)
301 gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item
)->child
), label
);
303 gtk_label_set_markup (GTK_LABEL (GTK_BIN (item
)->child
), label
);
306 if (flags
& XCMENU_MNEMONIC
)
307 item
= gtk_menu_item_new_with_mnemonic (label
);
309 item
= gtk_menu_item_new_with_label (label
);
313 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
314 g_object_set_data (G_OBJECT (item
), "u", userdata
);
316 g_signal_connect (G_OBJECT (item
), "activate",
317 G_CALLBACK (popup_menu_cb
), cmd
);
318 if (flags
& XCMENU_SHADED
)
319 gtk_widget_set_sensitive (GTK_WIDGET (item
), FALSE
);
320 gtk_widget_show_all (item
);
326 menu_quick_item_with_callback (void *callback
, char *label
, GtkWidget
* menu
,
331 item
= gtk_menu_item_new_with_label (label
);
332 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
333 g_signal_connect (G_OBJECT (item
), "activate",
334 G_CALLBACK (callback
), arg
);
335 gtk_widget_show (item
);
339 menu_quick_sub (char *name
, GtkWidget
*menu
, GtkWidget
**sub_item_ret
, int flags
, int pos
)
347 /* Code to add a submenu */
348 sub_menu
= gtk_menu_new ();
349 if (flags
& XCMENU_MARKUP
)
351 sub_item
= gtk_menu_item_new_with_label ("");
352 gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item
)->child
), name
);
356 if (flags
& XCMENU_MNEMONIC
)
357 sub_item
= gtk_menu_item_new_with_mnemonic (name
);
359 sub_item
= gtk_menu_item_new_with_label (name
);
361 gtk_menu_shell_insert (GTK_MENU_SHELL (menu
), sub_item
, pos
);
362 gtk_widget_show (sub_item
);
363 gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item
), sub_menu
);
366 *sub_item_ret
= sub_item
;
368 if (flags
& XCMENU_DOLIST
)
369 /* We create a new element in the list */
370 submenu_list
= g_slist_prepend (submenu_list
, sub_menu
);
377 /* Just delete the first element in the linked list pointed to by first */
379 submenu_list
= g_slist_remove (submenu_list
, submenu_list
->data
);
382 return (submenu_list
->data
);
388 toggle_cb (GtkWidget
*item
, char *pref_name
)
392 if (GTK_CHECK_MENU_ITEM (item
)->active
)
393 snprintf (buf
, sizeof (buf
), "set %s 1", pref_name
);
395 snprintf (buf
, sizeof (buf
), "set %s 0", pref_name
);
397 handle_command (current_sess
, buf
, FALSE
);
401 is_in_path (char *cmd
)
403 char *prog
= strdup (cmd
+ 1); /* 1st char is "!" */
404 char *space
, *path
, *orig
;
406 orig
= prog
; /* save for free()ing */
407 /* special-case these default entries. */
408 /* 123456789012345678 */
409 if (strncmp (prog
, "gnome-terminal -x ", 18) == 0)
410 /* don't check for gnome-terminal, but the thing it's executing! */
413 space
= strchr (prog
, ' '); /* this isn't 100% but good enuf */
417 path
= g_find_program_in_path (prog
);
429 /* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
432 menu_extract_icon (char *name
, char **label
, char **icon
)
443 if (p
== name
|| p
[-1] != '\\')
457 if (start
&& start
!= end
)
459 *label
= g_strndup (name
, (start
- name
) - 1);
460 *icon
= g_strndup (start
, (end
- start
) - 1);
464 *label
= g_strdup (name
);
469 /* append items to "menu" using the (struct popup*) list provided */
472 menu_create (GtkWidget
*menu
, GSList
*list
, char *target
, int check_path
)
475 GtkWidget
*tempmenu
= menu
, *subitem
= NULL
;
478 submenu_list
= g_slist_prepend (0, menu
);
481 pop
= (struct popup
*) list
->data
;
483 if (!strncasecmp (pop
->name
, "SUB", 3))
486 tempmenu
= menu_quick_sub (pop
->cmd
, tempmenu
, &subitem
, XCMENU_DOLIST
|XCMENU_MNEMONIC
, -1);
488 } else if (!strncasecmp (pop
->name
, "TOGGLE", 6))
491 menu_toggle_item (pop
->name
+ 7, tempmenu
, toggle_cb
, pop
->cmd
,
492 cfg_get_bool (pop
->cmd
));
494 } else if (!strncasecmp (pop
->name
, "ENDSUB", 6))
496 /* empty sub menu due to no programs in PATH? */
497 if (check_path
&& childcount
< 1)
498 gtk_widget_destroy (subitem
);
501 if (tempmenu
!= menu
)
502 tempmenu
= menu_quick_endsub ();
503 /* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
505 } else if (!strncasecmp (pop
->name
, "SEP", 3))
507 menu_quick_item (0, 0, tempmenu
, XCMENU_SHADED
, 0, 0);
513 /* default command in xchat.c */
514 if (pop
->cmd
[0] == 'n' && !strcmp (pop
->cmd
, "notify -n ASK %s"))
516 /* don't create this item if already in notify list */
517 if (!target
|| notify_is_in_list (current_sess
->server
, target
))
524 menu_extract_icon (pop
->name
, &label
, &icon
);
526 if (!check_path
|| pop
->cmd
[0] != '!')
528 menu_quick_item (pop
->cmd
, label
, tempmenu
, 0, target
, icon
);
529 /* check if the program is in path, if not, leave it out! */
530 } else if (is_in_path (pop
->cmd
))
533 menu_quick_item (pop
->cmd
, label
, tempmenu
, 0, target
, icon
);
543 /* Let's clean up the linked list from mem */
545 submenu_list
= g_slist_remove (submenu_list
, submenu_list
->data
);
548 static char *str_copy
= NULL
; /* for all pop-up menus */
549 static GtkWidget
*nick_submenu
= NULL
; /* user info submenu */
552 menu_destroy (GtkWidget
*menu
, gpointer objtounref
)
554 gtk_widget_destroy (menu
);
555 g_object_unref (menu
);
557 g_object_unref (G_OBJECT (objtounref
));
562 menu_popup (GtkWidget
*menu
, GdkEventButton
*event
, gpointer objtounref
)
564 if (event
&& event
->window
)
565 gtk_menu_set_screen (GTK_MENU (menu
), gdk_drawable_get_screen (event
->window
));
568 g_object_ref_sink (menu
);
569 g_object_unref (menu
);
570 g_signal_connect (G_OBJECT (menu
), "selection-done",
571 G_CALLBACK (menu_destroy
), objtounref
);
572 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
, NULL
, NULL
,
573 0, event
? event
->time
: 0);
577 menu_nickinfo_cb (GtkWidget
*menu
, session
*sess
)
581 if (!is_session (sess
))
585 snprintf (buf
, sizeof (buf
), "WHOIS %s %s", str_copy
, str_copy
);
586 handle_command (sess
, buf
, FALSE
);
587 /* and hide the output */
588 sess
->server
->skip_next_whois
= 1;
592 copy_to_clipboard_cb (GtkWidget
*item
, char *url
)
594 gtkutil_copy_to_clipboard (item
, NULL
, url
);
597 /* returns boolean: Some data is missing */
600 menu_create_nickinfo_menu (struct User
*user
, GtkWidget
*submenu
)
605 struct away_msg
*away
;
606 gboolean missing
= FALSE
;
609 /* let the translators tweak this if need be */
610 fmt
= _("<tt><b>%-11s</b></tt> %s");
611 snprintf (unknown
, sizeof (unknown
), "<i>%s</i>", _("Unknown"));
615 real
= strip_color (user
->realname
, -1, STRIP_ALL
|STRIP_ESCMARKUP
);
616 snprintf (buf
, sizeof (buf
), fmt
, _("Real Name:"), real
);
620 snprintf (buf
, sizeof (buf
), fmt
, _("Real Name:"), unknown
);
622 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
623 g_signal_connect (G_OBJECT (item
), "activate",
624 G_CALLBACK (copy_to_clipboard_cb
),
625 user
->realname
? user
->realname
: unknown
);
627 snprintf (buf
, sizeof (buf
), fmt
, _("User:"),
628 user
->hostname
? user
->hostname
: unknown
);
629 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
630 g_signal_connect (G_OBJECT (item
), "activate",
631 G_CALLBACK (copy_to_clipboard_cb
),
632 user
->hostname
? user
->hostname
: unknown
);
634 snprintf (buf
, sizeof (buf
), fmt
, _("Account:"),
635 user
->account
? user
->account
: unknown
);
636 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
637 g_signal_connect (G_OBJECT (item
), "activate",
638 G_CALLBACK (copy_to_clipboard_cb
),
639 user
->account
? user
->account
: unknown
);
641 snprintf (buf
, sizeof (buf
), fmt
, _("Country:"),
642 user
->hostname
? country(user
->hostname
) : unknown
);
643 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
644 g_signal_connect (G_OBJECT (item
), "activate",
645 G_CALLBACK (copy_to_clipboard_cb
),
646 user
->hostname
? country(user
->hostname
) : unknown
);
648 snprintf (buf
, sizeof (buf
), fmt
, _("Server:"),
649 user
->servername
? user
->servername
: unknown
);
650 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
651 g_signal_connect (G_OBJECT (item
), "activate",
652 G_CALLBACK (copy_to_clipboard_cb
),
653 user
->servername
? user
->servername
: unknown
);
659 snprintf (min
, sizeof (min
), _("%u minutes ago"),
660 (unsigned int) ((time (0) - user
->lasttalk
) / 60));
661 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), min
);
664 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), unknown
);
666 menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
670 away
= server_away_find_message (current_sess
->server
, user
->nick
);
673 char *msg
= strip_color (away
->message
? away
->message
: unknown
, -1, STRIP_ALL
|STRIP_ESCMARKUP
);
674 snprintf (buf
, sizeof (buf
), fmt
, _("Away Msg:"), msg
);
676 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
677 g_signal_connect (G_OBJECT (item
), "activate",
678 G_CALLBACK (copy_to_clipboard_cb
),
679 away
->message
? away
->message
: unknown
);
689 fe_userlist_update (session
*sess
, struct User
*user
)
693 if (!nick_submenu
|| !str_copy
)
696 /* not the same nick as the menu? */
697 if (sess
->server
->p_cmp (user
->nick
, str_copy
))
700 /* get rid of the "show" signal */
701 g_signal_handlers_disconnect_by_func (nick_submenu
, menu_nickinfo_cb
, sess
);
703 /* destroy all the old items */
704 items
= ((GtkMenuShell
*) nick_submenu
)->children
;
708 gtk_widget_destroy (items
->data
);
712 /* and re-create them with new info */
713 menu_create_nickinfo_menu (user
, nick_submenu
);
717 menu_nickmenu (session
*sess
, GdkEventButton
*event
, char *nick
, int num_sel
)
721 GtkWidget
*submenu
, *menu
= gtk_menu_new ();
725 str_copy
= strdup (nick
);
727 submenu_list
= 0; /* first time through, might not be 0 */
729 /* more than 1 nick selected? */
732 snprintf (buf
, sizeof (buf
), _("%d nicks selected."), num_sel
);
733 menu_quick_item (0, buf
, menu
, 0, 0, 0);
734 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
737 user
= userlist_find (sess
, nick
); /* lasttalk is channel specific */
739 user
= userlist_find_global (current_sess
->server
, nick
);
742 nick_submenu
= submenu
= menu_quick_sub (nick
, menu
, NULL
, XCMENU_DOLIST
, -1);
744 if (menu_create_nickinfo_menu (user
, submenu
) ||
745 !user
->hostname
|| !user
->realname
|| !user
->servername
)
747 g_signal_connect (G_OBJECT (submenu
), "show", G_CALLBACK (menu_nickinfo_cb
), sess
);
750 menu_quick_endsub ();
751 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
756 menu_create (menu
, popup_list
, NULL
, FALSE
);
758 menu_create (menu
, popup_list
, str_copy
, FALSE
);
760 if (num_sel
== 0) /* xtext click */
761 menu_add_plugin_items (menu
, "\x5$NICK", str_copy
);
762 else /* userlist treeview click */
763 menu_add_plugin_items (menu
, "\x5$NICK", NULL
);
765 menu_popup (menu
, event
, NULL
);
768 /* stuff for the View menu */
771 menu_showhide_cb (session
*sess
)
774 gtk_widget_hide (sess
->gui
->menu
);
776 gtk_widget_show (sess
->gui
->menu
);
780 menu_topic_showhide_cb (session
*sess
)
783 gtk_widget_show (sess
->gui
->topic_bar
);
785 gtk_widget_hide (sess
->gui
->topic_bar
);
789 menu_userlist_showhide_cb (session
*sess
)
791 mg_decide_userlist (sess
, TRUE
);
795 menu_ulbuttons_showhide_cb (session
*sess
)
797 if (prefs
.userlistbuttons
)
798 gtk_widget_show (sess
->gui
->button_box
);
800 gtk_widget_hide (sess
->gui
->button_box
);
804 menu_cmbuttons_showhide_cb (session
*sess
)
809 if (prefs
.chanmodebuttons
)
810 gtk_widget_show (sess
->gui
->topicbutton_box
);
812 gtk_widget_hide (sess
->gui
->topicbutton_box
);
815 gtk_widget_hide (sess
->gui
->topicbutton_box
);
820 menu_setting_foreach (void (*callback
) (session
*), int id
, guint state
)
824 int maindone
= FALSE
; /* do it only once for EVERY tab */
831 if (!sess
->gui
->is_tab
|| !maindone
)
833 if (sess
->gui
->is_tab
)
836 GTK_CHECK_MENU_ITEM (sess
->gui
->menu_item
[id
])->active
= state
;
846 menu_bar_toggle (void)
848 prefs
.hidemenu
= !prefs
.hidemenu
;
849 menu_setting_foreach (menu_showhide_cb
, MENU_ID_MENUBAR
, !prefs
.hidemenu
);
853 menu_bar_toggle_cb (void)
857 fe_message (_("The Menubar is now hidden. You can show it again"
858 " by pressing F9 or right-clicking in a blank part of"
859 " the main text area."), FE_MSG_INFO
);
863 menu_topicbar_toggle (GtkWidget
*wid
, gpointer ud
)
865 prefs
.topicbar
= !prefs
.topicbar
;
866 menu_setting_foreach (menu_topic_showhide_cb
, MENU_ID_TOPICBAR
,
871 menu_userlist_toggle (GtkWidget
*wid
, gpointer ud
)
873 prefs
.hideuserlist
= !prefs
.hideuserlist
;
874 menu_setting_foreach (menu_userlist_showhide_cb
, MENU_ID_USERLIST
,
875 !prefs
.hideuserlist
);
879 menu_ulbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
881 prefs
.userlistbuttons
= !prefs
.userlistbuttons
;
882 menu_setting_foreach (menu_ulbuttons_showhide_cb
, MENU_ID_ULBUTTONS
,
883 prefs
.userlistbuttons
);
887 menu_cmbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
889 prefs
.chanmodebuttons
= !prefs
.chanmodebuttons
;
890 menu_setting_foreach (menu_cmbuttons_showhide_cb
, MENU_ID_MODEBUTTONS
,
891 prefs
.chanmodebuttons
);
895 menu_middlemenu (session
*sess
, GdkEventButton
*event
)
898 GtkAccelGroup
*accel_group
;
900 accel_group
= gtk_accel_group_new ();
901 menu
= menu_create_main (accel_group
, FALSE
, sess
->server
->is_away
, !sess
->gui
->is_tab
, NULL
);
902 menu_popup (menu
, event
, accel_group
);
906 open_url_cb (GtkWidget
*item
, char *url
)
910 /* pass this to /URL so it can handle irc:// */
911 snprintf (buf
, sizeof (buf
), "URL %s", url
);
912 handle_command (current_sess
, buf
, FALSE
);
916 menu_urlmenu (GdkEventButton
*event
, char *url
)
923 str_copy
= strdup (url
);
925 menu
= gtk_menu_new ();
926 /* more than 51 chars? Chop it */
927 if (g_utf8_strlen (str_copy
, -1) >= 52)
929 tmp
= strdup (str_copy
);
930 chop
= g_utf8_offset_to_pointer (tmp
, 48);
931 chop
[0] = chop
[1] = chop
[2] = '.';
933 menu_quick_item (0, tmp
, menu
, XCMENU_SHADED
, 0, 0);
937 menu_quick_item (0, str_copy
, menu
, XCMENU_SHADED
, 0, 0);
939 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
941 /* Two hardcoded entries */
942 if (strncmp (str_copy
, "irc://", 6) == 0 ||
943 strncmp (str_copy
, "ircs://",7) == 0)
944 menu_quick_item_with_callback (open_url_cb
, _("Connect"), menu
, str_copy
);
946 menu_quick_item_with_callback (open_url_cb
, _("Open Link in Browser"), menu
, str_copy
);
947 menu_quick_item_with_callback (copy_to_clipboard_cb
, _("Copy Selected Link"), menu
, str_copy
);
948 /* custom ones from urlhandlers.conf */
949 menu_create (menu
, urlhandler_list
, str_copy
, TRUE
);
950 menu_add_plugin_items (menu
, "\x4$URL", str_copy
);
951 menu_popup (menu
, event
, NULL
);
955 menu_chan_cycle (GtkWidget
* menu
, char *chan
)
961 snprintf (tbuf
, sizeof tbuf
, "CYCLE %s", chan
);
962 handle_command (current_sess
, tbuf
, FALSE
);
967 menu_chan_part (GtkWidget
* menu
, char *chan
)
973 snprintf (tbuf
, sizeof tbuf
, "part %s", chan
);
974 handle_command (current_sess
, tbuf
, FALSE
);
979 menu_chan_join (GtkWidget
* menu
, char *chan
)
985 snprintf (tbuf
, sizeof tbuf
, "join %s", chan
);
986 handle_command (current_sess
, tbuf
, FALSE
);
991 menu_chanmenu (struct session
*sess
, GdkEventButton
* event
, char *chan
)
994 int is_joined
= FALSE
;
996 if (find_channel (sess
->server
, chan
))
1001 str_copy
= strdup (chan
);
1003 menu
= gtk_menu_new ();
1005 menu_quick_item (0, chan
, menu
, XCMENU_SHADED
, str_copy
, 0);
1006 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, str_copy
, 0);
1009 menu_quick_item_with_callback (menu_chan_join
, _("Join Channel"), menu
,
1013 menu_quick_item_with_callback (menu_chan_part
, _("Part Channel"), menu
,
1015 menu_quick_item_with_callback (menu_chan_cycle
, _("Cycle Channel"), menu
,
1019 menu_addfavoritemenu (sess
->server
, menu
, str_copy
);
1021 menu_add_plugin_items (menu
, "\x5$CHAN", str_copy
);
1022 menu_popup (menu
, event
, NULL
);
1026 menu_delfav_cb (GtkWidget
*item
, server
*serv
)
1028 servlist_autojoinedit (serv
->network
, str_copy
, FALSE
);
1032 menu_addfav_cb (GtkWidget
*item
, server
*serv
)
1034 servlist_autojoinedit (serv
->network
, str_copy
, TRUE
);
1038 menu_addfavoritemenu (server
*serv
, GtkWidget
*menu
, char *channel
)
1043 if (channel
!= str_copy
)
1047 str_copy
= strdup (channel
);
1050 if (joinlist_is_in_list (serv
, channel
))
1051 mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE
, menu
, menu_delfav_cb
, serv
);
1053 mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD
, menu
, menu_addfav_cb
, serv
);
1057 menu_open_server_list (GtkWidget
*wid
, gpointer none
)
1059 fe_serverlist_open (current_sess
);
1063 menu_settings (GtkWidget
* wid
, gpointer none
)
1065 extern void setup_open (void);
1070 menu_usermenu (void)
1072 editlist_gui_open (NULL
, NULL
, usermenu_list
, _("XChat: User menu"),
1073 "usermenu", "usermenu.conf", 0);
1077 usermenu_create (GtkWidget
*menu
)
1079 menu_create (menu
, usermenu_list
, "", FALSE
);
1080 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0); /* sep */
1081 menu_quick_item_with_callback (menu_usermenu
, _("Edit This Menu..."), menu
, 0);
1085 usermenu_destroy (GtkWidget
* menu
)
1087 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1093 gtk_widget_destroy (items
->data
);
1099 usermenu_update (void)
1101 int done_main
= FALSE
;
1102 GSList
*list
= sess_list
;
1109 menu
= sess
->gui
->menu_item
[MENU_ID_USERMENU
];
1110 if (sess
->gui
->is_tab
)
1112 if (!done_main
&& menu
)
1114 usermenu_destroy (menu
);
1115 usermenu_create (menu
);
1120 usermenu_destroy (menu
);
1121 usermenu_create (menu
);
1128 menu_newserver_window (GtkWidget
* wid
, gpointer none
)
1130 int old
= prefs
.tabchannels
;
1132 prefs
.tabchannels
= 0;
1133 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1134 prefs
.tabchannels
= old
;
1138 menu_newchannel_window (GtkWidget
* wid
, gpointer none
)
1140 int old
= prefs
.tabchannels
;
1142 prefs
.tabchannels
= 0;
1143 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1144 prefs
.tabchannels
= old
;
1148 menu_newserver_tab (GtkWidget
* wid
, gpointer none
)
1150 int old
= prefs
.tabchannels
;
1151 int oldf
= prefs
.newtabstofront
;
1153 prefs
.tabchannels
= 1;
1154 /* force focus if setting is "only requested tabs" */
1155 if (prefs
.newtabstofront
== 2)
1156 prefs
.newtabstofront
= 1;
1157 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1158 prefs
.tabchannels
= old
;
1159 prefs
.newtabstofront
= oldf
;
1163 menu_newchannel_tab (GtkWidget
* wid
, gpointer none
)
1165 int old
= prefs
.tabchannels
;
1167 prefs
.tabchannels
= 1;
1168 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1169 prefs
.tabchannels
= old
;
1173 menu_rawlog (GtkWidget
* wid
, gpointer none
)
1175 open_rawlog (current_sess
->server
);
1179 menu_detach (GtkWidget
* wid
, gpointer none
)
1181 mg_detach (current_sess
, 0);
1185 menu_close (GtkWidget
* wid
, gpointer none
)
1187 mg_close_sess (current_sess
);
1191 menu_quit (GtkWidget
* wid
, gpointer none
)
1193 mg_open_quit_dialog (FALSE
);
1199 search_open (current_sess
);
1203 menu_resetmarker (GtkWidget
* wid
, gpointer none
)
1205 gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess
->gui
->xtext
));
1209 menu_flushbuffer (GtkWidget
* wid
, gpointer none
)
1211 fe_text_clear (current_sess
, 0);
1215 savebuffer_req_done (session
*sess
, char *file
)
1222 fh
= open (file
, O_TRUNC
| O_WRONLY
| O_CREAT
, 0600);
1225 gtk_xtext_save (GTK_XTEXT (sess
->gui
->xtext
), fh
);
1231 menu_savebuffer (GtkWidget
* wid
, gpointer none
)
1233 gtkutil_file_req (_("Select an output filename"), savebuffer_req_done
,
1234 current_sess
, NULL
, FRF_WRITE
);
1238 menu_disconnect (GtkWidget
* wid
, gpointer none
)
1240 handle_command (current_sess
, "DISCON", FALSE
);
1244 menu_reconnect (GtkWidget
* wid
, gpointer none
)
1246 if (current_sess
->server
->hostname
[0])
1247 handle_command (current_sess
, "RECONNECT", FALSE
);
1249 fe_serverlist_open (current_sess
);
1253 menu_join_cb (GtkWidget
*dialog
, gint response
, GtkEntry
*entry
)
1257 case GTK_RESPONSE_ACCEPT
:
1258 menu_chan_join (NULL
, entry
->text
);
1261 case GTK_RESPONSE_HELP
:
1262 chanlist_opengui (current_sess
->server
, TRUE
);
1266 gtk_widget_destroy (dialog
);
1270 menu_join_entry_cb (GtkWidget
*entry
, GtkDialog
*dialog
)
1272 gtk_dialog_response (dialog
, GTK_RESPONSE_ACCEPT
);
1276 menu_join (GtkWidget
* wid
, gpointer none
)
1278 GtkWidget
*hbox
, *dialog
, *entry
, *label
;
1280 dialog
= gtk_dialog_new_with_buttons (_("Join Channel"),
1281 GTK_WINDOW (parent_window
), 0,
1282 _("Retrieve channel list..."), GTK_RESPONSE_HELP
,
1283 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
1284 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
1286 gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog
)->vbox
), TRUE
);
1287 gtk_window_set_position (GTK_WINDOW (dialog
), GTK_WIN_POS_MOUSE
);
1288 hbox
= gtk_hbox_new (TRUE
, 0);
1290 entry
= gtk_entry_new ();
1291 GTK_ENTRY (entry
)->editable
= 0; /* avoid auto-selection */
1292 gtk_entry_set_text (GTK_ENTRY (entry
), "#");
1293 g_signal_connect (G_OBJECT (entry
), "activate",
1294 G_CALLBACK (menu_join_entry_cb
), dialog
);
1295 gtk_box_pack_end (GTK_BOX (hbox
), entry
, 0, 0, 0);
1297 label
= gtk_label_new (_("Enter Channel to Join:"));
1298 gtk_box_pack_end (GTK_BOX (hbox
), label
, 0, 0, 0);
1300 g_signal_connect (G_OBJECT (dialog
), "response",
1301 G_CALLBACK (menu_join_cb
), entry
);
1303 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog
)->vbox
), hbox
);
1305 gtk_widget_show_all (dialog
);
1307 gtk_editable_set_editable (GTK_EDITABLE (entry
), TRUE
);
1308 gtk_editable_set_position (GTK_EDITABLE (entry
), 1);
1312 menu_away (GtkCheckMenuItem
*item
, gpointer none
)
1314 handle_command (current_sess
, item
->active
? "away" : "back", FALSE
);
1318 menu_chanlist (GtkWidget
* wid
, gpointer none
)
1320 chanlist_opengui (current_sess
->server
, FALSE
);
1324 menu_banlist (GtkWidget
* wid
, gpointer none
)
1326 banlist_opengui (current_sess
);
1332 menu_loadplugin (void)
1338 menu_pluginlist (void)
1345 #define menu_pluginlist 0
1346 #define menu_loadplugin 0
1350 #define usercommands_help _("User Commands - Special codes:\n\n"\
1351 "%c = current channel\n"\
1352 "%e = current network name\n"\
1353 "%m = machine info\n"\
1356 "%v = xchat version\n"\
1359 "&2 = word 2 to the end of line\n"\
1360 "&3 = word 3 to the end of line\n\n"\
1362 "/cmd john hello\n\n"\
1363 "%2 would be \042john\042\n"\
1364 "&2 would be \042john hello\042.")
1366 #define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1367 "%a = all selected nicks\n"\
1368 "%c = current channel\n"\
1369 "%e = current network name\n"\
1370 "%h = selected nick's hostname\n"\
1371 "%m = machine info\n"\
1373 "%s = selected nick\n"\
1376 #define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1377 "%a = all selected nicks\n"\
1378 "%c = current channel\n"\
1379 "%e = current network name\n"\
1380 "%h = selected nick's hostname\n"\
1381 "%m = machine info\n"\
1383 "%s = selected nick\n"\
1386 #define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1387 "%d = data (the whole ctcp)\n"\
1388 "%e = current network name\n"\
1389 "%m = machine info\n"\
1390 "%s = nick who sent the ctcp\n"\
1394 "&2 = word 2 to the end of line\n"\
1395 "&3 = word 3 to the end of line\n\n")
1397 #define url_help _("URL Handlers - Special codes:\n\n"\
1398 "%s = the URL string\n\n"\
1399 "Putting a ! infront of the command\n"\
1400 "indicates it should be sent to a\n"\
1401 "shell instead of XChat")
1404 menu_usercommands (void)
1406 editlist_gui_open (NULL
, NULL
, command_list
, _("XChat: User Defined Commands"),
1407 "commands", "commands.conf", usercommands_help
);
1413 editlist_gui_open (NULL
, NULL
, popup_list
, _("XChat: Userlist Popup menu"), "popup",
1414 "popup.conf", ulbutton_help
);
1420 editlist_gui_open (_("Text"), _("Replace with"), replace_list
, _("XChat: Replace"), "replace",
1425 menu_urlhandlers (void)
1427 editlist_gui_open (NULL
, NULL
, urlhandler_list
, _("XChat: URL Handlers"), "urlhandlers",
1428 "urlhandlers.conf", url_help
);
1432 menu_evtpopup (void)
1434 pevent_dialog_show ();
1438 menu_keypopup (void)
1444 menu_ulbuttons (void)
1446 editlist_gui_open (NULL
, NULL
, button_list
, _("XChat: Userlist buttons"), "buttons",
1447 "buttons.conf", ulbutton_help
);
1451 menu_dlgbuttons (void)
1453 editlist_gui_open (NULL
, NULL
, dlgbutton_list
, _("XChat: Dialog buttons"), "dlgbuttons",
1454 "dlgbuttons.conf", dlgbutton_help
);
1458 menu_ctcpguiopen (void)
1460 editlist_gui_open (NULL
, NULL
, ctcp_list
, _("XChat: CTCP Replies"), "ctcpreply",
1461 "ctcpreply.conf", ctcp_help
);
1465 menu_docs (GtkWidget
*wid
, gpointer none
)
1467 fe_open_url ("http://xchat.org/docs/");
1471 menu_webpage (GtkWidget *wid, gpointer none)
1473 fe_open_url ("http://xchat.org");
1477 menu_dcc_win (GtkWidget
*wid
, gpointer none
)
1479 fe_dcc_open_recv_win (FALSE
);
1480 fe_dcc_open_send_win (FALSE
);
1484 menu_dcc_chat_win (GtkWidget
*wid
, gpointer none
)
1486 fe_dcc_open_chat_win (FALSE
);
1490 menu_change_layout (void)
1492 if (prefs
.tab_layout
== 0)
1494 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 1);
1495 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 0);
1496 mg_change_layout (0);
1499 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 0);
1500 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 1);
1501 mg_change_layout (2);
1506 menu_layout_cb (GtkWidget
*item
, gpointer none
)
1508 prefs
.tab_layout
= 2;
1509 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1510 prefs
.tab_layout
= 0;
1512 menu_change_layout ();
1516 menu_apply_metres_cb (session
*sess
)
1518 mg_update_meters (sess
->gui
);
1522 menu_metres_off (GtkWidget
*item
, gpointer none
)
1524 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1526 prefs
.lagometer
= 0;
1527 prefs
.throttlemeter
= 0;
1528 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1533 menu_metres_text (GtkWidget
*item
, gpointer none
)
1535 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1537 prefs
.lagometer
= 2;
1538 prefs
.throttlemeter
= 2;
1539 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1544 menu_metres_graph (GtkWidget
*item
, gpointer none
)
1546 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1548 prefs
.lagometer
= 1;
1549 prefs
.throttlemeter
= 1;
1550 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1555 menu_metres_both (GtkWidget
*item
, gpointer none
)
1557 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1559 prefs
.lagometer
= 3;
1560 prefs
.throttlemeter
= 3;
1561 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1565 static struct mymenu mymenu
[] = {
1566 {N_("_XChat"), 0, 0, M_NEWMENU
, 0, 0, 1},
1567 {N_("Network Li_st..."), menu_open_server_list
, (char *)&pix_book
, M_MENUPIX
, 0, 0, 1, GDK_s
},
1568 {0, 0, 0, M_SEP
, 0, 0, 0},
1570 {N_("_New"), 0, GTK_STOCK_NEW
, M_MENUSUB
, 0, 0, 1},
1571 {N_("Server Tab..."), menu_newserver_tab
, 0, M_MENUITEM
, 0, 0, 1, GDK_t
},
1572 {N_("Channel Tab..."), menu_newchannel_tab
, 0, M_MENUITEM
, 0, 0, 1},
1573 {N_("Server Window..."), menu_newserver_window
, 0, M_MENUITEM
, 0, 0, 1},
1574 {N_("Channel Window..."), menu_newchannel_window
, 0, M_MENUITEM
, 0, 0, 1},
1575 {0, 0, 0, M_END
, 0, 0, 0},
1576 {0, 0, 0, M_SEP
, 0, 0, 0},
1579 {N_("_Load Plugin or Script..."), menu_loadplugin
, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 1},
1581 {N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 0},
1583 {0, 0, 0, M_SEP
, 0, 0, 0}, /* 11 */
1584 #define DETACH_OFFSET (12)
1585 {0, menu_detach
, GTK_STOCK_REDO
, M_MENUSTOCK
, 0, 0, 1, GDK_I
}, /* 12 */
1586 #define CLOSE_OFFSET (13)
1587 {0, menu_close
, GTK_STOCK_CLOSE
, M_MENUSTOCK
, 0, 0, 1, GDK_w
},
1588 {0, 0, 0, M_SEP
, 0, 0, 0},
1589 {N_("_Quit"), menu_quit
, GTK_STOCK_QUIT
, M_MENUSTOCK
, 0, 0, 1, GDK_q
}, /* 15 */
1591 {N_("_View"), 0, 0, M_NEWMENU
, 0, 0, 1},
1592 #define MENUBAR_OFFSET (17)
1593 {N_("_Menu Bar"), menu_bar_toggle_cb
, 0, M_MENUTOG
, MENU_ID_MENUBAR
, 0, 1, GDK_F9
},
1594 {N_("_Topic Bar"), menu_topicbar_toggle
, 0, M_MENUTOG
, MENU_ID_TOPICBAR
, 0, 1},
1595 {N_("_User List"), menu_userlist_toggle
, 0, M_MENUTOG
, MENU_ID_USERLIST
, 0, 1, GDK_F7
},
1596 {N_("U_serlist Buttons"), menu_ulbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_ULBUTTONS
, 0, 1},
1597 {N_("M_ode Buttons"), menu_cmbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_MODEBUTTONS
, 0, 1},
1598 {0, 0, 0, M_SEP
, 0, 0, 0},
1599 {N_("_Channel Switcher"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 23 */
1600 #define TABS_OFFSET (24)
1601 {N_("_Tabs"), menu_layout_cb
, 0, M_MENURADIO
, MENU_ID_LAYOUT_TABS
, 0, 1},
1602 {N_("T_ree"), 0, 0, M_MENURADIO
, MENU_ID_LAYOUT_TREE
, 0, 1},
1603 {0, 0, 0, M_END
, 0, 0, 0},
1604 {N_("_Network Meters"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 27 */
1605 #define METRE_OFFSET (28)
1606 {N_("Off"), menu_metres_off
, 0, M_MENURADIO
, 0, 0, 1},
1607 {N_("Graph"), menu_metres_graph
, 0, M_MENURADIO
, 0, 0, 1},
1608 {N_("Text"), menu_metres_text
, 0, M_MENURADIO
, 0, 0, 1},
1609 {N_("Both"), menu_metres_both
, 0, M_MENURADIO
, 0, 0, 1},
1610 {0, 0, 0, M_END
, 0, 0, 0}, /* 32 */
1612 {N_("_Server"), 0, 0, M_NEWMENU
, 0, 0, 1},
1613 {N_("_Disconnect"), menu_disconnect
, GTK_STOCK_DISCONNECT
, M_MENUSTOCK
, MENU_ID_DISCONNECT
, 0, 1},
1614 {N_("_Reconnect"), menu_reconnect
, GTK_STOCK_CONNECT
, M_MENUSTOCK
, MENU_ID_RECONNECT
, 0, 1},
1615 {N_("Join a Channel..."), menu_join
, GTK_STOCK_JUMP_TO
, M_MENUSTOCK
, MENU_ID_JOIN
, 0, 1},
1616 {N_("List of Channels..."), menu_chanlist
, GTK_STOCK_INDEX
, M_MENUITEM
, 0, 0, 1},
1617 {0, 0, 0, M_SEP
, 0, 0, 0},
1618 #define AWAY_OFFSET (39)
1619 {N_("Marked Away"), menu_away
, 0, M_MENUTOG
, MENU_ID_AWAY
, 0, 1, GDK_a
},
1621 {N_("_Usermenu"), 0, 0, M_NEWMENU
, MENU_ID_USERMENU
, 0, 1}, /* 40 */
1623 {N_("S_ettings"), 0, 0, M_NEWMENU
, 0, 0, 1},
1624 {N_("_Preferences"), menu_settings
, GTK_STOCK_PREFERENCES
, M_MENUSTOCK
, 0, 0, 1},
1626 {N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT
, M_MENUSUB
, 0, 0, 1},
1627 {N_("Auto Replace..."), menu_rpopup
, 0, M_MENUITEM
, 0, 0, 1},
1628 {N_("CTCP Replies..."), menu_ctcpguiopen
, 0, M_MENUITEM
, 0, 0, 1},
1629 {N_("Dialog Buttons..."), menu_dlgbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1630 {N_("Keyboard Shortcuts..."), menu_keypopup
, 0, M_MENUITEM
, 0, 0, 1},
1631 {N_("Text Events..."), menu_evtpopup
, 0, M_MENUITEM
, 0, 0, 1},
1632 {N_("URL Handlers..."), menu_urlhandlers
, 0, M_MENUITEM
, 0, 0, 1},
1633 {N_("User Commands..."), menu_usercommands
, 0, M_MENUITEM
, 0, 0, 1},
1634 {N_("Userlist Buttons..."), menu_ulbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1635 {N_("Userlist Popup..."), menu_ulpopup
, 0, M_MENUITEM
, 0, 0, 1},
1636 {0, 0, 0, M_END
, 0, 0, 0}, /* 53 */
1638 {N_("_Window"), 0, 0, M_NEWMENU
, 0, 0, 1},
1639 {N_("Ban List..."), menu_banlist
, 0, M_MENUITEM
, 0, 0, 1},
1640 {N_("Character Chart..."), ascii_open
, 0, M_MENUITEM
, 0, 0, 1},
1641 {N_("Direct Chat..."), menu_dcc_chat_win
, 0, M_MENUITEM
, 0, 0, 1},
1642 {N_("File Transfers..."), menu_dcc_win
, 0, M_MENUITEM
, 0, 0, 1},
1643 {N_("Friends List..."), notify_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1644 {N_("Ignore List..."), ignore_gui_open
, 0, M_MENUITEM
, 0, 0, 1},
1645 {N_("Plugins and Scripts..."), menu_pluginlist
, 0, M_MENUITEM
, 0, 0, 1},
1646 {N_("Raw Log..."), menu_rawlog
, 0, M_MENUITEM
, 0, 0, 1}, /* 62 */
1647 {N_("URL Grabber..."), url_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1648 {0, 0, 0, M_SEP
, 0, 0, 0},
1649 {N_("Reset Marker Line"), menu_resetmarker
, 0, M_MENUITEM
, 0, 0, 1, GDK_m
},
1650 {N_("C_lear Text"), menu_flushbuffer
, GTK_STOCK_CLEAR
, M_MENUSTOCK
, 0, 0, 1, GDK_l
},
1651 #define SEARCH_OFFSET 67
1652 {N_("Search Text..."), menu_search
, GTK_STOCK_FIND
, M_MENUSTOCK
, 0, 0, 1, GDK_f
},
1653 {N_("Save Text..."), menu_savebuffer
, GTK_STOCK_SAVE
, M_MENUSTOCK
, 0, 0, 1},
1655 {N_("_Help"), 0, 0, M_NEWMENU
, 0, 0, 1}, /* 69 */
1656 {N_("_Contents"), menu_docs
, GTK_STOCK_HELP
, M_MENUSTOCK
, 0, 0, 1, GDK_F1
},
1658 {N_("Check for updates"), menu_update
, 0, M_MENUITEM
, 0, 1},
1660 {N_("_About"), menu_about
, GTK_STOCK_ABOUT
, M_MENUSTOCK
, 0, 0, 1},
1662 {0, 0, 0, M_END
, 0, 0, 0},
1666 create_icon_menu (char *labeltext
, void *stock_name
, int is_stock
)
1668 GtkWidget
*item
, *img
;
1671 img
= gtk_image_new_from_stock (stock_name
, GTK_ICON_SIZE_MENU
);
1673 img
= gtk_image_new_from_pixbuf (*((GdkPixbuf
**)stock_name
));
1674 item
= gtk_image_menu_item_new_with_mnemonic (labeltext
);
1675 gtk_image_menu_item_set_image ((GtkImageMenuItem
*)item
, img
);
1676 gtk_widget_show (img
);
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
);
1694 /* === STUFF FOR /MENU === */
1696 static GtkMenuItem
*
1697 menu_find_item (GtkWidget
*menu
, char *name
)
1699 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1702 const char *labeltext
;
1707 child
= GTK_BIN (item
)->child
;
1708 if (child
) /* separators arn't labels, skip them */
1710 labeltext
= g_object_get_data (G_OBJECT (item
), "name");
1712 labeltext
= gtk_label_get_text (GTK_LABEL (child
));
1713 if (!menu_streq (labeltext
, name
, 1))
1715 } else if (name
== NULL
)
1719 items
= items
->next
;
1726 menu_find_path (GtkWidget
*menu
, char *path
)
1733 /* grab the next part of the path */
1734 s
= strchr (path
, '/');
1737 len
= strlen (path
);
1738 len
= MIN (len
, sizeof (name
) - 1);
1739 memcpy (name
, path
, len
);
1742 item
= menu_find_item (menu
, name
);
1746 menu
= gtk_menu_item_get_submenu (item
);
1754 return menu_find_path (menu
, path
+ 1);
1758 menu_find (GtkWidget
*menu
, char *path
, char *label
)
1760 GtkWidget
*item
= NULL
;
1763 menu
= menu_find_path (menu
, path
);
1765 item
= (GtkWidget
*)menu_find_item (menu
, label
);
1770 menu_foreach_gui (menu_entry
*me
, void (*callback
) (GtkWidget
*, menu_entry
*, char *))
1772 GSList
*list
= sess_list
;
1773 int tabdone
= FALSE
;
1777 return; /* not main menu */
1782 /* do it only once for tab sessions, since they share a GUI */
1783 if (!sess
->gui
->is_tab
|| !tabdone
)
1785 callback (sess
->gui
->menu
, me
, NULL
);
1786 if (sess
->gui
->is_tab
)
1794 menu_update_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1798 item
= menu_find (menu
, me
->path
, me
->label
);
1801 gtk_widget_set_sensitive (item
, me
->enable
);
1802 /* must do it without triggering the callback */
1803 if (GTK_IS_CHECK_MENU_ITEM (item
))
1804 GTK_CHECK_MENU_ITEM (item
)->active
= me
->state
;
1808 /* radio state changed via mouse click */
1810 menu_radio_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1816 /* update the state, incase this was changed via right-click. */
1817 /* This will update all other windows and menu bars */
1818 menu_foreach_gui (me
, menu_update_cb
);
1820 if (me
->state
&& me
->cmd
)
1821 handle_command (current_sess
, me
->cmd
, FALSE
);
1824 /* toggle state changed via mouse click */
1826 menu_toggle_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1832 /* update the state, incase this was changed via right-click. */
1833 /* This will update all other windows and menu bars */
1834 menu_foreach_gui (me
, menu_update_cb
);
1837 handle_command (current_sess
, me
->cmd
, FALSE
);
1839 handle_command (current_sess
, me
->ucmd
, FALSE
);
1843 menu_radio_item (char *label
, GtkWidget
*menu
, void *callback
, void *userdata
,
1844 int state
, char *groupname
)
1847 GtkMenuItem
*parent
;
1848 GSList
*grouplist
= NULL
;
1850 parent
= menu_find_item (menu
, groupname
);
1852 grouplist
= gtk_radio_menu_item_get_group ((GtkRadioMenuItem
*)parent
);
1854 item
= gtk_radio_menu_item_new_with_label (grouplist
, label
);
1855 gtk_check_menu_item_set_active ((GtkCheckMenuItem
*)item
, state
);
1856 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1857 g_signal_connect (G_OBJECT (item
), "activate",
1858 G_CALLBACK (callback
), userdata
);
1859 gtk_widget_show (item
);
1865 menu_reorder (GtkMenu
*menu
, GtkWidget
*item
, int pos
)
1867 if (pos
== 0xffff) /* outbound.c uses this default */
1870 if (pos
< 0) /* position offset from end/bottom */
1871 gtk_menu_reorder_child (menu
, item
, (g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
) - 1);
1873 gtk_menu_reorder_child (menu
, item
, pos
);
1877 menu_add_radio (GtkWidget
*menu
, menu_entry
*me
)
1879 GtkWidget
*item
= NULL
;
1880 char *path
= me
->path
+ me
->root_offset
;
1883 menu
= menu_find_path (menu
, path
);
1886 item
= menu_radio_item (me
->label
, menu
, menu_radio_cb
, me
, me
->state
, me
->group
);
1887 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1893 menu_add_toggle (GtkWidget
*menu
, menu_entry
*me
)
1895 GtkWidget
*item
= NULL
;
1896 char *path
= me
->path
+ me
->root_offset
;
1899 menu
= menu_find_path (menu
, path
);
1902 item
= menu_toggle_item (me
->label
, menu
, menu_toggle_cb
, me
, me
->state
);
1903 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1909 menu_add_item (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1911 GtkWidget
*item
= NULL
;
1912 char *path
= me
->path
+ me
->root_offset
;
1915 menu
= menu_find_path (menu
, path
);
1918 item
= menu_quick_item (me
->cmd
, me
->label
, menu
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, target
, me
->icon
);
1919 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1925 menu_add_sub (GtkWidget
*menu
, menu_entry
*me
)
1927 GtkWidget
*item
= NULL
;
1928 char *path
= me
->path
+ me
->root_offset
;
1932 menu
= menu_find_path (menu
, path
);
1936 if (pos
< 0) /* position offset from end/bottom */
1937 pos
= g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
;
1938 menu_quick_sub (me
->label
, menu
, &item
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, pos
);
1944 menu_del_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1946 GtkWidget
*item
= menu_find (menu
, me
->path
+ me
->root_offset
, me
->label
);
1948 gtk_widget_destroy (item
);
1952 menu_add_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1955 GtkAccelGroup
*accel_group
;
1957 if (me
->group
) /* have a group name? Must be a radio item */
1958 item
= menu_add_radio (menu
, me
);
1959 else if (me
->ucmd
) /* have unselect-cmd? Must be a toggle item */
1960 item
= menu_add_toggle (menu
, me
);
1961 else if (me
->cmd
|| !me
->label
) /* label=NULL for separators */
1962 item
= menu_add_item (menu
, me
, target
);
1964 item
= menu_add_sub (menu
, me
);
1968 gtk_widget_set_sensitive (item
, me
->enable
);
1971 accel_group
= g_object_get_data (G_OBJECT (menu
), "accel");
1972 if (accel_group
) /* popup menus don't have them */
1973 gtk_widget_add_accelerator (item
, "activate", accel_group
, me
->key
,
1974 me
->modifier
, GTK_ACCEL_VISIBLE
);
1980 fe_menu_add (menu_entry
*me
)
1984 menu_foreach_gui (me
, menu_add_cb
);
1989 if (!pango_parse_markup (me
->label
, -1, 0, NULL
, &text
, NULL
, NULL
))
1992 /* return the label with markup stripped */
1997 fe_menu_del (menu_entry
*me
)
1999 menu_foreach_gui (me
, menu_del_cb
);
2003 fe_menu_update (menu_entry
*me
)
2005 menu_foreach_gui (me
, menu_update_cb
);
2008 /* used to add custom menus to the right-click menu */
2011 menu_add_plugin_mainmenu_items (GtkWidget
*menu
)
2016 list
= menu_list
; /* outbound.c */
2021 menu_add_cb (menu
, me
, NULL
);
2027 menu_add_plugin_items (GtkWidget
*menu
, char *root
, char *target
)
2032 list
= menu_list
; /* outbound.c */
2036 if (!me
->is_main
&& !strncmp (me
->path
, root
+ 1, root
[0]))
2037 menu_add_cb (menu
, me
, target
);
2042 /* === END STUFF FOR /MENU === */
2045 menu_create_main (void *accel_group
, int bar
, int away
, int toplevel
,
2046 GtkWidget
**menu_widgets
)
2050 GtkWidget
*menu
= 0;
2051 GtkWidget
*menu_item
= 0;
2052 GtkWidget
*menu_bar
;
2053 GtkWidget
*usermenu
= 0;
2054 GtkWidget
*submenu
= 0;
2055 int close_mask
= GDK_CONTROL_MASK
;
2056 int away_mask
= GDK_MOD1_MASK
;
2057 char *key_theme
= NULL
;
2058 GtkSettings
*settings
;
2059 GSList
*group
= NULL
;
2062 menu_bar
= gtk_menu_bar_new ();
2064 menu_bar
= gtk_menu_new ();
2066 /* /MENU needs to know this later */
2067 g_object_set_data (G_OBJECT (menu_bar
), "accel", accel_group
);
2069 g_signal_connect (G_OBJECT (menu_bar
), "can-activate-accel",
2070 G_CALLBACK (menu_canacaccel
), 0);
2072 /* set the initial state of toggles */
2073 mymenu
[MENUBAR_OFFSET
].state
= !prefs
.hidemenu
;
2074 mymenu
[MENUBAR_OFFSET
+1].state
= prefs
.topicbar
;
2075 mymenu
[MENUBAR_OFFSET
+2].state
= !prefs
.hideuserlist
;
2076 mymenu
[MENUBAR_OFFSET
+3].state
= prefs
.userlistbuttons
;
2077 mymenu
[MENUBAR_OFFSET
+4].state
= prefs
.chanmodebuttons
;
2079 mymenu
[AWAY_OFFSET
].state
= away
;
2081 switch (prefs
.tab_layout
)
2084 mymenu
[TABS_OFFSET
].state
= 1;
2085 mymenu
[TABS_OFFSET
+1].state
= 0;
2088 mymenu
[TABS_OFFSET
].state
= 0;
2089 mymenu
[TABS_OFFSET
+1].state
= 1;
2092 mymenu
[METRE_OFFSET
].state
= 0;
2093 mymenu
[METRE_OFFSET
+1].state
= 0;
2094 mymenu
[METRE_OFFSET
+2].state
= 0;
2095 mymenu
[METRE_OFFSET
+3].state
= 0;
2096 switch (prefs
.lagometer
)
2099 mymenu
[METRE_OFFSET
].state
= 1;
2102 mymenu
[METRE_OFFSET
+1].state
= 1;
2105 mymenu
[METRE_OFFSET
+2].state
= 1;
2108 mymenu
[METRE_OFFSET
+3].state
= 1;
2111 /* change Close binding to ctrl-shift-w when using emacs keys */
2112 settings
= gtk_widget_get_settings (menu_bar
);
2115 g_object_get (settings
, "gtk-key-theme-name", &key_theme
, NULL
);
2118 if (!strcasecmp (key_theme
, "Emacs"))
2120 close_mask
= GDK_SHIFT_MASK
| GDK_CONTROL_MASK
;
2121 mymenu
[SEARCH_OFFSET
].key
= 0;
2127 /* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2129 char *help
= _("_Help");
2130 char *under
= strchr (help
, '_');
2131 if (under
&& (under
[1] == 'a' || under
[1] == 'A'))
2132 away_mask
= GDK_MOD1_MASK
| GDK_CONTROL_MASK
;
2137 mymenu
[DETACH_OFFSET
].text
= N_("_Detach");
2138 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2142 mymenu
[DETACH_OFFSET
].text
= N_("_Attach");
2143 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2149 if (mymenu
[i
].id
== MENU_ID_USERMENU
&& !prefs
.gui_usermenu
)
2155 switch (mymenu
[i
].type
)
2159 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2160 item
= menu
= gtk_menu_new ();
2161 if (mymenu
[i
].id
== MENU_ID_USERMENU
)
2163 menu_item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2164 /* record the English name for /menu */
2165 g_object_set_data (G_OBJECT (menu_item
), "name", mymenu
[i
].text
);
2166 gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar
), menu_item
);
2167 gtk_widget_show (menu_item
);
2171 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, FALSE
);
2175 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2179 item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2181 if (mymenu
[i
].key
!= 0)
2182 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2184 mymenu
[i
].key
== GDK_F1
? 0 :
2185 mymenu
[i
].key
== GDK_w
? close_mask
:
2188 if (mymenu
[i
].callback
)
2189 g_signal_connect (G_OBJECT (item
), "activate",
2190 G_CALLBACK (mymenu
[i
].callback
), 0);
2192 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2194 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2195 gtk_widget_show (item
);
2199 item
= gtk_check_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2201 /* must avoid callback for Radio buttons */
2202 GTK_CHECK_MENU_ITEM (item
)->active
= mymenu
[i
].state
;
2203 /*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2205 if (mymenu
[i
].key
!= 0)
2206 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2207 mymenu
[i
].key
, mymenu
[i
].id
== MENU_ID_AWAY
?
2208 away_mask
: GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
2209 if (mymenu
[i
].callback
)
2210 g_signal_connect (G_OBJECT (item
), "toggled",
2211 G_CALLBACK (mymenu
[i
].callback
), 0);
2213 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2215 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2216 gtk_widget_show (item
);
2217 gtk_widget_set_sensitive (item
, mymenu
[i
].sensitive
);
2221 item
= gtk_radio_menu_item_new_with_mnemonic (group
, _(mymenu
[i
].text
));
2222 group
= gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item
));
2226 item
= gtk_menu_item_new ();
2227 gtk_widget_set_sensitive (item
, FALSE
);
2228 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2229 gtk_widget_show (item
);
2234 submenu
= gtk_menu_new ();
2235 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2236 /* record the English name for /menu */
2237 g_object_set_data (G_OBJECT (item
), "name", mymenu
[i
].text
);
2238 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item
), submenu
);
2239 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2240 gtk_widget_show (item
);
2243 /*case M_END:*/ default:
2248 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2249 menu_add_plugin_mainmenu_items (menu_bar
);
2252 usermenu_create (usermenu
);
2258 /* record this GtkWidget * so it's state might be changed later */
2259 if (mymenu
[i
].id
!= 0 && menu_widgets
)
2260 /* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2261 menu_widgets
[mymenu
[i
].id
] = item
;