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"
71 static GSList
*submenu_list
;
91 unsigned char type
; /* M_XXX */
92 unsigned char id
; /* MENU_ID_XXX (menu.h) */
93 unsigned char state
; /* ticked or not? */
94 unsigned char sensitive
; /* shaded out? */
95 guint key
; /* GDK_x */
98 #define XCMENU_DOLIST 1
99 #define XCMENU_SHADED 1
100 #define XCMENU_MARKUP 2
101 #define XCMENU_MNEMONIC 4
103 /* execute a userlistbutton/popupmenu command */
106 nick_command (session
* sess
, char *cmd
)
109 xchat_exec (cmd
+ 1);
111 handle_command (sess
, cmd
, TRUE
);
114 /* fill in the %a %s %n etc and execute the command */
117 nick_command_parse (session
*sess
, char *cmd
, char *nick
, char *allnick
)
120 char *host
= _("Host unknown");
124 /* if (sess->type == SESS_DIALOG)
126 buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
127 buf = strrchr (buf, '@');
132 user
= userlist_find (sess
, nick
);
133 if (user
&& user
->hostname
)
134 host
= strchr (user
->hostname
, '@') + 1;
137 /* this can't overflow, since popup->cmd is only 256 */
138 len
= strlen (cmd
) + strlen (nick
) + strlen (allnick
) + 512;
141 auto_insert (buf
, len
, cmd
, 0, 0, allnick
, sess
->channel
, "",
142 server_get_network (sess
->server
, TRUE
), host
,
143 sess
->server
->nick
, nick
);
145 nick_command (sess
, buf
);
150 /* userlist button has been clicked */
153 userlist_button_cb (GtkWidget
* button
, char *cmd
)
155 int i
, num_sel
, using_allnicks
= FALSE
;
156 char **nicks
, *allnicks
;
162 if (strstr (cmd
, "%a"))
163 using_allnicks
= TRUE
;
165 if (sess
->type
== SESS_DIALOG
)
167 /* fake a selection */
168 nicks
= malloc (sizeof (char *) * 2);
169 nicks
[0] = g_strdup (sess
->channel
);
174 /* find number of selected rows */
175 nicks
= userlist_selection_list (sess
->gui
->user_tree
, &num_sel
);
178 nick_command_parse (sess
, cmd
, "", "");
183 /* create "allnicks" string */
184 allnicks
= malloc (((NICKLEN
+ 1) * num_sel
) + 1);
191 strcat (allnicks
, " ");
192 strcat (allnicks
, nicks
[i
]);
197 /* if not using "%a", execute the command once for each nickname */
199 nick_command_parse (sess
, cmd
, nicks
[i
], "");
208 nick_command_parse (sess
, cmd
, nick
, allnicks
);
214 g_free (nicks
[num_sel
]);
221 /* a popup-menu-item has been selected */
224 popup_menu_cb (GtkWidget
* item
, char *cmd
)
228 /* the userdata is set in menu_quick_item() */
229 nick
= g_object_get_data (G_OBJECT (item
), "u");
231 if (!nick
) /* userlist popup menu */
233 /* treat it just like a userlist button */
234 userlist_button_cb (NULL
, cmd
);
238 if (!current_sess
) /* for url grabber window */
239 nick_command_parse (sess_list
->data
, cmd
, nick
, nick
);
241 nick_command_parse (current_sess
, cmd
, nick
, nick
);
245 menu_toggle_item (char *label
, GtkWidget
*menu
, void *callback
, void *userdata
,
250 item
= gtk_check_menu_item_new_with_mnemonic (label
);
251 gtk_check_menu_item_set_active ((GtkCheckMenuItem
*)item
, state
);
252 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
253 g_signal_connect (G_OBJECT (item
), "activate",
254 G_CALLBACK (callback
), userdata
);
255 gtk_widget_show (item
);
261 menu_quick_item (char *cmd
, char *label
, GtkWidget
* menu
, int flags
,
262 gpointer userdata
, char *icon
)
264 GtkWidget
*img
, *item
;
268 item
= gtk_menu_item_new ();
273 /*if (flags & XCMENU_MARKUP)
274 item = gtk_image_menu_item_new_with_markup (label);
276 item
= gtk_image_menu_item_new_with_mnemonic (label
);
278 if (access (icon
, R_OK
) == 0) /* try fullpath */
279 img
= gtk_image_new_from_file (icon
);
282 /* try relative to ~/.xchat2 */
283 path
= g_strdup_printf ("%s/%s", get_xdir_fs (), icon
);
284 if (access (path
, R_OK
) == 0)
285 img
= gtk_image_new_from_file (path
);
287 img
= gtk_image_new_from_stock (icon
, GTK_ICON_SIZE_MENU
);
292 gtk_image_menu_item_set_image ((GtkImageMenuItem
*)item
, img
);
296 if (flags
& XCMENU_MARKUP
)
298 item
= gtk_menu_item_new_with_label ("");
299 if (flags
& XCMENU_MNEMONIC
)
300 gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item
)->child
), label
);
302 gtk_label_set_markup (GTK_LABEL (GTK_BIN (item
)->child
), label
);
305 if (flags
& XCMENU_MNEMONIC
)
306 item
= gtk_menu_item_new_with_mnemonic (label
);
308 item
= gtk_menu_item_new_with_label (label
);
312 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
313 g_object_set_data (G_OBJECT (item
), "u", userdata
);
315 g_signal_connect (G_OBJECT (item
), "activate",
316 G_CALLBACK (popup_menu_cb
), cmd
);
317 if (flags
& XCMENU_SHADED
)
318 gtk_widget_set_sensitive (GTK_WIDGET (item
), FALSE
);
319 gtk_widget_show_all (item
);
325 menu_quick_item_with_callback (void *callback
, char *label
, GtkWidget
* menu
,
330 item
= gtk_menu_item_new_with_label (label
);
331 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
332 g_signal_connect (G_OBJECT (item
), "activate",
333 G_CALLBACK (callback
), arg
);
334 gtk_widget_show (item
);
338 menu_quick_sub (char *name
, GtkWidget
*menu
, GtkWidget
**sub_item_ret
, int flags
, int pos
)
346 /* Code to add a submenu */
347 sub_menu
= gtk_menu_new ();
348 if (flags
& XCMENU_MARKUP
)
350 sub_item
= gtk_menu_item_new_with_label ("");
351 gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item
)->child
), name
);
355 if (flags
& XCMENU_MNEMONIC
)
356 sub_item
= gtk_menu_item_new_with_mnemonic (name
);
358 sub_item
= gtk_menu_item_new_with_label (name
);
360 gtk_menu_shell_insert (GTK_MENU_SHELL (menu
), sub_item
, pos
);
361 gtk_widget_show (sub_item
);
362 gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item
), sub_menu
);
365 *sub_item_ret
= sub_item
;
367 if (flags
& XCMENU_DOLIST
)
368 /* We create a new element in the list */
369 submenu_list
= g_slist_prepend (submenu_list
, sub_menu
);
376 /* Just delete the first element in the linked list pointed to by first */
378 submenu_list
= g_slist_remove (submenu_list
, submenu_list
->data
);
381 return (submenu_list
->data
);
387 toggle_cb (GtkWidget
*item
, char *pref_name
)
391 if (GTK_CHECK_MENU_ITEM (item
)->active
)
392 snprintf (buf
, sizeof (buf
), "set %s 1", pref_name
);
394 snprintf (buf
, sizeof (buf
), "set %s 0", pref_name
);
396 handle_command (current_sess
, buf
, FALSE
);
400 is_in_path (char *cmd
)
402 char *prog
= strdup (cmd
+ 1); /* 1st char is "!" */
403 char *space
, *path
, *orig
;
405 orig
= prog
; /* save for free()ing */
406 /* special-case these default entries. */
407 /* 123456789012345678 */
408 if (strncmp (prog
, "gnome-terminal -x ", 18) == 0)
409 /* don't check for gnome-terminal, but the thing it's executing! */
412 space
= strchr (prog
, ' '); /* this isn't 100% but good enuf */
416 path
= g_find_program_in_path (prog
);
428 /* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
431 menu_extract_icon (char *name
, char **label
, char **icon
)
442 if (p
== name
|| p
[-1] != '\\')
456 if (start
&& start
!= end
)
458 *label
= g_strndup (name
, (start
- name
) - 1);
459 *icon
= g_strndup (start
, (end
- start
) - 1);
463 *label
= g_strdup (name
);
468 /* append items to "menu" using the (struct popup*) list provided */
471 menu_create (GtkWidget
*menu
, GSList
*list
, char *target
, int check_path
)
474 GtkWidget
*tempmenu
= menu
, *subitem
= NULL
;
477 submenu_list
= g_slist_prepend (0, menu
);
480 pop
= (struct popup
*) list
->data
;
482 if (!strncasecmp (pop
->name
, "SUB", 3))
485 tempmenu
= menu_quick_sub (pop
->cmd
, tempmenu
, &subitem
, XCMENU_DOLIST
|XCMENU_MNEMONIC
, -1);
487 } else if (!strncasecmp (pop
->name
, "TOGGLE", 6))
490 menu_toggle_item (pop
->name
+ 7, tempmenu
, toggle_cb
, pop
->cmd
,
491 cfg_get_bool (pop
->cmd
));
493 } else if (!strncasecmp (pop
->name
, "ENDSUB", 6))
495 /* empty sub menu due to no programs in PATH? */
496 if (check_path
&& childcount
< 1)
497 gtk_widget_destroy (subitem
);
500 if (tempmenu
!= menu
)
501 tempmenu
= menu_quick_endsub ();
502 /* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
504 } else if (!strncasecmp (pop
->name
, "SEP", 3))
506 menu_quick_item (0, 0, tempmenu
, XCMENU_SHADED
, 0, 0);
512 /* default command in xchat.c */
513 if (pop
->cmd
[0] == 'n' && !strcmp (pop
->cmd
, "notify -n ASK %s"))
515 /* don't create this item if already in notify list */
516 if (!target
|| notify_is_in_list (current_sess
->server
, target
))
523 menu_extract_icon (pop
->name
, &label
, &icon
);
525 if (!check_path
|| pop
->cmd
[0] != '!')
527 menu_quick_item (pop
->cmd
, label
, tempmenu
, 0, target
, icon
);
528 /* check if the program is in path, if not, leave it out! */
529 } else if (is_in_path (pop
->cmd
))
532 menu_quick_item (pop
->cmd
, label
, tempmenu
, 0, target
, icon
);
542 /* Let's clean up the linked list from mem */
544 submenu_list
= g_slist_remove (submenu_list
, submenu_list
->data
);
547 static char *str_copy
= NULL
; /* for all pop-up menus */
548 static GtkWidget
*nick_submenu
= NULL
; /* user info submenu */
551 menu_destroy (GtkWidget
*menu
, gpointer objtounref
)
553 gtk_widget_destroy (menu
);
554 g_object_unref (menu
);
556 g_object_unref (G_OBJECT (objtounref
));
561 menu_popup (GtkWidget
*menu
, GdkEventButton
*event
, gpointer objtounref
)
563 if (event
&& event
->window
)
564 gtk_menu_set_screen (GTK_MENU (menu
), gdk_drawable_get_screen (event
->window
));
567 g_object_ref_sink (menu
);
568 g_object_unref (menu
);
569 g_signal_connect (G_OBJECT (menu
), "selection-done",
570 G_CALLBACK (menu_destroy
), objtounref
);
571 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
, NULL
, NULL
,
572 0, event
? event
->time
: 0);
576 menu_nickinfo_cb (GtkWidget
*menu
, session
*sess
)
580 if (!is_session (sess
))
584 snprintf (buf
, sizeof (buf
), "WHOIS %s %s", str_copy
, str_copy
);
585 handle_command (sess
, buf
, FALSE
);
586 /* and hide the output */
587 sess
->server
->skip_next_whois
= 1;
591 copy_to_clipboard_cb (GtkWidget
*item
, char *url
)
593 gtkutil_copy_to_clipboard (item
, NULL
, url
);
596 /* returns boolean: Some data is missing */
599 menu_create_nickinfo_menu (struct User
*user
, GtkWidget
*submenu
)
604 struct away_msg
*away
;
605 gboolean missing
= FALSE
;
608 /* let the translators tweak this if need be */
609 fmt
= _("<tt><b>%-11s</b></tt> %s");
610 snprintf (unknown
, sizeof (unknown
), "<i>%s</i>", _("Unknown"));
614 real
= strip_color (user
->realname
, -1, STRIP_ALL
|STRIP_ESCMARKUP
);
615 snprintf (buf
, sizeof (buf
), fmt
, _("Real Name:"), real
);
619 snprintf (buf
, sizeof (buf
), fmt
, _("Real Name:"), unknown
);
621 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
622 g_signal_connect (G_OBJECT (item
), "activate",
623 G_CALLBACK (copy_to_clipboard_cb
),
624 user
->realname
? user
->realname
: unknown
);
626 snprintf (buf
, sizeof (buf
), fmt
, _("User:"),
627 user
->hostname
? user
->hostname
: unknown
);
628 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
629 g_signal_connect (G_OBJECT (item
), "activate",
630 G_CALLBACK (copy_to_clipboard_cb
),
631 user
->hostname
? user
->hostname
: unknown
);
633 snprintf (buf
, sizeof (buf
), fmt
, _("Account:"),
634 user
->account
? user
->account
: unknown
);
635 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
636 g_signal_connect (G_OBJECT (item
), "activate",
637 G_CALLBACK (copy_to_clipboard_cb
),
638 user
->account
? user
->account
: unknown
);
640 snprintf (buf
, sizeof (buf
), fmt
, _("Country:"),
641 user
->hostname
? country(user
->hostname
) : unknown
);
642 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
643 g_signal_connect (G_OBJECT (item
), "activate",
644 G_CALLBACK (copy_to_clipboard_cb
),
645 user
->hostname
? country(user
->hostname
) : unknown
);
647 snprintf (buf
, sizeof (buf
), fmt
, _("Server:"),
648 user
->servername
? user
->servername
: unknown
);
649 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
650 g_signal_connect (G_OBJECT (item
), "activate",
651 G_CALLBACK (copy_to_clipboard_cb
),
652 user
->servername
? user
->servername
: unknown
);
658 snprintf (min
, sizeof (min
), _("%u minutes ago"),
659 (unsigned int) ((time (0) - user
->lasttalk
) / 60));
660 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), min
);
663 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), unknown
);
665 menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
669 away
= server_away_find_message (current_sess
->server
, user
->nick
);
672 char *msg
= strip_color (away
->message
? away
->message
: unknown
, -1, STRIP_ALL
|STRIP_ESCMARKUP
);
673 snprintf (buf
, sizeof (buf
), fmt
, _("Away Msg:"), msg
);
675 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
676 g_signal_connect (G_OBJECT (item
), "activate",
677 G_CALLBACK (copy_to_clipboard_cb
),
678 away
->message
? away
->message
: unknown
);
688 fe_userlist_update (session
*sess
, struct User
*user
)
692 if (!nick_submenu
|| !str_copy
)
695 /* not the same nick as the menu? */
696 if (sess
->server
->p_cmp (user
->nick
, str_copy
))
699 /* get rid of the "show" signal */
700 g_signal_handlers_disconnect_by_func (nick_submenu
, menu_nickinfo_cb
, sess
);
702 /* destroy all the old items */
703 items
= ((GtkMenuShell
*) nick_submenu
)->children
;
707 gtk_widget_destroy (items
->data
);
711 /* and re-create them with new info */
712 menu_create_nickinfo_menu (user
, nick_submenu
);
716 menu_nickmenu (session
*sess
, GdkEventButton
*event
, char *nick
, int num_sel
)
720 GtkWidget
*submenu
, *menu
= gtk_menu_new ();
724 str_copy
= strdup (nick
);
726 submenu_list
= 0; /* first time through, might not be 0 */
728 /* more than 1 nick selected? */
731 snprintf (buf
, sizeof (buf
), _("%d nicks selected."), num_sel
);
732 menu_quick_item (0, buf
, menu
, 0, 0, 0);
733 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
736 user
= userlist_find (sess
, nick
); /* lasttalk is channel specific */
738 user
= userlist_find_global (current_sess
->server
, nick
);
741 nick_submenu
= submenu
= menu_quick_sub (nick
, menu
, NULL
, XCMENU_DOLIST
, -1);
743 if (menu_create_nickinfo_menu (user
, submenu
) ||
744 !user
->hostname
|| !user
->realname
|| !user
->servername
)
746 g_signal_connect (G_OBJECT (submenu
), "show", G_CALLBACK (menu_nickinfo_cb
), sess
);
749 menu_quick_endsub ();
750 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
755 menu_create (menu
, popup_list
, NULL
, FALSE
);
757 menu_create (menu
, popup_list
, str_copy
, FALSE
);
759 if (num_sel
== 0) /* xtext click */
760 menu_add_plugin_items (menu
, "\x5$NICK", str_copy
);
761 else /* userlist treeview click */
762 menu_add_plugin_items (menu
, "\x5$NICK", NULL
);
764 menu_popup (menu
, event
, NULL
);
767 /* stuff for the View menu */
770 menu_showhide_cb (session
*sess
)
773 gtk_widget_hide (sess
->gui
->menu
);
775 gtk_widget_show (sess
->gui
->menu
);
779 menu_topic_showhide_cb (session
*sess
)
782 gtk_widget_show (sess
->gui
->topic_bar
);
784 gtk_widget_hide (sess
->gui
->topic_bar
);
788 menu_userlist_showhide_cb (session
*sess
)
790 mg_decide_userlist (sess
, TRUE
);
794 menu_ulbuttons_showhide_cb (session
*sess
)
796 if (prefs
.userlistbuttons
)
797 gtk_widget_show (sess
->gui
->button_box
);
799 gtk_widget_hide (sess
->gui
->button_box
);
803 menu_cmbuttons_showhide_cb (session
*sess
)
808 if (prefs
.chanmodebuttons
)
809 gtk_widget_show (sess
->gui
->topicbutton_box
);
811 gtk_widget_hide (sess
->gui
->topicbutton_box
);
814 gtk_widget_hide (sess
->gui
->topicbutton_box
);
819 menu_setting_foreach (void (*callback
) (session
*), int id
, guint state
)
823 int maindone
= FALSE
; /* do it only once for EVERY tab */
830 if (!sess
->gui
->is_tab
|| !maindone
)
832 if (sess
->gui
->is_tab
)
835 GTK_CHECK_MENU_ITEM (sess
->gui
->menu_item
[id
])->active
= state
;
845 menu_bar_toggle (void)
847 prefs
.hidemenu
= !prefs
.hidemenu
;
848 menu_setting_foreach (menu_showhide_cb
, MENU_ID_MENUBAR
, !prefs
.hidemenu
);
852 menu_bar_toggle_cb (void)
856 fe_message (_("The Menubar is now hidden. You can show it again"
857 " by pressing F9 or right-clicking in a blank part of"
858 " the main text area."), FE_MSG_INFO
);
862 menu_topicbar_toggle (GtkWidget
*wid
, gpointer ud
)
864 prefs
.topicbar
= !prefs
.topicbar
;
865 menu_setting_foreach (menu_topic_showhide_cb
, MENU_ID_TOPICBAR
,
870 menu_userlist_toggle (GtkWidget
*wid
, gpointer ud
)
872 prefs
.hideuserlist
= !prefs
.hideuserlist
;
873 menu_setting_foreach (menu_userlist_showhide_cb
, MENU_ID_USERLIST
,
874 !prefs
.hideuserlist
);
878 menu_ulbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
880 prefs
.userlistbuttons
= !prefs
.userlistbuttons
;
881 menu_setting_foreach (menu_ulbuttons_showhide_cb
, MENU_ID_ULBUTTONS
,
882 prefs
.userlistbuttons
);
886 menu_cmbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
888 prefs
.chanmodebuttons
= !prefs
.chanmodebuttons
;
889 menu_setting_foreach (menu_cmbuttons_showhide_cb
, MENU_ID_MODEBUTTONS
,
890 prefs
.chanmodebuttons
);
894 menu_middlemenu (session
*sess
, GdkEventButton
*event
)
897 GtkAccelGroup
*accel_group
;
899 accel_group
= gtk_accel_group_new ();
900 menu
= menu_create_main (accel_group
, FALSE
, sess
->server
->is_away
, !sess
->gui
->is_tab
, NULL
);
901 menu_popup (menu
, event
, accel_group
);
905 open_url_cb (GtkWidget
*item
, char *url
)
909 /* pass this to /URL so it can handle irc:// */
910 snprintf (buf
, sizeof (buf
), "URL %s", url
);
911 handle_command (current_sess
, buf
, FALSE
);
915 menu_urlmenu (GdkEventButton
*event
, char *url
)
922 str_copy
= strdup (url
);
924 menu
= gtk_menu_new ();
925 /* more than 51 chars? Chop it */
926 if (g_utf8_strlen (str_copy
, -1) >= 52)
928 tmp
= strdup (str_copy
);
929 chop
= g_utf8_offset_to_pointer (tmp
, 48);
930 chop
[0] = chop
[1] = chop
[2] = '.';
932 menu_quick_item (0, tmp
, menu
, XCMENU_SHADED
, 0, 0);
936 menu_quick_item (0, str_copy
, menu
, XCMENU_SHADED
, 0, 0);
938 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
940 /* Two hardcoded entries */
941 if (strncmp (str_copy
, "irc://", 6) == 0 ||
942 strncmp (str_copy
, "ircs://",7) == 0)
943 menu_quick_item_with_callback (open_url_cb
, _("Connect"), menu
, str_copy
);
945 menu_quick_item_with_callback (open_url_cb
, _("Open Link in Browser"), menu
, str_copy
);
946 menu_quick_item_with_callback (copy_to_clipboard_cb
, _("Copy Selected Link"), menu
, str_copy
);
947 /* custom ones from urlhandlers.conf */
948 menu_create (menu
, urlhandler_list
, str_copy
, TRUE
);
949 menu_add_plugin_items (menu
, "\x4$URL", str_copy
);
950 menu_popup (menu
, event
, NULL
);
954 menu_chan_cycle (GtkWidget
* menu
, char *chan
)
960 snprintf (tbuf
, sizeof tbuf
, "CYCLE %s", chan
);
961 handle_command (current_sess
, tbuf
, FALSE
);
966 menu_chan_part (GtkWidget
* menu
, char *chan
)
972 snprintf (tbuf
, sizeof tbuf
, "part %s", chan
);
973 handle_command (current_sess
, tbuf
, FALSE
);
978 menu_chan_join (GtkWidget
* menu
, char *chan
)
984 snprintf (tbuf
, sizeof tbuf
, "join %s", chan
);
985 handle_command (current_sess
, tbuf
, FALSE
);
990 menu_chanmenu (struct session
*sess
, GdkEventButton
* event
, char *chan
)
993 int is_joined
= FALSE
;
995 if (find_channel (sess
->server
, chan
))
1000 str_copy
= strdup (chan
);
1002 menu
= gtk_menu_new ();
1004 menu_quick_item (0, chan
, menu
, XCMENU_SHADED
, str_copy
, 0);
1005 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, str_copy
, 0);
1008 menu_quick_item_with_callback (menu_chan_join
, _("Join Channel"), menu
,
1012 menu_quick_item_with_callback (menu_chan_part
, _("Part Channel"), menu
,
1014 menu_quick_item_with_callback (menu_chan_cycle
, _("Cycle Channel"), menu
,
1018 menu_addfavoritemenu (sess
->server
, menu
, str_copy
);
1020 menu_add_plugin_items (menu
, "\x5$CHAN", str_copy
);
1021 menu_popup (menu
, event
, NULL
);
1025 menu_delfav_cb (GtkWidget
*item
, server
*serv
)
1027 servlist_autojoinedit (serv
->network
, str_copy
, FALSE
);
1031 menu_addfav_cb (GtkWidget
*item
, server
*serv
)
1033 servlist_autojoinedit (serv
->network
, str_copy
, TRUE
);
1037 menu_addfavoritemenu (server
*serv
, GtkWidget
*menu
, char *channel
)
1042 if (channel
!= str_copy
)
1046 str_copy
= strdup (channel
);
1049 if (joinlist_is_in_list (serv
, channel
))
1050 mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE
, menu
, menu_delfav_cb
, serv
);
1052 mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD
, menu
, menu_addfav_cb
, serv
);
1056 menu_open_server_list (GtkWidget
*wid
, gpointer none
)
1058 fe_serverlist_open (current_sess
);
1062 menu_settings (GtkWidget
* wid
, gpointer none
)
1064 extern void setup_open (void);
1069 menu_usermenu (void)
1071 editlist_gui_open (NULL
, NULL
, usermenu_list
, _("XChat: User menu"),
1072 "usermenu", "usermenu.conf", 0);
1076 usermenu_create (GtkWidget
*menu
)
1078 menu_create (menu
, usermenu_list
, "", FALSE
);
1079 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0); /* sep */
1080 menu_quick_item_with_callback (menu_usermenu
, _("Edit This Menu..."), menu
, 0);
1084 usermenu_destroy (GtkWidget
* menu
)
1086 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1092 gtk_widget_destroy (items
->data
);
1098 usermenu_update (void)
1100 int done_main
= FALSE
;
1101 GSList
*list
= sess_list
;
1108 menu
= sess
->gui
->menu_item
[MENU_ID_USERMENU
];
1109 if (sess
->gui
->is_tab
)
1111 if (!done_main
&& menu
)
1113 usermenu_destroy (menu
);
1114 usermenu_create (menu
);
1119 usermenu_destroy (menu
);
1120 usermenu_create (menu
);
1127 menu_newserver_window (GtkWidget
* wid
, gpointer none
)
1129 int old
= prefs
.tabchannels
;
1131 prefs
.tabchannels
= 0;
1132 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1133 prefs
.tabchannels
= old
;
1137 menu_newchannel_window (GtkWidget
* wid
, gpointer none
)
1139 int old
= prefs
.tabchannels
;
1141 prefs
.tabchannels
= 0;
1142 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1143 prefs
.tabchannels
= old
;
1147 menu_newserver_tab (GtkWidget
* wid
, gpointer none
)
1149 int old
= prefs
.tabchannels
;
1150 int oldf
= prefs
.newtabstofront
;
1152 prefs
.tabchannels
= 1;
1153 /* force focus if setting is "only requested tabs" */
1154 if (prefs
.newtabstofront
== 2)
1155 prefs
.newtabstofront
= 1;
1156 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1157 prefs
.tabchannels
= old
;
1158 prefs
.newtabstofront
= oldf
;
1162 menu_newchannel_tab (GtkWidget
* wid
, gpointer none
)
1164 int old
= prefs
.tabchannels
;
1166 prefs
.tabchannels
= 1;
1167 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1168 prefs
.tabchannels
= old
;
1172 menu_rawlog (GtkWidget
* wid
, gpointer none
)
1174 open_rawlog (current_sess
->server
);
1178 menu_detach (GtkWidget
* wid
, gpointer none
)
1180 mg_detach (current_sess
, 0);
1184 menu_close (GtkWidget
* wid
, gpointer none
)
1186 mg_close_sess (current_sess
);
1190 menu_quit (GtkWidget
* wid
, gpointer none
)
1192 mg_open_quit_dialog (FALSE
);
1198 search_open (current_sess
);
1202 menu_resetmarker (GtkWidget
* wid
, gpointer none
)
1204 gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess
->gui
->xtext
));
1208 menu_flushbuffer (GtkWidget
* wid
, gpointer none
)
1210 fe_text_clear (current_sess
, 0);
1214 savebuffer_req_done (session
*sess
, char *file
)
1221 fh
= open (file
, O_TRUNC
| O_WRONLY
| O_CREAT
, 0600);
1224 gtk_xtext_save (GTK_XTEXT (sess
->gui
->xtext
), fh
);
1230 menu_savebuffer (GtkWidget
* wid
, gpointer none
)
1232 gtkutil_file_req (_("Select an output filename"), savebuffer_req_done
,
1233 current_sess
, NULL
, FRF_WRITE
);
1237 menu_disconnect (GtkWidget
* wid
, gpointer none
)
1239 handle_command (current_sess
, "DISCON", FALSE
);
1243 menu_reconnect (GtkWidget
* wid
, gpointer none
)
1245 if (current_sess
->server
->hostname
[0])
1246 handle_command (current_sess
, "RECONNECT", FALSE
);
1248 fe_serverlist_open (current_sess
);
1252 menu_join_cb (GtkWidget
*dialog
, gint response
, GtkEntry
*entry
)
1256 case GTK_RESPONSE_ACCEPT
:
1257 menu_chan_join (NULL
, entry
->text
);
1260 case GTK_RESPONSE_HELP
:
1261 chanlist_opengui (current_sess
->server
, TRUE
);
1265 gtk_widget_destroy (dialog
);
1269 menu_join_entry_cb (GtkWidget
*entry
, GtkDialog
*dialog
)
1271 gtk_dialog_response (dialog
, GTK_RESPONSE_ACCEPT
);
1275 menu_join (GtkWidget
* wid
, gpointer none
)
1277 GtkWidget
*hbox
, *dialog
, *entry
, *label
;
1279 dialog
= gtk_dialog_new_with_buttons (_("Join Channel"),
1280 GTK_WINDOW (parent_window
), 0,
1281 _("Retrieve channel list..."), GTK_RESPONSE_HELP
,
1282 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
1283 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
1285 gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog
)->vbox
), TRUE
);
1286 gtk_window_set_position (GTK_WINDOW (dialog
), GTK_WIN_POS_MOUSE
);
1287 hbox
= gtk_hbox_new (TRUE
, 0);
1289 entry
= gtk_entry_new ();
1290 GTK_ENTRY (entry
)->editable
= 0; /* avoid auto-selection */
1291 gtk_entry_set_text (GTK_ENTRY (entry
), "#");
1292 g_signal_connect (G_OBJECT (entry
), "activate",
1293 G_CALLBACK (menu_join_entry_cb
), dialog
);
1294 gtk_box_pack_end (GTK_BOX (hbox
), entry
, 0, 0, 0);
1296 label
= gtk_label_new (_("Enter Channel to Join:"));
1297 gtk_box_pack_end (GTK_BOX (hbox
), label
, 0, 0, 0);
1299 g_signal_connect (G_OBJECT (dialog
), "response",
1300 G_CALLBACK (menu_join_cb
), entry
);
1302 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog
)->vbox
), hbox
);
1304 gtk_widget_show_all (dialog
);
1306 gtk_editable_set_editable (GTK_EDITABLE (entry
), TRUE
);
1307 gtk_editable_set_position (GTK_EDITABLE (entry
), 1);
1311 menu_away (GtkCheckMenuItem
*item
, gpointer none
)
1313 handle_command (current_sess
, item
->active
? "away" : "back", FALSE
);
1317 menu_chanlist (GtkWidget
* wid
, gpointer none
)
1319 chanlist_opengui (current_sess
->server
, FALSE
);
1323 menu_banlist (GtkWidget
* wid
, gpointer none
)
1325 banlist_opengui (current_sess
);
1331 menu_loadplugin (void)
1337 menu_pluginlist (void)
1344 #define menu_pluginlist 0
1345 #define menu_loadplugin 0
1349 #define usercommands_help _("User Commands - Special codes:\n\n"\
1350 "%c = current channel\n"\
1351 "%e = current network name\n"\
1352 "%m = machine info\n"\
1355 "%v = xchat version\n"\
1358 "&2 = word 2 to the end of line\n"\
1359 "&3 = word 3 to the end of line\n\n"\
1361 "/cmd john hello\n\n"\
1362 "%2 would be \042john\042\n"\
1363 "&2 would be \042john hello\042.")
1365 #define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1366 "%a = all selected nicks\n"\
1367 "%c = current channel\n"\
1368 "%e = current network name\n"\
1369 "%h = selected nick's hostname\n"\
1370 "%m = machine info\n"\
1372 "%s = selected nick\n"\
1375 #define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1376 "%a = all selected nicks\n"\
1377 "%c = current channel\n"\
1378 "%e = current network name\n"\
1379 "%h = selected nick's hostname\n"\
1380 "%m = machine info\n"\
1382 "%s = selected nick\n"\
1385 #define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1386 "%d = data (the whole ctcp)\n"\
1387 "%e = current network name\n"\
1388 "%m = machine info\n"\
1389 "%s = nick who sent the ctcp\n"\
1393 "&2 = word 2 to the end of line\n"\
1394 "&3 = word 3 to the end of line\n\n")
1396 #define url_help _("URL Handlers - Special codes:\n\n"\
1397 "%s = the URL string\n\n"\
1398 "Putting a ! infront of the command\n"\
1399 "indicates it should be sent to a\n"\
1400 "shell instead of XChat")
1403 menu_usercommands (void)
1405 editlist_gui_open (NULL
, NULL
, command_list
, _("XChat: User Defined Commands"),
1406 "commands", "commands.conf", usercommands_help
);
1412 editlist_gui_open (NULL
, NULL
, popup_list
, _("XChat: Userlist Popup menu"), "popup",
1413 "popup.conf", ulbutton_help
);
1419 editlist_gui_open (_("Text"), _("Replace with"), replace_list
, _("XChat: Replace"), "replace",
1424 menu_urlhandlers (void)
1426 editlist_gui_open (NULL
, NULL
, urlhandler_list
, _("XChat: URL Handlers"), "urlhandlers",
1427 "urlhandlers.conf", url_help
);
1431 menu_evtpopup (void)
1433 pevent_dialog_show ();
1437 menu_keypopup (void)
1443 menu_ulbuttons (void)
1445 editlist_gui_open (NULL
, NULL
, button_list
, _("XChat: Userlist buttons"), "buttons",
1446 "buttons.conf", ulbutton_help
);
1450 menu_dlgbuttons (void)
1452 editlist_gui_open (NULL
, NULL
, dlgbutton_list
, _("XChat: Dialog buttons"), "dlgbuttons",
1453 "dlgbuttons.conf", dlgbutton_help
);
1457 menu_ctcpguiopen (void)
1459 editlist_gui_open (NULL
, NULL
, ctcp_list
, _("XChat: CTCP Replies"), "ctcpreply",
1460 "ctcpreply.conf", ctcp_help
);
1464 menu_docs (GtkWidget
*wid
, gpointer none
)
1466 fe_open_url ("http://xchat.org/docs/");
1470 menu_webpage (GtkWidget *wid, gpointer none)
1472 fe_open_url ("http://xchat.org");
1476 menu_dcc_win (GtkWidget
*wid
, gpointer none
)
1478 fe_dcc_open_recv_win (FALSE
);
1479 fe_dcc_open_send_win (FALSE
);
1483 menu_dcc_chat_win (GtkWidget
*wid
, gpointer none
)
1485 fe_dcc_open_chat_win (FALSE
);
1489 menu_change_layout (void)
1491 if (prefs
.tab_layout
== 0)
1493 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 1);
1494 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 0);
1495 mg_change_layout (0);
1498 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 0);
1499 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 1);
1500 mg_change_layout (2);
1505 menu_layout_cb (GtkWidget
*item
, gpointer none
)
1507 prefs
.tab_layout
= 2;
1508 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1509 prefs
.tab_layout
= 0;
1511 menu_change_layout ();
1515 menu_apply_metres_cb (session
*sess
)
1517 mg_update_meters (sess
->gui
);
1521 menu_metres_off (GtkWidget
*item
, gpointer none
)
1523 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1525 prefs
.lagometer
= 0;
1526 prefs
.throttlemeter
= 0;
1527 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1532 menu_metres_text (GtkWidget
*item
, gpointer none
)
1534 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1536 prefs
.lagometer
= 2;
1537 prefs
.throttlemeter
= 2;
1538 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1543 menu_metres_graph (GtkWidget
*item
, gpointer none
)
1545 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1547 prefs
.lagometer
= 1;
1548 prefs
.throttlemeter
= 1;
1549 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1554 menu_metres_both (GtkWidget
*item
, gpointer none
)
1556 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1558 prefs
.lagometer
= 3;
1559 prefs
.throttlemeter
= 3;
1560 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1564 static struct mymenu mymenu
[] = {
1565 {N_("_XChat"), 0, 0, M_NEWMENU
, 0, 0, 1},
1566 {N_("Network Li_st..."), menu_open_server_list
, (char *)&pix_book
, M_MENUPIX
, 0, 0, 1, GDK_s
},
1567 {0, 0, 0, M_SEP
, 0, 0, 0},
1569 {N_("_New"), 0, GTK_STOCK_NEW
, M_MENUSUB
, 0, 0, 1},
1570 {N_("Server Tab..."), menu_newserver_tab
, 0, M_MENUITEM
, 0, 0, 1, GDK_t
},
1571 {N_("Channel Tab..."), menu_newchannel_tab
, 0, M_MENUITEM
, 0, 0, 1},
1572 {N_("Server Window..."), menu_newserver_window
, 0, M_MENUITEM
, 0, 0, 1},
1573 {N_("Channel Window..."), menu_newchannel_window
, 0, M_MENUITEM
, 0, 0, 1},
1574 {0, 0, 0, M_END
, 0, 0, 0},
1575 {0, 0, 0, M_SEP
, 0, 0, 0},
1578 {N_("_Load Plugin or Script..."), menu_loadplugin
, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 1},
1580 {N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 0},
1582 {0, 0, 0, M_SEP
, 0, 0, 0}, /* 11 */
1583 #define DETACH_OFFSET (12)
1584 {0, menu_detach
, GTK_STOCK_REDO
, M_MENUSTOCK
, 0, 0, 1, GDK_I
}, /* 12 */
1585 #define CLOSE_OFFSET (13)
1586 {0, menu_close
, GTK_STOCK_CLOSE
, M_MENUSTOCK
, 0, 0, 1, GDK_w
},
1587 {0, 0, 0, M_SEP
, 0, 0, 0},
1588 {N_("_Quit"), menu_quit
, GTK_STOCK_QUIT
, M_MENUSTOCK
, 0, 0, 1, GDK_q
}, /* 15 */
1590 {N_("_View"), 0, 0, M_NEWMENU
, 0, 0, 1},
1591 #define MENUBAR_OFFSET (17)
1592 {N_("_Menu Bar"), menu_bar_toggle_cb
, 0, M_MENUTOG
, MENU_ID_MENUBAR
, 0, 1, GDK_F9
},
1593 {N_("_Topic Bar"), menu_topicbar_toggle
, 0, M_MENUTOG
, MENU_ID_TOPICBAR
, 0, 1},
1594 {N_("_User List"), menu_userlist_toggle
, 0, M_MENUTOG
, MENU_ID_USERLIST
, 0, 1, GDK_F7
},
1595 {N_("U_serlist Buttons"), menu_ulbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_ULBUTTONS
, 0, 1},
1596 {N_("M_ode Buttons"), menu_cmbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_MODEBUTTONS
, 0, 1},
1597 {0, 0, 0, M_SEP
, 0, 0, 0},
1598 {N_("_Channel Switcher"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 23 */
1599 #define TABS_OFFSET (24)
1600 {N_("_Tabs"), menu_layout_cb
, 0, M_MENURADIO
, MENU_ID_LAYOUT_TABS
, 0, 1},
1601 {N_("T_ree"), 0, 0, M_MENURADIO
, MENU_ID_LAYOUT_TREE
, 0, 1},
1602 {0, 0, 0, M_END
, 0, 0, 0},
1603 {N_("_Network Meters"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 27 */
1604 #define METRE_OFFSET (28)
1605 {N_("Off"), menu_metres_off
, 0, M_MENURADIO
, 0, 0, 1},
1606 {N_("Graph"), menu_metres_graph
, 0, M_MENURADIO
, 0, 0, 1},
1607 {N_("Text"), menu_metres_text
, 0, M_MENURADIO
, 0, 0, 1},
1608 {N_("Both"), menu_metres_both
, 0, M_MENURADIO
, 0, 0, 1},
1609 {0, 0, 0, M_END
, 0, 0, 0}, /* 32 */
1611 {N_("_Server"), 0, 0, M_NEWMENU
, 0, 0, 1},
1612 {N_("_Disconnect"), menu_disconnect
, GTK_STOCK_DISCONNECT
, M_MENUSTOCK
, MENU_ID_DISCONNECT
, 0, 1},
1613 {N_("_Reconnect"), menu_reconnect
, GTK_STOCK_CONNECT
, M_MENUSTOCK
, MENU_ID_RECONNECT
, 0, 1},
1614 {N_("Join a Channel..."), menu_join
, GTK_STOCK_JUMP_TO
, M_MENUSTOCK
, MENU_ID_JOIN
, 0, 1},
1615 {N_("List of Channels..."), menu_chanlist
, GTK_STOCK_INDEX
, M_MENUITEM
, 0, 0, 1},
1616 {0, 0, 0, M_SEP
, 0, 0, 0},
1617 #define AWAY_OFFSET (39)
1618 {N_("Marked Away"), menu_away
, 0, M_MENUTOG
, MENU_ID_AWAY
, 0, 1, GDK_a
},
1620 {N_("_Usermenu"), 0, 0, M_NEWMENU
, MENU_ID_USERMENU
, 0, 1}, /* 40 */
1622 {N_("S_ettings"), 0, 0, M_NEWMENU
, 0, 0, 1},
1623 {N_("_Preferences"), menu_settings
, GTK_STOCK_PREFERENCES
, M_MENUSTOCK
, 0, 0, 1},
1625 {N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT
, M_MENUSUB
, 0, 0, 1},
1626 {N_("Auto Replace..."), menu_rpopup
, 0, M_MENUITEM
, 0, 0, 1},
1627 {N_("CTCP Replies..."), menu_ctcpguiopen
, 0, M_MENUITEM
, 0, 0, 1},
1628 {N_("Dialog Buttons..."), menu_dlgbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1629 {N_("Keyboard Shortcuts..."), menu_keypopup
, 0, M_MENUITEM
, 0, 0, 1},
1630 {N_("Text Events..."), menu_evtpopup
, 0, M_MENUITEM
, 0, 0, 1},
1631 {N_("URL Handlers..."), menu_urlhandlers
, 0, M_MENUITEM
, 0, 0, 1},
1632 {N_("User Commands..."), menu_usercommands
, 0, M_MENUITEM
, 0, 0, 1},
1633 {N_("Userlist Buttons..."), menu_ulbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1634 {N_("Userlist Popup..."), menu_ulpopup
, 0, M_MENUITEM
, 0, 0, 1},
1635 {0, 0, 0, M_END
, 0, 0, 0}, /* 53 */
1637 {N_("_Window"), 0, 0, M_NEWMENU
, 0, 0, 1},
1638 {N_("Ban List..."), menu_banlist
, 0, M_MENUITEM
, 0, 0, 1},
1639 {N_("Character Chart..."), ascii_open
, 0, M_MENUITEM
, 0, 0, 1},
1640 {N_("Direct Chat..."), menu_dcc_chat_win
, 0, M_MENUITEM
, 0, 0, 1},
1641 {N_("File Transfers..."), menu_dcc_win
, 0, M_MENUITEM
, 0, 0, 1},
1642 {N_("Friends List..."), notify_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1643 {N_("Ignore List..."), ignore_gui_open
, 0, M_MENUITEM
, 0, 0, 1},
1644 {N_("Plugins and Scripts..."), menu_pluginlist
, 0, M_MENUITEM
, 0, 0, 1},
1645 {N_("Raw Log..."), menu_rawlog
, 0, M_MENUITEM
, 0, 0, 1}, /* 62 */
1646 {N_("URL Grabber..."), url_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1647 {0, 0, 0, M_SEP
, 0, 0, 0},
1648 {N_("Reset Marker Line"), menu_resetmarker
, 0, M_MENUITEM
, 0, 0, 1, GDK_m
},
1649 {N_("C_lear Text"), menu_flushbuffer
, GTK_STOCK_CLEAR
, M_MENUSTOCK
, 0, 0, 1, GDK_l
},
1650 #define SEARCH_OFFSET 67
1651 {N_("Search Text..."), menu_search
, GTK_STOCK_FIND
, M_MENUSTOCK
, 0, 0, 1, GDK_f
},
1652 {N_("Save Text..."), menu_savebuffer
, GTK_STOCK_SAVE
, M_MENUSTOCK
, 0, 0, 1},
1654 {N_("_Help"), 0, 0, M_NEWMENU
, 0, 0, 1}, /* 69 */
1655 {N_("_Contents"), menu_docs
, GTK_STOCK_HELP
, M_MENUSTOCK
, 0, 0, 1, GDK_F1
},
1657 {N_("Check for updates"), menu_update
, 0, M_MENUITEM
, 0, 1},
1659 {N_("_About"), menu_about
, GTK_STOCK_ABOUT
, M_MENUSTOCK
, 0, 0, 1},
1661 {0, 0, 0, M_END
, 0, 0, 0},
1665 create_icon_menu (char *labeltext
, void *stock_name
, int is_stock
)
1667 GtkWidget
*item
, *img
;
1670 img
= gtk_image_new_from_stock (stock_name
, GTK_ICON_SIZE_MENU
);
1672 img
= gtk_image_new_from_pixbuf (*((GdkPixbuf
**)stock_name
));
1673 item
= gtk_image_menu_item_new_with_mnemonic (labeltext
);
1674 gtk_image_menu_item_set_image ((GtkImageMenuItem
*)item
, img
);
1675 gtk_widget_show (img
);
1680 /* Override the default GTK2.4 handler, which would make menu
1681 bindings not work when the menu-bar is hidden. */
1683 menu_canacaccel (GtkWidget
*widget
, guint signal_id
, gpointer user_data
)
1685 /* GTK2.2 behaviour */
1686 #if GTK_CHECK_VERSION(2,20,0)
1687 return gtk_widget_is_sensitive (widget
);
1689 return GTK_WIDGET_IS_SENSITIVE (widget
);
1693 /* === STUFF FOR /MENU === */
1695 static GtkMenuItem
*
1696 menu_find_item (GtkWidget
*menu
, char *name
)
1698 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1701 const char *labeltext
;
1706 child
= GTK_BIN (item
)->child
;
1707 if (child
) /* separators arn't labels, skip them */
1709 labeltext
= g_object_get_data (G_OBJECT (item
), "name");
1711 labeltext
= gtk_label_get_text (GTK_LABEL (child
));
1712 if (!menu_streq (labeltext
, name
, 1))
1714 } else if (name
== NULL
)
1718 items
= items
->next
;
1725 menu_find_path (GtkWidget
*menu
, char *path
)
1732 /* grab the next part of the path */
1733 s
= strchr (path
, '/');
1736 len
= strlen (path
);
1737 len
= MIN (len
, sizeof (name
) - 1);
1738 memcpy (name
, path
, len
);
1741 item
= menu_find_item (menu
, name
);
1745 menu
= gtk_menu_item_get_submenu (item
);
1753 return menu_find_path (menu
, path
+ 1);
1757 menu_find (GtkWidget
*menu
, char *path
, char *label
)
1759 GtkWidget
*item
= NULL
;
1762 menu
= menu_find_path (menu
, path
);
1764 item
= (GtkWidget
*)menu_find_item (menu
, label
);
1769 menu_foreach_gui (menu_entry
*me
, void (*callback
) (GtkWidget
*, menu_entry
*, char *))
1771 GSList
*list
= sess_list
;
1772 int tabdone
= FALSE
;
1776 return; /* not main menu */
1781 /* do it only once for tab sessions, since they share a GUI */
1782 if (!sess
->gui
->is_tab
|| !tabdone
)
1784 callback (sess
->gui
->menu
, me
, NULL
);
1785 if (sess
->gui
->is_tab
)
1793 menu_update_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1797 item
= menu_find (menu
, me
->path
, me
->label
);
1800 gtk_widget_set_sensitive (item
, me
->enable
);
1801 /* must do it without triggering the callback */
1802 if (GTK_IS_CHECK_MENU_ITEM (item
))
1803 GTK_CHECK_MENU_ITEM (item
)->active
= me
->state
;
1807 /* radio state changed via mouse click */
1809 menu_radio_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1815 /* update the state, incase this was changed via right-click. */
1816 /* This will update all other windows and menu bars */
1817 menu_foreach_gui (me
, menu_update_cb
);
1819 if (me
->state
&& me
->cmd
)
1820 handle_command (current_sess
, me
->cmd
, FALSE
);
1823 /* toggle state changed via mouse click */
1825 menu_toggle_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1831 /* update the state, incase this was changed via right-click. */
1832 /* This will update all other windows and menu bars */
1833 menu_foreach_gui (me
, menu_update_cb
);
1836 handle_command (current_sess
, me
->cmd
, FALSE
);
1838 handle_command (current_sess
, me
->ucmd
, FALSE
);
1842 menu_radio_item (char *label
, GtkWidget
*menu
, void *callback
, void *userdata
,
1843 int state
, char *groupname
)
1846 GtkMenuItem
*parent
;
1847 GSList
*grouplist
= NULL
;
1849 parent
= menu_find_item (menu
, groupname
);
1851 grouplist
= gtk_radio_menu_item_get_group ((GtkRadioMenuItem
*)parent
);
1853 item
= gtk_radio_menu_item_new_with_label (grouplist
, label
);
1854 gtk_check_menu_item_set_active ((GtkCheckMenuItem
*)item
, state
);
1855 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1856 g_signal_connect (G_OBJECT (item
), "activate",
1857 G_CALLBACK (callback
), userdata
);
1858 gtk_widget_show (item
);
1864 menu_reorder (GtkMenu
*menu
, GtkWidget
*item
, int pos
)
1866 if (pos
== 0xffff) /* outbound.c uses this default */
1869 if (pos
< 0) /* position offset from end/bottom */
1870 gtk_menu_reorder_child (menu
, item
, (g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
) - 1);
1872 gtk_menu_reorder_child (menu
, item
, pos
);
1876 menu_add_radio (GtkWidget
*menu
, menu_entry
*me
)
1878 GtkWidget
*item
= NULL
;
1879 char *path
= me
->path
+ me
->root_offset
;
1882 menu
= menu_find_path (menu
, path
);
1885 item
= menu_radio_item (me
->label
, menu
, menu_radio_cb
, me
, me
->state
, me
->group
);
1886 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1892 menu_add_toggle (GtkWidget
*menu
, menu_entry
*me
)
1894 GtkWidget
*item
= NULL
;
1895 char *path
= me
->path
+ me
->root_offset
;
1898 menu
= menu_find_path (menu
, path
);
1901 item
= menu_toggle_item (me
->label
, menu
, menu_toggle_cb
, me
, me
->state
);
1902 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1908 menu_add_item (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1910 GtkWidget
*item
= NULL
;
1911 char *path
= me
->path
+ me
->root_offset
;
1914 menu
= menu_find_path (menu
, path
);
1917 item
= menu_quick_item (me
->cmd
, me
->label
, menu
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, target
, me
->icon
);
1918 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1924 menu_add_sub (GtkWidget
*menu
, menu_entry
*me
)
1926 GtkWidget
*item
= NULL
;
1927 char *path
= me
->path
+ me
->root_offset
;
1931 menu
= menu_find_path (menu
, path
);
1935 if (pos
< 0) /* position offset from end/bottom */
1936 pos
= g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
;
1937 menu_quick_sub (me
->label
, menu
, &item
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, pos
);
1943 menu_del_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1945 GtkWidget
*item
= menu_find (menu
, me
->path
+ me
->root_offset
, me
->label
);
1947 gtk_widget_destroy (item
);
1951 menu_add_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1954 GtkAccelGroup
*accel_group
;
1956 if (me
->group
) /* have a group name? Must be a radio item */
1957 item
= menu_add_radio (menu
, me
);
1958 else if (me
->ucmd
) /* have unselect-cmd? Must be a toggle item */
1959 item
= menu_add_toggle (menu
, me
);
1960 else if (me
->cmd
|| !me
->label
) /* label=NULL for separators */
1961 item
= menu_add_item (menu
, me
, target
);
1963 item
= menu_add_sub (menu
, me
);
1967 gtk_widget_set_sensitive (item
, me
->enable
);
1970 accel_group
= g_object_get_data (G_OBJECT (menu
), "accel");
1971 if (accel_group
) /* popup menus don't have them */
1972 gtk_widget_add_accelerator (item
, "activate", accel_group
, me
->key
,
1973 me
->modifier
, GTK_ACCEL_VISIBLE
);
1979 fe_menu_add (menu_entry
*me
)
1983 menu_foreach_gui (me
, menu_add_cb
);
1988 if (!pango_parse_markup (me
->label
, -1, 0, NULL
, &text
, NULL
, NULL
))
1991 /* return the label with markup stripped */
1996 fe_menu_del (menu_entry
*me
)
1998 menu_foreach_gui (me
, menu_del_cb
);
2002 fe_menu_update (menu_entry
*me
)
2004 menu_foreach_gui (me
, menu_update_cb
);
2007 /* used to add custom menus to the right-click menu */
2010 menu_add_plugin_mainmenu_items (GtkWidget
*menu
)
2015 list
= menu_list
; /* outbound.c */
2020 menu_add_cb (menu
, me
, NULL
);
2026 menu_add_plugin_items (GtkWidget
*menu
, char *root
, char *target
)
2031 list
= menu_list
; /* outbound.c */
2035 if (!me
->is_main
&& !strncmp (me
->path
, root
+ 1, root
[0]))
2036 menu_add_cb (menu
, me
, target
);
2041 /* === END STUFF FOR /MENU === */
2044 menu_create_main (void *accel_group
, int bar
, int away
, int toplevel
,
2045 GtkWidget
**menu_widgets
)
2049 GtkWidget
*menu
= 0;
2050 GtkWidget
*menu_item
= 0;
2051 GtkWidget
*menu_bar
;
2052 GtkWidget
*usermenu
= 0;
2053 GtkWidget
*submenu
= 0;
2054 int close_mask
= GDK_CONTROL_MASK
;
2055 int away_mask
= GDK_MOD1_MASK
;
2056 char *key_theme
= NULL
;
2057 GtkSettings
*settings
;
2058 GSList
*group
= NULL
;
2061 menu_bar
= gtk_menu_bar_new ();
2063 menu_bar
= gtk_menu_new ();
2065 /* /MENU needs to know this later */
2066 g_object_set_data (G_OBJECT (menu_bar
), "accel", accel_group
);
2068 g_signal_connect (G_OBJECT (menu_bar
), "can-activate-accel",
2069 G_CALLBACK (menu_canacaccel
), 0);
2071 /* set the initial state of toggles */
2072 mymenu
[MENUBAR_OFFSET
].state
= !prefs
.hidemenu
;
2073 mymenu
[MENUBAR_OFFSET
+1].state
= prefs
.topicbar
;
2074 mymenu
[MENUBAR_OFFSET
+2].state
= !prefs
.hideuserlist
;
2075 mymenu
[MENUBAR_OFFSET
+3].state
= prefs
.userlistbuttons
;
2076 mymenu
[MENUBAR_OFFSET
+4].state
= prefs
.chanmodebuttons
;
2078 mymenu
[AWAY_OFFSET
].state
= away
;
2080 switch (prefs
.tab_layout
)
2083 mymenu
[TABS_OFFSET
].state
= 1;
2084 mymenu
[TABS_OFFSET
+1].state
= 0;
2087 mymenu
[TABS_OFFSET
].state
= 0;
2088 mymenu
[TABS_OFFSET
+1].state
= 1;
2091 mymenu
[METRE_OFFSET
].state
= 0;
2092 mymenu
[METRE_OFFSET
+1].state
= 0;
2093 mymenu
[METRE_OFFSET
+2].state
= 0;
2094 mymenu
[METRE_OFFSET
+3].state
= 0;
2095 switch (prefs
.lagometer
)
2098 mymenu
[METRE_OFFSET
].state
= 1;
2101 mymenu
[METRE_OFFSET
+1].state
= 1;
2104 mymenu
[METRE_OFFSET
+2].state
= 1;
2107 mymenu
[METRE_OFFSET
+3].state
= 1;
2110 /* change Close binding to ctrl-shift-w when using emacs keys */
2111 settings
= gtk_widget_get_settings (menu_bar
);
2114 g_object_get (settings
, "gtk-key-theme-name", &key_theme
, NULL
);
2117 if (!strcasecmp (key_theme
, "Emacs"))
2119 close_mask
= GDK_SHIFT_MASK
| GDK_CONTROL_MASK
;
2120 mymenu
[SEARCH_OFFSET
].key
= 0;
2126 /* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2128 char *help
= _("_Help");
2129 char *under
= strchr (help
, '_');
2130 if (under
&& (under
[1] == 'a' || under
[1] == 'A'))
2131 away_mask
= GDK_MOD1_MASK
| GDK_CONTROL_MASK
;
2136 mymenu
[DETACH_OFFSET
].text
= N_("_Detach");
2137 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2141 mymenu
[DETACH_OFFSET
].text
= N_("_Attach");
2142 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2148 if (mymenu
[i
].id
== MENU_ID_USERMENU
&& !prefs
.gui_usermenu
)
2154 switch (mymenu
[i
].type
)
2158 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2159 item
= menu
= gtk_menu_new ();
2160 if (mymenu
[i
].id
== MENU_ID_USERMENU
)
2162 menu_item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2163 /* record the English name for /menu */
2164 g_object_set_data (G_OBJECT (menu_item
), "name", mymenu
[i
].text
);
2165 gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar
), menu_item
);
2166 gtk_widget_show (menu_item
);
2170 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, FALSE
);
2174 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2178 item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2180 if (mymenu
[i
].key
!= 0)
2181 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2183 mymenu
[i
].key
== GDK_F1
? 0 :
2184 mymenu
[i
].key
== GDK_w
? close_mask
:
2187 if (mymenu
[i
].callback
)
2188 g_signal_connect (G_OBJECT (item
), "activate",
2189 G_CALLBACK (mymenu
[i
].callback
), 0);
2191 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2193 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2194 gtk_widget_show (item
);
2198 item
= gtk_check_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2200 /* must avoid callback for Radio buttons */
2201 GTK_CHECK_MENU_ITEM (item
)->active
= mymenu
[i
].state
;
2202 /*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2204 if (mymenu
[i
].key
!= 0)
2205 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2206 mymenu
[i
].key
, mymenu
[i
].id
== MENU_ID_AWAY
?
2207 away_mask
: GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
2208 if (mymenu
[i
].callback
)
2209 g_signal_connect (G_OBJECT (item
), "toggled",
2210 G_CALLBACK (mymenu
[i
].callback
), 0);
2212 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2214 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2215 gtk_widget_show (item
);
2216 gtk_widget_set_sensitive (item
, mymenu
[i
].sensitive
);
2220 item
= gtk_radio_menu_item_new_with_mnemonic (group
, _(mymenu
[i
].text
));
2221 group
= gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item
));
2225 item
= gtk_menu_item_new ();
2226 gtk_widget_set_sensitive (item
, FALSE
);
2227 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2228 gtk_widget_show (item
);
2233 submenu
= gtk_menu_new ();
2234 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2235 /* record the English name for /menu */
2236 g_object_set_data (G_OBJECT (item
), "name", mymenu
[i
].text
);
2237 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item
), submenu
);
2238 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2239 gtk_widget_show (item
);
2242 /*case M_END:*/ default:
2247 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2248 menu_add_plugin_mainmenu_items (menu_bar
);
2251 usermenu_create (usermenu
);
2257 /* record this GtkWidget * so it's state might be changed later */
2258 if (mymenu
[i
].id
!= 0 && menu_widgets
)
2259 /* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2260 menu_widgets
[mymenu
[i
].id
] = item
;