diff src/menubar-msw.c @ 251:677f6a0ee643 r20-5b24

Import from CVS: tag r20-5b24
author cvs
date Mon, 13 Aug 2007 10:19:59 +0200
parents 83b3d10dcba9
children 157b30c96d03
line wrap: on
line diff
--- a/src/menubar-msw.c	Mon Aug 13 10:19:12 2007 +0200
+++ b/src/menubar-msw.c	Mon Aug 13 10:19:59 2007 +0200
@@ -101,303 +101,44 @@
 /* Current menubar or popup hashtable. gcpro'ed */
 static Lisp_Object current_hashtable;
 
-/* Bound by menubar.el */
-static Lisp_Object Qfind_menu_item;
-
 /* This is used to allocate unique ids to menu items.
    Items ids are in MENU_ITEM_ID_MIN to MENU_ITEM_ID_MAX.
    Allocation checks that the item is not already in
    the TOP_LEVEL_MENU */
-/* #### defines go to gui-msw.h */
+
+/* #### defines go to gui-msw.h, as the range is shared with toolbars
+   (If only toolbars will be implemented as common controls) */
 #define MENU_ITEM_ID_MIN 0x8000
 #define MENU_ITEM_ID_MAX 0xFFFF
 #define MENU_ITEM_ID_BITS(x) ((x) & 0x7FFF | 0x8000)
 static HMENU top_level_menu;
 
