diff --git a/src/dialogue.c b/src/dialogue.c index a4881a3e6a..88de9b77a9 100644 --- a/src/dialogue.c +++ b/src/dialogue.c @@ -884,15 +884,14 @@ static int dialogue_custom_event( unsigned int wid, SDL_Event *event ) * @param event Custom event callback. * @param data Custom data. * @param dynamic Whether or not the custom is dynamic. - * @param autofree Should \p data be freed when the window is destroyed? + * @param freefunc Function to be run when cleaning the custom data. */ -void dialogue_custom( const char *caption, int width, int height, - int ( *update )( double dt, void *data ), - void ( *render )( double x, double y, double w, double h, - void *data ), - int ( *event )( unsigned int wid, SDL_Event *event, - void *data ), - void *data, int autofree, int dynamic ) +void dialogue_custom( + const char *caption, int width, int height, + int ( *update )( double dt, void *data ), + void ( *render )( double x, double y, double w, double h, void *data ), + int ( *event )( unsigned int wid, SDL_Event *event, void *data ), void *data, + int dynamic, void ( *freefunc )( void *data ) ) { struct dialogue_custom_data_s cd; dialogue_update_t du; @@ -923,8 +922,8 @@ void dialogue_custom( const char *caption, int width, int height, NULL, NULL, data ); if ( dynamic ) window_custSetDynamic( wid, "cstCustom", 1 ); - if ( autofree ) - window_custAutoFreeData( wid, "cstCustom" ); + if ( freefunc != NULL ) + window_custFreeDataFunc( wid, "cstCustom", freefunc ); window_custSetClipping( wid, "cstCustom", 1 ); /* set up event stuff. */ diff --git a/src/dialogue.h b/src/dialogue.h index 337b83af7b..a36602fa93 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -68,15 +68,14 @@ int dialogue_listPanelRaw( /* * Custom. */ -void dialogue_custom( const char *caption, int width, int height, - int ( *update )( double dt, void *data ), - void ( *render )( double x, double y, double w, double h, - void *data ), - int ( *event )( unsigned int wid, SDL_Event *event, - void *data ), - void *data, int autofree, int dynamic ); -int dialogue_customFullscreen( int enable ); -int dialogue_customResize( int width, int height ); +void dialogue_custom( + const char *caption, int width, int height, + int ( *update )( double dt, void *data ), + void ( *render )( double x, double y, double w, double h, void *data ), + int ( *event )( unsigned int wid, SDL_Event *event, void *data ), void *data, + int dynamic, void ( *freefunc )( void *data ) ); +int dialogue_customFullscreen( int enable ); +int dialogue_customResize( int width, int height ); /* * misc diff --git a/src/land_shipyard.c b/src/land_shipyard.c index 460414d34c..55aa53dd95 100644 --- a/src/land_shipyard.c +++ b/src/land_shipyard.c @@ -134,7 +134,7 @@ void shipyard_open( unsigned int wid ) window_custSetOverlay( wid, "cstSlots", shipyard_renderSlotsOver ); window_custSetClipping( wid, "cstSlots", 0 ); window_canFocusWidget( wid, "cstSlots", 0 ); - window_custAutoFreeData( wid, "cstSlots" ); + window_custFreeDataFunc( wid, "cstSlots", free ); /* stat text */ window_addText( wid, -4, -sw - 50 - 70 - 20, sw, -sh - 60 - 70 - 20 + h - bh, diff --git a/src/map.c b/src/map.c index 062e76acb8..f54319cf65 100644 --- a/src/map.c +++ b/src/map.c @@ -3243,7 +3243,7 @@ void map_show( int wid, int x, int y, int w, int h, double zoom, double xoff, window_addCust( wid, x, y, w, h, "cstMap", 1, map_render, map_mouse, NULL, map_focusLose, cst ); window_custSetDynamic( wid, "cstMap", 1 ); - window_custAutoFreeData( wid, "cstMap" ); + window_custFreeDataFunc( wid, "cstMap", free ); /* Set up stuff. */ map_setup(); diff --git a/src/news.c b/src/news.c index eb2d7a40e3..e8565b5efd 100644 --- a/src/news.c +++ b/src/news.c @@ -303,7 +303,7 @@ void news_widget( unsigned int wid, int x, int y, int w, int h ) news_focusLose, widptr ); window_custSetDynamic( wid, "cstNews", 1 ); window_canFocusWidget( wid, "cstNews", 0 ); - window_custAutoFreeData( wid, "cstNews" ); + window_custFreeDataFunc( wid, "cstNews", free ); } /* clears newslines for bar text, for when taking off */ diff --git a/src/nlua_tk.c b/src/nlua_tk.c index e1b25e9051..1f2004bfae 100644 --- a/src/nlua_tk.c +++ b/src/nlua_tk.c @@ -38,6 +38,7 @@ typedef struct custom_functions_s { int resize; int textinput; } custom_functions_t; +static void cust_cleanup( void *data ); static int cust_update( double dt, void *data ); static void cust_render( double x, double y, double w, double h, void *data ); static int cust_event( unsigned int wid, SDL_Event *event, void *data ); @@ -407,6 +408,22 @@ static int tkL_merchantOutfit( lua_State *L ) return 0; } +/** + * @brief Cleans up after the window. + */ +static void cust_cleanup( void *data ) +{ + custom_functions_t *cf = data; + lua_State *L = cf->L; + luaL_unref( L, LUA_REGISTRYINDEX, cf->update ); + luaL_unref( L, LUA_REGISTRYINDEX, cf->draw ); + luaL_unref( L, LUA_REGISTRYINDEX, cf->keyboard ); + luaL_unref( L, LUA_REGISTRYINDEX, cf->mouse ); + luaL_unref( L, LUA_REGISTRYINDEX, cf->resize ); + luaL_unref( L, LUA_REGISTRYINDEX, cf->textinput ); + free( cf ); +} + /** * @brief Creates a custom widget window. * @@ -458,17 +475,9 @@ static int tkL_custom( lua_State *L ) lua_setglobal( L, TK_CUSTOMDONE ); /* Create the dialogue. */ - dialogue_custom( caption, w, h, cust_update, cust_render, cust_event, cf, 1, - !nodynamic ); - - /* Clean up. */ + dialogue_custom( caption, w, h, cust_update, cust_render, cust_event, cf, + !nodynamic, cust_cleanup ); cf->done = 1; - luaL_unref( L, LUA_REGISTRYINDEX, cf->update ); - luaL_unref( L, LUA_REGISTRYINDEX, cf->draw ); - luaL_unref( L, LUA_REGISTRYINDEX, cf->keyboard ); - luaL_unref( L, LUA_REGISTRYINDEX, cf->mouse ); - luaL_unref( L, LUA_REGISTRYINDEX, cf->resize ); - luaL_unref( L, LUA_REGISTRYINDEX, cf->textinput ); return 0; } diff --git a/src/tk/widget/cust.c b/src/tk/widget/cust.c index 923ff5bafa..4f01791c74 100644 --- a/src/tk/widget/cust.c +++ b/src/tk/widget/cust.c @@ -71,7 +71,7 @@ void window_addCust( wgt->dat.cst.focusGain = focusGain; wgt->dat.cst.focusLose = focusLose; wgt->dat.cst.userdata = data; - wgt->dat.cst.autofree = 0; + wgt->dat.cst.free = NULL; /* position/size */ wgt->w = (double)w; @@ -154,8 +154,8 @@ static void cst_renderOverlay( Widget *cst, double bx, double by ) */ static void cst_cleanup( Widget *cst ) { - if ( cst->dat.cst.autofree ) - free( cst->dat.cst.userdata ); + if ( cst->dat.cst.free != NULL ) + cst->dat.cst.free( cst->dat.cst.userdata ); } /** @@ -237,12 +237,14 @@ void *window_custGetData( unsigned int wid, const char *name ) * * @param wid Window to which widget belongs. * @param name Name of the widget. + * @param func Function to use when freeing the data. */ -void window_custAutoFreeData( unsigned int wid, const char *name ) +void window_custFreeDataFunc( unsigned int wid, const char *name, + void ( *func )( void *ptr ) ) { Widget *wgt = cst_getWidget( wid, name ); if ( wgt != NULL ) - wgt->dat.cst.autofree = 1; + wgt->dat.cst.free = func; } /** diff --git a/src/tk/widget/cust.h b/src/tk/widget/cust.h index 3748d16d0f..72486e177a 100644 --- a/src/tk/widget/cust.h +++ b/src/tk/widget/cust.h @@ -27,8 +27,7 @@ typedef struct WidgetCustData_ { const char *wgtname ); /**< Lose focus. */ int clip; /**< 1 if should clip with glScissors or the like, 0 otherwise. */ void *userdata; - int autofree; /**< 1 if widget should free userdata upon cleanup, 0 if it - shouldn't. */ + void ( *free )( void *data ); } WidgetCustData; /* Required functions. */ @@ -48,5 +47,6 @@ void window_custSetOverlay( unsigned int wid, const char *name, double bw, double bh, void *data ) ); void *window_custGetData( unsigned int wid, const char *name ); -void window_custAutoFreeData( unsigned int wid, const char *name ); +void window_custFreeDataFunc( unsigned int wid, const char *name, + void ( *func )( void *ptr ) ); void window_custSetDynamic( unsigned int wid, const char *name, int dynamic );