"> TRUE;
if (id != -1)
GTK_CHECK_MENU_ITEM (sess->gui->menu_item[id])->active = state;
if (callback)
callback (sess);
}
list = list->next;
}
}
void
menu_bar_toggle (void)
{
prefs.hex_gui_hide_menu = !prefs.hex_gui_hide_menu;
menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hex_gui_hide_menu);
}
static void
menu_bar_toggle_cb (void)
{
menu_bar_toggle ();
if (prefs.hex_gui_hide_menu)
fe_message (_("The Menubar is now hidden. You can show it again"
" by pressing F9 or right-clicking in a blank part of"
" the main text area."), FE_MSG_INFO);
}
static void
menu_topicbar_toggle (GtkWidget *wid, gpointer ud)
{
prefs.hex_gui_topicbar = !prefs.hex_gui_topicbar;
menu_setting_foreach (menu_topic_showhide_cb, MENU_ID_TOPICBAR,
prefs.hex_gui_topicbar);
}
static void
menu_userlist_toggle (GtkWidget *wid, gpointer ud)
{
prefs.hex_gui_ulist_hide = !prefs.hex_gui_ulist_hide;
menu_setting_foreach (menu_userlist_showhide_cb, MENU_ID_USERLIST,
!prefs.hex_gui_ulist_hide);
}
static void
menu_ulbuttons_toggle (GtkWidget *wid, gpointer ud)
{
prefs.hex_gui_ulist_buttons = !prefs.hex_gui_ulist_buttons;
menu_setting_foreach (menu_ulbuttons_showhide_cb, MENU_ID_ULBUTTONS,
prefs.hex_gui_ulist_buttons);
}
static void
menu_cmbuttons_toggle (GtkWidget *wid, gpointer ud)
{
prefs.hex_gui_mode_buttons = !prefs.hex_gui_mode_buttons;
menu_setting_foreach (menu_cmbuttons_showhide_cb, MENU_ID_MODEBUTTONS,
prefs.hex_gui_mode_buttons);
}
void
menu_middlemenu (session *sess, GdkEventButton *event)
{
GtkWidget *menu;
GtkAccelGroup *accel_group;
accel_group = gtk_accel_group_new ();
menu = menu_create_main (accel_group, FALSE, sess->server->is_away, !sess->gui->is_tab, NULL);
menu_popup (menu, event, accel_group);
}
static void
open_url_cb (GtkWidget *item, char *url)
{
char buf[512];
/* pass this to /URL so it can handle irc:// */
snprintf (buf, sizeof (buf), "URL %s", url);
handle_command (current_sess, buf, FALSE);
}
void
menu_urlmenu (GdkEventButton *event, char *url)
{
GtkWidget *menu;
char *tmp, *chop;
if (str_copy)
free (str_copy);
str_copy = strdup (url);
menu = gtk_menu_new ();
/* more than 51 chars? Chop it */
if (g_utf8_strlen (str_copy, -1) >= 52)
{
tmp = strdup (str_copy);
chop = g_utf8_offset_to_pointer (tmp, 48);
chop[0] = chop[1] = chop[2] = '.';
chop[3] = 0;
menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
free (tmp);
} else
{
menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
}
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
/* Two hardcoded entries */
if (strncmp (str_copy, "irc://", 6) == 0 ||
strncmp (str_copy, "ircs://",7) == 0)
menu_quick_item_with_callback (open_url_cb, _("Connect"), menu, str_copy);
else
menu_quick_item_with_callback (open_url_cb, _("Open Link in Browser"), menu, str_copy);
menu_quick_item_with_callback (copy_to_clipboard_cb, _("Copy Selected Link"), menu, str_copy);
/* custom ones from urlhandlers.conf */
menu_create (menu, urlhandler_list, str_copy, TRUE);
menu_add_plugin_items (menu, "\x4$URL", str_copy);
menu_popup (menu, event, NULL);
}
static void
menu_chan_cycle (GtkWidget * menu, char *chan)
{
char tbuf[256];
if (current_sess)
{
snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
handle_command (current_sess, tbuf, FALSE);
}
}
static void
menu_chan_part (GtkWidget * menu, char *chan)
{
char tbuf[256];
if (current_sess)
{
snprintf (tbuf, sizeof tbuf, "part %s", chan);
handle_command (current_sess, tbuf, FALSE);
}
}
static void
menu_chan_join (GtkWidget * menu, char *chan)
{
char tbuf[256];
if (current_sess)
{
snprintf (tbuf, sizeof tbuf, "join %s", chan);
handle_command (current_sess, tbuf, FALSE);
}
}
void
menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
{
GtkWidget *menu;
int is_joined = FALSE;
if (find_channel (sess->server, chan))
is_joined = TRUE;
if (str_copy)
free (str_copy);
str_copy = strdup (chan);
menu = gtk_menu_new ();
menu_quick_item (0, chan, menu, XCMENU_SHADED, str_copy, 0);
menu_quick_item (0, 0, menu, XCMENU_SHADED, str_copy, 0);
if (!is_joined)
menu_quick_item_with_callback (menu_chan_join, _("Join Channel"), menu,
str_copy);
else
{
menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
str_copy);
menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
str_copy);
}
menu_addfavoritemenu (sess->server, menu, str_copy);
menu_add_plugin_items (menu, "\x5$CHAN", str_copy);
menu_popup (menu, event, NULL);
}
static void
menu_delfav_cb (GtkWidget *item, server *serv)
{
servlist_autojoinedit (serv->network, str_copy, FALSE);
}
static void
menu_addfav_cb (GtkWidget *item, server *serv)
{
servlist_autojoinedit (serv->network, str_copy, TRUE);
}
void
menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel)
{
if (!serv->network)
return;
if (channel != str_copy)
{
if (str_copy)
free (str_copy);
str_copy = strdup (channel);
}
if (joinlist_is_in_list (serv, channel))
mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE, menu, menu_delfav_cb, serv);
else
mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD, menu, menu_addfav_cb, serv);
}
static void
menu_open_server_list (GtkWidget *wid, gpointer none)
{
fe_serverlist_open (current_sess);
}
static void
menu_settings (GtkWidget * wid, gpointer none)
{
extern void setup_open (void);
setup_open ();
}
static void
menu_usermenu (void)
{
editlist_gui_open (NULL, NULL, usermenu_list, _(DISPLAY_NAME": User menu"),
"usermenu", "usermenu.conf", 0);
}
static void
usermenu_create (GtkWidget *menu)
{
menu_create (menu, usermenu_list, "", FALSE);
menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0); /* sep */
menu_quick_item_with_callback (menu_usermenu, _("Edit This Menu..."), menu, 0);
}
static void
usermenu_destroy (GtkWidget * menu)
{
GList *items = ((GtkMenuShell *) menu)->children;
GList *next;
while (items)
{
next = items->next;
gtk_widget_destroy (items->data);
items = next;
}
}
void
usermenu_update (void)
{
int done_main = FALSE;
GSList *list = sess_list;
session *sess;
GtkWidget *menu;
while (list)
{
sess = list->data;
menu = sess->gui->menu_item[MENU_ID_USERMENU];
if (sess->gui->is_tab)
{
if (!done_main && menu)
{
usermenu_destroy (menu);
usermenu_create (menu);
done_main = TRUE;
}
} else if (menu)
{
usermenu_destroy (menu);
usermenu_create (menu);
}
list = list->next;
}
}
static void
menu_newserver_window (GtkWidget * wid, gpointer none)
{
int old = prefs.hex_gui_tab_chans;
prefs.hex_gui_tab_chans = 0;
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
prefs.hex_gui_tab_chans = old;
}
static void
menu_newchannel_window (GtkWidget * wid, gpointer none)
{
int old = prefs.hex_gui_tab_chans;
prefs.hex_gui_tab_chans = 0;
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
prefs.hex_gui_tab_chans = old;
}
static void
menu_newserver_tab (GtkWidget * wid, gpointer none)
{
int old = prefs.hex_gui_tab_chans;
int oldf = prefs.hex_gui_tab_newtofront;
prefs.hex_gui_tab_chans = 1;
/* force focus if setting is "only requested tabs" */
if (prefs.hex_gui_tab_newtofront == 2)
prefs.hex_gui_tab_newtofront = 1;
new_ircwindow (NULL, NULL, SESS_SERVER, 0);
prefs.hex_gui_tab_chans = old;
prefs.hex_gui_tab_newtofront = oldf;
}
static void
menu_newchannel_tab (GtkWidget * wid, gpointer none)
{
int old = prefs.hex_gui_tab_chans;
prefs.hex_gui_tab_chans = 1;
new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
prefs.hex_gui_tab_chans = old;
}
static void
menu_rawlog (GtkWidget * wid, gpointer none)
{
open_rawlog (current_sess->server);
}
static void
menu_detach (GtkWidget * wid, gpointer none)
{
mg_detach (current_sess, 0);
}
static void
menu_close (GtkWidget * wid, gpointer none)
{
mg_close_sess (current_sess);
}
static void
menu_quit (GtkWidget * wid, gpointer none)
{
mg_open_quit_dialog (FALSE);
}
static void
menu_search ()
{
search_open (current_sess);
}
static void
menu_search_next ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
if (!gtk_xtext_search (xtext, buf->search_text,
(buf->search_flags & (case_match | follow | regexp)), NULL))
{
fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
}
}
static void
menu_search_prev ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
if (!gtk_xtext_search(xtext, buf->search_text,
(buf->search_flags & (case_match | follow | regexp)) | backward, NULL))
{
fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
}
}
static void
menu_search_reset ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
gtk_xtext_search (xtext, "", 0, NULL);
}
static void
menu_resetmarker (GtkWidget * wid, gpointer none)
{
gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
}
static void
menu_copy_selection (GtkWidget * wid, gpointer none)
{
gtk_xtext_copy_selection (GTK_XTEXT (current_sess->gui->xtext));
}
static void
menu_flushbuffer (GtkWidget * wid, gpointer none)
{
fe_text_clear (current_sess, 0);
}
static void
savebuffer_req_done (session *sess, char *file)
{
int fh;
if (!file)
return;
fh = open (file, O_TRUNC | O_WRONLY | O_CREAT, 0600);
if (fh != -1)
{
gtk_xtext_save (GTK_XTEXT (sess->gui->xtext), fh);
close (fh);
}
}
static void
menu_savebuffer (GtkWidget * wid, gpointer none)
{
gtkutil_file_req (_("Select an output filename"), savebuffer_req_done,
current_sess, NULL, NULL, FRF_WRITE);
}
static void
menu_disconnect (GtkWidget * wid, gpointer none)
{
handle_command (current_sess, "DISCON", FALSE);
}
static void
menu_reconnect (GtkWidget * wid, gpointer none)
{
if (current_sess->server->hostname[0])
handle_command (current_sess, "RECONNECT", FALSE);
else
fe_serverlist_open (current_sess);
}
static void
menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
{
switch (response)
{
case GTK_RESPONSE_ACCEPT:
menu_chan_join (NULL, entry->text);
break;
case GTK_RESPONSE_HELP:
chanlist_opengui (current_sess->server, TRUE);
break;
}
gtk_widget_destroy (dialog);
}
static void
menu_join_entry_cb (GtkWidget *entry, GtkDialog *dialog)
{
gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
}
static void
menu_join (GtkWidget * wid, gpointer none)
{
GtkWidget *hbox, *dialog, *entry, *label;
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
GTK_WINDOW (parent_window), 0,
_("Retrieve channel list..."), GTK_RESPONSE_HELP,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
hbox = gtk_hbox_new (TRUE, 0);
entry = gtk_entry_new ();
GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
gtk_entry_set_text (GTK_ENTRY (entry), "#");
g_signal_connect (G_OBJECT (entry), "activate",
G_CALLBACK (menu_join_entry_cb), dialog);
gtk_box_pack_end (GTK_BOX (hbox), entry, 0, 0, 0);
label = gtk_label_new (_("Enter Channel to Join:"));
gtk_box_pack_end (GTK_BOX (hbox), label, 0, 0, 0);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (menu_join_cb), entry);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (dialog);
gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
gtk_editable_set_position (GTK_EDITABLE (entry), 1);
}
static void
menu_away (GtkCheckMenuItem *item, gpointer none)
{
handle_command (current_sess, item->active ? "away" : "back", FALSE);
}
static void
menu_chanlist (GtkWidget * wid, gpointer none)
{
chanlist_opengui (current_sess->server, FALSE);
}
static void
menu_banlist (GtkWidget * wid, gpointer none)
{
banlist_opengui (current_sess);
}
#ifdef USE_PLUGIN
static void
menu_loadplugin (void)
{
plugingui_load ();
}
static void
menu_pluginlist (void)
{
plugingui_open ();
}
#else
#define menu_pluginlist 0
#define menu_loadplugin 0
#endif
#define usercommands_help _("User Commands - Special codes:\n\n"\
"%c = current channel\n"\
"%e = current network name\n"\
"%m = machine info\n"\
"%n = your nick\n"\
"%t = time/date\n"\
"%v = xchat version\n"\
"%2 = word 2\n"\
"%3 = word 3\n"\
"&2 = word 2 to the end of line\n"\
"&3 = word 3 to the end of line\n\n"\
"eg:\n"\
"/cmd john hello\n\n"\
"%2 would be \042john\042\n"\
"&2 would be \042john hello\042.")
#define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
"%a = all selected nicks\n"\
"%c = current channel\n"\
"%e = current network name\n"\
"%h = selected nick's hostname\n"\
"%m = machine info\n"\
"%n = your nick\n"\
"%s = selected nick\n"\
"%t = time/date\n")
#define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
"%a = all selected nicks\n"\
"%c = current channel\n"\
"%e = current network name\n"\
"%h = selected nick's hostname\n"\
"%m = machine info\n"\
"%n = your nick\n"\
"%s = selected nick\n"\
"%t = time/date\n")
#define ctcp_help _("CTCP Replies - Special codes:\n\n"\
"%d = data (the whole ctcp)\n"\
"%e = current network name\n"\
"%m = machine info\n"\
"%s = nick who sent the ctcp\n"\
"%t = time/date\n"\
"%2 = word 2\n"\
"%3 = word 3\n"\
"&2 = word 2 to the end of line\n"\
"&3 = word 3 to the end of line\n\n")
#define url_help _("URL Handlers - Special codes:\n\n"\
"%s = the URL string\n\n"\
"Putting a ! infront of the command\n"\
"indicates it should be sent to a\n"\
"shell instead of XChat")
static void
menu_usercommands (void)
{
editlist_gui_open (NULL, NULL, command_list, _(DISPLAY_NAME": User Defined Commands"),
"commands", "commands.conf", usercommands_help);
}
static void
menu_ulpopup (void)
{
editlist_gui_open (NULL, NULL, popup_list, _(DISPLAY_NAME": Userlist Popup menu"), "popup",
"popup.conf", ulbutton_help);
}
static void
menu_rpopup (void)
{
editlist_gui_open (_("Text"), _("Replace with"), replace_list, _(DISPLAY_NAME": Replace"), "replace",
"replace.conf", 0);
}
static void
menu_urlhandlers (void)
{
editlist_gui_open (NULL, NULL, urlhandler_list, _(DISPLAY_NAME": URL Handlers"), "urlhandlers",
"urlhandlers.conf", url_help);
}
static void
menu_evtpopup (void)
{
pevent_dialog_show ();
}
static void
menu_keypopup (void)
{
key_dialog_show ();
}
static void
menu_ulbuttons (void)
{
editlist_gui_open (NULL, NULL, button_list, _(DISPLAY_NAME": Userlist buttons"), "buttons",
"buttons.conf", ulbutton_help);
}
static void
menu_dlgbuttons (void)
{
editlist_gui_open (NULL, NULL, dlgbutton_list, _(DISPLAY_NAME": Dialog buttons"), "dlgbuttons",
"dlgbuttons.conf", dlgbutton_help);
}
static void
menu_ctcpguiopen (void)
{
editlist_gui_open (NULL, NULL, ctcp_list, _(DISPLAY_NAME": CTCP Replies"), "ctcpreply",
"ctcpreply.conf", ctcp_help);
}
static void
menu_docs (GtkWidget *wid, gpointer none)
{
fe_open_url ("http://www.hexchat.org/");
}
/*static void
menu_webpage (GtkWidget *wid, gpointer none)
{
fe_open_url ("http://xchat.org");
}*/
static void
menu_dcc_win (GtkWidget *wid, gpointer none)
{
fe_dcc_open_recv_win (FALSE);
fe_dcc_open_send_win (FALSE);
}
static void
menu_dcc_chat_win (GtkWidget *wid, gpointer none)
{
fe_dcc_open_chat_win (FALSE);
}
void
menu_change_layout (void)
{
if (prefs.hex_gui_tab_layout == 0)
{
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 1);
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 0);
mg_change_layout (0);
} else
{
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 0);
menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 1);
mg_change_layout (2);
}
}
static void
menu_layout_cb (GtkWidget *item, gpointer none)
{
prefs.hex_gui_tab_layout = 2;
if (GTK_CHECK_MENU_ITEM (item)->active)
prefs.hex_gui_tab_layout = 0;
menu_change_layout ();
}
static void
menu_apply_metres_cb (session *sess)
{
mg_update_meters (sess->gui);
}
static void
menu_metres_off (GtkWidget *item, gpointer none)
{
if (GTK_CHECK_MENU_ITEM (item)->active)
{
prefs.hex_gui_lagometer = 0;
prefs.hex_gui_throttlemeter = 0;
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
}
}
static void
menu_metres_text (GtkWidget *item, gpointer none)
{
if (GTK_CHECK_MENU_ITEM (item)->active)
{
prefs.hex_gui_lagometer = 2;
prefs.hex_gui_throttlemeter = 2;
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
}
}
static void
menu_metres_graph (GtkWidget *item, gpointer none)
{
if (GTK_CHECK_MENU_ITEM (item)->active)
{
prefs.hex_gui_lagometer = 1;
prefs.hex_gui_throttlemeter = 1;
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
}
}
static void
menu_metres_both (GtkWidget *item, gpointer none)
{
if (GTK_CHECK_MENU_ITEM (item)->active)
{
prefs.hex_gui_lagometer = 3;
prefs.hex_gui_throttlemeter = 3;
menu_setting_foreach (menu_apply_metres_cb, -1, 0);
}
}
static struct mymenu mymenu[] = {
{N_("He_xChat"), 0, 0, M_NEWMENU, 0, 0, 1},
{N_("Network Li_st..."), menu_open_server_list, (char *)&pix_book, M_MENUPIX, 0, 0, 1, GDK_s},
{0, 0, 0, M_SEP, 0, 0, 0},
{N_("_New"), 0, GTK_STOCK_NEW, M_MENUSUB, 0, 0, 1},
{N_("Server Tab..."), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_t},
{N_("Channel Tab..."), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
{N_("Server Window..."), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1},
{N_("Channel Window..."), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
{0, 0, 0, M_END, 0, 0, 0},
{0, 0, 0, M_SEP, 0, 0, 0},
#ifdef USE_PLUGIN
{N_("_Load Plugin or Script..."), menu_loadplugin, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 1},
#else
{N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 0},
#endif
{0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
#define DETACH_OFFSET (12)
{0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_i}, /* 12 */
#define CLOSE_OFFSET (13)
{0, menu_close, GTK_STOCK_CLOSE, M_MENUSTOCK, 0, 0, 1, GDK_w},
{0, 0, 0, M_SEP, 0, 0, 0},
{N_("_Quit"), menu_quit, GTK_STOCK_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_q}, /* 15 */
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
#define MENUBAR_OFFSET (17)
{N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_F9},
{N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
{N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_F7},
{N_("U_serlist Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
{N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
{0, 0, 0, M_SEP, 0, 0, 0},
{N_("_Channel Switcher"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 23 */
#define TABS_OFFSET (24)
{N_("_Tabs"), menu_layout_cb, 0, M_MENURADIO, MENU_ID_LAYOUT_TABS, 0, 1},
{N_("T_ree"), 0, 0, M_MENURADIO, MENU_ID_LAYOUT_TREE, 0, 1},
{0, 0, 0, M_END, 0, 0, 0},
{N_("_Network Meters"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 27 */
#define METRE_OFFSET (28)
{N_("Off"), menu_metres_off, 0, M_MENURADIO, 0, 0, 1},
{N_("Graph"), menu_metres_graph, 0, M_MENURADIO, 0, 0, 1},
{N_("Text"), menu_metres_text, 0, M_MENURADIO, 0, 0, 1},
{N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
{0, 0, 0, M_END, 0, 0, 0}, /* 32 */
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
{N_("_Disconnect"), menu_disconnect, GTK_STOCK_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
{N_("_Reconnect"), menu_reconnect, GTK_STOCK_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
{N_("Join a Channel..."), menu_join, GTK_STOCK_JUMP_TO, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
{N_("List of Channels..."), menu_chanlist, GTK_STOCK_INDEX, M_MENUITEM, 0, 0, 1},
{0, 0, 0, M_SEP, 0, 0, 0},
#define AWAY_OFFSET (39)
{N_("Marked Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_a},
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
{N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
{N_("_Preferences"), menu_settings, GTK_STOCK_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
{0, 0, 0, M_SEP, 0, 0, 0},
{N_("Auto Replace..."), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
{N_("CTCP Replies..."), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
{N_("Dialog Buttons..."), menu_dlgbuttons, 0, M_MENUITEM, 0, 0, 1},
{N_("Keyboard Shortcuts..."), menu_keypopup, 0, M_MENUITEM, 0, 0, 1},
{N_("Text Events..."), menu_evtpopup, 0, M_MENUITEM, 0, 0, 1},
{N_("URL Handlers..."), menu_urlhandlers, 0, M_MENUITEM, 0, 0, 1},
{N_("User Commands..."), menu_usercommands, 0, M_MENUITEM, 0, 0, 1},
{N_("Userlist Buttons..."), menu_ulbuttons, 0, M_MENUITEM, 0, 0, 1},
{N_("Userlist Popup..."), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1}, /* 52 */
{N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
{N_("Ban List..."), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
{N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
{N_("Direct Chat..."), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
{N_("File Transfers..."), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
{N_("Friends List..."), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
{N_("Ignore List..."), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
{N_("Plugins and Scripts..."), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
{N_("Raw Log..."), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 61 */
{N_("URL Grabber..."), url_opengui, 0, M_MENUITEM, 0, 0, 1},
{0, 0, 0, M_SEP, 0, 0, 0},
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_C},
{N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
{N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
#define SEARCH_OFFSET 68
{N_("Search"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
{N_("Reset Search"), menu_search_reset, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_F},
{N_("Search Next" ), menu_search_next, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_g},
{N_("Search Previous" ), menu_search_prev, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_G},
{0, 0, 0, M_END, 0, 0, 0},
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
{N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
#if 0
{N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},
#endif
{N_("_About"), menu_about, GTK_STOCK_ABOUT, M_MENUSTOCK, 0, 0, 1},
{0, 0, 0, M_END, 0, 0, 0},
};
GtkWidget *
create_icon_menu (char *labeltext, void *stock_name, int is_stock)
{
GtkWidget *item, *img;
if (is_stock)
img = gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
else
img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
item = gtk_image_menu_item_new_with_mnemonic (labeltext);
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
gtk_widget_show (img);
return item;
}
/* Override the default GTK2.4 handler, which would make menu
bindings not work when the menu-bar is hidden. */
static gboolean
menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
{
/* GTK2.2 behaviour */
#if GTK_CHECK_VERSION(2,20,0)
return gtk_widget_is_sensitive (widget);
#else
return GTK_WIDGET_IS_SENSITIVE (widget);
#endif
}
/* === STUFF FOR /MENU === */
static GtkMenuItem *
menu_find_item (GtkWidget *menu, char *name)
{
GList *items = ((GtkMenuShell *) menu)->children;
GtkMenuItem *item;
GtkWidget *child;
const char *labeltext;
while (items)
{
item = items->data;
child = GTK_BIN (item)->child;
if (child) /* separators arn't labels, skip them */
{
labeltext = g_object_get_data (G_OBJECT (item), "name");
if (!labeltext)
labeltext = gtk_label_get_text (GTK_LABEL (child));
if (!menu_streq (labeltext, name, 1))
return item;
} else if (name == NULL)
{
return item;
}
items = items->next;
}
return NULL;
}
static GtkWidget *
menu_find_path (GtkWidget *menu, char *path)
{
GtkMenuItem *item;
char *s;
char name[128];
int len;
/* grab the next part of the path */
s = strchr (path, '/');
len = s - path;
if (!s)
len = strlen (path);
len = MIN (len, sizeof (name) - 1);
memcpy (name, path, len);
name[len] = 0;
item = menu_find_item (menu, name);
if (!item)
return NULL;
menu = gtk_menu_item_get_submenu (item);
if (!menu)
return NULL;
path += len;
if (*path == 0)
return menu;
return menu_find_path (menu, path + 1);
}
static GtkWidget *
menu_find (GtkWidget *menu, char *path, char *label)
{
GtkWidget *item = NULL;
if (path[0] != 0)
menu = menu_find_path (menu, path);
if (menu)
item = (GtkWidget *)menu_find_item (menu, label);
return item;
}
static void
menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, char *))
{
GSList *list = sess_list;
int tabdone = FALSE;
session *sess;
if (!me->is_main)
return; /* not main menu */
while (list)
{
sess = list->data;
/* do it only once for tab sessions, since they share a GUI */
if (!sess->gui->is_tab || !tabdone)
{
callback (sess->gui->menu, me, NULL);
if (sess->gui->is_tab)
tabdone = TRUE;
}
list = list->next;
}
}
static void
menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
{
GtkWidget *item;
item = menu_find (menu, me->path, me->label);
if (item)
{
gtk_widget_set_sensitive (item, me->enable);
/* must do it without triggering the callback */
if (GTK_IS_CHECK_MENU_ITEM (item))
GTK_CHECK_MENU_ITEM (item)->active = me->state;
}
}
/* radio state changed via mouse click */
static void
menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
{
me->state = 0;
if (item->active)
me->state = 1;
/* update the state, incase this was changed via right-click. */
/* This will update all other windows and menu bars */
menu_foreach_gui (me, menu_update_cb);
if (me->state && me->cmd)
handle_command (current_sess, me->cmd, FALSE);
}
/* toggle state changed via mouse click */
static void
menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
{
me->state = 0;
if (item->active)
me->state = 1;
/* update the state, incase this was changed via right-click. */
/* This will update all other windows and menu bars */
menu_foreach_gui (me, menu_update_cb);
if (me->state)
handle_command (current_sess, me->cmd, FALSE);
else
handle_command (current_sess, me->ucmd, FALSE);
}
static GtkWidget *
menu_radio_item (char *label, GtkWidget *menu, void *callback, void *userdata,
int state, char *groupname)
{
GtkWidget *item;
GtkMenuItem *parent;
GSList *grouplist = NULL;
parent = menu_find_item (menu, groupname);
if (parent)
grouplist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *)parent);
item = gtk_radio_menu_item_new_with_label (grouplist, label);
gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
g_signal_connect (G_OBJECT (item), "activate",
G_CALLBACK (callback), userdata);
gtk_widget_show (item);
return item;
}
static void
menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
{
if (pos == 0xffff) /* outbound.c uses this default */
return;
if (pos < 0) /* position offset from end/bottom */
gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
else
gtk_menu_reorder_child (menu, item, pos);
}
static GtkWidget *
menu_add_radio (GtkWidget *menu, menu_entry *me)
{
GtkWidget *item = NULL;
char *path = me->path + me->root_offset;
if (path[0] != 0)
menu = menu_find_path (menu, path);
if (menu)
{
item = menu_radio_item (me->label, menu, menu_radio_cb, me, me->state, me->group);
menu_reorder (GTK_MENU (menu), item, me->pos);
}
return item;
}
static GtkWidget *
menu_add_toggle (GtkWidget *menu, menu_entry *me)
{
GtkWidget *item = NULL;
char *path = me->path + me->root_offset;
if (path[0] != 0)
menu = menu_find_path (menu, path);
if (menu)
{
item = menu_toggle_item (me->label, menu, menu_toggle_cb, me, me->state);
menu_reorder (GTK_MENU (menu), item, me->pos);
}
return item;
}
static GtkWidget *
menu_add_item (GtkWidget *menu, menu_entry *me, char *target)
{
GtkWidget *item = NULL;
char *path = me->path + me->root_offset;
if (path[0] != 0)
menu = menu_find_path (menu, path);
if (menu)
{
item = menu_quick_item (me->cmd, me->label, menu, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, target, me->icon);
menu_reorder (GTK_MENU (menu), item, me->pos);
}
return item;
}
static GtkWidget *
menu_add_sub (GtkWidget *menu, menu_entry *me)
{
GtkWidget *item = NULL;
char *path = me->path + me->root_offset;
int pos;
if (path[0] != 0)
menu = menu_find_path (menu, path);
if (menu)
{
pos = me->pos;
if (pos < 0) /* position offset from end/bottom */
pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
}
return item;
}
static void
menu_del_cb (GtkWidget *menu, menu_entry *me, char *target)
{
GtkWidget *item = menu_find (menu, me->path + me->root_offset, me->label);
if (item)
gtk_widget_destroy (item);
}
static void
menu_add_cb (GtkWidget *menu, menu_entry *me, char *target)
{
GtkWidget *item;
GtkAccelGroup *accel_group;
if (me->group) /* have a group name? Must be a radio item */
item = menu_add_radio (menu, me);
else if (me->ucmd) /* have unselect-cmd? Must be a toggle item */
item = menu_add_toggle (menu, me);
else if (me->cmd || !me->label) /* label=NULL for separators */
item = menu_add_item (menu, me, target);
else
item = menu_add_sub (menu, me);
if (item)
{
gtk_widget_set_sensitive (item, me->enable);
if (me->key)
{
accel_group = g_object_get_data (G_OBJECT (menu), "accel");
if (accel_group) /* popup menus don't have them */
gtk_widget_add_accelerator (item, "activate", accel_group, me->key,
me->modifier, GTK_ACCEL_VISIBLE);
}
}
}
char *
fe_menu_add (menu_entry *me)
{
char *text;
menu_foreach_gui (me, menu_add_cb);
if (!me->markup)
return NULL;
if (!pango_parse_markup (me->label, -1, 0, NULL, &text, NULL, NULL))
return NULL;
/* return the label with markup stripped */
return text;
}
void
fe_menu_del (menu_entry *me)
{
menu_foreach_gui (me, menu_del_cb);
}
void
fe_menu_update (menu_entry *me)
{
menu_foreach_gui (me, menu_update_cb);
}
/* used to add custom menus to the right-click menu */
static void
menu_add_plugin_mainmenu_items (GtkWidget *menu)
{
GSList *list;
menu_entry *me;
list = menu_list; /* outbound.c */
while (list)
{
me = list->data;
if (me->is_main)
menu_add_cb (menu, me, NULL);
list = list->next;
}
}
void
menu_add_plugin_items (GtkWidget *menu, char *root, char *target)
{
GSList *list;
menu_entry *me;
list = menu_list; /* outbound.c */
while (list)
{
me = list->data;
if (!me->is_main && !strncmp (me->path, root + 1, root[0]))
menu_add_cb (menu, me, target);
list = list->next;
}
}
/* === END STUFF FOR /MENU === */
GtkWidget *
menu_create_main (void *accel_group, int bar, int away, int toplevel,
GtkWidget **menu_widgets)
{
int i = 0;
GtkWidget *item;
GtkWidget *menu = 0;
GtkWidget *menu_item = 0;
GtkWidget *menu_bar;
GtkWidget *usermenu = 0;
GtkWidget *submenu = 0;
int close_mask = STATE_CTRL;
int away_mask = STATE_ALT;
char *key_theme = NULL;
GtkSettings *settings;
GSList *group = NULL;
if (bar)
menu_bar = gtk_menu_bar_new ();
else
menu_bar = gtk_menu_new ();
/* /MENU needs to know this later */
g_object_set_data (G_OBJECT (menu_bar), "accel", accel_group);
g_signal_connect (G_OBJECT (menu_bar), "can-activate-accel",
G_CALLBACK (menu_canacaccel), 0);
/* set the initial state of toggles */
mymenu[MENUBAR_OFFSET].state = !prefs.hex_gui_hide_menu;
mymenu[MENUBAR_OFFSET+1].state = prefs.hex_gui_topicbar;
mymenu[MENUBAR_OFFSET+2].state = !prefs.hex_gui_ulist_hide;
mymenu[MENUBAR_OFFSET+3].state = prefs.hex_gui_ulist_buttons;
mymenu[MENUBAR_OFFSET+4].state = prefs.hex_gui_mode_buttons;
mymenu[AWAY_OFFSET].state = away;
switch (prefs.hex_gui_tab_layout)
{
case 0:
mymenu[TABS_OFFSET].state = 1;
mymenu[TABS_OFFSET+1].state = 0;
break;
default:
mymenu[TABS_OFFSET].state = 0;
mymenu[TABS_OFFSET+1].state = 1;
}
mymenu[METRE_OFFSET].state = 0;
mymenu[METRE_OFFSET+1].state = 0;
mymenu[METRE_OFFSET+2].state = 0;
mymenu[METRE_OFFSET+3].state = 0;
switch (prefs.hex_gui_lagometer)
{
case 0:
mymenu[METRE_OFFSET].state = 1;
break;
case 1:
mymenu[METRE_OFFSET+1].state = 1;
break;
case 2:
mymenu[METRE_OFFSET+2].state = 1;
break;
default:
mymenu[METRE_OFFSET+3].state = 1;
}
/* change Close binding to ctrl-shift-w when using emacs keys */
settings = gtk_widget_get_settings (menu_bar);
if (settings)
{
g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
if (key_theme)
{
if (!g_ascii_strcasecmp (key_theme, "Emacs"))
{
close_mask = STATE_SHIFT | STATE_CTRL;
mymenu[SEARCH_OFFSET].key = 0;
}
g_free (key_theme);
}
}
/* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
{
char *help = _("_Help");
char *under = strchr (help, '_');
if (under && (under[1] == 'a' || under[1] == 'A'))
away_mask = STATE_ALT | STATE_CTRL;
}
if (!toplevel)
{
mymenu[DETACH_OFFSET].text = N_("_Detach");
mymenu[CLOSE_OFFSET].text = N_("_Close");
}
else
{
mymenu[DETACH_OFFSET].text = N_("_Attach");
mymenu[CLOSE_OFFSET].text = N_("_Close");
}
while (1)
{
item = NULL;
if (mymenu[i].id == MENU_ID_USERMENU && !prefs.hex_gui_usermenu)
{
i++;
continue;
}
switch (mymenu[i].type)
{
case M_NEWMENU:
if (menu)
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
item = menu = gtk_menu_new ();
if (mymenu[i].id == MENU_ID_USERMENU)
usermenu = menu;
menu_item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
/* record the English name for /menu */
g_object_set_data (G_OBJECT (menu_item), "name", mymenu[i].text);
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
gtk_widget_show (menu_item);
break;
case M_MENUPIX:
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, FALSE);
goto normalitem;
case M_MENUSTOCK:
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
goto normalitem;
case M_MENUITEM:
item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
normalitem:
if (mymenu[i].key != 0)
gtk_widget_add_accelerator (item, "activate", accel_group,
mymenu[i].key,
mymenu[i].key == GDK_F1 ? 0 :
mymenu[i].key == GDK_w ? close_mask :
(g_ascii_isupper (mymenu[i].key)) ?
STATE_SHIFT | STATE_CTRL :
STATE_CTRL,
GTK_ACCEL_VISIBLE);
if (mymenu[i].callback)
g_signal_connect (G_OBJECT (item), "activate",
G_CALLBACK (mymenu[i].callback), 0);
if (submenu)
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
else
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
break;
case M_MENUTOG:
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
togitem:
/* must avoid callback for Radio buttons */
GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
mymenu[i].state);*/
if (mymenu[i].key != 0)
gtk_widget_add_accelerator (item, "activate", accel_group,
mymenu[i].key, mymenu[i].id == MENU_ID_AWAY ?
away_mask : STATE_CTRL, GTK_ACCEL_VISIBLE);
if (mymenu[i].callback)
g_signal_connect (G_OBJECT (item), "toggled",
G_CALLBACK (mymenu[i].callback), 0);
if (submenu)
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
else
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
gtk_widget_set_sensitive (item, mymenu[i].sensitive);
break;
case M_MENURADIO:
item = gtk_radio_menu_item_new_with_mnemonic (group, _(mymenu[i].text));
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
goto togitem;
case M_SEP:
item = gtk_menu_item_new ();
gtk_widget_set_sensitive (item, FALSE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
break;
case M_MENUSUB:
group = NULL;
submenu = gtk_menu_new ();
item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
/* record the English name for /menu */
g_object_set_data (G_OBJECT (item), "name", mymenu[i].text);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
break;
/*case M_END:*/ default:
if (!submenu)
{
if (menu)
{
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
menu_add_plugin_mainmenu_items (menu_bar);
}
if (usermenu)
usermenu_create (usermenu);
return (menu_bar);
}
submenu = NULL;
}
/* record this GtkWidget * so it's state might be changed later */
if (mymenu[i].id != 0 && menu_widgets)
/* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
menu_widgets[mymenu[i].id] = item;
i++;
}
}
|