aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2000-01-23 03:22:21 +0000
committerJason Rumney2000-01-23 03:22:21 +0000
commit162d2499e2e57908141d208ade99b61ac9854223 (patch)
treeb171ca56ff07704761eb8d7ec3e956ccc843082b /src
parent4f4a5f699ba86f9186a8112c82cd46ff5f17e363 (diff)
downloademacs-162d2499e2e57908141d208ade99b61ac9854223.tar.gz
emacs-162d2499e2e57908141d208ade99b61ac9854223.zip
Add skeleton support for help strings on menus.
(add_menu_item): Native checkbox and radio support added, but not yet enabled due to bugs. (push_menu_item): Add parameters type, selection and help. Callers updated. Formatting changes to reduce unnecessary diffs with xmenu.c.
Diffstat (limited to 'src')
-rw-r--r--src/w32menu.c277
1 files changed, 199 insertions, 78 deletions
diff --git a/src/w32menu.c b/src/w32menu.c
index 5f0d0eb83da..772749af16c 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */
20 20
21#include <config.h> 21#include <config.h>
22#include <signal.h> 22#include <signal.h>
23
23#include <stdio.h> 24#include <stdio.h>
24#include "lisp.h" 25#include "lisp.h"
25#include "termhooks.h" 26#include "termhooks.h"
@@ -41,6 +42,10 @@ Boston, MA 02111-1307, USA. */
41 42
42#include "dispextern.h" 43#include "dispextern.h"
43 44
45#undef HAVE_MULTILINGUAL_MENU
46#undef HAVE_BOXES /* NTEMACS_TODO: Fix native checkmarks and radios. */
47#undef HAVE_DIALOGS /* NTEMACS_TODO: Fix native dialogs. */
48
44/******************************************************************/ 49/******************************************************************/
45/* Definitions copied from lwlib.h */ 50/* Definitions copied from lwlib.h */
46 51
@@ -50,6 +55,7 @@ typedef char Boolean;
50#define True 1 55#define True 1
51#define False 0 56#define False 0
52 57
58#if 0 /* Not used below. */
53typedef enum _change_type 59typedef enum _change_type
54{ 60{
55 NO_CHANGE = 0, 61 NO_CHANGE = 0,
@@ -57,6 +63,14 @@ typedef enum _change_type
57 VISIBLE_CHANGE = 2, 63 VISIBLE_CHANGE = 2,
58 STRUCTURAL_CHANGE = 3 64 STRUCTURAL_CHANGE = 3
59} change_type; 65} change_type;
66#endif
67
68enum button_type
69{
70 BUTTON_TYPE_NONE,
71 BUTTON_TYPE_TOGGLE,
72 BUTTON_TYPE_RADIO
73};
60 74
61typedef struct _widget_value 75typedef struct _widget_value
62{ 76{
@@ -66,10 +80,14 @@ typedef struct _widget_value
66 char* value; 80 char* value;
67 /* keyboard equivalent. no implications for XtTranslations */ 81 /* keyboard equivalent. no implications for XtTranslations */
68 char* key; 82 char* key;
83 /* Help string or null if none. */
84 char *help;
69 /* true if enabled */ 85 /* true if enabled */
70 Boolean enabled; 86 Boolean enabled;
71 /* true if selected */ 87 /* true if selected */
72 Boolean selected; 88 Boolean selected;
89 /* The type of a button. */
90 enum button_type button_type;
73 /* true if menu title */ 91 /* true if menu title */
74 Boolean title; 92 Boolean title;
75#if 0 93#if 0
@@ -133,8 +151,11 @@ extern Lisp_Object Qmenu_bar_update_hook;
133 151
134void set_frame_menubar (); 152void set_frame_menubar ();
135 153
136static Lisp_Object w32_menu_show (); 154static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
155 Lisp_Object, Lisp_Object, Lisp_Object,
156 Lisp_Object, Lisp_Object));
137static Lisp_Object w32_dialog_show (); 157static Lisp_Object w32_dialog_show ();
158static Lisp_Object w32_menu_show ();
138 159
139static void keymap_panes (); 160static void keymap_panes ();
140static void single_keymap_panes (); 161static void single_keymap_panes ();
@@ -168,12 +189,18 @@ static void list_of_items ();
168#define MENU_ITEMS_PANE_PREFIX 2 189#define MENU_ITEMS_PANE_PREFIX 2
169#define MENU_ITEMS_PANE_LENGTH 3 190#define MENU_ITEMS_PANE_LENGTH 3
170 191
171#define MENU_ITEMS_ITEM_NAME 0 192enum menu_item_idx
172#define MENU_ITEMS_ITEM_ENABLE 1 193{
173#define MENU_ITEMS_ITEM_VALUE 2 194 MENU_ITEMS_ITEM_NAME = 0,
174#define MENU_ITEMS_ITEM_EQUIV_KEY 3 195 MENU_ITEMS_ITEM_ENABLE,
175#define MENU_ITEMS_ITEM_DEFINITION 4 196 MENU_ITEMS_ITEM_VALUE,
176#define MENU_ITEMS_ITEM_LENGTH 5 197 MENU_ITEMS_ITEM_EQUIV_KEY,
198 MENU_ITEMS_ITEM_DEFINITION,
199 MENU_ITEMS_ITEM_TYPE,
200 MENU_ITEMS_ITEM_SELECTED,
201 MENU_ITEMS_ITEM_HELP,
202 MENU_ITEMS_ITEM_LENGTH
203};
177 204
178static Lisp_Object menu_items; 205static Lisp_Object menu_items;
179 206
@@ -194,6 +221,8 @@ static int menu_items_submenu_depth;
194 Xt on behalf of one of the widget sets. */ 221 Xt on behalf of one of the widget sets. */
195static int popup_activated_flag; 222static int popup_activated_flag;
196 223
224static int next_menubar_widget_id;
225
197/* This is set nonzero after the user activates the menu bar, and set 226/* This is set nonzero after the user activates the menu bar, and set
198 to zero again after the menu bars are redisplayed by prepare_menu_bar. 227 to zero again after the menu bars are redisplayed by prepare_menu_bar.
199 While it is nonzero, all calls to set_frame_menubar go deep. 228 While it is nonzero, all calls to set_frame_menubar go deep.
@@ -205,10 +234,11 @@ int pending_menu_activation;
205 234
206 235
207/* Return the frame whose ->output_data.w32->menubar_widget equals 236/* Return the frame whose ->output_data.w32->menubar_widget equals
208 MENU, or 0 if none. */ 237 ID, or 0 if none. */
209 238
210static struct frame * 239static struct frame *
211menubar_id_to_frame (HMENU menu) 240menubar_id_to_frame (id)
241 HMENU id;
212{ 242{
213 Lisp_Object tail, frame; 243 Lisp_Object tail, frame;
214 FRAME_PTR f; 244 FRAME_PTR f;
@@ -219,9 +249,9 @@ menubar_id_to_frame (HMENU menu)
219 if (!GC_FRAMEP (frame)) 249 if (!GC_FRAMEP (frame))
220 continue; 250 continue;
221 f = XFRAME (frame); 251 f = XFRAME (frame);
222 if (!FRAME_W32_P (f)) 252 if (!FRAME_WINDOW_P (f))
223 continue; 253 continue;
224 if (f->output_data.w32->menubar_widget == menu) 254 if (f->output_data.w32->menubar_widget == id)
225 return f; 255 return f;
226 } 256 }
227 return 0; 257 return 0;
@@ -334,17 +364,17 @@ push_menu_pane (name, prefix_vec)
334 XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec; 364 XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
335} 365}
336 366
337/* Push one menu item into the current pane. 367/* Push one menu item into the current pane. NAME is the string to
338 NAME is the string to display. ENABLE if non-nil means 368 display. ENABLE if non-nil means this item can be selected. KEY
339 this item can be selected. KEY is the key generated by 369 is the key generated by choosing this item, or nil if this item
340 choosing this item, or nil if this item doesn't really have a definition. 370 doesn't really have a definition. DEF is the definition of this
341 DEF is the definition of this item. 371 item. EQUIV is the textual description of the keyboard equivalent
342 EQUIV is the textual description of the keyboard equivalent for 372 for this item (or nil if none). TYPE is the type of this menu
343 this item (or nil if none). */ 373 item, one of nil, `toggle' or `radio'. */
344 374
345static void 375static void
346push_menu_item (name, enable, key, def, equiv) 376push_menu_item (name, enable, key, def, equiv, type, selected, help)
347 Lisp_Object name, enable, key, def, equiv; 377 Lisp_Object name, enable, key, def, equiv, type, selected, help;
348{ 378{
349 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated) 379 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
350 grow_menu_items (); 380 grow_menu_items ();
@@ -354,6 +384,9 @@ push_menu_item (name, enable, key, def, equiv)
354 XVECTOR (menu_items)->contents[menu_items_used++] = key; 384 XVECTOR (menu_items)->contents[menu_items_used++] = key;
355 XVECTOR (menu_items)->contents[menu_items_used++] = equiv; 385 XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
356 XVECTOR (menu_items)->contents[menu_items_used++] = def; 386 XVECTOR (menu_items)->contents[menu_items_used++] = def;
387 XVECTOR (menu_items)->contents[menu_items_used++] = type;
388 XVECTOR (menu_items)->contents[menu_items_used++] = selected;
389 XVECTOR (menu_items)->contents[menu_items_used++] = help;
357} 390}
358 391
359/* Look through KEYMAPS, a vector of keymaps that is NMAPS long, 392/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
@@ -475,7 +508,7 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
475 int maxdepth, notreal; 508 int maxdepth, notreal;
476 int *notbuttons_ptr; 509 int *notbuttons_ptr;
477{ 510{
478 Lisp_Object def, map, item_string, enabled; 511 Lisp_Object map, item_string, enabled;
479 struct gcpro gcpro1, gcpro2; 512 struct gcpro gcpro1, gcpro2;
480 int res; 513 int res;
481 514
@@ -570,7 +603,7 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
570 if (!NILP (prefix)) 603 if (!NILP (prefix))
571 item_string = concat2 (prefix, item_string); 604 item_string = concat2 (prefix, item_string);
572 } 605 }
573#endif /* not HAVE_BOXES */ 606#endif /* HAVE_BOXES */
574 607
575#if 0 608#if 0
576 if (!NILP(map)) 609 if (!NILP(map))
@@ -580,7 +613,10 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
580 613
581 push_menu_item (item_string, enabled, key, 614 push_menu_item (item_string, enabled, key,
582 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], 615 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
583 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]); 616 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
617 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
618 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
619 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
584 620
585#if 1 621#if 1
586 /* Display a submenu using the toolkit. */ 622 /* Display a submenu using the toolkit. */
@@ -632,7 +668,7 @@ list_of_items (pane)
632 { 668 {
633 item = Fcar (tail); 669 item = Fcar (tail);
634 if (STRINGP (item)) 670 if (STRINGP (item))
635 push_menu_item (item, Qnil, Qnil, Qt, Qnil); 671 push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
636 else if (NILP (item)) 672 else if (NILP (item))
637 push_left_right_boundary (); 673 push_left_right_boundary ();
638 else 674 else
@@ -640,7 +676,7 @@ list_of_items (pane)
640 CHECK_CONS (item, 0); 676 CHECK_CONS (item, 0);
641 item1 = Fcar (item); 677 item1 = Fcar (item);
642 CHECK_STRING (item1, 1); 678 CHECK_STRING (item1, 1);
643 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil); 679 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
644 } 680 }
645 } 681 }
646} 682}
@@ -681,13 +717,11 @@ cached information about equivalent key sequences.")
681 (position, menu) 717 (position, menu)
682 Lisp_Object position, menu; 718 Lisp_Object position, menu;
683{ 719{
684 int number_of_panes, panes;
685 Lisp_Object keymap, tem; 720 Lisp_Object keymap, tem;
686 int xpos, ypos; 721 int xpos, ypos;
687 Lisp_Object title; 722 Lisp_Object title;
688 char *error_name; 723 char *error_name;
689 Lisp_Object selection; 724 Lisp_Object selection;
690 int i, j;
691 FRAME_PTR f; 725 FRAME_PTR f;
692 Lisp_Object x, y, window; 726 Lisp_Object x, y, window;
693 int keymaps = 0; 727 int keymaps = 0;
@@ -704,9 +738,9 @@ cached information about equivalent key sequences.")
704 || (CONSP (position) && EQ (XCAR (position), Qmenu_bar))) 738 || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
705 { 739 {
706 /* Use the mouse's current position. */ 740 /* Use the mouse's current position. */
707 FRAME_PTR new_f = selected_frame; 741 FRAME_PTR new_f = SELECTED_FRAME ();
708 Lisp_Object bar_window; 742 Lisp_Object bar_window;
709 int part; 743 enum scroll_bar_part part;
710 unsigned long time; 744 unsigned long time;
711 745
712 if (mouse_position_hook) 746 if (mouse_position_hook)
@@ -757,9 +791,9 @@ cached information about equivalent key sequences.")
757 CHECK_LIVE_WINDOW (window, 0); 791 CHECK_LIVE_WINDOW (window, 0);
758 f = XFRAME (WINDOW_FRAME (XWINDOW (window))); 792 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
759 793
760 xpos = (FONT_WIDTH (f->output_data.w32->font) 794 xpos = (FONT_WIDTH (FRAME_FONT (f))
761 * XFASTINT (XWINDOW (window)->left)); 795 * XFASTINT (XWINDOW (window)->left));
762 ypos = (f->output_data.w32->line_height 796 ypos = (FRAME_LINE_HEIGHT (f)
763 * XFASTINT (XWINDOW (window)->top)); 797 * XFASTINT (XWINDOW (window)->top));
764 } 798 }
765 else 799 else
@@ -903,7 +937,7 @@ on the left of the dialog box and all following items on the right.\n\
903 { 937 {
904#if 0 /* Using the frame the mouse is on may not be right. */ 938#if 0 /* Using the frame the mouse is on may not be right. */
905 /* Use the mouse's current position. */ 939 /* Use the mouse's current position. */
906 FRAME_PTR new_f = selected_frame; 940 FRAME_PTR new_f = SELECTED_FRAME ();
907 Lisp_Object bar_window; 941 Lisp_Object bar_window;
908 int part; 942 int part;
909 unsigned long time; 943 unsigned long time;
@@ -949,7 +983,7 @@ on the left of the dialog box and all following items on the right.\n\
949 but I don't want to make one now. */ 983 but I don't want to make one now. */
950 CHECK_WINDOW (window, 0); 984 CHECK_WINDOW (window, 0);
951 985
952#if 1 986#ifndef HAVE_DIALOGS
953 /* Display a menu with these alternatives 987 /* Display a menu with these alternatives
954 in the middle of frame F. */ 988 in the middle of frame F. */
955 { 989 {
@@ -962,7 +996,7 @@ on the left of the dialog box and all following items on the right.\n\
962 return Fx_popup_menu (newpos, 996 return Fx_popup_menu (newpos,
963 Fcons (Fcar (contents), Fcons (contents, Qnil))); 997 Fcons (Fcar (contents), Fcons (contents, Qnil)));
964 } 998 }
965#else 999#else /* HAVE_DIALOGS */
966 { 1000 {
967 Lisp_Object title; 1001 Lisp_Object title;
968 char *error_name; 1002 char *error_name;
@@ -984,7 +1018,7 @@ on the left of the dialog box and all following items on the right.\n\
984 if (error_name) error (error_name); 1018 if (error_name) error (error_name);
985 return selection; 1019 return selection;
986 } 1020 }
987#endif 1021#endif /* HAVE_DIALOGS */
988} 1022}
989 1023
990/* Activate the menu bar of frame F. 1024/* Activate the menu bar of frame F.
@@ -999,6 +1033,7 @@ on the left of the dialog box and all following items on the right.\n\
999 1033
1000 This way we can safely execute Lisp code. */ 1034 This way we can safely execute Lisp code. */
1001 1035
1036void
1002x_activate_menubar (f) 1037x_activate_menubar (f)
1003 FRAME_PTR f; 1038 FRAME_PTR f;
1004{ 1039{
@@ -1148,7 +1183,6 @@ single_submenu (item_key, item_name, maps)
1148 int len; 1183 int len;
1149 Lisp_Object *mapvec; 1184 Lisp_Object *mapvec;
1150 widget_value **submenu_stack; 1185 widget_value **submenu_stack;
1151 int mapno;
1152 int previous_items = menu_items_used; 1186 int previous_items = menu_items_used;
1153 int top_level_items = 0; 1187 int top_level_items = 0;
1154 1188
@@ -1177,7 +1211,8 @@ single_submenu (item_key, item_name, maps)
1177 as opposed to a submenu. */ 1211 as opposed to a submenu. */
1178 top_level_items = 1; 1212 top_level_items = 1;
1179 push_menu_pane (Qnil, Qnil); 1213 push_menu_pane (Qnil, Qnil);
1180 push_menu_item (item_name, Qt, item_key, mapvec[i], Qnil); 1214 push_menu_item (item_name, Qt, item_key, mapvec[i],
1215 Qnil, Qnil, Qnil, Qnil);
1181 } 1216 }
1182 else 1217 else
1183 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); 1218 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
@@ -1192,6 +1227,7 @@ single_submenu (item_key, item_name, maps)
1192 wv->name = "menu"; 1227 wv->name = "menu";
1193 wv->value = 0; 1228 wv->value = 0;
1194 wv->enabled = 1; 1229 wv->enabled = 1;
1230 wv->button_type = BUTTON_TYPE_NONE;
1195 first_wv = wv; 1231 first_wv = wv;
1196 save_wv = 0; 1232 save_wv = 0;
1197 prev_wv = 0; 1233 prev_wv = 0;
@@ -1230,6 +1266,10 @@ single_submenu (item_key, item_name, maps)
1230 char *pane_string; 1266 char *pane_string;
1231 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; 1267 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
1232 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 1268 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1269#ifndef HAVE_MULTILINGUAL_MENU
1270 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1271 pane_name = string_make_unibyte (pane_name);
1272#endif
1233 pane_string = (NILP (pane_name) 1273 pane_string = (NILP (pane_name)
1234 ? "" : (char *) XSTRING (pane_name)->data); 1274 ? "" : (char *) XSTRING (pane_name)->data);
1235 /* If there is just one top-level pane, put all its items directly 1275 /* If there is just one top-level pane, put all its items directly
@@ -1254,6 +1294,7 @@ single_submenu (item_key, item_name, maps)
1254 wv->name++; 1294 wv->name++;
1255 wv->value = 0; 1295 wv->value = 0;
1256 wv->enabled = 1; 1296 wv->enabled = 1;
1297 wv->button_type = BUTTON_TYPE_NONE;
1257 } 1298 }
1258 save_wv = wv; 1299 save_wv = wv;
1259 prev_wv = 0; 1300 prev_wv = 0;
@@ -1262,12 +1303,24 @@ single_submenu (item_key, item_name, maps)
1262 else 1303 else
1263 { 1304 {
1264 /* Create a new item within current pane. */ 1305 /* Create a new item within current pane. */
1265 Lisp_Object item_name, enable, descrip, def; 1306 Lisp_Object item_name, enable, descrip, def, type, selected;
1307 Lisp_Object help;
1308
1266 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; 1309 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
1267 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; 1310 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
1268 descrip 1311 descrip
1269 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; 1312 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
1270 def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION]; 1313 def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
1314 type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
1315 selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
1316 help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
1317
1318#ifndef HAVE_MULTILINGUAL_MENU
1319 if (STRING_MULTIBYTE (item_name))
1320 item_name = string_make_unibyte (item_name);
1321 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1322 descrip = string_make_unibyte (descrip);
1323#endif
1271 1324
1272 wv = xmalloc_widget_value (); 1325 wv = xmalloc_widget_value ();
1273 if (prev_wv) 1326 if (prev_wv)
@@ -1283,6 +1336,20 @@ single_submenu (item_key, item_name, maps)
1283 as long as pointers have enough bits to hold small integers. */ 1336 as long as pointers have enough bits to hold small integers. */
1284 wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0); 1337 wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
1285 wv->enabled = !NILP (enable); 1338 wv->enabled = !NILP (enable);
1339
1340 if (NILP (type))
1341 wv->button_type = BUTTON_TYPE_NONE;
1342 else if (EQ (type, QCradio))
1343 wv->button_type = BUTTON_TYPE_RADIO;
1344 else if (EQ (type, QCtoggle))
1345 wv->button_type = BUTTON_TYPE_TOGGLE;
1346 else
1347 abort ();
1348
1349 wv->selected = !NILP (selected);
1350 if (STRINGP (help))
1351 wv->help = XSTRING (help)->data;
1352
1286 prev_wv = wv; 1353 prev_wv = wv;
1287 1354
1288 i += MENU_ITEMS_ITEM_LENGTH; 1355 i += MENU_ITEMS_ITEM_LENGTH;
@@ -1312,7 +1379,7 @@ set_frame_menubar (f, first_time, deep_p)
1312 int deep_p; 1379 int deep_p;
1313{ 1380{
1314 HMENU menubar_widget = f->output_data.w32->menubar_widget; 1381 HMENU menubar_widget = f->output_data.w32->menubar_widget;
1315 Lisp_Object tail, items, frame; 1382 Lisp_Object items;
1316 widget_value *wv, *first_wv, *prev_wv = 0; 1383 widget_value *wv, *first_wv, *prev_wv = 0;
1317 int i; 1384 int i;
1318 1385
@@ -1331,6 +1398,7 @@ set_frame_menubar (f, first_time, deep_p)
1331 wv->name = "menubar"; 1398 wv->name = "menubar";
1332 wv->value = 0; 1399 wv->value = 0;
1333 wv->enabled = 1; 1400 wv->enabled = 1;
1401 wv->button_type = BUTTON_TYPE_NONE;
1334 first_wv = wv; 1402 first_wv = wv;
1335 1403
1336 if (deep_p) 1404 if (deep_p)
@@ -1403,6 +1471,7 @@ set_frame_menubar (f, first_time, deep_p)
1403 first_wv->contents = wv; 1471 first_wv->contents = wv;
1404 /* Don't set wv->name here; GC during the loop might relocate it. */ 1472 /* Don't set wv->name here; GC during the loop might relocate it. */
1405 wv->enabled = 1; 1473 wv->enabled = 1;
1474 wv->button_type = BUTTON_TYPE_NONE;
1406 prev_wv = wv; 1475 prev_wv = wv;
1407 } 1476 }
1408 1477
@@ -1446,30 +1515,9 @@ set_frame_menubar (f, first_time, deep_p)
1446 else 1515 else
1447 { 1516 {
1448 /* Make a widget-value tree containing 1517 /* Make a widget-value tree containing
1449 just the top level menu bar strings. 1518 just the top level menu bar strings. */
1450
1451 It turns out to be worth comparing the new contents with the
1452 previous contents to avoid unnecessary rebuilding even of just
1453 the top-level menu bar, which turns out to be fairly slow. We
1454 co-opt f->menu_bar_vector for this purpose, since its contents
1455 are effectively discarded at this point anyway.
1456
1457 Note that the lisp-level hooks have already been run by
1458 update_menu_bar - it's kinda a shame the code is duplicated
1459 above as well for deep_p, but there we are. */
1460 1519
1461 items = FRAME_MENU_BAR_ITEMS (f); 1520 items = FRAME_MENU_BAR_ITEMS (f);
1462
1463 /* If there has been no change in the Lisp-level contents of just
1464 the menu bar itself, skip redisplaying it. Just exit. */
1465 for (i = 0; i < f->menu_bar_items_used; i += 4)
1466 if (i == XVECTOR (items)->size
1467 || (XVECTOR (f->menu_bar_vector)->contents[i]
1468 != XVECTOR (items)->contents[i]))
1469 break;
1470 if (i == XVECTOR (items)->size && i == f->menu_bar_items_used && i != 0)
1471 return;
1472
1473 for (i = 0; i < XVECTOR (items)->size; i += 4) 1521 for (i = 0; i < XVECTOR (items)->size; i += 4)
1474 { 1522 {
1475 Lisp_Object string; 1523 Lisp_Object string;
@@ -1482,6 +1530,7 @@ set_frame_menubar (f, first_time, deep_p)
1482 wv->name = (char *) XSTRING (string)->data; 1530 wv->name = (char *) XSTRING (string)->data;
1483 wv->value = 0; 1531 wv->value = 0;
1484 wv->enabled = 1; 1532 wv->enabled = 1;
1533 wv->button_type = BUTTON_TYPE_NONE;
1485 /* This prevents lwlib from assuming this 1534 /* This prevents lwlib from assuming this
1486 menu item is really supposed to be empty. */ 1535 menu item is really supposed to be empty. */
1487 /* The EMACS_INT cast avoids a warning. 1536 /* The EMACS_INT cast avoids a warning.
@@ -1495,16 +1544,10 @@ set_frame_menubar (f, first_time, deep_p)
1495 prev_wv = wv; 1544 prev_wv = wv;
1496 } 1545 }
1497 1546
1498 /* Remember the contents of FRAME_MENU_BAR_ITEMS (f) in 1547 /* Forget what we thought we knew about what is in the
1499 f->menu_bar_vector, so we can check whether the top-level 1548 detailed contents of the menu bar menus.
1500 menubar contents have changed next time. */ 1549 Changing the top level always destroys the contents. */
1501 if (XVECTOR (f->menu_bar_vector)->size < XVECTOR (items)->size) 1550 f->menu_bar_items_used = 0;
1502 f->menu_bar_vector
1503 = Fmake_vector (make_number (XVECTOR (items)->size), Qnil);
1504 bcopy (XVECTOR (items)->contents,
1505 XVECTOR (f->menu_bar_vector)->contents,
1506 XVECTOR (items)->size * sizeof (Lisp_Object));
1507 f->menu_bar_items_used = XVECTOR (items)->size;
1508 } 1551 }
1509 1552
1510 /* Create or update the menu bar widget. */ 1553 /* Create or update the menu bar widget. */
@@ -1612,7 +1655,6 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1612 Lisp_Object *subprefix_stack 1655 Lisp_Object *subprefix_stack
1613 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); 1656 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
1614 int submenu_depth = 0; 1657 int submenu_depth = 0;
1615
1616 int first_pane; 1658 int first_pane;
1617 int next_release_must_exit = 0; 1659 int next_release_must_exit = 0;
1618 1660
@@ -1630,6 +1672,7 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1630 wv->name = "menu"; 1672 wv->name = "menu";
1631 wv->value = 0; 1673 wv->value = 0;
1632 wv->enabled = 1; 1674 wv->enabled = 1;
1675 wv->button_type = BUTTON_TYPE_NONE;
1633 first_wv = wv; 1676 first_wv = wv;
1634 first_pane = 1; 1677 first_pane = 1;
1635 1678
@@ -1666,6 +1709,10 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1666 char *pane_string; 1709 char *pane_string;
1667 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; 1710 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
1668 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 1711 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1712#ifndef HAVE_MULTILINGUAL_MENU
1713 if (!NILP (pane_name) && STRING_MULTIBYTE (pane_name))
1714 pane_name = string_make_unibyte (pane_name);
1715#endif
1669 pane_string = (NILP (pane_name) 1716 pane_string = (NILP (pane_name)
1670 ? "" : (char *) XSTRING (pane_name)->data); 1717 ? "" : (char *) XSTRING (pane_name)->data);
1671 /* If there is just one top-level pane, put all its items directly 1718 /* If there is just one top-level pane, put all its items directly
@@ -1688,6 +1735,7 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1688 wv->name++; 1735 wv->name++;
1689 wv->value = 0; 1736 wv->value = 0;
1690 wv->enabled = 1; 1737 wv->enabled = 1;
1738 wv->button_type = BUTTON_TYPE_NONE;
1691 save_wv = wv; 1739 save_wv = wv;
1692 prev_wv = 0; 1740 prev_wv = 0;
1693 } 1741 }
@@ -1702,12 +1750,21 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1702 else 1750 else
1703 { 1751 {
1704 /* Create a new item within current pane. */ 1752 /* Create a new item within current pane. */
1705 Lisp_Object item_name, enable, descrip, def; 1753 Lisp_Object item_name, enable, descrip, def, type, selected;
1706 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; 1754 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
1707 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; 1755 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
1708 descrip 1756 descrip
1709 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; 1757 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
1710 def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION]; 1758 def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
1759 type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
1760 selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
1761
1762#ifndef HAVE_MULTILINGUAL_MENU
1763 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1764 item_name = string_make_unibyte (item_name);
1765 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1766 item_name = string_make_unibyte (descrip);
1767#endif
1711 1768
1712 wv = xmalloc_widget_value (); 1769 wv = xmalloc_widget_value ();
1713 if (prev_wv) 1770 if (prev_wv)
@@ -1722,6 +1779,18 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1722 restricted to 16-bits.. */ 1779 restricted to 16-bits.. */
1723 wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0; 1780 wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
1724 wv->enabled = !NILP (enable); 1781 wv->enabled = !NILP (enable);
1782
1783 if (NILP (type))
1784 wv->button_type = BUTTON_TYPE_NONE;
1785 else if (EQ (type, QCtoggle))
1786 wv->button_type = BUTTON_TYPE_TOGGLE;
1787 else if (EQ (type, QCradio))
1788 wv->button_type = BUTTON_TYPE_RADIO;
1789 else
1790 abort ();
1791
1792 wv->selected = !NILP (selected);
1793
1725 prev_wv = wv; 1794 prev_wv = wv;
1726 1795
1727 i += MENU_ITEMS_ITEM_LENGTH; 1796 i += MENU_ITEMS_ITEM_LENGTH;
@@ -1739,9 +1808,13 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1739 wv_sep->name = "--"; 1808 wv_sep->name = "--";
1740 wv_sep->next = first_wv->contents; 1809 wv_sep->next = first_wv->contents;
1741 1810
1811#ifndef HAVE_MULTILINGUAL_MENU
1812 if (STRING_MULTIBYTE (title))
1813 title = string_make_unibyte (title);
1814#endif
1742 wv_title->name = (char *) XSTRING (title)->data; 1815 wv_title->name = (char *) XSTRING (title)->data;
1743 /* Handle title specially, so it looks better. */ 1816 wv_title->enabled = True;
1744 wv_title->title = True; 1817 wv_title->button_type = BUTTON_TYPE_NONE;
1745 wv_title->next = wv_sep; 1818 wv_title->next = wv_sep;
1746 first_wv->contents = wv_title; 1819 first_wv->contents = wv_title;
1747 } 1820 }
@@ -1749,7 +1822,7 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1749 /* Actually create the menu. */ 1822 /* Actually create the menu. */
1750 menu = CreatePopupMenu (); 1823 menu = CreatePopupMenu ();
1751 fill_in_menu (menu, first_wv->contents); 1824 fill_in_menu (menu, first_wv->contents);
1752 1825
1753 /* Adjust coordinates to be root-window-relative. */ 1826 /* Adjust coordinates to be root-window-relative. */
1754 pos.x = x; 1827 pos.x = x;
1755 pos.y = y; 1828 pos.y = y;
@@ -1952,7 +2025,7 @@ w32_dialog_show (f, keymaps, title, error)
1952 } 2025 }
1953 2026
1954 /* Actually create the dialog. */ 2027 /* Actually create the dialog. */
1955#if 0 2028#ifdef HAVE_DIALOGS
1956 dialog_id = widget_id_tick++; 2029 dialog_id = widget_id_tick++;
1957 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, 2030 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
1958 f->output_data.w32->widget, 1, 0, 2031 f->output_data.w32->widget, 1, 0,
@@ -1967,7 +2040,7 @@ w32_dialog_show (f, keymaps, title, error)
1967 menu_item_selection = 0; 2040 menu_item_selection = 0;
1968 2041
1969 /* Display the menu. */ 2042 /* Display the menu. */
1970#if 0 2043#ifdef HAVE_DIALOGS
1971 lw_pop_up_all_widgets (dialog_id); 2044 lw_pop_up_all_widgets (dialog_id);
1972 popup_activated_flag = 1; 2045 popup_activated_flag = 1;
1973 2046
@@ -2069,6 +2142,47 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
2069#endif 2142#endif
2070 fuFlags = MF_OWNERDRAW | MF_DISABLED; 2143 fuFlags = MF_OWNERDRAW | MF_DISABLED;
2071 } 2144 }
2145
2146#ifdef HAVE_BOXES
2147 /* Draw radio buttons and tickboxes. */
2148 {
2149 switch (wv->button_type)
2150 {
2151 case BUTTON_TYPE_TOGGLE:
2152 CheckMenuItem (menu, (UINT)item,
2153 wv->selected ? MF_CHECKED : MF_UNCHECKED);
2154 break;
2155
2156 case BUTTON_TYPE_RADIO:
2157 /* CheckMenuRadioItem does not exist on NT 3.51 and
2158 earlier. Fallback on CheckMenuItem. */
2159 {
2160 HMODULE user32 = GetModuleHandle ("user32.dll");
2161 FARPROC set_menu_item_info
2162 = GetProcAddress (user32, "SetMenuItemInfo");
2163 if (set_menu_item_info)
2164 {
2165 MENUITEMINFO info;
2166 bzero (&info, sizeof (info));
2167 info.cbSize = sizeof (info);
2168 info.fMask = MIIM_TYPE | MIIM_STATE;
2169 info.fType = MFT_RADIOCHECK;
2170 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
2171
2172 set_menu_item_info (menu, item, FALSE, &info);
2173 }
2174 else
2175 CheckMenuItem (menu, (UINT)item, wv->selected ?
2176 MF_CHECKED : MF_UNCHECKED);
2177 }
2178 break;
2179
2180 default:
2181 CheckMenuItem (menu, (UINT)item, MF_UNCHECKED);
2182 break;
2183 }
2184 }
2185#endif
2072 } 2186 }
2073 2187
2074 if (item != NULL) 2188 if (item != NULL)
@@ -2111,6 +2225,13 @@ fill_in_menu (HMENU menu, widget_value *wv)
2111 return 1; 2225 return 1;
2112} 2226}
2113 2227
2228int
2229popup_activated ()
2230{
2231 /* popup_activated_flag not actually used on W32 */
2232 return 0;
2233}
2234
2114#endif /* HAVE_MENUS */ 2235#endif /* HAVE_MENUS */
2115 2236
2116syms_of_w32menu () 2237syms_of_w32menu ()