remove all remaining WIN32 code
[rofl0r-ixchat.git] / src / fe-gtk / menu.c
blobc4ba3988a70edf5e8e456b3d4f2e5d121cd2e6e3
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"
71 static GSList *submenu_list;
73 enum
75 M_MENUITEM,
76 M_NEWMENU,
77 M_END,
78 M_SEP,
79 M_MENUTOG,
80 M_MENURADIO,
81 M_MENUSTOCK,
82 M_MENUPIX,
83 M_MENUSUB
86 struct mymenu
88 char *text;
89 void *callback;
90 char *image;
91 unsigned char type; /* M_XXX */
92 unsigned char id; /* MENU_ID_XXX (menu.h) */
93 unsigned char state; /* ticked or not? */
94 unsigned char sensitive; /* shaded out? */
95 guint key; /* GDK_x */
98 #define XCMENU_DOLIST 1
99 #define XCMENU_SHADED 1
100 #define XCMENU_MARKUP 2
101 #define XCMENU_MNEMONIC 4
103 /* execute a userlistbutton/popupmenu command */
105 static void
106 nick_command (session * sess, char *cmd)
108 if (*cmd == '!')
109 xchat_exec (cmd + 1);
110 else
111 handle_command (sess, cmd, TRUE);
114 /* fill in the %a %s %n etc and execute the command */
116 void
117 nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
119 char *buf;
120 char *host = _("Host unknown");
121 struct User *user;
122 int len;
124 /* if (sess->type == SESS_DIALOG)
126 buf = (char *)(GTK_ENTRY (sess->gui->topic_entry)->text);
127 buf = strrchr (buf, '@');
128 if (buf)
129 host = buf + 1;
130 } else*/
132 user = userlist_find (sess, nick);
133 if (user && user->hostname)
134 host = strchr (user->hostname, '@') + 1;
137 /* this can't overflow, since popup->cmd is only 256 */
138 len = strlen (cmd) + strlen (nick) + strlen (allnick) + 512;
139 buf = malloc (len);
141 auto_insert (buf, len, cmd, 0, 0, allnick, sess->channel, "",
142 server_get_network (sess->server, TRUE), host,
143 sess->server->nick, nick);
145 nick_command (sess, buf);
147 free (buf);
150 /* userlist button has been clicked */
152 void
153 userlist_button_cb (GtkWidget * button, char *cmd)
155 int i, num_sel, using_allnicks = FALSE;
156 char **nicks, *allnicks;
157 char *nick = NULL;
158 session *sess;
160 sess = current_sess;
162 if (strstr (cmd, "%a"))
163 using_allnicks = TRUE;
165 if (sess->type == SESS_DIALOG)
167 /* fake a selection */
168 nicks = malloc (sizeof (char *) * 2);
169 nicks[0] = g_strdup (sess->channel);
170 nicks[1] = NULL;
171 num_sel = 1;
172 } else
174 /* find number of selected rows */
175 nicks = userlist_selection_list (sess->gui->user_tree, &num_sel);
176 if (num_sel < 1)
178 nick_command_parse (sess, cmd, "", "");
179 return;
183 /* create "allnicks" string */
184 allnicks = malloc (((NICKLEN + 1) * num_sel) + 1);
185 *allnicks = 0;
187 i = 0;
188 while (nicks[i])
190 if (i > 0)
191 strcat (allnicks, " ");
192 strcat (allnicks, nicks[i]);
194 if (!nick)
195 nick = nicks[0];
197 /* if not using "%a", execute the command once for each nickname */
198 if (!using_allnicks)
199 nick_command_parse (sess, cmd, nicks[i], "");
201 i++;
204 if (using_allnicks)
206 if (!nick)
207 nick = "";
208 nick_command_parse (sess, cmd, nick, allnicks);
211 while (num_sel)
213 num_sel--;
214 g_free (nicks[num_sel]);
217 free (nicks);
218 free (allnicks);
221 /* a popup-menu-item has been selected */
223 static void
224 popup_menu_cb (GtkWidget * item, char *cmd)
226 char *nick;
228 /* the userdata is set in menu_quick_item() */
229 nick = g_object_get_data (G_OBJECT (item), "u");
231 if (!nick) /* userlist popup menu */
233 /* treat it just like a userlist button */
234 userlist_button_cb (NULL, cmd);
235 return;
238 if (!current_sess) /* for url grabber window */
239 nick_command_parse (sess_list->data, cmd, nick, nick);
240 else
241 nick_command_parse (current_sess, cmd, nick, nick);
244 GtkWidget *
245 menu_toggle_item (char *label, GtkWidget *menu, void *callback, void *userdata,
246 int state)
248 GtkWidget *item;
250 item = gtk_check_menu_item_new_with_mnemonic (label);
251 gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
252 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
253 g_signal_connect (G_OBJECT (item), "activate",
254 G_CALLBACK (callback), userdata);
255 gtk_widget_show (item);
257 return item;
260 GtkWidget *
261 menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
262 gpointer userdata, char *icon)
264 GtkWidget *img, *item;
265 char *path;
267 if (!label)
268 item = gtk_menu_item_new ();
269 else
271 if (icon)
273 /*if (flags & XCMENU_MARKUP)
274 item = gtk_image_menu_item_new_with_markup (label);
275 else*/
276 item = gtk_image_menu_item_new_with_mnemonic (label);
277 img = NULL;
278 if (access (icon, R_OK) == 0) /* try fullpath */
279 img = gtk_image_new_from_file (icon);
280 else
282 /* try relative to ~/.xchat2 */
283 path = g_strdup_printf ("%s/%s", get_xdir_fs (), icon);
284 if (access (path, R_OK) == 0)
285 img = gtk_image_new_from_file (path);
286 else
287 img = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
288 g_free (path);
291 if (img)
292 gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
294 else
296 if (flags & XCMENU_MARKUP)
298 item = gtk_menu_item_new_with_label ("");
299 if (flags & XCMENU_MNEMONIC)
300 gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item)->child), label);
301 else
302 gtk_label_set_markup (GTK_LABEL (GTK_BIN (item)->child), label);
303 } else
305 if (flags & XCMENU_MNEMONIC)
306 item = gtk_menu_item_new_with_mnemonic (label);
307 else
308 item = gtk_menu_item_new_with_label (label);
312 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
313 g_object_set_data (G_OBJECT (item), "u", userdata);
314 if (cmd)
315 g_signal_connect (G_OBJECT (item), "activate",
316 G_CALLBACK (popup_menu_cb), cmd);
317 if (flags & XCMENU_SHADED)
318 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
319 gtk_widget_show_all (item);
321 return item;
324 static void
325 menu_quick_item_with_callback (void *callback, char *label, GtkWidget * menu,
326 void *arg)
328 GtkWidget *item;
330 item = gtk_menu_item_new_with_label (label);
331 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
332 g_signal_connect (G_OBJECT (item), "activate",
333 G_CALLBACK (callback), arg);
334 gtk_widget_show (item);
337 GtkWidget *
338 menu_quick_sub (char *name, GtkWidget *menu, GtkWidget **sub_item_ret, int flags, int pos)
340 GtkWidget *sub_menu;
341 GtkWidget *sub_item;
343 if (!name)
344 return menu;
346 /* Code to add a submenu */
347 sub_menu = gtk_menu_new ();
348 if (flags & XCMENU_MARKUP)
350 sub_item = gtk_menu_item_new_with_label ("");
351 gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item)->child), name);
353 else
355 if (flags & XCMENU_MNEMONIC)
356 sub_item = gtk_menu_item_new_with_mnemonic (name);
357 else
358 sub_item = gtk_menu_item_new_with_label (name);
360 gtk_menu_shell_insert (GTK_MENU_SHELL (menu), sub_item, pos);
361 gtk_widget_show (sub_item);
362 gtk_menu_item_set_submenu (GTK_MENU_ITEM (sub_item), sub_menu);
364 if (sub_item_ret)
365 *sub_item_ret = sub_item;
367 if (flags & XCMENU_DOLIST)
368 /* We create a new element in the list */
369 submenu_list = g_slist_prepend (submenu_list, sub_menu);
370 return sub_menu;
373 static GtkWidget *
374 menu_quick_endsub ()
376 /* Just delete the first element in the linked list pointed to by first */
377 if (submenu_list)
378 submenu_list = g_slist_remove (submenu_list, submenu_list->data);
380 if (submenu_list)
381 return (submenu_list->data);
382 else
383 return NULL;
386 static void
387 toggle_cb (GtkWidget *item, char *pref_name)
389 char buf[256];
391 if (GTK_CHECK_MENU_ITEM (item)->active)
392 snprintf (buf, sizeof (buf), "set %s 1", pref_name);
393 else
394 snprintf (buf, sizeof (buf), "set %s 0", pref_name);
396 handle_command (current_sess, buf, FALSE);
399 static int
400 is_in_path (char *cmd)
402 char *prog = strdup (cmd + 1); /* 1st char is "!" */
403 char *space, *path, *orig;
405 orig = prog; /* save for free()ing */
406 /* special-case these default entries. */
407 /* 123456789012345678 */
408 if (strncmp (prog, "gnome-terminal -x ", 18) == 0)
409 /* don't check for gnome-terminal, but the thing it's executing! */
410 prog += 18;
412 space = strchr (prog, ' '); /* this isn't 100% but good enuf */
413 if (space)
414 *space = 0;
416 path = g_find_program_in_path (prog);
417 if (path)
419 g_free (path);
420 g_free (orig);
421 return 1;
424 g_free (orig);
425 return 0;
428 /* syntax: "LABEL~ICON~STUFF~ADDED~LATER~" */
430 static void
431 menu_extract_icon (char *name, char **label, char **icon)
433 char *p = name;
434 char *start = NULL;
435 char *end = NULL;
437 while (*p)
439 if (*p == '~')
441 /* escape \~ */
442 if (p == name || p[-1] != '\\')
444 if (!start)
445 start = p + 1;
446 else if (!end)
447 end = p + 1;
450 p++;
453 if (!end)
454 end = p;
456 if (start && start != end)
458 *label = g_strndup (name, (start - name) - 1);
459 *icon = g_strndup (start, (end - start) - 1);
461 else
463 *label = g_strdup (name);
464 *icon = NULL;
468 /* append items to "menu" using the (struct popup*) list provided */
470 void
471 menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
473 struct popup *pop;
474 GtkWidget *tempmenu = menu, *subitem = NULL;
475 int childcount = 0;
477 submenu_list = g_slist_prepend (0, menu);
478 while (list)
480 pop = (struct popup *) list->data;
482 if (!strncasecmp (pop->name, "SUB", 3))
484 childcount = 0;
485 tempmenu = menu_quick_sub (pop->cmd, tempmenu, &subitem, XCMENU_DOLIST|XCMENU_MNEMONIC, -1);
487 } else if (!strncasecmp (pop->name, "TOGGLE", 6))
489 childcount++;
490 menu_toggle_item (pop->name + 7, tempmenu, toggle_cb, pop->cmd,
491 cfg_get_bool (pop->cmd));
493 } else if (!strncasecmp (pop->name, "ENDSUB", 6))
495 /* empty sub menu due to no programs in PATH? */
496 if (check_path && childcount < 1)
497 gtk_widget_destroy (subitem);
498 subitem = NULL;
500 if (tempmenu != menu)
501 tempmenu = menu_quick_endsub ();
502 /* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
504 } else if (!strncasecmp (pop->name, "SEP", 3))
506 menu_quick_item (0, 0, tempmenu, XCMENU_SHADED, 0, 0);
508 } else
510 char *icon, *label;
512 /* default command in xchat.c */
513 if (pop->cmd[0] == 'n' && !strcmp (pop->cmd, "notify -n ASK %s"))
515 /* don't create this item if already in notify list */
516 if (!target || notify_is_in_list (current_sess->server, target))
518 list = list->next;
519 continue;
523 menu_extract_icon (pop->name, &label, &icon);
525 if (!check_path || pop->cmd[0] != '!')
527 menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
528 /* check if the program is in path, if not, leave it out! */
529 } else if (is_in_path (pop->cmd))
531 childcount++;
532 menu_quick_item (pop->cmd, label, tempmenu, 0, target, icon);
535 g_free (label);
536 g_free (icon);
539 list = list->next;
542 /* Let's clean up the linked list from mem */
543 while (submenu_list)
544 submenu_list = g_slist_remove (submenu_list, submenu_list->data);
547 static char *str_copy = NULL; /* for all pop-up menus */
548 static GtkWidget *nick_submenu = NULL; /* user info submenu */
550 static void
551 menu_destroy (GtkWidget *menu, gpointer objtounref)
553 gtk_widget_destroy (menu);
554 g_object_unref (menu);
555 if (objtounref)
556 g_object_unref (G_OBJECT (objtounref));
557 nick_submenu = NULL;
560 static void
561 menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
563 if (event && event->window)
564 gtk_menu_set_screen (GTK_MENU (menu), gdk_drawable_get_screen (event->window));
566 g_object_ref (menu);
567 g_object_ref_sink (menu);
568 g_object_unref (menu);
569 g_signal_connect (G_OBJECT (menu), "selection-done",
570 G_CALLBACK (menu_destroy), objtounref);
571 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
572 0, event ? event->time : 0);
575 static void
576 menu_nickinfo_cb (GtkWidget *menu, session *sess)
578 char buf[512];
580 if (!is_session (sess))
581 return;
583 /* issue a /WHOIS */
584 snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
585 handle_command (sess, buf, FALSE);
586 /* and hide the output */
587 sess->server->skip_next_whois = 1;
590 static void
591 copy_to_clipboard_cb (GtkWidget *item, char *url)
593 gtkutil_copy_to_clipboard (item, NULL, url);
596 /* returns boolean: Some data is missing */
598 static gboolean
599 menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
601 char buf[512];
602 char unknown[96];
603 char *real, *fmt;
604 struct away_msg *away;
605 gboolean missing = FALSE;
606 GtkWidget *item;
608 /* let the translators tweak this if need be */
609 fmt = _("<tt><b>%-11s</b></tt> %s");
610 snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
612 if (user->realname)
614 real = strip_color (user->realname, -1, STRIP_ALL|STRIP_ESCMARKUP);
615 snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
616 g_free (real);
617 } else
619 snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
621 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
622 g_signal_connect (G_OBJECT (item), "activate",
623 G_CALLBACK (copy_to_clipboard_cb),
624 user->realname ? user->realname : unknown);
626 snprintf (buf, sizeof (buf), fmt, _("User:"),
627 user->hostname ? user->hostname : unknown);
628 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
629 g_signal_connect (G_OBJECT (item), "activate",
630 G_CALLBACK (copy_to_clipboard_cb),
631 user->hostname ? user->hostname : unknown);
633 snprintf (buf, sizeof (buf), fmt, _("Country:"),
634 user->hostname ? country(user->hostname) : unknown);
635 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
636 g_signal_connect (G_OBJECT (item), "activate",
637 G_CALLBACK (copy_to_clipboard_cb),
638 user->hostname ? country(user->hostname) : unknown);
640 snprintf (buf, sizeof (buf), fmt, _("Server:"),
641 user->servername ? user->servername : unknown);
642 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
643 g_signal_connect (G_OBJECT (item), "activate",
644 G_CALLBACK (copy_to_clipboard_cb),
645 user->servername ? user->servername : unknown);
647 if (user->lasttalk)
649 char min[96];
651 snprintf (min, sizeof (min), _("%u minutes ago"),
652 (unsigned int) ((time (0) - user->lasttalk) / 60));
653 snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
654 } else
656 snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
658 menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
660 if (user->away)
662 away = server_away_find_message (current_sess->server, user->nick);
663 if (away)
665 char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP);
666 snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
667 g_free (msg);
668 item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
669 g_signal_connect (G_OBJECT (item), "activate",
670 G_CALLBACK (copy_to_clipboard_cb),
671 away->message ? away->message : unknown);
673 else
674 missing = TRUE;
677 return missing;
680 void
681 fe_userlist_update (session *sess, struct User *user)
683 GList *items, *next;
685 if (!nick_submenu || !str_copy)
686 return;
688 /* not the same nick as the menu? */
689 if (sess->server->p_cmp (user->nick, str_copy))
690 return;
692 /* get rid of the "show" signal */
693 g_signal_handlers_disconnect_by_func (nick_submenu, menu_nickinfo_cb, sess);
695 /* destroy all the old items */
696 items = ((GtkMenuShell *) nick_submenu)->children;
697 while (items)
699 next = items->next;
700 gtk_widget_destroy (items->data);
701 items = next;
704 /* and re-create them with new info */
705 menu_create_nickinfo_menu (user, nick_submenu);
708 void
709 menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
711 char buf[512];
712 struct User *user;
713 GtkWidget *submenu, *menu = gtk_menu_new ();
715 if (str_copy)
716 free (str_copy);
717 str_copy = strdup (nick);
719 submenu_list = 0; /* first time through, might not be 0 */
721 /* more than 1 nick selected? */
722 if (num_sel > 1)
724 snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
725 menu_quick_item (0, buf, menu, 0, 0, 0);
726 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
727 } else
729 user = userlist_find (sess, nick); /* lasttalk is channel specific */
730 if (!user)
731 user = userlist_find_global (current_sess->server, nick);
732 if (user)
734 nick_submenu = submenu = menu_quick_sub (nick, menu, NULL, XCMENU_DOLIST, -1);
736 if (menu_create_nickinfo_menu (user, submenu) ||
737 !user->hostname || !user->realname || !user->servername)
739 g_signal_connect (G_OBJECT (submenu), "show", G_CALLBACK (menu_nickinfo_cb), sess);
742 menu_quick_endsub ();
743 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
747 if (num_sel > 1)
748 menu_create (menu, popup_list, NULL, FALSE);
749 else
750 menu_create (menu, popup_list, str_copy, FALSE);
752 if (num_sel == 0) /* xtext click */
753 menu_add_plugin_items (menu, "\x5$NICK", str_copy);
754 else /* userlist treeview click */
755 menu_add_plugin_items (menu, "\x5$NICK", NULL);
757 menu_popup (menu, event, NULL);
760 /* stuff for the View menu */
762 static void
763 menu_showhide_cb (session *sess)
765 if (prefs.hidemenu)
766 gtk_widget_hide (sess->gui->menu);
767 else
768 gtk_widget_show (sess->gui->menu);
771 static void
772 menu_topic_showhide_cb (session *sess)
774 if (prefs.topicbar)
775 gtk_widget_show (sess->gui->topic_bar);
776 else
777 gtk_widget_hide (sess->gui->topic_bar);
780 static void
781 menu_userlist_showhide_cb (session *sess)
783 mg_decide_userlist (sess, TRUE);
786 static void
787 menu_ulbuttons_showhide_cb (session *sess)
789 if (prefs.userlistbuttons)
790 gtk_widget_show (sess->gui->button_box);
791 else
792 gtk_widget_hide (sess->gui->button_box);
795 static void
796 menu_cmbuttons_showhide_cb (session *sess)
798 switch (sess->type)
800 case SESS_CHANNEL:
801 if (prefs.chanmodebuttons)
802 gtk_widget_show (sess->gui->topicbutton_box);
803 else
804 gtk_widget_hide (sess->gui->topicbutton_box);
805 break;
806 default:
807 gtk_widget_hide (sess->gui->topicbutton_box);
811 static void
812 menu_setting_foreach (void (*callback) (session *), int id, guint state)
814 session *sess;
815 GSList *list;
816 int maindone = FALSE; /* do it only once for EVERY tab */
818 list = sess_list;
819 while (list)
821 sess = list->data;
823 if (!sess->gui->is_tab || !maindone)
825 if (sess->gui->is_tab)
826 maindone = TRUE;
827 if (id != -1)
828 GTK_CHECK_MENU_ITEM (sess->gui->menu_item[id])->active = state;
829 if (callback)
830 callback (sess);
833 list = list->next;
837 void
838 menu_bar_toggle (void)
840 prefs.hidemenu = !prefs.hidemenu;
841 menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hidemenu);
844 static void
845 menu_bar_toggle_cb (void)
847 menu_bar_toggle ();
848 if (prefs.hidemenu)
849 fe_message (_("The Menubar is now hidden. You can show it again"
850 " by pressing F9 or right-clicking in a blank part of"
851 " the main text area."), FE_MSG_INFO);
854 static void
855 menu_topicbar_toggle (GtkWidget *wid, gpointer ud)
857 prefs.topicbar = !prefs.topicbar;
858 menu_setting_foreach (menu_topic_showhide_cb, MENU_ID_TOPICBAR,
859 prefs.topicbar);
862 static void
863 menu_userlist_toggle (GtkWidget *wid, gpointer ud)
865 prefs.hideuserlist = !prefs.hideuserlist;
866 menu_setting_foreach (menu_userlist_showhide_cb, MENU_ID_USERLIST,
867 !prefs.hideuserlist);
870 static void
871 menu_ulbuttons_toggle (GtkWidget *wid, gpointer ud)
873 prefs.userlistbuttons = !prefs.userlistbuttons;
874 menu_setting_foreach (menu_ulbuttons_showhide_cb, MENU_ID_ULBUTTONS,
875 prefs.userlistbuttons);
878 static void
879 menu_cmbuttons_toggle (GtkWidget *wid, gpointer ud)
881 prefs.chanmodebuttons = !prefs.chanmodebuttons;
882 menu_setting_foreach (menu_cmbuttons_showhide_cb, MENU_ID_MODEBUTTONS,
883 prefs.chanmodebuttons);
886 void
887 menu_middlemenu (session *sess, GdkEventButton *event)
889 GtkWidget *menu;
890 GtkAccelGroup *accel_group;
892 accel_group = gtk_accel_group_new ();
893 menu = menu_create_main (accel_group, FALSE, sess->server->is_away, !sess->gui->is_tab, NULL);
894 menu_popup (menu, event, accel_group);
897 static void
898 open_url_cb (GtkWidget *item, char *url)
900 char buf[512];
902 /* pass this to /URL so it can handle irc:// */
903 snprintf (buf, sizeof (buf), "URL %s", url);
904 handle_command (current_sess, buf, FALSE);
907 void
908 menu_urlmenu (GdkEventButton *event, char *url)
910 GtkWidget *menu;
911 char *tmp, *chop;
913 if (str_copy)
914 free (str_copy);
915 str_copy = strdup (url);
917 menu = gtk_menu_new ();
918 /* more than 51 chars? Chop it */
919 if (g_utf8_strlen (str_copy, -1) >= 52)
921 tmp = strdup (str_copy);
922 chop = g_utf8_offset_to_pointer (tmp, 48);
923 chop[0] = chop[1] = chop[2] = '.';
924 chop[3] = 0;
925 menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
926 free (tmp);
927 } else
929 menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
931 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
933 /* Two hardcoded entries */
934 if (strncmp (str_copy, "irc://", 6) == 0 ||
935 strncmp (str_copy, "ircs://",7) == 0)
936 menu_quick_item_with_callback (open_url_cb, _("Connect"), menu, str_copy);
937 else
938 menu_quick_item_with_callback (open_url_cb, _("Open Link in Browser"), menu, str_copy);
939 menu_quick_item_with_callback (copy_to_clipboard_cb, _("Copy Selected Link"), menu, str_copy);
940 /* custom ones from urlhandlers.conf */
941 menu_create (menu, urlhandler_list, str_copy, TRUE);
942 menu_add_plugin_items (menu, "\x4$URL", str_copy);
943 menu_popup (menu, event, NULL);
946 static void
947 menu_chan_cycle (GtkWidget * menu, char *chan)
949 char tbuf[256];
951 if (current_sess)
953 snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
954 handle_command (current_sess, tbuf, FALSE);
958 static void
959 menu_chan_part (GtkWidget * menu, char *chan)
961 char tbuf[256];
963 if (current_sess)
965 snprintf (tbuf, sizeof tbuf, "part %s", chan);
966 handle_command (current_sess, tbuf, FALSE);
970 static void
971 menu_chan_join (GtkWidget * menu, char *chan)
973 char tbuf[256];
975 if (current_sess)
977 snprintf (tbuf, sizeof tbuf, "join %s", chan);
978 handle_command (current_sess, tbuf, FALSE);
982 void
983 menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
985 GtkWidget *menu;
986 int is_joined = FALSE;
988 if (find_channel (sess->server, chan))
989 is_joined = TRUE;
991 if (str_copy)
992 free (str_copy);
993 str_copy = strdup (chan);
995 menu = gtk_menu_new ();
997 menu_quick_item (0, chan, menu, XCMENU_SHADED, str_copy, 0);
998 menu_quick_item (0, 0, menu, XCMENU_SHADED, str_copy, 0);
1000 if (!is_joined)
1001 menu_quick_item_with_callback (menu_chan_join, _("Join Channel"), menu,
1002 str_copy);
1003 else
1005 menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
1006 str_copy);
1007 menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
1008 str_copy);
1011 menu_addfavoritemenu (sess->server, menu, str_copy);
1013 menu_add_plugin_items (menu, "\x5$CHAN", str_copy);
1014 menu_popup (menu, event, NULL);
1017 static void
1018 menu_delfav_cb (GtkWidget *item, server *serv)
1020 servlist_autojoinedit (serv->network, str_copy, FALSE);
1023 static void
1024 menu_addfav_cb (GtkWidget *item, server *serv)
1026 servlist_autojoinedit (serv->network, str_copy, TRUE);
1029 void
1030 menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel)
1032 if (!serv->network)
1033 return;
1035 if (channel != str_copy)
1037 if (str_copy)
1038 free (str_copy);
1039 str_copy = strdup (channel);
1042 if (joinlist_is_in_list (serv, channel))
1043 mg_create_icon_item (_("_Remove from Favorites"), GTK_STOCK_REMOVE, menu, menu_delfav_cb, serv);
1044 else
1045 mg_create_icon_item (_("_Add to Favorites"), GTK_STOCK_ADD, menu, menu_addfav_cb, serv);
1048 static void
1049 menu_open_server_list (GtkWidget *wid, gpointer none)
1051 fe_serverlist_open (current_sess);
1054 static void
1055 menu_settings (GtkWidget * wid, gpointer none)
1057 extern void setup_open (void);
1058 setup_open ();
1061 static void
1062 menu_usermenu (void)
1064 editlist_gui_open (NULL, NULL, usermenu_list, _("XChat: User menu"),
1065 "usermenu", "usermenu.conf", 0);
1068 static void
1069 usermenu_create (GtkWidget *menu)
1071 menu_create (menu, usermenu_list, "", FALSE);
1072 menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0); /* sep */
1073 menu_quick_item_with_callback (menu_usermenu, _("Edit This Menu..."), menu, 0);
1076 static void
1077 usermenu_destroy (GtkWidget * menu)
1079 GList *items = ((GtkMenuShell *) menu)->children;
1080 GList *next;
1082 while (items)
1084 next = items->next;
1085 gtk_widget_destroy (items->data);
1086 items = next;
1090 void
1091 usermenu_update (void)
1093 int done_main = FALSE;
1094 GSList *list = sess_list;
1095 session *sess;
1096 GtkWidget *menu;
1098 while (list)
1100 sess = list->data;
1101 menu = sess->gui->menu_item[MENU_ID_USERMENU];
1102 if (sess->gui->is_tab)
1104 if (!done_main && menu)
1106 usermenu_destroy (menu);
1107 usermenu_create (menu);
1108 done_main = TRUE;
1110 } else if (menu)
1112 usermenu_destroy (menu);
1113 usermenu_create (menu);
1115 list = list->next;
1119 static void
1120 menu_newserver_window (GtkWidget * wid, gpointer none)
1122 int old = prefs.tabchannels;
1124 prefs.tabchannels = 0;
1125 new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1126 prefs.tabchannels = old;
1129 static void
1130 menu_newchannel_window (GtkWidget * wid, gpointer none)
1132 int old = prefs.tabchannels;
1134 prefs.tabchannels = 0;
1135 new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1136 prefs.tabchannels = old;
1139 static void
1140 menu_newserver_tab (GtkWidget * wid, gpointer none)
1142 int old = prefs.tabchannels;
1143 int oldf = prefs.newtabstofront;
1145 prefs.tabchannels = 1;
1146 /* force focus if setting is "only requested tabs" */
1147 if (prefs.newtabstofront == 2)
1148 prefs.newtabstofront = 1;
1149 new_ircwindow (NULL, NULL, SESS_SERVER, 0);
1150 prefs.tabchannels = old;
1151 prefs.newtabstofront = oldf;
1154 static void
1155 menu_newchannel_tab (GtkWidget * wid, gpointer none)
1157 int old = prefs.tabchannels;
1159 prefs.tabchannels = 1;
1160 new_ircwindow (current_sess->server, NULL, SESS_CHANNEL, 0);
1161 prefs.tabchannels = old;
1164 static void
1165 menu_rawlog (GtkWidget * wid, gpointer none)
1167 open_rawlog (current_sess->server);
1170 static void
1171 menu_detach (GtkWidget * wid, gpointer none)
1173 mg_detach (current_sess, 0);
1176 static void
1177 menu_close (GtkWidget * wid, gpointer none)
1179 mg_close_sess (current_sess);
1182 static void
1183 menu_quit (GtkWidget * wid, gpointer none)
1185 mg_open_quit_dialog (FALSE);
1188 static void
1189 menu_search ()
1191 search_open (current_sess);
1194 static void
1195 menu_resetmarker (GtkWidget * wid, gpointer none)
1197 gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
1200 static void
1201 menu_flushbuffer (GtkWidget * wid, gpointer none)
1203 fe_text_clear (current_sess, 0);
1206 static void
1207 savebuffer_req_done (session *sess, char *file)
1209 int fh;
1211 if (!file)
1212 return;
1214 fh = open (file, O_TRUNC | O_WRONLY | O_CREAT, 0600);
1215 if (fh != -1)
1217 gtk_xtext_save (GTK_XTEXT (sess->gui->xtext), fh);
1218 close (fh);
1222 static void
1223 menu_savebuffer (GtkWidget * wid, gpointer none)
1225 gtkutil_file_req (_("Select an output filename"), savebuffer_req_done,
1226 current_sess, NULL, FRF_WRITE);
1229 static void
1230 menu_disconnect (GtkWidget * wid, gpointer none)
1232 handle_command (current_sess, "DISCON", FALSE);
1235 static void
1236 menu_reconnect (GtkWidget * wid, gpointer none)
1238 if (current_sess->server->hostname[0])
1239 handle_command (current_sess, "RECONNECT", FALSE);
1240 else
1241 fe_serverlist_open (current_sess);
1244 static void
1245 menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
1247 switch (response)
1249 case GTK_RESPONSE_ACCEPT:
1250 menu_chan_join (NULL, entry->text);
1251 break;
1253 case GTK_RESPONSE_HELP:
1254 chanlist_opengui (current_sess->server, TRUE);
1255 break;
1258 gtk_widget_destroy (dialog);
1261 static void
1262 menu_join_entry_cb (GtkWidget *entry, GtkDialog *dialog)
1264 gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
1267 static void
1268 menu_join (GtkWidget * wid, gpointer none)
1270 GtkWidget *hbox, *dialog, *entry, *label;
1272 dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
1273 GTK_WINDOW (parent_window), 0,
1274 _("Retrieve channel list..."), GTK_RESPONSE_HELP,
1275 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1276 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1277 NULL);
1278 gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
1279 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1280 hbox = gtk_hbox_new (TRUE, 0);
1282 entry = gtk_entry_new ();
1283 GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
1284 gtk_entry_set_text (GTK_ENTRY (entry), "#");
1285 g_signal_connect (G_OBJECT (entry), "activate",
1286 G_CALLBACK (menu_join_entry_cb), dialog);
1287 gtk_box_pack_end (GTK_BOX (hbox), entry, 0, 0, 0);
1289 label = gtk_label_new (_("Enter Channel to Join:"));
1290 gtk_box_pack_end (GTK_BOX (hbox), label, 0, 0, 0);
1292 g_signal_connect (G_OBJECT (dialog), "response",
1293 G_CALLBACK (menu_join_cb), entry);
1295 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1297 gtk_widget_show_all (dialog);
1299 gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
1300 gtk_editable_set_position (GTK_EDITABLE (entry), 1);
1303 static void
1304 menu_away (GtkCheckMenuItem *item, gpointer none)
1306 handle_command (current_sess, item->active ? "away" : "back", FALSE);
1309 static void
1310 menu_chanlist (GtkWidget * wid, gpointer none)
1312 chanlist_opengui (current_sess->server, FALSE);
1315 static void
1316 menu_banlist (GtkWidget * wid, gpointer none)
1318 banlist_opengui (current_sess);
1321 #ifdef USE_PLUGIN
1323 static void
1324 menu_loadplugin (void)
1326 plugingui_load ();
1329 static void
1330 menu_pluginlist (void)
1332 plugingui_open ();
1335 #else
1337 #define menu_pluginlist 0
1338 #define menu_loadplugin 0
1340 #endif
1342 #define usercommands_help _("User Commands - Special codes:\n\n"\
1343 "%c = current channel\n"\
1344 "%e = current network name\n"\
1345 "%m = machine info\n"\
1346 "%n = your nick\n"\
1347 "%t = time/date\n"\
1348 "%v = xchat version\n"\
1349 "%2 = word 2\n"\
1350 "%3 = word 3\n"\
1351 "&2 = word 2 to the end of line\n"\
1352 "&3 = word 3 to the end of line\n\n"\
1353 "eg:\n"\
1354 "/cmd john hello\n\n"\
1355 "%2 would be \042john\042\n"\
1356 "&2 would be \042john hello\042.")
1358 #define ulbutton_help _("Userlist Buttons - Special codes:\n\n"\
1359 "%a = all selected nicks\n"\
1360 "%c = current channel\n"\
1361 "%e = current network name\n"\
1362 "%h = selected nick's hostname\n"\
1363 "%m = machine info\n"\
1364 "%n = your nick\n"\
1365 "%s = selected nick\n"\
1366 "%t = time/date\n")
1368 #define dlgbutton_help _("Dialog Buttons - Special codes:\n\n"\
1369 "%a = all selected nicks\n"\
1370 "%c = current channel\n"\
1371 "%e = current network name\n"\
1372 "%h = selected nick's hostname\n"\
1373 "%m = machine info\n"\
1374 "%n = your nick\n"\
1375 "%s = selected nick\n"\
1376 "%t = time/date\n")
1378 #define ctcp_help _("CTCP Replies - Special codes:\n\n"\
1379 "%d = data (the whole ctcp)\n"\
1380 "%e = current network name\n"\
1381 "%m = machine info\n"\
1382 "%s = nick who sent the ctcp\n"\
1383 "%t = time/date\n"\
1384 "%2 = word 2\n"\
1385 "%3 = word 3\n"\
1386 "&2 = word 2 to the end of line\n"\
1387 "&3 = word 3 to the end of line\n\n")
1389 #define url_help _("URL Handlers - Special codes:\n\n"\
1390 "%s = the URL string\n\n"\
1391 "Putting a ! infront of the command\n"\
1392 "indicates it should be sent to a\n"\
1393 "shell instead of XChat")
1395 static void
1396 menu_usercommands (void)
1398 editlist_gui_open (NULL, NULL, command_list, _("XChat: User Defined Commands"),
1399 "commands", "commands.conf", usercommands_help);
1402 static void
1403 menu_ulpopup (void)
1405 editlist_gui_open (NULL, NULL, popup_list, _("XChat: Userlist Popup menu"), "popup",
1406 "popup.conf", ulbutton_help);
1409 static void
1410 menu_rpopup (void)
1412 editlist_gui_open (_("Text"), _("Replace with"), replace_list, _("XChat: Replace"), "replace",
1413 "replace.conf", 0);
1416 static void
1417 menu_urlhandlers (void)
1419 editlist_gui_open (NULL, NULL, urlhandler_list, _("XChat: URL Handlers"), "urlhandlers",
1420 "urlhandlers.conf", url_help);
1423 static void
1424 menu_evtpopup (void)
1426 pevent_dialog_show ();
1429 static void
1430 menu_keypopup (void)
1432 key_dialog_show ();
1435 static void
1436 menu_ulbuttons (void)
1438 editlist_gui_open (NULL, NULL, button_list, _("XChat: Userlist buttons"), "buttons",
1439 "buttons.conf", ulbutton_help);
1442 static void
1443 menu_dlgbuttons (void)
1445 editlist_gui_open (NULL, NULL, dlgbutton_list, _("XChat: Dialog buttons"), "dlgbuttons",
1446 "dlgbuttons.conf", dlgbutton_help);
1449 static void
1450 menu_ctcpguiopen (void)
1452 editlist_gui_open (NULL, NULL, ctcp_list, _("XChat: CTCP Replies"), "ctcpreply",
1453 "ctcpreply.conf", ctcp_help);
1456 static void
1457 menu_docs (GtkWidget *wid, gpointer none)
1459 fe_open_url ("http://xchat.org/docs/");
1462 /*static void
1463 menu_webpage (GtkWidget *wid, gpointer none)
1465 fe_open_url ("http://xchat.org");
1468 static void
1469 menu_dcc_win (GtkWidget *wid, gpointer none)
1471 fe_dcc_open_recv_win (FALSE);
1472 fe_dcc_open_send_win (FALSE);
1475 static void
1476 menu_dcc_chat_win (GtkWidget *wid, gpointer none)
1478 fe_dcc_open_chat_win (FALSE);
1481 void
1482 menu_change_layout (void)
1484 if (prefs.tab_layout == 0)
1486 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 1);
1487 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 0);
1488 mg_change_layout (0);
1489 } else
1491 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TABS, 0);
1492 menu_setting_foreach (NULL, MENU_ID_LAYOUT_TREE, 1);
1493 mg_change_layout (2);
1497 static void
1498 menu_layout_cb (GtkWidget *item, gpointer none)
1500 prefs.tab_layout = 2;
1501 if (GTK_CHECK_MENU_ITEM (item)->active)
1502 prefs.tab_layout = 0;
1504 menu_change_layout ();
1507 static void
1508 menu_apply_metres_cb (session *sess)
1510 mg_update_meters (sess->gui);
1513 static void
1514 menu_metres_off (GtkWidget *item, gpointer none)
1516 if (GTK_CHECK_MENU_ITEM (item)->active)
1518 prefs.lagometer = 0;
1519 prefs.throttlemeter = 0;
1520 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1524 static void
1525 menu_metres_text (GtkWidget *item, gpointer none)
1527 if (GTK_CHECK_MENU_ITEM (item)->active)
1529 prefs.lagometer = 2;
1530 prefs.throttlemeter = 2;
1531 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1535 static void
1536 menu_metres_graph (GtkWidget *item, gpointer none)
1538 if (GTK_CHECK_MENU_ITEM (item)->active)
1540 prefs.lagometer = 1;
1541 prefs.throttlemeter = 1;
1542 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1546 static void
1547 menu_metres_both (GtkWidget *item, gpointer none)
1549 if (GTK_CHECK_MENU_ITEM (item)->active)
1551 prefs.lagometer = 3;
1552 prefs.throttlemeter = 3;
1553 menu_setting_foreach (menu_apply_metres_cb, -1, 0);
1557 static struct mymenu mymenu[] = {
1558 {N_("_XChat"), 0, 0, M_NEWMENU, 0, 0, 1},
1559 {N_("Network Li_st..."), menu_open_server_list, (char *)&pix_book, M_MENUPIX, 0, 0, 1, GDK_s},
1560 {0, 0, 0, M_SEP, 0, 0, 0},
1562 {N_("_New"), 0, GTK_STOCK_NEW, M_MENUSUB, 0, 0, 1},
1563 {N_("Server Tab..."), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_t},
1564 {N_("Channel Tab..."), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
1565 {N_("Server Window..."), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1},
1566 {N_("Channel Window..."), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
1567 {0, 0, 0, M_END, 0, 0, 0},
1568 {0, 0, 0, M_SEP, 0, 0, 0},
1570 #ifdef USE_PLUGIN
1571 {N_("_Load Plugin or Script..."), menu_loadplugin, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 1},
1572 #else
1573 {N_("_Load Plugin or Script..."), 0, GTK_STOCK_REVERT_TO_SAVED, M_MENUSTOCK, 0, 0, 0},
1574 #endif
1575 {0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
1576 #define DETACH_OFFSET (12)
1577 {0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_I}, /* 12 */
1578 #define CLOSE_OFFSET (13)
1579 {0, menu_close, GTK_STOCK_CLOSE, M_MENUSTOCK, 0, 0, 1, GDK_w},
1580 {0, 0, 0, M_SEP, 0, 0, 0},
1581 {N_("_Quit"), menu_quit, GTK_STOCK_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_q}, /* 15 */
1583 {N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
1584 #define MENUBAR_OFFSET (17)
1585 {N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_F9},
1586 {N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
1587 {N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_F7},
1588 {N_("U_serlist Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
1589 {N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
1590 {0, 0, 0, M_SEP, 0, 0, 0},
1591 {N_("_Channel Switcher"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 23 */
1592 #define TABS_OFFSET (24)
1593 {N_("_Tabs"), menu_layout_cb, 0, M_MENURADIO, MENU_ID_LAYOUT_TABS, 0, 1},
1594 {N_("T_ree"), 0, 0, M_MENURADIO, MENU_ID_LAYOUT_TREE, 0, 1},
1595 {0, 0, 0, M_END, 0, 0, 0},
1596 {N_("_Network Meters"), 0, 0, M_MENUSUB, 0, 0, 1}, /* 27 */
1597 #define METRE_OFFSET (28)
1598 {N_("Off"), menu_metres_off, 0, M_MENURADIO, 0, 0, 1},
1599 {N_("Graph"), menu_metres_graph, 0, M_MENURADIO, 0, 0, 1},
1600 {N_("Text"), menu_metres_text, 0, M_MENURADIO, 0, 0, 1},
1601 {N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
1602 {0, 0, 0, M_END, 0, 0, 0}, /* 32 */
1604 {N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
1605 {N_("_Disconnect"), menu_disconnect, GTK_STOCK_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
1606 {N_("_Reconnect"), menu_reconnect, GTK_STOCK_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
1607 {N_("Join a Channel..."), menu_join, GTK_STOCK_JUMP_TO, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
1608 {N_("List of Channels..."), menu_chanlist, GTK_STOCK_INDEX, M_MENUITEM, 0, 0, 1},
1609 {0, 0, 0, M_SEP, 0, 0, 0},
1610 #define AWAY_OFFSET (39)
1611 {N_("Marked Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_a},
1613 {N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
1615 {N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
1616 {N_("_Preferences"), menu_settings, GTK_STOCK_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
1618 {N_("Advanced"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
1619 {N_("Auto Replace..."), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
1620 {N_("CTCP Replies..."), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
1621 {N_("Dialog Buttons..."), menu_dlgbuttons, 0, M_MENUITEM, 0, 0, 1},
1622 {N_("Keyboard Shortcuts..."), menu_keypopup, 0, M_MENUITEM, 0, 0, 1},
1623 {N_("Text Events..."), menu_evtpopup, 0, M_MENUITEM, 0, 0, 1},
1624 {N_("URL Handlers..."), menu_urlhandlers, 0, M_MENUITEM, 0, 0, 1},
1625 {N_("User Commands..."), menu_usercommands, 0, M_MENUITEM, 0, 0, 1},
1626 {N_("Userlist Buttons..."), menu_ulbuttons, 0, M_MENUITEM, 0, 0, 1},
1627 {N_("Userlist Popup..."), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1},
1628 {0, 0, 0, M_END, 0, 0, 0}, /* 53 */
1630 {N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
1631 {N_("Ban List..."), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
1632 {N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
1633 {N_("Direct Chat..."), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
1634 {N_("File Transfers..."), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
1635 {N_("Friends List..."), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
1636 {N_("Ignore List..."), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
1637 {N_("Plugins and Scripts..."), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
1638 {N_("Raw Log..."), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 62 */
1639 {N_("URL Grabber..."), url_opengui, 0, M_MENUITEM, 0, 0, 1},
1640 {0, 0, 0, M_SEP, 0, 0, 0},
1641 {N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
1642 {N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
1643 #define SEARCH_OFFSET 67
1644 {N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
1645 {N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
1647 {N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 69 */
1648 {N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
1649 #if 0
1650 {N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},
1651 #endif
1652 {N_("_About"), menu_about, GTK_STOCK_ABOUT, M_MENUSTOCK, 0, 0, 1},
1654 {0, 0, 0, M_END, 0, 0, 0},
1657 GtkWidget *
1658 create_icon_menu (char *labeltext, void *stock_name, int is_stock)
1660 GtkWidget *item, *img;
1662 if (is_stock)
1663 img = gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
1664 else
1665 img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
1666 item = gtk_image_menu_item_new_with_mnemonic (labeltext);
1667 gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
1668 gtk_widget_show (img);
1670 return item;
1673 /* Override the default GTK2.4 handler, which would make menu
1674 bindings not work when the menu-bar is hidden. */
1675 static gboolean
1676 menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
1678 /* GTK2.2 behaviour */
1679 #if GTK_CHECK_VERSION(2,20,0)
1680 return gtk_widget_is_sensitive (widget);
1681 #else
1682 return GTK_WIDGET_IS_SENSITIVE (widget);
1683 #endif
1686 /* === STUFF FOR /MENU === */
1688 static GtkMenuItem *
1689 menu_find_item (GtkWidget *menu, char *name)
1691 GList *items = ((GtkMenuShell *) menu)->children;
1692 GtkMenuItem *item;
1693 GtkWidget *child;
1694 const char *labeltext;
1696 while (items)
1698 item = items->data;
1699 child = GTK_BIN (item)->child;
1700 if (child) /* separators arn't labels, skip them */
1702 labeltext = g_object_get_data (G_OBJECT (item), "name");
1703 if (!labeltext)
1704 labeltext = gtk_label_get_text (GTK_LABEL (child));
1705 if (!menu_streq (labeltext, name, 1))
1706 return item;
1707 } else if (name == NULL)
1709 return item;
1711 items = items->next;
1714 return NULL;
1717 static GtkWidget *
1718 menu_find_path (GtkWidget *menu, char *path)
1720 GtkMenuItem *item;
1721 char *s;
1722 char name[128];
1723 int len;
1725 /* grab the next part of the path */
1726 s = strchr (path, '/');
1727 len = s - path;
1728 if (!s)
1729 len = strlen (path);
1730 len = MIN (len, sizeof (name) - 1);
1731 memcpy (name, path, len);
1732 name[len] = 0;
1734 item = menu_find_item (menu, name);
1735 if (!item)
1736 return NULL;
1738 menu = gtk_menu_item_get_submenu (item);
1739 if (!menu)
1740 return NULL;
1742 path += len;
1743 if (*path == 0)
1744 return menu;
1746 return menu_find_path (menu, path + 1);
1749 static GtkWidget *
1750 menu_find (GtkWidget *menu, char *path, char *label)
1752 GtkWidget *item = NULL;
1754 if (path[0] != 0)
1755 menu = menu_find_path (menu, path);
1756 if (menu)
1757 item = (GtkWidget *)menu_find_item (menu, label);
1758 return item;
1761 static void
1762 menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, char *))
1764 GSList *list = sess_list;
1765 int tabdone = FALSE;
1766 session *sess;
1768 if (!me->is_main)
1769 return; /* not main menu */
1771 while (list)
1773 sess = list->data;
1774 /* do it only once for tab sessions, since they share a GUI */
1775 if (!sess->gui->is_tab || !tabdone)
1777 callback (sess->gui->menu, me, NULL);
1778 if (sess->gui->is_tab)
1779 tabdone = TRUE;
1781 list = list->next;
1785 static void
1786 menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
1788 GtkWidget *item;
1790 item = menu_find (menu, me->path, me->label);
1791 if (item)
1793 gtk_widget_set_sensitive (item, me->enable);
1794 /* must do it without triggering the callback */
1795 if (GTK_IS_CHECK_MENU_ITEM (item))
1796 GTK_CHECK_MENU_ITEM (item)->active = me->state;
1800 /* radio state changed via mouse click */
1801 static void
1802 menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
1804 me->state = 0;
1805 if (item->active)
1806 me->state = 1;
1808 /* update the state, incase this was changed via right-click. */
1809 /* This will update all other windows and menu bars */
1810 menu_foreach_gui (me, menu_update_cb);
1812 if (me->state && me->cmd)
1813 handle_command (current_sess, me->cmd, FALSE);
1816 /* toggle state changed via mouse click */
1817 static void
1818 menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
1820 me->state = 0;
1821 if (item->active)
1822 me->state = 1;
1824 /* update the state, incase this was changed via right-click. */
1825 /* This will update all other windows and menu bars */
1826 menu_foreach_gui (me, menu_update_cb);
1828 if (me->state)
1829 handle_command (current_sess, me->cmd, FALSE);
1830 else
1831 handle_command (current_sess, me->ucmd, FALSE);
1834 static GtkWidget *
1835 menu_radio_item (char *label, GtkWidget *menu, void *callback, void *userdata,
1836 int state, char *groupname)
1838 GtkWidget *item;
1839 GtkMenuItem *parent;
1840 GSList *grouplist = NULL;
1842 parent = menu_find_item (menu, groupname);
1843 if (parent)
1844 grouplist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *)parent);
1846 item = gtk_radio_menu_item_new_with_label (grouplist, label);
1847 gtk_check_menu_item_set_active ((GtkCheckMenuItem*)item, state);
1848 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1849 g_signal_connect (G_OBJECT (item), "activate",
1850 G_CALLBACK (callback), userdata);
1851 gtk_widget_show (item);
1853 return item;
1856 static void
1857 menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
1859 if (pos == 0xffff) /* outbound.c uses this default */
1860 return;
1862 if (pos < 0) /* position offset from end/bottom */
1863 gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
1864 else
1865 gtk_menu_reorder_child (menu, item, pos);
1868 static GtkWidget *
1869 menu_add_radio (GtkWidget *menu, menu_entry *me)
1871 GtkWidget *item = NULL;
1872 char *path = me->path + me->root_offset;
1874 if (path[0] != 0)
1875 menu = menu_find_path (menu, path);
1876 if (menu)
1878 item = menu_radio_item (me->label, menu, menu_radio_cb, me, me->state, me->group);
1879 menu_reorder (GTK_MENU (menu), item, me->pos);
1881 return item;
1884 static GtkWidget *
1885 menu_add_toggle (GtkWidget *menu, menu_entry *me)
1887 GtkWidget *item = NULL;
1888 char *path = me->path + me->root_offset;
1890 if (path[0] != 0)
1891 menu = menu_find_path (menu, path);
1892 if (menu)
1894 item = menu_toggle_item (me->label, menu, menu_toggle_cb, me, me->state);
1895 menu_reorder (GTK_MENU (menu), item, me->pos);
1897 return item;
1900 static GtkWidget *
1901 menu_add_item (GtkWidget *menu, menu_entry *me, char *target)
1903 GtkWidget *item = NULL;
1904 char *path = me->path + me->root_offset;
1906 if (path[0] != 0)
1907 menu = menu_find_path (menu, path);
1908 if (menu)
1910 item = menu_quick_item (me->cmd, me->label, menu, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, target, me->icon);
1911 menu_reorder (GTK_MENU (menu), item, me->pos);
1913 return item;
1916 static GtkWidget *
1917 menu_add_sub (GtkWidget *menu, menu_entry *me)
1919 GtkWidget *item = NULL;
1920 char *path = me->path + me->root_offset;
1921 int pos;
1923 if (path[0] != 0)
1924 menu = menu_find_path (menu, path);
1925 if (menu)
1927 pos = me->pos;
1928 if (pos < 0) /* position offset from end/bottom */
1929 pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
1930 menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
1932 return item;
1935 static void
1936 menu_del_cb (GtkWidget *menu, menu_entry *me, char *target)
1938 GtkWidget *item = menu_find (menu, me->path + me->root_offset, me->label);
1939 if (item)
1940 gtk_widget_destroy (item);
1943 static void
1944 menu_add_cb (GtkWidget *menu, menu_entry *me, char *target)
1946 GtkWidget *item;
1947 GtkAccelGroup *accel_group;
1949 if (me->group) /* have a group name? Must be a radio item */
1950 item = menu_add_radio (menu, me);
1951 else if (me->ucmd) /* have unselect-cmd? Must be a toggle item */
1952 item = menu_add_toggle (menu, me);
1953 else if (me->cmd || !me->label) /* label=NULL for separators */
1954 item = menu_add_item (menu, me, target);
1955 else
1956 item = menu_add_sub (menu, me);
1958 if (item)
1960 gtk_widget_set_sensitive (item, me->enable);
1961 if (me->key)
1963 accel_group = g_object_get_data (G_OBJECT (menu), "accel");
1964 if (accel_group) /* popup menus don't have them */
1965 gtk_widget_add_accelerator (item, "activate", accel_group, me->key,
1966 me->modifier, GTK_ACCEL_VISIBLE);
1971 char *
1972 fe_menu_add (menu_entry *me)
1974 char *text;
1976 menu_foreach_gui (me, menu_add_cb);
1978 if (!me->markup)
1979 return NULL;
1981 if (!pango_parse_markup (me->label, -1, 0, NULL, &text, NULL, NULL))
1982 return NULL;
1984 /* return the label with markup stripped */
1985 return text;
1988 void
1989 fe_menu_del (menu_entry *me)
1991 menu_foreach_gui (me, menu_del_cb);
1994 void
1995 fe_menu_update (menu_entry *me)
1997 menu_foreach_gui (me, menu_update_cb);
2000 /* used to add custom menus to the right-click menu */
2002 static void
2003 menu_add_plugin_mainmenu_items (GtkWidget *menu)
2005 GSList *list;
2006 menu_entry *me;
2008 list = menu_list; /* outbound.c */
2009 while (list)
2011 me = list->data;
2012 if (me->is_main)
2013 menu_add_cb (menu, me, NULL);
2014 list = list->next;
2018 void
2019 menu_add_plugin_items (GtkWidget *menu, char *root, char *target)
2021 GSList *list;
2022 menu_entry *me;
2024 list = menu_list; /* outbound.c */
2025 while (list)
2027 me = list->data;
2028 if (!me->is_main && !strncmp (me->path, root + 1, root[0]))
2029 menu_add_cb (menu, me, target);
2030 list = list->next;
2034 /* === END STUFF FOR /MENU === */
2036 GtkWidget *
2037 menu_create_main (void *accel_group, int bar, int away, int toplevel,
2038 GtkWidget **menu_widgets)
2040 int i = 0;
2041 GtkWidget *item;
2042 GtkWidget *menu = 0;
2043 GtkWidget *menu_item = 0;
2044 GtkWidget *menu_bar;
2045 GtkWidget *usermenu = 0;
2046 GtkWidget *submenu = 0;
2047 int close_mask = GDK_CONTROL_MASK;
2048 int away_mask = GDK_MOD1_MASK;
2049 char *key_theme = NULL;
2050 GtkSettings *settings;
2051 GSList *group = NULL;
2053 if (bar)
2054 menu_bar = gtk_menu_bar_new ();
2055 else
2056 menu_bar = gtk_menu_new ();
2058 /* /MENU needs to know this later */
2059 g_object_set_data (G_OBJECT (menu_bar), "accel", accel_group);
2061 g_signal_connect (G_OBJECT (menu_bar), "can-activate-accel",
2062 G_CALLBACK (menu_canacaccel), 0);
2064 /* set the initial state of toggles */
2065 mymenu[MENUBAR_OFFSET].state = !prefs.hidemenu;
2066 mymenu[MENUBAR_OFFSET+1].state = prefs.topicbar;
2067 mymenu[MENUBAR_OFFSET+2].state = !prefs.hideuserlist;
2068 mymenu[MENUBAR_OFFSET+3].state = prefs.userlistbuttons;
2069 mymenu[MENUBAR_OFFSET+4].state = prefs.chanmodebuttons;
2071 mymenu[AWAY_OFFSET].state = away;
2073 switch (prefs.tab_layout)
2075 case 0:
2076 mymenu[TABS_OFFSET].state = 1;
2077 mymenu[TABS_OFFSET+1].state = 0;
2078 break;
2079 default:
2080 mymenu[TABS_OFFSET].state = 0;
2081 mymenu[TABS_OFFSET+1].state = 1;
2084 mymenu[METRE_OFFSET].state = 0;
2085 mymenu[METRE_OFFSET+1].state = 0;
2086 mymenu[METRE_OFFSET+2].state = 0;
2087 mymenu[METRE_OFFSET+3].state = 0;
2088 switch (prefs.lagometer)
2090 case 0:
2091 mymenu[METRE_OFFSET].state = 1;
2092 break;
2093 case 1:
2094 mymenu[METRE_OFFSET+1].state = 1;
2095 break;
2096 case 2:
2097 mymenu[METRE_OFFSET+2].state = 1;
2098 break;
2099 default:
2100 mymenu[METRE_OFFSET+3].state = 1;
2103 /* change Close binding to ctrl-shift-w when using emacs keys */
2104 settings = gtk_widget_get_settings (menu_bar);
2105 if (settings)
2107 g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
2108 if (key_theme)
2110 if (!strcasecmp (key_theme, "Emacs"))
2112 close_mask = GDK_SHIFT_MASK | GDK_CONTROL_MASK;
2113 mymenu[SEARCH_OFFSET].key = 0;
2115 g_free (key_theme);
2119 /* Away binding to ctrl-alt-a if the _Help menu conflicts (FR/PT/IT) */
2121 char *help = _("_Help");
2122 char *under = strchr (help, '_');
2123 if (under && (under[1] == 'a' || under[1] == 'A'))
2124 away_mask = GDK_MOD1_MASK | GDK_CONTROL_MASK;
2127 if (!toplevel)
2129 mymenu[DETACH_OFFSET].text = N_("_Detach");
2130 mymenu[CLOSE_OFFSET].text = N_("_Close");
2132 else
2134 mymenu[DETACH_OFFSET].text = N_("_Attach");
2135 mymenu[CLOSE_OFFSET].text = N_("_Close");
2138 while (1)
2140 item = NULL;
2141 if (mymenu[i].id == MENU_ID_USERMENU && !prefs.gui_usermenu)
2143 i++;
2144 continue;
2147 switch (mymenu[i].type)
2149 case M_NEWMENU:
2150 if (menu)
2151 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2152 item = menu = gtk_menu_new ();
2153 if (mymenu[i].id == MENU_ID_USERMENU)
2154 usermenu = menu;
2155 menu_item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2156 /* record the English name for /menu */
2157 g_object_set_data (G_OBJECT (menu_item), "name", mymenu[i].text);
2158 gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
2159 gtk_widget_show (menu_item);
2160 break;
2162 case M_MENUPIX:
2163 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, FALSE);
2164 goto normalitem;
2166 case M_MENUSTOCK:
2167 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2168 goto normalitem;
2170 case M_MENUITEM:
2171 item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
2172 normalitem:
2173 if (mymenu[i].key != 0)
2174 gtk_widget_add_accelerator (item, "activate", accel_group,
2175 mymenu[i].key,
2176 mymenu[i].key == GDK_F1 ? 0 :
2177 mymenu[i].key == GDK_w ? close_mask :
2178 GDK_CONTROL_MASK,
2179 GTK_ACCEL_VISIBLE);
2180 if (mymenu[i].callback)
2181 g_signal_connect (G_OBJECT (item), "activate",
2182 G_CALLBACK (mymenu[i].callback), 0);
2183 if (submenu)
2184 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2185 else
2186 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2187 gtk_widget_show (item);
2188 break;
2190 case M_MENUTOG:
2191 item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
2192 togitem:
2193 /* must avoid callback for Radio buttons */
2194 GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
2195 /*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
2196 mymenu[i].state);*/
2197 if (mymenu[i].key != 0)
2198 gtk_widget_add_accelerator (item, "activate", accel_group,
2199 mymenu[i].key, mymenu[i].id == MENU_ID_AWAY ?
2200 away_mask : GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
2201 if (mymenu[i].callback)
2202 g_signal_connect (G_OBJECT (item), "toggled",
2203 G_CALLBACK (mymenu[i].callback), 0);
2204 if (submenu)
2205 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2206 else
2207 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2208 gtk_widget_show (item);
2209 gtk_widget_set_sensitive (item, mymenu[i].sensitive);
2210 break;
2212 case M_MENURADIO:
2213 item = gtk_radio_menu_item_new_with_mnemonic (group, _(mymenu[i].text));
2214 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
2215 goto togitem;
2217 case M_SEP:
2218 item = gtk_menu_item_new ();
2219 gtk_widget_set_sensitive (item, FALSE);
2220 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2221 gtk_widget_show (item);
2222 break;
2224 case M_MENUSUB:
2225 group = NULL;
2226 submenu = gtk_menu_new ();
2227 item = create_icon_menu (_(mymenu[i].text), mymenu[i].image, TRUE);
2228 /* record the English name for /menu */
2229 g_object_set_data (G_OBJECT (item), "name", mymenu[i].text);
2230 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
2231 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2232 gtk_widget_show (item);
2233 break;
2235 /*case M_END:*/ default:
2236 if (!submenu)
2238 if (menu)
2240 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
2241 menu_add_plugin_mainmenu_items (menu_bar);
2243 if (usermenu)
2244 usermenu_create (usermenu);
2245 return (menu_bar);
2247 submenu = NULL;
2250 /* record this GtkWidget * so it's state might be changed later */
2251 if (mymenu[i].id != 0 && menu_widgets)
2252 /* this ends up in sess->gui->menu_item[MENU_ID_XXX] */
2253 menu_widgets[mymenu[i].id] = item;
2255 i++;