#include <config.h>
#include <signal.h>
+
#include <stdio.h>
#include "lisp.h"
#include "termhooks.h"
#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. */
+
/******************************************************************/
/* Definitions copied from lwlib.h */
#define True 1
#define False 0
+#if 0 /* Not used below. */
typedef enum _change_type
{
NO_CHANGE = 0,
VISIBLE_CHANGE = 2,
STRUCTURAL_CHANGE = 3
} change_type;
+#endif
+
+enum button_type
+{
+ BUTTON_TYPE_NONE,
+ BUTTON_TYPE_TOGGLE,
+ BUTTON_TYPE_RADIO
+};
typedef struct _widget_value
{
char* value;
/* keyboard equivalent. no implications for XtTranslations */
char* key;
+ /* Help string or null if none. */
+ char *help;
/* true if enabled */
Boolean enabled;
/* true if selected */
Boolean selected;
+ /* The type of a button. */
+ enum button_type button_type;
/* true if menu title */
Boolean title;
#if 0
void set_frame_menubar ();
-static Lisp_Object w32_menu_show ();
+static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object));
static Lisp_Object w32_dialog_show ();
+static Lisp_Object w32_menu_show ();
static void keymap_panes ();
static void single_keymap_panes ();
#define MENU_ITEMS_PANE_PREFIX 2
#define MENU_ITEMS_PANE_LENGTH 3
-#define MENU_ITEMS_ITEM_NAME 0
-#define MENU_ITEMS_ITEM_ENABLE 1
-#define MENU_ITEMS_ITEM_VALUE 2
-#define MENU_ITEMS_ITEM_EQUIV_KEY 3
-#define MENU_ITEMS_ITEM_DEFINITION 4
-#define MENU_ITEMS_ITEM_LENGTH 5
+enum menu_item_idx
+{
+ MENU_ITEMS_ITEM_NAME = 0,
+ MENU_ITEMS_ITEM_ENABLE,
+ MENU_ITEMS_ITEM_VALUE,
+ MENU_ITEMS_ITEM_EQUIV_KEY,
+ MENU_ITEMS_ITEM_DEFINITION,
+ MENU_ITEMS_ITEM_TYPE,
+ MENU_ITEMS_ITEM_SELECTED,
+ MENU_ITEMS_ITEM_HELP,
+ MENU_ITEMS_ITEM_LENGTH
+};
static Lisp_Object menu_items;
Xt on behalf of one of the widget sets. */
static int popup_activated_flag;
+static int next_menubar_widget_id;
+
/* This is set nonzero after the user activates the menu bar, and set
to zero again after the menu bars are redisplayed by prepare_menu_bar.
While it is nonzero, all calls to set_frame_menubar go deep.
\f
/* Return the frame whose ->output_data.w32->menubar_widget equals
- MENU, or 0 if none. */
+ ID, or 0 if none. */
static struct frame *
-menubar_id_to_frame (HMENU menu)
+menubar_id_to_frame (id)
+ HMENU id;
{
Lisp_Object tail, frame;
FRAME_PTR f;
if (!GC_FRAMEP (frame))
continue;
f = XFRAME (frame);
- if (!FRAME_W32_P (f))
+ if (!FRAME_WINDOW_P (f))
continue;
- if (f->output_data.w32->menubar_widget == menu)
+ if (f->output_data.w32->menubar_widget == id)
return f;
}
return 0;
XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
}
-/* Push one menu item into the current pane.
- NAME is the string to display. ENABLE if non-nil means
- this item can be selected. KEY is the key generated by
- choosing this item, or nil if this item doesn't really have a definition.
- DEF is the definition of this item.
- EQUIV is the textual description of the keyboard equivalent for
- this item (or nil if none). */
+/* Push one menu item into the current pane. NAME is the string to
+ display. ENABLE if non-nil means this item can be selected. KEY
+ is the key generated by choosing this item, or nil if this item
+ doesn't really have a definition. DEF is the definition of this
+ item. EQUIV is the textual description of the keyboard equivalent
+ for this item (or nil if none). TYPE is the type of this menu
+ item, one of nil, `toggle' or `radio'. */
static void
-push_menu_item (name, enable, key, def, equiv)
- Lisp_Object name, enable, key, def, equiv;
+push_menu_item (name, enable, key, def, equiv, type, selected, help)
+ Lisp_Object name, enable, key, def, equiv, type, selected, help;
{
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
XVECTOR (menu_items)->contents[menu_items_used++] = key;
XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
XVECTOR (menu_items)->contents[menu_items_used++] = def;
+ XVECTOR (menu_items)->contents[menu_items_used++] = type;
+ XVECTOR (menu_items)->contents[menu_items_used++] = selected;
+ XVECTOR (menu_items)->contents[menu_items_used++] = help;
}
\f
/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
int maxdepth, notreal;
int *notbuttons_ptr;
{
- Lisp_Object def, map, item_string, enabled;
+ Lisp_Object map, item_string, enabled;
struct gcpro gcpro1, gcpro2;
int res;
if (!NILP (prefix))
item_string = concat2 (prefix, item_string);
}
-#endif /* not HAVE_BOXES */
+#endif /* HAVE_BOXES */
#if 0
if (!NILP(map))
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_KEYEQ],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
#if 1
/* Display a submenu using the toolkit. */
{
item = Fcar (tail);
if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil, Qt, Qnil);
+ push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
else if (NILP (item))
push_left_right_boundary ();
else
CHECK_CONS (item, 0);
item1 = Fcar (item);
CHECK_STRING (item1, 1);
- push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil);
+ push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
}
}
}
(position, menu)
Lisp_Object position, menu;
{
- int number_of_panes, panes;
Lisp_Object keymap, tem;
int xpos, ypos;
Lisp_Object title;
char *error_name;
Lisp_Object selection;
- int i, j;
FRAME_PTR f;
Lisp_Object x, y, window;
int keymaps = 0;
|| (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
{
/* Use the mouse's current position. */
- FRAME_PTR new_f = selected_frame;
+ FRAME_PTR new_f = SELECTED_FRAME ();
Lisp_Object bar_window;
- int part;
+ enum scroll_bar_part part;
unsigned long time;
if (mouse_position_hook)
CHECK_LIVE_WINDOW (window, 0);
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- xpos = (FONT_WIDTH (f->output_data.w32->font)
+ xpos = (FONT_WIDTH (FRAME_FONT (f))
* XFASTINT (XWINDOW (window)->left));
- ypos = (f->output_data.w32->line_height
+ ypos = (FRAME_LINE_HEIGHT (f)
* XFASTINT (XWINDOW (window)->top));
}
else
{
#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;
+ FRAME_PTR new_f = SELECTED_FRAME ();
Lisp_Object bar_window;
int part;
unsigned long time;
but I don't want to make one now. */
CHECK_WINDOW (window, 0);
-#if 1
+#ifndef HAVE_DIALOGS
/* Display a menu with these alternatives
in the middle of frame F. */
{
return Fx_popup_menu (newpos,
Fcons (Fcar (contents), Fcons (contents, Qnil)));
}
-#else
+#else /* HAVE_DIALOGS */
{
Lisp_Object title;
char *error_name;
if (error_name) error (error_name);
return selection;
}
-#endif
+#endif /* HAVE_DIALOGS */
}
/* Activate the menu bar of frame F.
This way we can safely execute Lisp code. */
+void
x_activate_menubar (f)
FRAME_PTR f;
{
int len;
Lisp_Object *mapvec;
widget_value **submenu_stack;
- int mapno;
int previous_items = menu_items_used;
int top_level_items = 0;
as opposed to a submenu. */
top_level_items = 1;
push_menu_pane (Qnil, Qnil);
- push_menu_item (item_name, Qt, item_key, mapvec[i], Qnil);
+ push_menu_item (item_name, Qt, item_key, mapvec[i],
+ Qnil, Qnil, Qnil, Qnil);
}
else
single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
wv->name = "menu";
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
save_wv = 0;
prev_wv = 0;
char *pane_string;
pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
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);
+#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
/* If there is just one top-level pane, put all its items directly
wv->name++;
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
}
save_wv = wv;
prev_wv = 0;
else
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def;
+ Lisp_Object item_name, enable, descrip, def, type, selected;
+ Lisp_Object 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];
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 (STRING_MULTIBYTE (item_name))
+ item_name = string_make_unibyte (item_name);
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ descrip = string_make_unibyte (descrip);
+#endif
wv = xmalloc_widget_value ();
if (prev_wv)
as long as pointers have enough bits to hold small integers. */
wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
wv->enabled = !NILP (enable);
+
+ if (NILP (type))
+ wv->button_type = BUTTON_TYPE_NONE;
+ else if (EQ (type, QCradio))
+ wv->button_type = BUTTON_TYPE_RADIO;
+ else if (EQ (type, QCtoggle))
+ wv->button_type = BUTTON_TYPE_TOGGLE;
+ else
+ abort ();
+
+ wv->selected = !NILP (selected);
+ if (STRINGP (help))
+ wv->help = XSTRING (help)->data;
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
int deep_p;
{
HMENU menubar_widget = f->output_data.w32->menubar_widget;
- Lisp_Object tail, items, frame;
+ Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
wv->name = "menubar";
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
if (deep_p)
first_wv->contents = wv;
/* Don't set wv->name here; GC during the loop might relocate it. */
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
prev_wv = wv;
}
else
{
/* Make a widget-value tree containing
- just the top level menu bar strings.
-
- It turns out to be worth comparing the new contents with the
- previous contents to avoid unnecessary rebuilding even of just
- the top-level menu bar, which turns out to be fairly slow. We
- co-opt f->menu_bar_vector for this purpose, since its contents
- are effectively discarded at this point anyway.
-
- Note that the lisp-level hooks have already been run by
- update_menu_bar - it's kinda a shame the code is duplicated
- above as well for deep_p, but there we are. */
+ just the top level menu bar strings. */
items = FRAME_MENU_BAR_ITEMS (f);
-
- /* If there has been no change in the Lisp-level contents of just
- the menu bar itself, skip redisplaying it. Just exit. */
- for (i = 0; i < f->menu_bar_items_used; i += 4)
- if (i == XVECTOR (items)->size
- || (XVECTOR (f->menu_bar_vector)->contents[i]
- != XVECTOR (items)->contents[i]))
- break;
- if (i == XVECTOR (items)->size && i == f->menu_bar_items_used && i != 0)
- return;
-
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object string;
wv->name = (char *) XSTRING (string)->data;
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
/* This prevents lwlib from assuming this
menu item is really supposed to be empty. */
/* The EMACS_INT cast avoids a warning.
prev_wv = wv;
}
- /* Remember the contents of FRAME_MENU_BAR_ITEMS (f) in
- f->menu_bar_vector, so we can check whether the top-level
- menubar contents have changed next time. */
- if (XVECTOR (f->menu_bar_vector)->size < XVECTOR (items)->size)
- f->menu_bar_vector
- = Fmake_vector (make_number (XVECTOR (items)->size), Qnil);
- bcopy (XVECTOR (items)->contents,
- XVECTOR (f->menu_bar_vector)->contents,
- XVECTOR (items)->size * sizeof (Lisp_Object));
- f->menu_bar_items_used = XVECTOR (items)->size;
+ /* Forget what we thought we knew about what is in the
+ detailed contents of the menu bar menus.
+ Changing the top level always destroys the contents. */
+ f->menu_bar_items_used = 0;
}
/* Create or update the menu bar widget. */
Lisp_Object *subprefix_stack
= (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
int submenu_depth = 0;
-
int first_pane;
int next_release_must_exit = 0;
wv->name = "menu";
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
first_pane = 1;
char *pane_string;
pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
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);
+#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
/* If there is just one top-level pane, put all its items directly
wv->name++;
wv->value = 0;
wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
save_wv = wv;
prev_wv = 0;
}
else
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def;
+ Lisp_Object item_name, enable, descrip, def, type, selected;
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];
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];
+
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
+ item_name = string_make_unibyte (item_name);
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ item_name = string_make_unibyte (descrip);
+#endif
wv = xmalloc_widget_value ();
if (prev_wv)
restricted to 16-bits.. */
wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
wv->enabled = !NILP (enable);
+
+ if (NILP (type))
+ wv->button_type = BUTTON_TYPE_NONE;
+ else if (EQ (type, QCtoggle))
+ wv->button_type = BUTTON_TYPE_TOGGLE;
+ else if (EQ (type, QCradio))
+ wv->button_type = BUTTON_TYPE_RADIO;
+ else
+ abort ();
+
+ wv->selected = !NILP (selected);
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
wv_sep->name = "--";
wv_sep->next = first_wv->contents;
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRING_MULTIBYTE (title))
+ title = string_make_unibyte (title);
+#endif
wv_title->name = (char *) XSTRING (title)->data;
- /* Handle title specially, so it looks better. */
- wv_title->title = True;
+ wv_title->enabled = True;
+ wv_title->button_type = BUTTON_TYPE_NONE;
wv_title->next = wv_sep;
first_wv->contents = wv_title;
}
/* Actually create the menu. */
menu = CreatePopupMenu ();
fill_in_menu (menu, first_wv->contents);
-
+
/* Adjust coordinates to be root-window-relative. */
pos.x = x;
pos.y = y;
}
/* Actually create the dialog. */
-#if 0
+#ifdef HAVE_DIALOGS
dialog_id = widget_id_tick++;
menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
f->output_data.w32->widget, 1, 0,
menu_item_selection = 0;
/* Display the menu. */
-#if 0
+#ifdef HAVE_DIALOGS
lw_pop_up_all_widgets (dialog_id);
popup_activated_flag = 1;
#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
}
if (item != NULL)
return 1;
}
+int
+popup_activated ()
+{
+ /* popup_activated_flag not actually used on W32 */
+ return 0;
+}
+
#endif /* HAVE_MENUS */
\f
syms_of_w32menu ()