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 */