diff --git a/src/game.cpp b/src/game.cpp index 2f228b0ed..2e4485e36 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -944,9 +944,16 @@ static inline void create_formspec_menu(GUIFormSpecMenu** cur_formspec, if (*cur_formspec == 0) { *cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, - invmgr, gamedef, tsrc, fs_src, txt_dest, cur_formspec, client); + invmgr, gamedef, tsrc, fs_src, txt_dest, client); (*cur_formspec)->doPause = false; - (*cur_formspec)->drop(); + + /* + Caution: do not call (*cur_formspec)->drop() here -- + the reference might outlive the menu, so we will + periodically check if *cur_formspec is the only + remaining reference (i.e. the menu was removed) + and delete it in that case. + */ } else { (*cur_formspec)->setFormSource(fs_src); @@ -3417,10 +3424,16 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } /* - make sure menu is on top + 1. Delete formspec menu reference if menu was removed + 2. Else, make sure formspec menu is on top */ - if ((!noMenuActive()) && (current_formspec)) { + if (current_formspec) { + if (current_formspec->getReferenceCount() == 1) { + current_formspec->drop(); + current_formspec = NULL; + } else if (!noMenuActive()) { guiroot->bringToFront(current_formspec); + } } /* @@ -3509,6 +3522,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input, g_menumgr.m_stack.front()->setVisible(false); g_menumgr.deletingMenu(g_menumgr.m_stack.front()); } + if (current_formspec) { + current_formspec->drop(); + current_formspec = NULL; + } + /* Draw a "shutting down" screen, which will be shown while the map generator and other stuff quits diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index 41a522caf..e53b52b01 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -190,7 +190,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, m_texture_source, m_formspecgui, m_buttonhandler, - NULL, NULL); + NULL); m_menu->allowClose(false); m_menu->lockSize(true,v2u32(800,600)); @@ -220,8 +220,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, } m_menu->quitMenu(); - m_menu->remove(); - delete m_menu; + m_menu->drop(); m_menu = NULL; } diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index a502c9682..e82ea829c 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -68,12 +68,11 @@ with this program; if not, write to the Free Software Foundation, Inc., /* GUIFormSpecMenu */ - GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef, ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst, - GUIFormSpecMenu** ext_ptr, Client* client) : + Client* client) : GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), m_device(dev), m_invmgr(invmgr), @@ -89,7 +88,6 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_lock(false), m_form_src(fsrc), m_text_dst(tdst), - m_ext_ptr(ext_ptr), m_font(dev->getGUIEnvironment()->getSkin()->getFont()), m_formspec_version(0) #ifdef __ANDROID__ @@ -130,11 +128,6 @@ GUIFormSpecMenu::~GUIFormSpecMenu() if (m_text_dst != NULL) { delete m_text_dst; } - - if (m_ext_ptr != NULL) { - assert(*m_ext_ptr == this); - *m_ext_ptr = NULL; - } } void GUIFormSpecMenu::removeChildren() diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 40be59b46..d38e9ec46 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -210,7 +210,6 @@ public: ISimpleTextureSource *tsrc, IFormSource* fs_src, TextDest* txt_dst, - GUIFormSpecMenu** ext_ptr, Client* client ); @@ -346,7 +345,6 @@ protected: private: IFormSource *m_form_src; TextDest *m_text_dst; - GUIFormSpecMenu **m_ext_ptr; gui::IGUIFont *m_font; unsigned int m_formspec_version; diff --git a/src/modalMenu.h b/src/modalMenu.h index 2c512d3ca..72ecedcb9 100644 --- a/src/modalMenu.h +++ b/src/modalMenu.h @@ -96,6 +96,8 @@ public: WARNING: THIS DEALLOCATES THE MENU FROM MEMORY. Return immediately if you call this from the menu itself. + + (More precisely, this decrements the reference count.) */ void quitMenu() {