cvsimport
[fvwm.git] / modules / FvwmGtk / menu.c
blobc117a4fc0fe3123b3e550ebc56851c42029691be
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
19 #include <stdio.h>
20 #include <unistd.h>
22 #include <X11/Xlib.h>
23 #include <X11/keysym.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xproto.h>
26 #include <X11/Xatom.h>
27 #include <X11/Intrinsic.h>
29 #include <glib.h>
30 #include <gtk/gtk.h>
31 #include <gdk/gdk.h>
32 #include <gdk/gdkprivate.h>
33 #include "gtkpixmapmenuitem.h"
34 #ifdef GDK_IMLIB
35 #include <gdk_imlib.h>
36 #endif
38 #include "libs/fvwmlib.h"
39 #include "libs/Module.h"
40 #include "libs/PictureBase.h"
43 extern int fvwm_fd[2];
44 extern char *image_path;
45 extern GHashTable *widgets;
46 extern GtkWidget *current;
47 extern GtkWidget *attach_to_toplevel;
48 extern unsigned long context;
49 extern int icon_w, icon_h;
52 static void
53 send_item (GtkWidget *item, char *s)
55 SendText (fvwm_fd, s, context);
59 static void
60 detacher (GtkWidget *attach, GtkMenu *menu)
65 GtkWidget*
66 find_or_create_menu (char *name)
68 GtkWidget *menu;
69 char *name_copy;
71 menu = g_hash_table_lookup (widgets, name);
73 if (menu == NULL)
75 menu = gtk_menu_new ();
76 gtk_menu_attach_to_widget (GTK_MENU (menu),
77 attach_to_toplevel, detacher);
78 gtk_widget_set_name (menu, name);
79 name_copy = gtk_widget_get_name (menu);
80 gtk_object_ref (GTK_OBJECT (menu));
81 gtk_object_sink (GTK_OBJECT (menu));
82 g_hash_table_insert (widgets, name_copy, menu);
83 gtk_object_ref (GTK_OBJECT (menu));
85 if (GTK_IS_MENU (menu))
87 return menu;
89 else
91 fprintf (stderr, "%s is not a menu\n", name);
92 return NULL;
97 /* from gtkcauldron.c */
98 /* result must be g_free'd */
99 static gchar *
100 convert_label_with_ampersand (const gchar * _label,
101 gint * accelerator_key,
102 gint * underbar_pos)
104 gchar *p;
105 gchar *label = g_strdup (_label);
106 for (p = label;; p++) {
107 if (!*p)
108 break;
109 if (!p[1])
110 break;
111 if (*p == '&') {
112 memmove (p, p + 1, strlen (p));
113 if (*p == '&') /* use && for an actual & */
114 continue;
115 *underbar_pos = (unsigned long) p - (unsigned long) label;
116 *accelerator_key = *p;
117 return label;
120 return label;
124 /* from gtkcauldron.c */
125 static gchar *
126 create_label_pattern (gchar * label, gint underbar_pos)
128 gchar *pattern;
129 pattern = g_strdup (label);
130 memset (pattern, ' ', strlen (label));
131 if (underbar_pos < strlen (pattern) && underbar_pos >= 0)
132 pattern[underbar_pos] = '_';
133 return pattern;
137 /* from gnome-app-helper.c */
138 static GtkAccelGroup *
139 get_menu_accel_group (GtkMenuShell *menu_shell)
141 GtkAccelGroup *ag;
143 ag = gtk_object_get_data (GTK_OBJECT (menu_shell),
144 "gnome_menu_accel_group");
146 if (!ag) {
147 ag = gtk_accel_group_new ();
148 gtk_accel_group_attach (ag, GTK_OBJECT (menu_shell));
149 gtk_object_set_data (GTK_OBJECT (menu_shell),
150 "gnome_menu_accel_group", ag);
153 return ag;
157 GtkWidget *
158 menu_item_new_with_pixmap_and_label (char *file, char *l_label, char *r_label)
160 GtkWidget *item, *label, *icon, *box;
161 GdkPixmap *pixmap = NULL;
162 GdkBitmap *mask = NULL;
163 char *path;
164 gint accel_key = 0, underbar_pos = -1;
165 gchar *pattern, *converted_label;
166 #ifdef GDK_IMLIB
167 GdkImlibImage *im;
168 int w, h;
169 #endif
171 path = PictureFindImageFile (file ? file : "", image_path, R_OK);
173 if (path == NULL)
175 item = gtk_menu_item_new ();
177 else
179 #ifdef GDK_IMLIB
180 im = gdk_imlib_load_image (path);
181 if (im)
183 if (icon_w == 0 || icon_h == 0)
185 w = im->rgb_width;
186 h = im->rgb_height;
188 else
190 w = icon_w;
191 h = icon_h;
193 gdk_imlib_render (im, w, h);
194 pixmap = gdk_imlib_move_image (im);
195 mask = gdk_imlib_move_mask (im);
197 #else
198 pixmap = gdk_pixmap_create_from_xpm (NULL, &mask, NULL, path);
199 #endif
200 if (pixmap)
202 item = gtk_pixmap_menu_item_new ();
203 icon = gtk_pixmap_new (pixmap, mask);
204 gtk_pixmap_menu_item_set_pixmap (GTK_PIXMAP_MENU_ITEM (item), icon);
205 gtk_widget_show (icon);
207 else
209 item = gtk_menu_item_new ();
212 free (path);
215 converted_label = convert_label_with_ampersand (l_label, &accel_key,
216 &underbar_pos);
217 label = gtk_label_new (converted_label);
218 if (underbar_pos != -1)
220 GtkAccelGroup *accel_group =
221 get_menu_accel_group (GTK_MENU_SHELL (current));
223 pattern = create_label_pattern (converted_label, underbar_pos);
224 gtk_label_set_pattern (GTK_LABEL (label), pattern);
226 gtk_widget_add_accelerator (item, "activate_item",
227 accel_group, accel_key, 0, 0);
229 g_free (converted_label);
231 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
232 if (r_label)
234 box = gtk_hbox_new (0, 0);
235 gtk_box_pack_start (GTK_BOX (box), label, 0, 1, 0);
236 label = gtk_label_new (r_label);
237 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
238 gtk_box_pack_end (GTK_BOX (box), label, 0, 1, 0);
239 gtk_container_add (GTK_CONTAINER (item), box);
240 gtk_widget_show_all (box);
242 else
244 gtk_container_add (GTK_CONTAINER (item), label);
245 gtk_widget_show (label);
248 return item;
252 void
253 open_menu (int argc, char **argv)
255 g_return_if_fail (argc > 0);
257 current = find_or_create_menu (argv[0]);
261 void
262 menu_title (int argc, char **argv)
264 GtkWidget *item;
266 g_return_if_fail (argc > 0);
268 item = menu_item_new_with_pixmap_and_label
269 (argc > 1 ? argv[1] : NULL, argv[0], argc > 2 ? argv[2] : NULL);
270 gtk_menu_append (GTK_MENU (current), item);
271 gtk_widget_show (item);
273 This is a hack stolen from the Gnome panel. There ought
274 to be a better way.
276 gtk_signal_connect
277 (GTK_OBJECT (item), "select",
278 GTK_SIGNAL_FUNC (gtk_menu_item_deselect), NULL);
282 void
283 menu_separator (int argc, char **argv)
285 GtkWidget *item;
287 item = gtk_menu_item_new ();
288 gtk_menu_append (GTK_MENU (current), item);
289 gtk_widget_show (item);
290 gtk_widget_set_sensitive (item, 0);
294 void
295 menu_item (int argc, char **argv)
297 GtkWidget *item;
299 g_return_if_fail (argc > 1);
301 item = menu_item_new_with_pixmap_and_label
302 (argc > 2 ? argv[2] : NULL, argv[0], argc > 3 ? argv[3] : NULL);
303 gtk_menu_append (GTK_MENU (current), item);
304 gtk_widget_show (item);
305 gtk_signal_connect
306 (GTK_OBJECT (item), "activate",
307 GTK_SIGNAL_FUNC (send_item), safestrdup (argv[1]));
311 void
312 menu_tearoff_item (int argc, char **argv)
314 GtkWidget *item;
316 item = gtk_tearoff_menu_item_new ();
318 gtk_menu_append (GTK_MENU (current), item);
319 gtk_widget_show (item);
323 void
324 menu_submenu (int argc, char **argv)
326 GtkWidget *item, *submenu;
328 item = menu_item_new_with_pixmap_and_label
329 (argc > 2 ? argv[2] : NULL, argv[0], NULL);
330 gtk_menu_append (GTK_MENU (current), item);
331 gtk_widget_show (item);
332 submenu = find_or_create_menu (argv[1]);
334 gtk_menu_detach (GTK_MENU (submenu));
335 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);