fix implicit declarations
[rofl0r-ixchat.git] / src / fe-gtk / menu.c
blob988e0f292aee893cffa91717213609515176f0f4
1 /* X-Chat
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
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
25 #include "fe-gtk.h"
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"
51 #include "xtext.h"
52 #include "about.h"
53 #include "ascii.h"
54 #include "banlist.h"
55 #include "chanlist.h"
56 #include "editlist.h"
57 #include "fkeys.h"
58 #include "gtkutil.h"
59 #include "maingui.h"
60 #include "notifygui.h"
61 #include "pixmaps.h"
62 #include "rawlog.h"
63 #include "palette.h"
64 #include "plugingui.h"
65 #include "search.h"
66 #include "textgui.h"
67 #include "urlgrab.h"
68 #include "userlistgui.h"
69 #include "menu.h"
70 #include "servlistgui.h"
72 static GSList *submenu_list;
74 enum
76 M_MENUITEM,
77 M_NEWMENU,
78 M_END,
79 M_SEP,
80 M_MENUTOG,
81 M_MENURADIO,
82 M_MENUSTOCK,
83 M_MENUPIX,
84 M_MENUSUB
87 struct mymenu
89 char *text;
90 void *callback;
91 char *image;
92 unsigned char type; /* M_XXX */
93 unsigned char id; /* MENU_ID_XXX (menu.h) */
94 unsigned char state; /* ticked or not? */
95 unsigned char sensitive; /* shaded out? */
96 guint key; /* GDK_x */
99 #define XCMENU_DOLIST 1
100 #define XCMENU_SHADED 1
101 #define XCMENU_MARKUP 2
102 #define XCMENU_MNEMONIC 4
104 /* execute a userlistbutton/popupmenu command */
106 static void
107 nick_command (session * sess, char *cmd)
109 if (*cmd == '!')
110 xchat_exec (cmd + 1);
111 else
112 handle_command (sess, cmd, TRUE);
115 /* fill in the %a %s %n etc and execute the command */
117 void
118 nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
120 char *buf;
121 char *host = _("Host unknown");
122 struct User *user;
123 int len;
125 /* if (sess->type == SESS_DIALOG)
127 buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
128 buf = strrchr (buf, '@');
129 if (buf)
130 host = buf + 1;
131 } else*/
133 user = userlist_find (sess, nick);
134 if (user && user->hostname)
135 host = strchr (user->hostname, '@') + 1;
138 /* this can't overflow, since popup->cmd is only 256 */
139 len = strlen (cmd) + strlen (nick) + strlen (allnick) + 512;
140 buf = malloc (len);
142 auto_insert (buf, len, cmd, 0, 0, allnick, sess->channel, "",
143 server_get_network (sess->server, TRUE), host,
144 sess->server->nick, nick);
146 nick_command (sess, buf);
148 free (buf);
151 /* userlist button has been clicked */
153 void
154 userlist_button_cb (GtkWidget * button, char *cmd)
156 int i, num_sel, using_allnicks = FALSE;
157 char **nicks, *allnicks;
158 char *nick = NULL;
159 session *sess;
161 sess = current_sess;
163 if (strstr (cmd, "%a"))
164 using_allnicks = TRUE;
166 if (sess->type == SESS_DIALOG)
168 /* fake a selection */
169 nicks = malloc (sizeof (char *) * 2);
170 nicks[0] = g_strdup (sess->channel);
171 nicks[1] = NULL;
172 num_sel = 1;
173 } else
175 /* find number of selected rows */
176 nicks = userlist_selection_list (sess->gui->user_tree, &num_sel);
177 if (num_sel < 1)
179 nick_command_parse (sess, cmd, "", "");
180 return;
184 /* create "allnicks" string */
185 allnicks = malloc (((NICKLEN + 1) * num_sel) + 1);
186 *allnicks = 0;
188 i = 0;
189 while (nicks[i])
191 if (i > 0)
192 strcat (allnicks, " ");
193 strcat (allnicks, nicks[i]);
195 if (!nick)
196 nick = nicks[0];
198 /* if not using "%a", execute the command once for each nickname */
199 if (!using_allnicks)
200 nick_command_parse (sess, cmd, nicks[i], "");
202 i++;
205 if (using_allnicks)
207 if (!nick)
208 nick = "";
209 nick_command_parse (sess, cmd, nick, allnicks);
212 while (num_sel)
214 num_sel--;
215 g_free (nicks[num_sel]);
218 free (nicks);
219 free (allnicks);
222 /* a popup-menu-item has been selected */
224 static void
225 popup_menu_cb (GtkWidget * item, char *cmd)
227 char *nick;
229 /* the userdata is set in menu_quick_item() */
230 nick = g_object_get_data (G_OBJECT (item), "u");
232 if (!nick) /* userlist popup menu */
234 /* treat it just like a userlist button */
235 userlist_button_cb (NULL, cmd);
236 return;
239 if (!current_sess) /* for url grabber window */
240 nick_command_parse (sess_list->data, cmd, nick, nick);
241 else
242 nick_command_parse (current_sess, cmd, nick, nick);
245 GtkWidget *
246 menu_toggle_item (char *label, GtkWidget *menu, void *callback, void *userdata,
247 int state)
249 GtkWidget *item;
251 item = gtk_check_menu_item_new_with_mnemonic (label);
252 gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
253 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
254 g_signal_connect (G_OBJECT (item), "activate",
255 G_CALLBACK (callback), userdata);
256 gtk_widget_show (item);
258 return item;
261 GtkWidget *
262 menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
263 gpointer userdata, char *icon)
265 GtkWidget *img, *item;
266 char *path;
268 if (!label)
269 item = gtk_menu_item_new ();
270 else
272 if (icon)
274 /*if (flags & XCMENU_MARKUP)
275 item = gtk_image_menu_item_new_with_markup (label);
276 else*/
277 item = gtk_image_menu_item_new_with_mnemonic (label);
278 img = NULL;
279 if (access (icon, R_OK) == 0) /* try fullpath */
280 img = gtk_image_new_from_file (icon);
281 else
283 /* try relative to ~/.xchat2 */
284 path = g_strdup_printf ("%s/%s", get_xdir_fs (), icon);
285 if (access (path, R_OK) == 0)
286 img = gtk_image_new_from_file (path);
287 else
288 img = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
289 g_free (path);
292 if (img)
293 gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
295 else
297 if (flags & XCMENU_MARKUP)
299 item = gtk_menu_item_new_with_label ("");
300 if (flags & XCMENU_MNEMONIC)
301 gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item)->child), label);
302 else
303 gtk_label_set_markup (GTK_LABEL (GTK_BIN (item)->child), label);
304 } else
306 if (flags & XCMENU_MNEMONIC)
307 item = gtk_menu_item_new_with_mnemonic (label);
308 else
309 item = gtk_menu_item_new_with_label (label);
313 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
314 g_object_set_data (G_OBJECT (item), "u", userdata);
315 if (cmd)
316 g_signal_connect (G_OBJECT (item), "activate",
317 G_CALLBACK (popup_menu_cb), cmd);
318 if (flags & XCMENU_SHADED)
319 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
320 gtk_widget_show_all (item);
322 return item;
325 static void
326 menu_quick_item_with_callback (void *callback, char *label, GtkWidget * menu,
327 void *arg)
329 GtkWidget *item;
331 item = gtk_menu_item_new_with_label (label);
332 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
333 g_signal_connect (G_OBJECT (item), "activate",
334 G_CALLBACK (callback), arg);
335 gtk_widget_show (item);
338 GtkWidget *
339 menu_quick_sub (char *name, GtkWidget *menu, GtkWidget **sub_item_ret, int flags, int pos)
341 GtkWidget *sub_menu;
342 GtkWidget *sub_item;
344 if (!name)
345 return menu;
347 /* Code to add a submenu */
348 sub_menu = gtk_menu_new ();
349 if (flags & XCMENU_MARKUP)
351 sub_item = gtk_menu_item_new_with_label ("");
352 gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item)->child), name);
354 else
356 if (flags & XCMENU_MNEMONIC)
357 sub_item = gtk_menu_item_new_with_mnemonic (name);
358 else
359 sub_item = gtk_menu_item_new_with_label (name);
361 gtk_menu_shell_insert (GTK_MENU_SHELL (menu), sub_item, pos);
362 gtk_widget_show (sub_item);
363 gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item), sub_menu);
365 if (sub_item_ret)
366 *sub_item_ret = sub_item;
368 if (flags & XCMENU_DOLIST)
369 /* We create a new element in the list */
370 submenu_list = g_slist_prepend (submenu_list, sub_menu);
371 return sub_menu;
374 static GtkWidget *
375 menu_quick_endsub ()
377 /* Just delete the first element in the linked list pointed to by first */
378 if (submenu_list)
379 submenu_list = g_slist_remove (submenu_list, submenu_list->data);
381 if (submenu_list)
382 return (submenu_list->data);
383 else
384 return NULL;
387 static void
388 toggle_cb (GtkWidget *item, char *pref_name)
390 char buf[256];
392 if (GTK_CHECK_MENU_ITEM (item)->active)
393 snprintf (buf, sizeof (buf), "set %s 1", pref_name);
394 else
395 snprintf (buf, sizeof (buf), "set %s 0", pref_name);
397 handle_command (current_sess, buf, FALSE);
400 static int
401 is_in_path (char *cmd)
403 char *prog = strdup (cmd + 1); /* 1st char is "!" */
404 char *space, *path, *orig;
406 orig = prog; /* save for free()ing */
407 /* special-case these default entries. */
408 /* 123456789012345678 */
409 if (strncmp (prog, "gnome-terminal -x ", 18) == 0)
410 /* don't check for gnome-terminal, but the thing it's executing! */
411 prog += 18;
413 space = strchr (prog, ' '); /* this isn't 100% but good enuf */
414 if (space)
415 *space = 0;
417 path = g_find_program_in_path (prog);
418 if (path)
420 g_free (path);
421 g_free (orig);
422 return 1;
425 g_free (orig);
426 return 0;
429 /* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
431 static void
432 menu_extract_icon (char *name, char **label, char **icon)
434 char *p = name;
435 char *start = NULL;
436 char *end = NULL;
438 while (*p)
440 if (*p == '~')
442 /* escape \~ */
443 if (p == name || p[-1] != '\\')
445 if (!start)
446 start = p + 1;
447 else if (!end)
448 end = p + 1;
451 p++;
454 if (!end)
455 end = p;
457 if (start && start != end)
459 *label = g_strndup (name, (start - name) - 1);
460 *icon = g_strndup (start, (end - start) - 1);
462 else
464 *label = g_strdup (name);
465 *icon = NULL;
469 /* append items to "menu" using the (struct popup*) list provided */
471 void
472 menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
474 struct popup *pop;
475 GtkWidget *tempmenu = menu, *subitem = NULL;
476 int childcount = 0;
478 submenu_list = g_slist_prepend (0, menu);
479 while (list)
481 pop = (struct popup *) list->data;
483 if (!strncasecmp (pop->name, "SUB", 3))
485 childcount = 0;
486 tempmenu = menu_quick_sub (pop->cmd, tempmenu, &subitem, XCMENU_DOLIST|XCMENU_MNEMONIC, -1);
488 } else if (!strncasecmp (pop->name, "TOGGLE", 6))
490 childcount++;
491 menu_toggle_item (pop->name + 7, tempmenu, toggle_cb, pop->cmd,
492 cfg_get_bool (pop->cmd));
494 } else if (!strncasecmp (pop->name, "ENDSUB", 6))
496 /* empty sub menu due to no programs in PATH? */
497 if (check_path && childcount < 1)
498 gtk_widget_destroy (subitem);
499 subitem = NULL;
501 if (tempmenu != menu)
502 tempmenu = menu_quick_endsub ();
503 /* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
505 } else if (!strncasecmp (pop->name, "SEP", 3))
507 menu_quick_item (0, 0, tempmenu, XCMENU_SHADED, 0, 0);
509 } else
511 char *icon, *label;
513 /* default command in xchat.c */
514 if (pop->cmd[0] == 'n' && !strcmp (pop->cmd, "notify -n ASK %s"))
516 /* don't create this item if already in notify list */
517 if (!target || notify_is_in_list (current_sess->server, target))
519 list = list->next;
520 continue;
524 menu_extract_icon (pop->name, &label, &icon);
526 if (!check_path || pop->cmd[0] != '!')
528 menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
529 /* check if the program is in path, if not, leave it out! */
530 } else if (is_in_path (pop->cmd))
532 childcount++;
533 menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
536 g_free (label);
537 g_free (icon);
540 list = list->next;
543 /* Let's clean up the linked list from mem */
544 while (submenu_list)
545 submenu_list = g_slist_remove (submenu_list, submenu_list->data);
548 static char *str_copy = NULL; /* for all pop-up menus */
549 static GtkWidget *nick_submenu = NULL; /* user info submenu */
551 static void
552 menu_destroy (GtkWidget *menu, gpointer objtounref)
554 gtk_widget_destroy (menu);
555 g_object_unref (menu);
556 if (objtounref)
557 g_object_unref (G_OBJECT (objtounref));
558 nick_submenu = NULL;
561 static void
562 menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
564 if (event && event->window)
565 gtk_menu_set_screen (GTK_MENU (menu), gdk_drawable_get_screen (event->window));
567 g_object_ref (menu);
568 g_object_ref_sink (menu);
569 g_object_unref (menu);
570 g_signal_connect (G_OBJECT (menu), "selection-done",
571 G_CALLBACK (menu_destroy), objtounref);
572 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
573 0, event ? event->time : 0);
576 static void
577 menu_nickinfo_cb (GtkWidget *menu, session *sess)
579 char buf[512];
581 if (!is_session (sess))
582 return;
584 /* issue a /WHOIS */
585 snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
586 handle_command (sess, buf, FALSE);
587 /* and hide the output */
588 sess->server->skip_next_whois = 1;
591 static void
592 copy_to_clipboard_cb (GtkWidget *item, char *url)
594 gtkutil_copy_to_clipboard (item, NULL, url);
597 /* returns boolean: Some data is missing */
599 static gboolean
600 menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
602 char buf[512];
603 char unknown[96];
604 char *real, *fmt;
605 struct away_msg *away;
606 gboolean missing = FALSE;
607 GtkWidget *item;
609 /* let the translators tweak this if need be */
610 fmt = _("<tt><b>%-11s</b></tt> %s");
611 snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
613 if (user->realname)
615 real = strip_color (user->realname, -1, STRIP_ALL|STRIP_ESCMARKUP);
616 snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
617 g_free (real);
618 } else
620 snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
622 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
623 g_signal_connect (G_OBJECT (item), "activate",
624 G_CALLBACK (copy_to_clipboard_cb),
625 user->realname ? user->realname : unknown);
627 snprintf (buf, sizeof (buf), fmt, _("User:"),
628 user->hostname ? user->hostname : unknown);
629 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
630 g_signal_connect (G_OBJECT (item), "activate",
631 G_CALLBACK (copy_to_clipboard_cb),
632 user->hostname ? user->hostname : unknown);
634 snprintf (buf, sizeof (buf), fmt, _("Account:"),
635 user->account ? user->account : unknown);
636 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
637 g_signal_connect (G_OBJECT (item), "activate",
638 G_CALLBACK (copy_to_clipboard_cb),
639 user->account ? user->account : unknown);
641 snprintf (buf, sizeof (buf), fmt, _("Country:"),
642 user->hostname ? country(user->hostname) : unknown);
643 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
644 g_signal_connect (G_OBJECT (item), "activate",
645 G_CALLBACK (copy_to_clipboard_cb),
646 user->hostname ? country(user->hostname) : unknown);
648 snprintf (buf, sizeof (buf), fmt, _("Server:"),
649 user->servername ? user->servername : unknown);
650 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
651 g_signal_connect (G_OBJECT (item), "activate",
652 G_CALLBACK (copy_to_clipboard_cb),
653 user->servername ? user->servername : unknown);
655 if (user->lasttalk)
657 char min[96];
659 snprintf (min, sizeof (min), _("%u minutes ago"),
660 (unsigned int) ((time (0) - user->lasttalk) / 60));
661 snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
662 } else
664 snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
666 menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
668 if (user->away)
670 away = server_away_find_message (current_sess->server, user->nick);
671 if (away)
673 char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP);
674 snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
675 g_free (msg);
676 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
677 g_signal_connect (G_OBJECT (item), "activate",
678 G_CALLBACK (copy_to_clipboard_cb),
679 away->message ? away->message : unknown);
681 else
682 missing = TRUE;
685 return missing;
688 void
689 fe_userlist_update (session *sess, struct User *user)
691 GList *items, *next;
693 if (!nick_submenu || !str_copy)
694 return;
696 /* not the same nick as the menu? */
697 if (sess->server->p_cmp (user->nick, str_copy))
698 return;
700 /* get rid of the "show" signal */
701 g_signal_handlers_disconnect_by_func (nick_submenu, menu_nickinfo_cb, sess);
703 /* destroy all the old items */
704 items = ((GtkMenuShell *) nick_submenu)->children;
705 while (items)
707 next = items->next;
708 gtk_widget_destroy (items->data);
709 items = next;
712 /* and re-create them with new info */
713 menu_create_nickinfo_menu (user, nick_submenu);
716 void
717 menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
719 char buf[512];
720 struct User *user;
721 GtkWidget *submenu, *menu = gtk_menu_new ();
723 if (str_copy)
724 free (str_copy);
725 str_copy = strdup (nick);
727 submenu_list = 0; /* first time through, might not be 0 */
729 /* more than 1 nick selected? */
730 if (num_sel > 1)
732 snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
733 menu_quick_item (0, buf, menu, 0, 0, 0);
734 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
735 } else
737 user = userlist_find (sess, nick); /* lasttalk is channel specific */
738 if (!user)
739 user = userlist_find_global (current_sess->server, nick);
740 if (user)
742 nick_submenu = submenu = menu_quick_sub (nick, menu, NULL, XCMENU_DOLIST, -1);
744 if (menu_create_nickinfo_menu (user, submenu) ||
745 !user->hostname || !user->realname || !user->servername)
747 g_signal_connect (G_OBJECT (submenu), "show", G_CALLBACK (menu_nickinfo_cb), sess);
750 menu_quick_endsub ();
751 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
755 if (num_sel > 1)
756 menu_create (menu, popup_list, NULL, FALSE);
757 else
758 menu_create (menu, popup_list, str_copy, FALSE);
760 if (num_sel == 0) /* xtext click */
761 menu_add_plugin_items (menu, "\x5$NICK", str_copy);
762 else /* userlist treeview click */
763 menu_add_plugin_items (menu, "\x5$NICK", NULL);
765 menu_popup (menu, event, NULL);
768 /* stuff for the View menu */
770 static void
771 menu_showhide_cb (session *sess)
773 if (prefs.hidemenu)
774 gtk_widget_hide (sess->gui->menu);
775 else
776 gtk_widget_show (sess->gui->menu);
779 static void
780 menu_topic_showhide_cb (session *sess)
782 if (prefs.topicbar)
783 gtk_widget_show (sess->gui->topic_bar);
784 else
785 gtk_widget_hide (sess->gui->topic_bar);
788 static void
789 menu_userlist_showhide_cb (session *sess)
791 mg_decide_userlist (sess, TRUE);
794 static void
795 menu_ulbuttons_showhide_cb (session *sess)
797 if (prefs.userlistbuttons)
798 gtk_widget_show (sess->gui->button_box);
799 else
800 gtk_widget_hide (sess->gui->button_box);
803 static void
804 menu_cmbuttons_showhide_cb (session *sess)
806 switch (sess->type)
808 case SESS_CHANNEL:
809 if (prefs.chanmodebuttons)
810 gtk_widget_show (sess->gui->topicbutton_box);
811 else
812 gtk_widget_hide (sess->gui->topicbutton_box);
813 break;
814 default:
815 gtk_widget_hide (sess->gui->topicbutton_box);
819 static void
820 menu_setting_foreach (void (*callback) (session *), int id, guint state)
822 session *sess;
823 GSList *list;
824 int maindone = FALSE; /* do it only once for EVERY tab */
826 list = sess_list;
827 while (list)
829 sess = list->data;
831 if (!sess->gui->is_tab || !maindone)
833 if (sess->gui->is_tab)
834 maindone = TRUE;
835 if (id != -1)
836 GTK_CHECK_MENU_ITEM (sess->gui->menu_item[id])->active = state;
837 if (callback)
838 callback (sess);
841 list = list->next;
845 void
846 menu_bar_toggle (void)
848 prefs.hidemenu = !prefs.hidemenu;
849 menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hidemenu);
852 static void
853 menu_bar_toggle_cb (void)
855 menu_bar_toggle ();
856 if (prefs.hidemenu)
857 fe_message (_("The Menubar is now hidden. You can show it again"
858 " by pressing F9 or right-clicking in a blank part of"
859 " the main text area."), FE_MSG_INFO);
862 static void
863 menu_topicbar_toggle (GtkWidget *wid, gpointer ud)
865 prefs.topicbar = !prefs.topicbar;
866 menu_setting_foreach (menu_topic_showhide_cb, MENU_ID_TOPICBAR,
867 prefs.topicbar);
870 static void
871 menu_userlist_toggle (GtkWidget *wid, gpointer ud)
873 prefs.hideuserlist = !prefs.hideuserlist;
874 menu_setting_foreach (menu_userlist_showhide_cb, MENU_ID_USERLIST,
875 !prefs.hideuserlist);
878 static void
879 menu_ulbuttons_toggle (GtkWidget *wid, gpointer ud)
881 prefs.userlistbuttons = !prefs.userlistbuttons;
882 menu_setting_foreach (menu_ulbuttons_showhide_cb, MENU_ID_ULBUTTONS,
883 prefs.userlistbuttons);
886 static void
887 menu_cmbuttons_toggle (GtkWidget *wid, gpointer ud)
889 prefs.chanmodebuttons = !prefs.chanmodebuttons;
890 menu_setting_foreach (menu_cmbuttons_showhide_cb, MENU_ID_MODEBUTTONS,
891 prefs.chanmodebuttons);
894 void
895 menu_middlemenu (session *sess, GdkEventButton *event)
897 GtkWidget *menu;
898 GtkAccelGroup *accel_group;
900 accel_group = gtk_accel_group_new ();
901 menu = menu_create_main (accel_group, FALSE, sess->server->is_away, !sess->gui->is_tab, NULL);
902 menu_popup (menu, event, accel_group);
905 static void
906 open_url_cb (GtkWidget *item, char *url)
908 char buf[512];
910 /* pass this to /URL so it can handle irc:// */
911 snprintf (buf, sizeof (buf), "URL %s", url);
912 handle_command (current_sess, buf, FALSE);
915 void
916 menu_urlmenu (GdkEventButton *event, char *url)
918 GtkWidget *menu;
919 char *tmp, *chop;
921 if (str_copy)
922 free (str_copy);
923 str_copy = strdup (url);
925 menu = gtk_menu_new ();
926 /* more than 51 chars? Chop it */
927 if (g_utf8_strlen (str_copy, -1) >= 52)
929 tmp = strdup (str_copy);
930 chop = g_utf8_offset_to_pointer (tmp, 48);
931 chop[0] = chop[1] = chop[2] = '.';
932 chop[3] = 0;
933 menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
934 free (tmp);
935 } else
937 menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
939 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
941 /* Two hardcoded entries */
942 if (strncmp (str_copy, "irc://", 6) == 0 ||
943 strncmp (str_copy, "ircs://",7) == 0)
944 menu_quick_item_with_callback (open_url_cb, _("Connect"), menu, str_copy);
945 else
946 menu_quick_item_with_callback (open_url_cb, _("Open Link in Browser"), menu, str_copy);
947 menu_quick_item_with_callback (copy_to_clipboard_cb, _("Copy Selected Link"), menu, str_copy);
948 /* custom ones from urlhandlers.conf */
949 menu_create (menu, urlhandler_list, str_copy, TRUE);
950 menu_add_plugin_items (menu, "\x4$URL", str_copy);
951 menu_popup (menu, event, NULL);
954 static void
955 menu_chan_cycle (GtkWidget * menu, char *chan)
957 char tbuf[256];
959 if (current_sess)
961 snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
962 handle_command (current_sess, tbuf, FALSE);
966 static void
967 menu_chan_part (GtkWidget * menu, char *chan)
969 char tbuf[256];
971 if (current_sess)
973 snprintf (tbuf, sizeof tbuf, "part %s", chan);
974 handle_command (current_sess, tbuf, FALSE);
978 static void
979 menu_chan_join (GtkWidget * menu, char *chan)
981 char tbuf[256];
983 if (current_sess)
985 snprintf (tbuf, sizeof tbuf, "join %s", chan);
986 handle_command (current_sess, tbuf, FALSE);
990 void
991 menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
993 GtkWidget *menu;
994 int is_joined = FALSE;
996 if (find_channel (sess->server, chan))
997 is_joined = TRUE;
999 if (str_copy)
1000 free (str_copy);
1001 str_copy = strdup (chan);
1003 menu = gtk_menu_new ();
1005 menu_quick_item (0, chan, menu, XCMENU_SHADED, str_copy, 0);
1006 menu_quick_item (0, 0, menu, XCMENU_SHADED, str_copy, 0);
1008 if (!is_joined)
1009 menu_quick_item_with_callback (menu_chan_join, _("Join Channel"), menu,
1010 str_copy);
1011 else
1013 menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
1014 str_copy);
1015 menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
1016 str_copy);
1019 menu_addfavoritemenu (sess->server, menu, str_copy);
1021 menu_add_plugin_items (menu, "\x5$CHAN", str_copy);
1022 menu_popup (menu, event, NULL);
1025 static void
1026 menu_delfav_cb (GtkWidget *item, server *serv)
1028 servlist_autojoinedit (serv->network, str_copy, FALSE);
1031 static void
1032 menu_addfav_cb (GtkWidget *item, server *serv)
1034 servlist_autojoinedit (serv->network, str_copy, TRUE);
1037 void
1038 menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel)
1040 if (!serv->network)
1041 return;
1043 if (channel != str_copy)
1045 if (str_copy)
1046 free (str_copy);
1047 str_copy = strdup (channel);
1050 if (joinlist_is_in_list (serv, channel))
1051 mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE, menu, menu_delfav_cb, serv);
1052 else
1053 mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD, menu, menu_addfav_cb, serv);
1056 static void
1057 menu_open_server_list (GtkWidget *wid, gpointer none)
1059 fe_serverlist_open (current_sess);
1062 static void
1063 menu_settings (GtkWidget * wid, gpointer none)
1065 extern void setup_open (void);
1066 setup_open ();
1069 static void
1070 menu_usermenu (void)
1072 editlist_gui_open (NULL, NULL, usermenu_list, _("XChat: User menu"),
1073 "usermenu", "usermenu.conf", 0);
1076 static void
1077 usermenu_create (GtkWidget *menu)
1079 menu_create (menu, usermenu_list, "", FALSE);
1080 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0); /* sep */
1081 menu_quick_item_with_callback (menu_usermenu, _("Edit This Menu..."), menu, 0);
1084 static void
1085 usermenu_destroy (GtkWidget * menu)
1087 GList *items = ((GtkMenuShell *) menu)->children;
1088 GList *next;
1090 while (items)
1092 next = items->next;
1093 gtk_widget_destroy (items->data);
1094 items = next;
1098 void
1099 usermenu_update (void)
1101 int done_main = FALSE;
1102 GSList *list = sess_list;
1103 session *sess;
1104 GtkWidget *menu;
1106 while (list)
1108 sess = list->data;
1109 menu = sess->gui->menu_item[MENU_ID_USERMENU];
1110 if (sess->gui->is_tab)
1112 if (!done_main && menu)
1114 usermenu_destroy (menu);
1115 usermenu_create (menu);
1116 done_main = TRUE;
1118 } else if (menu)
1120 usermenu_destroy (menu);
1121 usermenu_create (menu);
1123 list = list->next;
1127 static void
1128 menu_newserver_window (GtkWidget * wid, gpointer none)
1130 int old = prefs.tabchannels;
1132 prefs.tabchannels = 0;
1133 new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1134 prefs.tabchannels = old;
1137 static void
1138 menu_newchannel_window (GtkWidget * wid, gpointer none)
1140 int old = prefs.tabchannels;
1142 prefs.tabchannels = 0;
1143 new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1144 prefs.tabchannels = old;
1147 static void
1148 menu_newserver_tab (GtkWidget * wid, gpointer none)
1150 int old = prefs.tabchannels;
1151 int oldf = prefs.newtabstofront;
1153 prefs.tabchannels = 1;
1154 /* force focus if setting is "only requested tabs" */
1155 if (prefs.newtabstofront == 2)
1156 prefs.newtabstofront = 1;
1157 new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1158 prefs.tabchannels = old;
1159 prefs.newtabstofront = oldf;
1162 static void
1163 menu_newchannel_tab (GtkWidget * wid, gpointer none)
1165 int old = prefs.tabchannels;
1167 prefs.tabchannels = 1;
1168 new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1169 prefs.tabchannels = old;
1172 static void
1173 menu_rawlog (GtkWidget * wid, gpointer none)
1175 open_rawlog (current_sess->server);
1178 static void
1179 menu_detach (GtkWidget * wid, gpointer none)
1181 mg_detach (current_sess, 0);
1184 static void
1185 menu_close (GtkWidget * wid, gpointer none)
1187 mg_close_sess (current_sess);
1190 static void
1191 menu_quit (GtkWidget * wid, gpointer none)
1193 mg_open_quit_dialog (FALSE);
1196 static void
1197 menu_search ()
1199 search_open (current_sess);
1202 static void
1203 menu_resetmarker (GtkWidget * wid, gpointer none)
1205 gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
1208 static void
1209 menu_flushbuffer (GtkWidget * wid, gpointer none)
1211 fe_text_clear (current_sess, 0);
1214 static void
1215 savebuffer_req_done (session *sess, char *file)
1217 int fh;
1219 if (!file)
1220 return;
1222 fh = open (file, O_TRUNC | O_WRONLY | O_CREAT, 0600);
1223 if (fh != -1)
1225 gtk_xtext_save (GTK_XTEXT (sess->gui->xtext), fh);
1226 close (fh);
1230 static void
1231 menu_savebuffer (GtkWidget * wid, gpointer none)
1233 gtkutil_file_req (_("Select an output filename"), savebuffer_req_done,
1234 current_sess, NULL, FRF_WRITE);
1237 static void
1238 menu_disconnect (GtkWidget * wid, gpointer none)
1240 handle_command (current_sess, "DISCON", FALSE);
1243 static void
1244 menu_reconnect (GtkWidget * wid, gpointer none)
1246 if (current_sess->server->hostname[0])
1247 handle_command (current_sess, "RECONNECT", FALSE);
1248 else
1249 fe_serverlist_open (current_sess);
1252 static void
1253 menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
1255 switch (response)
1257 case GTK_RESPONSE_ACCEPT:
1258 menu_chan_join (NULL, entry->text);
1259 break;
1261 case GTK_RESPONSE_HELP:
1262 chanlist_opengui (current_sess->server, TRUE);
1263 break;
1266 gtk_widget_destroy (dialog);
1269 static void
1270 menu_join_entry_cb (GtkWidget *entry, GtkDialog *dialog)
1272 gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
1275 static void
1276 menu_join (GtkWidget * wid, gpointer none)
1278 GtkWidget *hbox, *dialog, *entry, *label;
1280 dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
1281 GTK_WINDOW (parent_window), 0,
1282 _("Retrieve channel list..."), GTK_RESPONSE_HELP,
1283 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1284 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1285 NULL);
1286 gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
1287 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1288 hbox = gtk_hbox_new (TRUE, 0);
1290 entry = gtk_entry_new ();
1291 GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
1292 gtk_entry_set_text (GTK_ENTRY (entry), "#");
1293 g_signal_connect (G_OBJECT (entry), "activate",
1294 G_CALLBACK (menu_join_entry_cb), dialog);
1295 gtk_box_pack_end (GTK_BOX (hbox), entry, 0, 0, 0);
1297 label = gtk_label_new (_("Enter Channel to Join:"));
1298 gtk_box_pack_end (GTK_BOX (hbox), label, 0, 0, 0);
1300 g_signal_connect (G_OBJECT (dialog), "response",
1301 G_CALLBACK (menu_join_cb), entry);
1303 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1305 gtk_widget_show_all (dialog);
1307 gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
1308 gtk_editable_set_position (GTK_EDITABLE (entry), 1);
1311 static void
1312 menu_away (GtkCheckMenuItem *item, gpointer none)
1314 handle_command (current_sess, item->active ? "away" : "back", FALSE);
1317 static void
1318 menu_chanlist (GtkWidget * wid, gpointer none)
1320 chanlist_opengui (current_sess->server, FALSE);
1323 static void
1324 menu_banlist (GtkWidget * wid, gpointer none)
1326 banlist_opengui (current_sess);
1329 #ifdef USE_PLUGIN
1331 static void
1332 menu_loadplugin (void)
1334 plugingui_load ();
1337 static void
1338 menu_pluginlist (void)
1340 plugingui_open ();
1343 #else
1345 #define menu_pluginlist 0
1346 #define menu_loadplugin 0
1348 #endif
1350 #define usercommands_help _("User Commands - Special codes:\n\n"\
1351 "%c = current channel\n"\
1352 "%e = current network name\n"\
1353 "%m = machine info\n"\
1354 "%n = your nick\n"\
1355 "%t = time/date\n"\
1356 "%v = xchat version\n"\
1357 "%2 = word 2\n"\
1358 "%3 = word 3\n"\
1359 "&2 = word 2 to the end of line\n"\
1360 "&3 = word 3 to the end of line\n\n"\
1361 "eg:\n"\
1362 "/cmd john hello\n\n"\
1363 "%2 would be \042john\042\n"\
1364 "&2 would be \042john hello\042.")
1366 #define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1367 "%a = all selected nicks\n"\
1368 "%c = current channel\n"\
1369 "%e = current network name\n"\
1370 "%h = selected nick's hostname\n"\
1371 "%m = machine info\n"\
1372 "%n = your nick\n"\
1373 "%s = selected nick\n"\
1374 "%t = time/date\n")
1376 #define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1377 "%a = all selected nicks\n"\
1378 "%c = current channel\n"\
1379 "%e = current network name\n"\
1380 "%h = selected nick's hostname\n"\
1381 "%m = machine info\n"\
1382 "%n = your nick\n"\
1383 "%s = selected nick\n"\
1384 "%t = time/date\n")
1386 #define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1387 "%d = data (the whole ctcp)\n"\
1388 "%e = current network name\n"\
1389 "%m = machine info\n"\
1390 "%s = nick who sent the ctcp\n"\
1391 "%t = time/date\n"\
1392 "%2 = word 2\n"\
1393 "%3 = word 3\n"\
1394 "&2 = word 2 to the end of line\n"\
1395 "&3 = word 3 to the end of line\n\n")
1397 #define url_help _("URL Handlers - Special codes:\n\n"\
1398 "%s = the URL string\n\n"\
1399 "Putting a ! infront of the command\n"\
1400 "indicates it should be sent to a\n"\
1401 "shell instead of XChat")
1403 static void
1404 menu_usercommands (void)
1406 editlist_gui_open (NULL, NULL, command_list, _("XChat: User Defined Commands"),
1407 "commands", "commands.conf", usercommands_help);
1410 static void
1411 menu_ulpopup (void)
1413 editlist_gui_open (NULL, NULL, popup_list, _("XChat: Userlist Popup menu"), "popup",
1414 "popup.conf", ulbutton_help);
1417 static void
1418 menu_rpopup (void)
1420 editlist_gui_open (_("Text"), _("Replace with"), replace_list, _("XChat: Replace"), "replace",
1421 "replace.conf", 0);
1424 static void
1425 menu_urlhandlers (void)
1427 editlist_gui_open (NULL, NULL, urlhandler_list, _("XChat: URL Handlers"), "urlhandlers",
1428 "urlhandlers.conf", url_help);
1431 static void
1432 menu_evtpopup (void)
1434 pevent_dialog_show ();
1437 static void
1438 menu_keypopup (void)
1440 key_dialog_show ();
1443 static void
1444 menu_ulbuttons (void)
1446 editlist_gui_open (NULL, NULL, button_list, _("XChat: Userlist buttons"), "buttons",
1447 "buttons.conf", ulbutton_help);
1450 static void
1451 menu_dlgbuttons (void)
1453 editlist_gui_open (NULL, NULL, dlgbutton_list, _("XChat: Dialog buttons"), "dlgbuttons",
1454 "dlgbuttons.conf", dlgbutton_help);
1457 static void
1458 menu_ctcpguiopen (void)
1460 editlist_gui_open (NULL, NULL, ctcp_list, _("XChat: CTCP Replies"), "ctcpreply",
1461 "ctcpreply.conf", ctcp_help);
1464 static void
1465 menu_docs (GtkWidget *wid, gpointer none)
1467 fe_open_url ("http://xchat.org/docs/");
1470 /*static void
1471 menu_webpage (GtkWidget *wid, gpointer none)
1473 fe_open_url ("http://xchat.org");
1476 static void
1477 menu_dcc_win (GtkWidget *wid, gpointer none)
1479 fe_dcc_open_recv_win (FALSE);
1480 fe_dcc_open_send_win (FALSE);
1483 static void
1484 menu_dcc_chat_win (GtkWidget *wid, gpointer none)
1486 fe_dcc_open_chat_win (FALSE);
1489 void
1490 menu_change_layout (void)
1492 if (prefs.tab_layout == 0)
1494 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 1);
1495 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 0);
1496 mg_change_layout (0);
1497 } else
1499 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 0);
1500 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 1);
1501 mg_change_layout (2);
1505 static void
1506 menu_layout_cb (GtkWidget *item, gpointer none)
1508 prefs.tab_layout = 2;
1509 if (GTK_CHECK_MENU_ITEM (item)->active)
1510 prefs.tab_layout = 0;
1512 menu_change_layout ();
1515 static void
1516 menu_apply_metres_cb (session *sess)
1518 mg_update_meters (sess->gui);
1521 static void
1522 menu_metres_off (GtkWidget *item, gpointer none)
1524 if (GTK_CHECK_MENU_ITEM (item)->active)
1526 prefs.lagometer = 0;
1527 prefs.throttlemeter = 0;
1528 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1532 static void
1533 menu_metres_text (GtkWidget *item, gpointer none)
1535 if (GTK_CHECK_MENU_ITEM (item)->active)
1537 prefs.lagometer = 2;
1538 prefs.throttlemeter = 2;
1539 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1543 static void
1544 menu_metres_graph (GtkWidget *item, gpointer none)
1546 if (GTK_CHECK_MENU_ITEM (item)->active)
1548 prefs.lagometer = 1;
1549 prefs.throttlemeter = 1;
1550 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1554 static void
1555 menu_metres_both (GtkWidget *item, gpointer none)
1557 if (GTK_CHECK_MENU_ITEM (item)->active)
1559 prefs.lagometer = 3;
1560 prefs.throttlemeter = 3;
1561 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1565 static struct mymenu mymenu[] = {
1566 {N_("_XChat"), 0, 0, M_NEWMENU, 0, 0, 1},
1567 {N_("Network Li_st..."), menu_open_server_list, (char *)&pix_book, M_MENUPIX, 0, 0, 1, GDK_s},
1568 {0, 0, 0, M_SEP, 0, 0, 0},
1570 {N_("_New"), 0, GTK_STOCK_NEW, M_MENUSUB, 0, 0, 1},
1571 {N_("Server Tab..."), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_t},
1572 {N_("Channel Tab..."), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
1573 {N_("Server Window..."), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1},
1574 {N_("Channel Window..."), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
1575 {0, 0, 0, M_END, 0, 0, 0},
1576 {0, 0, 0, M_SEP, 0, 0, 0},
1578 #ifdef USE_PLUGIN
1579 {N_("_Load Plugin or Script..."), menu_loadplugin, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 1},
1580 #else
1581 {N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 0},
1582 #endif
1583 {0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
1584 #define DETACH_OFFSET (12)
1585 {0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_I}, /* 12 */
1586 #define CLOSE_OFFSET (13)
1587 {0, menu_close, GTK_STOCK_CLOSE, M_MENUSTOCK, 0, 0, 1, GDK_w},
1588 {0, 0, 0, M_SEP, 0, 0, 0},
1589 {N_("_Quit"), menu_quit, GTK_STOCK_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_q}, /* 15 */
1591 {N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
1592 #define MENUBAR_OFFSET (17)
1593 {N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_F9},
1594 {N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
1595 {N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_F7},
1596 {N_("U_serlist Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
1597 {N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
1598 {0, 0, 0, M_SEP, 0, 0, 0},
1599 {N_("_Channel Switcher"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 23 */
1600 #define TABS_OFFSET (24)
1601 {N_("_Tabs"), menu_layout_cb, 0, M_MENURADIO, MENU_ID_LAYOUT_TABS, 0, 1},
1602 {N_("T_ree"), 0, 0, M_MENURADIO, MENU_ID_LAYOUT_TREE, 0, 1},
1603 {0, 0, 0, M_END, 0, 0, 0},
1604 {N_("_Network Meters"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 27 */
1605 #define METRE_OFFSET (28)
1606 {N_("Off"), menu_metres_off, 0, M_MENURADIO, 0, 0, 1},
1607 {N_("Graph"), menu_metres_graph, 0, M_MENURADIO, 0, 0, 1},
1608 {N_("Text"), menu_metres_text, 0, M_MENURADIO, 0, 0, 1},
1609 {N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
1610 {0, 0, 0, M_END, 0, 0, 0}, /* 32 */
1612 {N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
1613 {N_("_Disconnect"), menu_disconnect, GTK_STOCK_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
1614 {N_("_Reconnect"), menu_reconnect, GTK_STOCK_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
1615 {N_("Join a Channel..."), menu_join, GTK_STOCK_JUMP_TO, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
1616 {N_("List of Channels..."), menu_chanlist, GTK_STOCK_INDEX, M_MENUITEM, 0, 0, 1},
1617 {0, 0, 0, M_SEP, 0, 0, 0},
1618 #define AWAY_OFFSET (39)
1619 {N_("Marked Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_a},
1621 {N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
1623 {N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
1624 {N_("_Preferences"), menu_settings, GTK_STOCK_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
1626 {N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
1627 {N_("Auto Replace..."), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
1628 {N_("CTCP Replies..."), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
1629 {N_("Dialog Buttons..."), menu_dlgbuttons, 0, M_MENUITEM, 0, 0, 1},
1630 {N_("Keyboard Shortcuts..."), menu_keypopup, 0, M_MENUITEM, 0, 0, 1},
1631 {N_("Text Events..."), menu_evtpopup, 0, M_MENUITEM, 0, 0, 1},
1632 {N_("URL Handlers..."), menu_urlhandlers, 0, M_MENUITEM, 0, 0, 1},
1633 {N_("User Commands..."), menu_usercommands, 0, M_MENUITEM, 0, 0, 1},
1634 {N_("Userlist Buttons..."), menu_ulbuttons, 0, M_MENUITEM, 0, 0, 1},
1635 {N_("Userlist Popup..."), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1},
1636 {0, 0, 0, M_END, 0, 0, 0}, /* 53 */
1638 {N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
1639 {N_("Ban List..."), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
1640 {N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
1641 {N_("Direct Chat..."), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
1642 {N_("File Transfers..."), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
1643 {N_("Friends List..."), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
1644 {N_("Ignore List..."), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
1645 {N_("Plugins and Scripts..."), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
1646 {N_("Raw Log..."), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 62 */
1647 {N_("URL Grabber..."), url_opengui, 0, M_MENUITEM, 0, 0, 1},
1648 {0, 0, 0, M_SEP, 0, 0, 0},
1649 {N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
1650 {N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
1651 #define SEARCH_OFFSET 67
1652 {N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
1653 {N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
1655 {N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 69 */
1656 {N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
1657 #if 0
1658 {N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},
1659 #endif
1660 {N_("_About"), menu_about, GTK_STOCK_ABOUT, M_MENUSTOCK, 0, 0, 1},
1662 {0, 0, 0, M_END, 0, 0, 0},
1665 GtkWidget *
1666 create_icon_menu (char *labeltext, void *stock_name, int is_stock)
1668 GtkWidget *item, *img;
1670 if (is_stock)
1671 img = gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
1672 else
1673 img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
1674 item = gtk_image_menu_item_new_with_mnemonic (labeltext);
1675 gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
1676 gtk_widget_show (img);
1678 return item;
1681 /* Override the default GTK2.4 handler, which would make menu
1682 bindings not work when the menu-bar is hidden. */
1683 static gboolean
1684 menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
1686 /* GTK2.2 behaviour */
1687 #if GTK_CHECK_VERSION(2,20,0)
1688 return gtk_widget_is_sensitive (widget);
1689 #else
1690 return GTK_WIDGET_IS_SENSITIVE (widget);
1691 #endif
1694 /* === STUFF FOR /MENU === */
1696 static GtkMenuItem *
1697 menu_find_item (GtkWidget *menu, char *name)
1699 GList *items = ((GtkMenuShell *) menu)->children;
1700 GtkMenuItem *item;
1701 GtkWidget *child;
1702 const char *labeltext;
1704 while (items)
1706 item = items->data;
1707 child = GTK_BIN (item)->child;
1708 if (child) /* separators arn't labels, skip them */
1710 labeltext = g_object_get_data (G_OBJECT (item), "name");
1711 if (!labeltext)
1712 labeltext = gtk_label_get_text (GTK_LABEL (child));
1713 if (!menu_streq (labeltext, name, 1))
1714 return item;
1715 } else if (name == NULL)
1717 return item;
1719 items = items->next;
1722 return NULL;
1725 static GtkWidget *
1726 menu_find_path (GtkWidget *menu, char *path)
1728 GtkMenuItem *item;
1729 char *s;
1730 char name[128];
1731 int len;
1733 /* grab the next part of the path */
1734 s = strchr (path, '/');
1735 len = s - path;
1736 if (!s)
1737 len = strlen (path);
1738 len = MIN (len, sizeof (name) - 1);
1739 memcpy (name, path, len);
1740 name[len] = 0;
1742 item = menu_find_item (menu, name);
1743 if (!item)
1744 return NULL;
1746 menu = gtk_menu_item_get_submenu (item);
1747 if (!menu)
1748 return NULL;
1750 path += len;
1751 if (*path == 0)
1752 return menu;
1754 return menu_find_path (menu, path + 1);
1757 static GtkWidget *
1758 menu_find (GtkWidget *menu, char *path, char *label)
1760 GtkWidget *item = NULL;
1762 if (path[0] != 0)
1763 menu = menu_find_path (menu, path);
1764 if (menu)
1765 item = (GtkWidget *)menu_find_item (menu, label);
1766 return item;
1769 static void
1770 menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, char *))
1772 GSList *list = sess_list;
1773 int tabdone = FALSE;
1774 session *sess;
1776 if (!me->is_main)
1777 return; /* not main menu */
1779 while (list)
1781 sess = list->data;
1782 /* do it only once for tab sessions, since they share a GUI */
1783 if (!sess->gui->is_tab || !tabdone)
1785 callback (sess->gui->menu, me, NULL);
1786 if (sess->gui->is_tab)
1787 tabdone = TRUE;
1789 list = list->next;
1793 static void
1794 menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
1796 GtkWidget *item;
1798 item = menu_find (menu, me->path, me->label);
1799 if (item)
1801 gtk_widget_set_sensitive (item, me->enable);
1802 /* must do it without triggering the callback */
1803 if (GTK_IS_CHECK_MENU_ITEM (item))
1804 GTK_CHECK_MENU_ITEM (item)->active = me->state;
1808 /* radio state changed via mouse click */
1809 static void
1810 menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
1812 me->state = 0;
1813 if (item->active)
1814 me->state = 1;
1816 /* update the state, incase this was changed via right-click. */
1817 /* This will update all other windows and menu bars */
1818 menu_foreach_gui (me, menu_update_cb);
1820 if (me->state && me->cmd)
1821 handle_command (current_sess, me->cmd, FALSE);
1824 /* toggle state changed via mouse click */
1825 static void
1826 menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
1828 me->state = 0;
1829 if (item->active)
1830 me->state = 1;
1832 /* update the state, incase this was changed via right-click. */
1833 /* This will update all other windows and menu bars */
1834 menu_foreach_gui (me, menu_update_cb);
1836 if (me->state)
1837 handle_command (current_sess, me->cmd, FALSE);
1838 else
1839 handle_command (current_sess, me->ucmd, FALSE);
1842 static GtkWidget *
1843 menu_radio_item (char *label, GtkWidget *menu, void *callback, void *userdata,
1844 int state, char *groupname)
1846 GtkWidget *item;
1847 GtkMenuItem *parent;
1848 GSList *grouplist = NULL;
1850 parent = menu_find_item (menu, groupname);
1851 if (parent)
1852 grouplist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *)parent);
1854 item = gtk_radio_menu_item_new_with_label (grouplist, label);
1855 gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
1856 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1857 g_signal_connect (G_OBJECT (item), "activate",
1858 G_CALLBACK (callback), userdata);
1859 gtk_widget_show (item);
1861 return item;
1864 static void
1865 menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
1867 if (pos == 0xffff) /* outbound.c uses this default */
1868 return;
1870 if (pos < 0) /* position offset from end/bottom */
1871 gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
1872 else
1873 gtk_menu_reorder_child (menu, item, pos);
1876 static GtkWidget *
1877 menu_add_radio (GtkWidget *menu, menu_entry *me)
1879 GtkWidget *item = NULL;
1880 char *path = me->path + me->root_offset;
1882 if (path[0] != 0)
1883 menu = menu_find_path (menu, path);
1884 if (menu)
1886 item = menu_radio_item (me->label, menu, menu_radio_cb, me, me->state, me->group);
1887 menu_reorder (GTK_MENU (menu), item, me->pos);
1889 return item;
1892 static GtkWidget *
1893 menu_add_toggle (GtkWidget *menu, menu_entry *me)
1895 GtkWidget *item = NULL;
1896 char *path = me->path + me->root_offset;
1898 if (path[0] != 0)
1899 menu = menu_find_path (menu, path);
1900 if (menu)
1902 item = menu_toggle_item (me->label, menu, menu_toggle_cb, me, me->state);
1903 menu_reorder (GTK_MENU (menu), item, me->pos);
1905 return item;
1908 static GtkWidget *
1909 menu_add_item (GtkWidget *menu, menu_entry *me, char *target)
1911 GtkWidget *item = NULL;
1912 char *path = me->path + me->root_offset;
1914 if (path[0] != 0)
1915 menu = menu_find_path (menu, path);
1916 if (menu)
1918 item = menu_quick_item (me->cmd, me->label, menu, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, target, me->icon);
1919 menu_reorder (GTK_MENU (menu), item, me->pos);
1921 return item;
1924 static GtkWidget *
1925 menu_add_sub (GtkWidget *menu, menu_entry *me)
1927 GtkWidget *item = NULL;
1928 char *path = me->path + me->root_offset;
1929 int pos;
1931 if (path[0] != 0)
1932 menu = menu_find_path (menu, path);
1933 if (menu)
1935 pos = me->pos;
1936 if (pos < 0) /* position offset from end/bottom */
1937 pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
1938 menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
1940 return item;
1943 static void
1944 menu_del_cb (GtkWidget *menu, menu_entry *me, char *target)
1946 GtkWidget *item = menu_find (menu, me->path + me->root_offset, me->label);
1947 if (item)
1948 gtk_widget_destroy (item);
1951 static void
1952 menu_add_cb (GtkWidget *menu, menu_entry *me, char *target)
1954 GtkWidget *item;
1955 GtkAccelGroup *accel_group;
1957 if (me->group) /* have a group name? Must be a radio item */
1958 item = menu_add_radio (menu, me);
1959 else if (me->ucmd) /* have unselect-cmd? Must be a toggle item */
1960 item = menu_add_toggle (menu, me);
1961 else if (me->cmd || !me->label) /* label=NULL for separators */
1962 item = menu_add_item (menu, me, target);
1963 else
1964 item = menu_add_sub (menu, me);
1966 if (item)
1968 gtk_widget_set_sensitive (item, me->enable);
1969 if (me->key)
1971 accel_group = g_object_get_data (G_OBJECT (menu), "accel");
1972 if (accel_group) /* popup menus don't have them */
1973 gtk_widget_add_accelerator (item, "activate", accel_group, me->key,
1974 me->modifier, GTK_ACCEL_VISIBLE);
1979 char *
1980 fe_menu_add (menu_entry *me)
1982 char *text;
1984 menu_foreach_gui (me, menu_add_cb);
1986 if (!me->markup)
1987 return NULL;
1989 if (!pango_parse_markup (me->label, -1, 0, NULL, &text, NULL, NULL))
1990 return NULL;
1992 /* return the label with markup stripped */
1993 return text;
1996 void
1997 fe_menu_del (menu_entry *me)
1999 menu_foreach_gui (me, menu_del_cb);
2002 void
2003 fe_menu_update (menu_entry *me)
2005 menu_foreach_gui (me, menu_update_cb);
2008 /* used to add custom menus to the right-click menu */
2010 static void
2011 menu_add_plugin_mainmenu_items (GtkWidget *menu)
2013 GSList *list;
2014 menu_entry *me;
2016 list = menu_list; /* outbound.c */
2017 while (list)
2019 me = list->data;
2020 if (me->is_main)
2021 menu_add_cb (menu, me, NULL);
2022 list = list->next;
2026 void
2027 menu_add_plugin_items (GtkWidget *menu, char *root, char *target)
2029 GSList *list;
2030 menu_entry *me;
2032 list = menu_list; /* outbound.c */
2033 while (list)
2035 me = list->data;
2036 if (!me->is_main && !strncmp (me->path, root + 1, root[0]))
2037 menu_add_cb (menu, me, target);
2038 list = list->next;
2042 /* === END STUFF FOR /MENU === */
2044 GtkWidget *
2045 menu_create_main (void *accel_group, int bar, int away, int toplevel,
2046 GtkWidget **menu_widgets)
2048 int i = 0;
2049 GtkWidget *item;
2050 GtkWidget *menu = 0;
2051 GtkWidget *menu_item = 0;
2052 GtkWidget *menu_bar;
2053 GtkWidget *usermenu = 0;
2054 GtkWidget *submenu = 0;
2055 int close_mask = GDK_CONTROL_MASK;
2056 int away_mask = GDK_MOD1_MASK;
2057 char *key_theme = NULL;
2058 GtkSettings *settings;
2059 GSList *group = NULL;
2061 if (bar)
2062 menu_bar = gtk_menu_bar_new ();
2063 else
2064 menu_bar = gtk_menu_new ();
2066 /* /MENU needs to know this later */
2067 g_object_set_data (G_OBJECT (menu_bar), "accel", accel_group);
2069 g_signal_connect (G_OBJECT (menu_bar), "can-activate-accel",
2070 G_CALLBACK (menu_canacaccel), 0);
2072 /* set the initial state of toggles */
2073 mymenu[MENUBAR_OFFSET].state = !prefs.hidemenu;
2074 mymenu[MENUBAR_OFFSET+1].state = prefs.topicbar;
2075 mymenu[MENUBAR_OFFSET+2].state = !prefs.hideuserlist;
2076 mymenu[MENUBAR_OFFSET+3].state = prefs.userlistbuttons;
2077 mymenu[MENUBAR_OFFSET+4].state = prefs.chanmodebuttons;
2079 mymenu[AWAY_OFFSET].state = away;
2081 switch (prefs.tab_layout)
2083 case 0:
2084 mymenu[TABS_OFFSET].state = 1;
2085 mymenu[TABS_OFFSET+1].state = 0;
2086 break;
2087 default:
2088 mymenu[TABS_OFFSET].state = 0;
2089 mymenu[TABS_OFFSET+1].state = 1;
2092 mymenu[METRE_OFFSET].state = 0;
2093 mymenu[METRE_OFFSET+1].state = 0;
2094 mymenu[METRE_OFFSET+2].state = 0;
2095 mymenu[METRE_OFFSET+3].state = 0;
2096 switch (prefs.lagometer)
2098 case 0:
2099 mymenu[METRE_OFFSET].state = 1;
2100 break;
2101 case 1:
2102 mymenu[METRE_OFFSET+1].state = 1;
2103 break;
2104 case 2:
2105 mymenu[METRE_OFFSET+2].state = 1;
2106 break;
2107 default:
2108 mymenu[METRE_OFFSET+3].state = 1;
2111 /* change Close binding to ctrl-shift-w when using emacs keys */
2112 settings = gtk_widget_get_settings (menu_bar);
2113 if (settings)
2115 g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
2116 if (key_theme)
2118 if (!strcasecmp (key_theme, "Emacs"))
2120 close_mask = GDK_SHIFT_MASK | GDK_CONTROL_MASK;
2121 mymenu[SEARCH_OFFSET].key = 0;
2123 g_free (key_theme);
2127 /* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2129 char *help = _("_Help");
2130 char *under = strchr (help, '_');
2131 if (under && (under[1] == 'a' || under[1] == 'A'))
2132 away_mask = GDK_MOD1_MASK | GDK_CONTROL_MASK;
2135 if (!toplevel)
2137 mymenu[DETACH_OFFSET].text = N_("_Detach");
2138 mymenu[CLOSE_OFFSET].text = N_("_Close");
2140 else
2142 mymenu[DETACH_OFFSET].text = N_("_Attach");
2143 mymenu[CLOSE_OFFSET].text = N_("_Close");
2146 while (1)
2148 item = NULL;
2149 if (mymenu[i].id == MENU_ID_USERMENU && !prefs.gui_usermenu)
2151 i++;
2152 continue;
2155 switch (mymenu[i].type)
2157 case M_NEWMENU:
2158 if (menu)
2159 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2160 item = menu = gtk_menu_new ();
2161 if (mymenu[i].id == MENU_ID_USERMENU)
2162 usermenu = menu;
2163 menu_item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2164 /* record the English name for /menu */
2165 g_object_set_data (G_OBJECT (menu_item), "name", mymenu[i].text);
2166 gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
2167 gtk_widget_show (menu_item);
2168 break;
2170 case M_MENUPIX:
2171 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, FALSE);
2172 goto normalitem;
2174 case M_MENUSTOCK:
2175 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2176 goto normalitem;
2178 case M_MENUITEM:
2179 item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2180 normalitem:
2181 if (mymenu[i].key != 0)
2182 gtk_widget_add_accelerator (item, "activate", accel_group,
2183 mymenu[i].key,
2184 mymenu[i].key == GDK_F1 ? 0 :
2185 mymenu[i].key == GDK_w ? close_mask :
2186 GDK_CONTROL_MASK,
2187 GTK_ACCEL_VISIBLE);
2188 if (mymenu[i].callback)
2189 g_signal_connect (G_OBJECT (item), "activate",
2190 G_CALLBACK (mymenu[i].callback), 0);
2191 if (submenu)
2192 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2193 else
2194 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2195 gtk_widget_show (item);
2196 break;
2198 case M_MENUTOG:
2199 item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
2200 togitem:
2201 /* must avoid callback for Radio buttons */
2202 GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
2203 /*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2204 mymenu[i].state);*/
2205 if (mymenu[i].key != 0)
2206 gtk_widget_add_accelerator (item, "activate", accel_group,
2207 mymenu[i].key, mymenu[i].id == MENU_ID_AWAY ?
2208 away_mask : GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
2209 if (mymenu[i].callback)
2210 g_signal_connect (G_OBJECT (item), "toggled",
2211 G_CALLBACK (mymenu[i].callback), 0);
2212 if (submenu)
2213 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2214 else
2215 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2216 gtk_widget_show (item);
2217 gtk_widget_set_sensitive (item, mymenu[i].sensitive);
2218 break;
2220 case M_MENURADIO:
2221 item = gtk_radio_menu_item_new_with_mnemonic (group, _(mymenu[i].text));
2222 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
2223 goto togitem;
2225 case M_SEP:
2226 item = gtk_menu_item_new ();
2227 gtk_widget_set_sensitive (item, FALSE);
2228 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2229 gtk_widget_show (item);
2230 break;
2232 case M_MENUSUB:
2233 group = NULL;
2234 submenu = gtk_menu_new ();
2235 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2236 /* record the English name for /menu */
2237 g_object_set_data (G_OBJECT (item), "name", mymenu[i].text);
2238 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
2239 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2240 gtk_widget_show (item);
2241 break;
2243 /*case M_END:*/ default:
2244 if (!submenu)
2246 if (menu)
2248 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2249 menu_add_plugin_mainmenu_items (menu_bar);
2251 if (usermenu)
2252 usermenu_create (usermenu);
2253 return (menu_bar);
2255 submenu = NULL;
2258 /* record this GtkWidget * so it's state might be changed later */
2259 if (mymenu[i].id != 0 && menu_widgets)
2260 /* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2261 menu_widgets[mymenu[i].id] = item;
2263 i++;