main.c
changeset 13 0b716ba23b03
parent 11 f74fff438888
child 14 ff13ba17fb6d
equal deleted inserted replaced
12:a52d61f57e0d 13:0b716ba23b03
    39 /// Prints its arguments to log with default priority.
    39 /// Prints its arguments to log with default priority.
    40 /// A: string/number, ...
    40 /// A: string/number, ...
    41 static int lua_global_print (lua_State *L)
    41 static int lua_global_print (lua_State *L)
    42 {
    42 {
    43 	lua_concat (L, lua_gettop (L));
    43 	lua_concat (L, lua_gettop (L));
    44 	scr_LogPrint (LPRINT_LOGNORM, lua_tostring (L, -1));
    44 	scr_LogPrint (LPRINT_LOGNORM | LPRINT_NOTUTF8, lua_tostring (L, -1));
    45 	return 0;
    45 	return 0;
    46 }
    46 }
    47 
    47 
    48 /// dopath
    48 /// dopath
    49 /// Loads lua file from default location.
    49 /// Loads lua file from default location.
       
    50 /// XXX: g_filename_from_utf8?
    50 /// A: string (filename, without ".lua")
    51 /// A: string (filename, without ".lua")
    51 /// R: string (error message, optional)
    52 /// R: string (error message, optional)
    52 static int lua_global_dopath (lua_State *L)
    53 static int lua_global_dopath (lua_State *L)
    53 {
    54 {
    54 	const char *name = luaL_checkstring (L, 1);
    55 	const char *name = luaL_checkstring (L, 1);
    76 }
    77 }
    77 
    78 
    78 /// main.config_file
    79 /// main.config_file
    79 /// Adds mcabber default config location path to config file name.
    80 /// Adds mcabber default config location path to config file name.
    80 /// Note: deprecated, use dopath.
    81 /// Note: deprecated, use dopath.
       
    82 /// XXX: should we use g_filename_from_utf8?
    81 /// A: string (filename)
    83 /// A: string (filename)
    82 /// R: string (full path)
    84 /// R: string (full path)
    83 static int lua_main_config_file (lua_State *L)
    85 static int lua_main_config_file (lua_State *L)
    84 {
    86 {
    85 	char *home = mcabber_config_filename (luaL_checkstring (L, 1));
    87 	char *home = mcabber_config_filename (luaL_checkstring (L, 1));
   113 	{ NULL,      0                   },
   115 	{ NULL,      0                   },
   114 };
   116 };
   115 
   117 
   116 /// main.log
   118 /// main.log
   117 /// Prints message to log.
   119 /// Prints message to log.
       
   120 /// Note: most likely you need notutf8 flag enabled.
   118 /// A: log print type, message, message...
   121 /// A: log print type, message, message...
   119 static int lua_main_log (lua_State *L)
   122 static int lua_main_log (lua_State *L)
   120 {
   123 {
   121 	int type = luaL_checkenum_multi (L, 1, lua_lprint);
   124 	int type = luaL_checkenum_multi (L, 1, lua_lprint);
   122 	lua_concat (L, lua_gettop (L) - 1);
   125 	lua_concat (L, lua_gettop (L) - 1);
   130 /// XXX: Should we do types here?
   133 /// XXX: Should we do types here?
   131 /// A: string (option name), string (value, optional)
   134 /// A: string (option name), string (value, optional)
   132 /// R: string (value, optional)
   135 /// R: string (value, optional)
   133 static int lua_main_option (lua_State *L)
   136 static int lua_main_option (lua_State *L)
   134 {
   137 {
   135 	const char *name = luaL_checkstring (L, 1);
   138 	char *name = to_utf8 (luaL_checkstring (L, 1));
   136 	if (lua_gettop (L) > 1) { // Set
   139 	if (lua_gettop (L) > 1) { // Set
   137 		if (lua_type (L, 2) == LUA_TNIL) // Unset
   140 		if (lua_type (L, 2) == LUA_TNIL) // Unset
   138 			settings_del (SETTINGS_TYPE_OPTION, name);
   141 			settings_del (SETTINGS_TYPE_OPTION, name);
   139 		else { // Set
   142 		else { // Set
   140 			const char *value = luaL_checkstring (L, 2);
   143 			char *value = to_utf8 (luaL_checkstring (L, 2));
   141 			settings_set (SETTINGS_TYPE_OPTION, name, value);
   144 			settings_set (SETTINGS_TYPE_OPTION, name, value);
       
   145 			g_free (value);
   142 		}
   146 		}
       
   147 		g_free (name);
   143 		return 0;
   148 		return 0;
   144 	} else { // Get
   149 	} else { // Get
   145 		const char *value = settings_get (SETTINGS_TYPE_OPTION, name);
   150 		char *value = from_utf8 (settings_get (SETTINGS_TYPE_OPTION, name));
   146 		if (value)
   151 		if (value) {
   147 			lua_pushstring (L, value);
   152 			lua_pushstring (L, value);
   148 		else
   153 			g_free (value);
       
   154 		} else
   149 			lua_pushnil (L);
   155 			lua_pushnil (L);
       
   156 		g_free (name);
   150 		return 1;
   157 		return 1;
   151 	}
   158 	}
   152 }
   159 }
   153 
   160 
   154 /// main.connection
   161 /// main.connection
   164 /// main.print_info
   171 /// main.print_info
   165 /// Prints a system message to buddy's window.
   172 /// Prints a system message to buddy's window.
   166 /// A: string (jid), string (message)
   173 /// A: string (jid), string (message)
   167 static int lua_main_print_info (lua_State *L)
   174 static int lua_main_print_info (lua_State *L)
   168 {
   175 {
   169 	char *to = jidtodisp (luaL_checkstring (L, 1));
   176 	char *jid  = to_utf8 (luaL_checkstring (L, 1));
   170 	scr_WriteIncomingMessage (to, luaL_checkstring (L, 2), 0, HBB_PREFIX_INFO, 0);
   177 	char *to   = jidtodisp (jid);
       
   178 	char *mesg = to_utf8 (luaL_checkstring (L, 2));
       
   179 	scr_WriteIncomingMessage (to, mesg, 0, HBB_PREFIX_INFO, 0);
       
   180 	g_free (mesg);
   171 	g_free (to);
   181 	g_free (to);
       
   182 	g_free (jid);
   172 	return 0;
   183 	return 0;
   173 }
   184 }
   174 
   185 
   175 /// main.beep
   186 /// main.beep
   176 /// Beeps with system speaker.
   187 /// Beeps with system speaker.
   202 }
   213 }
   203 
   214 
   204 // expects table on top
   215 // expects table on top
   205 static void lua_rosterlist_callback (gpointer buddy, lua_State *L)
   216 static void lua_rosterlist_callback (gpointer buddy, lua_State *L)
   206 {
   217 {
       
   218 	char *jid = from_utf8 (buddy_getjid (buddy));
   207 	lua_pushnumber (L, lua_objlen (L, -1) + 1);
   219 	lua_pushnumber (L, lua_objlen (L, -1) + 1);
   208 	lua_pushstring (L, buddy_getjid (buddy));
   220 	lua_pushstring (L, jid);
   209 	lua_settable (L, -3);
   221 	lua_settable (L, -3);
       
   222 	g_free (jid);
   210 }
   223 }
   211 
   224 
   212 /// main.roster
   225 /// main.roster
   213 /// Returns array of jids of buddies in roster.
   226 /// Returns array of jids of buddies in roster.
   214 /// R: table
   227 /// R: table
   224 /// A: string (optional)
   237 /// A: string (optional)
   225 /// R: string (optional)
   238 /// R: string (optional)
   226 static int lua_main_current_buddy (lua_State *L)
   239 static int lua_main_current_buddy (lua_State *L)
   227 {
   240 {
   228 	if (lua_gettop (L) > 0) { // Set
   241 	if (lua_gettop (L) > 0) { // Set
       
   242 		// XXX: we need not convert to utf, RS works on jids/names in locale charset,
       
   243 		// but will jidtodisp always correctly work on such tings?
   229 		char *jid = jidtodisp (luaL_checkstring (L, 1));
   244 		char *jid = jidtodisp (luaL_checkstring (L, 1));
   230 		scr_RosterSearch (jid);
   245 		scr_RosterSearch (jid);
   231 		g_free (jid);
   246 		g_free (jid);
   232 		return 0;
   247 		return 0;
   233 	} else { // Get
   248 	} else { // Get
   234 		lua_pushstring (L, buddy_getjid (BUDDATA (current_buddy)));
   249 		char *jid = from_utf8 (buddy_getjid (BUDDATA (current_buddy)));
       
   250 		lua_pushstring (L, jid);
       
   251 		g_free (jid);
   235 		return 1;
   252 		return 1;
   236 	}
   253 	}
   237 }
   254 }
   238 
   255 
   239 /// main.full_jid
   256 /// main.full_jid
   244 static int lua_main_full_jid (lua_State *L)
   261 static int lua_main_full_jid (lua_State *L)
   245 {
   262 {
   246 	GList *buddy;
   263 	GList *buddy;
   247 	GSList *resources;
   264 	GSList *resources;
   248 	GSList *resource;
   265 	GSList *resource;
   249 	if (lua_gettop (L) > 0)
   266 	if (lua_gettop (L) > 0) {
   250 		buddy = buddy_search_jid (luaL_checkstring (L, 1));
   267 		char *jid = from_utf8 (luaL_checkstring (L, 1));
   251 	else
   268 		buddy = buddy_search_jid (jid);
       
   269 		g_free (jid);
       
   270 	} else
   252 		buddy = current_buddy;
   271 		buddy = current_buddy;
   253 	if (!buddy)
   272 	if (!buddy)
   254 		return 0;
   273 		return 0;
   255 	resources = buddy_getresources (BUDDATA (buddy));
   274 	resources = buddy_getresources (BUDDATA (buddy));
   256 	if (!resources) {
   275 	if (!resources) {
   257 		lua_pushstring (L, buddy_getjid (BUDDATA (buddy)));
   276 		char *loc = from_utf8 (buddy_getjid (BUDDATA (buddy)));
   258 		return 1;
   277 		lua_pushstring (L, loc);
   259 	}
   278 		g_free (loc);
   260 	lua_pushfstring (L, "%s%c%s", buddy_getjid (BUDDATA (buddy)), JID_RESOURCE_SEPARATOR, g_slist_last(resources)->data);
   279 	} else {
   261 	for (resource = resources; resource; resource = g_slist_next (resource))
   280 		char *jid = from_utf8 (buddy_getjid (BUDDATA (buddy)));
   262 		g_free (resource->data);
   281 		char *res = from_utf8 (g_slist_last (resources)->data);
   263 	g_slist_free (resources);
   282 		lua_pushfstring (L, "%s%c%s", jid, JID_RESOURCE_SEPARATOR, res);
       
   283 		for (resource = resources; resource; resource = g_slist_next (resource))
       
   284 			g_free (resource->data);
       
   285 		g_slist_free (resources);
       
   286 		g_free (jid);
       
   287 		g_free (res);
       
   288 	}
   264 	return 1;
   289 	return 1;
   265 }
   290 }
   266 
   291 
   267 typedef struct {
   292 typedef struct {
   268 	lua_State *L;
   293 	lua_State *L;
   270 } lua_state_and_buddy_t; // :)
   295 } lua_state_and_buddy_t; // :)
   271 
   296 
   272 // expects table on top!
   297 // expects table on top!
   273 static void lua_buddy_resources_callback (gpointer resource, lua_state_and_buddy_t *d)
   298 static void lua_buddy_resources_callback (gpointer resource, lua_state_and_buddy_t *d)
   274 {
   299 {
   275 	lua_pushstring (d->L, resource);
   300 	char *loc = from_utf8 (resource);
       
   301 	lua_pushstring (d->L, loc);
       
   302 	g_free (loc);
   276 	lua_createtable (d->L, 0, 3);
   303 	lua_createtable (d->L, 0, 3);
   277 	lua_pushstring (d->L, "priority");
   304 	lua_pushstring (d->L, "priority");
   278 	lua_pushnumber (d->L, buddy_getresourceprio (d->buddy, resource));
   305 	lua_pushnumber (d->L, buddy_getresourceprio (d->buddy, resource));
   279 	lua_settable   (d->L, -3);
   306 	lua_settable   (d->L, -3);
   280 	lua_pushstring  (d->L, "status");
   307 	lua_pushstring  (d->L, "status");
   281 	lua_pushlstring (d->L, &imstatus2char[buddy_getstatus (d->buddy, resource)], 1);
   308 	lua_pushlstring (d->L, &imstatus2char[buddy_getstatus (d->buddy, resource)], 1);
   282 	lua_settable    (d->L, -3);
   309 	lua_settable    (d->L, -3);
   283 	lua_pushstring (d->L, "message");
   310 	lua_pushstring (d->L, "message");
   284 	lua_pushstring (d->L, buddy_getstatusmsg (d->buddy, resource));
   311 	loc = from_utf8 (buddy_getstatusmsg (d->buddy, resource));
       
   312 	lua_pushstring (d->L, loc);
       
   313 	g_free (loc);
   285 	lua_settable   (d->L, -3);
   314 	lua_settable   (d->L, -3);
   286 	lua_settable (d->L, -3);
   315 	lua_settable (d->L, -3);
   287 	g_free (resource);
   316 	g_free (resource);
   288 }
   317 }
   289 
   318 
   295 /// priority, status and message.
   324 /// priority, status and message.
   296 /// A: string (jid)
   325 /// A: string (jid)
   297 /// R: table
   326 /// R: table
   298 static int lua_main_buddy_info (lua_State *L)
   327 static int lua_main_buddy_info (lua_State *L)
   299 {
   328 {
   300 	char                  *jid   = jidtodisp (luaL_checkstring (L, 1));
   329 	char                  *loc   = to_utf8 (luaL_checkstring (L, 1));
       
   330 	char                  *jid   = jidtodisp (loc);
   301 	GSList                *buddy = roster_find (jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM);
   331 	GSList                *buddy = roster_find (jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM);
   302 	GSList                *resources;
   332 	GSList                *resources;
   303 	lua_state_and_buddy_t  snb;
   333 	lua_state_and_buddy_t  snb;
   304 	g_free (jid);
   334 	g_free (jid);
       
   335 	g_free (loc);
   305 
   336 
   306 	if (!buddy) {
   337 	if (!buddy) {
   307 		lua_pushnil (L);
   338 		lua_pushnil (L);
   308 		return 1;
   339 		return 1;
   309 	}
   340 	}
   311 	lua_createtable (L, 0, 3);
   342 	lua_createtable (L, 0, 3);
   312 	lua_pushstring (L, "type");
   343 	lua_pushstring (L, "type");
   313 	luaL_pushenum  (L, buddy_gettype (BUDDATA (buddy)), lua_roster_type);
   344 	luaL_pushenum  (L, buddy_gettype (BUDDATA (buddy)), lua_roster_type);
   314 	lua_settable   (L, -3);
   345 	lua_settable   (L, -3);
   315 	lua_pushstring (L, "name");
   346 	lua_pushstring (L, "name");
   316 	lua_pushstring (L, buddy_getname (BUDDATA (buddy)));
   347 	loc = from_utf8 (buddy_getname (BUDDATA (buddy)));
       
   348 	lua_pushstring (L, loc);
       
   349 	g_free (loc);
   317 	lua_settable   (L, -3);
   350 	lua_settable   (L, -3);
   318 	lua_pushstring  (L, "onserver");
   351 	lua_pushstring  (L, "onserver");
   319 	lua_pushboolean (L, buddy_getonserverflag (BUDDATA (buddy)));
   352 	lua_pushboolean (L, buddy_getonserverflag (BUDDATA (buddy)));
   320 	lua_settable    (L, -3);
   353 	lua_settable    (L, -3);
   321 	lua_pushstring  (L, "resources");
   354 	lua_pushstring  (L, "resources");
   337 /// main.add_feature
   370 /// main.add_feature
   338 /// Adds xmlns to disco#info features list.
   371 /// Adds xmlns to disco#info features list.
   339 /// A: string (xmlns)
   372 /// A: string (xmlns)
   340 static int lua_main_add_feature (lua_State *L)
   373 static int lua_main_add_feature (lua_State *L)
   341 {
   374 {
   342 	const char *xmlns = luaL_checkstring (L, 1);
   375 	char *xmlns = to_utf8 (luaL_checkstring (L, 1));
   343 	xmpp_add_feature (xmlns);
   376 	xmpp_add_feature (xmlns);
   344 	lua_added_features = g_slist_prepend (lua_added_features, g_strdup (xmlns));
   377 	lua_added_features = g_slist_prepend (lua_added_features, xmlns);
   345 	return 0;
   378 	return 0;
   346 }
   379 }
   347 
   380 
   348 /// main.del_feature
   381 /// main.del_feature
   349 /// Removes xmlns from disco#info features list.
   382 /// Removes xmlns from disco#info features list.
   350 /// A: stirng (xmlns)
   383 /// A: stirng (xmlns)
   351 static int lua_main_del_feature (lua_State *L)
   384 static int lua_main_del_feature (lua_State *L)
   352 {
   385 {
   353 	const char *xmlns = luaL_checkstring (L, 1);
   386 	char   *xmlns = to_utf8 (luaL_checkstring (L, 1));
   354 	GSList     *el    = g_slist_find_custom (lua_added_features, xmlns, (GCompareFunc) strcmp);
   387 	GSList *el    = g_slist_find_custom (lua_added_features, xmlns, (GCompareFunc) strcmp);
   355 	xmpp_del_feature (xmlns);
   388 	xmpp_del_feature (xmlns);
   356 	if (el) {
   389 	if (el) {
   357 		g_free (el->data);
   390 		g_free (el->data);
   358 		lua_added_features = g_slist_delete_link (lua_added_features, el);
   391 		lua_added_features = g_slist_delete_link (lua_added_features, el);
   359 	}
   392 	}
   413 /// main.add_completion
   446 /// main.add_completion
   414 /// Adds word to a completion list.
   447 /// Adds word to a completion list.
   415 /// A: integer (completion group id), string (word)
   448 /// A: integer (completion group id), string (word)
   416 static int lua_main_add_completion (lua_State *L)
   449 static int lua_main_add_completion (lua_State *L)
   417 {
   450 {
   418 	guint       cid  = luaL_checkinteger (L, 1);
   451 	guint  cid  = luaL_checkinteger (L, 1);
   419 	const char *word = luaL_checkstring (L, 2);
   452 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   420 	compl_add_category_word (cid, word);
   453 	compl_add_category_word (cid, word);
       
   454 	g_free (word);
   421 }
   455 }
   422 
   456 
   423 /// main.del_completion
   457 /// main.del_completion
   424 /// Removes word from a completion list.
   458 /// Removes word from a completion list.
   425 /// A: integer (completion group id), string (word)
   459 /// A: integer (completion group id), string (word)
   426 static int lua_main_del_completion (lua_State *L)
   460 static int lua_main_del_completion (lua_State *L)
   427 {
   461 {
   428 	guint       cid  = luaL_checkinteger (L, 1);
   462 	guint  cid  = luaL_checkinteger (L, 1);
   429 	const char *word = luaL_checkstring (L, 2);
   463 	char  *word = to_utf8 (luaL_checkstring (L, 2)); // XXX
   430 	compl_del_category_word (cid, word);
   464 	compl_del_category_word (cid, word);
       
   465 	g_free (word);
   431 }
   466 }
   432 
   467 
   433 /// main.command
   468 /// main.command
   434 /// Associates or breaks association between mcabber command name and lua function.
   469 /// Associates or breaks association between mcabber command name and lua function.
   435 /// To unregister command omit function argument.
   470 /// To unregister command omit function argument.
   439 /// Also note, that it ignores keys in a completion table.
   474 /// Also note, that it ignores keys in a completion table.
   440 /// A: string (command name), command function (optional), table (completions, optional)/completion type (or integer comletion group id, optional)
   475 /// A: string (command name), command function (optional), table (completions, optional)/completion type (or integer comletion group id, optional)
   441 /// R: completion type (integer completion group id or string for builtin types, optional)
   476 /// R: completion type (integer completion group id or string for builtin types, optional)
   442 static int lua_main_command (lua_State *L)
   477 static int lua_main_command (lua_State *L)
   443 {
   478 {
   444 	const char             *name = luaL_checkstring (L, 1);
   479 	const char             *name = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/
   445 	lua_command_callback_t *cb;
   480 	lua_command_callback_t *cb;
   446 	if (lua_gettop (L) > 1) { // Register
   481 	if (lua_gettop (L) > 1) { // Register
   447 		guint cid = 0;
   482 		guint cid = 0;
   448 		luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   483 		luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   449 
   484 
   451 			if (lua_type (L, 3) == LUA_TTABLE) {
   486 			if (lua_type (L, 3) == LUA_TTABLE) {
   452 				cid = compl_new_category ();
   487 				cid = compl_new_category ();
   453 				if (cid) {
   488 				if (cid) {
   454 					lua_pushnil (L);
   489 					lua_pushnil (L);
   455 					while (lua_next (L, 3)) {
   490 					while (lua_next (L, 3)) {
   456 						compl_add_category_word (cid, luaL_checkstring (L, -1));
   491 						char *word = to_utf8 (luaL_checkstring (L, -1));
       
   492 						compl_add_category_word (cid, word);
   457 						lua_pop (L, 1);
   493 						lua_pop (L, 1);
       
   494 						g_free (word);
   458 					}
   495 					}
   459 				}
   496 				}
   460 			} else
   497 			} else
   461 				cid = luaL_checkenum (L, 3, lua_completion_type);
   498 				cid = luaL_checkenum (L, 3, lua_completion_type);
   462 		}
   499 		}
   677 		lua_pop (lua, 1);
   714 		lua_pop (lua, 1);
   678 		return;
   715 		return;
   679 	}
   716 	}
   680 	lua_newtable (L);
   717 	lua_newtable (L);
   681 	while (arg->name != NULL) {
   718 	while (arg->name != NULL) {
   682 		lua_pushstring (L, arg->name);
   719 		char *name  = from_utf8 (arg->name);
   683 		lua_pushstring (L, arg->value);
   720 		char *value = from_utf8 (arg->value);
       
   721 		lua_pushstring (L, name);
       
   722 		lua_pushstring (L, value);
   684 		lua_settable (L, -3);
   723 		lua_settable (L, -3);
       
   724 		g_free (name);
       
   725 		g_free (value);
   685 		arg++;
   726 		arg++;
   686 	}
   727 	}
   687 	if (lua_pcall (lua, 1, 0, 0)) {
   728 	if (lua_pcall (lua, 1, 0, 0)) {
   688 		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (lua, -1));
   729 		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (lua, -1));
   689 		lua_pop (lua, 1);
   730 		lua_pop (lua, 1);