[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;
}
-