-/* ============= THIS STUFF MIGHT GO SOMEWHERE ELSE ================= */
-
-/* All these functions are windows sys independent, and are candidates
-   to go to lisp code instead */
-
-/*
- * DESCRIPTOR is a list in the form ({:keyword value}+ rest...).
- * This function extracts all the key-value pairs into the newly
- * created plist, and returns pointer to REST. Original list is not
- * modified (heaven save!)
- */
-Lisp_Object
-gui_parse_menu_keywords (Lisp_Object descriptor, Lisp_Object *plist)
-{
-  Lisp_Object pair, key, val;
-  *plist = Qnil;
-  LIST_LOOP (pair, descriptor)
-    {
-      if (!CONSP(pair))
-	signal_simple_error ("Mailformed gui entity descriptor", descriptor);
-      key = XCAR(pair);
-      if (!KEYWORDP (key))
-	return pair;
-      pair = XCDR (pair);
-      if (!CONSP(pair))
-	signal_simple_error ("Mailformed gui entity descriptor", descriptor);
-      val = XCAR (pair);
-      internal_plist_put (plist, key, val);
-    }
-  return pair;
-}
-
-/*
- * DESC is a vector describing a menu item. The function returns menu
- * item name in NAME, callback form in CALLBACK, and all key-values
- * pairs in PLIST. For old-style vectors, the plist is faked.
- */
-void
-gui_parse_button_descriptor (Lisp_Object desc, Lisp_Object *name, 
-			     Lisp_Object *callback, Lisp_Object *plist)
-{
-  int length = XVECTOR_LENGTH (desc);
-  Lisp_Object *contents = XVECTOR_DATA (desc);
-  int plist_p;
-
-  *name = Qnil;
-  *callback = Qnil;
-  *plist = Qnil;
-
-  if (length < 3)
-    signal_simple_error ("Button descriptors must be at least 3 long", desc);
-
-  /* length 3:		[ "name" callback active-p ]
-     length 4:		[ "name" callback active-p suffix ]
-     		   or	[ "name" callback keyword  value  ]
-     length 5+:		[ "name" callback [ keyword value ]+ ]
-   */
-  plist_p = (length >= 5 || KEYWORDP (contents [2]));
-
-  *name = contents [0];
-  *callback = contents [1];
-
-  if (!plist_p)
-    /* the old way */
-    {
-      internal_plist_put (plist, Q_active, contents [2]);
-      if (length == 4)
-	internal_plist_put (plist, Q_suffix, contents [3]);
-    }
-  else
-    /* the new way */
-    {
-      int i;
-      if (length & 1)
-	signal_simple_error (
-		"Button descriptor has an odd number of keywords and values",
-			     desc);
-
-      for (i = 2; i < length;)
-	{
-	  Lisp_Object key = contents [i++];
-	  Lisp_Object val = contents [i++];
-	  if (!KEYWORDP (key))
-	    signal_simple_error_2 ("Not a keyword", key, desc);
-	  internal_plist_put (plist, key, val);
-	}
-    }    
-}
-
-/*
- * Given PLIST of key-value pairs for a menu item or button, consult
- * :included and :config properties (the latter against
- * CONFLIST). Return value is non-zero when item should *not* appear.
- */
-int
-gui_plist_says_item_excluded (Lisp_Object plist, Lisp_Object conflist)
-{
-  Lisp_Object tem;
-  /* This function can call lisp */
+#define MAX_MENUITEM_LENGTH 128
 
-  /* Evaluate :included first */
-  tem = internal_plist_get (plist, Q_included);
-  if (!UNBOUNDP (tem))
-    {
-      tem = Feval (tem);
-      if (NILP (tem))
-	return 1;
-    }
-
-  /* Do :config if conflist is given */
-  if (!NILP (conflist))
-    {
-      tem = internal_plist_get (plist, Q_config);
-      if (!UNBOUNDP (tem))
-	{
-	  tem = Fmemq (tem, conflist);
-	  if (NILP (tem))
-	    return 1;
-	}
-    }
-
-  return 0;
-}
-    
-/*
- * Given PLIST of key-value pairs for a menu item or button, consult
- * :active property. Return non-zero if the item is *inactive*
- */
-int
-gui_plist_says_item_inactive (Lisp_Object plist)
-{
-  Lisp_Object tem;
-  /* This function can call lisp */
-
-  tem = internal_plist_get (plist, Q_active);
-  if (!UNBOUNDP (tem))
-    {
-      tem = Feval (tem);
-      if (NILP (tem))
-	return 1;
-    }
-
-  return 0;
-}
-
-/*
- * Given PLIST of key-value pairs for a menu item or button, evaluate
- * the form which is the value of :filter property. Filter function
- * given DESC as argument. If there's no :filter property, DESC is
- * returned, otherwise the value returned by the filter function is
- * returned. 
- */
-Lisp_Object
-gui_plist_apply_filter (Lisp_Object plist, Lisp_Object desc)
-{
-  Lisp_Object tem;
-  /* This function can call lisp */
-
-  tem = internal_plist_get (plist, Q_filter);
-  if (UNBOUNDP (tem))
-    return desc;
-  else
-    return call1 (tem, desc);
-}
-
-/*
- * This is tricky because there's no menu item styles in Windows, only
- * states: Each item may be given no checkmark, radio or check
- * mark. This function returns required mark style as determined by
- * PLIST. Return value is the value of :style property if the item is
- * :seleted, or nil otherwise
- */
-Lisp_Object
-gui_plist_get_current_style (Lisp_Object plist)
-{
-  Lisp_Object style, selected;
-  style = internal_plist_get (plist, Q_style);
-  if (UNBOUNDP (style) || NILP(style))
-    return Qnil;
-
-  selected = internal_plist_get (plist, Q_selected);
-  if (UNBOUNDP (selected) || NILP(Feval(selected)))
-    return Qnil;
-
-  return style;
-}
-
-Lisp_Object
-current_frame_menubar (CONST struct frame* f)
-{
-  struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
-  return symbol_value_in_buffer (Qcurrent_menubar, w->buffer);
-}
-
-/* ============ END IF STUFF THAT MIGHT GO SOMEWHERE ELSE =============== */
-
-/* Change these together */
-#define MAX_MENUITEM_LENGTH 128
-#define DISPLAYABLE_MAX_MENUITEM_LENGTH "128"
-
-static void 
-signal_item_too_long (Lisp_Object name)
-{
-    signal_simple_error ("Menu item is longer than "
-			 DISPLAYABLE_MAX_MENUITEM_LENGTH
-			 " characters", name);
-}
-
-/* #### If this function returned (FLUSHLEFT . FLUSHRIGHT) it also
-   could be moved above that line - it becomes window system
-   independant */
 /*
  * This returns Windows-style menu item string:
  * "Left Flush\tRight Flush"
  */
