[AD] active_menu_player bug

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Hi,

In src/gui.c, when d_menu_proc opens a new menu, it sets the global pointer 
"active_menu_player". This pointer is only ever used for menus started by 
d_menu_proc.

There is a non documented assumption that the menu player designated by 
active_menu_player was started by a d_menu_proc that is part of the currently 
active dialog.

When a new dialog is started while the current one has a menu open, the 
assumption is broken: the currently active menu and the currently active 
dialog do not match anymore. This leads to a crash.

The attached patch documents the assumption, enforces it with an ASSERT (more 
might be needed), and fixes the crash by making init_dialog close the 
active_menu_player if necessary.

However, I don't claim to fully understand the code in gui.c (it is rather
intricate :-), so my fix might not be the best one, or even correct!

-- 
Julien Cugnière

PS: many thanks to Matthew for his patch creator :-)
--- src/gui.c	Thu Apr 28 08:53:37 2005 UTC
+++ src/gui.c	Thu May 26 15:41:50 2005 UTC
@@ -39,7 +39,17 @@
 int gui_font_baseline = 0;


-/* pointer to the currently active dialog and menu objects */
+/* Pointers to the currently active dialog and menu objects.
+ *
+ * Note: active_dialog_player always points to the currently active dialog
+ * player. However, active_menu_player only ever points to menu players
+ * started by a d_menu_proc. The code also assumes that that d_menu_proc can
+ * be found in the currently active dialog.
+ *
+ * Note: active_dialog points to the whole dialog currently running. However,
+ * active_menu points to the *current item* of the currently running menu,
+ * and should really have been called active_menu_item.
+ */
 static DIALOG_PLAYER *active_dialog_player = NULL;
 static MENU_PLAYER *active_menu_player = NULL;
 static int active_menu_player_zombie = FALSE;
@@ -864,6 +874,10 @@
    int c;
    ASSERT(dialog);

+   /* close any menu opened by a d_menu_proc */
+   if (active_menu_player)
+      object_message(active_menu_player->dialog, MSG_LOSTMOUSE, 0);
+
    player = malloc(sizeof(DIALOG_PLAYER));
    if (!player) {
       *allegro_errno = ENOMEM;
@@ -1054,6 +1068,7 @@
 	 for (c=0; player->dialog[c].proc; c++)
 	    if (&player->dialog[c] == active_menu_player->dialog)
 	       break;
+	 ASSERT(player->dialog[c].proc);

 	 MESSAGE(c, MSG_LOSTMOUSE, 0);
 	 goto getout;
@@ -2390,4 +2405,3 @@

    return ret;
 }
-


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/