comparison src/menubar-x.c @ 404:2f8bb876ab1d r21-2-32

Import from CVS: tag r21-2-32
author cvs
date Mon, 13 Aug 2007 11:16:07 +0200
parents 74fd4e045ea6
children b8cc9ab3f761
comparison
equal deleted inserted replaced
403:9f011ab08d48 404:2f8bb876ab1d
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
21 21
22 /* Synched up with: Not in FSF. */ 22 /* Synched up with: Not in FSF. */
23 23
24 /* created 16-dec-91 by jwz */ 24 /* Authorship:
25
26 Created 16-dec-91 by Jamie Zawinski.
27 Menu filters and many other keywords added by Stig for 19.12.
28 Original device-abstraction work and GC cleanup work by Ben Wing for 19.13.
29 Menu accelerators c. 1997? by ??. Moved here from event-stream.c.
30 Other work post-1996 by ??.
31 */
25 32
26 #include <config.h> 33 #include <config.h>
27 #include "lisp.h" 34 #include "lisp.h"
28 35
29 #include "console-x.h" 36 #include "console-x.h"
30 #include "EmacsFrame.h" 37 #include "EmacsFrame.h"
31 #include "gui-x.h" 38 #include "gui-x.h"
39 #include "../lwlib/lwlib.h"
32 40
33 #include "buffer.h" 41 #include "buffer.h"
34 #include "commands.h" /* zmacs_regions */ 42 #include "commands.h" /* zmacs_regions */
35 #include "gui.h"
36 #include "events.h" 43 #include "events.h"
37 #include "frame.h" 44 #include "frame.h"
45 #include "gui.h"
46 #include "keymap.h"
47 #include "menubar.h"
38 #include "opaque.h" 48 #include "opaque.h"
39 #include "window.h" 49 #include "window.h"
40 50
41 static int set_frame_menubar (struct frame *f, 51 static int set_frame_menubar (struct frame *f,
42 int deep_p, 52 int deep_p,
152 int included_spec = 0; 162 int included_spec = 0;
153 int active_spec = 0; 163 int active_spec = 0;
154 wv->type = CASCADE_TYPE; 164 wv->type = CASCADE_TYPE;
155 wv->enabled = 1; 165 wv->enabled = 1;
156 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc))); 166 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
157 wv->name = xstrdup (wv->name); 167 wv->name = strdup_and_add_accel (wv->name);
158 168
159 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc))); 169 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
160 wv->accel = LISP_TO_VOID (accel); 170 wv->accel = LISP_TO_VOID (accel);
161 171
162 desc = Fcdr (desc); 172 desc = Fcdr (desc);
265 dummy->type = BUTTON_TYPE; 275 dummy->type = BUTTON_TYPE;
266 dummy->call_data = NULL; 276 dummy->call_data = NULL;
267 dummy->next = NULL; 277 dummy->next = NULL;
268 278
269 goto menu_item_done; 279 goto menu_item_done;
270 } 280 }
271 281
272 } 282 }
273 else if (menubar_root_p) 283 else if (menubar_root_p)
274 { 284 {
275 wv->name = xstrdup ("menubar"); 285 wv->name = xstrdup ("menubar");
290 Lisp_Object child = Fcar (desc); 300 Lisp_Object child = Fcar (desc);
291 if (menubar_root_p && NILP (child)) /* the partition */ 301 if (menubar_root_p && NILP (child)) /* the partition */
292 { 302 {
293 if (partition_seen) 303 if (partition_seen)
294 error ( 304 error (
295 "More than one partition (nil) in menubar description"); 305 "More than one partition (nil) in menubar description");
296 partition_seen = 1; 306 partition_seen = 1;
297 next = xmalloc_widget_value (); 307 next = xmalloc_widget_value ();
298 next->type = PUSHRIGHT_TYPE; 308 next->type = PUSHRIGHT_TYPE;
299 } 309 }
300 else 310 else
317 else if (NILP (desc)) 327 else if (NILP (desc))
318 error ("nil may not appear in menu descriptions"); 328 error ("nil may not appear in menu descriptions");
319 else 329 else
320 signal_simple_error ("Unrecognized menu descriptor", desc); 330 signal_simple_error ("Unrecognized menu descriptor", desc);
321 331
322 menu_item_done: 332 menu_item_done:
323 333
324 if (wv) 334 if (wv)
325 { 335 {
326 /* Completed normally. Clear out the object that widget_value_unwind() 336 /* Completed normally. Clear out the object that widget_value_unwind()
327 will be called with to tell it not to free the wv (as we are 337 will be called with to tell it not to free the wv (as we are
334 } 344 }
335 345
336 static widget_value * 346 static widget_value *
337 menu_item_descriptor_to_widget_value (Lisp_Object desc, 347 menu_item_descriptor_to_widget_value (Lisp_Object desc,
338 int menu_type, /* if this is a menubar, 348 int menu_type, /* if this is a menubar,
339 popup or sub menu */ 349 popup or sub menu */
340 int deep_p, /* */ 350 int deep_p, /* */
341 int filter_p) /* if :filter forms 351 int filter_p) /* if :filter forms
342 should run now */ 352 should run now */
343 { 353 {
344 widget_value *wv; 354 widget_value *wv;
358 int in_menu_callback; 368 int in_menu_callback;
359 369
360 static Lisp_Object 370 static Lisp_Object
361 restore_in_menu_callback (Lisp_Object val) 371 restore_in_menu_callback (Lisp_Object val)
362 { 372 {
363 in_menu_callback = XINT (val); 373 in_menu_callback = XINT (val);
364 return Qnil; 374 return Qnil;
365 } 375 }
366 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */ 376 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
367 377
368 #if 0 378 #if 0
369 /* #### Sort of a hack needed to process Vactivate_menubar_hook 379 /* #### Sort of a hack needed to process Vactivate_menubar_hook
828 838
829 So there are two command-events, with a bunch of magic-events between 839 So there are two command-events, with a bunch of magic-events between
830 them. We don't want the *first* command event to alter the state of the 840 them. We don't want the *first* command event to alter the state of the
831 region, so that the region can be available as an argument for the second 841 region, so that the region can be available as an argument for the second
832 command. 842 command.
833 */ 843 */
834 if (zmacs_regions) 844 if (zmacs_regions)
835 zmacs_region_stays = 1; 845 zmacs_region_stays = 1;
836 846
837 popup_up_p++; 847 popup_up_p++;
838 lw_popup_menu (menu, &xev); 848 lw_popup_menu (menu, &xev);
839 /* this speeds up display of pop-up menus */ 849 /* this speeds up display of pop-up menus */
840 XFlush (XtDisplay (parent)); 850 XFlush (XtDisplay (parent));
841 } 851 }
842 852
843 853
854
855 #if defined(LWLIB_MENUBARS_LUCID)
856 static void
857 menu_move_up (void)
858 {
859 widget_value *current = lw_get_entries (False);
860 widget_value *entries = lw_get_entries (True);
861 widget_value *prev = NULL;
862
863 while (entries != current)
864 {
865 if (entries->name /*&& entries->enabled*/) prev = entries;
866 entries = entries->next;
867 assert (entries);
868 }
869
870 if (!prev)
871 /* move to last item */
872 {
873 while (entries->next)
874 {
875 if (entries->name /*&& entries->enabled*/) prev = entries;
876 entries = entries->next;
877 }
878 if (prev)
879 {
880 if (entries->name /*&& entries->enabled*/)
881 prev = entries;
882 }
883 else
884 {
885 /* no selectable items in this menu, pop up to previous level */
886 lw_pop_menu ();
887 return;
888 }
889 }
890 lw_set_item (prev);
891 }
892
893 static void
894 menu_move_down (void)
895 {
896 widget_value *current = lw_get_entries (False);
897 widget_value *new = current;
898
899 while (new->next)
900 {
901 new = new->next;
902 if (new->name /*&& new->enabled*/) break;
903 }
904
905 if (new==current||!(new->name/*||new->enabled*/))
906 {
907 new = lw_get_entries (True);
908 while (new!=current)
909 {
910 if (new->name /*&& new->enabled*/) break;
911 new = new->next;
912 }
913 if (new==current&&!(new->name /*|| new->enabled*/))
914 {
915 lw_pop_menu ();
916 return;
917 }
918 }
919
920 lw_set_item (new);
921 }
922
923 static void
924 menu_move_left (void)
925 {
926 int level = lw_menu_level ();
927 int l = level;
928 widget_value *current;
929
930 while (level-- >= 3)
931 lw_pop_menu ();
932
933 menu_move_up ();
934 current = lw_get_entries (False);
935 if (l > 2 && current->contents)
936 lw_push_menu (current->contents);
937 }
938
939 static void
940 menu_move_right (void)
941 {
942 int level = lw_menu_level ();
943 int l = level;
944 widget_value *current;
945
946 while (level-- >= 3)
947 lw_pop_menu ();
948
949 menu_move_down ();
950 current = lw_get_entries (False);
951 if (l > 2 && current->contents)
952 lw_push_menu (current->contents);
953 }
954
955 static void
956 menu_select_item (widget_value *val)
957 {
958 if (val == NULL)
959 val = lw_get_entries (False);
960
961 /* is match a submenu? */
962
963 if (val->contents)
964 {
965 /* enter the submenu */
966
967 lw_set_item (val);
968 lw_push_menu (val->contents);
969 }
970 else
971 {
972 /* Execute the menu entry by calling the menu's `select'
973 callback function
974 */
975 lw_kill_menus (val);
976 }
977 }
978
979 Lisp_Object
980 command_builder_operate_menu_accelerator (struct command_builder *builder)
981 {
982 /* this function can GC */
983
984 struct console *con = XCONSOLE (Vselected_console);
985 Lisp_Object evee = builder->most_current_event;
986 Lisp_Object binding;
987 widget_value *entries;
988
989 extern int lw_menu_accelerate; /* lwlib.c */
990
991 #if 0
992 {
993 int i;
994 Lisp_Object t;
995 char buf[50];
996
997 t = builder->current_events;
998 i = 0;
999 while (!NILP (t))
1000 {
1001 i++;
1002 sprintf (buf,"OPERATE (%d): ",i);
1003 write_c_string (buf, Qexternal_debugging_output);
1004 print_internal (t, Qexternal_debugging_output, 1);
1005 write_c_string ("\n", Qexternal_debugging_output);
1006 t = XEVENT_NEXT (t);
1007 }
1008 }
1009 #endif /* 0 */
1010
1011 /* menu accelerator keys don't go into keyboard macros */
1012 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1013 con->kbd_macro_ptr = con->kbd_macro_end;
1014
1015 /* don't echo menu accelerator keys */
1016 /*reset_key_echo (builder, 1);*/
1017
1018 if (!lw_menu_accelerate)
1019 {
1020 /* `convert' mouse display to keyboard display
1021 by entering the open submenu
1022 */
1023 entries = lw_get_entries (False);
1024 if (entries->contents)
1025 {
1026 lw_push_menu (entries->contents);
1027 lw_display_menu (CurrentTime);
1028 }
1029 }
1030
1031 /* compare event to the current menu accelerators */
1032
1033 entries=lw_get_entries (True);
1034
1035 while (entries)
1036 {
1037 Lisp_Object accel;
1038 VOID_TO_LISP (accel, entries->accel);
1039 if (entries->name && !NILP (accel))
1040 {
1041 if (event_matches_key_specifier_p (XEVENT (evee), accel))
1042 {
1043 /* a match! */
1044
1045 menu_select_item (entries);
1046
1047 if (lw_menu_active) lw_display_menu (CurrentTime);
1048
1049 reset_this_command_keys (Vselected_console, 1);
1050 /*reset_command_builder_event_chain (builder);*/
1051 return Vmenu_accelerator_map;
1052 }
1053 }
1054 entries = entries->next;
1055 }
1056
1057 /* try to look up event in menu-accelerator-map */
1058
1059 binding = event_binding_in (evee, Vmenu_accelerator_map, 1);
1060
1061 if (NILP (binding))
1062 {
1063 /* beep at user for undefined key */
1064 return Qnil;
1065 }
1066 else
1067 {
1068 if (EQ (binding, Qmenu_quit))
1069 {
1070 /* turn off menus and set quit flag */
1071 lw_kill_menus (NULL);
1072 Vquit_flag = Qt;
1073 }
1074 else if (EQ (binding, Qmenu_up))
1075 {
1076 int level = lw_menu_level ();
1077 if (level > 2)
1078 menu_move_up ();
1079 }
1080 else if (EQ (binding, Qmenu_down))
1081 {
1082 int level = lw_menu_level ();
1083 if (level > 2)
1084 menu_move_down ();
1085 else
1086 menu_select_item (NULL);
1087 }
1088 else if (EQ (binding, Qmenu_left))
1089 {
1090 int level = lw_menu_level ();
1091 if (level > 3)
1092 {
1093 lw_pop_menu ();
1094 lw_display_menu (CurrentTime);
1095 }
1096 else
1097 menu_move_left ();
1098 }
1099 else if (EQ (binding, Qmenu_right))
1100 {
1101 int level = lw_menu_level ();
1102 if (level > 2 &&
1103 lw_get_entries (False)->contents)
1104 {
1105 widget_value *current = lw_get_entries (False);
1106 if (current->contents)
1107 menu_select_item (NULL);
1108 }
1109 else
1110 menu_move_right ();
1111 }
1112 else if (EQ (binding, Qmenu_select))
1113 menu_select_item (NULL);
1114 else if (EQ (binding, Qmenu_escape))
1115 {
1116 int level = lw_menu_level ();
1117
1118 if (level > 2)
1119 {
1120 lw_pop_menu ();
1121 lw_display_menu (CurrentTime);
1122 }
1123 else
1124 {
1125 /* turn off menus quietly */
1126 lw_kill_menus (NULL);
1127 }
1128 }
1129 else if (KEYMAPP (binding))
1130 {
1131 /* prefix key */
1132 reset_this_command_keys (Vselected_console, 1);
1133 /*reset_command_builder_event_chain (builder);*/
1134 return binding;
1135 }
1136 else
1137 {
1138 /* turn off menus and execute binding */
1139 lw_kill_menus (NULL);
1140 reset_this_command_keys (Vselected_console, 1);
1141 /*reset_command_builder_event_chain (builder);*/
1142 return binding;
1143 }
1144 }
1145
1146 if (lw_menu_active) lw_display_menu (CurrentTime);
1147
1148 reset_this_command_keys (Vselected_console, 1);
1149 /*reset_command_builder_event_chain (builder);*/
1150
1151 return Vmenu_accelerator_map;
1152 }
1153
1154 static Lisp_Object
1155 menu_accelerator_junk_on_error (Lisp_Object errordata, Lisp_Object ignored)
1156 {
1157 Vmenu_accelerator_prefix = Qnil;
1158 Vmenu_accelerator_modifiers = Qnil;
1159 Vmenu_accelerator_enabled = Qnil;
1160 if (!NILP (errordata))
1161 {
1162 Lisp_Object args[2];
1163
1164 args[0] = build_string ("Error in menu accelerators (setting to nil)");
1165 /* #### This should call
1166 (with-output-to-string (display-error errordata))
1167 but that stuff is all in Lisp currently. */
1168 args[1] = errordata;
1169 warn_when_safe_lispobj
1170 (Qerror, Qwarning,
1171 emacs_doprnt_string_lisp ((const Bufbyte *) "%s: %s",
1172 Qnil, -1, 2, args));
1173 }
1174
1175 return Qnil;
1176 }
1177
1178 static Lisp_Object
1179 menu_accelerator_safe_compare (Lisp_Object event0)
1180 {
1181 if (CONSP (Vmenu_accelerator_prefix))
1182 {
1183 Lisp_Object t;
1184 t=Vmenu_accelerator_prefix;
1185 while (!NILP (t)
1186 && !NILP (event0)
1187 && event_matches_key_specifier_p (XEVENT (event0), Fcar (t)))
1188 {
1189 t = Fcdr (t);
1190 event0 = XEVENT_NEXT (event0);
1191 }
1192 if (!NILP (t))
1193 return Qnil;
1194 }
1195 else if (NILP (event0))
1196 return Qnil;
1197 else if (event_matches_key_specifier_p (XEVENT (event0), Vmenu_accelerator_prefix))
1198 event0 = XEVENT_NEXT (event0);
1199 else
1200 return Qnil;
1201 return event0;
1202 }
1203
1204 static Lisp_Object
1205 menu_accelerator_safe_mod_compare (Lisp_Object cons)
1206 {
1207 return (event_matches_key_specifier_p (XEVENT (XCAR (cons)), XCDR (cons))
1208 ? Qt
1209 : Qnil);
1210 }
1211
1212 Lisp_Object
1213 command_builder_find_menu_accelerator (struct command_builder *builder)
1214 {
1215 /* this function can GC */
1216 Lisp_Object event0 = builder->current_events;
1217 struct console *con = XCONSOLE (Vselected_console);
1218 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1219 Widget menubar_widget;
1220
1221 /* compare entries in event0 against the menu prefix */
1222
1223 if ((!CONSOLE_X_P (XCONSOLE (builder->console))) || NILP (event0) ||
1224 XEVENT (event0)->event_type != key_press_event)
1225 return Qnil;
1226
1227 if (!NILP (Vmenu_accelerator_prefix))
1228 {
1229 event0 = condition_case_1 (Qerror,
1230 menu_accelerator_safe_compare,
1231 event0,
1232 menu_accelerator_junk_on_error,
1233 Qnil);
1234 }
1235
1236 if (NILP (event0))
1237 return Qnil;
1238
1239 menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
1240 if (menubar_widget
1241 && CONSP (Vmenu_accelerator_modifiers))
1242 {
1243 Lisp_Object fake;
1244 Lisp_Object last = Qnil;
1245 struct gcpro gcpro1;
1246 Lisp_Object matchp;
1247
1248 widget_value *val;
1249 LWLIB_ID id = XPOPUP_DATA (f->menubar_data)->id;
1250
1251 val = lw_get_all_values (id);
1252 if (val)
1253 {
1254 val = val->contents;
1255
1256 fake = Fcopy_sequence (Vmenu_accelerator_modifiers);
1257 last = fake;
1258
1259 while (!NILP (Fcdr (last)))
1260 last = Fcdr (last);
1261
1262 Fsetcdr (last, Fcons (Qnil, Qnil));
1263 last = Fcdr (last);
1264 }
1265
1266 fake = Fcons (Qnil, fake);
1267
1268 GCPRO1 (fake);
1269
1270 while (val)
1271 {
1272 Lisp_Object accel;
1273 VOID_TO_LISP (accel, val->accel);
1274 if (val->name && !NILP (accel))
1275 {
1276 Fsetcar (last, accel);
1277 Fsetcar (fake, event0);
1278 matchp = condition_case_1 (Qerror,
1279 menu_accelerator_safe_mod_compare,
1280 fake,
1281 menu_accelerator_junk_on_error,
1282 Qnil);
1283 if (!NILP (matchp))
1284 {
1285 /* we found one! */
1286
1287 lw_set_menu (menubar_widget, val);
1288 /* yah - yet another hack.
1289 pretend emacs timestamp is the same as an X timestamp,
1290 which for the moment it is. (read events.h)
1291 */
1292 lw_map_menu (XEVENT (event0)->timestamp);
1293
1294 if (val->contents)
1295 lw_push_menu (val->contents);
1296
1297 lw_display_menu (CurrentTime);
1298
1299 /* menu accelerator keys don't go into keyboard macros */
1300 if (!NILP (con->defining_kbd_macro)
1301 && NILP (Vexecuting_macro))
1302 con->kbd_macro_ptr = con->kbd_macro_end;
1303
1304 /* don't echo menu accelerator keys */
1305 /*reset_key_echo (builder, 1);*/
1306 reset_this_command_keys (Vselected_console, 1);
1307 UNGCPRO;
1308
1309 return Vmenu_accelerator_map;
1310 }
1311 }
1312
1313 val = val->next;
1314 }
1315
1316 UNGCPRO;
1317 }
1318 return Qnil;
1319 }
1320
1321 int
1322 x_kludge_lw_menu_active (void)
1323 {
1324 return lw_menu_active;
1325 }
1326
1327 DEFUN ("accelerate-menu", Faccelerate_menu, 0, 0, "_", /*
1328 Make the menubar active. Menu items can be selected using menu accelerators
1329 or by actions defined in menu-accelerator-map.
1330 */
1331 ())
1332 {
1333 struct console *con = XCONSOLE (Vselected_console);
1334 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1335 LWLIB_ID id;
1336 widget_value *val;
1337
1338 if (NILP (f->menubar_data))
1339 error ("Frame has no menubar.");
1340
1341 id = XPOPUP_DATA (f->menubar_data)->id;
1342 val = lw_get_all_values (id);
1343 val = val->contents;
1344 lw_set_menu (FRAME_X_MENUBAR_WIDGET (f), val);
1345 lw_map_menu (CurrentTime);
1346
1347 lw_display_menu (CurrentTime);
1348
1349 /* menu accelerator keys don't go into keyboard macros */
1350 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1351 con->kbd_macro_ptr = con->kbd_macro_end;
1352
1353 return Qnil;
1354 }
1355 #endif /* LWLIB_MENUBARS_LUCID */
1356
1357
844 void 1358 void
845 syms_of_menubar_x (void) 1359 syms_of_menubar_x (void)
846 { 1360 {
1361 #if defined(LWLIB_MENUBARS_LUCID)
1362 DEFSUBR (Faccelerate_menu);
1363 #endif
847 } 1364 }
848 1365
849 void 1366 void
850 console_type_create_menubar_x (void) 1367 console_type_create_menubar_x (void)
851 { 1368 {