-static CONST char*
-plist_get_menu_item_name (Lisp_Object name, Lisp_Object callback, Lisp_Object plist)
+static char*
+displayable_menu_item (struct gui_item* pgui_item)
 {
   /* We construct the name in a static buffer. That's fine, beause
      menu items longer than 128 chars are probably programming errors,
      and better be caught than displayed! */
   
-  static char buf[MAX_MENUITEM_LENGTH];
-  char* p = buf;
-  int buf_left = MAX_MENUITEM_LENGTH - 1;
-  Lisp_Object tem;
-
-  /* Get name first */
-  buf_left -= XSTRING_LENGTH (name);
-  if (buf_left < 0)
-    signal_item_too_long (name);
-  strcpy (p, XSTRING_DATA (name));
-  p += XSTRING_LENGTH (name);
+  static char buf[MAX_MENUITEM_LENGTH+2];
+  unsigned int ll, lr;
 
-  /* Have suffix? */
-  tem = internal_plist_get (plist, Q_suffix);
-  if (!UNBOUNDP (tem))
-    {
-      if (!STRINGP (tem))
-	signal_simple_error (":suffix must be a string", tem);
-      buf_left -= XSTRING_LENGTH (tem) + 1;
-      if (buf_left < 0)
-	signal_item_too_long (name);
-      *p++ = ' ';
-      strcpy (p, XSTRING_DATA (tem));
-      p += XSTRING_LENGTH (tem);
-    }
+  /* Left flush part of the string */
+  ll = gui_item_display_flush_left (pgui_item, buf, MAX_MENUITEM_LENGTH);
 
-  /* Have keys? */
-  if (menubar_show_keybindings)
-    {
-      static char buf2 [1024];
-      buf2[0] = 0;
+  /* Right flush part */
+  assert (MAX_MENUITEM_LENGTH > ll + 1);
+  lr = gui_item_display_flush_right (pgui_item, buf + ll + 1,
+				     MAX_MENUITEM_LENGTH - ll - 1);
+  if (lr)
+    buf [ll] = '\t';
 
-      tem = internal_plist_get (plist, Q_keys);
-      if (!UNBOUNDP (tem))
-	{
-	  if (!STRINGP (tem))
-	    signal_simple_error (":keys must be a string", tem);
-	  if (XSTRING_LENGTH (tem) > sizeof (buf2) - 1)
-	    signal_item_too_long (name);
-	  strcpy (buf2, XSTRING_DATA (tem));
-	}
-      else if (SYMBOLP (callback))
-	{
-	  /* #### Warning, dependency here on current_buffer and point */
-	  /* #### I've borrowed this warning along with this code from
-	     menubar-x.c. What does that mean? -- kkm */
-	  where_is_to_char (callback, buf2);
-	}
-
-      if (buf2 [0])
-	{
-	  int n = strlen (buf2) + 1;
-	  buf_left -= n;
-	  if (buf_left < 0)
-	    signal_item_too_long (name);
-	  *p++ = '\t';
-	  strcpy (p, buf2);
-	  p += n-1;
-	}
-    }
-  
-  *p = 0;
   return buf;
 }
 
@@ -416,10 +157,11 @@
  * the hashtable rather than abandon it.
  */
 static Lisp_Object
