Mercurial > hg > xemacs-beta
comparison src/menubar-msw.c @ 418:e804706bfb8c r21-2-17
Import from CVS: tag r21-2-17
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:23:13 +0200 |
parents | 697ef44129c6 |
children | 41dbb7a9d5f2 |
comparison
equal
deleted
inserted
replaced
417:43a18b32d56e | 418:e804706bfb8c |
---|---|
121 /* | 121 /* |
122 * This returns Windows-style menu item string: | 122 * This returns Windows-style menu item string: |
123 * "Left Flush\tRight Flush" | 123 * "Left Flush\tRight Flush" |
124 */ | 124 */ |
125 static char* | 125 static char* |
126 displayable_menu_item (struct gui_item* pgui_item, int bar_p) | 126 displayable_menu_item (Lisp_Object gui_item, int bar_p) |
127 { | 127 { |
128 /* We construct the name in a static buffer. That's fine, because | 128 /* We construct the name in a static buffer. That's fine, because |
129 menu items longer than 128 chars are probably programming errors, | 129 menu items longer than 128 chars are probably programming errors, |
130 and better be caught than displayed! */ | 130 and better be caught than displayed! */ |
131 | 131 |
132 static char buf[MAX_MENUITEM_LENGTH+2]; | 132 static char buf[MAX_MENUITEM_LENGTH+2]; |
133 char *ptr; | 133 char *ptr; |
134 unsigned int ll, lr; | 134 unsigned int ll, lr; |
135 | 135 |
136 /* Left flush part of the string */ | 136 /* Left flush part of the string */ |
137 ll = gui_item_display_flush_left (pgui_item, buf, MAX_MENUITEM_LENGTH); | 137 ll = gui_item_display_flush_left (gui_item, buf, MAX_MENUITEM_LENGTH); |
138 | 138 |
139 /* Escape '&' as '&&' */ | 139 /* Escape '&' as '&&' */ |
140 ptr = buf; | 140 ptr = buf; |
141 while ((ptr=memchr (ptr, '&', ll-(ptr-buf))) != NULL) | 141 while ((ptr=memchr (ptr, '&', ll-(ptr-buf))) != NULL) |
142 { | 142 { |
143 if (ll+2 >= MAX_MENUITEM_LENGTH) | 143 if (ll+2 >= MAX_MENUITEM_LENGTH) |
144 signal_simple_error ("Menu item produces too long displayable string", | 144 signal_simple_error ("Menu item produces too long displayable string", |
145 pgui_item->name); | 145 XGUI_ITEM (gui_item)->name); |
146 memmove (ptr+1, ptr, (ll-(ptr-buf))+1); | 146 memmove (ptr+1, ptr, (ll-(ptr-buf))+1); |
147 ll++; | 147 ll++; |
148 ptr+=2; | 148 ptr+=2; |
149 } | 149 } |
150 | 150 |
163 | 163 |
164 /* Right flush part, unless we're at the top-level where it's not allowed */ | 164 /* Right flush part, unless we're at the top-level where it's not allowed */ |
165 if (!bar_p) | 165 if (!bar_p) |
166 { | 166 { |
167 assert (MAX_MENUITEM_LENGTH > ll + 1); | 167 assert (MAX_MENUITEM_LENGTH > ll + 1); |
168 lr = gui_item_display_flush_right (pgui_item, buf + ll + 1, | 168 lr = gui_item_display_flush_right (gui_item, buf + ll + 1, |
169 MAX_MENUITEM_LENGTH - ll - 1); | 169 MAX_MENUITEM_LENGTH - ll - 1); |
170 if (lr) | 170 if (lr) |
171 buf [ll] = '\t'; | 171 buf [ll] = '\t'; |
172 } | 172 } |
173 | 173 |
277 } | 277 } |
278 else if (CONSP (item)) | 278 else if (CONSP (item)) |
279 { | 279 { |
280 /* Submenu */ | 280 /* Submenu */ |
281 HMENU submenu; | 281 HMENU submenu; |
282 struct gui_item gui_item; | 282 Lisp_Object gui_item = allocate_gui_item (); |
283 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); | |
283 struct gcpro gcpro1; | 284 struct gcpro gcpro1; |
284 | 285 |
285 gui_item_init (&gui_item); | 286 GCPRO1 (gui_item); |
286 GCPRO_GUI_ITEM (&gui_item); | 287 |
287 | 288 menu_parse_submenu_keywords (item, gui_item); |
288 menu_parse_submenu_keywords (item, &gui_item); | 289 |
289 | 290 if (!STRINGP (pgui_item->name)) |
290 if (!STRINGP (gui_item.name)) | |
291 signal_simple_error ("Menu name (first element) must be a string", item); | 291 signal_simple_error ("Menu name (first element) must be a string", item); |
292 | 292 |
293 if (!gui_item_included_p (&gui_item, Vmenubar_configuration)) | 293 if (!gui_item_included_p (gui_item, Vmenubar_configuration)) |
294 return; | 294 return; |
295 | 295 |
296 if (!gui_item_active_p (&gui_item)) | 296 if (!gui_item_active_p (gui_item)) |
297 item_info.fState = MFS_GRAYED; | 297 item_info.fState = MFS_GRAYED; |
298 /* Temptation is to put 'else' right here. Although, the | 298 /* Temptation is to put 'else' right here. Although, the |
299 displayed item won't have an arrow indicating that it is a | 299 displayed item won't have an arrow indicating that it is a |
300 popup. So we go ahead a little bit more and create a popup */ | 300 popup. So we go ahead a little bit more and create a popup */ |
301 submenu = create_empty_popup_menu(); | 301 submenu = create_empty_popup_menu(); |
302 | 302 |
303 item_info.fMask |= MIIM_SUBMENU; | 303 item_info.fMask |= MIIM_SUBMENU; |
304 item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p); | 304 item_info.dwTypeData = displayable_menu_item (gui_item, bar_p); |
305 item_info.hSubMenu = submenu; | 305 item_info.hSubMenu = submenu; |
306 | 306 |
307 if (!(item_info.fState & MFS_GRAYED)) | 307 if (!(item_info.fState & MFS_GRAYED)) |
308 { | 308 { |
309 /* Now add the full submenu path as a value to the hash table, | 309 /* Now add the full submenu path as a value to the hash table, |
310 keyed by menu handle */ | 310 keyed by menu handle */ |
311 if (NILP(path)) | 311 if (NILP(path)) |
312 /* list1 cannot GC */ | 312 /* list1 cannot GC */ |
313 path = list1 (gui_item.name); | 313 path = list1 (pgui_item->name); |
314 else | 314 else |
315 { | 315 { |
316 Lisp_Object arg[2]; | 316 Lisp_Object arg[2]; |
317 arg[0] = path; | 317 arg[0] = path; |
318 arg[1] = list1 (gui_item.name); | 318 arg[1] = list1 (pgui_item->name); |
319 /* Fappend gcpro'es its arg */ | 319 /* Fappend gcpro'es its arg */ |
320 path = Fappend (2, arg); | 320 path = Fappend (2, arg); |
321 } | 321 } |
322 | 322 |
323 /* Fputhash GCPRO'es PATH */ | 323 /* Fputhash GCPRO'es PATH */ |
327 } | 327 } |
328 else if (VECTORP (item)) | 328 else if (VECTORP (item)) |
329 { | 329 { |
330 /* An ordinary item */ | 330 /* An ordinary item */ |
331 Lisp_Object style, id; | 331 Lisp_Object style, id; |
332 struct gui_item gui_item; | 332 Lisp_Object gui_item = gui_parse_item_keywords (item); |
333 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); | |
333 struct gcpro gcpro1; | 334 struct gcpro gcpro1; |
334 | 335 |
335 gui_item_init (&gui_item); | 336 GCPRO1 (gui_item); |
336 GCPRO_GUI_ITEM (&gui_item); | 337 |
337 | 338 if (!gui_item_included_p (gui_item, Vmenubar_configuration)) |
338 gui_parse_item_keywords (item, &gui_item); | |
339 | |
340 if (!gui_item_included_p (&gui_item, Vmenubar_configuration)) | |
341 return; | 339 return; |
342 | 340 |
343 if (!gui_item_active_p (&gui_item)) | 341 if (!gui_item_active_p (gui_item)) |
344 item_info.fState = MFS_GRAYED; | 342 item_info.fState = MFS_GRAYED; |
345 | 343 |
346 style = (NILP (gui_item.selected) || NILP (Feval (gui_item.selected)) | 344 style = (NILP (pgui_item->selected) || NILP (Feval (pgui_item->selected)) |
347 ? Qnil : gui_item.style); | 345 ? Qnil : pgui_item->style); |
348 | 346 |
349 if (EQ (style, Qradio)) | 347 if (EQ (style, Qradio)) |
350 { | 348 { |
351 item_info.fType |= MFT_RADIOCHECK; | 349 item_info.fType |= MFT_RADIOCHECK; |
352 item_info.fState |= MFS_CHECKED; | 350 item_info.fState |= MFS_CHECKED; |
354 else if (EQ (style, Qtoggle)) | 352 else if (EQ (style, Qtoggle)) |
355 { | 353 { |
356 item_info.fState |= MFS_CHECKED; | 354 item_info.fState |= MFS_CHECKED; |
357 } | 355 } |
358 | 356 |
359 id = allocate_menu_item_id (path, gui_item.name, | 357 id = allocate_menu_item_id (path, pgui_item->name, |
360 gui_item.suffix); | 358 pgui_item->suffix); |
361 Fputhash (id, gui_item.callback, hash_tab); | 359 Fputhash (id, pgui_item->callback, hash_tab); |
362 | 360 |
363 item_info.wID = (UINT) XINT(id); | 361 item_info.wID = (UINT) XINT(id); |
364 item_info.fType |= MFT_STRING; | 362 item_info.fType |= MFT_STRING; |
365 item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p); | 363 item_info.dwTypeData = displayable_menu_item (gui_item, bar_p); |
366 | 364 |
367 UNGCPRO; /* gui_item */ | 365 UNGCPRO; /* gui_item */ |
368 } | 366 } |
369 else | 367 else |
370 { | 368 { |
394 { | 392 { |
395 Lisp_Object item_desc; | 393 Lisp_Object item_desc; |
396 int deep_p, flush_right; | 394 int deep_p, flush_right; |
397 struct gcpro gcpro1; | 395 struct gcpro gcpro1; |
398 unsigned long checksum; | 396 unsigned long checksum; |
399 struct gui_item gui_item; | 397 Lisp_Object gui_item = allocate_gui_item (); |
400 | 398 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); |
401 gui_item_init (&gui_item); | 399 GCPRO1 (gui_item); |
402 GCPRO_GUI_ITEM (&gui_item); | |
403 | 400 |
404 /* We are sometimes called with the menubar unchanged, and with changed | 401 /* We are sometimes called with the menubar unchanged, and with changed |
405 right flush. We have to update the menubar in this case, | 402 right flush. We have to update the menubar in this case, |
406 so account for the compliance setting in the hash value */ | 403 so account for the compliance setting in the hash value */ |
407 checksum = REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIHGT_FLUSH; | 404 checksum = REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIHGT_FLUSH; |
412 | 409 |
413 /* PATH set to nil indicates top-level popup or menubar */ | 410 /* PATH set to nil indicates top-level popup or menubar */ |
414 deep_p = !NILP (path); | 411 deep_p = !NILP (path); |
415 | 412 |
416 /* Fetch keywords prepending the item list */ | 413 /* Fetch keywords prepending the item list */ |
417 desc = menu_parse_submenu_keywords (desc, &gui_item); | 414 desc = menu_parse_submenu_keywords (desc, gui_item); |
418 | 415 |
419 /* Check that menu name is specified when expected */ | 416 /* Check that menu name is specified when expected */ |
420 if (NILP (gui_item.name) && deep_p) | 417 if (NILP (pgui_item->name) && deep_p) |
421 signal_simple_error ("Menu must have a name", desc); | 418 signal_simple_error ("Menu must have a name", desc); |
422 | 419 |
423 /* Apply filter if specified */ | 420 /* Apply filter if specified */ |
424 if (!NILP (gui_item.filter)) | 421 if (!NILP (pgui_item->filter)) |
425 desc = call1 (gui_item.filter, desc); | 422 desc = call1 (pgui_item->filter, desc); |
426 | 423 |
427 /* Loop thru the desc's CDR and add items for each entry */ | 424 /* Loop thru the desc's CDR and add items for each entry */ |
428 flush_right = 0; | 425 flush_right = 0; |
429 EXTERNAL_LIST_LOOP (item_desc, desc) | 426 EXTERNAL_LIST_LOOP (item_desc, desc) |
430 { | 427 { |
451 RemoveMenu (menu, EMPTY_ITEM_ID, MF_BYCOMMAND); | 448 RemoveMenu (menu, EMPTY_ITEM_ID, MF_BYCOMMAND); |
452 | 449 |
453 /* Add the header to the popup, if told so. The same as in X - an | 450 /* Add the header to the popup, if told so. The same as in X - an |
454 insensitive item, and a separator (Seems to me, there were | 451 insensitive item, and a separator (Seems to me, there were |
455 two separators in X... In Windows this looks ugly, anyways. */ | 452 two separators in X... In Windows this looks ugly, anyways. */ |
456 if (!bar_p && !deep_p && popup_menu_titles && !NILP(gui_item.name)) | 453 if (!bar_p && !deep_p && popup_menu_titles && !NILP(pgui_item->name)) |
457 { | 454 { |
458 CHECK_STRING (gui_item.name); | 455 CHECK_STRING (pgui_item->name); |
459 InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED, | 456 InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED, |
460 0, XSTRING_DATA(gui_item.name)); | 457 0, XSTRING_DATA(pgui_item->name)); |
461 InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); | 458 InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); |
462 SetMenuDefaultItem (menu, 0, MF_BYPOSITION); | 459 SetMenuDefaultItem (menu, 0, MF_BYPOSITION); |
463 } | 460 } |
464 } | 461 } |
465 UNGCPRO; /* gui_item */ | 462 UNGCPRO; /* gui_item */ |