#include <stdio.h>
#include "lisp.h"
#include "termhooks.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
-#include "keyboard.h"
#include "blockinput.h"
#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
#include "dispextern.h"
#undef HAVE_MULTILINGUAL_MENU
-#undef HAVE_BOXES /* NTEMACS_TODO: Fix native checkmarks and radios. */
-#undef HAVE_DIALOGS /* NTEMACS_TODO: Fix native dialogs. */
+#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
/******************************************************************/
/* Definitions copied from lwlib.h */
typedef void * XtPointer;
typedef char Boolean;
-#define True 1
-#define False 0
-
-#if 0 /* Not used below. */
-typedef enum _change_type
-{
- NO_CHANGE = 0,
- INVISIBLE_CHANGE = 1,
- VISIBLE_CHANGE = 2,
- STRUCTURAL_CHANGE = 3
-} change_type;
-#endif
-
enum button_type
{
BUTTON_TYPE_NONE,
But don't make a pane that is empty--ignore that map instead.
P is the number of panes we have made so far. */
for (mapno = 0; mapno < nmaps; mapno++)
- single_keymap_panes (keymaps[mapno], Qnil, Qnil, notreal, 10);
+ single_keymap_panes (keymaps[mapno],
+ map_prompt (keymaps[mapno]), Qnil, notreal, 10);
finish_menu_items ();
}
Lisp_Object pending_maps = Qnil;
Lisp_Object tail, item;
struct gcpro gcpro1, gcpro2;
- int notbuttons = 0;
if (maxdepth <= 0)
return;
push_menu_pane (pane_name, prefix);
-#ifndef HAVE_BOXES
- /* Remember index for first item in this pane so we can go back and
- add a prefix when (if) we see the first button. After that, notbuttons
- is set to 0, to mark that we have seen a button and all non button
- items need a prefix. */
- notbuttons = menu_items_used;
-#endif
-
for (tail = keymap; CONSP (tail); tail = XCDR (tail))
{
GCPRO2 (keymap, pending_maps);
item = XCAR (tail);
if (CONSP (item))
single_menu_item (XCAR (item), XCDR (item),
- &pending_maps, notreal, maxdepth, ¬buttons);
+ &pending_maps, notreal, maxdepth);
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
Lisp_Object character;
XSETFASTINT (character, c);
single_menu_item (character, XVECTOR (item)->contents[c],
- &pending_maps, notreal, maxdepth, ¬buttons);
+ &pending_maps, notreal, maxdepth);
}
}
UNGCPRO;
separate panes.
If NOTREAL is nonzero, only check for equivalent key bindings, don't
evaluate expressions in menu items and don't make any menu.
- If we encounter submenus deeper than MAXDEPTH levels, ignore them.
- NOTBUTTONS_PTR is only used when simulating toggle boxes and radio
- buttons. It points to variable notbuttons in single_keymap_panes,
- which keeps track of if we have seen a button in this menu or not. */
+ If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
static void
-single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
- notbuttons_ptr)
+single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
Lisp_Object key, item;
Lisp_Object *pending_maps_ptr;
int maxdepth, notreal;
- int *notbuttons_ptr;
{
Lisp_Object map, item_string, enabled;
struct gcpro gcpro1, gcpro2;
return;
}
-#ifndef HAVE_BOXES
- /* Simulate radio buttons and toggle boxes by putting a prefix in
- front of them. */
- {
- Lisp_Object prefix = Qnil;
- Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
- if (!NILP (type))
- {
- Lisp_Object selected
- = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
-
- if (*notbuttons_ptr)
- /* The first button. Line up previous items in this menu. */
- {
- int index = *notbuttons_ptr; /* Index for first item this menu. */
- int submenu = 0;
- Lisp_Object tem;
- while (index < menu_items_used)
- {
- tem
- = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME];
- if (NILP (tem))
- {
- index++;
- submenu++; /* Skip sub menu. */
- }
- else if (EQ (tem, Qlambda))
- {
- index++;
- submenu--; /* End sub menu. */
- }
- else if (EQ (tem, Qt))
- index += 3; /* Skip new pane marker. */
- else if (EQ (tem, Qquote))
- index++; /* Skip a left, right divider. */
- else
- {
- if (!submenu && XSTRING (tem)->data[0] != '\0'
- && XSTRING (tem)->data[0] != '-')
- XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
- = concat2 (build_string (" "), tem);
- index += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- *notbuttons_ptr = 0;
- }
-
- /* Calculate prefix, if any, for this item. */
- if (EQ (type, QCtoggle))
- prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
- else if (EQ (type, QCradio))
- prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
- }
- /* Not a button. If we have earlier buttons, then we need a prefix. */
- else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0'
- && XSTRING (item_string)->data[0] != '-')
- prefix = build_string (" ");
-
- if (!NILP (prefix))
- item_string = concat2 (prefix, item_string);
- }
-#endif /* HAVE_BOXES */
-
-#if 0
- if (!NILP(map))
- /* Indicate visually that this is a submenu. */
- item_string = concat2 (item_string, build_string (" >"));
-#endif
-
push_menu_item (item_string, enabled, key,
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
-#if 1
/* Display a submenu using the toolkit. */
if (! (NILP (map) || NILP (enabled)))
{
single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
push_submenu_end ();
}
-#endif
}
\f
/* Push all the panes and items of a menu described by the
/* Decode the first argument: find the window and the coordinates. */
if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
{
/* Use the mouse's current position. */
FRAME_PTR new_f = SELECTED_FRAME ();
/* Decode the menu items from what was specified. */
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (CONSP (menu))
- tem = Fkeymapp (Fcar (menu));
- if (!NILP (keymap))
+ keymap = get_keymap (menu, 0, 0);
+ if (CONSP (keymap))
{
/* We were given a keymap. Extract menu info from the keymap. */
Lisp_Object prompt;
- keymap = get_keymap (menu);
/* Extract the detailed info to make one pane. */
keymap_panes (&menu, 1, NILP (position));
keymaps = 1;
}
- else if (!NILP (tem))
+ else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
{
/* We were given a list of keymaps. */
int nmaps = XFASTINT (Flength (menu));
{
Lisp_Object prompt;
- maps[i++] = keymap = get_keymap (Fcar (tem));
+ maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0);
prompt = map_prompt (keymap);
if (NILP (title) && !NILP (prompt))
/* Decode the first argument: find the window or frame to use. */
if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
{
#if 0 /* Using the frame the mouse is on may not be right. */
/* Use the mouse's current position. */
FRAME_PTR new_f = SELECTED_FRAME ();
Lisp_Object bar_window;
- int part;
+ enum scroll_bar_part part;
unsigned long time;
Lisp_Object x, y;
Lisp_Object frame;
XSETFRAME (frame, f);
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = frame;
kbd_buffer_store_event (&buf);
for (j = 0; j < submenu_depth; j++)
if (!NILP (subprefix_stack[j]))
{
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, subprefix_stack[j]);
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = subprefix_stack[j];
kbd_buffer_store_event (&buf);
}
if (!NILP (prefix))
{
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, prefix);
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = prefix;
kbd_buffer_store_event (&buf);
}
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, entry);
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = entry;
kbd_buffer_store_event (&buf);
return;
for (i = 0; i < len; i++)
{
if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i])
- && NILP (Fkeymapp (mapvec[i]))))
+ || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
{
/* Here we have a command at top level in the menu bar
as opposed to a submenu. */
prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
+ pane_name = ENCODE_SYSTEM (pane_name);
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
#ifndef HAVE_MULTILINGUAL_MENU
if (STRING_MULTIBYTE (item_name))
- item_name = string_make_unibyte (item_name);
+ item_name = ENCODE_SYSTEM (item_name);
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- descrip = string_make_unibyte (descrip);
+ descrip = ENCODE_SYSTEM (descrip);
#endif
wv = xmalloc_widget_value ();
wv->selected = !NILP (selected);
if (STRINGP (help))
- wv->help = XSTRING (help)->data;
-
+ wv->help = (char *) XSTRING (help)->data;
+ else
+ wv->help = NULL;
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
set_buffer_internal_1 (XBUFFER (buffer));
/* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
+ safe_run_hooks (Qactivate_menubar_hook);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
= (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
int submenu_depth = 0;
int first_pane;
- int next_release_must_exit = 0;
*error = NULL;
prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
#ifndef HAVE_MULTILINGUAL_MENU
if (!NILP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
+ pane_name = ENCODE_SYSTEM (pane_name);
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
else
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def, type, selected;
+ Lisp_Object item_name, enable, descrip, def, type, selected, help;
+
item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
descrip
def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
+ help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
- item_name = string_make_unibyte (item_name);
+ item_name = ENCODE_SYSTEM (item_name);
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- item_name = string_make_unibyte (descrip);
+ descrip = ENCODE_SYSTEM (descrip);
#endif
wv = xmalloc_widget_value ();
abort ();
wv->selected = !NILP (selected);
-
+
+ if (STRINGP (help))
+ wv->help = (char *) XSTRING (help)->data;
+ else
+ wv->help = NULL;
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
#ifndef HAVE_MULTILINGUAL_MENU
if (STRING_MULTIBYTE (title))
- title = string_make_unibyte (title);
+ title = ENCODE_SYSTEM (title);
#endif
wv_title->name = (char *) XSTRING (title)->data;
- wv_title->enabled = True;
+ wv_title->enabled = TRUE;
+ wv_title->title = TRUE;
wv_title->button_type = BUTTON_TYPE_NONE;
wv_title->next = wv_sep;
first_wv->contents = wv_title;
pos.y = y;
ClientToScreen (FRAME_W32_WINDOW (f), &pos);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
-
/* No selection has been chosen yet. */
menu_item_selection = 0;
during the call. */
discard_mouse_events ();
+ /* Free the widget_value objects we used to specify the contents. */
+ free_menubar_widget_value_tree (first_wv);
+
DestroyMenu (menu);
/* Find the selected item, and its pane, to return
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
+ Lisp_Object item_name, enable, descrip, help;
+
item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
descrip
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
if (NILP (item_name))
{
menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
f->output_data.w32->widget, 1, 0,
dialog_selection_callback, 0);
- lw_modify_all_widgets (dialog_id, first_wv->contents, True);
+ lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
#endif
/* Free the widget_value objects we used to specify the contents. */
{
UINT fuFlags;
char *out_string;
+ int return_value;
if (name_is_separator (wv->name))
- fuFlags = MF_SEPARATOR;
+ {
+ fuFlags = MF_SEPARATOR;
+ out_string = NULL;
+ }
else
{
if (wv->enabled)
#endif
fuFlags = MF_OWNERDRAW | MF_DISABLED;
}
-
-#ifdef HAVE_BOXES
/* Draw radio buttons and tickboxes. */
- {
- switch (wv->button_type)
- {
- case BUTTON_TYPE_TOGGLE:
- CheckMenuItem (menu, (UINT)item,
- wv->selected ? MF_CHECKED : MF_UNCHECKED);
- break;
-
- case BUTTON_TYPE_RADIO:
- /* CheckMenuRadioItem does not exist on NT 3.51 and
- earlier. Fallback on CheckMenuItem. */
- {
- HMODULE user32 = GetModuleHandle ("user32.dll");
- FARPROC set_menu_item_info
- = GetProcAddress (user32, "SetMenuItemInfo");
- if (set_menu_item_info)
- {
- MENUITEMINFO info;
- bzero (&info, sizeof (info));
- info.cbSize = sizeof (info);
- info.fMask = MIIM_TYPE | MIIM_STATE;
- info.fType = MFT_RADIOCHECK;
- info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
-
- set_menu_item_info (menu, item, FALSE, &info);
- }
- else
- CheckMenuItem (menu, (UINT)item, wv->selected ?
- MF_CHECKED : MF_UNCHECKED);
- }
- break;
-
- default:
- CheckMenuItem (menu, (UINT)item, MF_UNCHECKED);
- break;
- }
- }
-#endif
+ else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
+ wv->button_type == BUTTON_TYPE_RADIO))
+ fuFlags |= MF_CHECKED;
+ else
+ fuFlags |= MF_UNCHECKED;
}
if (item != NULL)
fuFlags = MF_POPUP;
- return AppendMenu (menu,
- fuFlags,
- item != NULL ? (UINT) item : (UINT) wv->call_data,
- (fuFlags == MF_SEPARATOR) ? NULL: out_string );
+ return_value =
+ AppendMenu (menu,
+ fuFlags,
+ item != NULL ? (UINT) item : (UINT) wv->call_data,
+ out_string );
+
+ /* This must be done after the menu item is created. */
+ if ((fuFlags & MF_STRING) != 0)
+ {
+ HMODULE user32 = GetModuleHandle ("user32.dll");
+ FARPROC set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfoA");
+
+ if (set_menu_item_info)
+ {
+ MENUITEMINFO info;
+ bzero (&info, sizeof (info));
+ info.cbSize = sizeof (info);
+ info.fMask = MIIM_DATA;
+
+ /* Set help string for menu item. */
+ info.dwItemData = (DWORD)wv->help;
+
+ if (wv->button_type == BUTTON_TYPE_RADIO)
+ {
+ /* CheckMenuRadioItem allows us to differentiate TOGGLE and
+ RADIO items, but is not available on NT 3.51 and earlier. */
+ info.fMask |= MIIM_TYPE | MIIM_STATE;
+ info.fType = MFT_RADIOCHECK | MFT_STRING;
+ info.dwTypeData = out_string;
+ info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
+ }
+
+ set_menu_item_info (menu,
+ item != NULL ? (UINT) item : (UINT) wv->call_data,
+ FALSE, &info);
+ }
+ }
+ return return_value;
}
/* Construct native Windows menu(bar) based on widget_value tree. */
-static int
+int
fill_in_menu (HMENU menu, widget_value *wv)
{
int items_added = 0;
return 0;
}
+/* Display help string for currently pointed to menu item. Not
+ supported on NT 3.51 and earlier, as GetMenuItemInfo is not
+ available. */
+void
+w32_menu_display_help (HMENU menu, UINT item, UINT flags)
+{
+ int pane = 0; /* TODO: Set this to pane number. */
+
+ HMODULE user32 = GetModuleHandle ("user32.dll");
+ FARPROC get_menu_item_info = GetProcAddress (user32, "GetMenuItemInfoA");
+
+ if (get_menu_item_info)
+ {
+ extern Lisp_Object Qmenu_item;
+ Lisp_Object *first_item;
+ Lisp_Object pane_name;
+ Lisp_Object menu_object;
+ MENUITEMINFO info;
+
+ bzero (&info, sizeof (info));
+ info.cbSize = sizeof (info);
+ info.fMask = MIIM_DATA;
+ get_menu_item_info (menu, item, FALSE, &info);
+
+ first_item = XVECTOR (menu_items)->contents;
+ if (EQ (first_item[0], Qt))
+ pane_name = first_item[MENU_ITEMS_PANE_NAME];
+ else if (EQ (first_item[0], Qquote))
+ /* This shouldn't happen, see w32_menu_show. */
+ pane_name = build_string ("");
+ else
+ pane_name = first_item[MENU_ITEMS_ITEM_NAME];
+
+ /* (menu-item MENU-NAME PANE-NUMBER) */
+ menu_object = Fcons (Qmenu_item,
+ Fcons (pane_name,
+ Fcons (make_number (pane), Qnil)));
+
+ show_help_echo (info.dwItemData ?
+ build_string ((char *) info.dwItemData) : Qnil,
+ Qnil, menu_object, make_number (item), 1);
+ }
+}
+
+
+
#endif /* HAVE_MENUS */
\f
syms_of_w32menu ()