Mercurial > hg > xemacs-beta
annotate src/menubar-gtk.c @ 4976:16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-04 Ben Wing <ben@xemacs.org>
* alloc.c (release_breathing_space):
* alloc.c (resize_string):
* alloc.c (sweep_lcrecords_1):
* alloc.c (SWEEP_FIXED_TYPE_BLOCK_1):
* alloc.c (ADDITIONAL_FREE_compiled_function):
* alloc.c (compact_string_chars):
* alloc.c (ADDITIONAL_FREE_string):
* alloc.c (sweep_strings):
* alloca.c (xemacs_c_alloca):
* alsaplay.c (alsa_play_sound_file):
* buffer.c (init_initial_directory):
* buffer.h:
* buffer.h (BUFFER_FREE):
* console-stream.c (stream_delete_console):
* console-tty.c (free_tty_console_struct):
* data.c (Fnumber_to_string):
* device-gtk.c (gtk_init_device):
* device-gtk.c (free_gtk_device_struct):
* device-gtk.c (gtk_delete_device):
* device-msw.c (mswindows_delete_device):
* device-msw.c (msprinter_delete_device):
* device-tty.c (free_tty_device_struct):
* device-tty.c (tty_delete_device):
* device-x.c (x_init_device):
* device-x.c (free_x_device_struct):
* device-x.c (x_delete_device):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-x.c (dbox_descriptor_to_widget_value):
* dired-msw.c (Fmswindows_insert_directory):
* dired.c (free_user_cache):
* dired.c (user_name_completion_unwind):
* doc.c (unparesseuxify_doc_string):
* doc.c (Fsubstitute_command_keys):
* doprnt.c (emacs_doprnt_1):
* dumper.c (pdump_load_finish):
* dumper.c (pdump_file_free):
* dumper.c (pdump_file_unmap):
* dynarr.c:
* dynarr.c (Dynarr_free):
* editfns.c (uncache_home_directory):
* editfns.c (Fset_time_zone_rule):
* elhash.c:
* elhash.c (pdump_reorganize_hash_table):
* elhash.c (maphash_unwind):
* emacs.c (make_arg_list_1):
* emacs.c (free_argc_argv):
* emacs.c (sort_args):
* emacs.c (Frunning_temacs_p):
* emodules.c (attempt_module_delete):
* eval.c (free_pointer):
* event-Xt.c (unselect_filedesc):
* event-Xt.c (emacs_Xt_select_process):
* event-gtk.c (unselect_filedesc):
* event-gtk.c (dragndrop_data_received):
* event-msw.c (winsock_closer):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* event-stream.c (finalize_command_builder):
* event-stream.c (free_command_builder):
* extents.c (free_gap_array):
* extents.c (free_extent_list):
* extents.c (free_soe):
* extents.c (extent_fragment_delete):
* extents.c (extent_priority_sort_function):
* file-coding.c (make_coding_system_1):
* file-coding.c (coding_finalizer):
* file-coding.c (set_coding_stream_coding_system):
* file-coding.c (chain_finalize_coding_stream_1):
* file-coding.c (chain_finalize):
* file-coding.c (free_detection_state):
* file-coding.c (coding_category_symbol_to_id):
* fileio.c:
* fileio.c (Ffile_name_directory):
* fileio.c (if):
* fileio.c (Ffile_symlink_p):
* filelock.c (FREE_LOCK_INFO):
* filelock.c (current_lock_owner):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* frame-gtk.c (gtk_delete_frame):
* frame-msw.c (mswindows_delete_frame):
* frame-msw.c (msprinter_delete_frame):
* frame-x.c (x_cde_destroy_callback):
* frame-x.c (Fcde_start_drag_internal):
* frame-x.c (x_cde_transfer_callback):
* frame-x.c (x_delete_frame):
* frame.c (update_frame_title):
* frame.c (Fset_frame_pointer):
* gc.c (register_for_finalization):
* gccache-gtk.c (free_gc_cache):
* gccache-gtk.c (gc_cache_lookup):
* gccache-x.c (free_gc_cache):
* gccache-x.c (gc_cache_lookup):
* glyphs-eimage.c:
* glyphs-eimage.c (jpeg_instantiate_unwind):
* glyphs-eimage.c (gif_instantiate_unwind):
* glyphs-eimage.c (png_instantiate_unwind):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate_unwind):
* glyphs-gtk.c (convert_EImage_to_GDKImage):
* glyphs-gtk.c (gtk_finalize_image_instance):
* glyphs-gtk.c (gtk_init_image_instance_from_eimage):
* glyphs-gtk.c (gtk_xpm_instantiate):
* glyphs-msw.c (convert_EImage_to_DIBitmap):
* glyphs-msw.c (mswindows_init_image_instance_from_eimage):
* glyphs-msw.c (mswindows_initialize_image_instance_mask):
* glyphs-msw.c (xpm_to_eimage):
* glyphs-msw.c (mswindows_xpm_instantiate):
* glyphs-msw.c (xbm_create_bitmap_from_data):
* glyphs-msw.c (mswindows_finalize_image_instance):
* glyphs-x.c (convert_EImage_to_XImage):
* glyphs-x.c (x_finalize_image_instance):
* glyphs-x.c (x_init_image_instance_from_eimage):
* glyphs-x.c (x_xpm_instantiate):
* gui-x.c (free_popup_widget_value_tree):
* hash.c (free_hash_table):
* hash.c (grow_hash_table):
* hash.c (pregrow_hash_table_if_necessary):
* imgproc.c (build_EImage_quantable):
* insdel.c (uninit_buffer_text):
* intl-win32.c (convert_multibyte_to_internal_malloc):
* intl.c:
* intl.c (Fset_current_locale):
* keymap.c:
* keymap.c (where_is_recursive_mapper):
* keymap.c (where_is_internal):
* lisp.h:
* lisp.h (xfree):
* lstream.c (Lstream_close):
* lstream.c (resizing_buffer_closer):
* mule-coding.c:
* mule-coding.c (iso2022_finalize_detection_state):
* nt.c:
* nt.c (mswindows_get_long_filename):
* nt.c (nt_get_resource):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_opendir):
* nt.c (mswindows_closedir):
* nt.c (mswindows_readdir):
* nt.c (mswindows_stat):
* nt.c (mswindows_getdcwd):
* nt.c (Fmswindows_long_file_name):
* ntplay.c (nt_play_sound_file):
* ntplay.c (play_sound_data_1):
* number-gmp.c (gmp_free):
* number-gmp.c (init_number_gmp):
* number-mp.c (bignum_to_string):
* number-mp.c (BIGNUM_TO_TYPE):
* number.c (bignum_print):
* number.c (bignum_convfree):
* number.c (ratio_print):
* number.c (bigfloat_print):
* number.c (bigfloat_finalize):
* objects-gtk.c (gtk_finalize_color_instance):
* objects-gtk.c (gtk_finalize_font_instance):
* objects-msw.c (mswindows_finalize_color_instance):
* objects-msw.c (mswindows_finalize_font_instance):
* objects-tty.c (tty_finalize_color_instance):
* objects-tty.c (tty_finalize_font_instance):
* objects-tty.c (tty_font_list):
* objects-x.c (x_finalize_color_instance):
* objects-x.c (x_finalize_font_instance):
* process.c:
* process.c (finalize_process):
* realpath.c:
* redisplay.c (add_propagation_runes):
* regex.c:
* regex.c (xfree):
* regex.c (REGEX_FREE_STACK):
* regex.c (FREE_STACK_RETURN):
* regex.c (regex_compile):
* regex.c (regexec):
* regex.c (regfree):
* scrollbar-gtk.c (gtk_free_scrollbar_instance):
* scrollbar-gtk.c (gtk_release_scrollbar_instance):
* scrollbar-msw.c (mswindows_free_scrollbar_instance):
* scrollbar-msw.c (unshow_that_mofo):
* scrollbar-x.c (x_free_scrollbar_instance):
* scrollbar-x.c (x_release_scrollbar_instance):
* select-gtk.c (emacs_gtk_selection_handle):
* select-msw.c (mswindows_own_selection):
* select-x.c:
* select-x.c (x_handle_selection_request):
* select-x.c (unexpect_property_change):
* select-x.c (x_handle_property_notify):
* select-x.c (receive_incremental_selection):
* select-x.c (x_get_window_property_as_lisp_data):
* select-x.c (Fx_get_cutbuffer_internal):
* specifier.c (finalize_specifier):
* syntax.c (uninit_buffer_syntax_cache):
* sysdep.c (qxe_allocating_getcwd):
* sysdep.c (qxe_lstat):
* sysdep.c (copy_in_passwd):
* sysdep.c (qxe_ctime):
* sysdep.c (closedir):
* sysdep.c (DIRSIZ):
* termcap.c (tgetent):
* termcap.c (tprint):
* tests.c (Ftest_data_format_conversion):
* text.c (new_dfc_convert_copy_data):
* text.h (eifree):
* text.h (eito_alloca):
* text.h (eito_external):
* toolbar-msw.c (mswindows_output_toolbar):
* ui-gtk.c (CONVERT_RETVAL):
* ui-gtk.c (__allocate_object_storage):
* unicode.c (free_from_unicode_table):
* unicode.c (free_to_unicode_table):
* unicode.c (free_charset_unicode_tables):
* win32.c (mswindows_read_link_1):
Rename: xfree(VAL, TYPE)->xfree(VAL)
Command used:
gr 'xfree *\((.*),.*\);' 'xfree (\1);' *.[ch]
Followed by grepping for 'xfree.*,' and fixing anything left.
Rationale: Having to specify the TYPE argument is annoying and
error-prone. It was originally put in to work around warnings
due to strict aliasing but years and years ago I rewrote it
in a way that doesn't use the TYPE argument at all and no one
has complained since then. (And anyway, XEmacs is far from
ever being in compliance with strict aliasing and would require
far-reaching changes to get that way.)
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 04 Feb 2010 07:28:14 -0600 |
parents | 8f1ee2d15784 |
children | 4aebb0131297 |
rev | line source |
---|---|
2081 | 1 /* Implements an elisp-programmable menubar -- Gtk interface. |
462 | 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. |
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | |
1346 | 4 Copyright (C) 2002, 2003 Ben Wing. |
462 | 5 |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 /* created 16-dec-91 by jwz */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
30 #include "buffer.h" | |
31 #include "commands.h" /* zmacs_regions */ | |
1346 | 32 #include "device-impl.h" |
462 | 33 #include "events.h" |
872 | 34 #include "frame-impl.h" |
35 #include "gui.h" | |
462 | 36 #include "opaque.h" |
37 #include "window.h" | |
876 | 38 #include "window-impl.h" |
462 | 39 |
872 | 40 #include "console-gtk-impl.h" |
41 #include "ui-gtk.h" | |
876 | 42 #include "menubar.h" |
872 | 43 |
462 | 44 #ifdef HAVE_GNOME |
45 #include <libgnomeui/libgnomeui.h> | |
46 #endif | |
47 | |
48 #define MENUBAR_TYPE 0 | |
49 #define SUBMENU_TYPE 1 | |
50 #define POPUP_TYPE 2 | |
51 | |
2081 | 52 static GtkWidget *menu_descriptor_to_widget_1 (Lisp_Object descr, GtkAccelGroup* accel_group); |
462 | 53 |
1346 | 54 #define FRAME_GTK_MENUBAR_DATA(f) (FRAME_GTK_DATA (f)->menubar_data) |
55 #define XFRAME_GTK_MENUBAR_DATA_LASTBUFF(f) XCAR (FRAME_GTK_MENUBAR_DATA (f)) | |
56 #define XFRAME_GTK_MENUBAR_DATA_UPTODATE(f) XCDR (FRAME_GTK_MENUBAR_DATA (f)) | |
462 | 57 |
58 | |
59 /* This is a bogus subclass of GtkMenuBar so that the menu never tries | |
60 ** to be bigger than the text widget. This prevents weird resizing | |
61 ** when jumping around between buffers with radically different menu | |
62 ** sizes. | |
63 */ | |
64 | |
65 #define GTK_XEMACS_MENUBAR(obj) GTK_CHECK_CAST (obj, gtk_xemacs_menubar_get_type (), GtkXEmacsMenubar) | |
66 #define GTK_XEMACS_MENUBAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_xemacs_menubar_get_type (), GtkXEmacsMenubarClass) | |
67 #define GTK_IS_XEMACS_MENUBAR(obj) GTK_CHECK_TYPE (obj, gtk_xemacs_menubar_get_type ()) | |
68 #define GTK_XEMACS_MENUBAR_FRAME(obj) GTK_XEMACS_MENUBAR (obj)->f | |
69 | |
70 typedef struct _GtkXEmacsMenubar GtkXEmacsMenubar; | |
71 typedef struct _GtkXEmacsMenubarClass GtkXEmacsMenubarClass; | |
72 | |
73 struct _GtkXEmacsMenubar | |
74 { | |
75 GtkMenuBar menu; | |
76 struct frame *frame; | |
77 }; | |
78 | |
79 struct _GtkXEmacsMenubarClass | |
80 { | |
81 GtkMenuBarClass parent_class; | |
82 }; | |
83 | |
84 guint gtk_xemacs_menubar_get_type (void); | |
85 GtkWidget *gtk_xemacs_menubar_new (struct frame *f); | |
86 | |
87 static void gtk_xemacs_menubar_class_init (GtkXEmacsMenubarClass *klass); | |
88 static void gtk_xemacs_menubar_init (GtkXEmacsMenubar *xemacs); | |
89 static void gtk_xemacs_menubar_size_request (GtkWidget *widget, GtkRequisition *requisition); | |
90 | |
91 guint | |
92 gtk_xemacs_menubar_get_type (void) | |
93 { | |
94 static guint xemacs_menubar_type; | |
95 | |
96 if (!xemacs_menubar_type) | |
97 { | |
98 static const GtkTypeInfo xemacs_menubar_info = | |
99 { | |
100 "GtkXEmacsMenubar", | |
101 sizeof (GtkXEmacsMenubar), | |
102 sizeof (GtkXEmacsMenubarClass), | |
103 (GtkClassInitFunc) gtk_xemacs_menubar_class_init, | |
104 (GtkObjectInitFunc) gtk_xemacs_menubar_init, | |
105 /* reserved_1 */ NULL, | |
106 /* reserved_2 */ NULL, | |
107 (GtkClassInitFunc) NULL, | |
108 }; | |
109 | |
110 xemacs_menubar_type = gtk_type_unique (gtk_menu_bar_get_type (), &xemacs_menubar_info); | |
111 } | |
112 | |
113 return xemacs_menubar_type; | |
114 } | |
115 | |
2081 | 116 static GtkWidgetClass *menubar_parent_class; |
462 | 117 |
1416 | 118 static void |
119 gtk_xemacs_menubar_class_init (GtkXEmacsMenubarClass *klass) | |
462 | 120 { |
121 GtkWidgetClass *widget_class; | |
122 | |
123 widget_class = (GtkWidgetClass*) klass; | |
2081 | 124 menubar_parent_class = (GtkWidgetClass *) gtk_type_class (gtk_menu_bar_get_type ()); |
462 | 125 |
126 widget_class->size_request = gtk_xemacs_menubar_size_request; | |
127 } | |
128 | |
1416 | 129 static void |
2286 | 130 gtk_xemacs_menubar_init (GtkXEmacsMenubar *UNUSED (xemacs)) |
462 | 131 { |
132 } | |
133 | |
1416 | 134 static void |
135 gtk_xemacs_menubar_size_request (GtkWidget *widget, GtkRequisition *requisition) | |
462 | 136 { |
137 GtkXEmacsMenubar *x = GTK_XEMACS_MENUBAR (widget); | |
138 GtkRequisition frame_size; | |
139 | |
2081 | 140 menubar_parent_class->size_request (widget, requisition); |
462 | 141 |
142 /* #### BILL! | |
143 ** We should really only do this if the menu has not been detached! | |
144 ** | |
145 ** WMP 9/9/2000 | |
146 */ | |
147 | |
148 gtk_widget_size_request (FRAME_GTK_TEXT_WIDGET (x->frame), &frame_size); | |
149 | |
150 requisition->width = frame_size.width; | |
151 } | |
152 | |
153 GtkWidget * | |
154 gtk_xemacs_menubar_new (struct frame *f) | |
155 { | |
2054 | 156 GtkXEmacsMenubar *menubar = (GtkXEmacsMenubar*) gtk_type_new (gtk_xemacs_menubar_get_type ()); |
462 | 157 |
158 menubar->frame = f; | |
159 | |
160 return (GTK_WIDGET (menubar)); | |
161 } | |
162 | |
2081 | 163 /* |
164 * Label with XEmacs accelerator character support. | |
165 * | |
166 * The default interfaces to GtkAccelLabel does not understand XEmacs | |
167 * keystroke printing conventions, nor is it convenient in the places where is | |
168 * it needed. This subclass provides an alternative interface more suited to | |
169 * XEmacs needs but does not add new functionality. | |
170 */ | |
171 #define GTK_TYPE_XEMACS_ACCEL_LABEL (gtk_xemacs_accel_label_get_type ()) | |
172 #define GTK_XEMACS_ACCEL_LABEL(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_ACCEL_LABEL, GtkXEmacsAccelLabel)) | |
173 #define GTK_XEMACS_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_LABEL, GtkXEmacsAccelLabelClass)) | |
174 #define GTK_IS_XEMACS_ACCEL_LABEL(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_XEMACS_ACCEL_LABEL)) | |
175 #define GTK_IS_XEMACS_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XEMACS_ACCEL_LABEL)) | |
176 | |
177 typedef struct _GtkXEmacsAccelLabel GtkXEmacsAccelLabel; | |
178 typedef struct _GtkXEmacsAccelLabelClass GtkXEmacsAccelLabelClass; | |
179 | |
180 /* Instance structure. No additional fields required. */ | |
181 struct _GtkXEmacsAccelLabel | |
182 { | |
183 GtkAccelLabel label; | |
184 }; | |
185 | |
186 /* Class structure. No additional fields required. */ | |
187 struct _GtkXEmacsAccelLabelClass | |
188 { | |
189 GtkAccelLabelClass parent_class; | |
190 }; | |
191 | |
192 static GtkType gtk_xemacs_accel_label_get_type(void); | |
193 static GtkWidget* gtk_xemacs_accel_label_new(const gchar *string); | |
194 static void gtk_xemacs_set_accel_keys(GtkXEmacsAccelLabel* l, | |
195 Lisp_Object keys); | |
196 static void gtk_xemacs_accel_label_class_init(GtkXEmacsAccelLabelClass *klass); | |
197 static void gtk_xemacs_accel_label_init(GtkXEmacsAccelLabel *xemacs); | |
198 | |
199 static GtkType | |
200 gtk_xemacs_accel_label_get_type(void) | |
201 { | |
202 static GtkType xemacs_accel_label_type = 0; | |
203 | |
204 if (!xemacs_accel_label_type) | |
205 { | |
206 static const GtkTypeInfo xemacs_accel_label_info = | |
207 { | |
208 "GtkXEmacsAccelLabel", | |
209 sizeof (GtkXEmacsAccelLabel), | |
210 sizeof (GtkXEmacsAccelLabelClass), | |
211 (GtkClassInitFunc) gtk_xemacs_accel_label_class_init, | |
212 (GtkObjectInitFunc) gtk_xemacs_accel_label_init, | |
213 /* reserved_1 */ NULL, | |
214 /* reserved_2 */ NULL, | |
215 (GtkClassInitFunc) NULL, | |
216 }; | |
217 | |
218 xemacs_accel_label_type = gtk_type_unique (gtk_accel_label_get_type(), &xemacs_accel_label_info); | |
219 } | |
220 | |
221 return xemacs_accel_label_type; | |
222 } | |
223 | |
224 static void | |
2286 | 225 gtk_xemacs_accel_label_class_init(GtkXEmacsAccelLabelClass *UNUSED (klass)) |
2081 | 226 { |
227 /* Nothing to do. */ | |
228 } | |
229 | |
230 static void | |
2286 | 231 gtk_xemacs_accel_label_init(GtkXEmacsAccelLabel *UNUSED (xemacs)) |
2081 | 232 { |
233 /* Nothing to do. */ | |
234 } | |
235 | |
236 static GtkWidget* | |
237 gtk_xemacs_accel_label_new (const gchar *string) | |
238 { | |
239 GtkXEmacsAccelLabel *xemacs_accel_label; | |
240 | |
241 xemacs_accel_label = (GtkXEmacsAccelLabel*) gtk_type_new (GTK_TYPE_XEMACS_ACCEL_LABEL); | |
242 | |
243 if (string && *string) | |
244 gtk_label_set_text (GTK_LABEL (xemacs_accel_label), string); | |
245 | |
246 return GTK_WIDGET (xemacs_accel_label); | |
247 } | |
248 | |
249 /* Make the string <keys> the accelerator string for the label. */ | |
250 static void | |
251 gtk_xemacs_set_accel_keys(GtkXEmacsAccelLabel* l, Lisp_Object keys) | |
252 { | |
253 g_return_if_fail (l != NULL); | |
254 g_return_if_fail (GTK_IS_XEMACS_ACCEL_LABEL (l)); | |
255 | |
256 /* Disable the standard way of finding the accelerator string for the | |
257 label. */ | |
258 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL(l), NULL); | |
259 | |
260 /* Set the string straight from the object. */ | |
261 if (STRINGP (keys) && XSTRING_LENGTH (keys)) | |
262 { | |
263 C_STRING_TO_EXTERNAL_MALLOC(XSTRING_DATA (keys), | |
264 l->label.accel_string, | |
265 Qctext); | |
266 } | |
267 else | |
268 { | |
269 /* l->label.accel_string = NULL;*/ | |
270 } | |
271 } | |
272 | |
273 | |
462 | 274 /* We now return you to your regularly scheduled menus... */ |
275 | |
276 int dockable_menubar; | |
277 | |
278 /* #define TEAR_OFF_MENUS */ | |
279 | |
280 #ifdef TEAR_OFF_MENUS | |
281 int tear_off_menus; | |
282 #endif | |
283 | |
284 | |
285 /* Converting from XEmacs to GTK representation */ | |
286 static Lisp_Object | |
2054 | 287 menu_name_to_accelerator (Ibyte *name) |
462 | 288 { |
289 while (*name) { | |
290 if (*name=='%') { | |
291 ++name; | |
292 if (!(*name)) | |
293 return Qnil; | |
294 if (*name=='_' && *(name+1)) | |
295 { | |
2054 | 296 int accelerator = (int) (*(name+1)); |
462 | 297 return make_char (tolower (accelerator)); |
298 } | |
299 } | |
300 ++name; | |
301 } | |
302 return Qnil; | |
303 } | |
304 | |
305 #define XEMACS_MENU_DESCR_TAG "xemacs::menu::description" | |
306 #define XEMACS_MENU_FILTER_TAG "xemacs::menu::filter" | |
307 #define XEMACS_MENU_GUIID_TAG "xemacs::menu::gui_id" | |
308 #define XEMACS_MENU_FIRSTTIME_TAG "xemacs::menu::first_time" | |
309 | |
310 static void __activate_menu(GtkMenuItem *, gpointer); | |
311 | |
312 #ifdef TEAR_OFF_MENUS | |
313 static void | |
2286 | 314 __torn_off_sir(GtkMenuItem *UNUSED (item), gpointer user_data) |
462 | 315 { |
316 GtkWidget *menu_item = GTK_WIDGET (user_data); | |
317 | |
318 if (GTK_TEAROFF_MENU_ITEM (item)->torn_off) | |
319 { | |
320 /* Menu was just torn off */ | |
321 GUI_ID id = new_gui_id (); | |
322 Lisp_Object menu_desc = Qnil; | |
323 GtkWidget *old_submenu = GTK_MENU_ITEM (menu_item)->submenu; | |
324 | |
826 | 325 menu_desc = VOID_TO_LISP (gtk_object_get_data (GTK_OBJECT (menu_item), XEMACS_MENU_DESCR_TAG)); |
462 | 326 |
327 /* GCPRO all of our very own */ | |
328 gcpro_popup_callbacks (id, menu_desc); | |
329 | |
330 /* Hide the now detached menu from the attentions of | |
331 __activate_menu destroying the old submenu */ | |
332 #if 0 | |
333 gtk_widget_ref (old_submenu); | |
334 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), gtk_menu_new ()); | |
335 gtk_widget_show_all (old_submenu); | |
336 #endif | |
337 } | |
338 } | |
339 #endif | |
340 | |
341 /* This is called when a menu is about to be shown... this is what | |
342 does the delayed creation of the menu items. We populate the | |
343 submenu and away we go. */ | |
344 static void | |
2286 | 345 __maybe_destroy (GtkWidget *child, GtkWidget *UNUSED (precious)) |
462 | 346 { |
347 if (GTK_IS_MENU_ITEM (child) && !GTK_IS_TEAROFF_MENU_ITEM (child)) | |
348 { | |
349 if (GTK_WIDGET_VISIBLE (child)) | |
350 { | |
351 /* If we delete the menu item that was 'active' when the | |
352 menu was cancelled, GTK gets upset because it tries to | |
353 remove the focus rectangle from a (now) dead widget. | |
354 | |
355 This widget will eventually get killed because it will | |
356 not be visible the next time the window is shown. | |
357 */ | |
358 gtk_widget_set_sensitive (child, FALSE); | |
359 gtk_widget_hide_all (child); | |
360 } | |
361 else | |
362 { | |
363 gtk_widget_destroy (child); | |
364 } | |
365 } | |
366 } | |
367 | |
368 /* If user_data != 0x00 then we are using a hook to build the menu. */ | |
369 static void | |
370 __activate_menu(GtkMenuItem *item, gpointer user_data) | |
371 { | |
372 Lisp_Object desc; | |
373 gpointer force_clear = gtk_object_get_data (GTK_OBJECT (item), XEMACS_MENU_FIRSTTIME_TAG); | |
374 | |
375 gtk_object_set_data (GTK_OBJECT (item), XEMACS_MENU_FIRSTTIME_TAG, 0x00); | |
376 | |
377 /* Delete the old contents of the menu if we are the top level menubar */ | |
378 if (GTK_IS_MENU_BAR (GTK_WIDGET (item)->parent) || force_clear) | |
379 { | |
380 GtkWidget *selected = gtk_menu_get_active (GTK_MENU (item->submenu)); | |
381 | |
382 gtk_container_foreach (GTK_CONTAINER (item->submenu),(GtkCallback) __maybe_destroy, | |
383 selected); | |
384 } | |
385 else if (gtk_container_children (GTK_CONTAINER (item->submenu))) | |
386 { | |
387 return; | |
388 } | |
389 | |
826 | 390 desc = VOID_TO_LISP (gtk_object_get_data (GTK_OBJECT (item), XEMACS_MENU_DESCR_TAG)); |
462 | 391 |
392 #ifdef TEAR_OFF_MENUS | |
393 /* Lets stick in a detacher just for giggles */ | |
394 if (tear_off_menus && !gtk_container_children (GTK_CONTAINER (item->submenu))) | |
395 { | |
396 GtkWidget *w = gtk_tearoff_menu_item_new (); | |
397 gtk_widget_show (w); | |
398 gtk_menu_append (GTK_MENU (item->submenu), w); | |
399 gtk_signal_connect (GTK_OBJECT (w), "activate", GTK_SIGNAL_FUNC (__torn_off_sir), item); | |
400 } | |
401 #endif | |
402 | |
403 if (user_data) | |
404 { | |
405 GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (item), XEMACS_MENU_GUIID_TAG); | |
406 Lisp_Object hook_fn; | |
407 struct gcpro gcpro1, gcpro2; | |
408 | |
826 | 409 hook_fn = VOID_TO_LISP (gtk_object_get_data (GTK_OBJECT (item), XEMACS_MENU_FILTER_TAG)); |
462 | 410 |
411 GCPRO2 (desc, hook_fn); | |
412 | |
413 desc = call1 (hook_fn, desc); | |
414 | |
415 UNGCPRO; | |
416 | |
417 ungcpro_popup_callbacks (id); | |
418 gcpro_popup_callbacks (id, desc); | |
419 } | |
420 | |
421 /* Build the child widgets */ | |
422 for (; !NILP (desc); desc = Fcdr (desc)) | |
423 { | |
424 GtkWidget *next = NULL; | |
425 Lisp_Object child = Fcar (desc); | |
426 | |
427 if (NILP (child)) /* the partition */ | |
428 { | |
429 /* Signal an error here? The NILP handling is handled a | |
430 layer higher where appropriate */ | |
431 } | |
432 else | |
433 { | |
2081 | 434 next = menu_descriptor_to_widget_1 (child, |
435 gtk_menu_ensure_uline_accel_group (GTK_MENU (item->submenu))); | |
462 | 436 } |
437 | |
438 if (!next) | |
439 { | |
440 continue; | |
441 } | |
442 | |
443 gtk_widget_show_all (next); | |
444 gtk_menu_append (GTK_MENU (item->submenu), next); | |
445 } | |
446 } | |
447 | |
448 /* This is called whenever an item with a GUI_ID associated with it is | |
449 destroyed. This allows us to remove the references in gui-gtk.c | |
450 that made sure callbacks and such were GCPRO-ed | |
451 */ | |
452 static void | |
453 __remove_gcpro_by_id (gpointer user_data) | |
454 { | |
455 ungcpro_popup_callbacks ((GUI_ID) user_data); | |
456 } | |
457 | |
458 static void | |
2286 | 459 __kill_stupid_gtk_timer (GtkObject *obj, gpointer UNUSED (user_data)) |
462 | 460 { |
461 GtkMenuItem *mi = GTK_MENU_ITEM (obj); | |
462 | |
463 if (mi->timer) | |
464 { | |
465 gtk_timeout_remove (mi->timer); | |
466 mi->timer = 0; | |
467 } | |
468 } | |
469 | |
2081 | 470 /* Convert the XEmacs menu accelerator representation to Gtk mnemonic form. If |
471 no accelerator has been provided, put one at the start of the string (this | |
472 mirrors the behaviour under X). This algorithm is also found in | |
473 dialog-gtk.el:gtk-popup-convert-underscores. | |
474 */ | |
462 | 475 static char * |
2081 | 476 convert_underscores(const Ibyte *name) |
462 | 477 { |
2081 | 478 char *rval; |
479 int i,j; | |
480 int found_accel = FALSE; | |
481 int underscores = 0; | |
482 | |
483 for (i = 0; name[i]; ++i) | |
484 if (name[i] == '%' && name[i+1] == '_') | |
485 { | |
486 found_accel = TRUE; | |
487 } | |
488 else if (name[i] == '_') | |
489 { | |
490 underscores++; | |
491 } | |
492 | |
493 /* Allocate space for the original string, plus zero byte plus extra space | |
494 for all quoted underscores plus possible additional leading accelerator. */ | |
495 rval = (char*) xmalloc_and_zero (qxestrlen(name) + 1 + underscores | |
496 + (found_accel ? 0 : 1)); | |
497 | |
498 if (!found_accel) | |
499 rval[0] = '_'; | |
500 | |
501 for (i = 0, j = (found_accel ? 0 : 1); name[i]; i++) | |
502 { | |
503 if (name[i]=='%') | |
504 { | |
505 i++; | |
506 if (!(name[i])) | |
507 continue; | |
508 | |
509 if ((name[i] != '_') && (name[i] != '%')) | |
510 i--; | |
511 | |
512 found_accel = TRUE; | |
513 } | |
514 else if (name[i] == '_') | |
515 { | |
516 rval[j++] = '_'; | |
517 } | |
518 | |
519 rval[j++] = name[i]; | |
520 } | |
521 | |
522 return rval; | |
523 } | |
524 | |
525 /* Remove the XEmacs menu accellerator representation from a string. */ | |
526 static char * | |
527 remove_underscores(const Ibyte *name) | |
528 { | |
529 char *rval = (char*) xmalloc_and_zero (qxestrlen(name) + 1); | |
462 | 530 int i,j; |
531 | |
532 for (i = 0, j = 0; name[i]; i++) | |
533 { | |
534 if (name[i]=='%') { | |
535 i++; | |
536 if (!(name[i])) | |
537 continue; | |
538 | |
2081 | 539 if ((name[i] != '_') && (name[i] != '%')) |
540 i--; | |
541 else | |
462 | 542 continue; |
543 } | |
544 rval[j++] = name[i]; | |
545 } | |
546 return rval; | |
547 } | |
548 | |
549 /* This converts an entire menu into a GtkMenuItem (with an attached | |
550 submenu). A menu is a list of (STRING [:keyword value]+ [DESCR]+) | |
551 DESCR is either a list (meaning a submenu), a vector, or nil (if | |
552 you include a :filter keyword) */ | |
553 static GtkWidget * | |
2081 | 554 menu_convert (Lisp_Object desc, GtkWidget *reuse, |
555 GtkAccelGroup* menubar_accel_group) | |
462 | 556 { |
557 GtkWidget *menu_item = NULL; | |
558 GtkWidget *submenu = NULL; | |
559 Lisp_Object key, val; | |
560 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil; | |
561 Lisp_Object active_p = Qt; | |
562 Lisp_Object accel; | |
563 int included_spec = 0; | |
564 int active_spec = 0; | |
565 | |
566 if (STRINGP (XCAR (desc))) | |
567 { | |
568 accel = menu_name_to_accelerator (XSTRING_DATA (XCAR (desc))); | |
569 | |
570 if (!reuse) | |
571 { | |
2081 | 572 char *temp_menu_name = convert_underscores (XSTRING_DATA (XCAR (desc))); |
573 GtkWidget* accel_label = gtk_xemacs_accel_label_new(NULL); | |
574 guint accel_key; | |
575 | |
576 gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5); | |
577 accel_key = gtk_label_parse_uline (GTK_LABEL (accel_label), temp_menu_name); | |
578 | |
579 menu_item = gtk_menu_item_new (); | |
580 gtk_container_add (GTK_CONTAINER (menu_item), accel_label); | |
581 gtk_widget_show (accel_label); | |
582 | |
583 if (menubar_accel_group) | |
584 gtk_widget_add_accelerator (menu_item, | |
585 "activate_item", | |
586 menubar_accel_group, | |
587 accel_key, GDK_MOD1_MASK, | |
588 GTK_ACCEL_LOCKED); | |
462 | 589 free (temp_menu_name); |
590 } | |
591 else | |
592 { | |
593 menu_item = reuse; | |
594 } | |
595 | |
596 submenu = gtk_menu_new (); | |
597 gtk_widget_show (menu_item); | |
598 gtk_widget_show (submenu); | |
599 | |
600 if (!reuse) | |
601 gtk_signal_connect (GTK_OBJECT (menu_item), "destroy", | |
602 GTK_SIGNAL_FUNC (__kill_stupid_gtk_timer), NULL); | |
603 | |
604 /* Without this sometimes a submenu gets left on the screen - | |
605 ** urk | |
606 */ | |
607 if (GTK_MENU_ITEM (menu_item)->submenu) | |
608 { | |
609 gtk_widget_destroy (GTK_MENU_ITEM (menu_item)->submenu); | |
610 } | |
611 | |
612 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu); | |
613 | |
614 /* We put this bogus menu item in so that GTK does the right | |
615 ** thing when the menu is near the screen border. | |
616 ** | |
617 ** Aug 29, 2000 | |
618 */ | |
619 { | |
620 GtkWidget *bogus_item = gtk_menu_item_new_with_label ("A suitably long label here..."); | |
621 | |
622 gtk_object_set_data (GTK_OBJECT (menu_item), XEMACS_MENU_FIRSTTIME_TAG, (gpointer)0x01); | |
623 gtk_widget_show_all (bogus_item); | |
624 gtk_menu_append (GTK_MENU (submenu), bogus_item); | |
625 } | |
626 | |
627 desc = Fcdr (desc); | |
628 | |
629 while (key = Fcar (desc), KEYWORDP (key)) | |
630 { | |
631 Lisp_Object cascade = desc; | |
632 desc = Fcdr (desc); | |
633 if (NILP (desc)) | |
563 | 634 sferror ("keyword in menu lacks a value", |
462 | 635 cascade); |
636 val = Fcar (desc); | |
637 desc = Fcdr (desc); | |
638 if (EQ (key, Q_included)) | |
639 include_p = val, included_spec = 1; | |
640 else if (EQ (key, Q_config)) | |
641 config_tag = val; | |
642 else if (EQ (key, Q_filter)) | |
643 hook_fn = val; | |
644 else if (EQ (key, Q_active)) | |
645 active_p = val, active_spec = 1; | |
646 else if (EQ (key, Q_accelerator)) | |
647 { | |
648 #if 0 | |
649 if ( SYMBOLP (val) | |
650 || CHARP (val)) | |
651 wv->accel = LISP_TO_VOID (val); | |
652 else | |
563 | 653 invalid_argument ("bad keyboard accelerator", val); |
462 | 654 #endif |
655 } | |
656 else if (EQ (key, Q_label)) | |
657 { | |
658 /* implement in 21.2 */ | |
659 } | |
660 else | |
563 | 661 invalid_argument ("unknown menu cascade keyword", cascade); |
462 | 662 } |
663 | |
664 gtk_object_set_data (GTK_OBJECT (menu_item), XEMACS_MENU_DESCR_TAG, LISP_TO_VOID (desc)); | |
665 gtk_object_set_data (GTK_OBJECT (menu_item), XEMACS_MENU_FILTER_TAG, LISP_TO_VOID (hook_fn)); | |
666 | |
667 if ((!NILP (config_tag) | |
668 && NILP (Fmemq (config_tag, Vmenubar_configuration))) | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
669 || (included_spec && |
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
670 NILP (IGNORE_MULTIPLE_VALUES (Feval (include_p))))) |
462 | 671 { |
672 return (NULL); | |
673 } | |
674 | |
675 if (active_spec) | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
676 active_p = IGNORE_MULTIPLE_VALUES (Feval (active_p)); |
462 | 677 |
678 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), ! NILP (active_p)); | |
679 } | |
680 else | |
681 { | |
563 | 682 invalid_argument ("menu name (first element) must be a string", |
462 | 683 desc); |
684 } | |
685 | |
686 /* If we are reusing a widget, we need to make sure we clean | |
687 ** everything up. | |
688 */ | |
689 if (reuse) | |
690 { | |
691 gpointer id = gtk_object_get_data (GTK_OBJECT (reuse), XEMACS_MENU_GUIID_TAG); | |
692 | |
693 if (id) | |
694 { | |
695 /* If the menu item had a GUI_ID that means it was a filter menu */ | |
696 __remove_gcpro_by_id (id); | |
697 gtk_signal_disconnect_by_func (GTK_OBJECT (reuse), | |
698 GTK_SIGNAL_FUNC (__activate_menu), | |
699 (gpointer) 0x01 ); | |
700 } | |
701 else | |
702 { | |
703 gtk_signal_disconnect_by_func (GTK_OBJECT (reuse), | |
704 GTK_SIGNAL_FUNC (__activate_menu), | |
705 NULL); | |
706 } | |
707 | |
708 GTK_MENU_ITEM (reuse)->right_justify = 0; | |
709 } | |
710 | |
711 if (NILP (hook_fn)) | |
712 { | |
713 /* Generic menu builder */ | |
714 gtk_signal_connect (GTK_OBJECT (menu_item), "activate", | |
715 GTK_SIGNAL_FUNC (__activate_menu), | |
716 NULL); | |
717 } | |
718 else | |
719 { | |
720 GUI_ID id = new_gui_id (); | |
721 | |
722 gtk_object_set_data (GTK_OBJECT (menu_item), XEMACS_MENU_GUIID_TAG, | |
723 (gpointer) id); | |
724 | |
725 /* Make sure we gcpro the menu descriptions */ | |
726 gcpro_popup_callbacks (id, desc); | |
727 gtk_object_weakref (GTK_OBJECT (menu_item), __remove_gcpro_by_id, | |
728 (gpointer) id); | |
729 | |
730 gtk_signal_connect (GTK_OBJECT (menu_item), "activate", | |
731 GTK_SIGNAL_FUNC (__activate_menu), | |
732 (gpointer) 0x01); | |
733 } | |
734 | |
735 return (menu_item); | |
736 } | |
737 | |
738 /* Called whenever a button, radio, or toggle is selected in the menu */ | |
739 static void | |
740 __generic_button_callback (GtkMenuItem *item, gpointer user_data) | |
741 { | |
742 Lisp_Object callback, function, data, channel; | |
743 | |
2168 | 744 channel = wrap_frame (gtk_widget_to_frame (GTK_WIDGET (item))); |
462 | 745 |
826 | 746 callback = VOID_TO_LISP (user_data); |
462 | 747 |
748 get_gui_callback (callback, &function, &data); | |
749 | |
750 signal_special_gtk_user_event (channel, function, data); | |
751 } | |
752 | |
753 /* Convert a single menu item descriptor to a suitable GtkMenuItem */ | |
754 /* This function cannot GC. | |
755 It is only called from menu_item_descriptor_to_widget_value, which | |
756 prohibits GC. */ | |
1416 | 757 static GtkWidget * |
2081 | 758 menu_descriptor_to_widget_1 (Lisp_Object descr, GtkAccelGroup* accel_group) |
462 | 759 { |
760 if (STRINGP (descr)) | |
761 { | |
762 /* It is a separator. Unfortunately GTK does not allow us to | |
763 specify what our separators look like, so we can't do all the | |
764 fancy stuff that the X code does. | |
765 */ | |
766 return (gtk_menu_item_new ()); | |
767 } | |
768 else if (LISTP (descr)) | |
769 { | |
770 /* It is a submenu */ | |
2081 | 771 return (menu_convert (descr, NULL, accel_group)); |
462 | 772 } |
773 else if (VECTORP (descr)) | |
774 { | |
775 /* An actual menu item description! This gets yucky. */ | |
776 Lisp_Object name = Qnil; | |
777 Lisp_Object callback = Qnil; | |
778 Lisp_Object suffix = Qnil; | |
779 Lisp_Object active_p = Qt; | |
780 Lisp_Object include_p = Qt; | |
781 Lisp_Object selected_p = Qnil; | |
782 Lisp_Object keys = Qnil; | |
783 Lisp_Object style = Qnil; | |
784 Lisp_Object config_tag = Qnil; | |
785 Lisp_Object accel = Qnil; | |
786 GtkWidget *main_label = NULL; | |
787 int length = XVECTOR_LENGTH (descr); | |
788 Lisp_Object *contents = XVECTOR_DATA (descr); | |
789 int plist_p; | |
790 int selected_spec = 0, included_spec = 0; | |
791 GtkWidget *widget = NULL; | |
2081 | 792 guint accel_key; |
462 | 793 |
794 if (length < 2) | |
563 | 795 sferror ("button descriptors must be at least 2 long", descr); |
462 | 796 |
797 /* length 2: [ "name" callback ] | |
798 length 3: [ "name" callback active-p ] | |
799 length 4: [ "name" callback active-p suffix ] | |
800 or [ "name" callback keyword value ] | |
801 length 5+: [ "name" callback [ keyword value ]+ ] | |
802 */ | |
803 plist_p = (length >= 5 || (length > 2 && KEYWORDP (contents [2]))); | |
804 | |
805 if (!plist_p && length > 2) | |
806 /* the old way */ | |
807 { | |
808 name = contents [0]; | |
809 callback = contents [1]; | |
810 active_p = contents [2]; | |
811 if (length == 4) | |
812 suffix = contents [3]; | |
813 } | |
814 else | |
815 { | |
816 /* the new way */ | |
817 int i; | |
818 if (length & 1) | |
563 | 819 sferror ( |
462 | 820 "button descriptor has an odd number of keywords and values", |
821 descr); | |
822 | |
823 name = contents [0]; | |
824 callback = contents [1]; | |
825 for (i = 2; i < length;) | |
826 { | |
827 Lisp_Object key = contents [i++]; | |
828 Lisp_Object val = contents [i++]; | |
829 if (!KEYWORDP (key)) | |
563 | 830 invalid_argument_2 ("not a keyword", key, descr); |
462 | 831 |
832 if (EQ (key, Q_active)) active_p = val; | |
833 else if (EQ (key, Q_suffix)) suffix = val; | |
834 else if (EQ (key, Q_keys)) keys = val; | |
835 else if (EQ (key, Q_key_sequence)) ; /* ignored for FSF compat */ | |
836 else if (EQ (key, Q_label)) ; /* implement for 21.0 */ | |
837 else if (EQ (key, Q_style)) style = val; | |
838 else if (EQ (key, Q_selected)) selected_p = val, selected_spec = 1; | |
839 else if (EQ (key, Q_included)) include_p = val, included_spec = 1; | |
840 else if (EQ (key, Q_config)) config_tag = val; | |
841 else if (EQ (key, Q_accelerator)) | |
842 { | |
843 if ( SYMBOLP (val) || CHARP (val)) | |
844 accel = val; | |
845 else | |
563 | 846 invalid_argument ("bad keyboard accelerator", val); |
462 | 847 } |
848 else if (EQ (key, Q_filter)) | |
563 | 849 sferror(":filter keyword not permitted on leaf nodes", descr); |
462 | 850 else |
563 | 851 invalid_argument_2 ("unknown menu item keyword", key, descr); |
462 | 852 } |
853 } | |
854 | |
855 #ifdef HAVE_MENUBARS | |
856 if ((!NILP (config_tag) && NILP (Fmemq (config_tag, Vmenubar_configuration))) | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
857 || (included_spec && NILP (IGNORE_MULTIPLE_VALUES (Feval (include_p))))) |
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
858 |
462 | 859 { |
860 /* the include specification says to ignore this item. */ | |
861 return 0; | |
862 } | |
863 #endif /* HAVE_MENUBARS */ | |
864 | |
865 CHECK_STRING (name); | |
866 | |
867 if (NILP (accel)) | |
868 accel = menu_name_to_accelerator (XSTRING_DATA (name)); | |
869 | |
870 if (!NILP (suffix)) | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
871 suffix = IGNORE_MULTIPLE_VALUES (Feval (suffix)); |
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
872 |
462 | 873 |
874 if (!separator_string_p (XSTRING_DATA (name))) | |
875 { | |
2054 | 876 Ibyte *label_buffer = NULL; |
462 | 877 char *temp_label = NULL; |
878 | |
879 if (STRINGP (suffix) && XSTRING_LENGTH (suffix)) | |
880 { | |
2367 | 881 /* !!#### */ |
882 label_buffer = alloca_ibytes (XSTRING_LENGTH (name) + 15 + XSTRING_LENGTH (suffix)); | |
883 qxesprintf (label_buffer, "%s %s ", XSTRING_DATA (name), | |
884 XSTRING_DATA (suffix)); | |
462 | 885 } |
886 else | |
887 { | |
2367 | 888 label_buffer = alloca_ibytes (XSTRING_LENGTH (name) + 15); |
889 qxesprintf (label_buffer, "%s ", XSTRING_DATA (name)); | |
462 | 890 } |
891 | |
2081 | 892 temp_label = convert_underscores (label_buffer); |
893 main_label = gtk_xemacs_accel_label_new (NULL); | |
894 accel_key = gtk_label_parse_uline (GTK_LABEL (main_label), temp_label); | |
462 | 895 free (temp_label); |
896 } | |
897 | |
898 /* Evaluate the selected and active items now */ | |
899 if (selected_spec) | |
900 { | |
901 if (NILP (selected_p) || EQ (selected_p, Qt)) | |
902 { | |
903 /* Do nothing */ | |
904 } | |
905 else | |
906 { | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
907 selected_p = IGNORE_MULTIPLE_VALUES (Feval (selected_p)); |
462 | 908 } |
909 } | |
910 | |
911 if (NILP (active_p) || EQ (active_p, Qt)) | |
912 { | |
913 /* Do Nothing */ | |
914 } | |
915 else | |
916 { | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
2500
diff
changeset
|
917 active_p = IGNORE_MULTIPLE_VALUES (Feval (active_p)); |
462 | 918 } |
919 | |
920 if (0 || | |
921 #ifdef HAVE_MENUBARS | |
922 menubar_show_keybindings | |
923 #endif | |
924 ) | |
925 { | |
926 /* Need to get keybindings */ | |
927 if (!NILP (keys)) | |
928 { | |
929 /* User-specified string to generate key bindings with */ | |
930 CHECK_STRING (keys); | |
931 | |
932 keys = Fsubstitute_command_keys (keys); | |
933 } | |
934 else if (SYMBOLP (callback)) | |
935 { | |
793 | 936 DECLARE_EISTRING_MALLOC (buf); |
462 | 937 |
938 /* #### Warning, dependency here on current_buffer and point */ | |
939 where_is_to_char (callback, buf); | |
940 | |
833 | 941 if (eilen (buf) > 0) |
942 keys = eimake_string (buf); | |
943 else | |
944 { | |
945 | |
946 keys = Qnil; | |
947 } | |
948 | |
793 | 949 eifree (buf); |
462 | 950 } |
951 } | |
952 | |
953 /* Now we get down to the dirty business of creating the widgets */ | |
954 if (NILP (style) || EQ (style, Qtext) || EQ (style, Qbutton)) | |
955 { | |
956 /* A normal menu item */ | |
957 widget = gtk_menu_item_new (); | |
958 } | |
959 else if (EQ (style, Qtoggle) || EQ (style, Qradio)) | |
960 { | |
961 /* They are radio or toggle buttons. | |
962 | |
963 XEmacs' menu descriptions are fairly lame in that they do | |
964 not have the idea of a 'group' of radio buttons. They | |
965 are exactly like toggle buttons except that they get | |
966 drawn differently. | |
967 | |
968 GTK rips us a new one again. If you have a radio button | |
969 in a group by itself, it always draws it as highlighted. | |
970 So we dummy up and create a second radio button that does | |
971 not get added to the menu, but gets invisibly set/unset | |
972 when the other gets unset/set. *sigh* | |
973 | |
974 */ | |
975 if (EQ (style, Qradio)) | |
976 { | |
977 GtkWidget *dummy_sibling = NULL; | |
978 GSList *group = NULL; | |
979 | |
980 dummy_sibling = gtk_radio_menu_item_new (group); | |
981 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (dummy_sibling)); | |
982 widget = gtk_radio_menu_item_new (group); | |
983 | |
984 /* We need to notice when the 'real' one gets destroyed | |
985 so we can clean up the dummy as well. */ | |
986 gtk_object_weakref (GTK_OBJECT (widget), | |
987 (GtkDestroyNotify) gtk_widget_destroy, | |
988 dummy_sibling); | |
989 } | |
990 else | |
991 { | |
992 widget = gtk_check_menu_item_new (); | |
993 } | |
994 | |
995 /* What horrible defaults you have GTK dear! The default | |
996 for a toggle menu item is to not show the toggle unless it | |
997 is turned on or actively highlighted. How absolutely | |
998 hideous. */ | |
999 gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (widget), TRUE); | |
1000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), | |
1001 NILP (selected_p) ? FALSE : TRUE); | |
1002 } | |
1003 else | |
1004 { | |
563 | 1005 invalid_argument_2 ("unknown style", style, descr); |
462 | 1006 } |
1007 | |
1008 gtk_widget_set_sensitive (widget, ! NILP (active_p)); | |
1009 | |
1010 gtk_signal_connect (GTK_OBJECT (widget), "activate-item", | |
1011 GTK_SIGNAL_FUNC (__generic_button_callback), | |
1012 LISP_TO_VOID (callback)); | |
1013 | |
1014 gtk_signal_connect (GTK_OBJECT (widget), "activate", | |
1015 GTK_SIGNAL_FUNC (__generic_button_callback), | |
1016 LISP_TO_VOID (callback)); | |
1017 | |
2081 | 1018 /* Now that all the information about the menu item is know, set the |
1019 remaining properties. | |
462 | 1020 */ |
1021 | |
1022 if (main_label) | |
1023 { | |
1024 gtk_container_add (GTK_CONTAINER (widget), main_label); | |
1025 | |
2081 | 1026 gtk_misc_set_alignment (GTK_MISC (main_label), 0.0, 0.5); |
1027 gtk_xemacs_set_accel_keys(GTK_XEMACS_ACCEL_LABEL(main_label), keys); | |
462 | 1028 |
2081 | 1029 if (accel_group) |
1030 gtk_widget_add_accelerator (widget, | |
1031 "activate_item", | |
1032 accel_group, | |
1033 accel_key, 0, | |
1034 GTK_ACCEL_LOCKED); | |
462 | 1035 } |
1036 | |
1037 return (widget); | |
1038 } | |
1039 else | |
1040 { | |
1041 return (NULL); | |
2500 | 1042 /* ABORT (); ???? */ |
462 | 1043 } |
1044 } | |
1045 | |
1416 | 1046 static GtkWidget * |
2081 | 1047 menu_descriptor_to_widget (Lisp_Object descr, GtkAccelGroup* accel_group) |
462 | 1048 { |
1049 GtkWidget *rval = NULL; | |
771 | 1050 int count = begin_gc_forbidden (); |
462 | 1051 |
1052 /* Cannot GC from here on out... */ | |
2081 | 1053 rval = menu_descriptor_to_widget_1 (descr, accel_group); |
771 | 1054 unbind_to (count); |
462 | 1055 return (rval); |
1056 | |
1057 } | |
1058 | |
1059 static gboolean | |
2054 | 1060 menu_can_reuse_widget (GtkWidget *child, const Ibyte *label) |
462 | 1061 { |
1062 /* Everything up at the top level was done using | |
2081 | 1063 ** gtk_xemacs_accel_label_new(), but we still double check to make |
462 | 1064 ** sure we don't seriously foobar ourselves. |
1065 */ | |
2081 | 1066 gpointer possible_child = |
1067 g_list_nth_data (gtk_container_children (GTK_CONTAINER (child)), 0); | |
1068 gboolean ret_val = FALSE; | |
462 | 1069 |
1070 if (possible_child && GTK_IS_LABEL (possible_child)) | |
1071 { | |
2081 | 1072 char *temp_label = remove_underscores (label); |
1073 | |
462 | 1074 if (!strcmp (GTK_LABEL (possible_child)->label, temp_label)) |
2081 | 1075 ret_val = TRUE; |
1076 | |
1077 free (temp_label); | |
462 | 1078 } |
2081 | 1079 |
1080 return ret_val; | |
462 | 1081 } |
1082 | |
1083 /* Converts a menubar description into a GtkMenuBar... a menubar is a | |
1084 list of menus or buttons | |
1085 */ | |
1086 static void | |
1087 menu_create_menubar (struct frame *f, Lisp_Object descr) | |
1088 { | |
1089 gboolean right_justify = FALSE; | |
1090 Lisp_Object value = descr; | |
1091 GtkWidget *menubar = FRAME_GTK_MENUBAR_WIDGET (f); | |
1092 GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (menubar), XEMACS_MENU_GUIID_TAG); | |
1093 guint menu_position = 0; | |
2081 | 1094 GtkAccelGroup *menubar_accel_group; |
462 | 1095 |
1096 /* Remove any existing protection for old menu items */ | |
1097 ungcpro_popup_callbacks (id); | |
1098 | |
1099 /* GCPRO the whole damn thing */ | |
1100 gcpro_popup_callbacks (id, descr); | |
1101 | |
2081 | 1102 menubar_accel_group = gtk_accel_group_new(); |
1103 | |
2367 | 1104 { |
1105 EXTERNAL_LIST_LOOP_2 (item_descr, value) | |
1106 { | |
1107 gpointer current_child = g_list_nth_data (GTK_MENU_SHELL (menubar)->children, menu_position); | |
462 | 1108 |
2367 | 1109 if (NILP (item_descr)) |
1110 { | |
1111 /* Need to start right-justifying menus */ | |
1112 right_justify = TRUE; | |
1113 menu_position--; | |
1114 } | |
1115 else if (VECTORP (item_descr)) | |
1116 { | |
1117 /* It is a button description */ | |
1118 GtkWidget *item; | |
462 | 1119 |
2367 | 1120 item = menu_descriptor_to_widget (item_descr, menubar_accel_group); |
1121 gtk_widget_set_name (item, "XEmacsMenuButton"); | |
1122 | |
1123 if (!item) | |
1124 { | |
1125 item = gtk_menu_item_new_with_label ("ITEM CREATION ERROR"); | |
1126 } | |
462 | 1127 |
2367 | 1128 gtk_widget_show_all (item); |
1129 if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); | |
1130 gtk_menu_bar_insert (GTK_MENU_BAR (menubar), item, menu_position); | |
1131 } | |
1132 else if (LISTP (item_descr)) | |
1133 { | |
1134 /* Need to actually convert it into a menu and slap it in */ | |
1135 GtkWidget *widget; | |
1136 gboolean reused_p = FALSE; | |
462 | 1137 |
2367 | 1138 /* We may be able to reuse the widget, let's at least check. */ |
1139 if (current_child && menu_can_reuse_widget (GTK_WIDGET (current_child), | |
1140 XSTRING_DATA (XCAR (item_descr)))) | |
1141 { | |
1142 widget = menu_convert (item_descr, GTK_WIDGET (current_child), | |
1143 menubar_accel_group); | |
1144 reused_p = TRUE; | |
1145 } | |
1146 else | |
1147 { | |
1148 widget = menu_convert (item_descr, NULL, menubar_accel_group); | |
1149 if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); | |
1150 gtk_menu_bar_insert (GTK_MENU_BAR (menubar), widget, menu_position); | |
1151 } | |
462 | 1152 |
2367 | 1153 if (widget) |
1154 { | |
1155 if (right_justify) gtk_menu_item_right_justify (GTK_MENU_ITEM (widget)); | |
1156 } | |
1157 else | |
1158 { | |
1159 widget = gtk_menu_item_new_with_label ("ERROR"); | |
2500 | 1160 /* ABORT() */ |
2367 | 1161 } |
1162 gtk_widget_show_all (widget); | |
1163 } | |
1164 else if (STRINGP (item_descr)) | |
1165 { | |
1166 /* Do I really want to be this careful? Anything else in a | |
1167 menubar description is illegal */ | |
1168 } | |
1169 menu_position++; | |
1170 } | |
1171 } | |
462 | 1172 |
1173 /* Need to delete any menu items that were past the bounds of the new one */ | |
1174 { | |
1175 GList *l = NULL; | |
1176 | |
1177 while ((l = g_list_nth (GTK_MENU_SHELL (menubar)->children, menu_position))) | |
1178 { | |
1179 gpointer data = l->data; | |
1180 g_list_remove_link (GTK_MENU_SHELL (menubar)->children, l); | |
1181 | |
1182 if (data) | |
1183 { | |
1184 gtk_widget_destroy (GTK_WIDGET (data)); | |
1185 } | |
1186 } | |
1187 } | |
2081 | 1188 |
1189 /* Attach the new accelerator group to the frame. */ | |
1190 gtk_window_add_accel_group (GTK_WINDOW (FRAME_GTK_SHELL_WIDGET(f)), | |
1191 menubar_accel_group); | |
462 | 1192 } |
1193 | |
1194 | |
1195 /* Deal with getting/setting the menubar */ | |
1196 #ifndef GNOME_IS_APP | |
1197 #define GNOME_IS_APP(x) 0 | |
1198 #define gnome_app_set_menus(x,y) | |
1199 #endif | |
1200 | |
1201 static gboolean | |
2286 | 1202 run_menubar_hook (GtkWidget *widget, GdkEventButton *UNUSED (event), |
1203 gpointer UNUSED (user_data)) | |
462 | 1204 { |
1205 if (!GTK_MENU_SHELL(widget)->active) | |
1206 { | |
1207 run_hook (Qactivate_menubar_hook); | |
1208 } | |
1209 return(FALSE); | |
1210 } | |
1211 | |
1212 static void | |
1213 create_menubar_widget (struct frame *f) | |
1214 { | |
1215 GUI_ID id = new_gui_id (); | |
1216 GtkWidget *handlebox = NULL; | |
1217 GtkWidget *menubar = gtk_xemacs_menubar_new (f); | |
1218 | |
1219 if (GNOME_IS_APP (FRAME_GTK_SHELL_WIDGET (f))) | |
1220 { | |
1221 gnome_app_set_menus (GNOME_APP (FRAME_GTK_SHELL_WIDGET (f)), GTK_MENU_BAR (menubar)); | |
1222 } | |
1223 else if (dockable_menubar) | |
1224 { | |
1225 handlebox = gtk_handle_box_new (); | |
1226 gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (handlebox), GTK_POS_LEFT); | |
1227 gtk_container_add (GTK_CONTAINER (handlebox), menubar); | |
1228 gtk_box_pack_start (GTK_BOX (FRAME_GTK_CONTAINER_WIDGET (f)), handlebox, FALSE, FALSE, 0); | |
1229 } | |
1230 else | |
1231 { | |
1232 gtk_box_pack_start (GTK_BOX (FRAME_GTK_CONTAINER_WIDGET (f)), menubar, FALSE, FALSE, 0); | |
1233 } | |
1234 | |
1235 gtk_signal_connect (GTK_OBJECT (menubar), "button-press-event", | |
1236 GTK_SIGNAL_FUNC (run_menubar_hook), NULL); | |
1237 | |
1238 FRAME_GTK_MENUBAR_WIDGET (f) = menubar; | |
1239 gtk_object_set_data (GTK_OBJECT (menubar), XEMACS_MENU_GUIID_TAG, (gpointer) id); | |
1240 gtk_object_weakref (GTK_OBJECT (menubar), __remove_gcpro_by_id, (gpointer) id); | |
1241 } | |
1242 | |
1243 static int | |
1244 set_frame_menubar (struct frame *f, int first_time_p) | |
1245 { | |
1246 Lisp_Object menubar; | |
1247 int menubar_visible; | |
1248 /* As for the toolbar, the minibuffer does not have its own menubar. */ | |
1249 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
1250 | |
1251 if (! FRAME_GTK_P (f)) | |
1252 return 0; | |
1253 | |
1254 /***** first compute the contents of the menubar *****/ | |
1255 | |
1256 if (! first_time_p) | |
1257 { | |
1258 /* evaluate `current-menubar' in the buffer of the selected window | |
1259 of the frame in question. */ | |
1260 menubar = symbol_value_in_buffer (Qcurrent_menubar, w->buffer); | |
1261 } | |
1262 else | |
1263 { | |
1264 /* That's a little tricky the first time since the frame isn't | |
1265 fully initialized yet. */ | |
1266 menubar = Fsymbol_value (Qcurrent_menubar); | |
1267 } | |
1268 | |
1269 if (NILP (menubar)) | |
1270 { | |
1271 menubar = Vblank_menubar; | |
1272 menubar_visible = 0; | |
1273 } | |
1274 else | |
1275 { | |
1276 menubar_visible = !NILP (w->menubar_visible_p); | |
1277 } | |
1278 | |
1279 if (!FRAME_GTK_MENUBAR_WIDGET (f)) | |
1280 { | |
1281 create_menubar_widget (f); | |
1282 } | |
1283 | |
1284 /* Populate the menubar, but nothing is shown yet */ | |
1285 { | |
1286 Lisp_Object old_buffer; | |
1287 int count = specpdl_depth (); | |
1288 | |
1289 old_buffer = Fcurrent_buffer (); | |
1290 record_unwind_protect (Fset_buffer, old_buffer); | |
1291 Fset_buffer (XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer); | |
1292 | |
1293 menu_create_menubar (f, menubar); | |
1294 | |
1295 Fset_buffer (old_buffer); | |
771 | 1296 unbind_to (count); |
462 | 1297 } |
1298 | |
1346 | 1299 FRAME_GTK_MENUBAR_DATA (f) = Fcons (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer, Qt); |
462 | 1300 |
1301 return (menubar_visible); | |
1302 } | |
1303 | |
1304 /* Called from gtk_create_widgets() to create the inital menubar of a frame | |
1305 before it is mapped, so that the window is mapped with the menubar already | |
1306 there instead of us tacking it on later and thrashing the window after it | |
1307 is visible. */ | |
1308 int | |
1309 gtk_initialize_frame_menubar (struct frame *f) | |
1310 { | |
1311 create_menubar_widget (f); | |
1312 return set_frame_menubar (f, 1); | |
1313 } | |
1314 | |
1315 | |
1316 static void | |
1317 gtk_update_frame_menubar_internal (struct frame *f) | |
1318 { | |
1319 /* We assume the menubar contents has changed if the global flag is set, | |
1320 or if the current buffer has changed, or if the menubar has never | |
1321 been updated before. | |
1322 */ | |
1323 int menubar_contents_changed = | |
1324 (f->menubar_changed | |
1346 | 1325 || NILP (FRAME_GTK_MENUBAR_DATA (f)) |
1326 || (!EQ (XFRAME_GTK_MENUBAR_DATA_LASTBUFF (f), | |
462 | 1327 XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer))); |
1328 | |
1329 gboolean menubar_was_visible = GTK_WIDGET_VISIBLE (FRAME_GTK_MENUBAR_WIDGET (f)); | |
1330 gboolean menubar_will_be_visible = menubar_was_visible; | |
1331 gboolean menubar_visibility_changed; | |
1332 | |
1333 if (menubar_contents_changed) | |
1334 { | |
1335 menubar_will_be_visible = set_frame_menubar (f, 0); | |
1336 } | |
1337 | |
1338 menubar_visibility_changed = menubar_was_visible != menubar_will_be_visible; | |
1339 | |
1340 if (!menubar_visibility_changed) | |
1341 { | |
1342 return; | |
1343 } | |
1344 | |
1345 /* We hide and show the menubar's parent (which is actually the | |
1346 GtkHandleBox)... this is to simplify the code that destroys old | |
1347 menu items, etc. There is no easy way to get the child out of a | |
1348 handle box, and I didn't want to add yet another stupid widget | |
1349 slot to struct gtk_frame. */ | |
1350 if (menubar_will_be_visible) | |
1351 { | |
1352 gtk_widget_show_all (FRAME_GTK_MENUBAR_WIDGET (f)->parent); | |
1353 } | |
1354 else | |
1355 { | |
1356 gtk_widget_hide_all (FRAME_GTK_MENUBAR_WIDGET (f)->parent); | |
1357 } | |
1358 | |
1359 MARK_FRAME_SIZE_SLIPPED (f); | |
1360 } | |
1361 | |
1362 static void | |
1363 gtk_update_frame_menubars (struct frame *f) | |
1364 { | |
1365 GtkWidget *menubar = NULL; | |
1366 | |
1367 assert (FRAME_GTK_P (f)); | |
1368 | |
1369 menubar = FRAME_GTK_MENUBAR_WIDGET (f); | |
1370 | |
1371 if ((GTK_MENU_SHELL (menubar)->active) || | |
1372 (GTK_MENU_SHELL (menubar)->have_grab) || | |
1373 (GTK_MENU_SHELL (menubar)->have_xgrab)) | |
1374 { | |
1375 return; | |
1376 } | |
1377 | |
1378 gtk_update_frame_menubar_internal (f); | |
1379 } | |
1380 | |
1381 static void | |
1382 gtk_free_frame_menubars (struct frame *f) | |
1383 { | |
1384 GtkWidget *menubar_widget; | |
1385 | |
1386 assert (FRAME_GTK_P (f)); | |
1387 | |
1388 menubar_widget = FRAME_GTK_MENUBAR_WIDGET (f); | |
1389 if (menubar_widget) | |
1390 { | |
1391 gtk_widget_destroy (menubar_widget); | |
1392 } | |
1393 } | |
1394 | |
1416 | 1395 static void |
2286 | 1396 popdown_menu_cb (GtkMenuShell *UNUSED (menu), gpointer UNUSED (user_data)) |
462 | 1397 { |
1398 popup_up_p--; | |
1399 } | |
1400 | |
1401 static void | |
1402 gtk_popup_menu (Lisp_Object menu_desc, Lisp_Object event) | |
1403 { | |
1404 struct Lisp_Event *eev = NULL; | |
714 | 1405 GtkWidget *widget = NULL; |
1406 GtkWidget *menu = NULL; | |
1407 gpointer id = NULL; | |
462 | 1408 |
714 | 1409 /* Do basic error checking first... */ |
1410 if (SYMBOLP (menu_desc)) | |
1411 menu_desc = Fsymbol_value (menu_desc); | |
1412 CHECK_CONS (menu_desc); | |
1413 CHECK_STRING (XCAR (menu_desc)); | |
1414 | |
1415 /* Now lets get down to business... */ | |
2081 | 1416 widget = menu_descriptor_to_widget (menu_desc, NULL); |
714 | 1417 menu = GTK_MENU_ITEM (widget)->submenu; |
462 | 1418 gtk_widget_set_name (widget, "XEmacsPopupMenu"); |
714 | 1419 id = gtk_object_get_data (GTK_OBJECT (widget), XEMACS_MENU_GUIID_TAG); |
462 | 1420 |
1421 __activate_menu (GTK_MENU_ITEM (widget), id); | |
1422 | |
1423 if (!NILP (event)) | |
1424 { | |
1425 CHECK_LIVE_EVENT (event); | |
1426 eev = XEVENT (event); | |
1427 | |
1428 if ((eev->event_type != button_press_event) && | |
1429 (eev->event_type != button_release_event)) | |
1430 wrong_type_argument (Qmouse_event_p, event); | |
1431 } | |
1432 else if (!NILP (Vthis_command_keys)) | |
1433 { | |
1434 /* If an event wasn't passed, use the last event of the event | |
1435 sequence currently being executed, if that event is a mouse | |
1436 event. */ | |
1437 eev = XEVENT (Vthis_command_keys); | |
1438 if ((eev->event_type != button_press_event) && | |
1439 (eev->event_type != button_release_event)) | |
1440 eev = NULL; | |
1441 } | |
1442 | |
1443 gtk_widget_show (menu); | |
1444 | |
1445 popup_up_p++; | |
1446 gtk_signal_connect (GTK_OBJECT (menu), "deactivate", | |
1447 GTK_SIGNAL_FUNC (popdown_menu_cb), NULL); | |
1448 | |
1449 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, | |
1204 | 1450 eev ? EVENT_BUTTON_BUTTON (eev) : 0, |
462 | 1451 eev ? eev->timestamp : GDK_CURRENT_TIME); |
1452 } | |
1453 | |
1454 DEFUN ("gtk-build-xemacs-menu", Fgtk_build_xemacs_menu, 1, 1, 0, /* | |
1455 Returns a GTK menu item from MENU, a standard XEmacs menu description. | |
1456 See the definition of `popup-menu' for more information on the format of MENU. | |
1457 */ | |
1458 (menu)) | |
1459 { | |
2081 | 1460 GtkWidget *w = menu_descriptor_to_widget (menu, NULL); |
462 | 1461 |
1462 return (w ? build_gtk_object (GTK_OBJECT (w)) : Qnil); | |
1463 } | |
1464 | |
1465 | |
1466 void | |
1467 syms_of_menubar_gtk (void) | |
1468 { | |
1469 DEFSUBR (Fgtk_build_xemacs_menu); | |
1470 } | |
1471 | |
1472 void | |
1473 console_type_create_menubar_gtk (void) | |
1474 { | |
1475 CONSOLE_HAS_METHOD (gtk, update_frame_menubars); | |
1476 CONSOLE_HAS_METHOD (gtk, free_frame_menubars); | |
1477 CONSOLE_HAS_METHOD (gtk, popup_menu); | |
1478 } | |
1479 | |
1416 | 1480 void |
1481 reinit_vars_of_menubar_gtk (void) | |
462 | 1482 { |
1483 dockable_menubar = 1; | |
1484 #ifdef TEAR_OFF_MENUS | |
1485 tear_off_menus = 1; | |
1486 #endif | |
1487 } | |
1488 | |
1489 void | |
1490 vars_of_menubar_gtk (void) | |
1491 { | |
1492 Fprovide (intern ("gtk-menubars")); | |
1493 DEFVAR_BOOL ("menubar-dockable-p", &dockable_menubar /* | |
1494 If non-nil, the frame menubar can be detached into its own top-level window. | |
1495 */ ); | |
1496 #ifdef TEAR_OFF_MENUS | |
1497 DEFVAR_BOOL ("menubar-tearable-p", &tear_off_menus /* | |
1498 If non-nil, menus can be torn off into their own top-level windows. | |
1499 */ ); | |
1500 #endif | |
1501 } | |
2081 | 1502 |
1503 /*---------------------------------------------------------------------------*/ | |
1504 |