-allocate_menu_item_id (Lisp_Object path, Lisp_Object name)
+allocate_menu_item_id (Lisp_Object path, Lisp_Object name, Lisp_Object suffix)
 {
-  UINT id = MENU_ITEM_ID_BITS (HASH2 (internal_hash (path, 0),
-				      internal_hash (name, 0)));
+  UINT id = MENU_ITEM_ID_BITS (HASH3 (internal_hash (path, 0),
+				      internal_hash (name, 0),
+				      internal_hash (suffix, 0)));
   do {
       id = MENU_ITEM_ID_BITS (id + 1);
   } while (GetMenuState (top_level_menu, id, MF_BYCOMMAND) != 0xFFFFFFFF);
@@ -429,12 +171,7 @@
 static HMENU
 create_empty_popup_menu (void)
 {
-  HMENU submenu = CreatePopupMenu ();
-  /* #### It seems that really we do not need "(empty)" at this stage */
-#if 0
-  AppendMenu (submenu, MF_STRING | MF_GRAYED, EMPTY_ITEM_ID, EMPTY_ITEM_NAME);
-#endif
-  return submenu;
+  return CreatePopupMenu ();
 }
 
 static void
@@ -473,10 +210,8 @@
   else if (VECTORP (item))
     {
       /* An ordinary item - hash its name and callback form. */
-      Lisp_Object plist, name, callback;
-      gui_parse_button_descriptor (item, &name, &callback, &plist);
-      return HASH2 (internal_hash (name, 0),
-		    internal_hash (callback, 0));
+      return HASH2 (internal_hash (XVECTOR_DATA(item)[0], 0),
+		    internal_hash (XVECTOR_DATA(item)[1], 0));
     }
  
   /* An error - will be caught later */
@@ -488,7 +223,6 @@
 			Lisp_Object hash_tab, Lisp_Object item, int flush_right)
 {
   MENUITEMINFO item_info;
-  struct gcpro gcpro1, gcpro2;
 
   item_info.cbSize = sizeof (item_info);
   item_info.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
@@ -511,20 +245,23 @@
   else if (CONSP (item))
     {
       /* Submenu */
-      Lisp_Object subname = XCAR (item);
-      Lisp_Object plist;
       HMENU submenu;
-	
-      if (!STRINGP (subname))
+      struct gui_item gui_item;
+      struct gcpro gcpro1;
+
+      gui_item_init (&gui_item);
+      GCPRO1 (gui_item);
+      gcpro1.nvars = GUI_ITEM_GCPRO_COUNT;
+
+      menu_parse_submenu_keywords (item, &gui_item);
+
+      if (!STRINGP (gui_item.name))
 	signal_simple_error ("Menu name (first element) must be a string", item);
 
-      item = gui_parse_menu_keywords (XCDR (item), &plist);
-      GCPRO1 (plist);
-
-      if (gui_plist_says_item_excluded (plist, Vmenubar_configuration))
+      if (!gui_item_included_p (&gui_item, Vmenubar_configuration))
 	return;
 
-      if (gui_plist_says_item_inactive (plist))
+      if (!gui_item_active_p (&gui_item))
 	item_info.fState = MFS_GRAYED;
       /* Temptation is to put 'else' right here. Although, the
 	 displayed item won't have an arrow indicating that it is a
@@ -532,46 +269,50 @@
       submenu = create_empty_popup_menu();
 
       item_info.fMask |= MIIM_SUBMENU;
-      item_info.dwTypeData = plist_get_menu_item_name (subname, Qnil, plist);
+      item_info.dwTypeData = displayable_menu_item (&gui_item);
       item_info.hSubMenu = submenu;
 
-      UNGCPRO; /* plist */
-
       if (!(item_info.fState & MFS_GRAYED))
 	{
 	  /* Now add the full submenu path as a value to the hash table,
 	     keyed by menu handle */
 	  if (NILP(path))
-	    path = list1 (subname);
-	  else {
-	    Lisp_Object arg[2];
-	    arg[0] = path;
-	    arg[1] = list1 (subname);
-	    GCPRO1 (arg[1]);
-	    path = Fappend (2, arg);
-	    UNGCPRO; /* arg[1] */
-	  }
+	    /* list1 cannot GC */
+	    path = list1 (gui_item.name);
+	  else
+	    {
+	      Lisp_Object arg[2] = { path, list1 (gui_item.name) };
+	      /* Fappend gcpro'es its arg */
+	      path = Fappend (2, arg);
+	    }
 
-	  GCPRO1 (path);
+	  /* Fputhash GCPRO'es PATH */
 	  Fputhash (hmenu_to_lisp_object (submenu), path, hash_tab);
-	  UNGCPRO; /* path */
 	}
+      UNGCPRO; /* gui_item */
     } 
   else if (VECTORP (item))
     {
       /* An ordinary item */
-      Lisp_Object plist, name, callback, style, id;
-      
-      gui_parse_button_descriptor (item, &name, &callback, &plist);
-      GCPRO2 (plist, callback);
+      Lisp_Object style, id;
+      struct gui_item gui_item;
+      struct gcpro gcpro1;
 
-      if (gui_plist_says_item_excluded (plist, Vmenubar_configuration))
+      gui_item_init (&gui_item);
+      GCPRO1 (gui_item);
+      gcpro1.nvars = GUI_ITEM_GCPRO_COUNT;
+
+      gui_parse_item_keywords (item, &gui_item);
+
+      if (!gui_item_included_p (&gui_item, Vmenubar_configuration))
 	return;
 
-      if (gui_plist_says_item_inactive (plist))
-	item_info.fState |= MFS_GRAYED;
+      if (!gui_item_active_p (&gui_item))
+	item_info.fState = MFS_GRAYED;
 
-      style = gui_plist_get_current_style (plist);
+      style = (NILP (gui_item.selected) || NILP (Feval (gui_item.selected))
+	       ? Qnil : gui_item.style);
+
       if (EQ (style, Qradio))
 	{
 	  item_info.fType |= MFT_RADIOCHECK;
@@ -582,18 +323,19 @@
 	  item_info.fState |= MFS_CHECKED;
 	}
 
-      id = allocate_menu_item_id (path, name);
-      Fputhash (id, callback, hash_tab);
-      
-      UNGCPRO; /* plist, callback */
+      id = allocate_menu_item_id (path, gui_item.name,
+				  gui_item.suffix);
+      Fputhash (id, gui_item.callback, hash_tab);
 
       item_info.wID = (UINT) XINT(id);
       item_info.fType |= MFT_STRING;
-      item_info.dwTypeData = plist_get_menu_item_name (name, callback, plist);
+      item_info.dwTypeData = displayable_menu_item (&gui_item);
+
+      UNGCPRO; /* gui_item */
     }
   else
     {
-      signal_simple_error ("Ill-constructed menu descriptor", item);
+      signal_simple_error ("Mailformed menu item descriptor", item);
     }
 
   if (flush_right)
@@ -614,13 +356,18 @@
  * Return value is the menu checksum.
  */
 static unsigned long
-populate_or_checksum_helper (HMENU menu, Lisp_Object path, Lisp_Object descriptor,
+populate_or_checksum_helper (HMENU menu, Lisp_Object path, Lisp_Object desc,
 			     Lisp_Object hash_tab, int bar_p, int populate_p)
 {
-  Lisp_Object menu_name, plist, item_desc;
+  Lisp_Object item_desc;
   int deep_p, flush_right;
   struct gcpro gcpro1;
   unsigned long checksum = 0;
+  struct gui_item gui_item;
+
+  gui_item_init (&gui_item);
+  GCPRO1 (gui_item);
+  gcpro1.nvars = GUI_ITEM_GCPRO_COUNT;
 
   /* Will initially contain only "(empty)" */
   if (populate_p)
@@ -629,33 +376,20 @@
   /* PATH set to nil indicates top-level popup or menubar */
   deep_p = !NILP (path);
 
-  if (!deep_p)
-    top_level_menu = menu;
+  /* Fetch keywords prepending the item list */
+  desc = menu_parse_submenu_keywords (desc, &gui_item);
 
-  if (!CONSP(descriptor))
-    signal_simple_error ("Menu descriptor must be a list", descriptor);
+  /* Check that menu name is specified when expected */
+  if (NILP (gui_item.name) && deep_p)
+    signal_simple_error ("Menu must have a name", desc);
 
-  if (STRINGP (XCAR (descriptor)))
-    {
-      menu_name = XCAR (descriptor);
-      descriptor = XCDR (descriptor);
-    }
-  else
-    {
-      menu_name = Qnil;
-      if (deep_p) /* Not a popup or bar */
-	signal_simple_error ("Menu must have a name", descriptor);
-    }
+  /* Apply filter if specified */
+  if (!NILP (gui_item.filter))
+    desc = call1 (gui_item.filter, desc);
 
-  /* Fetch keywords prepending the item list */
-  descriptor = gui_parse_menu_keywords (descriptor, &plist);
-  GCPRO1 (plist);
-  descriptor = gui_plist_apply_filter (plist, descriptor);
-  UNGCPRO; /* plist */
-  
-  /* Loop thru the descriptor's CDR and add items for each entry */
+  /* Loop thru the desc's CDR and add items for each entry */
   flush_right = 0;
-  EXTERNAL_LIST_LOOP (item_desc, descriptor)
+  EXTERNAL_LIST_LOOP (item_desc, desc)
     {
       if (NILP (XCAR (item_desc)))
 	{
@@ -681,47 +415,30 @@
       /* Add the header to the popup, if told so. The same as in X - an
 	 insensitive item, and a separator (Seems to me, there were
 	 two separators in X... In Windows this looks ugly, anywats. */
-      if (!bar_p && !deep_p && popup_menu_titles && !NILP(menu_name))
+      if (!bar_p && !deep_p && popup_menu_titles && !NILP(gui_item.name))
 	{
+	  CHECK_STRING (gui_item.name);
 	  InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED,
-		      0, XSTRING_DATA(menu_name));
+		      0, XSTRING_DATA(gui_item.name));
 	  InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
 	  SetMenuDefaultItem (menu, 0, MF_BYPOSITION);
 	}
     }
+  UNGCPRO; /* gui_item */
   return checksum;
 }
 
 static void
-populate_menu (HMENU menu, Lisp_Object path, Lisp_Object descriptor,
+populate_menu (HMENU menu, Lisp_Object path, Lisp_Object desc,
 			     Lisp_Object hash_tab, int bar_p)
 {
-  populate_or_checksum_helper (menu, path, descriptor, hash_tab, bar_p, 1);
+  populate_or_checksum_helper (menu, path, desc, hash_tab, bar_p, 1);
 }
 
 static unsigned long
-checksum_menu (Lisp_Object descriptor)
-{
-  return populate_or_checksum_helper (NULL, Qnil, descriptor, Qunbound, 0, 0);
-}
-
-static Lisp_Object
-find_menu (Lisp_Object desc, Lisp_Object path)
+checksum_menu (Lisp_Object desc)
 {
-  /* #### find-menu-item is not what's required here. 
-     Need to write this in C, or improve lisp */
-  if (!NILP (path))
-    {
-      desc = call2 (Qfind_menu_item, desc, path);
-      /* desc is (supposed to be) (ITEM . PARENT). Supposed
-         to signal but sometimes manages to return nil */
-      if (!NILP(desc))
-	{
-	  CHECK_CONS (desc);
-	  desc = XCAR (desc);
-	}
-    }
-  return desc;
+  return populate_or_checksum_helper (NULL, Qnil, desc, Qunbound, 0, 0);
 }
 
 static void
@@ -733,6 +450,8 @@
 		      ? symbol_value_in_buffer (Qcurrent_menubar, w->buffer)
 		      : Qnil);
 
+  top_level_menu = menubar;
+
   if (NILP (desc) && menubar != NULL)
     {
       /* Menubar has gone */
@@ -842,13 +561,9 @@
 
   /* Now find a desc chunk for it. If none, then probably menu open
      hook has played too much games around stuff */
-  desc = current_menudesc;
-  if (!NILP (path))
-    {
-      desc = find_menu (desc, path);
-      if (NILP (desc))
-	signal_simple_error ("This menu does not exist any more", path);
-    }
+  desc = Fmenu_find_real_submenu (current_menudesc, path);
+  if (NILP (desc))
+    signal_simple_error ("This menu does not exist any more", path);
 
   /* Now, stuff it */
   /* DESC may be generated by filter, so we have to gcpro it */
@@ -862,6 +577,10 @@
 unsafe_handle_wm_initmenu_1 (struct frame* f)
 {
   /* This function can call lisp */
+
+  /* NOTE: This is called for the bar only, WM_INITMENU
+     for popups is filtered out */
+
   /* #### - this menubar update mechanism is expensively anti-social and
      the activate-menubar-hook is now mostly obsolete. */
 
@@ -878,20 +597,6 @@
   return Qt;
 }
 
-#ifdef KKM_DOES_NOT_LIKE_UNDOCS_SOMETIMES
-
-/* #### This may become wrong in future Windows */
-
-static Lisp_Object
-unsafe_handle_wm_exitmenuloop_1 (struct frame* f)
-{
-  if (!NILP (current_tracking_popup))
-    prune_menubar (f);
-  return Qt;
-}
-
-#endif
-
 /*
  * Return value is Qt if we have dispatched the command,
  * or Qnil if id has not been mapped to a callback.
@@ -924,7 +629,8 @@
   else if (CONSP (command))
       funcsym = Qeval;
   else
-    signal_simple_error ("Illegal callback", command);
+    signal_simple_error ("Callback must be either evallable form or a symbol",
+			 command);
 
   XSETFRAME (frame, f);
   enqueue_misc_user_event (frame, funcsym, command);
@@ -959,14 +665,6 @@
   return unsafe_handle_wm_initmenu_1 (wm_initmenu_frame);
 }
 
-#ifdef KKM_DOES_NOT_LIKE_UNDOCS_SOMETIMES
-static Lisp_Object
-unsafe_handle_wm_exitmenuloop (Lisp_Object u_n_u_s_e_d)
-{
-  return unsafe_handle_wm_exitmenuloop_1 (wm_initmenu_frame);
-}
-#endif
-
 Lisp_Object
 mswindows_handle_wm_initmenupopup (HMENU hmenu, struct frame* frm)
 {
@@ -988,15 +686,12 @@
   return Qt;
 }
 
+/* #### This function goes away. Removing it now may
+   interfere with pending patch 980128-jhar */
 Lisp_Object
 mswindows_handle_wm_exitmenuloop (struct frame* f)
 {
-#ifdef KKM_DOES_NOT_LIKE_UNDOCS_SOMETIMES
-  wm_initmenu_frame = f;
-  return mswindows_protect_modal_loop (unsafe_handle_wm_exitmenuloop, Qnil);
-#else
   return Qt;
-#endif
 }
 
 
@@ -1007,7 +702,13 @@
 static void
 mswindows_update_frame_menubars (struct frame* f)
 {
-  update_frame_menubar_maybe (f);
+  /* #### KLUDGE. menubar.c calls us when the following
+     condition is true:
+	(f->menubar_changed || f->windows_changed)
+     Is that much really necessary?
+     */
+  if (f->menubar_changed)
+    update_frame_menubar_maybe (f);
 }
 
 static void
@@ -1060,6 +761,7 @@
   current_hashtable = Fmake_hashtable (make_int(10), Qequal);
   menu = create_empty_popup_menu();
   Fputhash (hmenu_to_lisp_object (menu), Qnil, current_hashtable);
+  top_level_menu = menu;
   
   ok = TrackPopupMenu (menu,
 		       TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
@@ -1086,7 +788,6 @@
 void
 syms_of_menubar_mswindows (void)
 {
-  defsymbol (&Qfind_menu_item, "find-menu-item");
 }
 
 void
@@ -1106,5 +807,3 @@
   staticpro (&current_menudesc);
   staticpro (&current_hashtable);
 
-  Fprovide (intern ("mswindows-menubars"));
-}