main.c
changeset 97 b00f9ce82016
parent 95 f2f4c7810a72
child 98 59aeae623ac6
equal deleted inserted replaced
96:270ce1cfc823 97:b00f9ce82016
    23 #include <lualib.h>
    23 #include <lualib.h>
    24 #include <stdio.h>
    24 #include <stdio.h>
    25 #include <stdlib.h>    // getenv
    25 #include <stdlib.h>    // getenv
    26 #include <string.h>    // strcmp
    26 #include <string.h>    // strcmp
    27 
    27 
    28 #include <mcabber/logprint.h>    // scr_LogPrint
    28 #include <mcabber/logprint.h>    // scr_log_print
    29 #include <mcabber/screen.h>      // scr_Beep, scr_WriteIncomingMessage
    29 #include <mcabber/screen.h>      // scr_Beep, scr_WriteIncomingMessage
    30 #include <mcabber/hbuf.h>        // HBB_PREFIX_INFO
    30 #include <mcabber/hbuf.h>        // HBB_PREFIX_INFO
    31 #include <mcabber/commands.h>    // process_command, cmd_add, cmd_del
    31 #include <mcabber/commands.h>    // process_command, cmd_add, cmd_del
    32 #include <mcabber/xmpp.h>        // xmpp_getstatus, xmpp_getstatusmsg, lconnection
    32 #include <mcabber/xmpp.h>        // xmpp_getstatus, xmpp_getstatusmsg, lconnection
    33 #include <mcabber/xmpp_helper.h> // xmpp_add_feature, xmpp_del_feature
    33 #include <mcabber/xmpp_helper.h> // xmpp_add_feature, xmpp_del_feature
    58 	"Provides command /lua" )
    58 	"Provides command /lua" )
    59 #endif
    59 #endif
    60 
    60 
    61 static module_info_t info_lua_experimental = {
    61 static module_info_t info_lua_experimental = {
    62 	.branch      = "experimental",
    62 	.branch      = "experimental",
    63 	.api         = 5,
    63 	.api         = 10,
    64 	.version     = PROJECT_VERSION,
    64 	.version     = PROJECT_VERSION,
    65 	.description = DESCRIPTION,
    65 	.description = DESCRIPTION,
    66 	.requires    = NULL,
    66 	.requires    = NULL,
    67 	.init        = mlua_init,
    67 	.init        = mlua_init,
    68 	.uninit      = mlua_uninit,
    68 	.uninit      = mlua_uninit,
    69 	.next        = NULL,
    69 	.next        = NULL,
    70 };
    70 };
    71 
    71 
    72 module_info_t info_lua = {
    72 module_info_t info_lua = {
    73 	.branch      = "dev",
    73 	.branch      = "dev",
    74 	.api         = 4,
    74 	.api         = 11,
    75 	.version     = PROJECT_VERSION,
    75 	.version     = PROJECT_VERSION,
    76 	.description = DESCRIPTION,
    76 	.description = DESCRIPTION,
    77 	.requires    = NULL,
    77 	.requires    = NULL,
    78 	.init        = mlua_init,
    78 	.init        = mlua_init,
    79 	.uninit      = mlua_uninit,
    79 	.uninit      = mlua_uninit,
   126 			luaL_addlstring (&B, xbuf, 8); // XXX
   126 			luaL_addlstring (&B, xbuf, 8); // XXX
   127 		}
   127 		}
   128 	}
   128 	}
   129 	luaL_pushresult (&B);
   129 	luaL_pushresult (&B);
   130 
   130 
   131 	scr_LogPrint (LPRINT_LOGNORM | LPRINT_NOTUTF8, lua_tostring (L, -1));
   131 	scr_log_print (LPRINT_LOGNORM | LPRINT_NOTUTF8, lua_tostring (L, -1));
   132 	return 0;
   132 	return 0;
   133 }
   133 }
   134 
   134 
   135 /// dopath
   135 /// dopath
   136 /// Loads lua file from default location.
   136 /// Loads lua file from default location.
   149 		char *fname = g_strconcat (name, ".lua", NULL);
   149 		char *fname = g_strconcat (name, ".lua", NULL);
   150 		path = mcabber_config_filename (fname);
   150 		path = mcabber_config_filename (fname);
   151 		g_free (fname);
   151 		g_free (fname);
   152 	}
   152 	}
   153 
   153 
   154 	if (ret = luaL_loadfile (L, path))
   154 	if ((ret = luaL_loadfile (L, path)))
   155 		scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1));
   155 		scr_log_print (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1));
   156 	else if (ret = lua_pcall (L, 0, LUA_MULTRET, 0))
   156 	else if ((ret = lua_pcall (L, 0, LUA_MULTRET, 0)))
   157 		scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1));
   157 		scr_log_print (LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1));
   158 	g_free (path);
   158 	g_free (path);
   159 
   159 
   160 	if (ret)
   160 	if (ret)
   161 		return 1;
   161 		return 1;
   162 	else
   162 	else
   227 /// A: log print type, message, message...
   227 /// A: log print type, message, message...
   228 static int lua_main_log (lua_State *L)
   228 static int lua_main_log (lua_State *L)
   229 {
   229 {
   230 	int type = luaL_checkenum_multi (L, 1, lua_lprint);
   230 	int type = luaL_checkenum_multi (L, 1, lua_lprint);
   231 	lua_concat (L, lua_gettop (L) - 1);
   231 	lua_concat (L, lua_gettop (L) - 1);
   232 	scr_LogPrint (type, lua_tostring (L, -1));
   232 	scr_log_print (type, lua_tostring (L, -1));
   233 	return 0;
   233 	return 0;
   234 }
   234 }
   235 
   235 
   236 // expects table on top
   236 // expects table on top
   237 static void lua_options_callback (char *key, char *value, lua_State *L)
   237 static void lua_options_callback (char *key, char *value, lua_State *L)
   396 static int lua_main_print_info (lua_State *L)
   396 static int lua_main_print_info (lua_State *L)
   397 {
   397 {
   398 	char *jid  = to_utf8 (luaL_checkstring (L, 1));
   398 	char *jid  = to_utf8 (luaL_checkstring (L, 1));
   399 	char *to   = jidtodisp (jid);
   399 	char *to   = jidtodisp (jid);
   400 	char *mesg = to_utf8 (luaL_checkstring (L, 2));
   400 	char *mesg = to_utf8 (luaL_checkstring (L, 2));
   401 	scr_WriteIncomingMessage (to, mesg, 0, HBB_PREFIX_INFO, 0);
   401 	scr_write_incoming_message (to, mesg, 0, HBB_PREFIX_INFO, 0);
   402 	g_free (mesg);
   402 	g_free (mesg);
   403 	g_free (to);
   403 	g_free (to);
   404 	g_free (jid);
   404 	g_free (jid);
   405 	return 0;
   405 	return 0;
   406 }
   406 }
   407 
   407 
   408 /// main.beep
   408 /// main.beep
   409 /// Beeps with system speaker.
   409 /// Beeps with system speaker.
   410 static int lua_main_beep (lua_State *L)
   410 static int lua_main_beep (lua_State *L)
   411 {
   411 {
   412 	scr_Beep ();
   412 	scr_beep ();
   413 	return 0;
   413 	return 0;
   414 }
   414 }
   415 
   415 
   416 /// main.run
   416 /// main.run
   417 /// Runs specified mcabber command.
   417 /// Runs specified mcabber command.
   462 {
   462 {
   463 	if (lua_gettop (L) > 0) { // Set
   463 	if (lua_gettop (L) > 0) { // Set
   464 		// XXX: we need not convert to utf, RS works on jids/names in locale charset,
   464 		// XXX: we need not convert to utf, RS works on jids/names in locale charset,
   465 		// but will jidtodisp always correctly work on such tings?
   465 		// but will jidtodisp always correctly work on such tings?
   466 		char *jid = jidtodisp (luaL_checkstring (L, 1));
   466 		char *jid = jidtodisp (luaL_checkstring (L, 1));
   467 		scr_RosterSearch (jid);
   467 		scr_roster_search (jid);
   468 		g_free (jid);
   468 		g_free (jid);
   469 		return 0;
   469 		return 0;
   470 	} else { // Get
   470 	} else { // Get
   471 		char *jid = from_utf8 (buddy_getjid (BUDDATA (current_buddy)));
   471 		char *jid = from_utf8 (buddy_getjid (BUDDATA (current_buddy)));
   472 		lua_pushstring (L, jid);
   472 		lua_pushstring (L, jid);
   654 
   654 
   655 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   655 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   656 	luaL_pushenum (cb->L, context, lua_event_context);
   656 	luaL_pushenum (cb->L, context, lua_event_context);
   657 	lua_pushstring (cb -> L, arg);
   657 	lua_pushstring (cb -> L, arg);
   658 	if (lua_pcall (cb->L, 2, 1, 0)) {
   658 	if (lua_pcall (cb->L, 2, 1, 0)) {
   659 		scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1));
   659 		scr_log_print (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1));
   660 		lua_pop (cb->L, 1);
   660 		lua_pop (cb->L, 1);
   661 	}
   661 	}
   662 
   662 
   663 	if (lua_toboolean (cb -> L, -1))
   663 	if (lua_toboolean (cb -> L, -1))
   664 		return TRUE;
   664 		return TRUE;
   892 		luaL_pushargs (cb->L, args);
   892 		luaL_pushargs (cb->L, args);
   893 	else
   893 	else
   894 		lua_pushstring (cb->L, args);
   894 		lua_pushstring (cb->L, args);
   895 
   895 
   896 	if (lua_pcall (cb->L, 1, 0, 0)) {
   896 	if (lua_pcall (cb->L, 1, 0, 0)) {
   897 		scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
   897 		scr_log_print (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
   898 		lua_pop (cb->L, 1);
   898 		lua_pop (cb->L, 1);
   899 	}
   899 	}
   900 }
   900 }
   901 
   901 
   902 /// main.parse_args
   902 /// main.parse_args
   961 {
   961 {
   962 	guint  cid  = luaL_checkinteger (L, 1);
   962 	guint  cid  = luaL_checkinteger (L, 1);
   963 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   963 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   964 	compl_add_category_word (cid, word);
   964 	compl_add_category_word (cid, word);
   965 	g_free (word);
   965 	g_free (word);
       
   966 	return 0;
   966 }
   967 }
   967 
   968 
   968 /// main.del_completion
   969 /// main.del_completion
   969 /// Removes word from a completion list.
   970 /// Removes word from a completion list.
   970 /// A: integer (completion group id), string (word)
   971 /// A: integer (completion group id), string (word)
   972 {
   973 {
   973 	guint  cid  = luaL_checkinteger (L, 1);
   974 	guint  cid  = luaL_checkinteger (L, 1);
   974 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   975 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   975 	compl_del_category_word (cid, word);
   976 	compl_del_category_word (cid, word);
   976 	g_free (word);
   977 	g_free (word);
       
   978 	return 0;
   977 }
   979 }
   978 
   980 
   979 /// main.command
   981 /// main.command
   980 /// Associates or breaks association between mcabber command name and lua function.
   982 /// Associates or breaks association between mcabber command name and lua function.
   981 /// To unregister command omit function argument.
   983 /// To unregister command omit function argument.
  1069 static gboolean lua_timer_callback (lua_timer_callback_t *cb)
  1071 static gboolean lua_timer_callback (lua_timer_callback_t *cb)
  1070 {
  1072 {
  1071 	int ret;
  1073 	int ret;
  1072 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1074 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1073 	if (lua_pcall (cb->L, 0, 1, 0)) {
  1075 	if (lua_pcall (cb->L, 0, 1, 0)) {
  1074 		scr_LogPrint (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", lua_tostring (cb->L, -1));
  1076 		scr_log_print (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", lua_tostring (cb->L, -1));
  1075 		lua_pop (cb->L, 1);
  1077 		lua_pop (cb->L, 1);
  1076 		return FALSE;
  1078 		return FALSE;
  1077 	}
  1079 	}
  1078 	ret = lua_toboolean (cb->L, -1);
  1080 	ret = lua_toboolean (cb->L, -1);
  1079 	lua_pop (cb->L, 1);
  1081 	lua_pop (cb->L, 1);
  1138 				break;
  1140 				break;
  1139 
  1141 
  1140 			lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1142 			lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1141 			lua_pushlstring (cb->L, lua_bgread_buffer, read);
  1143 			lua_pushlstring (cb->L, lua_bgread_buffer, read);
  1142 			if (lua_pcall (cb->L, 1, 1, 0)) {
  1144 			if (lua_pcall (cb->L, 1, 1, 0)) {
  1143 				scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1));
  1145 				scr_log_print (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1));
  1144 				lua_pop (cb->L, 1);
  1146 				lua_pop (cb->L, 1);
  1145 				return FALSE;
  1147 				return FALSE;
  1146 			}
  1148 			}
  1147 			ret = lua_toboolean (cb->L, -1);
  1149 			ret = lua_toboolean (cb->L, -1);
  1148 			lua_pop (cb->L, 1);
  1150 			lua_pop (cb->L, 1);
  1153 
  1155 
  1154 	if (condition & ~G_IO_IN) { // err or hup
  1156 	if (condition & ~G_IO_IN) { // err or hup
  1155 		lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1157 		lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1156 		lua_pushnil (cb->L);
  1158 		lua_pushnil (cb->L);
  1157 		if (lua_pcall (cb->L, 1, 1, 0)) {
  1159 		if (lua_pcall (cb->L, 1, 1, 0)) {
  1158 			scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1));
  1160 			scr_log_print (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1));
  1159 			lua_pop (cb->L, 1);
  1161 			lua_pop (cb->L, 1);
  1160 			return FALSE;
  1162 			return FALSE;
  1161 		}
  1163 		}
  1162 		ret = lua_toboolean (cb->L, -1);
  1164 		ret = lua_toboolean (cb->L, -1);
  1163 		lua_pop (cb->L, 1);
  1165 		lua_pop (cb->L, 1);
  1207 	// unref?
  1209 	// unref?
  1208 
  1210 
  1209 	return 0;
  1211 	return 0;
  1210 }
  1212 }
  1211 
  1213 
  1212 // MAIN INITIALIZATION CODE
  1214 // HOOK HANDLING
  1213 
  1215 
  1214 #ifdef LLM_LOG_HANDLER
  1216 typedef struct {
  1215 // FIXME: this should not be here
  1217 	lua_State *L;       // lua environment for handler use
  1216 guint lua_lm_log_handler_id;
  1218 	int        nameref; // reference to hook name string
  1217 
  1219 	int        cbref;   // reference to hook handler function
  1218 void lua_lm_log_handler (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer ignore)
  1220 	int        selfref; // self-reference to object
  1219 {
  1221 	guint      hid;     // hook id for object destruction
  1220 	if (settings_opt_get_int ("lua_lm_debug"))
  1222 } lua_hook_t;
  1221 		scr_LogPrint (LPRINT_LOGNORM, "%s: %s", domain, message);
  1223 
  1222 }
  1224 /// hook handler result
  1223 #endif
  1225 /// What to do with hook processing afterwards
  1224 
  1226 /// G:
  1225 static void do_lua(char *arg, lua_State *L)
  1227 static const string2enum_t lua_hook_handler_result[] = {
  1226 {
  1228 	{ "proceed", HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS       },
  1227 	if (luaL_loadbuffer (L, arg, strlen (arg), "line")) {
  1229 	{ "stop",    HOOK_HANDLER_RESULT_NO_MORE_HANDLER           },
  1228 		scr_LogPrint (LPRINT_LOGNORM, "lua: Compilation error: %s", lua_tostring (L, -1));
  1230 	{ "drop",    HOOK_HANDLER_RESULT_NO_MORE_HANDLER_DROP_DATA },
  1229 		lua_pop (L, 1);
  1231 	{ NULL,      HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS       },
  1230 		return;
  1232 };
  1231 	}
  1233 
  1232  
  1234 /// hook handler priority
  1233 	if (lua_pcall (L, 0, 0, 0)) {
  1235 /// Feel free to specify just a number instead of some preset value.
  1234 		scr_LogPrint (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(L, -1));
  1236 /// G:
  1235 		lua_pop (L, 1);
  1237 static const string2enum_t lua_hook_handler_priority[] = {
  1236 		return;
  1238 	{ "high",      G_PRIORITY_HIGH         },
  1237 	}
  1239 	{ "default",   G_PRIORITY_DEFAULT      },
  1238 }
  1240 	{ "idle-high", G_PRIORITY_HIGH_IDLE    },
  1239 
  1241 	{ "idle",      G_PRIORITY_DEFAULT_IDLE },
  1240 static void lua_hook (guint32 hookid, hk_arg_t *args, lua_State *L)
  1242 	{ "low",       G_PRIORITY_LOW          },
  1241 {
  1243 	{ NULL,        G_PRIORITY_DEFAULT      },
  1242 	hk_arg_t   *arg  = args;
  1244 };
  1243 	const char *hook = settings_opt_get ("lua_hook_function");
  1245 
  1244 	if (!hook)
  1246 /// hook function
  1245 		return;
  1247 /// Function to be called, when hook will be processsed.
  1246 	lua_getglobal (L, hook);
  1248 /// XXX: we can provide object as argument, but is this necessary?
       
  1249 /// A: table (arguments hash)
       
  1250 /// R: hook handler result
       
  1251 static guint lua_hook_cb (const gchar *hookid, hk_arg_t *args, gpointer data)
       
  1252 {
       
  1253 	lua_hook_t *cb  = data;
       
  1254 	hk_arg_t   *arg = args;
       
  1255 	guint       ret = HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
       
  1256 	lua_State  *L   = cb -> L;
       
  1257 
       
  1258 	if (cb -> cbref == LUA_NOREF)
       
  1259 		return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
       
  1260 
       
  1261 	lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> cbref);
  1247 	if (!lua_isfunction (L, -1)) {
  1262 	if (!lua_isfunction (L, -1)) {
  1248 		lua_pop (L, 1);
  1263 		lua_pop (L, 1);
  1249 		return;
  1264 		return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  1250 	}
  1265 	}
       
  1266 
  1251 	lua_newtable (L);
  1267 	lua_newtable (L);
       
  1268 	lua_pushliteral (L, "hook");
       
  1269 	lua_pushstring  (L, hookid);
       
  1270 	lua_settable (L, -3);
  1252 	while (arg->name != NULL) {
  1271 	while (arg->name != NULL) {
  1253 		char *name  = from_utf8 (arg->name);
  1272 		char *name  = from_utf8 (arg->name);
  1254 		char *value = from_utf8 (arg->value);
  1273 		char *value = from_utf8 (arg->value);
  1255 		lua_pushstring (L, name);
  1274 		lua_pushstring (L, name);
  1256 		lua_pushstring (L, value);
  1275 		lua_pushstring (L, value);
  1257 		lua_settable (L, -3);
  1276 		lua_settable (L, -3);
  1258 		g_free (name);
  1277 		g_free (name);
  1259 		g_free (value);
  1278 		g_free (value);
  1260 		arg++;
  1279 		arg++;
  1261 	}
  1280 	}
  1262 	if (lua_pcall (L, 1, 0, 0)) {
  1281 
  1263 		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1));
  1282 	if (lua_pcall (L, 1, 1, 0)) {
       
  1283 		scr_log_print (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1));
  1264 		lua_pop (L, 1);
  1284 		lua_pop (L, 1);
       
  1285 	} else {
       
  1286 		switch (lua_type (L, -1)) {
       
  1287 		case LUA_TSTRING:
       
  1288 		case LUA_TNUMBER:
       
  1289 			ret = luaL_checkenum (L, -1, lua_hook_handler_result);
       
  1290 			break;
       
  1291 		default:
       
  1292 			ret = HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
       
  1293 			break;
       
  1294 		}
       
  1295 		lua_pop (L, 1);
       
  1296 	}
       
  1297 
       
  1298 	return ret;
       
  1299 }
       
  1300 
       
  1301 /// main.hook
       
  1302 /// Installs hook handler, returns an object, that you need to keep until
       
  1303 /// hook handling is no more needed.
       
  1304 /// A: string (hook name), hook function, integer (priority, optional)
       
  1305 /// R: userdata (hook object)
       
  1306 static int lua_main_hook (lua_State *L)
       
  1307 {
       
  1308 	const char   *hook_name = luaL_checkstring (L, 1);
       
  1309 	int           priority  = G_PRIORITY_DEFAULT;
       
  1310 	lua_hook_t   *cb;
       
  1311 
       
  1312 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
       
  1313 
       
  1314 	if (lua_gettop (L) > 2)
       
  1315 		priority = luaL_checkenum (L, 3, lua_hook_handler_priority);
       
  1316 
       
  1317 	cb = lua_newuserdata (L, sizeof (lua_hook_t));
       
  1318 	luaL_getmetatable (L, "mcabber.hook");
       
  1319 	lua_setmetatable (L, -2);
       
  1320 
       
  1321 	lua_pushvalue (L, -1);
       
  1322 	cb -> selfref = luaL_ref (L, LUA_REGISTRYINDEX);
       
  1323 	lua_pushvalue (L, 1);
       
  1324 	cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX);
       
  1325 	lua_pushvalue (L, 2);
       
  1326 	cb -> cbref   = luaL_ref (L, LUA_REGISTRYINDEX);
       
  1327 	cb -> L       = L;
       
  1328 	cb -> hid     = hk_add_handler (lua_hook_cb, hook_name, priority, cb);
       
  1329 
       
  1330 	return 1;
       
  1331 }
       
  1332 
       
  1333 static void lua_mcabber_unregister_hook (lua_State *L, lua_hook_t *cb)
       
  1334 {
       
  1335 	const char *name;
       
  1336 
       
  1337 	if (!cb -> hid || cb -> nameref == LUA_NOREF)
       
  1338 		return;
       
  1339 
       
  1340 	lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1341 	name = lua_tostring (L, -1);
       
  1342 	if (name) {
       
  1343 		hk_del_handler (name, cb -> hid);
       
  1344 		cb -> hid = 0;
       
  1345 	}
       
  1346 
       
  1347 	lua_pop (L, 1);
       
  1348 }
       
  1349 
       
  1350 /// hook:del
       
  1351 /// Unregisters given hook handler from mcabber. Object will be destroyed later.
       
  1352 static int lua_mcabber_hook_del (lua_State *L)
       
  1353 {
       
  1354 	lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.hook");
       
  1355 	luaL_argcheck (L, cb != NULL, 1, "mcabber hook object expected");
       
  1356 	lua_mcabber_unregister_hook (L, cb);
       
  1357 	if (cb -> selfref != LUA_NOREF) {
       
  1358 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> selfref);
       
  1359 		cb -> selfref = LUA_NOREF;
       
  1360 	}
       
  1361 	return 0;
       
  1362 }
       
  1363 
       
  1364 static int lua_mcabber_hook_gc (lua_State *L)
       
  1365 {
       
  1366 	lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.hook");
       
  1367 	luaL_argcheck (L, cb != NULL, 1, "mcabber hook object expected");
       
  1368 	lua_mcabber_unregister_hook (L, cb);
       
  1369 	if (cb -> nameref != LUA_NOREF)
       
  1370 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1371 	if (cb -> cbref != LUA_NOREF)
       
  1372 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref);
       
  1373 	return 0;
       
  1374 }
       
  1375 
       
  1376 static const luaL_Reg lua_mcabber_hook_reg_m[] = {
       
  1377 	{ "del",  lua_mcabber_hook_del },
       
  1378 	{ "__gc", lua_mcabber_hook_gc  },
       
  1379 	{ NULL,   NULL                 },
       
  1380 };
       
  1381 
       
  1382 static void lua_hook_init (lua_State *L)
       
  1383 {
       
  1384 	luaL_newmetatable (L, "mcabber.hook");
       
  1385 	lua_pushvalue (L, -1);
       
  1386 	lua_setfield (L, -2, "__index");
       
  1387 	luaL_register (L, NULL, lua_mcabber_hook_reg_m);
       
  1388 	lua_pop (L, 1);
       
  1389 }
       
  1390 
       
  1391 #if 0
       
  1392 // OPTION GUARDS
       
  1393 
       
  1394 GSList *lua_installed_guards = NULL;
       
  1395 
       
  1396 typedef struct {
       
  1397 	lua_State *L;       // lua environment for handler use
       
  1398 	int        nameref; // reference to key name string
       
  1399 	int        cbref;   // reference to guard function
       
  1400 //	int        objref;  // self_reference to object
       
  1401 	guint      hid;     // hook id for object destruction
       
  1402 } lua_guard_t;
       
  1403 
       
  1404 /// guard function
       
  1405 /// Function to be called, when option changes it's value.
       
  1406 /// Old option value is still accessible through main.option.
       
  1407 /// A: string (key), string (new value)
       
  1408 /// R: string (value to save in hash table)
       
  1409 static gchar *lua_guard_cb (const gchar *key, const gchar *value)
       
  1410 {
       
  1411 	lua_guard_t *cb = ;// FIXME
       
  1412 	lua_State   *L  = cb -> L;
       
  1413 
       
  1414 	if (cb -> cbref == LUA_NOREF)
       
  1415 		return g_strdup (value);
       
  1416 
       
  1417 	lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> cbref);
       
  1418 	if (!lua_isfunction (L, -1)) {
       
  1419 		lua_pop (L, 1);
       
  1420 		return g_strdup (value);
       
  1421 	}
       
  1422 
       
  1423 	lua_pushstring (L, key);
       
  1424 	lua_psuhstring (L, value);
       
  1425 
       
  1426 	if (lua_pcall (L, 2, 1, 0)) {
       
  1427 		scr_log_print (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1));
       
  1428 		lua_pop (L, 1);
       
  1429 		return g_strdup (value);
       
  1430 	}
       
  1431 
       
  1432 	return g_strdup (lua_tostring (L, -1));
       
  1433 }
       
  1434 
       
  1435 /// main.guard
       
  1436 /// Installs option guard for given option. Returns guard object, that
       
  1437 /// should be kept around as long, as guard is needed.
       
  1438 /// A: string (option name), guard function
       
  1439 /// R: userdata (guard object)
       
  1440 static int lua_main_guard (lua_State *L)
       
  1441 {
       
  1442 	const char   *name      = luaL_checkstring (L, 1);
       
  1443 	int           priority  = G_PRIORITY_DEFAULT;
       
  1444 	lua_guard_t   *cb;
       
  1445 
       
  1446 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
       
  1447 
       
  1448 	cb = lua_newuserdata (L, sizeof (lua_guard_t));
       
  1449 	luaL_getmetatable (L, "mcabber.guard");
       
  1450 	lua_setmetatable (L, -2);
       
  1451 
       
  1452 	lua_pushvalue (L, 1);
       
  1453 	cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX);
       
  1454 	lua_pushvalue (L, 2);
       
  1455 	cb -> cbref   = luaL_ref (L, LUA_REGISTRYINDEX);
       
  1456 	cb -> L       = L;
       
  1457 
       
  1458 	settings_set_guard (name, lua_guard_cb)
       
  1459 
       
  1460 	return 1;
       
  1461 }
       
  1462 
       
  1463 static void lua_mcabber_unregister_guard (lua_State *L, lua_guard_t *cb)
       
  1464 {
       
  1465 	const char *name;
       
  1466 
       
  1467 	if (cb -> nameref == LUA_NOREF)
       
  1468 		return;
       
  1469 
       
  1470 	lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1471 	name = lua_tostring (L, -1);
       
  1472 	if (name) {
       
  1473 		settings_del_guard (name);
       
  1474 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1475 		cb -> nameref = LUA_NOREF;
       
  1476 	}
       
  1477 
       
  1478 	lua_pop (L, 1);
       
  1479 }
       
  1480 
       
  1481 /// guard:del
       
  1482 /// Unregisters given option guard from mcabber. Object will be destroyed later.
       
  1483 static int lua_mcabber_guard_del (lua_State *L)
       
  1484 {
       
  1485 	lua_guard_t *cb = luaL_checkudata (L, 1, "mcabber.guard");
       
  1486 	luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected");
       
  1487 	lua_mcabber_unregister_guard (L, cb);
       
  1488 	return 0;
       
  1489 }
       
  1490 
       
  1491 static int lua_mcabber_guard_gc (lua_State *L)
       
  1492 {
       
  1493 	lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.guard");
       
  1494 	luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected");
       
  1495 	lua_mcabber_unregister_guard (L, cb);
       
  1496 	if (cb -> cbref != LUA_NOREF)
       
  1497 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref);
       
  1498 	return 0;
       
  1499 }
       
  1500 
       
  1501 static const luaL_Reg lua_mcabber_hook_reg_m[] = {
       
  1502 	{ "del",  lua_mcabber_guard_del },
       
  1503 	{ "__gc", lua_mcabber_guard_gc  },
       
  1504 	{ NULL,   NULL                 },
       
  1505 };
       
  1506 
       
  1507 static void lua_guard_init (lua_State *L)
       
  1508 {
       
  1509 	luaL_newmetatable (L, "mcabber.guard");
       
  1510 	lua_pushvalue (L, -1);
       
  1511 	lua_setfield (L, -2, "__index");
       
  1512 	luaL_register (L, NULL, lua_mcabber_guard_reg_m);
       
  1513 	lua_pop (L, 1);
       
  1514 }
       
  1515 
       
  1516 static void lua_guard_uninit (lua_State *L)
       
  1517 {
       
  1518 }
       
  1519 #endif
       
  1520 
       
  1521 // MAIN INITIALIZATION CODE
       
  1522 
       
  1523 #ifdef LLM_LOG_HANDLER
       
  1524 // FIXME: this should not be here
       
  1525 guint lua_lm_log_handler_id;
       
  1526 
       
  1527 void lua_lm_log_handler (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer ignore)
       
  1528 {
       
  1529 	if (settings_opt_get_int ("lua_lm_debug"))
       
  1530 		scr_log_print (LPRINT_LOGNORM, "%s: %s", domain, message);
       
  1531 }
       
  1532 #endif
       
  1533 
       
  1534 static void do_lua(char *arg, lua_State *L)
       
  1535 {
       
  1536 	if (luaL_loadbuffer (L, arg, strlen (arg), "line")) {
       
  1537 		scr_log_print (LPRINT_LOGNORM, "lua: Compilation error: %s", lua_tostring (L, -1));
       
  1538 		lua_pop (L, 1);
       
  1539 		return;
       
  1540 	}
       
  1541  
       
  1542 	if (lua_pcall (L, 0, 0, 0)) {
       
  1543 		scr_log_print (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(L, -1));
       
  1544 		lua_pop (L, 1);
       
  1545 		return;
  1265 	}
  1546 	}
  1266 }
  1547 }
  1267 
  1548 
  1268 static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
  1549 static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
  1269 	if (nsize == 0) {
  1550 	if (nsize == 0) {
  1301 	reg ( roster         ) 
  1582 	reg ( roster         ) 
  1302 	reg ( current_buddy  ) 
  1583 	reg ( current_buddy  ) 
  1303 	reg ( full_jid       ) 
  1584 	reg ( full_jid       ) 
  1304 	reg ( buddy_info     ) 
  1585 	reg ( buddy_info     ) 
  1305 	reg ( timer          ) 
  1586 	reg ( timer          ) 
       
  1587 	reg ( alias          ) 
       
  1588 	reg ( binding        ) 
       
  1589 	reg ( fileoption     ) 
       
  1590 	reg ( add_feature    ) 
       
  1591 	reg ( del_feature    ) 
       
  1592 	reg ( event          )
       
  1593 	reg ( parse_args     ) 
       
  1594 	reg ( add_category   ) 
       
  1595 	reg ( del_category   ) 
       
  1596 	reg ( add_completion ) 
       
  1597 	reg ( del_completion ) 
       
  1598 	reg ( command        ) 
       
  1599 	reg ( print_info     ) 
       
  1600 	reg ( beep           ) 
       
  1601 	reg ( run            ) 
       
  1602 	reg ( status         ) 
       
  1603 	reg ( roster         ) 
       
  1604 	reg ( current_buddy  ) 
       
  1605 	reg ( full_jid       ) 
       
  1606 	reg ( buddy_info     ) 
       
  1607 	reg ( timer          ) 
  1306 	reg ( bgread         ) 
  1608 	reg ( bgread         ) 
       
  1609 	reg ( hook           )
  1307 	{ NULL, NULL },
  1610 	{ NULL, NULL },
  1308 };
  1611 };
  1309 #undef reg
  1612 #undef reg
  1310 
  1613 
  1311 const gchar *g_module_check_init (GModule *module)
  1614 const gchar *g_module_check_init (GModule *module)
  1353 #ifdef LLM_LOG_HANDLER
  1656 #ifdef LLM_LOG_HANDLER
  1354 	// FIXME: this should not be here.
  1657 	// FIXME: this should not be here.
  1355 	lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL);
  1658 	lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL);
  1356 #endif
  1659 #endif
  1357 
  1660 
       
  1661 	lua_hook_init (lua);
       
  1662 
  1358 	{
  1663 	{
  1359 		char *initfile = expand_filename (settings_opt_get ("lua_init_filename"));
  1664 		char *initfile = expand_filename (settings_opt_get ("lua_init_filename"));
  1360 		
  1665 		
  1361 		if (!initfile)
  1666 		if (!initfile)
  1362 			scr_LogPrint (LPRINT_LOGNORM, "lua: Cannot determine config file name");
  1667 			scr_log_print (LPRINT_LOGNORM, "lua: Cannot determine config file name");
  1363 		else {
  1668 		else {
  1364 			if (luaL_loadfile(lua, initfile)) {
  1669 			if (luaL_loadfile(lua, initfile)) {
  1365 				scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1));
  1670 				scr_log_print (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1));
  1366 				lua_pop (lua, 1);
  1671 				lua_pop (lua, 1);
  1367 			} else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) {
  1672 			} else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) {
  1368 				scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1));
  1673 				scr_log_print (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1));
  1369 				lua_pop (lua, 1);
  1674 				lua_pop (lua, 1);
  1370 			} else
  1675 			} else
  1371 				scr_LogPrint (LPRINT_LOGNORM, "lua: Loaded %s", initfile);
  1676 				scr_log_print (LPRINT_LOGNORM, "lua: Loaded %s", initfile);
  1372 			g_free (initfile);
  1677 			g_free (initfile);
  1373 		}
  1678 		}
  1374 	}
  1679 	}
  1375 
       
  1376 	hk_add_handler ((hk_handler_t) lua_hook, ~((guint32)0), lua);
       
  1377 
  1680 
  1378 	{
  1681 	{
  1379 		hk_arg_t args[] = {
  1682 		hk_arg_t args[] = {
  1380 			{ "hook", "hook-start" },
  1683 			{ NULL, NULL },
  1381 			{ NULL,   NULL         },
       
  1382 		};
  1684 		};
  1383 		lua_hook (0, args, lua);
  1685 		hk_run_handlers("hook-lua-start", args);
  1384 	}
  1686 	}
  1385 }
  1687 }
  1386 
  1688 
  1387 static void lua_events_cancel (gpointer data, gpointer ignore)
  1689 static void lua_events_cancel (gpointer data, gpointer ignore)
  1388 {
  1690 {
  1439 
  1741 
  1440 static void mlua_uninit (void)
  1742 static void mlua_uninit (void)
  1441 {
  1743 {
  1442 	if (lua) {
  1744 	if (lua) {
  1443 		hk_arg_t args[] = {
  1745 		hk_arg_t args[] = {
  1444 			{ "hook", "hook-quit" },
  1746 			{ NULL, NULL },
  1445 			{ NULL,   NULL        },
       
  1446 		};
  1747 		};
  1447 		lua_hook (0, args, lua);
  1748 		hk_run_handlers ("hook-lua-quit", args);
  1448 
  1749 
  1449 		hk_del_handler ((hk_handler_t) lua_hook, lua);
  1750 		// hook handlers will be unregistered upon objects destruction
  1450 
  1751 
  1451 		g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL);
  1752 		g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL);
  1452 		g_slist_free (lua_bgreads);
  1753 		g_slist_free (lua_bgreads);
  1453 		lua_bgreads = NULL;
  1754 		lua_bgreads = NULL;
  1454 
  1755