(x_free_gcs): Add prototype.
[bpt/emacs.git] / src / w32menu.c
index 6ca1aa7..49052c3 100644 (file)
@@ -24,11 +24,13 @@ Boston, MA 02111-1307, USA.  */
 #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.  */
@@ -43,7 +45,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 
 #undef HAVE_MULTILINGUAL_MENU
-#undef HAVE_DIALOGS /* NTEMACS_TODO: Implement native dialogs.  */
+#undef HAVE_DIALOGS /* TODO: Implement native dialogs.  */
 
 /******************************************************************/
 /* Definitions copied from lwlib.h */
@@ -51,9 +53,6 @@ Boston, MA 02111-1307, USA.  */
 typedef void * XtPointer;
 typedef char Boolean;
 
-#define True 1
-#define False 0
-
 enum button_type
 {
   BUTTON_TYPE_NONE,
@@ -69,8 +68,8 @@ typedef struct _widget_value
   char*                value;
   /* keyboard equivalent. no implications for XtTranslations */ 
   char*                key;
-  /* Help string.  */
-  char*        help;
+  /* Help string or null if none.  */
+  char         *help;
   /* true if enabled */
   Boolean      enabled;
   /* true if selected */
@@ -397,7 +396,8 @@ keymap_panes (keymaps, nmaps, notreal)
      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 ();
 }
@@ -639,7 +639,8 @@ cached information about equivalent key sequences.")
 
       /* 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 ();
@@ -718,15 +719,11 @@ cached information about equivalent key sequences.")
 
   /* 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));
@@ -743,7 +740,7 @@ cached information about equivalent key sequences.")
 
       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));
@@ -759,7 +756,7 @@ cached information about equivalent key sequences.")
        {
          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))
@@ -837,13 +834,14 @@ on the left of the dialog box and all following items on the right.\n\
 
   /* 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;
 
@@ -1000,27 +998,31 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
              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;
@@ -1108,8 +1110,7 @@ single_submenu (item_key, item_name, maps)
   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.  */
@@ -1172,7 +1173,7 @@ single_submenu (item_key, item_name, maps)
          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);
@@ -1210,8 +1211,6 @@ single_submenu (item_key, item_name, maps)
          Lisp_Object item_name, enable, descrip, def, type, selected;
           Lisp_Object help;
 
-          /* NTEMACS_TODO: implement popup/modeline help for menus. */
-
          item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
          enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
          descrip
@@ -1223,9 +1222,9 @@ single_submenu (item_key, item_name, maps)
 
 #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 ();
@@ -1564,7 +1563,6 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
     = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
   int submenu_depth = 0;
   int first_pane;
-  int next_release_must_exit = 0;
 
   *error = NULL;
 
@@ -1619,7 +1617,7 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
          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);
@@ -1671,9 +1669,9 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
 
 #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))
-            descrip = string_make_unibyte (descrip);
+            descrip = ENCODE_SYSTEM (descrip);
 #endif
 
          wv = xmalloc_widget_value ();
@@ -1725,10 +1723,11 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
 
 #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;
@@ -1743,9 +1742,6 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
   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;
 
@@ -1758,6 +1754,9 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
      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
@@ -1947,7 +1946,7 @@ w32_dialog_show (f, keymaps, title, error)
   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.  */
@@ -2034,7 +2033,10 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
   int return_value;
 
   if (name_is_separator (wv->name))
-    fuFlags = MF_SEPARATOR;
+    {
+      fuFlags = MF_SEPARATOR;
+      out_string = NULL;
+    }
   else 
     {
       if (wv->enabled)
@@ -2052,13 +2054,14 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       else
        out_string = wv->name;
 
-      if (wv->title || wv->call_data == 0)
+      if (wv->title)
        {
 #if 0  /* no GC while popup menu is active */
          out_string = LocalAlloc (0, strlen (wv->name) + 1);
          strcpy (out_string, wv->name);
 #endif
-         fuFlags = MF_OWNERDRAW | MF_DISABLED;
+          /* TODO: Why has owner-draw stopped working? */
+         fuFlags |= /*MF_OWNERDRAW |*/ MF_DISABLED;
        }
 
       /* Draw radio buttons and tickboxes. */
@@ -2077,7 +2080,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
     AppendMenu (menu,
                 fuFlags,
                 item != NULL ? (UINT) item : (UINT) wv->call_data,
-                (fuFlags == MF_SEPARATOR) ? NULL: out_string );
+                out_string );
 
   /* This must be done after the menu item is created.  */
   {
@@ -2090,7 +2093,8 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
         bzero (&info, sizeof (info));
         info.cbSize = sizeof (info);
         info.fMask = MIIM_DATA;
-        /* Set help string for menu item. */
+
+        /* Set help string for menu item.  */
         info.dwItemData = (DWORD)wv->help;
 
         if (wv->button_type == BUTTON_TYPE_RADIO)
@@ -2098,9 +2102,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
             /* 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;
+            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);
@@ -2110,7 +2116,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 }
 
 /* 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;
@@ -2153,14 +2159,17 @@ popup_activated ()
 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)
     {
-      struct gcpro gcpro1;
-      extern Lisp_Object Vshow_help_function;
-      Lisp_Object msg;
+      extern Lisp_Object Qmenu_item;
+      Lisp_Object *first_item;
+      Lisp_Object pane_name;
+      Lisp_Object menu_object;
       MENUITEMINFO info;
 
       bzero (&info, sizeof (info));
@@ -2168,19 +2177,23 @@ w32_menu_display_help (HMENU menu, UINT item, UINT flags)
       info.fMask = MIIM_DATA;
       get_menu_item_info (menu, item, FALSE, &info);
 
-      msg = info.dwItemData ? build_string ((char *) info.dwItemData) : Qnil;
-      GCPRO1 (msg);
+      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];
 
-      if (!NILP (Vshow_help_function))
-        call1 (Vshow_help_function, msg);
-      else if (!MINI_WINDOW_P (XWINDOW (selected_window)))
-        {
-          if (STRINGP(msg))
-            message3_nolog (msg, XSTRING (msg)->size, STRING_MULTIBYTE (msg));
-          else
-            message (0);
-        }
-      UNGCPRO;
+      /* (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);
     }
 }