diff options
author | Luis Ontanon <luis.ontanon@gmail.com> | 2006-09-25 01:09:00 +0000 |
---|---|---|
committer | Luis Ontanon <luis.ontanon@gmail.com> | 2006-09-25 01:09:00 +0000 |
commit | 6462d05044d74e475253518912c0635222bd7fc2 (patch) | |
tree | 32834c107cb9baab32f865999d3d69d877452e71 /epan/wslua/wslua_gui.c | |
parent | 299469d48d57337e6381f2d5363ece52c9a36d37 (diff) |
Move the Lua interface into epan... (not a plugin anymore).
- Rename Tap into Listener
- add a mechanism to pass protocols' tap data to the Listener
svn path=/trunk/; revision=19319
Diffstat (limited to 'epan/wslua/wslua_gui.c')
-rw-r--r-- | epan/wslua/wslua_gui.c | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/epan/wslua/wslua_gui.c b/epan/wslua/wslua_gui.c new file mode 100644 index 0000000000..9c7c563913 --- /dev/null +++ b/epan/wslua/wslua_gui.c @@ -0,0 +1,508 @@ +/* + * lua_gui.c + * + * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com> + * + * $Id: wslua_gui.c 18611 2006-06-29 13:49:56Z lego $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "wslua.h" + +static const funnel_ops_t* ops = NULL; + +struct _lua_menu_data { + lua_State* L; + int cb_ref; + int data_ref; +}; + +static int menu_cb_error_handler(lua_State* L) { + const gchar* error = lua_tostring(L,1); + report_failure("Lua: Error During execution of Menu Callback:\n %s",error); + return 0; +} + +WSLUA_FUNCTION wslua_gui_enabled(lua_State* L) { /* Checks whether the GUI facility is enabled. */ + lua_pushboolean(L,GPOINTER_TO_INT(ops)); + WSLUA_RETURN(1); /* A boolean: true if it is enabled, false if it isn't. */ +} + +void lua_menu_callback(gpointer data) { + struct _lua_menu_data* md = data; + + lua_pushcfunction(md->L,menu_cb_error_handler); + lua_rawgeti(md->L, LUA_REGISTRYINDEX, md->cb_ref); + lua_rawgeti(md->L, LUA_REGISTRYINDEX, md->data_ref); + + lua_pcall(md->L,1,0,1); + + return; +} + +WSLUA_FUNCTION wslua_register_menu(lua_State* L) { /* Register a menu item in the Statistics menu. */ +#define WSLUA_ARG_register_menu_NAME 1 /* The name of the menu item. */ +#define WSLUA_ARG_register_menu_ACTION 2 /* The function to be called when the menu item is invoked. */ +#define WSLUA_OPTARG_register_menu_USERDATA 3 /* To be passed to the action. */ + + const gchar* name = luaL_checkstring(L,WSLUA_ARG_register_menu_NAME); + struct _lua_menu_data* md; + gboolean retap = FALSE; + + if(!name) + WSLUA_ARG_ERROR(register_menu,NAME,"must be a string"); + + if (!lua_isfunction(L,WSLUA_ARG_register_menu_ACTION)) + WSLUA_ARG_ERROR(register_menu,ACTION,"must be a function"); + + md = g_malloc(sizeof(struct _lua_menu_data)); + md->L = L; + + lua_pushvalue(L, 2); + md->cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + if ( lua_gettop(L) > 2) { + lua_pushvalue(L, WSLUA_OPTARG_register_menu_USERDATA); + md->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + } else { + md->data_ref = LUA_NOREF; + } + + funnel_register_menu(name, + REGISTER_STAT_GROUP_GENERIC, + lua_menu_callback, + md, + retap); + + WSLUA_RETURN(0); +} + + + + +struct _dlg_cb_data { + lua_State* L; + int func_ref; + int data_ref; +}; + +static int dlg_cb_error_handler(lua_State* L) { + const gchar* error = lua_tostring(L,1); + report_failure("Lua: Error During execution of dialog callback:\n %s",error); + return 0; +} + +static void lua_dialog_cb(gchar** user_input, void* data) { + struct _dlg_cb_data* dcbd = data; + int i = 0; + gchar* input; + lua_State* L = dcbd->L; + + lua_settop(L,0); + lua_pushcfunction(L,dlg_cb_error_handler); + lua_rawgeti(L, LUA_REGISTRYINDEX, dcbd->func_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, dcbd->data_ref); + + for (i = 0; (input = user_input[i]) ; i++) { + lua_pushstring(L,input); + g_free(input); + } + + g_free(user_input); + + switch ( lua_pcall(L,i+1,0,1) ) { + case 0: + break; + case LUA_ERRRUN: + g_warning("Runtime error while calling dialog callback"); + break; + case LUA_ERRMEM: + g_warning("Memory alloc error while calling dialog callback"); + break; + default: + g_assert_not_reached(); + break; + } + +} + +WSLUA_FUNCTION wslua_new_dialog(lua_State* L) { /* Pops up a new dialog */ +#define WSLUA_ARG_new_dialog_TITLE 1 /* Title of the dialog's window. */ +#define WSLUA_ARG_new_dialog_ACTION 2 /* Action to be performed when OKd. */ +/* WSLUA_MOREARGS new_dialog A series of strings to be used as labels of the dialog's fields */ + + const gchar* title; + int top = lua_gettop(L); + int i; + GPtrArray* labels; + struct _dlg_cb_data* dcbd; + + if (! ops) { + luaL_error(L,"the GUI facility has to be enabled"); + return 0; + } + + if (! (title = luaL_checkstring(L,WSLUA_ARG_new_dialog_TITLE)) ) { + WSLUA_ARG_ERROR(new_dialog,TITLE,"must be a string"); + return 0; + } + + if (! lua_isfunction(L,WSLUA_ARG_new_dialog_ACTION)) { + WSLUA_ARG_ERROR(new_dialog,ACTION,"must be a function"); + return 0; + } + + if (top < 3) { + WSLUA_ERROR(new_dialog,"at least one field required"); + return 0; + } + + + dcbd = g_malloc(sizeof(struct _dlg_cb_data)); + dcbd->L = L; + + lua_remove(L,1); + + lua_pushvalue(L, 1); + dcbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_remove(L,1); + + lua_pushvalue(L, 1); + dcbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_remove(L,1); + + labels = g_ptr_array_new(); + + top -= 3; + + for (i = 1; i <= top; i++) { + gchar* label = (void*)luaL_checkstring(L,i); + + /* XXX leaks labels on error */ + if (! label) + WSLUA_ERROR(new_dialog,"all fields must be strings"); + + g_ptr_array_add(labels,label); + } + + g_ptr_array_add(labels,NULL); + + ops->new_dialog(title, (const gchar**)labels->pdata, lua_dialog_cb, dcbd); + + g_ptr_array_free(labels,TRUE); + + WSLUA_RETURN(0); +} + + + +WSLUA_CLASS_DEFINE(TextWindow,NOP,NOP); /* Manages a text window. */ + +WSLUA_CONSTRUCTOR TextWindow_new(lua_State* L) { /* Creates a new TextWindow. */ +#define WSLUA_OPTARG_TextWindow_new_TITLE 1 /* Title of the new window. */ + + const gchar* title; + TextWindow tw; + + title = luaL_optstring(L,WSLUA_OPTARG_TextWindow_new_TITLE,"Untitled Window"); + tw = ops->new_text_window(title); + pushTextWindow(L,tw); + + WSLUA_RETURN(1); /* The newly created TextWindow object. */ +} + +struct _close_cb_data { + lua_State* L; + int func_ref; + int data_ref; +}; + +int text_win_close_cb_error_handler(lua_State* L) { + const gchar* error = lua_tostring(L,1); + report_failure("Lua: Error During execution of TextWindow close callback:\n %s",error); + return 0; +} + +static void text_win_close_cb(void* data) { + struct _close_cb_data* cbd = data; + lua_State* L = cbd->L; + + lua_pushcfunction(L,text_win_close_cb_error_handler); + lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->func_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->data_ref); + + switch ( lua_pcall(L,1,0,1) ) { + case 0: + break; + case LUA_ERRRUN: + g_warning("Runtime error during execution of TextWindow close callback"); + break; + case LUA_ERRMEM: + g_warning("Memory alloc error during execution of TextWindow close callback"); + break; + default: + g_assert_not_reached(); + break; + } +} + +WSLUA_METHOD TextWindow_set_atclose(lua_State* L) { /* Set the function that will be called when the window closes */ +#define WSLUA_ARG_TextWindow_at_close_ACTION 2 /* A function to be executed when the user closes the window */ + + TextWindow tw = checkTextWindow(L,1); + struct _close_cb_data* cbd; + + if (!tw) + WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow"); + + lua_settop(L,3); + + if (! lua_isfunction(L,2)) + WSLUA_ARG_ERROR(TextWindow_at_close,ACTION,"must be a function"); + + cbd = g_malloc(sizeof(struct _close_cb_data)); + + cbd->L = L; + cbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + cbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + ops->set_close_cb(tw,text_win_close_cb,cbd); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHOD TextWindow_set(lua_State* L) { /* Sets the text. */ +#define WSLUA_ARG_TextWindow_set_TEXT 2 /* The text to be used. */ + + TextWindow tw = checkTextWindow(L,1); + const gchar* text = luaL_checkstring(L,2); + + if (!tw) + WSLUA_ERROR(TextWindow_set,"cannot be called for something not a TextWindow"); + + if (!text) + WSLUA_ARG_ERROR(TextWindow_set,TEXT,"must be a string"); + + ops->set_text(tw,text); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHOD TextWindow_append(lua_State* L) { /* Appends text */ +#define WSLUA_ARG_TextWindow_append_TEXT 2 /* The text to be appended */ + TextWindow tw = checkTextWindow(L,1); + const gchar* text = luaL_checkstring(L,2); + + if (!tw) + WSLUA_ERROR(TextWindow_append,"cannot be called for something not a TextWindow"); + + if (!text) + WSLUA_ARG_ERROR(TextWindow_append,TEXT,"must be a string"); + + ops->append_text(tw,text); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHOD TextWindow_prepend(lua_State* L) { /* Prepends text */ +#define WSLUA_ARG_TextWindow_prepend_TEXT 2 /* The text to be appended */ + TextWindow tw = checkTextWindow(L,1); + const gchar* text = luaL_checkstring(L,2); + + if (!tw) + WSLUA_ERROR(TextWindow_prepend,"cannot be called for something not a TextWindow"); + + if (!text) + WSLUA_ARG_ERROR(TextWindow_prepend,TEXT,"must be a string"); + + ops->prepend_text(tw,text); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHOD TextWindow_clear(lua_State* L) { /* Errases all text in the window. */ + TextWindow tw = checkTextWindow(L,1); + + if (!tw) + WSLUA_ERROR(TextWindow_clear,"cannot be called for something not a TextWindow"); + + ops->clear_text(tw); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHOD TextWindow_get_text(lua_State* L) { /* Get the text of the window */ + TextWindow tw = checkTextWindow(L,1); + const gchar* text; + + if (!tw) + WSLUA_ERROR(TextWindow_get_text,"cannot be called for something not a TextWindow"); + + text = ops->get_text(tw); + + lua_pushstring(L,text); + WSLUA_RETURN(1); /* The TextWindow's text. */ +} + +static int TextWindow__gc(lua_State* L) { + TextWindow tw = checkTextWindow(L,1); + + if (!tw) + WSLUA_ERROR(TextWindow_gc,"cannot be called for something not a TextWindow"); + + ops->destroy_text_window(tw); + return 1; +} + +WSLUA_METHOD TextWindow_set_editable(lua_State* L) { /* Set the function that will be called when the window closes */ +#define WSLUA_OPTARG_TextWindow_at_close_EDITABLE 2 /* A boolean flag, defaults to true */ + + TextWindow tw = checkTextWindow(L,1); + gboolean editable = luaL_optint(L,2,1); + + if (!tw) + WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow"); + + if (ops->set_editable) + ops->set_editable(tw,editable); + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +typedef struct _wslua_bt_cb_t { + lua_State* L; + int func_ref; + int data_ref; +} wslua_bt_cb_t; + +static gboolean wslua_button_callback(funnel_text_window_t* tw, void* data) { + wslua_bt_cb_t* cbd = data; + lua_State* L = cbd->L; + + lua_settop(L,0); + lua_pushcfunction(L,dlg_cb_error_handler); + lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->func_ref); + pushTextWindow(L,tw); + lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->data_ref); + + switch ( lua_pcall(L,2,0,1) ) { + case 0: + break; + case LUA_ERRRUN: + g_warning("Runtime error while calling button callback"); + break; + case LUA_ERRMEM: + g_warning("Memory alloc error while calling button callback"); + break; + default: + g_assert_not_reached(); + break; + } + + return TRUE; +} + +WSLUA_METHOD TextWindow_add_button(lua_State* L) { +#define WSLUA_ARG_TextWindow_add_button_LABEL 2 /* The label of the button */ +#define WSLUA_ARG_TextWindow_add_button_FUNCTION 3 /* The function to be called when clicked */ +#define WSLUA_ARG_TextWindow_add_button_DATA 4 /* The data to be passed to the function (other than the window) */ + TextWindow tw = checkTextWindow(L,1); + const gchar* label = luaL_checkstring(L,WSLUA_ARG_TextWindow_add_button_LABEL); + + funnel_bt_t* fbt; + wslua_bt_cb_t* cbd; + + if (!tw) + WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow"); + + if (! lua_isfunction(L,WSLUA_ARG_TextWindow_add_button_FUNCTION) ) + WSLUA_ARG_ERROR(TextWindow_add_button,FUNCTION,"must be a function"); + + lua_settop(L,4); + + if (ops->add_button) { + fbt = ep_alloc(sizeof(funnel_bt_t)); + cbd = ep_alloc(sizeof(wslua_bt_cb_t)); + + fbt->tw = tw; + fbt->func = wslua_button_callback; + fbt->data = cbd; + + cbd->L = L; + cbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + cbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + ops->add_button(tw,fbt,label); + } + + pushTextWindow(L,tw); + WSLUA_RETURN(1); /* The TextWindow object. */ +} + +WSLUA_METHODS TextWindow_methods[] = { + WSLUA_CLASS_FNREG(TextWindow,new), + WSLUA_CLASS_FNREG(TextWindow,set), + WSLUA_CLASS_FNREG(TextWindow,new), + WSLUA_CLASS_FNREG(TextWindow,append), + WSLUA_CLASS_FNREG(TextWindow,prepend), + WSLUA_CLASS_FNREG(TextWindow,clear), + WSLUA_CLASS_FNREG(TextWindow,set_atclose), + WSLUA_CLASS_FNREG(TextWindow,set_editable), + WSLUA_CLASS_FNREG(TextWindow,get_text), + WSLUA_CLASS_FNREG(TextWindow,add_button), + {0, 0} +}; + +WSLUA_META TextWindow_meta[] = { + {"__tostring", TextWindow_get_text}, + {"__gc", TextWindow__gc}, + {0, 0} +}; + +int TextWindow_register(lua_State* L) { + + ops = funnel_get_funnel_ops(); + + WSLUA_REGISTER_CLASS(TextWindow); + + return 1; +} + + +WSLUA_FUNCTION wslua_retap_packets(lua_State* L) { + /* + Rescan all packets and just run taps - don't reconstruct the display. + */ + if ( ops->retap_packets ) { + ops->retap_packets(); + } else { + WSLUA_ERROR(wslua_retap_packets, "does not work on TShark"); + } + + return 0; +} + + |