summaryrefslogtreecommitdiff
path: root/source/ap/vim/patches/7.3.490
diff options
context:
space:
mode:
Diffstat (limited to 'source/ap/vim/patches/7.3.490')
-rw-r--r--source/ap/vim/patches/7.3.4902517
1 files changed, 2517 insertions, 0 deletions
diff --git a/source/ap/vim/patches/7.3.490 b/source/ap/vim/patches/7.3.490
new file mode 100644
index 00000000..6c49a48d
--- /dev/null
+++ b/source/ap/vim/patches/7.3.490
@@ -0,0 +1,2517 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.490
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.490
+Problem: Member confusion in Lua interface.
+Solution: Fix it. Add luaeval(). (Taro Muraoka, Luis Carvalho)
+Files: runtime/doc/if_lua.txt, src/eval.c, src/if_lua.c,
+ src/proto/if_lua.pro
+
+
+*** ../vim-7.3.489/runtime/doc/if_lua.txt 2010-08-15 21:57:14.000000000 +0200
+--- runtime/doc/if_lua.txt 2012-04-05 16:41:35.000000000 +0200
+***************
+*** 1,4 ****
+! *if_lua.txt* For Vim version 7.3. Last change: 2010 Jul 22
+
+
+ VIM REFERENCE MANUAL by Luis Carvalho
+--- 1,4 ----
+! *if_lua.txt* For Vim version 7.3. Last change: 2012 Jan 16
+
+
+ VIM REFERENCE MANUAL by Luis Carvalho
+***************
+*** 8,15 ****
+
+ 1. Commands |lua-commands|
+ 2. The vim module |lua-vim|
+! 3. Buffer userdata |lua-buffer|
+! 4. Window userdata |lua-window|
+
+ {Vi does not have any of these commands}
+
+--- 8,18 ----
+
+ 1. Commands |lua-commands|
+ 2. The vim module |lua-vim|
+! 3. List userdata |lua-list|
+! 4. Dict userdata |lua-dict|
+! 5. Buffer userdata |lua-buffer|
+! 6. Window userdata |lua-window|
+! 7. The luaeval function |lua-luaeval|
+
+ {Vi does not have any of these commands}
+
+***************
+*** 88,98 ****
+ All these commands execute a Lua chunk from either the command line (:lua and
+ :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua
+ interpreter, each chunk has its own scope and so only global variables are
+! shared between command calls. Lua default libraries "table", "string", "math",
+! and "package" are available, "io" and "debug" are not, and "os" is restricted
+! to functions "date", "clock", "time", "difftime", and "getenv". In addition,
+! Lua "print" function has its output redirected to the Vim message area, with
+! arguments separated by a white space instead of a tab.
+
+ Lua uses the "vim" module (see |lua-vim|) to issue commands to Vim
+ and manage buffers (|lua-buffer|) and windows (|lua-window|). However,
+--- 91,99 ----
+ All these commands execute a Lua chunk from either the command line (:lua and
+ :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua
+ interpreter, each chunk has its own scope and so only global variables are
+! shared between command calls. All Lua default libraries are available. In
+! addition, Lua "print" function has its output redirected to the Vim message
+! area, with arguments separated by a white space instead of a tab.
+
+ Lua uses the "vim" module (see |lua-vim|) to issue commands to Vim
+ and manage buffers (|lua-buffer|) and windows (|lua-window|). However,
+***************
+*** 108,116 ****
+ module also includes routines for buffer, window, and current line queries,
+ Vim evaluation and command execution, and others.
+
+! vim.isbuffer(value) Returns 'true' (boolean, not string) if
+! "value" is a buffer userdata and 'false'
+! otherwise (see |lua-buffer|).
+
+ vim.buffer([arg]) If "arg" is a number, returns buffer with
+ number "arg" in the buffer list or, if "arg"
+--- 109,117 ----
+ module also includes routines for buffer, window, and current line queries,
+ Vim evaluation and command execution, and others.
+
+! vim.list() Returns an empty list (see |List|).
+!
+! vim.dict() Returns an empty dictionary (see |Dictionary|).
+
+ vim.buffer([arg]) If "arg" is a number, returns buffer with
+ number "arg" in the buffer list or, if "arg"
+***************
+*** 121,136 ****
+ 'true' returns the first buffer in the buffer
+ list or else the current buffer.
+
+- vim.iswindow(value) Returns 'true' (boolean, not string) if
+- "value" is a window userdata and
+- 'false' otherwise (see |lua-window|).
+-
+ vim.window([arg]) If "arg" is a number, returns window with
+ number "arg" or 'nil' (nil value, not string)
+ if not found. Otherwise, if "toboolean(arg)"
+ is 'true' returns the first window or else the
+ current window.
+
+ vim.command({cmd}) Executes the vim (ex-mode) command {cmd}.
+ Examples: >
+ :lua vim.command"set tw=60"
+--- 122,142 ----
+ 'true' returns the first buffer in the buffer
+ list or else the current buffer.
+
+ vim.window([arg]) If "arg" is a number, returns window with
+ number "arg" or 'nil' (nil value, not string)
+ if not found. Otherwise, if "toboolean(arg)"
+ is 'true' returns the first window or else the
+ current window.
+
++ vim.type({arg}) Returns the type of {arg}. It is equivalent to
++ Lua's "type" function, but returns "list",
++ "dict", "buffer", or "window" if {arg} is a
++ list, dictionary, buffer, or window,
++ respectively. Examples: >
++ :lua l = vim.list()
++ :lua print(type(l), vim.type(l))
++ :" userdata list
++ <
+ vim.command({cmd}) Executes the vim (ex-mode) command {cmd}.
+ Examples: >
+ :lua vim.command"set tw=60"
+***************
+*** 141,147 ****
+ Vim strings and numbers are directly converted
+ to Lua strings and numbers respectively. Vim
+ lists and dictionaries are converted to Lua
+! tables (lists become integer-keyed tables).
+ Examples: >
+ :lua tw = vim.eval"&tw"
+ :lua print(vim.eval"{'a': 'one'}".a)
+--- 147,153 ----
+ Vim strings and numbers are directly converted
+ to Lua strings and numbers respectively. Vim
+ lists and dictionaries are converted to Lua
+! userdata (see |lua-list| and |lua-dict|).
+ Examples: >
+ :lua tw = vim.eval"&tw"
+ :lua print(vim.eval"{'a': 'one'}".a)
+***************
+*** 157,163 ****
+
+
+ ==============================================================================
+! 3. Buffer userdata *lua-buffer*
+
+ Buffer userdata represent vim buffers. A buffer userdata "b" has the following
+ properties and methods:
+--- 163,234 ----
+
+
+ ==============================================================================
+! 3. List userdata *lua-list*
+!
+! List userdata represent vim lists, and the interface tries to follow closely
+! Vim's syntax for lists. Since lists are objects, changes in list references in
+! Lua are reflected in Vim and vice-versa. A list "l" has the following
+! properties and methods:
+!
+! Properties
+! ----------
+! o "#l" is the number of items in list "l", equivalent to "len(l)"
+! in Vim.
+! o "l[k]" returns the k-th item in "l"; "l" is zero-indexed, as in Vim.
+! To modify the k-th item, simply do "l[k] = newitem"; in
+! particular, "l[k] = nil" removes the k-th item from "l".
+! o "l()" returns an iterator for "l".
+!
+! Methods
+! -------
+! o "l:add(item)" appends "item" to the end of "l".
+! o "l:insert(item[, pos])" inserts "item" at (optional)
+! position "pos" in the list. The default value for "pos" is 0.
+!
+! Examples:
+! >
+! :let l = [1, 'item']
+! :lua l = vim.eval('l') -- same 'l'
+! :lua l:add(vim.list())
+! :lua l[0] = math.pi
+! :echo l[0] " 3.141593
+! :lua l[0] = nil -- remove first item
+! :lua l:insert(true, 1)
+! :lua print(l, #l, l[0], l[1], l[-1])
+! :lua for item in l() do print(item) end
+! <
+!
+! ==============================================================================
+! 4. Dict userdata *lua-dict*
+!
+! Similarly to list userdata, dict userdata represent vim dictionaries; since
+! dictionaries are also objects, references are kept between Lua and Vim. A dict
+! "d" has the following properties:
+!
+! Properties
+! ----------
+! o "#d" is the number of items in dict "d", equivalent to "len(d)"
+! in Vim.
+! o "d.key" or "d['key']" returns the value at entry "key" in "d".
+! To modify the entry at this key, simply do "d.key = newvalue"; in
+! particular, "d.key = nil" removes the entry from "d".
+! o "d()" returns an iterator for "d" and is equivalent to "items(d)" in
+! Vim.
+!
+! Examples:
+! >
+! :let d = {'n':10}
+! :lua d = vim.eval('d') -- same 'd'
+! :lua print(d, d.n, #d)
+! :let d.self = d
+! :lua for k, v in d() do print(d, k, v) end
+! :lua d.x = math.pi
+! :lua d.self = nil -- remove entry
+! :echo d
+! <
+!
+! ==============================================================================
+! 5. Buffer userdata *lua-buffer*
+
+ Buffer userdata represent vim buffers. A buffer userdata "b" has the following
+ properties and methods:
+***************
+*** 209,215 ****
+ <
+
+ ==============================================================================
+! 4. Window userdata *lua-window*
+
+ Window objects represent vim windows. A window userdata "w" has the following
+ properties and methods:
+--- 280,286 ----
+ <
+
+ ==============================================================================
+! 6. Window userdata *lua-window*
+
+ Window objects represent vim windows. A window userdata "w" has the following
+ properties and methods:
+***************
+*** 241,244 ****
+ <
+
+ ==============================================================================
+! vim:tw=78:ts=8:ft=help:norl:
+--- 312,340 ----
+ <
+
+ ==============================================================================
+! 7. The luaeval function *lua-luaeval*
+!
+! The (dual) equivalent of "vim.eval" for passing Lua values to Vim is
+! "luaeval". "luaeval" takes an expression string and an optional argument and
+! returns the result of the expression. It is semantically equivalent in Lua to:
+! >
+! local chunkheader = "local _A = select(1, ...) return "
+! function luaeval (expstr, arg)
+! local chunk = assert(loadstring(chunkheader .. expstr, "luaeval"))
+! return chunk(arg) -- return typval
+! end
+! <
+! Note that "_A" receives the argument to "luaeval". Examples: >
+!
+! :echo luaeval('math.pi')
+! :lua a = vim.list():add('newlist')
+! :let a = luaeval('a')
+! :echo a[0] " 'newlist'
+! :function Rand(x,y) " random uniform between x and y
+! : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y})
+! : endfunction
+! :echo Rand(1,10)
+!
+!
+! ==============================================================================
+! vim:tw=78:ts=8:noet:ft=help:norl:
+*** ../vim-7.3.489/src/eval.c 2012-03-28 16:49:25.000000000 +0200
+--- src/eval.c 2012-04-05 16:41:35.000000000 +0200
+***************
+*** 622,627 ****
+--- 622,630 ----
+ static void f_log __ARGS((typval_T *argvars, typval_T *rettv));
+ static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv));
+ #endif
++ #ifdef FEAT_LUA
++ static void f_luaeval __ARGS((typval_T *argvars, typval_T *rettv));
++ #endif
+ static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
+ static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
+ static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
+***************
+*** 6777,6782 ****
+--- 6780,6789 ----
+ /* v: vars */
+ set_ref_in_ht(&vimvarht, copyID);
+
++ #ifdef FEAT_LUA
++ set_ref_in_lua(copyID);
++ #endif
++
+ /*
+ * 2. Free lists and dictionaries that are not referenced.
+ */
+***************
+*** 7946,7951 ****
+--- 7953,7961 ----
+ {"log", 1, 1, f_log},
+ {"log10", 1, 1, f_log10},
+ #endif
++ #ifdef FEAT_LUA
++ {"luaeval", 1, 2, f_luaeval},
++ #endif
+ {"map", 2, 2, f_map},
+ {"maparg", 1, 4, f_maparg},
+ {"mapcheck", 1, 3, f_mapcheck},
+***************
+*** 13626,13631 ****
+--- 13636,13658 ----
+ }
+ #endif
+
++ #ifdef FEAT_LUA
++ /*
++ * "luaeval()" function
++ */
++ static void
++ f_luaeval(argvars, rettv)
++ typval_T *argvars;
++ typval_T *rettv;
++ {
++ char_u *str;
++ char_u buf[NUMBUFLEN];
++
++ str = get_tv_string_buf(&argvars[0], buf);
++ do_luaeval(str, argvars + 1, rettv);
++ }
++ #endif
++
+ /*
+ * "map()" function
+ */
+*** ../vim-7.3.489/src/if_lua.c 2011-12-08 16:00:12.000000000 +0100
+--- src/if_lua.c 2012-04-05 16:41:35.000000000 +0200
+***************
+*** 1,4 ****
+! /* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+--- 1,4 ----
+! /* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+***************
+*** 21,35 ****
+--- 21,53 ----
+
+ #define LUAVIM_CHUNKNAME "vim chunk"
+ #define LUAVIM_NAME "vim"
++ #define LUAVIM_EVALNAME "luaeval"
++ #define LUAVIM_EVALHEADER "local _A=select(1,...) return "
+
+ typedef buf_T *luaV_Buffer;
+ typedef win_T *luaV_Window;
++ typedef dict_T *luaV_Dict;
++ typedef list_T *luaV_List;
+ typedef void (*msgfunc_T)(char_u *);
+
++ static const char LUAVIM_DICT[] = "dict";
++ static const char LUAVIM_LIST[] = "list";
+ static const char LUAVIM_BUFFER[] = "buffer";
+ static const char LUAVIM_WINDOW[] = "window";
+ static const char LUAVIM_FREE[] = "luaV_free";
++ static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
++ static const char LUAVIM_SETREF[] = "luaV_setref";
+
++ /* most functions are closures with a cache table as first upvalue;
++ * get/setudata manage references to vim userdata in cache table through
++ * object pointers (light userdata) */
++ #define luaV_getudata(L, v) \
++ lua_pushlightuserdata((L), (void *) (v)); \
++ lua_rawget((L), lua_upvalueindex(1))
++ #define luaV_setudata(L, v) \
++ lua_pushlightuserdata((L), (void *) (v)); \
++ lua_pushvalue((L), -2); \
++ lua_rawset((L), lua_upvalueindex(1))
+ #define luaV_getfield(L, s) \
+ lua_pushlightuserdata((L), (void *)(s)); \
+ lua_rawget((L), LUA_REGISTRYINDEX)
+***************
+*** 38,43 ****
+--- 56,70 ----
+ #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
+ #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
+
++ static luaV_List *luaV_pushlist (lua_State *L, list_T *lis);
++ static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic);
++
++ #if LUA_VERSION_NUM <= 501
++ #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
++ #define luaL_typeerror luaL_typerror
++ #else
++ #define luaV_openlib luaL_setfuncs
++ #endif
+
+ #ifdef DYNAMIC_LUA
+
+***************
+*** 54,85 ****
+ #endif
+
+ /* lauxlib */
+ #define luaL_register dll_luaL_register
+ #define luaL_typerror dll_luaL_typerror
+ #define luaL_checklstring dll_luaL_checklstring
+ #define luaL_checkinteger dll_luaL_checkinteger
+ #define luaL_optinteger dll_luaL_optinteger
+ #define luaL_checktype dll_luaL_checktype
+ #define luaL_error dll_luaL_error
+- #define luaL_loadfile dll_luaL_loadfile
+- #define luaL_loadbuffer dll_luaL_loadbuffer
+ #define luaL_newstate dll_luaL_newstate
+ #define luaL_buffinit dll_luaL_buffinit
+- #define luaL_prepbuffer dll_luaL_prepbuffer
+ #define luaL_addlstring dll_luaL_addlstring
+ #define luaL_pushresult dll_luaL_pushresult
+ /* lua */
+ #define lua_close dll_lua_close
+ #define lua_gettop dll_lua_gettop
+ #define lua_settop dll_lua_settop
+ #define lua_pushvalue dll_lua_pushvalue
+ #define lua_replace dll_lua_replace
+ #define lua_isnumber dll_lua_isnumber
+ #define lua_isstring dll_lua_isstring
+ #define lua_type dll_lua_type
+ #define lua_rawequal dll_lua_rawequal
+- #define lua_tonumber dll_lua_tonumber
+- #define lua_tointeger dll_lua_tointeger
+ #define lua_toboolean dll_lua_toboolean
+ #define lua_tolstring dll_lua_tolstring
+ #define lua_touserdata dll_lua_touserdata
+--- 81,134 ----
+ #endif
+
+ /* lauxlib */
++ #if LUA_VERSION_NUM <= 501
+ #define luaL_register dll_luaL_register
++ #define luaL_prepbuffer dll_luaL_prepbuffer
++ #define luaL_openlib dll_luaL_openlib
+ #define luaL_typerror dll_luaL_typerror
++ #define luaL_loadfile dll_luaL_loadfile
++ #define luaL_loadbuffer dll_luaL_loadbuffer
++ #else
++ #define luaL_prepbuffsize dll_luaL_prepbuffsize
++ #define luaL_setfuncs dll_luaL_setfuncs
++ #define luaL_loadfilex dll_luaL_loadfilex
++ #define luaL_loadbufferx dll_luaL_loadbufferx
++ #define luaL_argerror dll_luaL_argerror
++ #endif
+ #define luaL_checklstring dll_luaL_checklstring
+ #define luaL_checkinteger dll_luaL_checkinteger
+ #define luaL_optinteger dll_luaL_optinteger
+ #define luaL_checktype dll_luaL_checktype
+ #define luaL_error dll_luaL_error
+ #define luaL_newstate dll_luaL_newstate
+ #define luaL_buffinit dll_luaL_buffinit
+ #define luaL_addlstring dll_luaL_addlstring
+ #define luaL_pushresult dll_luaL_pushresult
+ /* lua */
++ #if LUA_VERSION_NUM <= 501
++ #define lua_tonumber dll_lua_tonumber
++ #define lua_tointeger dll_lua_tointeger
++ #define lua_call dll_lua_call
++ #define lua_pcall dll_lua_pcall
++ #else
++ #define lua_tonumberx dll_lua_tonumberx
++ #define lua_tointegerx dll_lua_tointegerx
++ #define lua_callk dll_lua_callk
++ #define lua_pcallk dll_lua_pcallk
++ #define lua_getglobal dll_lua_getglobal
++ #define lua_setglobal dll_lua_setglobal
++ #define lua_typename dll_lua_typename
++ #endif
+ #define lua_close dll_lua_close
+ #define lua_gettop dll_lua_gettop
+ #define lua_settop dll_lua_settop
+ #define lua_pushvalue dll_lua_pushvalue
+ #define lua_replace dll_lua_replace
++ #define lua_remove dll_lua_remove
+ #define lua_isnumber dll_lua_isnumber
+ #define lua_isstring dll_lua_isstring
+ #define lua_type dll_lua_type
+ #define lua_rawequal dll_lua_rawequal
+ #define lua_toboolean dll_lua_toboolean
+ #define lua_tolstring dll_lua_tolstring
+ #define lua_touserdata dll_lua_touserdata
+***************
+*** 94,109 ****
+ #define lua_pushlightuserdata dll_lua_pushlightuserdata
+ #define lua_getfield dll_lua_getfield
+ #define lua_rawget dll_lua_rawget
+ #define lua_createtable dll_lua_createtable
+ #define lua_newuserdata dll_lua_newuserdata
+ #define lua_getmetatable dll_lua_getmetatable
+ #define lua_setfield dll_lua_setfield
+ #define lua_rawset dll_lua_rawset
+ #define lua_rawseti dll_lua_rawseti
+- #define lua_remove dll_lua_remove
+ #define lua_setmetatable dll_lua_setmetatable
+- #define lua_call dll_lua_call
+- #define lua_pcall dll_lua_pcall
+ /* libs */
+ #define luaopen_base dll_luaopen_base
+ #define luaopen_table dll_luaopen_table
+--- 143,156 ----
+ #define lua_pushlightuserdata dll_lua_pushlightuserdata
+ #define lua_getfield dll_lua_getfield
+ #define lua_rawget dll_lua_rawget
++ #define lua_rawgeti dll_lua_rawgeti
+ #define lua_createtable dll_lua_createtable
+ #define lua_newuserdata dll_lua_newuserdata
+ #define lua_getmetatable dll_lua_getmetatable
+ #define lua_setfield dll_lua_setfield
+ #define lua_rawset dll_lua_rawset
+ #define lua_rawseti dll_lua_rawseti
+ #define lua_setmetatable dll_lua_setmetatable
+ /* libs */
+ #define luaopen_base dll_luaopen_base
+ #define luaopen_table dll_luaopen_table
+***************
+*** 116,147 ****
+ #define luaL_openlibs dll_luaL_openlibs
+
+ /* lauxlib */
+ void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
+ int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
+ const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
+ lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
+ lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
+ void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
+ int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
+- int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
+- int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
+ lua_State *(*dll_luaL_newstate) (void);
+ void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+- char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
+ void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+ void (*dll_luaL_pushresult) (luaL_Buffer *B);
+ /* lua */
+ void (*dll_lua_close) (lua_State *L);
+ int (*dll_lua_gettop) (lua_State *L);
+ void (*dll_lua_settop) (lua_State *L, int idx);
+ void (*dll_lua_pushvalue) (lua_State *L, int idx);
+ void (*dll_lua_replace) (lua_State *L, int idx);
+ int (*dll_lua_isnumber) (lua_State *L, int idx);
+ int (*dll_lua_isstring) (lua_State *L, int idx);
+ int (*dll_lua_type) (lua_State *L, int idx);
+ int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
+- lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
+- lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
+ int (*dll_lua_toboolean) (lua_State *L, int idx);
+ const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
+ void *(*dll_lua_touserdata) (lua_State *L, int idx);
+--- 163,218 ----
+ #define luaL_openlibs dll_luaL_openlibs
+
+ /* lauxlib */
++ #if LUA_VERSION_NUM <= 501
+ void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
++ char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
++ void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
+ int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
++ int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
++ int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
++ #else
++ char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
++ void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
++ int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
++ int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
++ int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
++ #endif
+ const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
+ lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
+ lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
+ void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
+ int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
+ lua_State *(*dll_luaL_newstate) (void);
+ void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+ void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+ void (*dll_luaL_pushresult) (luaL_Buffer *B);
+ /* lua */
++ #if LUA_VERSION_NUM <= 501
++ lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
++ lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
++ void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
++ int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
++ #else
++ lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
++ lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
++ void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
++ lua_CFunction k);
++ int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
++ int ctx, lua_CFunction k);
++ void (*dll_lua_getglobal) (lua_State *L, const char *var);
++ void (*dll_lua_setglobal) (lua_State *L, const char *var);
++ const char *(*dll_lua_typename) (lua_State *L, int tp);
++ #endif
+ void (*dll_lua_close) (lua_State *L);
+ int (*dll_lua_gettop) (lua_State *L);
+ void (*dll_lua_settop) (lua_State *L, int idx);
+ void (*dll_lua_pushvalue) (lua_State *L, int idx);
+ void (*dll_lua_replace) (lua_State *L, int idx);
++ void (*dll_lua_remove) (lua_State *L, int idx);
+ int (*dll_lua_isnumber) (lua_State *L, int idx);
+ int (*dll_lua_isstring) (lua_State *L, int idx);
+ int (*dll_lua_type) (lua_State *L, int idx);
+ int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
+ int (*dll_lua_toboolean) (lua_State *L, int idx);
+ const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
+ void *(*dll_lua_touserdata) (lua_State *L, int idx);
+***************
+*** 156,171 ****
+ void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
+ void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
+ void (*dll_lua_rawget) (lua_State *L, int idx);
+ void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
+ void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
+ int (*dll_lua_getmetatable) (lua_State *L, int objindex);
+ void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
+ void (*dll_lua_rawset) (lua_State *L, int idx);
+ void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
+- void (*dll_lua_remove) (lua_State *L, int idx);
+ int (*dll_lua_setmetatable) (lua_State *L, int objindex);
+- void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
+- int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
+ /* libs */
+ int (*dll_luaopen_base) (lua_State *L);
+ int (*dll_luaopen_table) (lua_State *L);
+--- 227,240 ----
+ void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
+ void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
+ void (*dll_lua_rawget) (lua_State *L, int idx);
++ void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
+ void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
+ void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
+ int (*dll_lua_getmetatable) (lua_State *L, int objindex);
+ void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
+ void (*dll_lua_rawset) (lua_State *L, int idx);
+ void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
+ int (*dll_lua_setmetatable) (lua_State *L, int objindex);
+ /* libs */
+ int (*dll_luaopen_base) (lua_State *L);
+ int (*dll_luaopen_table) (lua_State *L);
+***************
+*** 185,216 ****
+
+ static const luaV_Reg luaV_dll[] = {
+ /* lauxlib */
+ {"luaL_register", (luaV_function) &dll_luaL_register},
+ {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
+ {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
+ {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
+ {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
+ {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
+ {"luaL_error", (luaV_function) &dll_luaL_error},
+- {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
+- {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
+ {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
+ {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
+- {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
+ {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
+ {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
+ /* lua */
+ {"lua_close", (luaV_function) &dll_lua_close},
+ {"lua_gettop", (luaV_function) &dll_lua_gettop},
+ {"lua_settop", (luaV_function) &dll_lua_settop},
+ {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
+ {"lua_replace", (luaV_function) &dll_lua_replace},
+ {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
+ {"lua_isstring", (luaV_function) &dll_lua_isstring},
+ {"lua_type", (luaV_function) &dll_lua_type},
+ {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
+- {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
+- {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
+ {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
+ {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
+ {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
+--- 254,307 ----
+
+ static const luaV_Reg luaV_dll[] = {
+ /* lauxlib */
++ #if LUA_VERSION_NUM <= 501
+ {"luaL_register", (luaV_function) &dll_luaL_register},
++ {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
++ {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
+ {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
++ {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
++ {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
++ #else
++ {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
++ {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
++ {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
++ {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
++ {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
++ #endif
+ {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
+ {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
+ {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
+ {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
+ {"luaL_error", (luaV_function) &dll_luaL_error},
+ {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
+ {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
+ {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
+ {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
+ /* lua */
++ #if LUA_VERSION_NUM <= 501
++ {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
++ {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
++ {"lua_call", (luaV_function) &dll_lua_call},
++ {"lua_pcall", (luaV_function) &dll_lua_pcall},
++ #else
++ {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
++ {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
++ {"lua_callk", (luaV_function) &dll_lua_callk},
++ {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
++ {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
++ {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
++ {"lua_typename", (luaV_function) &dll_lua_typename},
++ #endif
+ {"lua_close", (luaV_function) &dll_lua_close},
+ {"lua_gettop", (luaV_function) &dll_lua_gettop},
+ {"lua_settop", (luaV_function) &dll_lua_settop},
+ {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
+ {"lua_replace", (luaV_function) &dll_lua_replace},
++ {"lua_remove", (luaV_function) &dll_lua_remove},
+ {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
+ {"lua_isstring", (luaV_function) &dll_lua_isstring},
+ {"lua_type", (luaV_function) &dll_lua_type},
+ {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
+ {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
+ {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
+ {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
+***************
+*** 225,240 ****
+ {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
+ {"lua_getfield", (luaV_function) &dll_lua_getfield},
+ {"lua_rawget", (luaV_function) &dll_lua_rawget},
+ {"lua_createtable", (luaV_function) &dll_lua_createtable},
+ {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
+ {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
+ {"lua_setfield", (luaV_function) &dll_lua_setfield},
+ {"lua_rawset", (luaV_function) &dll_lua_rawset},
+ {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
+- {"lua_remove", (luaV_function) &dll_lua_remove},
+ {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
+- {"lua_call", (luaV_function) &dll_lua_call},
+- {"lua_pcall", (luaV_function) &dll_lua_pcall},
+ /* libs */
+ {"luaopen_base", (luaV_function) &dll_luaopen_base},
+ {"luaopen_table", (luaV_function) &dll_luaopen_table},
+--- 316,329 ----
+ {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
+ {"lua_getfield", (luaV_function) &dll_lua_getfield},
+ {"lua_rawget", (luaV_function) &dll_lua_rawget},
++ {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
+ {"lua_createtable", (luaV_function) &dll_lua_createtable},
+ {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
+ {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
+ {"lua_setfield", (luaV_function) &dll_lua_setfield},
+ {"lua_rawset", (luaV_function) &dll_lua_rawset},
+ {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
+ {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
+ /* libs */
+ {"luaopen_base", (luaV_function) &dll_luaopen_base},
+ {"luaopen_table", (luaV_function) &dll_luaopen_table},
+***************
+*** 294,299 ****
+--- 383,398 ----
+
+ #endif /* DYNAMIC_LUA */
+
++ #if LUA_VERSION_NUM > 501
++ static int
++ luaL_typeerror (lua_State *L, int narg, const char *tname)
++ {
++ const char *msg = lua_pushfstring(L, "%s expected, got %s",
++ tname, luaL_typename(L, narg));
++ return luaL_argerror(L, narg, msg);
++ }
++ #endif
++
+
+ /* ======= Internal ======= */
+
+***************
+*** 327,343 ****
+ }
+
+ static void *
+ luaV_checkudata(lua_State *L, int ud, const char *tname)
+ {
+ void *p = luaV_toudata(L, ud, tname);
+! if (p == NULL) luaL_typerror(L, ud, tname);
+ return p;
+ }
+
+ static void
+ luaV_pushtypval(lua_State *L, typval_T *tv)
+ {
+! if (tv == NULL) luaL_error(L, "null type");
+ switch (tv->v_type)
+ {
+ case VAR_STRING:
+--- 426,460 ----
+ }
+
+ static void *
++ luaV_checkcache(lua_State *L, void *p)
++ {
++ luaV_getudata(L, p);
++ if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
++ lua_pop(L, 1);
++ return p;
++ }
++
++ #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
++
++ #define luaV_checkvalid(L,luatyp,ud) \
++ luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
++
++ static void *
+ luaV_checkudata(lua_State *L, int ud, const char *tname)
+ {
+ void *p = luaV_toudata(L, ud, tname);
+! if (p == NULL) luaL_typeerror(L, ud, tname);
+ return p;
+ }
+
+ static void
+ luaV_pushtypval(lua_State *L, typval_T *tv)
+ {
+! if (tv == NULL)
+! {
+! lua_pushnil(L);
+! return;
+! }
+ switch (tv->v_type)
+ {
+ case VAR_STRING:
+***************
+*** 351,418 ****
+ lua_pushnumber(L, (lua_Number) tv->vval.v_float);
+ break;
+ #endif
+! case VAR_LIST: {
+! list_T *l = tv->vval.v_list;
+
+! if (l != NULL)
+ {
+! /* check cache */
+! lua_pushlightuserdata(L, (void *) l);
+! lua_rawget(L, LUA_ENVIRONINDEX);
+! if (lua_isnil(L, -1)) /* not interned? */
+ {
+! listitem_T *li;
+! int n = 0;
+! lua_pop(L, 1); /* nil */
+! lua_newtable(L);
+! lua_pushlightuserdata(L, (void *) l);
+! lua_pushvalue(L, -2);
+! lua_rawset(L, LUA_ENVIRONINDEX);
+! for (li = l->lv_first; li != NULL; li = li->li_next)
+! {
+! luaV_pushtypval(L, &li->li_tv);
+! lua_rawseti(L, -2, ++n);
+! }
+ }
+! }
+! else lua_pushnil(L);
+! break;
+! }
+! case VAR_DICT: {
+! dict_T *d = tv->vval.v_dict;
+!
+! if (d != NULL)
+! {
+! /* check cache */
+! lua_pushlightuserdata(L, (void *) d);
+! lua_rawget(L, LUA_ENVIRONINDEX);
+! if (lua_isnil(L, -1)) /* not interned? */
+ {
+! hashtab_T *ht = &d->dv_hashtab;
+! hashitem_T *hi;
+! int n = ht->ht_used; /* remaining items */
+! lua_pop(L, 1); /* nil */
+! lua_newtable(L);
+! lua_pushlightuserdata(L, (void *) d);
+! lua_pushvalue(L, -2);
+! lua_rawset(L, LUA_ENVIRONINDEX);
+! for (hi = ht->ht_array; n > 0; hi++)
+! {
+! if (!HASHITEM_EMPTY(hi))
+! {
+! dictitem_T *di = dict_lookup(hi);
+! luaV_pushtypval(L, &di->di_tv);
+! lua_setfield(L, -2, (char *) hi->hi_key);
+! n--;
+! }
+! }
+ }
+ }
+- else lua_pushnil(L);
+ break;
+ }
+ default:
+! luaL_error(L, "invalid type");
+ }
+ }
+
+--- 468,537 ----
+ lua_pushnumber(L, (lua_Number) tv->vval.v_float);
+ break;
+ #endif
+! case VAR_LIST:
+! luaV_pushlist(L, tv->vval.v_list);
+! break;
+! case VAR_DICT:
+! luaV_pushdict(L, tv->vval.v_dict);
+! break;
+! default:
+! lua_pushnil(L);
+! }
+! }
+
+! /* converts lua value at 'pos' to typval 'tv' */
+! static void
+! luaV_totypval (lua_State *L, int pos, typval_T *tv)
+! {
+! switch(lua_type(L, pos)) {
+! case LUA_TBOOLEAN:
+! tv->v_type = VAR_NUMBER;
+! tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
+! break;
+! case LUA_TSTRING:
+! tv->v_type = VAR_STRING;
+! tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
+! break;
+! case LUA_TNUMBER:
+! #ifdef FEAT_FLOAT
+! tv->v_type = VAR_FLOAT;
+! tv->vval.v_float = (float_T) lua_tonumber(L, pos);
+! #else
+! tv->v_type = VAR_NUMBER;
+! tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
+! #endif
+! break;
+! case LUA_TUSERDATA: {
+! void *p = lua_touserdata(L, pos);
+! if (lua_getmetatable(L, pos)) /* has metatable? */
+ {
+! /* check list */
+! luaV_getfield(L, LUAVIM_LIST);
+! if (lua_rawequal(L, -1, -2))
+ {
+! tv->v_type = VAR_LIST;
+! tv->vval.v_list = *((luaV_List *) p);
+! ++tv->vval.v_list->lv_refcount;
+! lua_pop(L, 2); /* MTs */
+! return;
+ }
+! /* check dict */
+! luaV_getfield(L, LUAVIM_DICT);
+! if (lua_rawequal(L, -1, -3))
+ {
+! tv->v_type = VAR_DICT;
+! tv->vval.v_dict = *((luaV_Dict *) p);
+! ++tv->vval.v_dict->dv_refcount;
+! lua_pop(L, 3); /* MTs */
+! return;
+ }
++ lua_pop(L, 3); /* MTs */
+ }
+ break;
+ }
+ default:
+! tv->v_type = VAR_NUMBER;
+! tv->vval.v_number = 0;
+ }
+ }
+
+***************
+*** 481,569 ****
+ lua_pop(L, 2); /* original and modified strings */
+ }
+
+
+! /* ======= Buffer type ======= */
+
+! static luaV_Buffer *
+! luaV_newbuffer(lua_State *L, buf_T *buf)
+ {
+! luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer));
+! *b = buf;
+! lua_pushlightuserdata(L, (void *) buf);
+! lua_pushvalue(L, -2);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */
+! /* to avoid GC, store as key in env */
+! lua_pushvalue(L, -1);
+! lua_pushboolean(L, 1);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
+! /* set metatable */
+! luaV_getfield(L, LUAVIM_BUFFER);
+ lua_setmetatable(L, -2);
+! return b;
+ }
+
+! static luaV_Buffer *
+! luaV_pushbuffer (lua_State *L, buf_T *buf)
+ {
+! luaV_Buffer *b = NULL;
+! if (buf == NULL)
+! lua_pushnil(L);
+! else {
+! lua_pushlightuserdata(L, (void *) buf);
+! lua_rawget(L, LUA_ENVIRONINDEX);
+! if (lua_isnil(L, -1)) /* not interned? */
+ {
+! lua_pop(L, 1);
+! b = luaV_newbuffer(L, buf);
+ }
+ else
+! b = (luaV_Buffer *) lua_touserdata(L, -1);
+ }
+! return b;
+ }
+
+! /* Buffer metamethods */
+
+ static int
+! luaV_buffer_tostring(lua_State *L)
+ {
+! lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1));
+ return 1;
+ }
+
+ static int
+ luaV_buffer_len(lua_State *L)
+ {
+! luaV_Buffer *b = lua_touserdata(L, 1);
+! lua_pushinteger(L, (*b)->b_ml.ml_line_count);
+ return 1;
+ }
+
+ static int
+ luaV_buffer_call(lua_State *L)
+ {
+! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
+ lua_settop(L, 1);
+! set_curbuf(*b, DOBUF_SPLIT);
+ return 1;
+ }
+
+ static int
+ luaV_buffer_index(lua_State *L)
+ {
+! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
+ linenr_T n = (linenr_T) lua_tointeger(L, 2);
+! if (n > 0 && n <= (*b)->b_ml.ml_line_count)
+! luaV_pushline(L, *b, n);
+ else if (lua_isstring(L, 2))
+ {
+ const char *s = lua_tostring(L, 2);
+ if (strncmp(s, "name", 4) == 0)
+! lua_pushstring(L, (char *) (*b)->b_sfname);
+ else if (strncmp(s, "fname", 5) == 0)
+! lua_pushstring(L, (char *) (*b)->b_ffname);
+ else if (strncmp(s, "number", 6) == 0)
+! lua_pushinteger(L, (*b)->b_fnum);
+ /* methods */
+ else if (strncmp(s, "insert", 6) == 0
+ || strncmp(s, "next", 4) == 0
+--- 600,1107 ----
+ lua_pop(L, 2); /* original and modified strings */
+ }
+
++ #define luaV_newtype(typ,tname,luatyp,luatname) \
++ static luatyp * \
++ luaV_new##tname (lua_State *L, typ *obj) \
++ { \
++ luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
++ *o = obj; \
++ luaV_setudata(L, obj); /* cache[obj] = udata */ \
++ luaV_getfield(L, luatname); \
++ lua_setmetatable(L, -2); \
++ return o; \
++ }
++
++ #define luaV_pushtype(typ,tname,luatyp) \
++ static luatyp * \
++ luaV_push##tname (lua_State *L, typ *obj) \
++ { \
++ luatyp *o = NULL; \
++ if (obj == NULL) \
++ lua_pushnil(L); \
++ else { \
++ luaV_getudata(L, obj); \
++ if (lua_isnil(L, -1)) /* not interned? */ \
++ { \
++ lua_pop(L, 1); \
++ o = luaV_new##tname(L, obj); \
++ } \
++ else \
++ o = (luatyp *) lua_touserdata(L, -1); \
++ } \
++ return o; \
++ }
++
++ #define luaV_type_tostring(tname,luatname) \
++ static int \
++ luaV_##tname##_tostring (lua_State *L) \
++ { \
++ lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
++ return 1; \
++ }
++
+
+! /* adapted from eval.c */
+!
+! #define listitem_alloc() (listitem_T *)alloc(sizeof(listitem_T))
+!
+! static listitem_T *
+! list_find (list_T *l, long n)
+! {
+! listitem_T *li;
+! if (l == NULL || n < -l->lv_len || n >= l->lv_len)
+! return NULL;
+! if (n < 0) /* search backward? */
+! for (li = l->lv_last; n < -1; li = li->li_prev)
+! n++;
+! else /* search forward */
+! for (li = l->lv_first; n > 0; li = li->li_next)
+! n--;
+! return li;
+! }
+
+! static void
+! list_remove (list_T *l, listitem_T *li)
+ {
+! listwatch_T *lw;
+! --l->lv_len;
+! /* fix watchers */
+! for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
+! if (lw->lw_item == li)
+! lw->lw_item = li->li_next;
+! /* fix list pointers */
+! if (li->li_next == NULL) /* last? */
+! l->lv_last = li->li_prev;
+! else
+! li->li_next->li_prev = li->li_prev;
+! if (li->li_prev == NULL) /* first? */
+! l->lv_first = li->li_next;
+! else
+! li->li_prev->li_next = li->li_next;
+! l->lv_idx_item = NULL;
+! }
+!
+! static void
+! list_append(list_T *l, listitem_T *item)
+! {
+! if (l->lv_last == NULL) /* empty list? */
+! l->lv_first = item;
+! else
+! l->lv_last->li_next = item;
+! item->li_prev = l->lv_last;
+! item->li_next = NULL;
+! l->lv_last = item;
+! ++l->lv_len;
+! }
+!
+! static int
+! list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
+! {
+! listitem_T *ni = listitem_alloc();
+!
+! if (ni == NULL)
+! return FAIL;
+! copy_tv(tv, &ni->li_tv);
+! if (item == NULL)
+! list_append(l, ni);
+! else
+! {
+! ni->li_prev = item->li_prev;
+! ni->li_next = item;
+! if (item->li_prev == NULL)
+! {
+! l->lv_first = ni;
+! ++l->lv_idx;
+! }
+! else
+! {
+! item->li_prev->li_next = ni;
+! l->lv_idx_item = NULL;
+! }
+! item->li_prev = ni;
+! ++l->lv_len;
+! }
+! return OK;
+! }
+!
+! /* set references */
+!
+! static void set_ref_in_tv (typval_T *tv, int copyID);
+!
+! static void
+! set_ref_in_dict(dict_T *d, int copyID)
+! {
+! hashtab_T *ht = &d->dv_hashtab;
+! int n = ht->ht_used;
+! hashitem_T *hi;
+! for (hi = ht->ht_array; n > 0; ++hi)
+! if (!HASHITEM_EMPTY(hi))
+! {
+! dictitem_T *di = dict_lookup(hi);
+! set_ref_in_tv(&di->di_tv, copyID);
+! --n;
+! }
+! }
+!
+! static void
+! set_ref_in_list(list_T *l, int copyID)
+! {
+! listitem_T *li;
+! for (li = l->lv_first; li != NULL; li = li->li_next)
+! set_ref_in_tv(&li->li_tv, copyID);
+! }
+!
+! static void
+! set_ref_in_tv(typval_T *tv, int copyID)
+! {
+! if (tv->v_type == VAR_LIST)
+! {
+! list_T *l = tv->vval.v_list;
+! if (l != NULL && l->lv_copyID != copyID)
+! {
+! l->lv_copyID = copyID;
+! set_ref_in_list(l, copyID);
+! }
+! }
+! else if (tv->v_type == VAR_DICT)
+! {
+! dict_T *d = tv->vval.v_dict;
+! if (d != NULL && d->dv_copyID != copyID)
+! {
+! d->dv_copyID = copyID;
+! set_ref_in_dict(d, copyID);
+! }
+! }
+! }
+!
+!
+! /* ======= List type ======= */
+!
+! static luaV_List *
+! luaV_newlist (lua_State *L, list_T *lis)
+! {
+! luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
+! *l = lis;
+! lis->lv_refcount++; /* reference in Lua */
+! luaV_setudata(L, lis); /* cache[lis] = udata */
+! luaV_getfield(L, LUAVIM_LIST);
+ lua_setmetatable(L, -2);
+! return l;
+ }
+
+! luaV_pushtype(list_T, list, luaV_List)
+! luaV_type_tostring(list, LUAVIM_LIST)
+!
+! static int
+! luaV_list_gc (lua_State *L)
+ {
+! list_unref(luaV_unbox(L, luaV_List, 1));
+! return 0;
+! }
+!
+! static int
+! luaV_list_len (lua_State *L)
+! {
+! list_T *l = luaV_unbox(L, luaV_List, 1);
+! lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len);
+! return 1;
+! }
+!
+! static int
+! luaV_list_iter (lua_State *L)
+! {
+! listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
+! if (li == NULL) return 0;
+! luaV_pushtypval(L, &li->li_tv);
+! lua_pushlightuserdata(L, (void *) li->li_next);
+! lua_replace(L, lua_upvalueindex(2));
+! return 1;
+! }
+!
+! static int
+! luaV_list_call (lua_State *L)
+! {
+! list_T *l = luaV_unbox(L, luaV_List, 1);
+! lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
+! lua_pushlightuserdata(L, (void *) l->lv_first);
+! lua_pushcclosure(L, luaV_list_iter, 2);
+! return 1;
+! }
+!
+! static int
+! luaV_list_index (lua_State *L)
+! {
+! list_T *l = luaV_unbox(L, luaV_List, 1);
+! if (lua_isnumber(L, 2)) /* list item? */
+! {
+! listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2));
+! if (li == NULL)
+! lua_pushnil(L);
+! else
+! luaV_pushtypval(L, &li->li_tv);
+! }
+! else if (lua_isstring(L, 2)) /* method? */
+! {
+! const char *s = lua_tostring(L, 2);
+! if (strncmp(s, "add", 3) == 0
+! || strncmp(s, "insert", 6) == 0
+! || strncmp(s, "extend", 6) == 0)
+ {
+! lua_getmetatable(L, 1);
+! lua_getfield(L, -1, s);
+ }
+ else
+! lua_pushnil(L);
+ }
+! else
+! lua_pushnil(L);
+! return 1;
+ }
+
+! static int
+! luaV_list_newindex (lua_State *L)
+! {
+! list_T *l = luaV_unbox(L, luaV_List, 1);
+! long n = (long) luaL_checkinteger(L, 2);
+! listitem_T *li;
+! if (l->lv_lock)
+! luaL_error(L, "list is locked");
+! li = list_find(l, n);
+! if (li == NULL) return 0;
+! if (lua_isnil(L, 3)) /* remove? */
+! {
+! list_remove(l, li);
+! clear_tv(&li->li_tv);
+! vim_free(li);
+! }
+! else
+! {
+! typval_T v;
+! luaV_totypval(L, 3, &v);
+! clear_tv(&li->li_tv);
+! copy_tv(&v, &li->li_tv);
+! }
+! return 0;
+! }
+
+ static int
+! luaV_list_add (lua_State *L)
+ {
+! luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
+! list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
+! listitem_T *li;
+! if (l->lv_lock)
+! luaL_error(L, "list is locked");
+! li = listitem_alloc();
+! if (li != NULL)
+! {
+! typval_T v;
+! lua_settop(L, 2);
+! luaV_totypval(L, 2, &v);
+! copy_tv(&v, &li->li_tv);
+! list_append(l, li);
+! }
+! lua_settop(L, 1);
+ return 1;
+ }
+
+ static int
++ luaV_list_insert (lua_State *L)
++ {
++ luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
++ list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
++ long pos = luaL_optlong(L, 3, 0);
++ listitem_T *li = NULL;
++ typval_T v;
++ if (l->lv_lock)
++ luaL_error(L, "list is locked");
++ if (pos < l->lv_len)
++ {
++ li = list_find(l, pos);
++ if (li == NULL)
++ luaL_error(L, "invalid position");
++ }
++ lua_settop(L, 2);
++ luaV_totypval(L, 2, &v);
++ list_insert_tv(l, &v, li);
++ lua_settop(L, 1);
++ return 1;
++ }
++
++ static const luaL_Reg luaV_List_mt[] = {
++ {"__tostring", luaV_list_tostring},
++ {"__gc", luaV_list_gc},
++ {"__len", luaV_list_len},
++ {"__call", luaV_list_call},
++ {"__index", luaV_list_index},
++ {"__newindex", luaV_list_newindex},
++ {"add", luaV_list_add},
++ {"insert", luaV_list_insert},
++ {NULL, NULL}
++ };
++
++
++ /* ======= Dict type ======= */
++
++ static luaV_Dict *
++ luaV_newdict (lua_State *L, dict_T *dic)
++ {
++ luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
++ *d = dic;
++ dic->dv_refcount++; /* reference in Lua */
++ luaV_setudata(L, dic); /* cache[dic] = udata */
++ luaV_getfield(L, LUAVIM_DICT);
++ lua_setmetatable(L, -2);
++ return d;
++ }
++
++ luaV_pushtype(dict_T, dict, luaV_Dict)
++ luaV_type_tostring(dict, LUAVIM_DICT)
++
++ static int
++ luaV_dict_gc (lua_State *L)
++ {
++ dict_unref(luaV_unbox(L, luaV_Dict, 1));
++ return 0;
++ }
++
++ static int
++ luaV_dict_len (lua_State *L)
++ {
++ dict_T *d = luaV_unbox(L, luaV_Dict, 1);
++ lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used);
++ return 1;
++ }
++
++ static int
++ luaV_dict_iter (lua_State *L)
++ {
++ hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
++ int n = lua_tointeger(L, lua_upvalueindex(3));
++ dictitem_T *di;
++ if (n <= 0) return 0;
++ while (HASHITEM_EMPTY(hi)) hi++;
++ di = dict_lookup(hi);
++ lua_pushstring(L, (char *) hi->hi_key);
++ luaV_pushtypval(L, &di->di_tv);
++ lua_pushlightuserdata(L, (void *) (hi + 1));
++ lua_replace(L, lua_upvalueindex(2));
++ lua_pushinteger(L, n - 1);
++ lua_replace(L, lua_upvalueindex(3));
++ return 2;
++ }
++
++ static int
++ luaV_dict_call (lua_State *L)
++ {
++ dict_T *d = luaV_unbox(L, luaV_Dict, 1);
++ hashtab_T *ht = &d->dv_hashtab;
++ lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
++ lua_pushlightuserdata(L, (void *) ht->ht_array);
++ lua_pushinteger(L, ht->ht_used); /* # remaining items */
++ lua_pushcclosure(L, luaV_dict_iter, 3);
++ return 1;
++ }
++
++ static int
++ luaV_dict_index (lua_State *L)
++ {
++ dict_T *d = luaV_unbox(L, luaV_Dict, 1);
++ char_u *key = (char_u *) luaL_checkstring(L, 2);
++ dictitem_T *di = dict_find(d, key, -1);
++ if (di == NULL)
++ lua_pushnil(L);
++ else
++ luaV_pushtypval(L, &di->di_tv);
++ return 1;
++ }
++
++ static int
++ luaV_dict_newindex (lua_State *L)
++ {
++ dict_T *d = luaV_unbox(L, luaV_Dict, 1);
++ char_u *key = (char_u *) luaL_checkstring(L, 2);
++ dictitem_T *di;
++ if (d->dv_lock)
++ luaL_error(L, "dict is locked");
++ di = dict_find(d, key, -1);
++ if (di == NULL) /* non-existing key? */
++ {
++ if (lua_isnil(L, 3)) return 0;
++ di = dictitem_alloc(key);
++ if (di == NULL) return 0;
++ if (dict_add(d, di) == FAIL)
++ {
++ vim_free(di);
++ return 0;
++ }
++ }
++ else
++ clear_tv(&di->di_tv);
++ if (lua_isnil(L, 3)) /* remove? */
++ {
++ hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
++ hash_remove(&d->dv_hashtab, hi);
++ dictitem_free(di);
++ }
++ else {
++ typval_T v;
++ luaV_totypval(L, 3, &v);
++ copy_tv(&v, &di->di_tv);
++ }
++ return 0;
++ }
++
++ static const luaL_Reg luaV_Dict_mt[] = {
++ {"__tostring", luaV_dict_tostring},
++ {"__gc", luaV_dict_gc},
++ {"__len", luaV_dict_len},
++ {"__call", luaV_dict_call},
++ {"__index", luaV_dict_index},
++ {"__newindex", luaV_dict_newindex},
++ {NULL, NULL}
++ };
++
++
++ /* ======= Buffer type ======= */
++
++ luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
++ luaV_pushtype(buf_T, buffer, luaV_Buffer)
++ luaV_type_tostring(buffer, LUAVIM_BUFFER)
++
++ static int
+ luaV_buffer_len(lua_State *L)
+ {
+! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
+! lua_pushinteger(L, b->b_ml.ml_line_count);
+ return 1;
+ }
+
+ static int
+ luaV_buffer_call(lua_State *L)
+ {
+! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
+ lua_settop(L, 1);
+! set_curbuf(b, DOBUF_SPLIT);
+ return 1;
+ }
+
+ static int
+ luaV_buffer_index(lua_State *L)
+ {
+! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
+ linenr_T n = (linenr_T) lua_tointeger(L, 2);
+! if (n > 0 && n <= b->b_ml.ml_line_count)
+! luaV_pushline(L, b, n);
+ else if (lua_isstring(L, 2))
+ {
+ const char *s = lua_tostring(L, 2);
+ if (strncmp(s, "name", 4) == 0)
+! lua_pushstring(L, (char *) b->b_sfname);
+ else if (strncmp(s, "fname", 5) == 0)
+! lua_pushstring(L, (char *) b->b_ffname);
+ else if (strncmp(s, "number", 6) == 0)
+! lua_pushinteger(L, b->b_fnum);
+ /* methods */
+ else if (strncmp(s, "insert", 6) == 0
+ || strncmp(s, "next", 4) == 0
+***************
+*** 584,600 ****
+ static int
+ luaV_buffer_newindex(lua_State *L)
+ {
+! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
+ linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! if (n < 1 || n > (*b)->b_ml.ml_line_count)
+ luaL_error(L, "invalid line number");
+ if (lua_isnil(L, 3)) /* delete line */
+ {
+ buf_T *buf = curbuf;
+! curbuf = *b;
+ if (u_savedel(n, 1L) == FAIL)
+ {
+ curbuf = buf;
+--- 1122,1138 ----
+ static int
+ luaV_buffer_newindex(lua_State *L)
+ {
+! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
+ linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! if (n < 1 || n > b->b_ml.ml_line_count)
+ luaL_error(L, "invalid line number");
+ if (lua_isnil(L, 3)) /* delete line */
+ {
+ buf_T *buf = curbuf;
+! curbuf = b;
+ if (u_savedel(n, 1L) == FAIL)
+ {
+ curbuf = buf;
+***************
+*** 607,613 ****
+ }
+ else {
+ deleted_lines_mark(n, 1L);
+! if (*b == curwin->w_buffer) /* fix cursor in current window? */
+ {
+ if (curwin->w_cursor.lnum >= n)
+ {
+--- 1145,1151 ----
+ }
+ else {
+ deleted_lines_mark(n, 1L);
+! if (b == curwin->w_buffer) /* fix cursor in current window? */
+ {
+ if (curwin->w_cursor.lnum >= n)
+ {
+***************
+*** 627,633 ****
+ else if (lua_isstring(L, 3)) /* update line */
+ {
+ buf_T *buf = curbuf;
+! curbuf = *b;
+ if (u_savesub(n) == FAIL)
+ {
+ curbuf = buf;
+--- 1165,1171 ----
+ else if (lua_isstring(L, 3)) /* update line */
+ {
+ buf_T *buf = curbuf;
+! curbuf = b;
+ if (u_savesub(n) == FAIL)
+ {
+ curbuf = buf;
+***************
+*** 640,646 ****
+ }
+ else changed_bytes(n, 0);
+ curbuf = buf;
+! if (*b == curwin->w_buffer)
+ check_cursor_col();
+ }
+ else
+--- 1178,1184 ----
+ }
+ else changed_bytes(n, 0);
+ curbuf = buf;
+! if (b == curwin->w_buffer)
+ check_cursor_col();
+ }
+ else
+***************
+*** 651,658 ****
+ static int
+ luaV_buffer_insert(lua_State *L)
+ {
+! luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! linenr_T last = (*b)->b_ml.ml_line_count;
+ linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
+ buf_T *buf;
+ luaL_checktype(L, 2, LUA_TSTRING);
+--- 1189,1197 ----
+ static int
+ luaV_buffer_insert(lua_State *L)
+ {
+! luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
+! linenr_T last = b->b_ml.ml_line_count;
+ linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
+ buf_T *buf;
+ luaL_checktype(L, 2, LUA_TSTRING);
+***************
+*** 664,670 ****
+ if (n > last) n = last;
+ /* insert */
+ buf = curbuf;
+! curbuf = *b;
+ if (u_save(n, n + 1) == FAIL)
+ {
+ curbuf = buf;
+--- 1203,1209 ----
+ if (n > last) n = last;
+ /* insert */
+ buf = curbuf;
+! curbuf = b;
+ if (u_save(n, n + 1) == FAIL)
+ {
+ curbuf = buf;
+***************
+*** 686,692 ****
+ luaV_buffer_next(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! luaV_pushbuffer(L, (*b)->b_next);
+ return 1;
+ }
+
+--- 1225,1232 ----
+ luaV_buffer_next(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
+! luaV_pushbuffer(L, buf->b_next);
+ return 1;
+ }
+
+***************
+*** 694,700 ****
+ luaV_buffer_previous(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! luaV_pushbuffer(L, (*b)->b_prev);
+ return 1;
+ }
+
+--- 1234,1241 ----
+ luaV_buffer_previous(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
+! luaV_pushbuffer(L, buf->b_prev);
+ return 1;
+ }
+
+***************
+*** 702,709 ****
+ luaV_buffer_isvalid(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! lua_pushlightuserdata(L, (void *) (*b));
+! lua_rawget(L, LUA_ENVIRONINDEX);
+ lua_pushboolean(L, !lua_isnil(L, -1));
+ return 1;
+ }
+--- 1243,1249 ----
+ luaV_buffer_isvalid(lua_State *L)
+ {
+ luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
+! luaV_getudata(L, *b);
+ lua_pushboolean(L, !lua_isnil(L, -1));
+ return 1;
+ }
+***************
+*** 724,801 ****
+
+ /* ======= Window type ======= */
+
+! static luaV_Window *
+! luaV_newwindow(lua_State *L, win_T *win)
+! {
+! luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window));
+! *w = win;
+! lua_pushlightuserdata(L, (void *) win);
+! lua_pushvalue(L, -2);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */
+! /* to avoid GC, store as key in env */
+! lua_pushvalue(L, -1);
+! lua_pushboolean(L, 1);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
+! /* set metatable */
+! luaV_getfield(L, LUAVIM_WINDOW);
+! lua_setmetatable(L, -2);
+! return w;
+! }
+!
+! static luaV_Window *
+! luaV_pushwindow(lua_State *L, win_T *win)
+! {
+! luaV_Window *w = NULL;
+! if (win == NULL)
+! lua_pushnil(L);
+! else {
+! lua_pushlightuserdata(L, (void *) win);
+! lua_rawget(L, LUA_ENVIRONINDEX);
+! if (lua_isnil(L, -1)) /* not interned? */
+! {
+! lua_pop(L, 1);
+! w = luaV_newwindow(L, win);
+! }
+! else w = (luaV_Window *) lua_touserdata(L, -1);
+! }
+! return w;
+! }
+!
+! /* Window metamethods */
+!
+! static int
+! luaV_window_tostring(lua_State *L)
+! {
+! lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1));
+! return 1;
+! }
+
+ static int
+ luaV_window_call(lua_State *L)
+ {
+! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
+ lua_settop(L, 1);
+! win_goto(*w);
+ return 1;
+ }
+
+ static int
+ luaV_window_index(lua_State *L)
+ {
+! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
+ const char *s = luaL_checkstring(L, 2);
+ if (strncmp(s, "buffer", 6) == 0)
+! luaV_pushbuffer(L, (*w)->w_buffer);
+ else if (strncmp(s, "line", 4) == 0)
+! lua_pushinteger(L, (*w)->w_cursor.lnum);
+ else if (strncmp(s, "col", 3) == 0)
+! lua_pushinteger(L, (*w)->w_cursor.col + 1);
+ #ifdef FEAT_VERTSPLIT
+ else if (strncmp(s, "width", 5) == 0)
+! lua_pushinteger(L, W_WIDTH((*w)));
+ #endif
+ else if (strncmp(s, "height", 6) == 0)
+! lua_pushinteger(L, (*w)->w_height);
+ /* methods */
+ else if (strncmp(s, "next", 4) == 0
+ || strncmp(s, "previous", 8) == 0
+--- 1264,1299 ----
+
+ /* ======= Window type ======= */
+
+! luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
+! luaV_pushtype(win_T, window, luaV_Window)
+! luaV_type_tostring(window, LUAVIM_WINDOW)
+
+ static int
+ luaV_window_call(lua_State *L)
+ {
+! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
+ lua_settop(L, 1);
+! win_goto(w);
+ return 1;
+ }
+
+ static int
+ luaV_window_index(lua_State *L)
+ {
+! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
+ const char *s = luaL_checkstring(L, 2);
+ if (strncmp(s, "buffer", 6) == 0)
+! luaV_pushbuffer(L, w->w_buffer);
+ else if (strncmp(s, "line", 4) == 0)
+! lua_pushinteger(L, w->w_cursor.lnum);
+ else if (strncmp(s, "col", 3) == 0)
+! lua_pushinteger(L, w->w_cursor.col + 1);
+ #ifdef FEAT_VERTSPLIT
+ else if (strncmp(s, "width", 5) == 0)
+! lua_pushinteger(L, W_WIDTH(w));
+ #endif
+ else if (strncmp(s, "height", 6) == 0)
+! lua_pushinteger(L, w->w_height);
+ /* methods */
+ else if (strncmp(s, "next", 4) == 0
+ || strncmp(s, "previous", 8) == 0
+***************
+*** 812,818 ****
+ static int
+ luaV_window_newindex (lua_State *L)
+ {
+! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
+ const char *s = luaL_checkstring(L, 2);
+ int v = luaL_checkinteger(L, 3);
+ if (strncmp(s, "line", 4) == 0)
+--- 1310,1316 ----
+ static int
+ luaV_window_newindex (lua_State *L)
+ {
+! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
+ const char *s = luaL_checkstring(L, 2);
+ int v = luaL_checkinteger(L, 3);
+ if (strncmp(s, "line", 4) == 0)
+***************
+*** 820,828 ****
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count)
+ luaL_error(L, "line out of range");
+! (*w)->w_cursor.lnum = v;
+ update_screen(VALID);
+ }
+ else if (strncmp(s, "col", 3) == 0)
+--- 1318,1326 ----
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
+ luaL_error(L, "line out of range");
+! w->w_cursor.lnum = v;
+ update_screen(VALID);
+ }
+ else if (strncmp(s, "col", 3) == 0)
+***************
+*** 830,836 ****
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! (*w)->w_cursor.col = v - 1;
+ update_screen(VALID);
+ }
+ #ifdef FEAT_VERTSPLIT
+--- 1328,1334 ----
+ #ifdef HAVE_SANDBOX
+ luaV_checksandbox(L);
+ #endif
+! w->w_cursor.col = v - 1;
+ update_screen(VALID);
+ }
+ #ifdef FEAT_VERTSPLIT
+***************
+*** 840,846 ****
+ #ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+ #endif
+! curwin = *w;
+ win_setwidth(v);
+ curwin = win;
+ }
+--- 1338,1344 ----
+ #ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+ #endif
+! curwin = w;
+ win_setwidth(v);
+ curwin = win;
+ }
+***************
+*** 851,857 ****
+ #ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+ #endif
+! curwin = *w;
+ win_setheight(v);
+ curwin = win;
+ }
+--- 1349,1355 ----
+ #ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+ #endif
+! curwin = w;
+ win_setheight(v);
+ curwin = win;
+ }
+***************
+*** 864,870 ****
+ luaV_window_next(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! luaV_pushwindow(L, (*w)->w_next);
+ return 1;
+ }
+
+--- 1362,1369 ----
+ luaV_window_next(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
+! luaV_pushwindow(L, win->w_next);
+ return 1;
+ }
+
+***************
+*** 872,878 ****
+ luaV_window_previous(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! luaV_pushwindow(L, (*w)->w_prev);
+ return 1;
+ }
+
+--- 1371,1378 ----
+ luaV_window_previous(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
+! luaV_pushwindow(L, win->w_prev);
+ return 1;
+ }
+
+***************
+*** 880,887 ****
+ luaV_window_isvalid(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! lua_pushlightuserdata(L, (void *) (*w));
+! lua_rawget(L, LUA_ENVIRONINDEX);
+ lua_pushboolean(L, !lua_isnil(L, -1));
+ return 1;
+ }
+--- 1380,1386 ----
+ luaV_window_isvalid(lua_State *L)
+ {
+ luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
+! luaV_getudata(L, *w);
+ lua_pushboolean(L, !lua_isnil(L, -1));
+ return 1;
+ }
+***************
+*** 983,988 ****
+--- 1482,1509 ----
+ }
+
+ static int
++ luaV_list(lua_State *L)
++ {
++ list_T *l = list_alloc();
++ if (l == NULL)
++ lua_pushnil(L);
++ else
++ luaV_newlist(L, l);
++ return 1;
++ }
++
++ static int
++ luaV_dict(lua_State *L)
++ {
++ dict_T *d = dict_alloc();
++ if (d == NULL)
++ lua_pushnil(L);
++ else
++ luaV_newdict(L, d);
++ return 1;
++ }
++
++ static int
+ luaV_buffer(lua_State *L)
+ {
+ buf_T *buf;
+***************
+*** 1008,1022 ****
+ break;
+ }
+ }
+- if (buf == NULL) /* not found? */
+- lua_pushnil(L);
+- else
+- luaV_pushbuffer(L, buf);
+ }
+! else {
+ buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
+! luaV_pushbuffer(L, buf);
+! }
+ return 1;
+ }
+
+--- 1529,1538 ----
+ break;
+ }
+ }
+ }
+! else
+ buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
+! luaV_pushbuffer(L, buf);
+ return 1;
+ }
+
+***************
+*** 1029,1043 ****
+ int n = lua_tointeger(L, 1);
+ for (win = firstwin; win != NULL; win = win->w_next, n--)
+ if (n == 1) break;
+- if (win == NULL) /* not found? */
+- lua_pushnil(L);
+- else
+- luaV_pushwindow(L, win);
+ }
+! else {
+ win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
+! luaV_pushwindow(L, win);
+! }
+ return 1;
+ }
+
+--- 1545,1554 ----
+ int n = lua_tointeger(L, 1);
+ for (win = firstwin; win != NULL; win = win->w_next, n--)
+ if (n == 1) break;
+ }
+! else
+ win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
+! luaV_pushwindow(L, win);
+ return 1;
+ }
+
+***************
+*** 1054,1086 ****
+ }
+
+ static int
+! luaV_isbuffer(lua_State *L)
+! {
+! lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL);
+! return 1;
+! }
+!
+! static int
+! luaV_iswindow(lua_State *L)
+ {
+! lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL);
+! return 1;
+! }
+!
+! /* for freeing buffer and window objects; lightuserdata as arg */
+! static int
+! luaV_free(lua_State *L)
+! {
+! lua_pushvalue(L, 1); /* lightudata */
+! lua_rawget(L, LUA_ENVIRONINDEX);
+! if (!lua_isnil(L, -1))
+ {
+! lua_pushnil(L);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */
+! lua_pushnil(L);
+! lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */
+ }
+! return 0;
+ }
+
+ static const luaL_Reg luaV_module[] = {
+--- 1565,1606 ----
+ }
+
+ static int
+! luaV_type(lua_State *L)
+ {
+! luaL_checkany(L, 1);
+! if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */
+ {
+! lua_settop(L, 1);
+! if (lua_getmetatable(L, 1))
+! {
+! luaV_getfield(L, LUAVIM_LIST);
+! if (lua_rawequal(L, -1, 2))
+! {
+! lua_pushstring(L, "list");
+! return 1;
+! }
+! luaV_getfield(L, LUAVIM_DICT);
+! if (lua_rawequal(L, -1, 2))
+! {
+! lua_pushstring(L, "dict");
+! return 1;
+! }
+! luaV_getfield(L, LUAVIM_BUFFER);
+! if (lua_rawequal(L, -1, 2))
+! {
+! lua_pushstring(L, "buffer");
+! return 1;
+! }
+! luaV_getfield(L, LUAVIM_WINDOW);
+! if (lua_rawequal(L, -1, 2))
+! {
+! lua_pushstring(L, "window");
+! return 1;
+! }
+! }
+ }
+! lua_pushstring(L, luaL_typename(L, 1)); /* fallback */
+! return 1;
+ }
+
+ static const luaL_Reg luaV_module[] = {
+***************
+*** 1088,1111 ****
+ {"eval", luaV_eval},
+ {"beep", luaV_beep},
+ {"line", luaV_line},
+ {"buffer", luaV_buffer},
+ {"window", luaV_window},
+ {"open", luaV_open},
+! {"isbuffer", luaV_isbuffer},
+! {"iswindow", luaV_iswindow},
+ {NULL, NULL}
+ };
+
+ static int
+ luaopen_vim(lua_State *L)
+ {
+! /* set environment */
+ lua_newtable(L);
+ lua_newtable(L);
+! lua_pushliteral(L, "v");
+ lua_setfield(L, -2, "__mode");
+! lua_setmetatable(L, -2);
+! lua_replace(L, LUA_ENVIRONINDEX);
+ /* print */
+ lua_pushcfunction(L, luaV_print);
+ lua_setglobal(L, "print");
+--- 1608,1695 ----
+ {"eval", luaV_eval},
+ {"beep", luaV_beep},
+ {"line", luaV_line},
++ {"list", luaV_list},
++ {"dict", luaV_dict},
+ {"buffer", luaV_buffer},
+ {"window", luaV_window},
+ {"open", luaV_open},
+! {"type", luaV_type},
+ {NULL, NULL}
+ };
+
++ /* for freeing list, dict, buffer and window objects; lightuserdata as arg */
++ static int
++ luaV_free(lua_State *L)
++ {
++ lua_pushnil(L);
++ luaV_setudata(L, lua_touserdata(L, 1));
++ return 0;
++ }
++
++ static int
++ luaV_luaeval (lua_State *L)
++ {
++ luaL_Buffer b;
++ size_t l;
++ const char *str = lua_tolstring(L, 1, &l);
++ typval_T *arg = (typval_T *) lua_touserdata(L, 2);
++ typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
++ luaL_buffinit(L, &b);
++ luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
++ luaL_addlstring(&b, str, l);
++ luaL_pushresult(&b);
++ str = lua_tolstring(L, -1, &l);
++ if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */
++ {
++ luaV_emsg(L);
++ return 0;
++ }
++ luaV_pushtypval(L, arg);
++ if (lua_pcall(L, 1, 1, 0)) /* running error? */
++ {
++ luaV_emsg(L);
++ return 0;
++ }
++ luaV_totypval(L, -1, rettv);
++ return 0;
++ }
++
++ static int
++ luaV_setref (lua_State *L)
++ {
++ int copyID = lua_tointeger(L, 1);
++ typval_T tv;
++ luaV_getfield(L, LUAVIM_LIST);
++ luaV_getfield(L, LUAVIM_DICT);
++ lua_pushnil(L);
++ while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
++ {
++ lua_getmetatable(L, -1);
++ if (lua_rawequal(L, -1, 2)) /* list? */
++ {
++ tv.v_type = VAR_LIST;
++ tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */
++ }
++ else if (lua_rawequal(L, -1, 3)) /* dict? */
++ {
++ tv.v_type = VAR_DICT;
++ tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
++ }
++ lua_pop(L, 2); /* metatable and value */
++ set_ref_in_tv(&tv, copyID);
++ }
++ return 0;
++ }
++
+ static int
+ luaopen_vim(lua_State *L)
+ {
+! /* set cache table */
+ lua_newtable(L);
+ lua_newtable(L);
+! lua_pushstring(L, "v");
+ lua_setfield(L, -2, "__mode");
+! lua_setmetatable(L, -2); /* cache is weak-valued */
+ /* print */
+ lua_pushcfunction(L, luaV_print);
+ lua_setglobal(L, "print");
+***************
+*** 1116,1129 ****
+ lua_pop(L, 1);
+ /* free */
+ lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
+! lua_pushcfunction(L, luaV_free);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ /* register */
+ luaV_newmetatable(L, LUAVIM_BUFFER);
+! luaL_register(L, NULL, luaV_Buffer_mt);
+ luaV_newmetatable(L, LUAVIM_WINDOW);
+! luaL_register(L, NULL, luaV_Window_mt);
+! luaL_register(L, LUAVIM_NAME, luaV_module);
+ return 0;
+ }
+
+--- 1700,1735 ----
+ lua_pop(L, 1);
+ /* free */
+ lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
+! lua_pushvalue(L, 1); /* cache table */
+! lua_pushcclosure(L, luaV_free, 1);
+! lua_rawset(L, LUA_REGISTRYINDEX);
+! /* luaeval */
+! lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
+! lua_pushvalue(L, 1); /* cache table */
+! lua_pushcclosure(L, luaV_luaeval, 1);
+! lua_rawset(L, LUA_REGISTRYINDEX);
+! /* setref */
+! lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
+! lua_pushvalue(L, 1); /* cache table */
+! lua_pushcclosure(L, luaV_setref, 1);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ /* register */
++ luaV_newmetatable(L, LUAVIM_LIST);
++ lua_pushvalue(L, 1);
++ luaV_openlib(L, luaV_List_mt, 1);
++ luaV_newmetatable(L, LUAVIM_DICT);
++ lua_pushvalue(L, 1);
++ luaV_openlib(L, luaV_Dict_mt, 1);
+ luaV_newmetatable(L, LUAVIM_BUFFER);
+! lua_pushvalue(L, 1); /* cache table */
+! luaV_openlib(L, luaV_Buffer_mt, 1);
+ luaV_newmetatable(L, LUAVIM_WINDOW);
+! lua_pushvalue(L, 1); /* cache table */
+! luaV_openlib(L, luaV_Window_mt, 1);
+! lua_newtable(L); /* vim table */
+! lua_pushvalue(L, 1); /* cache table */
+! luaV_openlib(L, luaV_module, 1);
+! lua_setglobal(L, LUAVIM_NAME);
+ return 0;
+ }
+
+***************
+*** 1154,1160 ****
+ static lua_State *L = NULL;
+
+ static int
+! lua_is_open(void)
+ {
+ return L != NULL;
+ }
+--- 1760,1766 ----
+ static lua_State *L = NULL;
+
+ static int
+! lua_isopen(void)
+ {
+ return L != NULL;
+ }
+***************
+*** 1162,1168 ****
+ static int
+ lua_init(void)
+ {
+! if (L == NULL)
+ {
+ #ifdef DYNAMIC_LUA
+ if (!lua_enabled(TRUE))
+--- 1768,1774 ----
+ static int
+ lua_init(void)
+ {
+! if (!lua_isopen())
+ {
+ #ifdef DYNAMIC_LUA
+ if (!lua_enabled(TRUE))
+***************
+*** 1179,1185 ****
+ void
+ lua_end(void)
+ {
+! if (L != NULL)
+ {
+ lua_close(L);
+ L = NULL;
+--- 1785,1791 ----
+ void
+ lua_end(void)
+ {
+! if (lua_isopen())
+ {
+ lua_close(L);
+ L = NULL;
+***************
+*** 1273,1295 ****
+ }
+ }
+
+! /* buffer */
+ void
+! lua_buffer_free(buf_T *buf)
+ {
+! if (!lua_is_open()) return;
+! luaV_getfield(L, LUAVIM_FREE);
+! lua_pushlightuserdata(L, (void *) buf);
+! lua_call(L, 1, 0);
+ }
+
+- /* window */
+ void
+! lua_window_free(win_T *win)
+ {
+! if (!lua_is_open()) return;
+! luaV_getfield(L, LUAVIM_FREE);
+! lua_pushlightuserdata(L, (void *) win);
+ lua_call(L, 1, 0);
+ }
+
+--- 1879,1914 ----
+ }
+ }
+
+! #define luaV_freetype(typ,tname) \
+! void \
+! lua_##tname##_free(typ *o) \
+! { \
+! if (!lua_isopen()) return; \
+! luaV_getfield(L, LUAVIM_FREE); \
+! lua_pushlightuserdata(L, (void *) o); \
+! lua_call(L, 1, 0); \
+! }
+!
+! luaV_freetype(buf_T, buffer)
+! luaV_freetype(win_T, window)
+!
+ void
+! do_luaeval (char_u *str, typval_T *arg, typval_T *rettv)
+ {
+! lua_init();
+! luaV_getfield(L, LUAVIM_LUAEVAL);
+! lua_pushstring(L, (char *) str);
+! lua_pushlightuserdata(L, (void *) arg);
+! lua_pushlightuserdata(L, (void *) rettv);
+! lua_call(L, 3, 0);
+ }
+
+ void
+! set_ref_in_lua (int copyID)
+ {
+! if (!lua_isopen()) return;
+! luaV_getfield(L, LUAVIM_SETREF);
+! lua_pushinteger(L, copyID);
+ lua_call(L, 1, 0);
+ }
+
+*** ../vim-7.3.489/src/proto/if_lua.pro 2010-08-15 21:57:28.000000000 +0200
+--- src/proto/if_lua.pro 2012-04-05 16:41:35.000000000 +0200
+***************
+*** 6,9 ****
+--- 6,11 ----
+ void ex_luafile __ARGS((exarg_T *eap));
+ void lua_buffer_free __ARGS((buf_T *buf));
+ void lua_window_free __ARGS((win_T *win));
++ void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
++ void set_ref_in_lua __ARGS((int copyID));
+ /* vim: set ft=c : */
+*** ../vim-7.3.489/src/version.c 2012-04-05 16:07:01.000000000 +0200
+--- src/version.c 2012-04-05 16:52:08.000000000 +0200
+***************
+*** 716,717 ****
+--- 716,719 ----
+ { /* Add new patch number below this line */
++ /**/
++ 490,
+ /**/
+
+--
+Even got a Datapoint 3600(?) with a DD50 connector instead of the
+usual DB25... what a nightmare trying to figure out the pinout
+for *that* with no spex...
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
+/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
+\\\ an exciting new programming language -- http://www.Zimbu.org ///
+ \\\ help me help AIDS victims -- http://ICCF-Holland.org ///