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
, _("Country:"),
634 user
->hostname
? country(user
->hostname
) : 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
->hostname
? country(user
->hostname
) : unknown
);
640 snprintf (buf
, sizeof (buf
), fmt
, _("Server:"),
641 user
->servername
? user
->servername
: 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
->servername
? user
->servername
: unknown
);
651 snprintf (min
, sizeof (min
), _("%u minutes ago"),
652 (unsigned int) ((time (0) - user
->lasttalk
) / 60));
653 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), min
);
656 snprintf (buf
, sizeof (buf
), fmt
, _("Last Msg:"), unknown
);
658 menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
662 away
= server_away_find_message (current_sess
->server
, user
->nick
);
665 char *msg
= strip_color (away
->message
? away
->message
: unknown
, -1, STRIP_ALL
|STRIP_ESCMARKUP
);
666 snprintf (buf
, sizeof (buf
), fmt
, _("Away Msg:"), msg
);
668 item
= menu_quick_item (0, buf
, submenu
, XCMENU_MARKUP
, 0, 0);
669 g_signal_connect (G_OBJECT (item
), "activate",
670 G_CALLBACK (copy_to_clipboard_cb
),
671 away
->message
? away
->message
: unknown
);
681 fe_userlist_update (session
*sess
, struct User
*user
)
685 if (!nick_submenu
|| !str_copy
)
688 /* not the same nick as the menu? */
689 if (sess
->server
->p_cmp (user
->nick
, str_copy
))
692 /* get rid of the "show" signal */
693 g_signal_handlers_disconnect_by_func (nick_submenu
, menu_nickinfo_cb
, sess
);
695 /* destroy all the old items */
696 items
= ((GtkMenuShell
*) nick_submenu
)->children
;
700 gtk_widget_destroy (items
->data
);
704 /* and re-create them with new info */
705 menu_create_nickinfo_menu (user
, nick_submenu
);
709 menu_nickmenu (session
*sess
, GdkEventButton
*event
, char *nick
, int num_sel
)
713 GtkWidget
*submenu
, *menu
= gtk_menu_new ();
717 str_copy
= strdup (nick
);
719 submenu_list
= 0; /* first time through, might not be 0 */
721 /* more than 1 nick selected? */
724 snprintf (buf
, sizeof (buf
), _("%d nicks selected."), num_sel
);
725 menu_quick_item (0, buf
, menu
, 0, 0, 0);
726 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
729 user
= userlist_find (sess
, nick
); /* lasttalk is channel specific */
731 user
= userlist_find_global (current_sess
->server
, nick
);
734 nick_submenu
= submenu
= menu_quick_sub (nick
, menu
, NULL
, XCMENU_DOLIST
, -1);
736 if (menu_create_nickinfo_menu (user
, submenu
) ||
737 !user
->hostname
|| !user
->realname
|| !user
->servername
)
739 g_signal_connect (G_OBJECT (submenu
), "show", G_CALLBACK (menu_nickinfo_cb
), sess
);
742 menu_quick_endsub ();
743 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
748 menu_create (menu
, popup_list
, NULL
, FALSE
);
750 menu_create (menu
, popup_list
, str_copy
, FALSE
);
752 if (num_sel
== 0) /* xtext click */
753 menu_add_plugin_items (menu
, "\x5$NICK", str_copy
);
754 else /* userlist treeview click */
755 menu_add_plugin_items (menu
, "\x5$NICK", NULL
);
757 menu_popup (menu
, event
, NULL
);
760 /* stuff for the View menu */
763 menu_showhide_cb (session
*sess
)
766 gtk_widget_hide (sess
->gui
->menu
);
768 gtk_widget_show (sess
->gui
->menu
);
772 menu_topic_showhide_cb (session
*sess
)
775 gtk_widget_show (sess
->gui
->topic_bar
);
777 gtk_widget_hide (sess
->gui
->topic_bar
);
781 menu_userlist_showhide_cb (session
*sess
)
783 mg_decide_userlist (sess
, TRUE
);
787 menu_ulbuttons_showhide_cb (session
*sess
)
789 if (prefs
.userlistbuttons
)
790 gtk_widget_show (sess
->gui
->button_box
);
792 gtk_widget_hide (sess
->gui
->button_box
);
796 menu_cmbuttons_showhide_cb (session
*sess
)
801 if (prefs
.chanmodebuttons
)
802 gtk_widget_show (sess
->gui
->topicbutton_box
);
804 gtk_widget_hide (sess
->gui
->topicbutton_box
);
807 gtk_widget_hide (sess
->gui
->topicbutton_box
);
812 menu_setting_foreach (void (*callback
) (session
*), int id
, guint state
)
816 int maindone
= FALSE
; /* do it only once for EVERY tab */
823 if (!sess
->gui
->is_tab
|| !maindone
)
825 if (sess
->gui
->is_tab
)
828 GTK_CHECK_MENU_ITEM (sess
->gui
->menu_item
[id
])->active
= state
;
838 menu_bar_toggle (void)
840 prefs
.hidemenu
= !prefs
.hidemenu
;
841 menu_setting_foreach (menu_showhide_cb
, MENU_ID_MENUBAR
, !prefs
.hidemenu
);
845 menu_bar_toggle_cb (void)
849 fe_message (_("The Menubar is now hidden. You can show it again"
850 " by pressing F9 or right-clicking in a blank part of"
851 " the main text area."), FE_MSG_INFO
);
855 menu_topicbar_toggle (GtkWidget
*wid
, gpointer ud
)
857 prefs
.topicbar
= !prefs
.topicbar
;
858 menu_setting_foreach (menu_topic_showhide_cb
, MENU_ID_TOPICBAR
,
863 menu_userlist_toggle (GtkWidget
*wid
, gpointer ud
)
865 prefs
.hideuserlist
= !prefs
.hideuserlist
;
866 menu_setting_foreach (menu_userlist_showhide_cb
, MENU_ID_USERLIST
,
867 !prefs
.hideuserlist
);
871 menu_ulbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
873 prefs
.userlistbuttons
= !prefs
.userlistbuttons
;
874 menu_setting_foreach (menu_ulbuttons_showhide_cb
, MENU_ID_ULBUTTONS
,
875 prefs
.userlistbuttons
);
879 menu_cmbuttons_toggle (GtkWidget
*wid
, gpointer ud
)
881 prefs
.chanmodebuttons
= !prefs
.chanmodebuttons
;
882 menu_setting_foreach (menu_cmbuttons_showhide_cb
, MENU_ID_MODEBUTTONS
,
883 prefs
.chanmodebuttons
);
887 menu_middlemenu (session
*sess
, GdkEventButton
*event
)
890 GtkAccelGroup
*accel_group
;
892 accel_group
= gtk_accel_group_new ();
893 menu
= menu_create_main (accel_group
, FALSE
, sess
->server
->is_away
, !sess
->gui
->is_tab
, NULL
);
894 menu_popup (menu
, event
, accel_group
);
898 open_url_cb (GtkWidget
*item
, char *url
)
902 /* pass this to /URL so it can handle irc:// */
903 snprintf (buf
, sizeof (buf
), "URL %s", url
);
904 handle_command (current_sess
, buf
, FALSE
);
908 menu_urlmenu (GdkEventButton
*event
, char *url
)
915 str_copy
= strdup (url
);
917 menu
= gtk_menu_new ();
918 /* more than 51 chars? Chop it */
919 if (g_utf8_strlen (str_copy
, -1) >= 52)
921 tmp
= strdup (str_copy
);
922 chop
= g_utf8_offset_to_pointer (tmp
, 48);
923 chop
[0] = chop
[1] = chop
[2] = '.';
925 menu_quick_item (0, tmp
, menu
, XCMENU_SHADED
, 0, 0);
929 menu_quick_item (0, str_copy
, menu
, XCMENU_SHADED
, 0, 0);
931 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0);
933 /* Two hardcoded entries */
934 if (strncmp (str_copy
, "irc://", 6) == 0 ||
935 strncmp (str_copy
, "ircs://",7) == 0)
936 menu_quick_item_with_callback (open_url_cb
, _("Connect"), menu
, str_copy
);
938 menu_quick_item_with_callback (open_url_cb
, _("Open Link in Browser"), menu
, str_copy
);
939 menu_quick_item_with_callback (copy_to_clipboard_cb
, _("Copy Selected Link"), menu
, str_copy
);
940 /* custom ones from urlhandlers.conf */
941 menu_create (menu
, urlhandler_list
, str_copy
, TRUE
);
942 menu_add_plugin_items (menu
, "\x4$URL", str_copy
);
943 menu_popup (menu
, event
, NULL
);
947 menu_chan_cycle (GtkWidget
* menu
, char *chan
)
953 snprintf (tbuf
, sizeof tbuf
, "CYCLE %s", chan
);
954 handle_command (current_sess
, tbuf
, FALSE
);
959 menu_chan_part (GtkWidget
* menu
, char *chan
)
965 snprintf (tbuf
, sizeof tbuf
, "part %s", chan
);
966 handle_command (current_sess
, tbuf
, FALSE
);
971 menu_chan_join (GtkWidget
* menu
, char *chan
)
977 snprintf (tbuf
, sizeof tbuf
, "join %s", chan
);
978 handle_command (current_sess
, tbuf
, FALSE
);
983 menu_chanmenu (struct session
*sess
, GdkEventButton
* event
, char *chan
)
986 int is_joined
= FALSE
;
988 if (find_channel (sess
->server
, chan
))
993 str_copy
= strdup (chan
);
995 menu
= gtk_menu_new ();
997 menu_quick_item (0, chan
, menu
, XCMENU_SHADED
, str_copy
, 0);
998 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, str_copy
, 0);
1001 menu_quick_item_with_callback (menu_chan_join
, _("Join Channel"), menu
,
1005 menu_quick_item_with_callback (menu_chan_part
, _("Part Channel"), menu
,
1007 menu_quick_item_with_callback (menu_chan_cycle
, _("Cycle Channel"), menu
,
1011 menu_addfavoritemenu (sess
->server
, menu
, str_copy
);
1013 menu_add_plugin_items (menu
, "\x5$CHAN", str_copy
);
1014 menu_popup (menu
, event
, NULL
);
1018 menu_delfav_cb (GtkWidget
*item
, server
*serv
)
1020 servlist_autojoinedit (serv
->network
, str_copy
, FALSE
);
1024 menu_addfav_cb (GtkWidget
*item
, server
*serv
)
1026 servlist_autojoinedit (serv
->network
, str_copy
, TRUE
);
1030 menu_addfavoritemenu (server
*serv
, GtkWidget
*menu
, char *channel
)
1035 if (channel
!= str_copy
)
1039 str_copy
= strdup (channel
);
1042 if (joinlist_is_in_list (serv
, channel
))
1043 mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE
, menu
, menu_delfav_cb
, serv
);
1045 mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD
, menu
, menu_addfav_cb
, serv
);
1049 menu_open_server_list (GtkWidget
*wid
, gpointer none
)
1051 fe_serverlist_open (current_sess
);
1055 menu_settings (GtkWidget
* wid
, gpointer none
)
1057 extern void setup_open (void);
1062 menu_usermenu (void)
1064 editlist_gui_open (NULL
, NULL
, usermenu_list
, _("XChat: User menu"),
1065 "usermenu", "usermenu.conf", 0);
1069 usermenu_create (GtkWidget
*menu
)
1071 menu_create (menu
, usermenu_list
, "", FALSE
);
1072 menu_quick_item (0, 0, menu
, XCMENU_SHADED
, 0, 0); /* sep */
1073 menu_quick_item_with_callback (menu_usermenu
, _("Edit This Menu..."), menu
, 0);
1077 usermenu_destroy (GtkWidget
* menu
)
1079 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1085 gtk_widget_destroy (items
->data
);
1091 usermenu_update (void)
1093 int done_main
= FALSE
;
1094 GSList
*list
= sess_list
;
1101 menu
= sess
->gui
->menu_item
[MENU_ID_USERMENU
];
1102 if (sess
->gui
->is_tab
)
1104 if (!done_main
&& menu
)
1106 usermenu_destroy (menu
);
1107 usermenu_create (menu
);
1112 usermenu_destroy (menu
);
1113 usermenu_create (menu
);
1120 menu_newserver_window (GtkWidget
* wid
, gpointer none
)
1122 int old
= prefs
.tabchannels
;
1124 prefs
.tabchannels
= 0;
1125 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1126 prefs
.tabchannels
= old
;
1130 menu_newchannel_window (GtkWidget
* wid
, gpointer none
)
1132 int old
= prefs
.tabchannels
;
1134 prefs
.tabchannels
= 0;
1135 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1136 prefs
.tabchannels
= old
;
1140 menu_newserver_tab (GtkWidget
* wid
, gpointer none
)
1142 int old
= prefs
.tabchannels
;
1143 int oldf
= prefs
.newtabstofront
;
1145 prefs
.tabchannels
= 1;
1146 /* force focus if setting is "only requested tabs" */
1147 if (prefs
.newtabstofront
== 2)
1148 prefs
.newtabstofront
= 1;
1149 new_ircwindow (NULL
, NULL
, SESS_SERVER
, 0);
1150 prefs
.tabchannels
= old
;
1151 prefs
.newtabstofront
= oldf
;
1155 menu_newchannel_tab (GtkWidget
* wid
, gpointer none
)
1157 int old
= prefs
.tabchannels
;
1159 prefs
.tabchannels
= 1;
1160 new_ircwindow (current_sess
->server
, NULL
, SESS_CHANNEL
, 0);
1161 prefs
.tabchannels
= old
;
1165 menu_rawlog (GtkWidget
* wid
, gpointer none
)
1167 open_rawlog (current_sess
->server
);
1171 menu_detach (GtkWidget
* wid
, gpointer none
)
1173 mg_detach (current_sess
, 0);
1177 menu_close (GtkWidget
* wid
, gpointer none
)
1179 mg_close_sess (current_sess
);
1183 menu_quit (GtkWidget
* wid
, gpointer none
)
1185 mg_open_quit_dialog (FALSE
);
1191 search_open (current_sess
);
1195 menu_resetmarker (GtkWidget
* wid
, gpointer none
)
1197 gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess
->gui
->xtext
));
1201 menu_flushbuffer (GtkWidget
* wid
, gpointer none
)
1203 fe_text_clear (current_sess
, 0);
1207 savebuffer_req_done (session
*sess
, char *file
)
1214 fh
= open (file
, O_TRUNC
| O_WRONLY
| O_CREAT
, 0600);
1217 gtk_xtext_save (GTK_XTEXT (sess
->gui
->xtext
), fh
);
1223 menu_savebuffer (GtkWidget
* wid
, gpointer none
)
1225 gtkutil_file_req (_("Select an output filename"), savebuffer_req_done
,
1226 current_sess
, NULL
, FRF_WRITE
);
1230 menu_disconnect (GtkWidget
* wid
, gpointer none
)
1232 handle_command (current_sess
, "DISCON", FALSE
);
1236 menu_reconnect (GtkWidget
* wid
, gpointer none
)
1238 if (current_sess
->server
->hostname
[0])
1239 handle_command (current_sess
, "RECONNECT", FALSE
);
1241 fe_serverlist_open (current_sess
);
1245 menu_join_cb (GtkWidget
*dialog
, gint response
, GtkEntry
*entry
)
1249 case GTK_RESPONSE_ACCEPT
:
1250 menu_chan_join (NULL
, entry
->text
);
1253 case GTK_RESPONSE_HELP
:
1254 chanlist_opengui (current_sess
->server
, TRUE
);
1258 gtk_widget_destroy (dialog
);
1262 menu_join_entry_cb (GtkWidget
*entry
, GtkDialog
*dialog
)
1264 gtk_dialog_response (dialog
, GTK_RESPONSE_ACCEPT
);
1268 menu_join (GtkWidget
* wid
, gpointer none
)
1270 GtkWidget
*hbox
, *dialog
, *entry
, *label
;
1272 dialog
= gtk_dialog_new_with_buttons (_("Join Channel"),
1273 GTK_WINDOW (parent_window
), 0,
1274 _("Retrieve channel list..."), GTK_RESPONSE_HELP
,
1275 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
1276 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
1278 gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog
)->vbox
), TRUE
);
1279 gtk_window_set_position (GTK_WINDOW (dialog
), GTK_WIN_POS_MOUSE
);
1280 hbox
= gtk_hbox_new (TRUE
, 0);
1282 entry
= gtk_entry_new ();
1283 GTK_ENTRY (entry
)->editable
= 0; /* avoid auto-selection */
1284 gtk_entry_set_text (GTK_ENTRY (entry
), "#");
1285 g_signal_connect (G_OBJECT (entry
), "activate",
1286 G_CALLBACK (menu_join_entry_cb
), dialog
);
1287 gtk_box_pack_end (GTK_BOX (hbox
), entry
, 0, 0, 0);
1289 label
= gtk_label_new (_("Enter Channel to Join:"));
1290 gtk_box_pack_end (GTK_BOX (hbox
), label
, 0, 0, 0);
1292 g_signal_connect (G_OBJECT (dialog
), "response",
1293 G_CALLBACK (menu_join_cb
), entry
);
1295 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog
)->vbox
), hbox
);
1297 gtk_widget_show_all (dialog
);
1299 gtk_editable_set_editable (GTK_EDITABLE (entry
), TRUE
);
1300 gtk_editable_set_position (GTK_EDITABLE (entry
), 1);
1304 menu_away (GtkCheckMenuItem
*item
, gpointer none
)
1306 handle_command (current_sess
, item
->active
? "away" : "back", FALSE
);
1310 menu_chanlist (GtkWidget
* wid
, gpointer none
)
1312 chanlist_opengui (current_sess
->server
, FALSE
);
1316 menu_banlist (GtkWidget
* wid
, gpointer none
)
1318 banlist_opengui (current_sess
);
1324 menu_loadplugin (void)
1330 menu_pluginlist (void)
1337 #define menu_pluginlist 0
1338 #define menu_loadplugin 0
1342 #define usercommands_help _("User Commands - Special codes:\n\n"\
1343 "%c = current channel\n"\
1344 "%e = current network name\n"\
1345 "%m = machine info\n"\
1348 "%v = xchat version\n"\
1351 "&2 = word 2 to the end of line\n"\
1352 "&3 = word 3 to the end of line\n\n"\
1354 "/cmd john hello\n\n"\
1355 "%2 would be \042john\042\n"\
1356 "&2 would be \042john hello\042.")
1358 #define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1359 "%a = all selected nicks\n"\
1360 "%c = current channel\n"\
1361 "%e = current network name\n"\
1362 "%h = selected nick's hostname\n"\
1363 "%m = machine info\n"\
1365 "%s = selected nick\n"\
1368 #define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1369 "%a = all selected nicks\n"\
1370 "%c = current channel\n"\
1371 "%e = current network name\n"\
1372 "%h = selected nick's hostname\n"\
1373 "%m = machine info\n"\
1375 "%s = selected nick\n"\
1378 #define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1379 "%d = data (the whole ctcp)\n"\
1380 "%e = current network name\n"\
1381 "%m = machine info\n"\
1382 "%s = nick who sent the ctcp\n"\
1386 "&2 = word 2 to the end of line\n"\
1387 "&3 = word 3 to the end of line\n\n")
1389 #define url_help _("URL Handlers - Special codes:\n\n"\
1390 "%s = the URL string\n\n"\
1391 "Putting a ! infront of the command\n"\
1392 "indicates it should be sent to a\n"\
1393 "shell instead of XChat")
1396 menu_usercommands (void)
1398 editlist_gui_open (NULL
, NULL
, command_list
, _("XChat: User Defined Commands"),
1399 "commands", "commands.conf", usercommands_help
);
1405 editlist_gui_open (NULL
, NULL
, popup_list
, _("XChat: Userlist Popup menu"), "popup",
1406 "popup.conf", ulbutton_help
);
1412 editlist_gui_open (_("Text"), _("Replace with"), replace_list
, _("XChat: Replace"), "replace",
1417 menu_urlhandlers (void)
1419 editlist_gui_open (NULL
, NULL
, urlhandler_list
, _("XChat: URL Handlers"), "urlhandlers",
1420 "urlhandlers.conf", url_help
);
1424 menu_evtpopup (void)
1426 pevent_dialog_show ();
1430 menu_keypopup (void)
1436 menu_ulbuttons (void)
1438 editlist_gui_open (NULL
, NULL
, button_list
, _("XChat: Userlist buttons"), "buttons",
1439 "buttons.conf", ulbutton_help
);
1443 menu_dlgbuttons (void)
1445 editlist_gui_open (NULL
, NULL
, dlgbutton_list
, _("XChat: Dialog buttons"), "dlgbuttons",
1446 "dlgbuttons.conf", dlgbutton_help
);
1450 menu_ctcpguiopen (void)
1452 editlist_gui_open (NULL
, NULL
, ctcp_list
, _("XChat: CTCP Replies"), "ctcpreply",
1453 "ctcpreply.conf", ctcp_help
);
1457 menu_docs (GtkWidget
*wid
, gpointer none
)
1459 fe_open_url ("http://xchat.org/docs/");
1463 menu_webpage (GtkWidget *wid, gpointer none)
1465 fe_open_url ("http://xchat.org");
1469 menu_dcc_win (GtkWidget
*wid
, gpointer none
)
1471 fe_dcc_open_recv_win (FALSE
);
1472 fe_dcc_open_send_win (FALSE
);
1476 menu_dcc_chat_win (GtkWidget
*wid
, gpointer none
)
1478 fe_dcc_open_chat_win (FALSE
);
1482 menu_change_layout (void)
1484 if (prefs
.tab_layout
== 0)
1486 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 1);
1487 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 0);
1488 mg_change_layout (0);
1491 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TABS
, 0);
1492 menu_setting_foreach (NULL
, MENU_ID_LAYOUT_TREE
, 1);
1493 mg_change_layout (2);
1498 menu_layout_cb (GtkWidget
*item
, gpointer none
)
1500 prefs
.tab_layout
= 2;
1501 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1502 prefs
.tab_layout
= 0;
1504 menu_change_layout ();
1508 menu_apply_metres_cb (session
*sess
)
1510 mg_update_meters (sess
->gui
);
1514 menu_metres_off (GtkWidget
*item
, gpointer none
)
1516 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1518 prefs
.lagometer
= 0;
1519 prefs
.throttlemeter
= 0;
1520 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1525 menu_metres_text (GtkWidget
*item
, gpointer none
)
1527 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1529 prefs
.lagometer
= 2;
1530 prefs
.throttlemeter
= 2;
1531 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1536 menu_metres_graph (GtkWidget
*item
, gpointer none
)
1538 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1540 prefs
.lagometer
= 1;
1541 prefs
.throttlemeter
= 1;
1542 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1547 menu_metres_both (GtkWidget
*item
, gpointer none
)
1549 if (GTK_CHECK_MENU_ITEM (item
)->active
)
1551 prefs
.lagometer
= 3;
1552 prefs
.throttlemeter
= 3;
1553 menu_setting_foreach (menu_apply_metres_cb
, -1, 0);
1557 static struct mymenu mymenu
[] = {
1558 {N_("_XChat"), 0, 0, M_NEWMENU
, 0, 0, 1},
1559 {N_("Network Li_st..."), menu_open_server_list
, (char *)&pix_book
, M_MENUPIX
, 0, 0, 1, GDK_s
},
1560 {0, 0, 0, M_SEP
, 0, 0, 0},
1562 {N_("_New"), 0, GTK_STOCK_NEW
, M_MENUSUB
, 0, 0, 1},
1563 {N_("Server Tab..."), menu_newserver_tab
, 0, M_MENUITEM
, 0, 0, 1, GDK_t
},
1564 {N_("Channel Tab..."), menu_newchannel_tab
, 0, M_MENUITEM
, 0, 0, 1},
1565 {N_("Server Window..."), menu_newserver_window
, 0, M_MENUITEM
, 0, 0, 1},
1566 {N_("Channel Window..."), menu_newchannel_window
, 0, M_MENUITEM
, 0, 0, 1},
1567 {0, 0, 0, M_END
, 0, 0, 0},
1568 {0, 0, 0, M_SEP
, 0, 0, 0},
1571 {N_("_Load Plugin or Script..."), menu_loadplugin
, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 1},
1573 {N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED
, M_MENUSTOCK
, 0, 0, 0},
1575 {0, 0, 0, M_SEP
, 0, 0, 0}, /* 11 */
1576 #define DETACH_OFFSET (12)
1577 {0, menu_detach
, GTK_STOCK_REDO
, M_MENUSTOCK
, 0, 0, 1, GDK_I
}, /* 12 */
1578 #define CLOSE_OFFSET (13)
1579 {0, menu_close
, GTK_STOCK_CLOSE
, M_MENUSTOCK
, 0, 0, 1, GDK_w
},
1580 {0, 0, 0, M_SEP
, 0, 0, 0},
1581 {N_("_Quit"), menu_quit
, GTK_STOCK_QUIT
, M_MENUSTOCK
, 0, 0, 1, GDK_q
}, /* 15 */
1583 {N_("_View"), 0, 0, M_NEWMENU
, 0, 0, 1},
1584 #define MENUBAR_OFFSET (17)
1585 {N_("_Menu Bar"), menu_bar_toggle_cb
, 0, M_MENUTOG
, MENU_ID_MENUBAR
, 0, 1, GDK_F9
},
1586 {N_("_Topic Bar"), menu_topicbar_toggle
, 0, M_MENUTOG
, MENU_ID_TOPICBAR
, 0, 1},
1587 {N_("_User List"), menu_userlist_toggle
, 0, M_MENUTOG
, MENU_ID_USERLIST
, 0, 1, GDK_F7
},
1588 {N_("U_serlist Buttons"), menu_ulbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_ULBUTTONS
, 0, 1},
1589 {N_("M_ode Buttons"), menu_cmbuttons_toggle
, 0, M_MENUTOG
, MENU_ID_MODEBUTTONS
, 0, 1},
1590 {0, 0, 0, M_SEP
, 0, 0, 0},
1591 {N_("_Channel Switcher"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 23 */
1592 #define TABS_OFFSET (24)
1593 {N_("_Tabs"), menu_layout_cb
, 0, M_MENURADIO
, MENU_ID_LAYOUT_TABS
, 0, 1},
1594 {N_("T_ree"), 0, 0, M_MENURADIO
, MENU_ID_LAYOUT_TREE
, 0, 1},
1595 {0, 0, 0, M_END
, 0, 0, 0},
1596 {N_("_Network Meters"), 0, 0, M_MENUSUB
, 0, 0, 1}, /* 27 */
1597 #define METRE_OFFSET (28)
1598 {N_("Off"), menu_metres_off
, 0, M_MENURADIO
, 0, 0, 1},
1599 {N_("Graph"), menu_metres_graph
, 0, M_MENURADIO
, 0, 0, 1},
1600 {N_("Text"), menu_metres_text
, 0, M_MENURADIO
, 0, 0, 1},
1601 {N_("Both"), menu_metres_both
, 0, M_MENURADIO
, 0, 0, 1},
1602 {0, 0, 0, M_END
, 0, 0, 0}, /* 32 */
1604 {N_("_Server"), 0, 0, M_NEWMENU
, 0, 0, 1},
1605 {N_("_Disconnect"), menu_disconnect
, GTK_STOCK_DISCONNECT
, M_MENUSTOCK
, MENU_ID_DISCONNECT
, 0, 1},
1606 {N_("_Reconnect"), menu_reconnect
, GTK_STOCK_CONNECT
, M_MENUSTOCK
, MENU_ID_RECONNECT
, 0, 1},
1607 {N_("Join a Channel..."), menu_join
, GTK_STOCK_JUMP_TO
, M_MENUSTOCK
, MENU_ID_JOIN
, 0, 1},
1608 {N_("List of Channels..."), menu_chanlist
, GTK_STOCK_INDEX
, M_MENUITEM
, 0, 0, 1},
1609 {0, 0, 0, M_SEP
, 0, 0, 0},
1610 #define AWAY_OFFSET (39)
1611 {N_("Marked Away"), menu_away
, 0, M_MENUTOG
, MENU_ID_AWAY
, 0, 1, GDK_a
},
1613 {N_("_Usermenu"), 0, 0, M_NEWMENU
, MENU_ID_USERMENU
, 0, 1}, /* 40 */
1615 {N_("S_ettings"), 0, 0, M_NEWMENU
, 0, 0, 1},
1616 {N_("_Preferences"), menu_settings
, GTK_STOCK_PREFERENCES
, M_MENUSTOCK
, 0, 0, 1},
1618 {N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT
, M_MENUSUB
, 0, 0, 1},
1619 {N_("Auto Replace..."), menu_rpopup
, 0, M_MENUITEM
, 0, 0, 1},
1620 {N_("CTCP Replies..."), menu_ctcpguiopen
, 0, M_MENUITEM
, 0, 0, 1},
1621 {N_("Dialog Buttons..."), menu_dlgbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1622 {N_("Keyboard Shortcuts..."), menu_keypopup
, 0, M_MENUITEM
, 0, 0, 1},
1623 {N_("Text Events..."), menu_evtpopup
, 0, M_MENUITEM
, 0, 0, 1},
1624 {N_("URL Handlers..."), menu_urlhandlers
, 0, M_MENUITEM
, 0, 0, 1},
1625 {N_("User Commands..."), menu_usercommands
, 0, M_MENUITEM
, 0, 0, 1},
1626 {N_("Userlist Buttons..."), menu_ulbuttons
, 0, M_MENUITEM
, 0, 0, 1},
1627 {N_("Userlist Popup..."), menu_ulpopup
, 0, M_MENUITEM
, 0, 0, 1},
1628 {0, 0, 0, M_END
, 0, 0, 0}, /* 53 */
1630 {N_("_Window"), 0, 0, M_NEWMENU
, 0, 0, 1},
1631 {N_("Ban List..."), menu_banlist
, 0, M_MENUITEM
, 0, 0, 1},
1632 {N_("Character Chart..."), ascii_open
, 0, M_MENUITEM
, 0, 0, 1},
1633 {N_("Direct Chat..."), menu_dcc_chat_win
, 0, M_MENUITEM
, 0, 0, 1},
1634 {N_("File Transfers..."), menu_dcc_win
, 0, M_MENUITEM
, 0, 0, 1},
1635 {N_("Friends List..."), notify_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1636 {N_("Ignore List..."), ignore_gui_open
, 0, M_MENUITEM
, 0, 0, 1},
1637 {N_("Plugins and Scripts..."), menu_pluginlist
, 0, M_MENUITEM
, 0, 0, 1},
1638 {N_("Raw Log..."), menu_rawlog
, 0, M_MENUITEM
, 0, 0, 1}, /* 62 */
1639 {N_("URL Grabber..."), url_opengui
, 0, M_MENUITEM
, 0, 0, 1},
1640 {0, 0, 0, M_SEP
, 0, 0, 0},
1641 {N_("Reset Marker Line"), menu_resetmarker
, 0, M_MENUITEM
, 0, 0, 1, GDK_m
},
1642 {N_("C_lear Text"), menu_flushbuffer
, GTK_STOCK_CLEAR
, M_MENUSTOCK
, 0, 0, 1, GDK_l
},
1643 #define SEARCH_OFFSET 67
1644 {N_("Search Text..."), menu_search
, GTK_STOCK_FIND
, M_MENUSTOCK
, 0, 0, 1, GDK_f
},
1645 {N_("Save Text..."), menu_savebuffer
, GTK_STOCK_SAVE
, M_MENUSTOCK
, 0, 0, 1},
1647 {N_("_Help"), 0, 0, M_NEWMENU
, 0, 0, 1}, /* 69 */
1648 {N_("_Contents"), menu_docs
, GTK_STOCK_HELP
, M_MENUSTOCK
, 0, 0, 1, GDK_F1
},
1650 {N_("Check for updates"), menu_update
, 0, M_MENUITEM
, 0, 1},
1652 {N_("_About"), menu_about
, GTK_STOCK_ABOUT
, M_MENUSTOCK
, 0, 0, 1},
1654 {0, 0, 0, M_END
, 0, 0, 0},
1658 create_icon_menu (char *labeltext
, void *stock_name
, int is_stock
)
1660 GtkWidget
*item
, *img
;
1663 img
= gtk_image_new_from_stock (stock_name
, GTK_ICON_SIZE_MENU
);
1665 img
= gtk_image_new_from_pixbuf (*((GdkPixbuf
**)stock_name
));
1666 item
= gtk_image_menu_item_new_with_mnemonic (labeltext
);
1667 gtk_image_menu_item_set_image ((GtkImageMenuItem
*)item
, img
);
1668 gtk_widget_show (img
);
1673 /* Override the default GTK2.4 handler, which would make menu
1674 bindings not work when the menu-bar is hidden. */
1676 menu_canacaccel (GtkWidget
*widget
, guint signal_id
, gpointer user_data
)
1678 /* GTK2.2 behaviour */
1679 #if GTK_CHECK_VERSION(2,20,0)
1680 return gtk_widget_is_sensitive (widget
);
1682 return GTK_WIDGET_IS_SENSITIVE (widget
);
1686 /* === STUFF FOR /MENU === */
1688 static GtkMenuItem
*
1689 menu_find_item (GtkWidget
*menu
, char *name
)
1691 GList
*items
= ((GtkMenuShell
*) menu
)->children
;
1694 const char *labeltext
;
1699 child
= GTK_BIN (item
)->child
;
1700 if (child
) /* separators arn't labels, skip them */
1702 labeltext
= g_object_get_data (G_OBJECT (item
), "name");
1704 labeltext
= gtk_label_get_text (GTK_LABEL (child
));
1705 if (!menu_streq (labeltext
, name
, 1))
1707 } else if (name
== NULL
)
1711 items
= items
->next
;
1718 menu_find_path (GtkWidget
*menu
, char *path
)
1725 /* grab the next part of the path */
1726 s
= strchr (path
, '/');
1729 len
= strlen (path
);
1730 len
= MIN (len
, sizeof (name
) - 1);
1731 memcpy (name
, path
, len
);
1734 item
= menu_find_item (menu
, name
);
1738 menu
= gtk_menu_item_get_submenu (item
);
1746 return menu_find_path (menu
, path
+ 1);
1750 menu_find (GtkWidget
*menu
, char *path
, char *label
)
1752 GtkWidget
*item
= NULL
;
1755 menu
= menu_find_path (menu
, path
);
1757 item
= (GtkWidget
*)menu_find_item (menu
, label
);
1762 menu_foreach_gui (menu_entry
*me
, void (*callback
) (GtkWidget
*, menu_entry
*, char *))
1764 GSList
*list
= sess_list
;
1765 int tabdone
= FALSE
;
1769 return; /* not main menu */
1774 /* do it only once for tab sessions, since they share a GUI */
1775 if (!sess
->gui
->is_tab
|| !tabdone
)
1777 callback (sess
->gui
->menu
, me
, NULL
);
1778 if (sess
->gui
->is_tab
)
1786 menu_update_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1790 item
= menu_find (menu
, me
->path
, me
->label
);
1793 gtk_widget_set_sensitive (item
, me
->enable
);
1794 /* must do it without triggering the callback */
1795 if (GTK_IS_CHECK_MENU_ITEM (item
))
1796 GTK_CHECK_MENU_ITEM (item
)->active
= me
->state
;
1800 /* radio state changed via mouse click */
1802 menu_radio_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1808 /* update the state, incase this was changed via right-click. */
1809 /* This will update all other windows and menu bars */
1810 menu_foreach_gui (me
, menu_update_cb
);
1812 if (me
->state
&& me
->cmd
)
1813 handle_command (current_sess
, me
->cmd
, FALSE
);
1816 /* toggle state changed via mouse click */
1818 menu_toggle_cb (GtkCheckMenuItem
*item
, menu_entry
*me
)
1824 /* update the state, incase this was changed via right-click. */
1825 /* This will update all other windows and menu bars */
1826 menu_foreach_gui (me
, menu_update_cb
);
1829 handle_command (current_sess
, me
->cmd
, FALSE
);
1831 handle_command (current_sess
, me
->ucmd
, FALSE
);
1835 menu_radio_item (char *label
, GtkWidget
*menu
, void *callback
, void *userdata
,
1836 int state
, char *groupname
)
1839 GtkMenuItem
*parent
;
1840 GSList
*grouplist
= NULL
;
1842 parent
= menu_find_item (menu
, groupname
);
1844 grouplist
= gtk_radio_menu_item_get_group ((GtkRadioMenuItem
*)parent
);
1846 item
= gtk_radio_menu_item_new_with_label (grouplist
, label
);
1847 gtk_check_menu_item_set_active ((GtkCheckMenuItem
*)item
, state
);
1848 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1849 g_signal_connect (G_OBJECT (item
), "activate",
1850 G_CALLBACK (callback
), userdata
);
1851 gtk_widget_show (item
);
1857 menu_reorder (GtkMenu
*menu
, GtkWidget
*item
, int pos
)
1859 if (pos
== 0xffff) /* outbound.c uses this default */
1862 if (pos
< 0) /* position offset from end/bottom */
1863 gtk_menu_reorder_child (menu
, item
, (g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
) - 1);
1865 gtk_menu_reorder_child (menu
, item
, pos
);
1869 menu_add_radio (GtkWidget
*menu
, menu_entry
*me
)
1871 GtkWidget
*item
= NULL
;
1872 char *path
= me
->path
+ me
->root_offset
;
1875 menu
= menu_find_path (menu
, path
);
1878 item
= menu_radio_item (me
->label
, menu
, menu_radio_cb
, me
, me
->state
, me
->group
);
1879 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1885 menu_add_toggle (GtkWidget
*menu
, menu_entry
*me
)
1887 GtkWidget
*item
= NULL
;
1888 char *path
= me
->path
+ me
->root_offset
;
1891 menu
= menu_find_path (menu
, path
);
1894 item
= menu_toggle_item (me
->label
, menu
, menu_toggle_cb
, me
, me
->state
);
1895 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1901 menu_add_item (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1903 GtkWidget
*item
= NULL
;
1904 char *path
= me
->path
+ me
->root_offset
;
1907 menu
= menu_find_path (menu
, path
);
1910 item
= menu_quick_item (me
->cmd
, me
->label
, menu
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, target
, me
->icon
);
1911 menu_reorder (GTK_MENU (menu
), item
, me
->pos
);
1917 menu_add_sub (GtkWidget
*menu
, menu_entry
*me
)
1919 GtkWidget
*item
= NULL
;
1920 char *path
= me
->path
+ me
->root_offset
;
1924 menu
= menu_find_path (menu
, path
);
1928 if (pos
< 0) /* position offset from end/bottom */
1929 pos
= g_list_length (GTK_MENU_SHELL (menu
)->children
) + pos
;
1930 menu_quick_sub (me
->label
, menu
, &item
, me
->markup
? XCMENU_MARKUP
|XCMENU_MNEMONIC
: XCMENU_MNEMONIC
, pos
);
1936 menu_del_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1938 GtkWidget
*item
= menu_find (menu
, me
->path
+ me
->root_offset
, me
->label
);
1940 gtk_widget_destroy (item
);
1944 menu_add_cb (GtkWidget
*menu
, menu_entry
*me
, char *target
)
1947 GtkAccelGroup
*accel_group
;
1949 if (me
->group
) /* have a group name? Must be a radio item */
1950 item
= menu_add_radio (menu
, me
);
1951 else if (me
->ucmd
) /* have unselect-cmd? Must be a toggle item */
1952 item
= menu_add_toggle (menu
, me
);
1953 else if (me
->cmd
|| !me
->label
) /* label=NULL for separators */
1954 item
= menu_add_item (menu
, me
, target
);
1956 item
= menu_add_sub (menu
, me
);
1960 gtk_widget_set_sensitive (item
, me
->enable
);
1963 accel_group
= g_object_get_data (G_OBJECT (menu
), "accel");
1964 if (accel_group
) /* popup menus don't have them */
1965 gtk_widget_add_accelerator (item
, "activate", accel_group
, me
->key
,
1966 me
->modifier
, GTK_ACCEL_VISIBLE
);
1972 fe_menu_add (menu_entry
*me
)
1976 menu_foreach_gui (me
, menu_add_cb
);
1981 if (!pango_parse_markup (me
->label
, -1, 0, NULL
, &text
, NULL
, NULL
))
1984 /* return the label with markup stripped */
1989 fe_menu_del (menu_entry
*me
)
1991 menu_foreach_gui (me
, menu_del_cb
);
1995 fe_menu_update (menu_entry
*me
)
1997 menu_foreach_gui (me
, menu_update_cb
);
2000 /* used to add custom menus to the right-click menu */
2003 menu_add_plugin_mainmenu_items (GtkWidget
*menu
)
2008 list
= menu_list
; /* outbound.c */
2013 menu_add_cb (menu
, me
, NULL
);
2019 menu_add_plugin_items (GtkWidget
*menu
, char *root
, char *target
)
2024 list
= menu_list
; /* outbound.c */
2028 if (!me
->is_main
&& !strncmp (me
->path
, root
+ 1, root
[0]))
2029 menu_add_cb (menu
, me
, target
);
2034 /* === END STUFF FOR /MENU === */
2037 menu_create_main (void *accel_group
, int bar
, int away
, int toplevel
,
2038 GtkWidget
**menu_widgets
)
2042 GtkWidget
*menu
= 0;
2043 GtkWidget
*menu_item
= 0;
2044 GtkWidget
*menu_bar
;
2045 GtkWidget
*usermenu
= 0;
2046 GtkWidget
*submenu
= 0;
2047 int close_mask
= GDK_CONTROL_MASK
;
2048 int away_mask
= GDK_MOD1_MASK
;
2049 char *key_theme
= NULL
;
2050 GtkSettings
*settings
;
2051 GSList
*group
= NULL
;
2054 menu_bar
= gtk_menu_bar_new ();
2056 menu_bar
= gtk_menu_new ();
2058 /* /MENU needs to know this later */
2059 g_object_set_data (G_OBJECT (menu_bar
), "accel", accel_group
);
2061 g_signal_connect (G_OBJECT (menu_bar
), "can-activate-accel",
2062 G_CALLBACK (menu_canacaccel
), 0);
2064 /* set the initial state of toggles */
2065 mymenu
[MENUBAR_OFFSET
].state
= !prefs
.hidemenu
;
2066 mymenu
[MENUBAR_OFFSET
+1].state
= prefs
.topicbar
;
2067 mymenu
[MENUBAR_OFFSET
+2].state
= !prefs
.hideuserlist
;
2068 mymenu
[MENUBAR_OFFSET
+3].state
= prefs
.userlistbuttons
;
2069 mymenu
[MENUBAR_OFFSET
+4].state
= prefs
.chanmodebuttons
;
2071 mymenu
[AWAY_OFFSET
].state
= away
;
2073 switch (prefs
.tab_layout
)
2076 mymenu
[TABS_OFFSET
].state
= 1;
2077 mymenu
[TABS_OFFSET
+1].state
= 0;
2080 mymenu
[TABS_OFFSET
].state
= 0;
2081 mymenu
[TABS_OFFSET
+1].state
= 1;
2084 mymenu
[METRE_OFFSET
].state
= 0;
2085 mymenu
[METRE_OFFSET
+1].state
= 0;
2086 mymenu
[METRE_OFFSET
+2].state
= 0;
2087 mymenu
[METRE_OFFSET
+3].state
= 0;
2088 switch (prefs
.lagometer
)
2091 mymenu
[METRE_OFFSET
].state
= 1;
2094 mymenu
[METRE_OFFSET
+1].state
= 1;
2097 mymenu
[METRE_OFFSET
+2].state
= 1;
2100 mymenu
[METRE_OFFSET
+3].state
= 1;
2103 /* change Close binding to ctrl-shift-w when using emacs keys */
2104 settings
= gtk_widget_get_settings (menu_bar
);
2107 g_object_get (settings
, "gtk-key-theme-name", &key_theme
, NULL
);
2110 if (!strcasecmp (key_theme
, "Emacs"))
2112 close_mask
= GDK_SHIFT_MASK
| GDK_CONTROL_MASK
;
2113 mymenu
[SEARCH_OFFSET
].key
= 0;
2119 /* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2121 char *help
= _("_Help");
2122 char *under
= strchr (help
, '_');
2123 if (under
&& (under
[1] == 'a' || under
[1] == 'A'))
2124 away_mask
= GDK_MOD1_MASK
| GDK_CONTROL_MASK
;
2129 mymenu
[DETACH_OFFSET
].text
= N_("_Detach");
2130 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2134 mymenu
[DETACH_OFFSET
].text
= N_("_Attach");
2135 mymenu
[CLOSE_OFFSET
].text
= N_("_Close");
2141 if (mymenu
[i
].id
== MENU_ID_USERMENU
&& !prefs
.gui_usermenu
)
2147 switch (mymenu
[i
].type
)
2151 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2152 item
= menu
= gtk_menu_new ();
2153 if (mymenu
[i
].id
== MENU_ID_USERMENU
)
2155 menu_item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2156 /* record the English name for /menu */
2157 g_object_set_data (G_OBJECT (menu_item
), "name", mymenu
[i
].text
);
2158 gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar
), menu_item
);
2159 gtk_widget_show (menu_item
);
2163 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, FALSE
);
2167 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2171 item
= gtk_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2173 if (mymenu
[i
].key
!= 0)
2174 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2176 mymenu
[i
].key
== GDK_F1
? 0 :
2177 mymenu
[i
].key
== GDK_w
? close_mask
:
2180 if (mymenu
[i
].callback
)
2181 g_signal_connect (G_OBJECT (item
), "activate",
2182 G_CALLBACK (mymenu
[i
].callback
), 0);
2184 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2186 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2187 gtk_widget_show (item
);
2191 item
= gtk_check_menu_item_new_with_mnemonic (_(mymenu
[i
].text
));
2193 /* must avoid callback for Radio buttons */
2194 GTK_CHECK_MENU_ITEM (item
)->active
= mymenu
[i
].state
;
2195 /*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2197 if (mymenu
[i
].key
!= 0)
2198 gtk_widget_add_accelerator (item
, "activate", accel_group
,
2199 mymenu
[i
].key
, mymenu
[i
].id
== MENU_ID_AWAY
?
2200 away_mask
: GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
2201 if (mymenu
[i
].callback
)
2202 g_signal_connect (G_OBJECT (item
), "toggled",
2203 G_CALLBACK (mymenu
[i
].callback
), 0);
2205 gtk_menu_shell_append (GTK_MENU_SHELL (submenu
), item
);
2207 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2208 gtk_widget_show (item
);
2209 gtk_widget_set_sensitive (item
, mymenu
[i
].sensitive
);
2213 item
= gtk_radio_menu_item_new_with_mnemonic (group
, _(mymenu
[i
].text
));
2214 group
= gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item
));
2218 item
= gtk_menu_item_new ();
2219 gtk_widget_set_sensitive (item
, FALSE
);
2220 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2221 gtk_widget_show (item
);
2226 submenu
= gtk_menu_new ();
2227 item
= create_icon_menu (_(mymenu
[i
].text
), mymenu
[i
].image
, TRUE
);
2228 /* record the English name for /menu */
2229 g_object_set_data (G_OBJECT (item
), "name", mymenu
[i
].text
);
2230 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item
), submenu
);
2231 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
2232 gtk_widget_show (item
);
2235 /*case M_END:*/ default:
2240 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item
), menu
);
2241 menu_add_plugin_mainmenu_items (menu_bar
);
2244 usermenu_create (usermenu
);
2250 /* record this GtkWidget * so it's state might be changed later */
2251 if (mymenu
[i
].id
!= 0 && menu_widgets
)
2252 /* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2253 menu_widgets
[mymenu
[i
].id
] = item
;