#define MENU_ITEM_ID_BITS(x) (((x) & 0x7FFF) | 0x8000)
static HMENU top_level_menu;
-/* Translate (in place) %_ to &, %% to %.
- Return new length, and (through accel) the accelerator character.
- (If there is no accelerator, it will be added on the first character.)
- len = number of bytes (not including zero terminator).
- maxlen = size of buffer.
- We assume and maintain zero-termination. To be absolutely sure
- of not hitting an error, maxlen should be >= 2*len + 3. */
-
+/*
+ * Translate (in place) X accelerator syntax to win32 accelerator syntax.
+ * Return new length.
+ * len = number of bytes (not including zero terminator).
+ * maxlen = size of buffer.
+ * accel = (Emchar*) to receive the accelerator character
+ * or NULL to suppress accelerators in the menu or dialog item.
+ *
+ * %% is replaced with %
+ * if accel is NULL:
+ * %_ is removed.
+ * if accel is non-NULL:
+ * %_ is replaced with &.
+ * The accelerator character is passed back in *accel.
+ * (If there is no accelerator, it will be added on the first character.)
+ *
+ * We assume and maintain zero-termination. To be absolutely sure
+ * of not hitting an error, maxlen should be >= 2*len + 3.
+ */
Bytecount
mswindows_translate_menu_or_dialog_item (Bufbyte *item, Bytecount len,
- Bytecount maxlen, Emchar *accel,
- Lisp_Object error_name)
+ Bytecount maxlen, Emchar *accel,
+ Lisp_Object error_name)
{
Bufbyte *ptr;
- *accel = '\0';
+ if (accel)
+ *accel = '\0';
/* Escape '&' as '&&' */
-
ptr = item;
while ((ptr = (Bufbyte *) memchr (ptr, '&', len - (ptr - item))) != NULL)
{
if (len + 2 > maxlen)
- signal_simple_error ("Menu item produces too long displayable string",
- error_name);
+ syntax_error ("Menu item produces too long displayable string",
+ error_name);
memmove (ptr + 1, ptr, (len - (ptr - item)) + 1);
len++;
ptr += 2;
{
if (*(ptr + 1) == '_')
{
- *ptr = '&';
- if (!*accel)
- /* #### urk ! We need a reference translation table for
- case changes that aren't buffer-specific. */
- *accel = DOWNCASE (current_buffer, charptr_emchar (ptr + 2));
- memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
- len--;
+ if (accel)
+ {
+ *ptr = '&';
+ if (!*accel)
+ /* #### urk ! We need a reference translation table for
+ case changes that aren't buffer-specific. */
+ *accel = DOWNCASE (current_buffer, charptr_emchar (ptr + 2));
+ memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
+ len--;
+ }
+ else /* Skip accelerator */
+ {
+ memmove (ptr, ptr + 2, len - (ptr - item + 2) + 1);
+ len-=2;
+ }
}
else if (*(ptr + 1) == '%')
{
memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
len--;
+ ptr++;
}
- ptr++;
+ else /* % on its own - shouldn't happen */
+ ptr++;
}
- if (!*accel)
+ if (accel && !*accel)
{
+ /* Force a default accelerator */
if (len + 2 > maxlen)
- signal_simple_error ("Menu item produces too long displayable string",
- error_name);
+ syntax_error ("Menu item produces too long displayable string",
+ error_name);
ptr = item;
memmove (ptr + 1, ptr, len + 1);
/* #### urk ! We need a reference translation table for
/* We construct the name in a static buffer. That's fine, because
menu items longer than 128 chars are probably programming errors,
and better be caught than displayed! */
-
+
static char buf[MAX_MENUITEM_LENGTH+2];
/* Left flush part of the string */
return HASH2 (internal_hash (XVECTOR_DATA(item)[0], 0),
internal_hash (XVECTOR_DATA(item)[1], 0));
}
-
+
/* An error - will be caught later */
return 0;
}
int flush_right, int bar_p)
{
MENUITEMINFO item_info;
+ UINT oldflags = MF_BYPOSITION;
+ UINT olduidnewitem = 0;
+ LPCTSTR oldlpnewitem = 0;
item_info.cbSize = sizeof (item_info);
item_info.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
{
/* Separator or unselectable text */
if (separator_string_p (XSTRING_DATA (item)))
- item_info.fType = MFT_SEPARATOR;
+ {
+ item_info.fType = MFT_SEPARATOR;
+ oldflags |= MF_SEPARATOR;
+ }
else
{
item_info.fType = MFT_STRING;
item_info.fState = MFS_DISABLED;
item_info.dwTypeData = XSTRING_DATA (item);
+ oldflags |= MF_STRING | MF_DISABLED;
+ oldlpnewitem = item_info.dwTypeData;
}
}
else if (CONSP (item))
menu_parse_submenu_keywords (item, gui_item);
if (!STRINGP (pgui_item->name))
- signal_simple_error ("Menu name (first element) must be a string",
+ syntax_error ("Menu name (first element) must be a string",
item);
if (!gui_item_included_p (gui_item, Vmenubar_configuration))
- {
- UNGCPRO;
- goto done;
- }
+ {
+ UNGCPRO;
+ goto done;
+ }
if (!gui_item_active_p (gui_item))
- item_info.fState = MFS_GRAYED;
+ {
+ item_info.fState = MFS_GRAYED;
+ oldflags |= MF_GRAYED;
+ }
/* Temptation is to put 'else' right here. Although, the
displayed item won't have an arrow indicating that it is a
popup. So we go ahead a little bit more and create a popup */
item_info.fMask |= MIIM_SUBMENU;
item_info.dwTypeData = displayable_menu_item (gui_item, bar_p, &accel);
item_info.hSubMenu = submenu;
+ olduidnewitem = (UINT) submenu;
+ oldlpnewitem = item_info.dwTypeData;
+ oldflags |= MF_POPUP;
if (accel && bar_p)
*accel_list = Fcons (make_char (accel), *accel_list);
Fputhash (hmenu_to_lisp_object (submenu), path, hash_tab);
}
UNGCPRO;
- }
+ }
else if (VECTORP (item))
{
/* An ordinary item */
GCPRO2 (gui_item, *accel_list);
if (!gui_item_included_p (gui_item, Vmenubar_configuration))
- {
- UNGCPRO;
- goto done;
- }
+ {
+ UNGCPRO;
+ goto done;
+ }
if (!STRINGP (pgui_item->name))
pgui_item->name = Feval (pgui_item->name);
if (!gui_item_active_p (gui_item))
- item_info.fState = MFS_GRAYED;
+ {
+ item_info.fState = MFS_GRAYED;
+ oldflags = MF_GRAYED;
+ }
style = (NILP (pgui_item->selected) || NILP (Feval (pgui_item->selected))
? Qnil : pgui_item->style);
{
item_info.fType |= MFT_RADIOCHECK;
item_info.fState |= MFS_CHECKED;
+ oldflags |= MF_CHECKED; /* Can't support radio-button checkmarks
+ under 3.51 */
}
else if (EQ (style, Qtoggle))
{
item_info.fState |= MFS_CHECKED;
+ oldflags |= MF_CHECKED;
}
id = allocate_menu_item_id (path, pgui_item->name,
item_info.wID = (UINT) XINT (id);
item_info.fType |= MFT_STRING;
item_info.dwTypeData = displayable_menu_item (gui_item, bar_p, &accel);
+ olduidnewitem = item_info.wID;
+ oldflags |= MF_STRING;
+ oldlpnewitem = item_info.dwTypeData;
if (accel && bar_p)
*accel_list = Fcons (make_char (accel), *accel_list);
UNGCPRO;
}
else
- {
- signal_simple_error ("Malformed menu item descriptor", item);
- }
+ syntax_error ("Malformed menu item descriptor", item);
if (flush_right)
- item_info.fType |= MFT_RIGHTJUSTIFY;
+ item_info.fType |= MFT_RIGHTJUSTIFY; /* can't support in 3.51 */
- InsertMenuItem (menu, UINT_MAX, TRUE, &item_info);
+ if (xInsertMenuItemA)
+ xInsertMenuItemA (menu, UINT_MAX, TRUE, &item_info);
+ else
+ InsertMenu (menu, UINT_MAX, oldflags, olduidnewitem, oldlpnewitem);
done:;
-}
+}
/*
* This function is called from populate_menu and checksum_menu.
/* Check that menu name is specified when expected */
if (NILP (pgui_item->name) && deep_p)
- signal_simple_error ("Menu must have a name", desc);
+ syntax_error ("Menu must have a name", desc);
/* Apply filter if specified */
if (!NILP (pgui_item->filter))
checksum = HASH2 (checksum,
checksum_menu_item (XCAR (item_desc)));
}
-
+
if (populate_p)
{
/* Remove the "(empty)" item, if there are other ones */
{
CHECK_STRING (pgui_item->name);
InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED,
- 0, XSTRING_DATA(pgui_item->name));
+ 0, displayable_menu_item (gui_item, bar_p, NULL));
InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
- SetMenuDefaultItem (menu, 0, MF_BYPOSITION);
+ if (xSetMenuDefaultItem) /* not in NT 3.5x */
+ xSetMenuDefaultItem (menu, 0, MF_BYPOSITION);
}
}
if (menubar == NULL)
return;
- /* #### If a filter function has set desc to Qnil, this abort()
+ /* #### If a filter function has set desc to Qnil, this ABORT()
triggers. To resolve, we must prevent filters explicitly from
mangling with the active menu. In apply_filter probably?
Is copy-tree on the whole menu too expensive? */
if (NILP (desc))
- /* abort(); */
+ /* ABORT(); */
return;
GCPRO1 (desc); /* just to be safe -- see above */
Fputhash (hmenu_to_lisp_object (menubar), Qnil,
FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
- populate_menu (menubar, Qnil, desc,
+ populate_menu (menubar, Qnil, desc,
FRAME_MSWINDOWS_MENU_HASH_TABLE (f), 1);
UNGCPRO;
}
{
Lisp_Object hash = FRAME_MSWINDOWS_MENU_HASH_TABLE (f);
- assert (HASH_TABLEP (hash));
+ if (NILP (hash))
+ return 0;
/* !!#### not Mule-ized */
return !NILP (memq_no_quit (make_char (tolower (ch)),
Fgethash (Qt, hash, Qnil)));
}
-
+
\f
/*------------------------------------------------------------------------*/
/* Message handlers */
Lisp_Object path, desc;
struct gcpro gcpro1;
-
+
/* Find which guy is going to explode */
path = Fgethash (hmenu_to_lisp_object (menu), current_hash_table, Qunbound);
assert (!UNBOUNDP (path));
XSETFRAME (frame, f);
/* this used to call mswindows_enqueue_misc_user_event but that
breaks customize because the misc_event gets eval'ed in some
- cicumstances. Don't change it back unless you can fix the
+ circumstances. Don't change it back unless you can fix the
customize problem also.*/
- enqueue_misc_user_event (frame, fn, arg);
- mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
+ mswindows_enqueue_misc_user_event (frame, fn, arg);
UNGCPRO; /* data */
return Qt;
eev = NULL;
}
+ popup_up_p++;
+
/* Default is to put the menu at the point (10, 10) in frame */
if (eev)
{
CHECK_CONS (menu_desc);
CHECK_STRING (XCAR (menu_desc));
+ menu_cleanup (f);
+
current_menudesc = menu_desc;
current_hash_table =
make_lisp_hash_table (10, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
menu = create_empty_popup_menu ();
Fputhash (hmenu_to_lisp_object (menu), Qnil, current_hash_table);
top_level_menu = menu;
-
+
/* see comments in menubar-x.c */
if (zmacs_regions)
zmacs_region_stays = 1;
-
+
ok = TrackPopupMenu (menu,
TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
pt.x, pt.y, 0,
DestroyMenu (menu);
- /* Signal a signal if caught by Track...() modal loop */
+ /* A WM_COMMAND is not issued until TrackPopupMenu returns. This
+ makes setting popup_up_p fairly pointless since we cannot keep
+ the menu up and dispatch events. Furthermore, we seem to have
+ little control over what happens to the menu when we click. */
+ popup_up_p--;
+
+ /* Signal a signal if caught by Track...() modal loop. */
+ /* I think this is pointless, the code hasn't actually put us in a
+ modal loop at this time -- andyp. */
mswindows_unmodalize_signal_maybe ();
/* This is probably the only real reason for failure */