xref: /vim-8.2.3635/src/if_lua.c (revision 4eefe47e)
11dced572SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
20ba04296SBram Moolenaar  *
30ba04296SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
40ba04296SBram Moolenaar  *
50ba04296SBram Moolenaar  * Lua interface by Luis Carvalho
60ba04296SBram Moolenaar  *
70ba04296SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
80ba04296SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
90ba04296SBram Moolenaar  * See README.txt for an overview of the Vim source code.
100ba04296SBram Moolenaar  */
110ba04296SBram Moolenaar 
12e2793357SBram Moolenaar #include "vim.h"
13e2793357SBram Moolenaar 
140ba04296SBram Moolenaar #include <lua.h>
150ba04296SBram Moolenaar #include <lualib.h>
160ba04296SBram Moolenaar #include <lauxlib.h>
170ba04296SBram Moolenaar 
180ba04296SBram Moolenaar /* Only do the following when the feature is enabled.  Needed for "make
190ba04296SBram Moolenaar  * depend". */
200ba04296SBram Moolenaar #if defined(FEAT_LUA) || defined(PROTO)
210ba04296SBram Moolenaar 
220ba04296SBram Moolenaar #define LUAVIM_CHUNKNAME "vim chunk"
230ba04296SBram Moolenaar #define LUAVIM_NAME "vim"
241dced572SBram Moolenaar #define LUAVIM_EVALNAME "luaeval"
251dced572SBram Moolenaar #define LUAVIM_EVALHEADER "local _A=select(1,...) return "
260ba04296SBram Moolenaar 
270ba04296SBram Moolenaar typedef buf_T *luaV_Buffer;
280ba04296SBram Moolenaar typedef win_T *luaV_Window;
291dced572SBram Moolenaar typedef dict_T *luaV_Dict;
301dced572SBram Moolenaar typedef list_T *luaV_List;
31ca06da92SBram Moolenaar typedef struct {
32*4eefe47eSBram Moolenaar     char_u	*name;	// funcref
33ca06da92SBram Moolenaar     dict_T	*self;	// selfdict
34ca06da92SBram Moolenaar } luaV_Funcref;
350ba04296SBram Moolenaar typedef void (*msgfunc_T)(char_u *);
360ba04296SBram Moolenaar 
371dced572SBram Moolenaar static const char LUAVIM_DICT[] = "dict";
381dced572SBram Moolenaar static const char LUAVIM_LIST[] = "list";
39ca06da92SBram Moolenaar static const char LUAVIM_FUNCREF[] = "funcref";
400ba04296SBram Moolenaar static const char LUAVIM_BUFFER[] = "buffer";
410ba04296SBram Moolenaar static const char LUAVIM_WINDOW[] = "window";
420ba04296SBram Moolenaar static const char LUAVIM_FREE[] = "luaV_free";
431dced572SBram Moolenaar static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
441dced572SBram Moolenaar static const char LUAVIM_SETREF[] = "luaV_setref";
450ba04296SBram Moolenaar 
461dced572SBram Moolenaar /* most functions are closures with a cache table as first upvalue;
471dced572SBram Moolenaar  * get/setudata manage references to vim userdata in cache table through
481dced572SBram Moolenaar  * object pointers (light userdata) */
491dced572SBram Moolenaar #define luaV_getudata(L, v) \
501dced572SBram Moolenaar     lua_pushlightuserdata((L), (void *) (v)); \
511dced572SBram Moolenaar     lua_rawget((L), lua_upvalueindex(1))
521dced572SBram Moolenaar #define luaV_setudata(L, v) \
531dced572SBram Moolenaar     lua_pushlightuserdata((L), (void *) (v)); \
541dced572SBram Moolenaar     lua_pushvalue((L), -2); \
551dced572SBram Moolenaar     lua_rawset((L), lua_upvalueindex(1))
560ba04296SBram Moolenaar #define luaV_getfield(L, s) \
570ba04296SBram Moolenaar     lua_pushlightuserdata((L), (void *)(s)); \
580ba04296SBram Moolenaar     lua_rawget((L), LUA_REGISTRYINDEX)
590ba04296SBram Moolenaar #define luaV_checksandbox(L) \
600ba04296SBram Moolenaar     if (sandbox) luaL_error((L), "not allowed in sandbox")
610ba04296SBram Moolenaar #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
620ba04296SBram Moolenaar #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
63ca06da92SBram Moolenaar #define luaV_checktypval(L, a, v, msg) \
64ca06da92SBram Moolenaar     do { \
65ca06da92SBram Moolenaar         if (luaV_totypval(L, a, v) == FAIL) \
66ca06da92SBram Moolenaar 	    luaL_error(L, msg ": cannot convert value"); \
67ca06da92SBram Moolenaar     } while (0)
680ba04296SBram Moolenaar 
691dced572SBram Moolenaar static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
701dced572SBram Moolenaar static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
71*4eefe47eSBram Moolenaar static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
721dced572SBram Moolenaar 
731dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
741dced572SBram Moolenaar #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
751dced572SBram Moolenaar #define luaL_typeerror luaL_typerror
761dced572SBram Moolenaar #else
771dced572SBram Moolenaar #define luaV_openlib luaL_setfuncs
781dced572SBram Moolenaar #endif
790ba04296SBram Moolenaar 
800ba04296SBram Moolenaar #ifdef DYNAMIC_LUA
812334b6d5SBram Moolenaar 
824f97475dSBram Moolenaar #ifndef MSWIN
832334b6d5SBram Moolenaar # include <dlfcn.h>
842334b6d5SBram Moolenaar # define HANDLE void*
852334b6d5SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
862334b6d5SBram Moolenaar # define symbol_from_dll dlsym
872334b6d5SBram Moolenaar # define close_dll dlclose
882334b6d5SBram Moolenaar #else
89ebbcb824SBram Moolenaar # define load_dll vimLoadLib
902334b6d5SBram Moolenaar # define symbol_from_dll GetProcAddress
912334b6d5SBram Moolenaar # define close_dll FreeLibrary
922334b6d5SBram Moolenaar #endif
932334b6d5SBram Moolenaar 
940ba04296SBram Moolenaar /* lauxlib */
951dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
960ba04296SBram Moolenaar #define luaL_register dll_luaL_register
971dced572SBram Moolenaar #define luaL_prepbuffer dll_luaL_prepbuffer
981dced572SBram Moolenaar #define luaL_openlib dll_luaL_openlib
990ba04296SBram Moolenaar #define luaL_typerror dll_luaL_typerror
1001dced572SBram Moolenaar #define luaL_loadfile dll_luaL_loadfile
1011dced572SBram Moolenaar #define luaL_loadbuffer dll_luaL_loadbuffer
1021dced572SBram Moolenaar #else
1031dced572SBram Moolenaar #define luaL_prepbuffsize dll_luaL_prepbuffsize
1041dced572SBram Moolenaar #define luaL_setfuncs dll_luaL_setfuncs
1051dced572SBram Moolenaar #define luaL_loadfilex dll_luaL_loadfilex
1061dced572SBram Moolenaar #define luaL_loadbufferx dll_luaL_loadbufferx
1071dced572SBram Moolenaar #define luaL_argerror dll_luaL_argerror
1081dced572SBram Moolenaar #endif
109bd2f3c3eSBram Moolenaar #define luaL_checkany dll_luaL_checkany
1100ba04296SBram Moolenaar #define luaL_checklstring dll_luaL_checklstring
1110ba04296SBram Moolenaar #define luaL_checkinteger dll_luaL_checkinteger
1120ba04296SBram Moolenaar #define luaL_optinteger dll_luaL_optinteger
1130ba04296SBram Moolenaar #define luaL_checktype dll_luaL_checktype
1140ba04296SBram Moolenaar #define luaL_error dll_luaL_error
1150ba04296SBram Moolenaar #define luaL_newstate dll_luaL_newstate
1160ba04296SBram Moolenaar #define luaL_buffinit dll_luaL_buffinit
1170ba04296SBram Moolenaar #define luaL_addlstring dll_luaL_addlstring
1180ba04296SBram Moolenaar #define luaL_pushresult dll_luaL_pushresult
1190ba04296SBram Moolenaar /* lua */
1201dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
1211dced572SBram Moolenaar #define lua_tonumber dll_lua_tonumber
1221dced572SBram Moolenaar #define lua_tointeger dll_lua_tointeger
1231dced572SBram Moolenaar #define lua_call dll_lua_call
1241dced572SBram Moolenaar #define lua_pcall dll_lua_pcall
1251dced572SBram Moolenaar #else
1261dced572SBram Moolenaar #define lua_tonumberx dll_lua_tonumberx
1271dced572SBram Moolenaar #define lua_tointegerx dll_lua_tointegerx
1281dced572SBram Moolenaar #define lua_callk dll_lua_callk
1291dced572SBram Moolenaar #define lua_pcallk dll_lua_pcallk
1301dced572SBram Moolenaar #define lua_getglobal dll_lua_getglobal
1311dced572SBram Moolenaar #define lua_setglobal dll_lua_setglobal
1321dced572SBram Moolenaar #endif
1331f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
1341f860d85SBram Moolenaar #define lua_replace dll_lua_replace
1351f860d85SBram Moolenaar #define lua_remove dll_lua_remove
1361f860d85SBram Moolenaar #endif
1371f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
1381f860d85SBram Moolenaar #define lua_rotate dll_lua_rotate
1391f860d85SBram Moolenaar #define lua_copy dll_lua_copy
1401f860d85SBram Moolenaar #endif
141bd2f3c3eSBram Moolenaar #define lua_typename dll_lua_typename
1420ba04296SBram Moolenaar #define lua_close dll_lua_close
1430ba04296SBram Moolenaar #define lua_gettop dll_lua_gettop
1440ba04296SBram Moolenaar #define lua_settop dll_lua_settop
1450ba04296SBram Moolenaar #define lua_pushvalue dll_lua_pushvalue
1460ba04296SBram Moolenaar #define lua_isnumber dll_lua_isnumber
1470ba04296SBram Moolenaar #define lua_isstring dll_lua_isstring
1480ba04296SBram Moolenaar #define lua_type dll_lua_type
1490ba04296SBram Moolenaar #define lua_rawequal dll_lua_rawequal
1500ba04296SBram Moolenaar #define lua_toboolean dll_lua_toboolean
1510ba04296SBram Moolenaar #define lua_tolstring dll_lua_tolstring
1520ba04296SBram Moolenaar #define lua_touserdata dll_lua_touserdata
1530ba04296SBram Moolenaar #define lua_pushnil dll_lua_pushnil
1540ba04296SBram Moolenaar #define lua_pushnumber dll_lua_pushnumber
1550ba04296SBram Moolenaar #define lua_pushinteger dll_lua_pushinteger
1560ba04296SBram Moolenaar #define lua_pushlstring dll_lua_pushlstring
1570ba04296SBram Moolenaar #define lua_pushstring dll_lua_pushstring
1580ba04296SBram Moolenaar #define lua_pushfstring dll_lua_pushfstring
1590ba04296SBram Moolenaar #define lua_pushcclosure dll_lua_pushcclosure
1600ba04296SBram Moolenaar #define lua_pushboolean dll_lua_pushboolean
1610ba04296SBram Moolenaar #define lua_pushlightuserdata dll_lua_pushlightuserdata
1620ba04296SBram Moolenaar #define lua_getfield dll_lua_getfield
1630ba04296SBram Moolenaar #define lua_rawget dll_lua_rawget
1641dced572SBram Moolenaar #define lua_rawgeti dll_lua_rawgeti
1650ba04296SBram Moolenaar #define lua_createtable dll_lua_createtable
166830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
167830e3583SBram Moolenaar  #define lua_newuserdatauv dll_lua_newuserdatauv
168830e3583SBram Moolenaar #else
1690ba04296SBram Moolenaar  #define lua_newuserdata dll_lua_newuserdata
170830e3583SBram Moolenaar #endif
1710ba04296SBram Moolenaar #define lua_getmetatable dll_lua_getmetatable
1720ba04296SBram Moolenaar #define lua_setfield dll_lua_setfield
1730ba04296SBram Moolenaar #define lua_rawset dll_lua_rawset
1740ba04296SBram Moolenaar #define lua_rawseti dll_lua_rawseti
1750ba04296SBram Moolenaar #define lua_setmetatable dll_lua_setmetatable
176bd2f3c3eSBram Moolenaar #define lua_next dll_lua_next
1770ba04296SBram Moolenaar /* libs */
1780ba04296SBram Moolenaar #define luaopen_base dll_luaopen_base
1790ba04296SBram Moolenaar #define luaopen_table dll_luaopen_table
1800ba04296SBram Moolenaar #define luaopen_string dll_luaopen_string
1810ba04296SBram Moolenaar #define luaopen_math dll_luaopen_math
18216c98f9cSBram Moolenaar #define luaopen_io dll_luaopen_io
1830ba04296SBram Moolenaar #define luaopen_os dll_luaopen_os
1840ba04296SBram Moolenaar #define luaopen_package dll_luaopen_package
1850ba04296SBram Moolenaar #define luaopen_debug dll_luaopen_debug
18616c98f9cSBram Moolenaar #define luaL_openlibs dll_luaL_openlibs
1870ba04296SBram Moolenaar 
1880ba04296SBram Moolenaar /* lauxlib */
1891dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
1900ba04296SBram Moolenaar void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
1911dced572SBram Moolenaar char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
1921dced572SBram Moolenaar void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
1930ba04296SBram Moolenaar int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
1941dced572SBram Moolenaar int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
1951dced572SBram Moolenaar int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
1961dced572SBram Moolenaar #else
1971dced572SBram Moolenaar char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
1981dced572SBram Moolenaar void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
1991dced572SBram Moolenaar int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
2001dced572SBram Moolenaar int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
2011dced572SBram Moolenaar int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
2021dced572SBram Moolenaar #endif
203bd2f3c3eSBram Moolenaar void (*dll_luaL_checkany) (lua_State *L, int narg);
2040ba04296SBram Moolenaar const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
2050ba04296SBram Moolenaar lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
2060ba04296SBram Moolenaar lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
2070ba04296SBram Moolenaar void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
2080ba04296SBram Moolenaar int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
2090ba04296SBram Moolenaar lua_State *(*dll_luaL_newstate) (void);
2100ba04296SBram Moolenaar void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
2110ba04296SBram Moolenaar void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
2120ba04296SBram Moolenaar void (*dll_luaL_pushresult) (luaL_Buffer *B);
2130ba04296SBram Moolenaar /* lua */
2141dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
2151dced572SBram Moolenaar lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
2161dced572SBram Moolenaar lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
2171dced572SBram Moolenaar void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
2181dced572SBram Moolenaar int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
2191dced572SBram Moolenaar #else
2201dced572SBram Moolenaar lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
2211dced572SBram Moolenaar lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
2221dced572SBram Moolenaar void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
2231dced572SBram Moolenaar 	lua_CFunction k);
2241dced572SBram Moolenaar int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
2251dced572SBram Moolenaar 	int ctx, lua_CFunction k);
2261dced572SBram Moolenaar void (*dll_lua_getglobal) (lua_State *L, const char *var);
2271dced572SBram Moolenaar void (*dll_lua_setglobal) (lua_State *L, const char *var);
2281f860d85SBram Moolenaar #endif
2291f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
2301f860d85SBram Moolenaar void (*dll_lua_replace) (lua_State *L, int idx);
2311f860d85SBram Moolenaar void (*dll_lua_remove) (lua_State *L, int idx);
2321f860d85SBram Moolenaar #endif
2331f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
2341f860d85SBram Moolenaar void  (*dll_lua_rotate) (lua_State *L, int idx, int n);
2359514b1f9SBram Moolenaar void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx);
2361dced572SBram Moolenaar #endif
237bd2f3c3eSBram Moolenaar const char *(*dll_lua_typename) (lua_State *L, int tp);
2380ba04296SBram Moolenaar void       (*dll_lua_close) (lua_State *L);
2390ba04296SBram Moolenaar int (*dll_lua_gettop) (lua_State *L);
2400ba04296SBram Moolenaar void (*dll_lua_settop) (lua_State *L, int idx);
2410ba04296SBram Moolenaar void (*dll_lua_pushvalue) (lua_State *L, int idx);
2420ba04296SBram Moolenaar int (*dll_lua_isnumber) (lua_State *L, int idx);
2430ba04296SBram Moolenaar int (*dll_lua_isstring) (lua_State *L, int idx);
2440ba04296SBram Moolenaar int (*dll_lua_type) (lua_State *L, int idx);
2450ba04296SBram Moolenaar int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
2460ba04296SBram Moolenaar int (*dll_lua_toboolean) (lua_State *L, int idx);
2470ba04296SBram Moolenaar const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
2480ba04296SBram Moolenaar void *(*dll_lua_touserdata) (lua_State *L, int idx);
2490ba04296SBram Moolenaar void (*dll_lua_pushnil) (lua_State *L);
2500ba04296SBram Moolenaar void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
2510ba04296SBram Moolenaar void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
2520ba04296SBram Moolenaar void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
2530ba04296SBram Moolenaar void (*dll_lua_pushstring) (lua_State *L, const char *s);
2540ba04296SBram Moolenaar const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
2550ba04296SBram Moolenaar void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
2560ba04296SBram Moolenaar void (*dll_lua_pushboolean) (lua_State *L, int b);
2570ba04296SBram Moolenaar void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
2580ba04296SBram Moolenaar void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
25917413671SBram Moolenaar #if LUA_VERSION_NUM <= 502
2600ba04296SBram Moolenaar void (*dll_lua_rawget) (lua_State *L, int idx);
2611dced572SBram Moolenaar void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
26217413671SBram Moolenaar #else
26317413671SBram Moolenaar int (*dll_lua_rawget) (lua_State *L, int idx);
26417413671SBram Moolenaar int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
26517413671SBram Moolenaar #endif
2660ba04296SBram Moolenaar void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
267830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
268830e3583SBram Moolenaar void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
269830e3583SBram Moolenaar #else
2700ba04296SBram Moolenaar void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
271830e3583SBram Moolenaar #endif
2720ba04296SBram Moolenaar int (*dll_lua_getmetatable) (lua_State *L, int objindex);
2730ba04296SBram Moolenaar void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
2740ba04296SBram Moolenaar void (*dll_lua_rawset) (lua_State *L, int idx);
27517413671SBram Moolenaar #if LUA_VERSION_NUM <= 502
2760ba04296SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
27717413671SBram Moolenaar #else
27817413671SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n);
27917413671SBram Moolenaar #endif
2800ba04296SBram Moolenaar int (*dll_lua_setmetatable) (lua_State *L, int objindex);
281bd2f3c3eSBram Moolenaar int (*dll_lua_next) (lua_State *L, int idx);
2820ba04296SBram Moolenaar /* libs */
2830ba04296SBram Moolenaar int (*dll_luaopen_base) (lua_State *L);
2840ba04296SBram Moolenaar int (*dll_luaopen_table) (lua_State *L);
2850ba04296SBram Moolenaar int (*dll_luaopen_string) (lua_State *L);
2860ba04296SBram Moolenaar int (*dll_luaopen_math) (lua_State *L);
28716c98f9cSBram Moolenaar int (*dll_luaopen_io) (lua_State *L);
2880ba04296SBram Moolenaar int (*dll_luaopen_os) (lua_State *L);
2890ba04296SBram Moolenaar int (*dll_luaopen_package) (lua_State *L);
2900ba04296SBram Moolenaar int (*dll_luaopen_debug) (lua_State *L);
29116c98f9cSBram Moolenaar void (*dll_luaL_openlibs) (lua_State *L);
2920ba04296SBram Moolenaar 
2930ba04296SBram Moolenaar typedef void **luaV_function;
2940ba04296SBram Moolenaar typedef struct {
2950ba04296SBram Moolenaar     const char *name;
2960ba04296SBram Moolenaar     luaV_function func;
2970ba04296SBram Moolenaar } luaV_Reg;
2980ba04296SBram Moolenaar 
2990ba04296SBram Moolenaar static const luaV_Reg luaV_dll[] = {
3000ba04296SBram Moolenaar     /* lauxlib */
3011dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
3020ba04296SBram Moolenaar     {"luaL_register", (luaV_function) &dll_luaL_register},
3031dced572SBram Moolenaar     {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
3041dced572SBram Moolenaar     {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
3050ba04296SBram Moolenaar     {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
3061dced572SBram Moolenaar     {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
3071dced572SBram Moolenaar     {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
3081dced572SBram Moolenaar #else
3091dced572SBram Moolenaar     {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
3101dced572SBram Moolenaar     {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
3111dced572SBram Moolenaar     {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
3121dced572SBram Moolenaar     {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
3131dced572SBram Moolenaar     {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
3141dced572SBram Moolenaar #endif
315bd2f3c3eSBram Moolenaar     {"luaL_checkany", (luaV_function) &dll_luaL_checkany},
3160ba04296SBram Moolenaar     {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
3170ba04296SBram Moolenaar     {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
3180ba04296SBram Moolenaar     {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
3190ba04296SBram Moolenaar     {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
3200ba04296SBram Moolenaar     {"luaL_error", (luaV_function) &dll_luaL_error},
3210ba04296SBram Moolenaar     {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
3220ba04296SBram Moolenaar     {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
3230ba04296SBram Moolenaar     {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
3240ba04296SBram Moolenaar     {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
3250ba04296SBram Moolenaar     /* lua */
3261dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
3271dced572SBram Moolenaar     {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
3281dced572SBram Moolenaar     {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
3291dced572SBram Moolenaar     {"lua_call", (luaV_function) &dll_lua_call},
3301dced572SBram Moolenaar     {"lua_pcall", (luaV_function) &dll_lua_pcall},
3311dced572SBram Moolenaar #else
3321dced572SBram Moolenaar     {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
3331dced572SBram Moolenaar     {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
3341dced572SBram Moolenaar     {"lua_callk", (luaV_function) &dll_lua_callk},
3351dced572SBram Moolenaar     {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
3361dced572SBram Moolenaar     {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
3371dced572SBram Moolenaar     {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
3381dced572SBram Moolenaar #endif
3391f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
3401f860d85SBram Moolenaar     {"lua_replace", (luaV_function) &dll_lua_replace},
3411f860d85SBram Moolenaar     {"lua_remove", (luaV_function) &dll_lua_remove},
3421f860d85SBram Moolenaar #endif
3431f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
3441f860d85SBram Moolenaar     {"lua_rotate", (luaV_function) &dll_lua_rotate},
3451f860d85SBram Moolenaar     {"lua_copy", (luaV_function) &dll_lua_copy},
3461f860d85SBram Moolenaar #endif
347bd2f3c3eSBram Moolenaar     {"lua_typename", (luaV_function) &dll_lua_typename},
3480ba04296SBram Moolenaar     {"lua_close", (luaV_function) &dll_lua_close},
3490ba04296SBram Moolenaar     {"lua_gettop", (luaV_function) &dll_lua_gettop},
3500ba04296SBram Moolenaar     {"lua_settop", (luaV_function) &dll_lua_settop},
3510ba04296SBram Moolenaar     {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
3520ba04296SBram Moolenaar     {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
3530ba04296SBram Moolenaar     {"lua_isstring", (luaV_function) &dll_lua_isstring},
3540ba04296SBram Moolenaar     {"lua_type", (luaV_function) &dll_lua_type},
3550ba04296SBram Moolenaar     {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
3560ba04296SBram Moolenaar     {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
3570ba04296SBram Moolenaar     {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
3580ba04296SBram Moolenaar     {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
3590ba04296SBram Moolenaar     {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
3600ba04296SBram Moolenaar     {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
3610ba04296SBram Moolenaar     {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
3620ba04296SBram Moolenaar     {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
3630ba04296SBram Moolenaar     {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
3640ba04296SBram Moolenaar     {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
3650ba04296SBram Moolenaar     {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
3660ba04296SBram Moolenaar     {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
3670ba04296SBram Moolenaar     {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
3680ba04296SBram Moolenaar     {"lua_getfield", (luaV_function) &dll_lua_getfield},
3690ba04296SBram Moolenaar     {"lua_rawget", (luaV_function) &dll_lua_rawget},
3701dced572SBram Moolenaar     {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
3710ba04296SBram Moolenaar     {"lua_createtable", (luaV_function) &dll_lua_createtable},
372830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
373830e3583SBram Moolenaar     {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv},
374830e3583SBram Moolenaar #else
3750ba04296SBram Moolenaar     {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
376830e3583SBram Moolenaar #endif
3770ba04296SBram Moolenaar     {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
3780ba04296SBram Moolenaar     {"lua_setfield", (luaV_function) &dll_lua_setfield},
3790ba04296SBram Moolenaar     {"lua_rawset", (luaV_function) &dll_lua_rawset},
3800ba04296SBram Moolenaar     {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
3810ba04296SBram Moolenaar     {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
382bd2f3c3eSBram Moolenaar     {"lua_next", (luaV_function) &dll_lua_next},
3830ba04296SBram Moolenaar     /* libs */
3840ba04296SBram Moolenaar     {"luaopen_base", (luaV_function) &dll_luaopen_base},
3850ba04296SBram Moolenaar     {"luaopen_table", (luaV_function) &dll_luaopen_table},
3860ba04296SBram Moolenaar     {"luaopen_string", (luaV_function) &dll_luaopen_string},
3870ba04296SBram Moolenaar     {"luaopen_math", (luaV_function) &dll_luaopen_math},
38816c98f9cSBram Moolenaar     {"luaopen_io", (luaV_function) &dll_luaopen_io},
3890ba04296SBram Moolenaar     {"luaopen_os", (luaV_function) &dll_luaopen_os},
3900ba04296SBram Moolenaar     {"luaopen_package", (luaV_function) &dll_luaopen_package},
3910ba04296SBram Moolenaar     {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
39216c98f9cSBram Moolenaar     {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
3930ba04296SBram Moolenaar     {NULL, NULL}
3940ba04296SBram Moolenaar };
3950ba04296SBram Moolenaar 
3962334b6d5SBram Moolenaar static HANDLE hinstLua = NULL;
3970ba04296SBram Moolenaar 
39855d5c034SBram Moolenaar     static void
39955d5c034SBram Moolenaar end_dynamic_lua(void)
40055d5c034SBram Moolenaar {
40155d5c034SBram Moolenaar     if (hinstLua)
40255d5c034SBram Moolenaar     {
4032334b6d5SBram Moolenaar 	close_dll(hinstLua);
4040ba04296SBram Moolenaar 	hinstLua = 0;
4050ba04296SBram Moolenaar     }
4060ba04296SBram Moolenaar }
4070ba04296SBram Moolenaar 
40855d5c034SBram Moolenaar     static int
40955d5c034SBram Moolenaar lua_link_init(char *libname, int verbose)
41055d5c034SBram Moolenaar {
4110ba04296SBram Moolenaar     const luaV_Reg *reg;
4120ba04296SBram Moolenaar     if (hinstLua) return OK;
4132334b6d5SBram Moolenaar     hinstLua = load_dll(libname);
41455d5c034SBram Moolenaar     if (!hinstLua)
41555d5c034SBram Moolenaar     {
41655d5c034SBram Moolenaar 	if (verbose)
417f9e3e09fSBram Moolenaar 	    semsg(_(e_loadlib), libname);
4180ba04296SBram Moolenaar 	return FAIL;
4190ba04296SBram Moolenaar     }
42055d5c034SBram Moolenaar     for (reg = luaV_dll; reg->func; reg++)
42155d5c034SBram Moolenaar     {
4222334b6d5SBram Moolenaar 	if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
4232334b6d5SBram Moolenaar 	{
4242334b6d5SBram Moolenaar 	    close_dll(hinstLua);
4250ba04296SBram Moolenaar 	    hinstLua = 0;
42655d5c034SBram Moolenaar 	    if (verbose)
427f9e3e09fSBram Moolenaar 		semsg(_(e_loadfunc), reg->name);
4280ba04296SBram Moolenaar 	    return FAIL;
4290ba04296SBram Moolenaar 	}
4300ba04296SBram Moolenaar     }
4310ba04296SBram Moolenaar     return OK;
4320ba04296SBram Moolenaar }
433d90b6c02SBram Moolenaar #endif /* DYNAMIC_LUA */
4340ba04296SBram Moolenaar 
435d90b6c02SBram Moolenaar #if defined(DYNAMIC_LUA) || defined(PROTO)
43655d5c034SBram Moolenaar     int
43755d5c034SBram Moolenaar lua_enabled(int verbose)
43855d5c034SBram Moolenaar {
43925e4fcdeSBram Moolenaar     return lua_link_init((char *)p_luadll, verbose) == OK;
4400ba04296SBram Moolenaar }
441d90b6c02SBram Moolenaar #endif
4420ba04296SBram Moolenaar 
4431dced572SBram Moolenaar #if LUA_VERSION_NUM > 501
4441dced572SBram Moolenaar     static int
4451dced572SBram Moolenaar luaL_typeerror(lua_State *L, int narg, const char *tname)
4461dced572SBram Moolenaar {
4471dced572SBram Moolenaar     const char *msg = lua_pushfstring(L, "%s expected, got %s",
4481dced572SBram Moolenaar 	    tname, luaL_typename(L, narg));
4491dced572SBram Moolenaar     return luaL_argerror(L, narg, msg);
4501dced572SBram Moolenaar }
4511dced572SBram Moolenaar #endif
4521dced572SBram Moolenaar 
4530ba04296SBram Moolenaar 
4540ba04296SBram Moolenaar /* =======   Internal   ======= */
4550ba04296SBram Moolenaar 
45655d5c034SBram Moolenaar     static void
45755d5c034SBram Moolenaar luaV_newmetatable(lua_State *L, const char *tname)
45855d5c034SBram Moolenaar {
4590ba04296SBram Moolenaar     lua_newtable(L);
4600ba04296SBram Moolenaar     lua_pushlightuserdata(L, (void *) tname);
4610ba04296SBram Moolenaar     lua_pushvalue(L, -2);
4620ba04296SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
4630ba04296SBram Moolenaar }
4640ba04296SBram Moolenaar 
46555d5c034SBram Moolenaar     static void *
46655d5c034SBram Moolenaar luaV_toudata(lua_State *L, int ud, const char *tname)
46755d5c034SBram Moolenaar {
4680ba04296SBram Moolenaar     void *p = lua_touserdata(L, ud);
46955d5c034SBram Moolenaar 
47055d5c034SBram Moolenaar     if (p != NULL) /* value is userdata? */
47155d5c034SBram Moolenaar     {
47255d5c034SBram Moolenaar 	if (lua_getmetatable(L, ud)) /* does it have a metatable? */
47355d5c034SBram Moolenaar 	{
4740ba04296SBram Moolenaar 	    luaV_getfield(L, tname); /* get metatable */
47555d5c034SBram Moolenaar 	    if (lua_rawequal(L, -1, -2)) /* MTs match? */
47655d5c034SBram Moolenaar 	    {
4770ba04296SBram Moolenaar 		lua_pop(L, 2); /* MTs */
4780ba04296SBram Moolenaar 		return p;
4790ba04296SBram Moolenaar 	    }
4800ba04296SBram Moolenaar 	}
4810ba04296SBram Moolenaar     }
4820ba04296SBram Moolenaar     return NULL;
4830ba04296SBram Moolenaar }
4840ba04296SBram Moolenaar 
48555d5c034SBram Moolenaar     static void *
4861dced572SBram Moolenaar luaV_checkcache(lua_State *L, void *p)
4871dced572SBram Moolenaar {
4881dced572SBram Moolenaar     luaV_getudata(L, p);
4891dced572SBram Moolenaar     if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
4901dced572SBram Moolenaar     lua_pop(L, 1);
4911dced572SBram Moolenaar     return p;
4921dced572SBram Moolenaar }
4931dced572SBram Moolenaar 
4941dced572SBram Moolenaar #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
4951dced572SBram Moolenaar 
4961dced572SBram Moolenaar #define luaV_checkvalid(L,luatyp,ud) \
4971dced572SBram Moolenaar     luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
4981dced572SBram Moolenaar 
4991dced572SBram Moolenaar     static void *
50055d5c034SBram Moolenaar luaV_checkudata(lua_State *L, int ud, const char *tname)
50155d5c034SBram Moolenaar {
5020ba04296SBram Moolenaar     void *p = luaV_toudata(L, ud, tname);
5031dced572SBram Moolenaar     if (p == NULL) luaL_typeerror(L, ud, tname);
5040ba04296SBram Moolenaar     return p;
5050ba04296SBram Moolenaar }
5060ba04296SBram Moolenaar 
50755d5c034SBram Moolenaar     static void
50855d5c034SBram Moolenaar luaV_pushtypval(lua_State *L, typval_T *tv)
50955d5c034SBram Moolenaar {
5101dced572SBram Moolenaar     if (tv == NULL)
5111dced572SBram Moolenaar     {
5121dced572SBram Moolenaar 	lua_pushnil(L);
5131dced572SBram Moolenaar 	return;
5141dced572SBram Moolenaar     }
51555d5c034SBram Moolenaar     switch (tv->v_type)
51655d5c034SBram Moolenaar     {
5170ba04296SBram Moolenaar 	case VAR_STRING:
518d04da7cbSBram Moolenaar 	    lua_pushstring(L, tv->vval.v_string == NULL
519d04da7cbSBram Moolenaar 					    ? "" : (char *)tv->vval.v_string);
5200ba04296SBram Moolenaar 	    break;
5210ba04296SBram Moolenaar 	case VAR_NUMBER:
5220ba04296SBram Moolenaar 	    lua_pushinteger(L, (int) tv->vval.v_number);
5230ba04296SBram Moolenaar 	    break;
5240ba04296SBram Moolenaar #ifdef FEAT_FLOAT
5250ba04296SBram Moolenaar 	case VAR_FLOAT:
5260ba04296SBram Moolenaar 	    lua_pushnumber(L, (lua_Number) tv->vval.v_float);
5270ba04296SBram Moolenaar 	    break;
5280ba04296SBram Moolenaar #endif
5291dced572SBram Moolenaar 	case VAR_LIST:
5301dced572SBram Moolenaar 	    luaV_pushlist(L, tv->vval.v_list);
5310ba04296SBram Moolenaar 	    break;
5321dced572SBram Moolenaar 	case VAR_DICT:
5331dced572SBram Moolenaar 	    luaV_pushdict(L, tv->vval.v_dict);
5341dced572SBram Moolenaar 	    break;
535520e1e41SBram Moolenaar 	case VAR_SPECIAL:
536520e1e41SBram Moolenaar 	    if (tv->vval.v_number <= VVAL_TRUE)
537520e1e41SBram Moolenaar 		lua_pushinteger(L, (int) tv->vval.v_number);
538520e1e41SBram Moolenaar 	    else
539520e1e41SBram Moolenaar 		lua_pushnil(L);
540520e1e41SBram Moolenaar 	    break;
541ca06da92SBram Moolenaar 	case VAR_FUNC:
542*4eefe47eSBram Moolenaar 	    luaV_pushfuncref(L, tv->vval.v_string);
543ca06da92SBram Moolenaar 	    break;
5441dced572SBram Moolenaar 	default:
5451dced572SBram Moolenaar 	    lua_pushnil(L);
5460ba04296SBram Moolenaar     }
5471dced572SBram Moolenaar }
54855d5c034SBram Moolenaar 
549ca06da92SBram Moolenaar /*
550ca06da92SBram Moolenaar  * Converts lua value at 'pos' to typval 'tv'.
551ca06da92SBram Moolenaar  * Returns OK or FAIL.
552ca06da92SBram Moolenaar  */
553ca06da92SBram Moolenaar     static int
5541dced572SBram Moolenaar luaV_totypval(lua_State *L, int pos, typval_T *tv)
55555d5c034SBram Moolenaar {
556ca06da92SBram Moolenaar     int status = OK;
557ca06da92SBram Moolenaar 
558ca06da92SBram Moolenaar     switch (lua_type(L, pos))
559ca06da92SBram Moolenaar     {
5601dced572SBram Moolenaar 	case LUA_TBOOLEAN:
561520e1e41SBram Moolenaar 	    tv->v_type = VAR_SPECIAL;
5621dced572SBram Moolenaar 	    tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
5631dced572SBram Moolenaar 	    break;
5649067cd6cSBram Moolenaar 	case LUA_TNIL:
5659067cd6cSBram Moolenaar 	    tv->v_type = VAR_SPECIAL;
5669067cd6cSBram Moolenaar 	    tv->vval.v_number = VVAL_NULL;
5679067cd6cSBram Moolenaar 	    break;
5681dced572SBram Moolenaar 	case LUA_TSTRING:
5691dced572SBram Moolenaar 	    tv->v_type = VAR_STRING;
5701dced572SBram Moolenaar 	    tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
5711dced572SBram Moolenaar 	    break;
5721dced572SBram Moolenaar 	case LUA_TNUMBER:
5731dced572SBram Moolenaar #ifdef FEAT_FLOAT
5741dced572SBram Moolenaar 	    tv->v_type = VAR_FLOAT;
5751dced572SBram Moolenaar 	    tv->vval.v_float = (float_T) lua_tonumber(L, pos);
5761dced572SBram Moolenaar #else
5771dced572SBram Moolenaar 	    tv->v_type = VAR_NUMBER;
5781dced572SBram Moolenaar 	    tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
5791dced572SBram Moolenaar #endif
5801dced572SBram Moolenaar 	    break;
581ca06da92SBram Moolenaar 	case LUA_TUSERDATA:
582ca06da92SBram Moolenaar 	{
5831dced572SBram Moolenaar 	    void *p = lua_touserdata(L, pos);
584ca06da92SBram Moolenaar 
5851dced572SBram Moolenaar 	    if (lua_getmetatable(L, pos)) /* has metatable? */
5862334b6d5SBram Moolenaar 	    {
5871dced572SBram Moolenaar 		/* check list */
5881dced572SBram Moolenaar 		luaV_getfield(L, LUAVIM_LIST);
5891dced572SBram Moolenaar 		if (lua_rawequal(L, -1, -2))
59055d5c034SBram Moolenaar 		{
5911dced572SBram Moolenaar 		    tv->v_type = VAR_LIST;
5921dced572SBram Moolenaar 		    tv->vval.v_list = *((luaV_List *) p);
5931dced572SBram Moolenaar 		    ++tv->vval.v_list->lv_refcount;
5941dced572SBram Moolenaar 		    lua_pop(L, 2); /* MTs */
595ca06da92SBram Moolenaar 		    break;
5961dced572SBram Moolenaar 		}
5971dced572SBram Moolenaar 		/* check dict */
5981dced572SBram Moolenaar 		luaV_getfield(L, LUAVIM_DICT);
5991dced572SBram Moolenaar 		if (lua_rawequal(L, -1, -3))
60055d5c034SBram Moolenaar 		{
6011dced572SBram Moolenaar 		    tv->v_type = VAR_DICT;
6021dced572SBram Moolenaar 		    tv->vval.v_dict = *((luaV_Dict *) p);
6031dced572SBram Moolenaar 		    ++tv->vval.v_dict->dv_refcount;
6041dced572SBram Moolenaar 		    lua_pop(L, 3); /* MTs */
6050ba04296SBram Moolenaar 		    break;
6060ba04296SBram Moolenaar 		}
607ca06da92SBram Moolenaar 		/* check funcref */
608ca06da92SBram Moolenaar 		luaV_getfield(L, LUAVIM_FUNCREF);
609ca06da92SBram Moolenaar 		if (lua_rawequal(L, -1, -4))
610ca06da92SBram Moolenaar 		{
611ca06da92SBram Moolenaar 		    luaV_Funcref *f = (luaV_Funcref *) p;
612*4eefe47eSBram Moolenaar 		    func_ref(f->name);
613*4eefe47eSBram Moolenaar 		    tv->v_type = VAR_FUNC;
614*4eefe47eSBram Moolenaar 		    tv->vval.v_string = vim_strsave(f->name);
615ca06da92SBram Moolenaar 		    lua_pop(L, 4); /* MTs */
616ca06da92SBram Moolenaar 		    break;
617ca06da92SBram Moolenaar 		}
618ca06da92SBram Moolenaar 		lua_pop(L, 4); /* MTs */
619ca06da92SBram Moolenaar 	    }
620ca06da92SBram Moolenaar 	}
621ca06da92SBram Moolenaar 	/* FALLTHROUGH */
6220ba04296SBram Moolenaar 	default:
6231dced572SBram Moolenaar 	    tv->v_type = VAR_NUMBER;
6241dced572SBram Moolenaar 	    tv->vval.v_number = 0;
625ca06da92SBram Moolenaar 	    status = FAIL;
6260ba04296SBram Moolenaar     }
627ca06da92SBram Moolenaar     return status;
6280ba04296SBram Moolenaar }
6290ba04296SBram Moolenaar 
6300ba04296SBram Moolenaar /* similar to luaL_addlstring, but replaces \0 with \n if toline and
6310ba04296SBram Moolenaar  * \n with \0 otherwise */
63255d5c034SBram Moolenaar     static void
63355d5c034SBram Moolenaar luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
63455d5c034SBram Moolenaar {
63555d5c034SBram Moolenaar     while (l--)
63655d5c034SBram Moolenaar     {
63755d5c034SBram Moolenaar 	if (*s == '\0' && toline)
63855d5c034SBram Moolenaar 	    luaL_addchar(b, '\n');
63955d5c034SBram Moolenaar 	else if (*s == '\n' && !toline)
64055d5c034SBram Moolenaar 	    luaL_addchar(b, '\0');
64155d5c034SBram Moolenaar 	else
64255d5c034SBram Moolenaar 	    luaL_addchar(b, *s);
6430ba04296SBram Moolenaar 	s++;
6440ba04296SBram Moolenaar     }
6450ba04296SBram Moolenaar }
6460ba04296SBram Moolenaar 
64755d5c034SBram Moolenaar     static void
64855d5c034SBram Moolenaar luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
64955d5c034SBram Moolenaar {
6500ba04296SBram Moolenaar     const char *s = (const char *) ml_get_buf(buf, n, FALSE);
6510ba04296SBram Moolenaar     luaL_Buffer b;
6520ba04296SBram Moolenaar     luaL_buffinit(L, &b);
6530ba04296SBram Moolenaar     luaV_addlstring(&b, s, strlen(s), 0);
6540ba04296SBram Moolenaar     luaL_pushresult(&b);
6550ba04296SBram Moolenaar }
6560ba04296SBram Moolenaar 
65755d5c034SBram Moolenaar     static char_u *
65855d5c034SBram Moolenaar luaV_toline(lua_State *L, int pos)
65955d5c034SBram Moolenaar {
6600ba04296SBram Moolenaar     size_t l;
6610ba04296SBram Moolenaar     const char *s = lua_tolstring(L, pos, &l);
66255d5c034SBram Moolenaar 
6630ba04296SBram Moolenaar     luaL_Buffer b;
6640ba04296SBram Moolenaar     luaL_buffinit(L, &b);
6650ba04296SBram Moolenaar     luaV_addlstring(&b, s, l, 1);
6660ba04296SBram Moolenaar     luaL_pushresult(&b);
6670ba04296SBram Moolenaar     return (char_u *) lua_tostring(L, -1);
6680ba04296SBram Moolenaar }
6690ba04296SBram Moolenaar 
6700ba04296SBram Moolenaar /* pops a string s from the top of the stack and calls mf(t) for pieces t of
6710ba04296SBram Moolenaar  * s separated by newlines */
67255d5c034SBram Moolenaar     static void
67355d5c034SBram Moolenaar luaV_msgfunc(lua_State *L, msgfunc_T mf)
67455d5c034SBram Moolenaar {
6750ba04296SBram Moolenaar     luaL_Buffer b;
6760ba04296SBram Moolenaar     size_t l;
6770ba04296SBram Moolenaar     const char *p, *s = lua_tolstring(L, -1, &l);
6780ba04296SBram Moolenaar     luaL_buffinit(L, &b);
6790ba04296SBram Moolenaar     luaV_addlstring(&b, s, l, 0);
6800ba04296SBram Moolenaar     luaL_pushresult(&b);
6810ba04296SBram Moolenaar     /* break string */
6820ba04296SBram Moolenaar     p = s = lua_tolstring(L, -1, &l);
68355d5c034SBram Moolenaar     while (l--)
68455d5c034SBram Moolenaar     {
68555d5c034SBram Moolenaar 	if (*p++ == '\0') /* break? */
68655d5c034SBram Moolenaar 	{
6870ba04296SBram Moolenaar 	    mf((char_u *) s);
6880ba04296SBram Moolenaar 	    s = p;
6890ba04296SBram Moolenaar 	}
6900ba04296SBram Moolenaar     }
6910ba04296SBram Moolenaar     mf((char_u *) s);
6920ba04296SBram Moolenaar     lua_pop(L, 2); /* original and modified strings */
6930ba04296SBram Moolenaar }
6940ba04296SBram Moolenaar 
6951dced572SBram Moolenaar #define luaV_newtype(typ,tname,luatyp,luatname) \
6961dced572SBram Moolenaar 	static luatyp * \
6971dced572SBram Moolenaar     luaV_new##tname(lua_State *L, typ *obj) \
6981dced572SBram Moolenaar     { \
6991dced572SBram Moolenaar 	luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
7001dced572SBram Moolenaar 	*o = obj; \
7011dced572SBram Moolenaar 	luaV_setudata(L, obj); /* cache[obj] = udata */ \
7021dced572SBram Moolenaar 	luaV_getfield(L, luatname); \
7031dced572SBram Moolenaar 	lua_setmetatable(L, -2); \
7041dced572SBram Moolenaar 	return o; \
7050ba04296SBram Moolenaar     }
7060ba04296SBram Moolenaar 
7071dced572SBram Moolenaar #define luaV_pushtype(typ,tname,luatyp) \
7081dced572SBram Moolenaar 	static luatyp * \
7091dced572SBram Moolenaar     luaV_push##tname(lua_State *L, typ *obj) \
7101dced572SBram Moolenaar     { \
7111dced572SBram Moolenaar 	luatyp *o = NULL; \
7121dced572SBram Moolenaar 	if (obj == NULL) \
7131dced572SBram Moolenaar 	    lua_pushnil(L); \
7141dced572SBram Moolenaar 	else { \
7151dced572SBram Moolenaar 	    luaV_getudata(L, obj); \
7161dced572SBram Moolenaar 	    if (lua_isnil(L, -1)) /* not interned? */ \
7171dced572SBram Moolenaar 	    { \
7181dced572SBram Moolenaar 		lua_pop(L, 1); \
7191dced572SBram Moolenaar 		o = luaV_new##tname(L, obj); \
7201dced572SBram Moolenaar 	    } \
7211dced572SBram Moolenaar 	    else \
7221dced572SBram Moolenaar 		o = (luatyp *) lua_touserdata(L, -1); \
7231dced572SBram Moolenaar 	} \
7241dced572SBram Moolenaar 	return o; \
7250ba04296SBram Moolenaar     }
7261dced572SBram Moolenaar 
7271dced572SBram Moolenaar #define luaV_type_tostring(tname,luatname) \
7281dced572SBram Moolenaar 	static int \
7291dced572SBram Moolenaar     luaV_##tname##_tostring(lua_State *L) \
7301dced572SBram Moolenaar     { \
7311dced572SBram Moolenaar 	lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
7321dced572SBram Moolenaar 	return 1; \
7331dced572SBram Moolenaar     }
7341dced572SBram Moolenaar 
7351dced572SBram Moolenaar /* =======   List type   ======= */
7361dced572SBram Moolenaar 
7371dced572SBram Moolenaar     static luaV_List *
7381dced572SBram Moolenaar luaV_newlist(lua_State *L, list_T *lis)
7391dced572SBram Moolenaar {
7401dced572SBram Moolenaar     luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
7411dced572SBram Moolenaar     *l = lis;
7421dced572SBram Moolenaar     lis->lv_refcount++; /* reference in Lua */
7431dced572SBram Moolenaar     luaV_setudata(L, lis); /* cache[lis] = udata */
7441dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LIST);
7451dced572SBram Moolenaar     lua_setmetatable(L, -2);
7461dced572SBram Moolenaar     return l;
7471dced572SBram Moolenaar }
7481dced572SBram Moolenaar 
7491dced572SBram Moolenaar luaV_pushtype(list_T, list, luaV_List)
7501dced572SBram Moolenaar luaV_type_tostring(list, LUAVIM_LIST)
7511dced572SBram Moolenaar 
7521dced572SBram Moolenaar     static int
7531dced572SBram Moolenaar luaV_list_len(lua_State *L)
7541dced572SBram Moolenaar {
7551dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
7561dced572SBram Moolenaar     lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len);
7570ba04296SBram Moolenaar     return 1;
7580ba04296SBram Moolenaar }
7590ba04296SBram Moolenaar 
76055d5c034SBram Moolenaar     static int
7611dced572SBram Moolenaar luaV_list_iter(lua_State *L)
7621dced572SBram Moolenaar {
7631dced572SBram Moolenaar     listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
7641dced572SBram Moolenaar     if (li == NULL) return 0;
7651dced572SBram Moolenaar     luaV_pushtypval(L, &li->li_tv);
7661dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) li->li_next);
7671dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(2));
7681dced572SBram Moolenaar     return 1;
7691dced572SBram Moolenaar }
7701dced572SBram Moolenaar 
7711dced572SBram Moolenaar     static int
7721dced572SBram Moolenaar luaV_list_call(lua_State *L)
7731dced572SBram Moolenaar {
7741dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
7751dced572SBram Moolenaar     lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
7761dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) l->lv_first);
7771dced572SBram Moolenaar     lua_pushcclosure(L, luaV_list_iter, 2);
7781dced572SBram Moolenaar     return 1;
7791dced572SBram Moolenaar }
7801dced572SBram Moolenaar 
7811dced572SBram Moolenaar     static int
7821dced572SBram Moolenaar luaV_list_index(lua_State *L)
7831dced572SBram Moolenaar {
7841dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
7851dced572SBram Moolenaar     if (lua_isnumber(L, 2)) /* list item? */
7861dced572SBram Moolenaar     {
7871dced572SBram Moolenaar 	listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2));
7881dced572SBram Moolenaar 	if (li == NULL)
7891dced572SBram Moolenaar 	    lua_pushnil(L);
7901dced572SBram Moolenaar 	else
7911dced572SBram Moolenaar 	    luaV_pushtypval(L, &li->li_tv);
7921dced572SBram Moolenaar     }
7931dced572SBram Moolenaar     else if (lua_isstring(L, 2)) /* method? */
7941dced572SBram Moolenaar     {
7951dced572SBram Moolenaar 	const char *s = lua_tostring(L, 2);
7961dced572SBram Moolenaar 	if (strncmp(s, "add", 3) == 0
797b376647bSBram Moolenaar 		|| strncmp(s, "insert", 6) == 0)
7981dced572SBram Moolenaar 	{
7991dced572SBram Moolenaar 	    lua_getmetatable(L, 1);
8001dced572SBram Moolenaar 	    lua_getfield(L, -1, s);
8011dced572SBram Moolenaar 	}
8021dced572SBram Moolenaar 	else
8031dced572SBram Moolenaar 	    lua_pushnil(L);
8041dced572SBram Moolenaar     }
8051dced572SBram Moolenaar     else
8061dced572SBram Moolenaar 	lua_pushnil(L);
8071dced572SBram Moolenaar     return 1;
8081dced572SBram Moolenaar }
8091dced572SBram Moolenaar 
8101dced572SBram Moolenaar     static int
8111dced572SBram Moolenaar luaV_list_newindex(lua_State *L)
8121dced572SBram Moolenaar {
8131dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
8141dced572SBram Moolenaar     long n = (long) luaL_checkinteger(L, 2);
8151dced572SBram Moolenaar     listitem_T *li;
8161dced572SBram Moolenaar     if (l->lv_lock)
8171dced572SBram Moolenaar 	luaL_error(L, "list is locked");
8181dced572SBram Moolenaar     li = list_find(l, n);
8191dced572SBram Moolenaar     if (li == NULL) return 0;
8201dced572SBram Moolenaar     if (lua_isnil(L, 3)) /* remove? */
8211dced572SBram Moolenaar     {
8223ec7f4e4SBram Moolenaar 	vimlist_remove(l, li, li);
8231dced572SBram Moolenaar 	clear_tv(&li->li_tv);
8241dced572SBram Moolenaar 	vim_free(li);
8251dced572SBram Moolenaar     }
8261dced572SBram Moolenaar     else
8271dced572SBram Moolenaar     {
8281dced572SBram Moolenaar 	typval_T v;
829ca06da92SBram Moolenaar 	luaV_checktypval(L, 3, &v, "setting list item");
8301dced572SBram Moolenaar 	clear_tv(&li->li_tv);
8311dced572SBram Moolenaar 	copy_tv(&v, &li->li_tv);
832b376647bSBram Moolenaar 	clear_tv(&v);
8331dced572SBram Moolenaar     }
8341dced572SBram Moolenaar     return 0;
8351dced572SBram Moolenaar }
8361dced572SBram Moolenaar 
8371dced572SBram Moolenaar     static int
8381dced572SBram Moolenaar luaV_list_add(lua_State *L)
8391dced572SBram Moolenaar {
8401dced572SBram Moolenaar     luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
8411dced572SBram Moolenaar     list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
842b376647bSBram Moolenaar     typval_T v;
8431dced572SBram Moolenaar     if (l->lv_lock)
8441dced572SBram Moolenaar 	luaL_error(L, "list is locked");
8451dced572SBram Moolenaar     lua_settop(L, 2);
846ca06da92SBram Moolenaar     luaV_checktypval(L, 2, &v, "adding list item");
847b376647bSBram Moolenaar     if (list_append_tv(l, &v) == FAIL)
848ca06da92SBram Moolenaar 	luaL_error(L, "failed to add item to list");
849b376647bSBram Moolenaar     clear_tv(&v);
8501dced572SBram Moolenaar     lua_settop(L, 1);
8511dced572SBram Moolenaar     return 1;
8521dced572SBram Moolenaar }
8531dced572SBram Moolenaar 
8541dced572SBram Moolenaar     static int
8551dced572SBram Moolenaar luaV_list_insert(lua_State *L)
8561dced572SBram Moolenaar {
8571dced572SBram Moolenaar     luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
8581dced572SBram Moolenaar     list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
85946538ee4SBram Moolenaar     long pos = (long) luaL_optinteger(L, 3, 0);
8601dced572SBram Moolenaar     listitem_T *li = NULL;
8611dced572SBram Moolenaar     typval_T v;
8621dced572SBram Moolenaar     if (l->lv_lock)
8631dced572SBram Moolenaar 	luaL_error(L, "list is locked");
8641dced572SBram Moolenaar     if (pos < l->lv_len)
8651dced572SBram Moolenaar     {
8661dced572SBram Moolenaar 	li = list_find(l, pos);
8671dced572SBram Moolenaar 	if (li == NULL)
8681dced572SBram Moolenaar 	    luaL_error(L, "invalid position");
8691dced572SBram Moolenaar     }
8701dced572SBram Moolenaar     lua_settop(L, 2);
871ca06da92SBram Moolenaar     luaV_checktypval(L, 2, &v, "inserting list item");
872b376647bSBram Moolenaar     if (list_insert_tv(l, &v, li) == FAIL)
873ca06da92SBram Moolenaar 	luaL_error(L, "failed to add item to list");
874b376647bSBram Moolenaar     clear_tv(&v);
8751dced572SBram Moolenaar     lua_settop(L, 1);
8761dced572SBram Moolenaar     return 1;
8771dced572SBram Moolenaar }
8781dced572SBram Moolenaar 
8791dced572SBram Moolenaar static const luaL_Reg luaV_List_mt[] = {
8801dced572SBram Moolenaar     {"__tostring", luaV_list_tostring},
8811dced572SBram Moolenaar     {"__len", luaV_list_len},
8821dced572SBram Moolenaar     {"__call", luaV_list_call},
8831dced572SBram Moolenaar     {"__index", luaV_list_index},
8841dced572SBram Moolenaar     {"__newindex", luaV_list_newindex},
8851dced572SBram Moolenaar     {"add", luaV_list_add},
8861dced572SBram Moolenaar     {"insert", luaV_list_insert},
8871dced572SBram Moolenaar     {NULL, NULL}
8881dced572SBram Moolenaar };
8891dced572SBram Moolenaar 
8901dced572SBram Moolenaar 
8911dced572SBram Moolenaar /* =======   Dict type   ======= */
8921dced572SBram Moolenaar 
8931dced572SBram Moolenaar     static luaV_Dict *
8941dced572SBram Moolenaar luaV_newdict(lua_State *L, dict_T *dic)
8951dced572SBram Moolenaar {
8961dced572SBram Moolenaar     luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
8971dced572SBram Moolenaar     *d = dic;
8981dced572SBram Moolenaar     dic->dv_refcount++; /* reference in Lua */
8991dced572SBram Moolenaar     luaV_setudata(L, dic); /* cache[dic] = udata */
9001dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_DICT);
9011dced572SBram Moolenaar     lua_setmetatable(L, -2);
9021dced572SBram Moolenaar     return d;
9031dced572SBram Moolenaar }
9041dced572SBram Moolenaar 
9051dced572SBram Moolenaar luaV_pushtype(dict_T, dict, luaV_Dict)
9061dced572SBram Moolenaar luaV_type_tostring(dict, LUAVIM_DICT)
9071dced572SBram Moolenaar 
9081dced572SBram Moolenaar     static int
9091dced572SBram Moolenaar luaV_dict_len(lua_State *L)
9101dced572SBram Moolenaar {
9111dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
9121dced572SBram Moolenaar     lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used);
9131dced572SBram Moolenaar     return 1;
9141dced572SBram Moolenaar }
9151dced572SBram Moolenaar 
9161dced572SBram Moolenaar     static int
917feeaa688SBram Moolenaar luaV_dict_iter(lua_State *L UNUSED)
9181dced572SBram Moolenaar {
919feeaa688SBram Moolenaar #ifdef FEAT_EVAL
9201dced572SBram Moolenaar     hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
9211dced572SBram Moolenaar     int n = lua_tointeger(L, lua_upvalueindex(3));
9221dced572SBram Moolenaar     dictitem_T *di;
9231dced572SBram Moolenaar     if (n <= 0) return 0;
9241dced572SBram Moolenaar     while (HASHITEM_EMPTY(hi)) hi++;
9251dced572SBram Moolenaar     di = dict_lookup(hi);
9261dced572SBram Moolenaar     lua_pushstring(L, (char *) hi->hi_key);
9271dced572SBram Moolenaar     luaV_pushtypval(L, &di->di_tv);
9281dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) (hi + 1));
9291dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(2));
9301dced572SBram Moolenaar     lua_pushinteger(L, n - 1);
9311dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(3));
9321dced572SBram Moolenaar     return 2;
933feeaa688SBram Moolenaar #else
934feeaa688SBram Moolenaar     return 0;
935feeaa688SBram Moolenaar #endif
9361dced572SBram Moolenaar }
9371dced572SBram Moolenaar 
9381dced572SBram Moolenaar     static int
9391dced572SBram Moolenaar luaV_dict_call(lua_State *L)
9401dced572SBram Moolenaar {
9411dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
9421dced572SBram Moolenaar     hashtab_T *ht = &d->dv_hashtab;
9431dced572SBram Moolenaar     lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
9441dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) ht->ht_array);
9451dced572SBram Moolenaar     lua_pushinteger(L, ht->ht_used); /* # remaining items */
9461dced572SBram Moolenaar     lua_pushcclosure(L, luaV_dict_iter, 3);
9471dced572SBram Moolenaar     return 1;
9481dced572SBram Moolenaar }
9491dced572SBram Moolenaar 
9501dced572SBram Moolenaar     static int
9511dced572SBram Moolenaar luaV_dict_index(lua_State *L)
9521dced572SBram Moolenaar {
9531dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
9541dced572SBram Moolenaar     char_u *key = (char_u *) luaL_checkstring(L, 2);
9551dced572SBram Moolenaar     dictitem_T *di = dict_find(d, key, -1);
956ca06da92SBram Moolenaar 
9571dced572SBram Moolenaar     if (di == NULL)
9581dced572SBram Moolenaar 	lua_pushnil(L);
9591dced572SBram Moolenaar     else
960ca06da92SBram Moolenaar     {
9611dced572SBram Moolenaar 	luaV_pushtypval(L, &di->di_tv);
962ca06da92SBram Moolenaar 	if (di->di_tv.v_type == VAR_FUNC) /* funcref? */
963ca06da92SBram Moolenaar 	{
964ca06da92SBram Moolenaar 	    luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
965ca06da92SBram Moolenaar 	    f->self = d; /* keep "self" reference */
966ca06da92SBram Moolenaar 	    d->dv_refcount++;
967ca06da92SBram Moolenaar 	}
968ca06da92SBram Moolenaar     }
9691dced572SBram Moolenaar     return 1;
9701dced572SBram Moolenaar }
9711dced572SBram Moolenaar 
9721dced572SBram Moolenaar     static int
9731dced572SBram Moolenaar luaV_dict_newindex(lua_State *L)
9741dced572SBram Moolenaar {
9751dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
9761dced572SBram Moolenaar     char_u *key = (char_u *) luaL_checkstring(L, 2);
9771dced572SBram Moolenaar     dictitem_T *di;
978ca06da92SBram Moolenaar     typval_T v;
979713bf9e9SBram Moolenaar 
9801dced572SBram Moolenaar     if (d->dv_lock)
9811dced572SBram Moolenaar 	luaL_error(L, "dict is locked");
982d6ef5f9bSBram Moolenaar     if (key == NULL)
983d6ef5f9bSBram Moolenaar 	return 0;
984d6ef5f9bSBram Moolenaar     if (*key == NUL)
985ca06da92SBram Moolenaar 	luaL_error(L, "empty key");
98617413671SBram Moolenaar     if (!lua_isnil(L, 3)) /* read value? */
98717413671SBram Moolenaar     {
988ca06da92SBram Moolenaar 	luaV_checktypval(L, 3, &v, "setting dict item");
989ca06da92SBram Moolenaar 	if (d->dv_scope == VAR_DEF_SCOPE && v.v_type == VAR_FUNC)
990ca06da92SBram Moolenaar 	    luaL_error(L, "cannot assign funcref to builtin scope");
991ca06da92SBram Moolenaar     }
9921dced572SBram Moolenaar     di = dict_find(d, key, -1);
9931dced572SBram Moolenaar     if (di == NULL) /* non-existing key? */
9941dced572SBram Moolenaar     {
995d6ef5f9bSBram Moolenaar 	if (lua_isnil(L, 3))
996d6ef5f9bSBram Moolenaar 	    return 0;
9971dced572SBram Moolenaar 	di = dictitem_alloc(key);
998d6ef5f9bSBram Moolenaar 	if (di == NULL)
999d6ef5f9bSBram Moolenaar 	    return 0;
10001dced572SBram Moolenaar 	if (dict_add(d, di) == FAIL)
10011dced572SBram Moolenaar 	{
10021dced572SBram Moolenaar 	    vim_free(di);
10031dced572SBram Moolenaar 	    return 0;
10041dced572SBram Moolenaar 	}
10051dced572SBram Moolenaar     }
10061dced572SBram Moolenaar     else
10071dced572SBram Moolenaar 	clear_tv(&di->di_tv);
10081dced572SBram Moolenaar     if (lua_isnil(L, 3)) /* remove? */
10091dced572SBram Moolenaar     {
10101dced572SBram Moolenaar 	hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
10111dced572SBram Moolenaar 	hash_remove(&d->dv_hashtab, hi);
10121dced572SBram Moolenaar 	dictitem_free(di);
10131dced572SBram Moolenaar     }
1014ca06da92SBram Moolenaar     else
1015ca06da92SBram Moolenaar     {
10161dced572SBram Moolenaar 	copy_tv(&v, &di->di_tv);
1017b376647bSBram Moolenaar 	clear_tv(&v);
10181dced572SBram Moolenaar     }
10191dced572SBram Moolenaar     return 0;
10201dced572SBram Moolenaar }
10211dced572SBram Moolenaar 
10221dced572SBram Moolenaar static const luaL_Reg luaV_Dict_mt[] = {
10231dced572SBram Moolenaar     {"__tostring", luaV_dict_tostring},
10241dced572SBram Moolenaar     {"__len", luaV_dict_len},
10251dced572SBram Moolenaar     {"__call", luaV_dict_call},
10261dced572SBram Moolenaar     {"__index", luaV_dict_index},
10271dced572SBram Moolenaar     {"__newindex", luaV_dict_newindex},
10281dced572SBram Moolenaar     {NULL, NULL}
10291dced572SBram Moolenaar };
10301dced572SBram Moolenaar 
10311dced572SBram Moolenaar 
1032ca06da92SBram Moolenaar /* =======   Funcref type   ======= */
1033ca06da92SBram Moolenaar 
1034ca06da92SBram Moolenaar     static luaV_Funcref *
1035ca06da92SBram Moolenaar luaV_newfuncref(lua_State *L, char_u *name)
1036ca06da92SBram Moolenaar {
1037ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1038ca06da92SBram Moolenaar 
1039ca06da92SBram Moolenaar     if (name != NULL)
1040ca06da92SBram Moolenaar     {
1041*4eefe47eSBram Moolenaar 	func_ref(name);
1042*4eefe47eSBram Moolenaar 	f->name = vim_strsave(name);
1043ca06da92SBram Moolenaar     }
1044ca06da92SBram Moolenaar     f->self = NULL;
1045ca06da92SBram Moolenaar     luaV_getfield(L, LUAVIM_FUNCREF);
1046ca06da92SBram Moolenaar     lua_setmetatable(L, -2);
1047ca06da92SBram Moolenaar     return f;
1048ca06da92SBram Moolenaar }
1049ca06da92SBram Moolenaar 
1050ca06da92SBram Moolenaar     static luaV_Funcref *
1051*4eefe47eSBram Moolenaar luaV_pushfuncref(lua_State *L, char_u *name)
1052ca06da92SBram Moolenaar {
1053*4eefe47eSBram Moolenaar     return luaV_newfuncref(L, name);
1054ca06da92SBram Moolenaar }
1055ca06da92SBram Moolenaar 
1056ca06da92SBram Moolenaar 
1057ca06da92SBram Moolenaar luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1058ca06da92SBram Moolenaar 
1059ca06da92SBram Moolenaar     static int
1060ca06da92SBram Moolenaar luaV_funcref_gc(lua_State *L)
1061ca06da92SBram Moolenaar {
1062ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1063ca06da92SBram Moolenaar 
1064*4eefe47eSBram Moolenaar     func_unref(f->name);
1065*4eefe47eSBram Moolenaar     vim_free(f->name);
1066*4eefe47eSBram Moolenaar     // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
1067*4eefe47eSBram Moolenaar     // will be (or has been already) freed by Vim's garbage collection.
1068ca06da92SBram Moolenaar     return 0;
1069ca06da92SBram Moolenaar }
1070ca06da92SBram Moolenaar 
1071ca06da92SBram Moolenaar /* equivalent to string(funcref) */
1072ca06da92SBram Moolenaar     static int
1073ca06da92SBram Moolenaar luaV_funcref_len(lua_State *L)
1074ca06da92SBram Moolenaar {
1075ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1076ca06da92SBram Moolenaar 
1077*4eefe47eSBram Moolenaar     lua_pushstring(L, (const char *) f->name);
1078ca06da92SBram Moolenaar     return 1;
1079ca06da92SBram Moolenaar }
1080ca06da92SBram Moolenaar 
1081ca06da92SBram Moolenaar     static int
1082ca06da92SBram Moolenaar luaV_funcref_call(lua_State *L)
1083ca06da92SBram Moolenaar {
1084ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1085*4eefe47eSBram Moolenaar     int i, n = lua_gettop(L) - 1; // #args
1086*4eefe47eSBram Moolenaar     int status = FAIL;
1087*4eefe47eSBram Moolenaar     typval_T args;
1088*4eefe47eSBram Moolenaar     typval_T rettv;
1089ca06da92SBram Moolenaar 
1090*4eefe47eSBram Moolenaar     args.v_type = VAR_LIST;
1091*4eefe47eSBram Moolenaar     args.vval.v_list = list_alloc();
1092*4eefe47eSBram Moolenaar     rettv.v_type = VAR_UNKNOWN; // as in clear_tv
1093*4eefe47eSBram Moolenaar     if (args.vval.v_list != NULL)
1094d6ef5f9bSBram Moolenaar     {
1095*4eefe47eSBram Moolenaar 	typval_T v;
1096*4eefe47eSBram Moolenaar 
109717413671SBram Moolenaar 	for (i = 0; i < n; i++)
109817413671SBram Moolenaar 	{
1099ca06da92SBram Moolenaar 	    luaV_checktypval(L, i + 2, &v, "calling funcref");
1100*4eefe47eSBram Moolenaar 	    list_append_tv(args.vval.v_list, &v);
1101713bf9e9SBram Moolenaar 	    clear_tv(&v);
1102ca06da92SBram Moolenaar 	}
1103*4eefe47eSBram Moolenaar 	status = func_call(f->name, &args, NULL, f->self, &rettv);
1104ca06da92SBram Moolenaar 	if (status == OK)
1105ca06da92SBram Moolenaar 	    luaV_pushtypval(L, &rettv);
1106*4eefe47eSBram Moolenaar 	clear_tv(&args);
1107ca06da92SBram Moolenaar 	clear_tv(&rettv);
1108d6ef5f9bSBram Moolenaar     }
1109ca06da92SBram Moolenaar     if (status != OK)
1110ca06da92SBram Moolenaar 	luaL_error(L, "cannot call funcref");
1111ca06da92SBram Moolenaar     return 1;
1112ca06da92SBram Moolenaar }
1113ca06da92SBram Moolenaar 
1114ca06da92SBram Moolenaar static const luaL_Reg luaV_Funcref_mt[] = {
1115ca06da92SBram Moolenaar     {"__tostring", luaV_funcref_tostring},
1116ca06da92SBram Moolenaar     {"__gc", luaV_funcref_gc},
1117ca06da92SBram Moolenaar     {"__len", luaV_funcref_len},
1118ca06da92SBram Moolenaar     {"__call", luaV_funcref_call},
1119ca06da92SBram Moolenaar     {NULL, NULL}
1120ca06da92SBram Moolenaar };
1121ca06da92SBram Moolenaar 
1122ca06da92SBram Moolenaar 
11231dced572SBram Moolenaar /* =======   Buffer type   ======= */
11241dced572SBram Moolenaar 
11251dced572SBram Moolenaar luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
11261dced572SBram Moolenaar luaV_pushtype(buf_T, buffer, luaV_Buffer)
11271dced572SBram Moolenaar luaV_type_tostring(buffer, LUAVIM_BUFFER)
11281dced572SBram Moolenaar 
11291dced572SBram Moolenaar     static int
113055d5c034SBram Moolenaar luaV_buffer_len(lua_State *L)
113155d5c034SBram Moolenaar {
11321dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
11331dced572SBram Moolenaar     lua_pushinteger(L, b->b_ml.ml_line_count);
11340ba04296SBram Moolenaar     return 1;
11350ba04296SBram Moolenaar }
11360ba04296SBram Moolenaar 
113755d5c034SBram Moolenaar     static int
113855d5c034SBram Moolenaar luaV_buffer_call(lua_State *L)
113955d5c034SBram Moolenaar {
11401dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
11410ba04296SBram Moolenaar     lua_settop(L, 1);
11421dced572SBram Moolenaar     set_curbuf(b, DOBUF_SPLIT);
11430ba04296SBram Moolenaar     return 1;
11440ba04296SBram Moolenaar }
11450ba04296SBram Moolenaar 
114655d5c034SBram Moolenaar     static int
114755d5c034SBram Moolenaar luaV_buffer_index(lua_State *L)
114855d5c034SBram Moolenaar {
11491dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
11500ba04296SBram Moolenaar     linenr_T n = (linenr_T) lua_tointeger(L, 2);
11511dced572SBram Moolenaar     if (n > 0 && n <= b->b_ml.ml_line_count)
11521dced572SBram Moolenaar 	luaV_pushline(L, b, n);
115355d5c034SBram Moolenaar     else if (lua_isstring(L, 2))
115455d5c034SBram Moolenaar     {
11550ba04296SBram Moolenaar 	const char *s = lua_tostring(L, 2);
11560ba04296SBram Moolenaar 	if (strncmp(s, "name", 4) == 0)
1157fe08df45SBram Moolenaar 	    lua_pushstring(L, (b->b_sfname == NULL)
1158fe08df45SBram Moolenaar 					? "" : (char *) b->b_sfname);
11590ba04296SBram Moolenaar 	else if (strncmp(s, "fname", 5) == 0)
1160fe08df45SBram Moolenaar 	    lua_pushstring(L, (b->b_ffname == NULL)
1161fe08df45SBram Moolenaar 					? "" : (char *) b->b_ffname);
11620ba04296SBram Moolenaar 	else if (strncmp(s, "number", 6) == 0)
11631dced572SBram Moolenaar 	    lua_pushinteger(L, b->b_fnum);
11640ba04296SBram Moolenaar 	/* methods */
11650ba04296SBram Moolenaar 	else if (strncmp(s,   "insert", 6) == 0
11660ba04296SBram Moolenaar 		|| strncmp(s, "next", 4) == 0
11670ba04296SBram Moolenaar 		|| strncmp(s, "previous", 8) == 0
116855d5c034SBram Moolenaar 		|| strncmp(s, "isvalid", 7) == 0)
116955d5c034SBram Moolenaar 	{
11700ba04296SBram Moolenaar 	    lua_getmetatable(L, 1);
11710ba04296SBram Moolenaar 	    lua_getfield(L, -1, s);
11720ba04296SBram Moolenaar 	}
117355d5c034SBram Moolenaar 	else
117455d5c034SBram Moolenaar 	    lua_pushnil(L);
11750ba04296SBram Moolenaar     }
117655d5c034SBram Moolenaar     else
117755d5c034SBram Moolenaar 	lua_pushnil(L);
11780ba04296SBram Moolenaar     return 1;
11790ba04296SBram Moolenaar }
11800ba04296SBram Moolenaar 
118155d5c034SBram Moolenaar     static int
118255d5c034SBram Moolenaar luaV_buffer_newindex(lua_State *L)
118355d5c034SBram Moolenaar {
11841dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
11850ba04296SBram Moolenaar     linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
11860ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
11870ba04296SBram Moolenaar     luaV_checksandbox(L);
11880ba04296SBram Moolenaar #endif
11891dced572SBram Moolenaar     if (n < 1 || n > b->b_ml.ml_line_count)
11900ba04296SBram Moolenaar 	luaL_error(L, "invalid line number");
119155d5c034SBram Moolenaar     if (lua_isnil(L, 3)) /* delete line */
119255d5c034SBram Moolenaar     {
11930ba04296SBram Moolenaar 	buf_T *buf = curbuf;
11941dced572SBram Moolenaar 	curbuf = b;
119555d5c034SBram Moolenaar 	if (u_savedel(n, 1L) == FAIL)
119655d5c034SBram Moolenaar 	{
11970ba04296SBram Moolenaar 	    curbuf = buf;
11980ba04296SBram Moolenaar 	    luaL_error(L, "cannot save undo information");
11990ba04296SBram Moolenaar 	}
120055d5c034SBram Moolenaar 	else if (ml_delete(n, FALSE) == FAIL)
120155d5c034SBram Moolenaar 	{
12020ba04296SBram Moolenaar 	    curbuf = buf;
12030ba04296SBram Moolenaar 	    luaL_error(L, "cannot delete line");
12040ba04296SBram Moolenaar 	}
1205ca06da92SBram Moolenaar 	else
1206ca06da92SBram Moolenaar 	{
12070ba04296SBram Moolenaar 	    deleted_lines_mark(n, 1L);
12081dced572SBram Moolenaar 	    if (b == curwin->w_buffer) /* fix cursor in current window? */
120955d5c034SBram Moolenaar 	    {
121055d5c034SBram Moolenaar 		if (curwin->w_cursor.lnum >= n)
121155d5c034SBram Moolenaar 		{
121255d5c034SBram Moolenaar 		    if (curwin->w_cursor.lnum > n)
121355d5c034SBram Moolenaar 		    {
12140ba04296SBram Moolenaar 			curwin->w_cursor.lnum -= 1;
12150ba04296SBram Moolenaar 			check_cursor_col();
12160ba04296SBram Moolenaar 		    }
12170ba04296SBram Moolenaar 		    else check_cursor();
12180ba04296SBram Moolenaar 		    changed_cline_bef_curs();
12190ba04296SBram Moolenaar 		}
12200ba04296SBram Moolenaar 		invalidate_botline();
12210ba04296SBram Moolenaar 	    }
12220ba04296SBram Moolenaar 	}
12230ba04296SBram Moolenaar 	curbuf = buf;
12240ba04296SBram Moolenaar     }
122555d5c034SBram Moolenaar     else if (lua_isstring(L, 3)) /* update line */
122655d5c034SBram Moolenaar     {
12270ba04296SBram Moolenaar 	buf_T *buf = curbuf;
12281dced572SBram Moolenaar 	curbuf = b;
122955d5c034SBram Moolenaar 	if (u_savesub(n) == FAIL)
123055d5c034SBram Moolenaar 	{
12310ba04296SBram Moolenaar 	    curbuf = buf;
12320ba04296SBram Moolenaar 	    luaL_error(L, "cannot save undo information");
12330ba04296SBram Moolenaar 	}
123455d5c034SBram Moolenaar 	else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
123555d5c034SBram Moolenaar 	{
12360ba04296SBram Moolenaar 	    curbuf = buf;
12370ba04296SBram Moolenaar 	    luaL_error(L, "cannot replace line");
12380ba04296SBram Moolenaar 	}
12390ba04296SBram Moolenaar 	else changed_bytes(n, 0);
12400ba04296SBram Moolenaar 	curbuf = buf;
12411dced572SBram Moolenaar 	if (b == curwin->w_buffer)
12420ba04296SBram Moolenaar 	    check_cursor_col();
12430ba04296SBram Moolenaar     }
12440ba04296SBram Moolenaar     else
12450ba04296SBram Moolenaar 	luaL_error(L, "wrong argument to change line");
12460ba04296SBram Moolenaar     return 0;
12470ba04296SBram Moolenaar }
12480ba04296SBram Moolenaar 
124955d5c034SBram Moolenaar     static int
125055d5c034SBram Moolenaar luaV_buffer_insert(lua_State *L)
125155d5c034SBram Moolenaar {
12521dced572SBram Moolenaar     luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
12531dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
12541dced572SBram Moolenaar     linenr_T last = b->b_ml.ml_line_count;
12550ba04296SBram Moolenaar     linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
12560ba04296SBram Moolenaar     buf_T *buf;
12570ba04296SBram Moolenaar     luaL_checktype(L, 2, LUA_TSTRING);
12580ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
12590ba04296SBram Moolenaar     luaV_checksandbox(L);
12600ba04296SBram Moolenaar #endif
12610ba04296SBram Moolenaar     /* fix insertion line */
12620ba04296SBram Moolenaar     if (n < 0) n = 0;
12630ba04296SBram Moolenaar     if (n > last) n = last;
12640ba04296SBram Moolenaar     /* insert */
12650ba04296SBram Moolenaar     buf = curbuf;
12661dced572SBram Moolenaar     curbuf = b;
126755d5c034SBram Moolenaar     if (u_save(n, n + 1) == FAIL)
126855d5c034SBram Moolenaar     {
12690ba04296SBram Moolenaar 	curbuf = buf;
12700ba04296SBram Moolenaar 	luaL_error(L, "cannot save undo information");
12710ba04296SBram Moolenaar     }
127255d5c034SBram Moolenaar     else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
127355d5c034SBram Moolenaar     {
12740ba04296SBram Moolenaar 	curbuf = buf;
12750ba04296SBram Moolenaar 	luaL_error(L, "cannot insert line");
12760ba04296SBram Moolenaar     }
12770ba04296SBram Moolenaar     else
12780ba04296SBram Moolenaar 	appended_lines_mark(n, 1L);
12790ba04296SBram Moolenaar     curbuf = buf;
12800ba04296SBram Moolenaar     update_screen(VALID);
12810ba04296SBram Moolenaar     return 0;
12820ba04296SBram Moolenaar }
12830ba04296SBram Moolenaar 
128455d5c034SBram Moolenaar     static int
128555d5c034SBram Moolenaar luaV_buffer_next(lua_State *L)
128655d5c034SBram Moolenaar {
12870ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
12881dced572SBram Moolenaar     buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
12891dced572SBram Moolenaar     luaV_pushbuffer(L, buf->b_next);
12900ba04296SBram Moolenaar     return 1;
12910ba04296SBram Moolenaar }
12920ba04296SBram Moolenaar 
129355d5c034SBram Moolenaar     static int
129455d5c034SBram Moolenaar luaV_buffer_previous(lua_State *L)
129555d5c034SBram Moolenaar {
12960ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
12971dced572SBram Moolenaar     buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
12981dced572SBram Moolenaar     luaV_pushbuffer(L, buf->b_prev);
12990ba04296SBram Moolenaar     return 1;
13000ba04296SBram Moolenaar }
13010ba04296SBram Moolenaar 
130255d5c034SBram Moolenaar     static int
130355d5c034SBram Moolenaar luaV_buffer_isvalid(lua_State *L)
130455d5c034SBram Moolenaar {
13050ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
13061dced572SBram Moolenaar     luaV_getudata(L, *b);
13070ba04296SBram Moolenaar     lua_pushboolean(L, !lua_isnil(L, -1));
13080ba04296SBram Moolenaar     return 1;
13090ba04296SBram Moolenaar }
13100ba04296SBram Moolenaar 
13110ba04296SBram Moolenaar static const luaL_Reg luaV_Buffer_mt[] = {
13120ba04296SBram Moolenaar     {"__tostring", luaV_buffer_tostring},
13130ba04296SBram Moolenaar     {"__len", luaV_buffer_len},
13140ba04296SBram Moolenaar     {"__call", luaV_buffer_call},
13150ba04296SBram Moolenaar     {"__index", luaV_buffer_index},
13160ba04296SBram Moolenaar     {"__newindex", luaV_buffer_newindex},
13170ba04296SBram Moolenaar     {"insert", luaV_buffer_insert},
13180ba04296SBram Moolenaar     {"next", luaV_buffer_next},
13190ba04296SBram Moolenaar     {"previous", luaV_buffer_previous},
13200ba04296SBram Moolenaar     {"isvalid", luaV_buffer_isvalid},
13210ba04296SBram Moolenaar     {NULL, NULL}
13220ba04296SBram Moolenaar };
13230ba04296SBram Moolenaar 
13240ba04296SBram Moolenaar 
13250ba04296SBram Moolenaar /* =======   Window type   ======= */
13260ba04296SBram Moolenaar 
13271dced572SBram Moolenaar luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
13281dced572SBram Moolenaar luaV_pushtype(win_T, window, luaV_Window)
13291dced572SBram Moolenaar luaV_type_tostring(window, LUAVIM_WINDOW)
13300ba04296SBram Moolenaar 
133155d5c034SBram Moolenaar     static int
133255d5c034SBram Moolenaar luaV_window_call(lua_State *L)
133355d5c034SBram Moolenaar {
13341dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
13350ba04296SBram Moolenaar     lua_settop(L, 1);
13361dced572SBram Moolenaar     win_goto(w);
13370ba04296SBram Moolenaar     return 1;
13380ba04296SBram Moolenaar }
13390ba04296SBram Moolenaar 
134055d5c034SBram Moolenaar     static int
134155d5c034SBram Moolenaar luaV_window_index(lua_State *L)
134255d5c034SBram Moolenaar {
13431dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
13440ba04296SBram Moolenaar     const char *s = luaL_checkstring(L, 2);
13450ba04296SBram Moolenaar     if (strncmp(s, "buffer", 6) == 0)
13461dced572SBram Moolenaar 	luaV_pushbuffer(L, w->w_buffer);
13470ba04296SBram Moolenaar     else if (strncmp(s, "line", 4) == 0)
13481dced572SBram Moolenaar 	lua_pushinteger(L, w->w_cursor.lnum);
13490ba04296SBram Moolenaar     else if (strncmp(s, "col", 3) == 0)
13501dced572SBram Moolenaar 	lua_pushinteger(L, w->w_cursor.col + 1);
13510ba04296SBram Moolenaar     else if (strncmp(s, "width", 5) == 0)
13520263146bSBram Moolenaar 	lua_pushinteger(L, w->w_width);
13530ba04296SBram Moolenaar     else if (strncmp(s, "height", 6) == 0)
13541dced572SBram Moolenaar 	lua_pushinteger(L, w->w_height);
13550ba04296SBram Moolenaar     /* methods */
13560ba04296SBram Moolenaar     else if (strncmp(s,   "next", 4) == 0
13570ba04296SBram Moolenaar 	    || strncmp(s, "previous", 8) == 0
135855d5c034SBram Moolenaar 	    || strncmp(s, "isvalid", 7) == 0)
135955d5c034SBram Moolenaar     {
13600ba04296SBram Moolenaar 	lua_getmetatable(L, 1);
13610ba04296SBram Moolenaar 	lua_getfield(L, -1, s);
13620ba04296SBram Moolenaar     }
13630ba04296SBram Moolenaar     else
13640ba04296SBram Moolenaar 	lua_pushnil(L);
13650ba04296SBram Moolenaar     return 1;
13660ba04296SBram Moolenaar }
13670ba04296SBram Moolenaar 
136855d5c034SBram Moolenaar     static int
136955d5c034SBram Moolenaar luaV_window_newindex(lua_State *L)
137055d5c034SBram Moolenaar {
13711dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
13720ba04296SBram Moolenaar     const char *s = luaL_checkstring(L, 2);
13730ba04296SBram Moolenaar     int v = luaL_checkinteger(L, 3);
137455d5c034SBram Moolenaar     if (strncmp(s, "line", 4) == 0)
137555d5c034SBram Moolenaar     {
13760ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
13770ba04296SBram Moolenaar 	luaV_checksandbox(L);
13780ba04296SBram Moolenaar #endif
13791dced572SBram Moolenaar 	if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
13800ba04296SBram Moolenaar 	    luaL_error(L, "line out of range");
13811dced572SBram Moolenaar 	w->w_cursor.lnum = v;
13820ba04296SBram Moolenaar 	update_screen(VALID);
13830ba04296SBram Moolenaar     }
138455d5c034SBram Moolenaar     else if (strncmp(s, "col", 3) == 0)
138555d5c034SBram Moolenaar     {
13860ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
13870ba04296SBram Moolenaar 	luaV_checksandbox(L);
13880ba04296SBram Moolenaar #endif
13891dced572SBram Moolenaar 	w->w_cursor.col = v - 1;
139053901442SBram Moolenaar 	w->w_set_curswant = TRUE;
13910ba04296SBram Moolenaar 	update_screen(VALID);
13920ba04296SBram Moolenaar     }
139355d5c034SBram Moolenaar     else if (strncmp(s, "width", 5) == 0)
139455d5c034SBram Moolenaar     {
13950ba04296SBram Moolenaar 	win_T *win = curwin;
13960ba04296SBram Moolenaar #ifdef FEAT_GUI
13970ba04296SBram Moolenaar 	need_mouse_correct = TRUE;
13980ba04296SBram Moolenaar #endif
13991dced572SBram Moolenaar 	curwin = w;
14000ba04296SBram Moolenaar 	win_setwidth(v);
14010ba04296SBram Moolenaar 	curwin = win;
14020ba04296SBram Moolenaar     }
140355d5c034SBram Moolenaar     else if (strncmp(s, "height", 6) == 0)
140455d5c034SBram Moolenaar     {
14050ba04296SBram Moolenaar 	win_T *win = curwin;
14060ba04296SBram Moolenaar #ifdef FEAT_GUI
14070ba04296SBram Moolenaar 	need_mouse_correct = TRUE;
14080ba04296SBram Moolenaar #endif
14091dced572SBram Moolenaar 	curwin = w;
14100ba04296SBram Moolenaar 	win_setheight(v);
14110ba04296SBram Moolenaar 	curwin = win;
14120ba04296SBram Moolenaar     }
14130ba04296SBram Moolenaar     else
14140ba04296SBram Moolenaar 	luaL_error(L, "invalid window property: `%s'", s);
14150ba04296SBram Moolenaar     return 0;
14160ba04296SBram Moolenaar }
14170ba04296SBram Moolenaar 
141855d5c034SBram Moolenaar     static int
141955d5c034SBram Moolenaar luaV_window_next(lua_State *L)
142055d5c034SBram Moolenaar {
14210ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
14221dced572SBram Moolenaar     win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
14231dced572SBram Moolenaar     luaV_pushwindow(L, win->w_next);
14240ba04296SBram Moolenaar     return 1;
14250ba04296SBram Moolenaar }
14260ba04296SBram Moolenaar 
142755d5c034SBram Moolenaar     static int
142855d5c034SBram Moolenaar luaV_window_previous(lua_State *L)
142955d5c034SBram Moolenaar {
14300ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
14311dced572SBram Moolenaar     win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
14321dced572SBram Moolenaar     luaV_pushwindow(L, win->w_prev);
14330ba04296SBram Moolenaar     return 1;
14340ba04296SBram Moolenaar }
14350ba04296SBram Moolenaar 
143655d5c034SBram Moolenaar     static int
143755d5c034SBram Moolenaar luaV_window_isvalid(lua_State *L)
143855d5c034SBram Moolenaar {
14390ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
14401dced572SBram Moolenaar     luaV_getudata(L, *w);
14410ba04296SBram Moolenaar     lua_pushboolean(L, !lua_isnil(L, -1));
14420ba04296SBram Moolenaar     return 1;
14430ba04296SBram Moolenaar }
14440ba04296SBram Moolenaar 
14450ba04296SBram Moolenaar static const luaL_Reg luaV_Window_mt[] = {
14460ba04296SBram Moolenaar     {"__tostring", luaV_window_tostring},
14470ba04296SBram Moolenaar     {"__call", luaV_window_call},
14480ba04296SBram Moolenaar     {"__index", luaV_window_index},
14490ba04296SBram Moolenaar     {"__newindex", luaV_window_newindex},
14500ba04296SBram Moolenaar     {"next", luaV_window_next},
14510ba04296SBram Moolenaar     {"previous", luaV_window_previous},
14520ba04296SBram Moolenaar     {"isvalid", luaV_window_isvalid},
14530ba04296SBram Moolenaar     {NULL, NULL}
14540ba04296SBram Moolenaar };
14550ba04296SBram Moolenaar 
14560ba04296SBram Moolenaar 
14570ba04296SBram Moolenaar /* =======   Vim module   ======= */
14580ba04296SBram Moolenaar 
145955d5c034SBram Moolenaar     static int
146055d5c034SBram Moolenaar luaV_print(lua_State *L)
146155d5c034SBram Moolenaar {
14620ba04296SBram Moolenaar     int i, n = lua_gettop(L); /* nargs */
14630ba04296SBram Moolenaar     const char *s;
14640ba04296SBram Moolenaar     size_t l;
14650ba04296SBram Moolenaar     luaL_Buffer b;
14660ba04296SBram Moolenaar     luaL_buffinit(L, &b);
14670ba04296SBram Moolenaar     lua_getglobal(L, "tostring");
146855d5c034SBram Moolenaar     for (i = 1; i <= n; i++)
146955d5c034SBram Moolenaar     {
14700ba04296SBram Moolenaar 	lua_pushvalue(L, -1); /* tostring */
14710ba04296SBram Moolenaar 	lua_pushvalue(L, i); /* arg */
14720ba04296SBram Moolenaar 	lua_call(L, 1, 1);
14730ba04296SBram Moolenaar 	s = lua_tolstring(L, -1, &l);
14740ba04296SBram Moolenaar 	if (s == NULL)
14750ba04296SBram Moolenaar 	    return luaL_error(L, "cannot convert to string");
14760ba04296SBram Moolenaar 	if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */
14770ba04296SBram Moolenaar 	luaV_addlstring(&b, s, l, 0);
14780ba04296SBram Moolenaar 	lua_pop(L, 1);
14790ba04296SBram Moolenaar     }
14800ba04296SBram Moolenaar     luaL_pushresult(&b);
14810ba04296SBram Moolenaar     luaV_msg(L);
14820ba04296SBram Moolenaar     return 0;
14830ba04296SBram Moolenaar }
14840ba04296SBram Moolenaar 
148555d5c034SBram Moolenaar     static int
148638e2b063SBram Moolenaar luaV_debug(lua_State *L)
148738e2b063SBram Moolenaar {
148838e2b063SBram Moolenaar     lua_settop(L, 0);
148938e2b063SBram Moolenaar     lua_getglobal(L, "vim");
149038e2b063SBram Moolenaar     lua_getfield(L, -1, "eval");
149138e2b063SBram Moolenaar     lua_remove(L, -2); /* vim.eval at position 1 */
149238e2b063SBram Moolenaar     for (;;)
149338e2b063SBram Moolenaar     {
149438e2b063SBram Moolenaar 	const char *input;
149538e2b063SBram Moolenaar 	size_t l;
149638e2b063SBram Moolenaar 	lua_pushvalue(L, 1); /* vim.eval */
149738e2b063SBram Moolenaar 	lua_pushliteral(L, "input('lua_debug> ')");
149838e2b063SBram Moolenaar 	lua_call(L, 1, 1); /* return string */
149938e2b063SBram Moolenaar 	input = lua_tolstring(L, -1, &l);
150038e2b063SBram Moolenaar 	if (l == 0 || strcmp(input, "cont") == 0)
150138e2b063SBram Moolenaar 	    return 0;
150238e2b063SBram Moolenaar 	msg_putchar('\n'); /* avoid outputting on input line */
150338e2b063SBram Moolenaar 	if (luaL_loadbuffer(L, input, l, "=(debug command)")
150438e2b063SBram Moolenaar 		|| lua_pcall(L, 0, 0, 0))
150538e2b063SBram Moolenaar 	    luaV_emsg(L);
150638e2b063SBram Moolenaar 	lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */
150738e2b063SBram Moolenaar     }
150838e2b063SBram Moolenaar }
150938e2b063SBram Moolenaar 
151038e2b063SBram Moolenaar     static int
151155d5c034SBram Moolenaar luaV_command(lua_State *L)
151255d5c034SBram Moolenaar {
15130ba04296SBram Moolenaar     do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
15140ba04296SBram Moolenaar     update_screen(VALID);
15150ba04296SBram Moolenaar     return 0;
15160ba04296SBram Moolenaar }
15170ba04296SBram Moolenaar 
151855d5c034SBram Moolenaar     static int
151955d5c034SBram Moolenaar luaV_eval(lua_State *L)
152055d5c034SBram Moolenaar {
15210ba04296SBram Moolenaar     typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
15220ba04296SBram Moolenaar     if (tv == NULL) luaL_error(L, "invalid expression");
15230ba04296SBram Moolenaar     luaV_pushtypval(L, tv);
1524b376647bSBram Moolenaar     free_tv(tv);
15250ba04296SBram Moolenaar     return 1;
15260ba04296SBram Moolenaar }
15270ba04296SBram Moolenaar 
152855d5c034SBram Moolenaar     static int
15290d2e4fceSBram Moolenaar luaV_beep(lua_State *L UNUSED)
153055d5c034SBram Moolenaar {
1531165bc69dSBram Moolenaar     vim_beep(BO_LANG);
15320ba04296SBram Moolenaar     return 0;
15330ba04296SBram Moolenaar }
15340ba04296SBram Moolenaar 
153555d5c034SBram Moolenaar     static int
153655d5c034SBram Moolenaar luaV_line(lua_State *L)
153755d5c034SBram Moolenaar {
15380ba04296SBram Moolenaar     luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
15390ba04296SBram Moolenaar     return 1;
15400ba04296SBram Moolenaar }
15410ba04296SBram Moolenaar 
154255d5c034SBram Moolenaar     static int
15431dced572SBram Moolenaar luaV_list(lua_State *L)
15441dced572SBram Moolenaar {
1545ca06da92SBram Moolenaar     list_T *l;
1546ca06da92SBram Moolenaar     int initarg = !lua_isnoneornil(L, 1);
1547ca06da92SBram Moolenaar 
1548ca06da92SBram Moolenaar     if (initarg && lua_type(L, 1) != LUA_TTABLE)
1549ca06da92SBram Moolenaar 	luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1550ca06da92SBram Moolenaar     l = list_alloc();
15511dced572SBram Moolenaar     if (l == NULL)
15521dced572SBram Moolenaar 	lua_pushnil(L);
15531dced572SBram Moolenaar     else
1554ca06da92SBram Moolenaar     {
15551dced572SBram Moolenaar 	luaV_newlist(L, l);
155617413671SBram Moolenaar 	if (initarg) /* traverse table to init list */
155717413671SBram Moolenaar 	{
1558ca06da92SBram Moolenaar 	    int notnil, i = 0;
1559ca06da92SBram Moolenaar 	    typval_T v;
156017413671SBram Moolenaar 	    do
156117413671SBram Moolenaar 	    {
1562ca06da92SBram Moolenaar 		lua_rawgeti(L, 1, ++i);
1563ca06da92SBram Moolenaar 		notnil = !lua_isnil(L, -1);
156417413671SBram Moolenaar 		if (notnil)
156517413671SBram Moolenaar 		{
1566ca06da92SBram Moolenaar 		    luaV_checktypval(L, -1, &v, "vim.list");
1567ca06da92SBram Moolenaar 		    list_append_tv(l, &v);
1568713bf9e9SBram Moolenaar 		    clear_tv(&v);
1569ca06da92SBram Moolenaar 		}
1570ca06da92SBram Moolenaar 		lua_pop(L, 1); /* value */
1571ca06da92SBram Moolenaar 	    } while (notnil);
1572ca06da92SBram Moolenaar 	}
1573ca06da92SBram Moolenaar     }
15741dced572SBram Moolenaar     return 1;
15751dced572SBram Moolenaar }
15761dced572SBram Moolenaar 
15771dced572SBram Moolenaar     static int
15781dced572SBram Moolenaar luaV_dict(lua_State *L)
15791dced572SBram Moolenaar {
1580ca06da92SBram Moolenaar     dict_T *d;
1581ca06da92SBram Moolenaar     int initarg = !lua_isnoneornil(L, 1);
1582ca06da92SBram Moolenaar 
1583ca06da92SBram Moolenaar     if (initarg && lua_type(L, 1) != LUA_TTABLE)
1584ca06da92SBram Moolenaar 	luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1585ca06da92SBram Moolenaar     d = dict_alloc();
15861dced572SBram Moolenaar     if (d == NULL)
15871dced572SBram Moolenaar 	lua_pushnil(L);
15881dced572SBram Moolenaar     else
1589ca06da92SBram Moolenaar     {
15901dced572SBram Moolenaar 	luaV_newdict(L, d);
1591ca06da92SBram Moolenaar 	if (initarg) /* traverse table to init dict */
1592ca06da92SBram Moolenaar 	{
1593ca06da92SBram Moolenaar 	    lua_pushnil(L);
1594ca06da92SBram Moolenaar 	    while (lua_next(L, 1))
1595ca06da92SBram Moolenaar 	    {
1596ca06da92SBram Moolenaar 		char_u *key;
1597ca06da92SBram Moolenaar 		dictitem_T *di;
1598ca06da92SBram Moolenaar 		typval_T v;
1599d6ef5f9bSBram Moolenaar 
1600ca06da92SBram Moolenaar 		lua_pushvalue(L, -2); /* dup key in case it's a number */
1601ca06da92SBram Moolenaar 		key = (char_u *) lua_tostring(L, -1);
1602d6ef5f9bSBram Moolenaar 		if (key == NULL)
1603d6ef5f9bSBram Moolenaar 		{
1604d6ef5f9bSBram Moolenaar 		    lua_pushnil(L);
1605d6ef5f9bSBram Moolenaar 		    return 1;
1606d6ef5f9bSBram Moolenaar 		}
1607d6ef5f9bSBram Moolenaar 		if (*key == NUL)
1608ca06da92SBram Moolenaar 		    luaL_error(L, "table has empty key");
1609ca06da92SBram Moolenaar 		luaV_checktypval(L, -2, &v, "vim.dict"); /* value */
1610ca06da92SBram Moolenaar 		di = dictitem_alloc(key);
1611d6ef5f9bSBram Moolenaar 		if (di == NULL || dict_add(d, di) == FAIL)
1612d6ef5f9bSBram Moolenaar 		{
1613ca06da92SBram Moolenaar 		    vim_free(di);
1614ca06da92SBram Moolenaar 		    lua_pushnil(L);
1615ca06da92SBram Moolenaar 		    return 1;
1616ca06da92SBram Moolenaar 		}
1617ca06da92SBram Moolenaar 		copy_tv(&v, &di->di_tv);
1618ca06da92SBram Moolenaar 		clear_tv(&v);
1619ca06da92SBram Moolenaar 		lua_pop(L, 2); /* key copy and value */
1620ca06da92SBram Moolenaar 	    }
1621ca06da92SBram Moolenaar 	}
1622ca06da92SBram Moolenaar     }
1623ca06da92SBram Moolenaar     return 1;
1624ca06da92SBram Moolenaar }
1625ca06da92SBram Moolenaar 
1626ca06da92SBram Moolenaar     static int
1627ca06da92SBram Moolenaar luaV_funcref(lua_State *L)
1628ca06da92SBram Moolenaar {
1629ca06da92SBram Moolenaar     const char *name = luaL_checkstring(L, 1);
1630ca06da92SBram Moolenaar     /* note: not checking if function exists (needs function_exists) */
1631ca06da92SBram Moolenaar     if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
1632ca06da92SBram Moolenaar 	luaL_error(L, "invalid function name: %s", name);
1633ca06da92SBram Moolenaar     luaV_newfuncref(L, (char_u *) name);
16341dced572SBram Moolenaar     return 1;
16351dced572SBram Moolenaar }
16361dced572SBram Moolenaar 
16371dced572SBram Moolenaar     static int
163855d5c034SBram Moolenaar luaV_buffer(lua_State *L)
163955d5c034SBram Moolenaar {
16400ba04296SBram Moolenaar     buf_T *buf;
164155d5c034SBram Moolenaar     if (lua_isstring(L, 1)) /* get by number or name? */
164255d5c034SBram Moolenaar     {
164355d5c034SBram Moolenaar 	if (lua_isnumber(L, 1)) /* by number? */
164455d5c034SBram Moolenaar 	{
16450ba04296SBram Moolenaar 	    int n = lua_tointeger(L, 1);
164629323590SBram Moolenaar 	    FOR_ALL_BUFFERS(buf)
16470ba04296SBram Moolenaar 		if (buf->b_fnum == n) break;
16480ba04296SBram Moolenaar 	}
1649ca06da92SBram Moolenaar 	else // by name
1650ca06da92SBram Moolenaar 	{
16510ba04296SBram Moolenaar 	    size_t l;
16520ba04296SBram Moolenaar 	    const char *s = lua_tolstring(L, 1, &l);
165329323590SBram Moolenaar 	    FOR_ALL_BUFFERS(buf)
165455d5c034SBram Moolenaar 	    {
165555d5c034SBram Moolenaar 		if (buf->b_ffname == NULL || buf->b_sfname == NULL)
165655d5c034SBram Moolenaar 		{
16570ba04296SBram Moolenaar 		    if (l == 0) break;
16580ba04296SBram Moolenaar 		}
16590d2e4fceSBram Moolenaar 		else if (strncmp(s, (char *)buf->b_ffname, l) == 0
16600d2e4fceSBram Moolenaar 			|| strncmp(s, (char *)buf->b_sfname, l) == 0)
16610ba04296SBram Moolenaar 		    break;
16620ba04296SBram Moolenaar 	    }
16630ba04296SBram Moolenaar 	}
16640ba04296SBram Moolenaar     }
16651dced572SBram Moolenaar     else
16660ba04296SBram Moolenaar 	buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
16670ba04296SBram Moolenaar     luaV_pushbuffer(L, buf);
16680ba04296SBram Moolenaar     return 1;
16690ba04296SBram Moolenaar }
16700ba04296SBram Moolenaar 
167155d5c034SBram Moolenaar     static int
167255d5c034SBram Moolenaar luaV_window(lua_State *L)
167355d5c034SBram Moolenaar {
16740ba04296SBram Moolenaar     win_T *win;
167555d5c034SBram Moolenaar     if (lua_isnumber(L, 1)) /* get by number? */
167655d5c034SBram Moolenaar     {
16770ba04296SBram Moolenaar 	int n = lua_tointeger(L, 1);
16780ba04296SBram Moolenaar 	for (win = firstwin; win != NULL; win = win->w_next, n--)
16790ba04296SBram Moolenaar 	    if (n == 1) break;
16800ba04296SBram Moolenaar     }
16811dced572SBram Moolenaar     else
16820ba04296SBram Moolenaar 	win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
16830ba04296SBram Moolenaar     luaV_pushwindow(L, win);
16840ba04296SBram Moolenaar     return 1;
16850ba04296SBram Moolenaar }
16860ba04296SBram Moolenaar 
168755d5c034SBram Moolenaar     static int
168855d5c034SBram Moolenaar luaV_open(lua_State *L)
168955d5c034SBram Moolenaar {
16900ba04296SBram Moolenaar     char_u *s = NULL;
16910ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
16920ba04296SBram Moolenaar     luaV_checksandbox(L);
16930ba04296SBram Moolenaar #endif
16940ba04296SBram Moolenaar     if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
1695fa263a51SBram Moolenaar     luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
16960ba04296SBram Moolenaar     return 1;
16970ba04296SBram Moolenaar }
16980ba04296SBram Moolenaar 
169955d5c034SBram Moolenaar     static int
17001dced572SBram Moolenaar luaV_type(lua_State *L)
170155d5c034SBram Moolenaar {
17021dced572SBram Moolenaar     luaL_checkany(L, 1);
17031dced572SBram Moolenaar     if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */
17041dced572SBram Moolenaar     {
17051dced572SBram Moolenaar 	lua_settop(L, 1);
17061dced572SBram Moolenaar 	if (lua_getmetatable(L, 1))
17071dced572SBram Moolenaar 	{
17081dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_LIST);
17091dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
17101dced572SBram Moolenaar 	    {
17111dced572SBram Moolenaar 		lua_pushstring(L, "list");
17120ba04296SBram Moolenaar 		return 1;
17130ba04296SBram Moolenaar 	    }
17141dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_DICT);
17151dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
171655d5c034SBram Moolenaar 	    {
17171dced572SBram Moolenaar 		lua_pushstring(L, "dict");
17180ba04296SBram Moolenaar 		return 1;
17190ba04296SBram Moolenaar 	    }
1720ca06da92SBram Moolenaar 	    luaV_getfield(L, LUAVIM_FUNCREF);
1721ca06da92SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
1722ca06da92SBram Moolenaar 	    {
1723ca06da92SBram Moolenaar 		lua_pushstring(L, "funcref");
1724ca06da92SBram Moolenaar 		return 1;
1725ca06da92SBram Moolenaar 	    }
17261dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_BUFFER);
17271dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
172855d5c034SBram Moolenaar 	    {
17291dced572SBram Moolenaar 		lua_pushstring(L, "buffer");
17301dced572SBram Moolenaar 		return 1;
17310ba04296SBram Moolenaar 	    }
17321dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_WINDOW);
17331dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
17341dced572SBram Moolenaar 	    {
17351dced572SBram Moolenaar 		lua_pushstring(L, "window");
17361dced572SBram Moolenaar 		return 1;
17371dced572SBram Moolenaar 	    }
17381dced572SBram Moolenaar 	}
17391dced572SBram Moolenaar     }
17401dced572SBram Moolenaar     lua_pushstring(L, luaL_typename(L, 1)); /* fallback */
17411dced572SBram Moolenaar     return 1;
17420ba04296SBram Moolenaar }
17430ba04296SBram Moolenaar 
17440ba04296SBram Moolenaar static const luaL_Reg luaV_module[] = {
17450ba04296SBram Moolenaar     {"command", luaV_command},
17460ba04296SBram Moolenaar     {"eval", luaV_eval},
17470ba04296SBram Moolenaar     {"beep", luaV_beep},
17480ba04296SBram Moolenaar     {"line", luaV_line},
17491dced572SBram Moolenaar     {"list", luaV_list},
17501dced572SBram Moolenaar     {"dict", luaV_dict},
1751ca06da92SBram Moolenaar     {"funcref", luaV_funcref},
17520ba04296SBram Moolenaar     {"buffer", luaV_buffer},
17530ba04296SBram Moolenaar     {"window", luaV_window},
17540ba04296SBram Moolenaar     {"open", luaV_open},
17551dced572SBram Moolenaar     {"type", luaV_type},
17560ba04296SBram Moolenaar     {NULL, NULL}
17570ba04296SBram Moolenaar };
17580ba04296SBram Moolenaar 
17591dced572SBram Moolenaar /* for freeing list, dict, buffer and window objects; lightuserdata as arg */
17601dced572SBram Moolenaar     static int
17611dced572SBram Moolenaar luaV_free(lua_State *L)
17621dced572SBram Moolenaar {
17631dced572SBram Moolenaar     lua_pushnil(L);
17641dced572SBram Moolenaar     luaV_setudata(L, lua_touserdata(L, 1));
17651dced572SBram Moolenaar     return 0;
17661dced572SBram Moolenaar }
17671dced572SBram Moolenaar 
17681dced572SBram Moolenaar     static int
17691dced572SBram Moolenaar luaV_luaeval(lua_State *L)
17701dced572SBram Moolenaar {
17711dced572SBram Moolenaar     luaL_Buffer b;
17721dced572SBram Moolenaar     size_t l;
17731dced572SBram Moolenaar     const char *str = lua_tolstring(L, 1, &l);
17741dced572SBram Moolenaar     typval_T *arg = (typval_T *) lua_touserdata(L, 2);
17751dced572SBram Moolenaar     typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
17761dced572SBram Moolenaar     luaL_buffinit(L, &b);
17771dced572SBram Moolenaar     luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
17781dced572SBram Moolenaar     luaL_addlstring(&b, str, l);
17791dced572SBram Moolenaar     luaL_pushresult(&b);
17801dced572SBram Moolenaar     str = lua_tolstring(L, -1, &l);
17811dced572SBram Moolenaar     if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */
17821dced572SBram Moolenaar     {
17831dced572SBram Moolenaar 	luaV_emsg(L);
17841dced572SBram Moolenaar 	return 0;
17851dced572SBram Moolenaar     }
17861dced572SBram Moolenaar     luaV_pushtypval(L, arg);
17871dced572SBram Moolenaar     if (lua_pcall(L, 1, 1, 0)) /* running error? */
17881dced572SBram Moolenaar     {
17891dced572SBram Moolenaar 	luaV_emsg(L);
17901dced572SBram Moolenaar 	return 0;
17911dced572SBram Moolenaar     }
1792ca06da92SBram Moolenaar     if (luaV_totypval(L, -1, rettv) == FAIL)
1793f9e3e09fSBram Moolenaar 	emsg("luaeval: cannot convert value");
1794f554a328SBram Moolenaar     return 0;
17951dced572SBram Moolenaar }
17961dced572SBram Moolenaar 
17971dced572SBram Moolenaar     static int
17981dced572SBram Moolenaar luaV_setref(lua_State *L)
17991dced572SBram Moolenaar {
18001dced572SBram Moolenaar     int copyID = lua_tointeger(L, 1);
18012459a5ecSBram Moolenaar     int abort = FALSE;
18022459a5ecSBram Moolenaar 
18031dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LIST);
18041dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_DICT);
1805*4eefe47eSBram Moolenaar     luaV_getfield(L, LUAVIM_FUNCREF);
18061dced572SBram Moolenaar     lua_pushnil(L);
1807*4eefe47eSBram Moolenaar     // traverse cache table
1808b84634deSBram Moolenaar     while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
18091dced572SBram Moolenaar     {
18101dced572SBram Moolenaar 	lua_getmetatable(L, -1);
1811*4eefe47eSBram Moolenaar 	if (lua_rawequal(L, -1, 2)) // list?
18121dced572SBram Moolenaar 	{
1813*4eefe47eSBram Moolenaar 	    list_T *l = (list_T *)lua_touserdata(L, 5); // key
1814*4eefe47eSBram Moolenaar 
1815*4eefe47eSBram Moolenaar 	    if (l->lv_copyID != copyID)
18161dced572SBram Moolenaar 	    {
1817*4eefe47eSBram Moolenaar 		l->lv_copyID = copyID;
1818*4eefe47eSBram Moolenaar 		abort = set_ref_in_list(l, copyID, NULL);
18191dced572SBram Moolenaar 	    }
1820*4eefe47eSBram Moolenaar 	}
1821*4eefe47eSBram Moolenaar 	else if (lua_rawequal(L, -1, 3)) // dict?
1822*4eefe47eSBram Moolenaar 	{
1823*4eefe47eSBram Moolenaar 	    dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
1824*4eefe47eSBram Moolenaar 
1825*4eefe47eSBram Moolenaar 	    if (d->dv_copyID != copyID)
1826*4eefe47eSBram Moolenaar 	    {
1827*4eefe47eSBram Moolenaar 		d->dv_copyID = copyID;
1828*4eefe47eSBram Moolenaar 		abort = set_ref_in_ht(&d->dv_hashtab, copyID, NULL);
1829*4eefe47eSBram Moolenaar 	    }
1830*4eefe47eSBram Moolenaar 	}
1831*4eefe47eSBram Moolenaar 	else if (lua_rawequal(L, -1, 4)) // funcref?
1832*4eefe47eSBram Moolenaar 	{
1833*4eefe47eSBram Moolenaar 	    luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
1834*4eefe47eSBram Moolenaar 
1835*4eefe47eSBram Moolenaar 	    if (f->self != NULL && f->self->dv_copyID != copyID)
1836*4eefe47eSBram Moolenaar 	    {
1837*4eefe47eSBram Moolenaar 		f->self->dv_copyID = copyID;
1838*4eefe47eSBram Moolenaar 		abort = set_ref_in_ht(&f->self->dv_hashtab, copyID, NULL);
1839*4eefe47eSBram Moolenaar 	    }
1840*4eefe47eSBram Moolenaar 	}
1841*4eefe47eSBram Moolenaar 	lua_pop(L, 2); // metatable and value
18421dced572SBram Moolenaar     }
18432459a5ecSBram Moolenaar     lua_pushinteger(L, abort);
1844f554a328SBram Moolenaar     return 1;
18451dced572SBram Moolenaar }
18461dced572SBram Moolenaar 
184755d5c034SBram Moolenaar     static int
184855d5c034SBram Moolenaar luaopen_vim(lua_State *L)
184955d5c034SBram Moolenaar {
18501dced572SBram Moolenaar     /* set cache table */
18510ba04296SBram Moolenaar     lua_newtable(L);
18520ba04296SBram Moolenaar     lua_newtable(L);
18531dced572SBram Moolenaar     lua_pushstring(L, "v");
18540ba04296SBram Moolenaar     lua_setfield(L, -2, "__mode");
18551dced572SBram Moolenaar     lua_setmetatable(L, -2); /* cache is weak-valued */
18560ba04296SBram Moolenaar     /* print */
18570ba04296SBram Moolenaar     lua_pushcfunction(L, luaV_print);
18580ba04296SBram Moolenaar     lua_setglobal(L, "print");
185938e2b063SBram Moolenaar     /* debug.debug */
186038e2b063SBram Moolenaar     lua_getglobal(L, "debug");
186138e2b063SBram Moolenaar     lua_pushcfunction(L, luaV_debug);
186238e2b063SBram Moolenaar     lua_setfield(L, -2, "debug");
186338e2b063SBram Moolenaar     lua_pop(L, 1);
18640ba04296SBram Moolenaar     /* free */
18650ba04296SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
18661dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18671dced572SBram Moolenaar     lua_pushcclosure(L, luaV_free, 1);
18681dced572SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
18691dced572SBram Moolenaar     /* luaeval */
18701dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
18711dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18721dced572SBram Moolenaar     lua_pushcclosure(L, luaV_luaeval, 1);
18731dced572SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
18741dced572SBram Moolenaar     /* setref */
18751dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
18761dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18771dced572SBram Moolenaar     lua_pushcclosure(L, luaV_setref, 1);
18780ba04296SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
18790ba04296SBram Moolenaar     /* register */
18801dced572SBram Moolenaar     luaV_newmetatable(L, LUAVIM_LIST);
18811dced572SBram Moolenaar     lua_pushvalue(L, 1);
18821dced572SBram Moolenaar     luaV_openlib(L, luaV_List_mt, 1);
18831dced572SBram Moolenaar     luaV_newmetatable(L, LUAVIM_DICT);
18841dced572SBram Moolenaar     lua_pushvalue(L, 1);
18851dced572SBram Moolenaar     luaV_openlib(L, luaV_Dict_mt, 1);
1886ca06da92SBram Moolenaar     luaV_newmetatable(L, LUAVIM_FUNCREF);
1887ca06da92SBram Moolenaar     lua_pushvalue(L, 1);
1888ca06da92SBram Moolenaar     luaV_openlib(L, luaV_Funcref_mt, 1);
18890ba04296SBram Moolenaar     luaV_newmetatable(L, LUAVIM_BUFFER);
18901dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18911dced572SBram Moolenaar     luaV_openlib(L, luaV_Buffer_mt, 1);
18920ba04296SBram Moolenaar     luaV_newmetatable(L, LUAVIM_WINDOW);
18931dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18941dced572SBram Moolenaar     luaV_openlib(L, luaV_Window_mt, 1);
18951dced572SBram Moolenaar     lua_newtable(L); /* vim table */
18961dced572SBram Moolenaar     lua_pushvalue(L, 1); /* cache table */
18971dced572SBram Moolenaar     luaV_openlib(L, luaV_module, 1);
18981dced572SBram Moolenaar     lua_setglobal(L, LUAVIM_NAME);
18990ba04296SBram Moolenaar     return 0;
19000ba04296SBram Moolenaar }
19010ba04296SBram Moolenaar 
190255d5c034SBram Moolenaar     static lua_State *
190355d5c034SBram Moolenaar luaV_newstate(void)
190455d5c034SBram Moolenaar {
19050ba04296SBram Moolenaar     lua_State *L = luaL_newstate();
190616c98f9cSBram Moolenaar     luaL_openlibs(L); /* core libs */
190716c98f9cSBram Moolenaar     lua_pushcfunction(L, luaopen_vim); /* vim */
19080ba04296SBram Moolenaar     lua_call(L, 0, 0);
19090ba04296SBram Moolenaar     return L;
19100ba04296SBram Moolenaar }
19110ba04296SBram Moolenaar 
191255d5c034SBram Moolenaar     static void
191355d5c034SBram Moolenaar luaV_setrange(lua_State *L, int line1, int line2)
191455d5c034SBram Moolenaar {
19150ba04296SBram Moolenaar     lua_getglobal(L, LUAVIM_NAME);
19160ba04296SBram Moolenaar     lua_pushinteger(L, line1);
19170ba04296SBram Moolenaar     lua_setfield(L, -2, "firstline");
19180ba04296SBram Moolenaar     lua_pushinteger(L, line2);
19190ba04296SBram Moolenaar     lua_setfield(L, -2, "lastline");
19200ba04296SBram Moolenaar     lua_pop(L, 1); /* vim table */
19210ba04296SBram Moolenaar }
19220ba04296SBram Moolenaar 
19230ba04296SBram Moolenaar 
19240ba04296SBram Moolenaar /* =======   Interface   ======= */
19250ba04296SBram Moolenaar 
19260ba04296SBram Moolenaar static lua_State *L = NULL;
19270ba04296SBram Moolenaar 
192855d5c034SBram Moolenaar     static int
19291dced572SBram Moolenaar lua_isopen(void)
19302bd6a1b5SBram Moolenaar {
19312bd6a1b5SBram Moolenaar     return L != NULL;
19322bd6a1b5SBram Moolenaar }
19332bd6a1b5SBram Moolenaar 
19342bd6a1b5SBram Moolenaar     static int
193555d5c034SBram Moolenaar lua_init(void)
193655d5c034SBram Moolenaar {
19371dced572SBram Moolenaar     if (!lua_isopen())
193855d5c034SBram Moolenaar     {
19390ba04296SBram Moolenaar #ifdef DYNAMIC_LUA
194055d5c034SBram Moolenaar 	if (!lua_enabled(TRUE))
194155d5c034SBram Moolenaar 	{
1942f9e3e09fSBram Moolenaar 	    emsg(_("Lua library cannot be loaded."));
19430ba04296SBram Moolenaar 	    return FAIL;
19440ba04296SBram Moolenaar 	}
19450ba04296SBram Moolenaar #endif
19460ba04296SBram Moolenaar 	L = luaV_newstate();
19470ba04296SBram Moolenaar     }
19480ba04296SBram Moolenaar     return OK;
19490ba04296SBram Moolenaar }
19500ba04296SBram Moolenaar 
195155d5c034SBram Moolenaar     void
195255d5c034SBram Moolenaar lua_end(void)
195355d5c034SBram Moolenaar {
19541dced572SBram Moolenaar     if (lua_isopen())
195555d5c034SBram Moolenaar     {
19560ba04296SBram Moolenaar 	lua_close(L);
19570ba04296SBram Moolenaar 	L = NULL;
19580ba04296SBram Moolenaar #ifdef DYNAMIC_LUA
19590ba04296SBram Moolenaar 	end_dynamic_lua();
19600ba04296SBram Moolenaar #endif
19610ba04296SBram Moolenaar     }
19620ba04296SBram Moolenaar }
19630ba04296SBram Moolenaar 
19640ba04296SBram Moolenaar /* ex commands */
196555d5c034SBram Moolenaar     void
196655d5c034SBram Moolenaar ex_lua(exarg_T *eap)
196755d5c034SBram Moolenaar {
19680ba04296SBram Moolenaar     char *script;
19690ba04296SBram Moolenaar     if (lua_init() == FAIL) return;
19700ba04296SBram Moolenaar     script = (char *) script_get(eap, eap->arg);
197155d5c034SBram Moolenaar     if (!eap->skip)
197255d5c034SBram Moolenaar     {
19730ba04296SBram Moolenaar 	char *s = (script) ? script :  (char *) eap->arg;
19740ba04296SBram Moolenaar 	luaV_setrange(L, eap->line1, eap->line2);
19750ba04296SBram Moolenaar 	if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
19760ba04296SBram Moolenaar 		|| lua_pcall(L, 0, 0, 0))
19770ba04296SBram Moolenaar 	    luaV_emsg(L);
19780ba04296SBram Moolenaar     }
19790ba04296SBram Moolenaar     if (script != NULL) vim_free(script);
19800ba04296SBram Moolenaar }
19810ba04296SBram Moolenaar 
198255d5c034SBram Moolenaar     void
198355d5c034SBram Moolenaar ex_luado(exarg_T *eap)
198455d5c034SBram Moolenaar {
19850ba04296SBram Moolenaar     linenr_T l;
19860ba04296SBram Moolenaar     const char *s = (const char *) eap->arg;
19870ba04296SBram Moolenaar     luaL_Buffer b;
19880ba04296SBram Moolenaar     size_t len;
1989d58f03b1SBram Moolenaar     buf_T *was_curbuf = curbuf;
1990d58f03b1SBram Moolenaar 
19910ba04296SBram Moolenaar     if (lua_init() == FAIL) return;
199255d5c034SBram Moolenaar     if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
199355d5c034SBram Moolenaar     {
1994f9e3e09fSBram Moolenaar 	emsg(_("cannot save undo information"));
19950ba04296SBram Moolenaar 	return;
19960ba04296SBram Moolenaar     }
19970ba04296SBram Moolenaar     luaV_setrange(L, eap->line1, eap->line2);
19980ba04296SBram Moolenaar     luaL_buffinit(L, &b);
1999bd2f3c3eSBram Moolenaar     luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */
20000ba04296SBram Moolenaar     luaL_addlstring(&b, s, strlen(s));
20010ba04296SBram Moolenaar     luaL_addlstring(&b, " end", 4); /* footer */
20020ba04296SBram Moolenaar     luaL_pushresult(&b);
20030ba04296SBram Moolenaar     s = lua_tolstring(L, -1, &len);
200455d5c034SBram Moolenaar     if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
200555d5c034SBram Moolenaar     {
20060ba04296SBram Moolenaar 	luaV_emsg(L);
20070ba04296SBram Moolenaar 	lua_pop(L, 1); /* function body */
20080ba04296SBram Moolenaar 	return;
20090ba04296SBram Moolenaar     }
20100ba04296SBram Moolenaar     lua_call(L, 0, 1);
20110ba04296SBram Moolenaar     lua_replace(L, -2); /* function -> body */
201255d5c034SBram Moolenaar     for (l = eap->line1; l <= eap->line2; l++)
201355d5c034SBram Moolenaar     {
2014d58f03b1SBram Moolenaar 	/* Check the line number, the command my have deleted lines. */
2015d58f03b1SBram Moolenaar 	if (l > curbuf->b_ml.ml_line_count)
2016d58f03b1SBram Moolenaar 	    break;
2017d58f03b1SBram Moolenaar 
20180ba04296SBram Moolenaar 	lua_pushvalue(L, -1); /* function */
20190ba04296SBram Moolenaar 	luaV_pushline(L, curbuf, l); /* current line as arg */
2020bd2f3c3eSBram Moolenaar 	lua_pushinteger(L, l); /* current line number as arg */
2021bd2f3c3eSBram Moolenaar 	if (lua_pcall(L, 2, 1, 0))
202255d5c034SBram Moolenaar 	{
20230ba04296SBram Moolenaar 	    luaV_emsg(L);
20240ba04296SBram Moolenaar 	    break;
20250ba04296SBram Moolenaar 	}
2026d58f03b1SBram Moolenaar 	/* Catch the command switching to another buffer. */
2027d58f03b1SBram Moolenaar 	if (curbuf != was_curbuf)
2028d58f03b1SBram Moolenaar 	    break;
202955d5c034SBram Moolenaar 	if (lua_isstring(L, -1)) /* update line? */
203055d5c034SBram Moolenaar 	{
20310ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
20320ba04296SBram Moolenaar 	    luaV_checksandbox(L);
20330ba04296SBram Moolenaar #endif
20340ba04296SBram Moolenaar 	    ml_replace(l, luaV_toline(L, -1), TRUE);
20350ba04296SBram Moolenaar 	    changed_bytes(l, 0);
20360ba04296SBram Moolenaar 	    lua_pop(L, 1); /* result from luaV_toline */
20370ba04296SBram Moolenaar 	}
20380ba04296SBram Moolenaar 	lua_pop(L, 1); /* line */
20390ba04296SBram Moolenaar     }
20400ba04296SBram Moolenaar     lua_pop(L, 1); /* function */
20410ba04296SBram Moolenaar     check_cursor();
20420ba04296SBram Moolenaar     update_screen(NOT_VALID);
20430ba04296SBram Moolenaar }
20440ba04296SBram Moolenaar 
204555d5c034SBram Moolenaar     void
204655d5c034SBram Moolenaar ex_luafile(exarg_T *eap)
204755d5c034SBram Moolenaar {
204855d5c034SBram Moolenaar     if (lua_init() == FAIL)
204955d5c034SBram Moolenaar 	return;
205055d5c034SBram Moolenaar     if (!eap->skip)
205155d5c034SBram Moolenaar     {
20520ba04296SBram Moolenaar 	luaV_setrange(L, eap->line1, eap->line2);
20530ba04296SBram Moolenaar 	if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
20540ba04296SBram Moolenaar 	    luaV_emsg(L);
20550ba04296SBram Moolenaar     }
20560ba04296SBram Moolenaar }
20570ba04296SBram Moolenaar 
20581dced572SBram Moolenaar #define luaV_freetype(typ,tname) \
20591dced572SBram Moolenaar 	void \
20601dced572SBram Moolenaar     lua_##tname##_free(typ *o) \
20611dced572SBram Moolenaar     { \
20621dced572SBram Moolenaar 	if (!lua_isopen()) return; \
20631dced572SBram Moolenaar 	luaV_getfield(L, LUAVIM_FREE); \
20641dced572SBram Moolenaar 	lua_pushlightuserdata(L, (void *) o); \
20651dced572SBram Moolenaar 	lua_call(L, 1, 0); \
20660ba04296SBram Moolenaar     }
20670ba04296SBram Moolenaar 
20681dced572SBram Moolenaar luaV_freetype(buf_T, buffer)
20691dced572SBram Moolenaar luaV_freetype(win_T, window)
20701dced572SBram Moolenaar 
207155d5c034SBram Moolenaar     void
20721dced572SBram Moolenaar do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
207355d5c034SBram Moolenaar {
20741dced572SBram Moolenaar     lua_init();
20751dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LUAEVAL);
20761dced572SBram Moolenaar     lua_pushstring(L, (char *) str);
20771dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) arg);
20781dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) rettv);
20791dced572SBram Moolenaar     lua_call(L, 3, 0);
20801dced572SBram Moolenaar }
20811dced572SBram Moolenaar 
20822459a5ecSBram Moolenaar     int
20831dced572SBram Moolenaar set_ref_in_lua(int copyID)
20841dced572SBram Moolenaar {
20852459a5ecSBram Moolenaar     int aborted = 0;
20862459a5ecSBram Moolenaar 
20872459a5ecSBram Moolenaar     if (lua_isopen())
20882459a5ecSBram Moolenaar     {
20891dced572SBram Moolenaar 	luaV_getfield(L, LUAVIM_SETREF);
20902459a5ecSBram Moolenaar 	/* call the function with 1 arg, getting 1 result back */
20911dced572SBram Moolenaar 	lua_pushinteger(L, copyID);
20922459a5ecSBram Moolenaar 	lua_call(L, 1, 1);
20932459a5ecSBram Moolenaar 	/* get the result */
20942459a5ecSBram Moolenaar 	aborted = lua_tointeger(L, -1);
20952459a5ecSBram Moolenaar 	/* pop result off the stack */
20962459a5ecSBram Moolenaar 	lua_pop(L, 1);
20972459a5ecSBram Moolenaar     }
20982459a5ecSBram Moolenaar     return aborted;
20990ba04296SBram Moolenaar }
21000ba04296SBram Moolenaar 
21010ba04296SBram Moolenaar #endif
2102