1/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved	by Bram Moolenaar
4 *
5 * Ruby interface by Shugo Maeda
6 *   with improvements by SegPhault (Ryan Paul)
7 *   with improvements by Jon Maken
8 *
9 * Do ":help uganda"  in Vim to read copying and usage conditions.
10 * Do ":help credits" in Vim to see a list of people who contributed.
11 * See README.txt for an overview of the Vim source code.
12 */
13
14#define VIM_SIZEOF_INT 4
15#if __LP64__
16#define VIM_SIZEOF_LONG 8
17#else
18#define VIM_SIZEOF_LONG 4
19#endif
20
21#ifdef HAVE_CONFIG_H
22# include "auto/config.h"
23#endif
24
25#include <stdio.h>
26#include <string.h>
27
28#ifdef _WIN32
29# if !defined(DYNAMIC_RUBY_VER) || (DYNAMIC_RUBY_VER < 18)
30#   define NT
31# endif
32# ifndef DYNAMIC_RUBY
33#  define IMPORT /* For static dll usage __declspec(dllimport) */
34#  define RUBYEXTERN __declspec(dllimport)
35# endif
36#endif
37#ifndef RUBYEXTERN
38# define RUBYEXTERN extern
39#endif
40
41#ifdef DYNAMIC_RUBY
42/*
43 * This is tricky.  In ruby.h there is (inline) function rb_class_of()
44 * definition.  This function use these variables.  But we want function to
45 * use dll_* variables.
46 */
47# define rb_cFalseClass		(*dll_rb_cFalseClass)
48# define rb_cFixnum		(*dll_rb_cFixnum)
49# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
50#  define rb_cFloat		(*dll_rb_cFloat)
51# endif
52# define rb_cNilClass		(*dll_rb_cNilClass)
53# define rb_cSymbol		(*dll_rb_cSymbol)
54# define rb_cTrueClass		(*dll_rb_cTrueClass)
55# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
56/*
57 * On ver 1.8, all Ruby functions are exported with "__declspec(dllimport)"
58 * in ruby.h.  But it causes trouble for these variables, because it is
59 * defined in this file.  When defined this RUBY_EXPORT it modified to
60 * "extern" and be able to avoid this problem.
61 */
62#  define RUBY_EXPORT
63# endif
64
65#if !(defined(WIN32) || defined(_WIN64))
66# include <dlfcn.h>
67# define HINSTANCE void*
68# define RUBY_PROC void*
69# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
70# define symbol_from_dll dlsym
71# define close_dll dlclose
72#else
73# define RUBY_PROC FARPROC
74# define load_dll vimLoadLib
75# define symbol_from_dll GetProcAddress
76# define close_dll FreeLibrary
77#endif
78
79#endif  /* ifdef DYNAMIC_RUBY */
80
81/* suggested by Ariya Mizutani */
82#if (_MSC_VER == 1200)
83# undef _WIN32_WINNT
84#endif
85
86#if (defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
87    || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
88# define RUBY19_OR_LATER 1
89#endif
90
91#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
92/* Ruby 1.9 defines a number of static functions which use rb_num2long and
93 * rb_int2big */
94# define rb_num2long rb_num2long_stub
95# define rb_int2big rb_int2big_stub
96#endif
97
98#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
99	&& VIM_SIZEOF_INT < VIM_SIZEOF_LONG
100/* Ruby 1.9 defines a number of static functions which use rb_fix2int and
101 * rb_num2int if VIM_SIZEOF_INT < VIM_SIZEOF_LONG (64bit) */
102# define rb_fix2int rb_fix2int_stub
103# define rb_num2int rb_num2int_stub
104#endif
105
106# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 21
107/* Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses
108 * rb_gc_writebarrier_unprotect_promoted if USE_RGENGC  */
109#  define rb_gc_writebarrier_unprotect_promoted rb_gc_writebarrier_unprotect_promoted_stub
110# endif
111
112#include <ruby.h>
113#ifdef RUBY19_OR_LATER
114# include <ruby/encoding.h>
115#endif
116
117#undef off_t	/* ruby defines off_t as _int64, Mingw uses long */
118#undef EXTERN
119#undef _
120
121/* T_DATA defined both by Ruby and Mac header files, hack around it... */
122#if defined(MACOS_X_UNIX) || defined(macintosh)
123# define __OPENTRANSPORT__
124# define __OPENTRANSPORTPROTOCOL__
125# define __OPENTRANSPORTPROVIDERS__
126#endif
127
128/*
129 * Backward compatibility for Ruby 1.8 and earlier.
130 * Ruby 1.9 does not provide STR2CSTR, instead StringValuePtr is provided.
131 * Ruby 1.9 does not provide RXXX(s)->len and RXXX(s)->ptr, instead
132 * RXXX_LEN(s) and RXXX_PTR(s) are provided.
133 */
134#ifndef StringValuePtr
135# define StringValuePtr(s) STR2CSTR(s)
136#endif
137#ifndef RARRAY_LEN
138# define RARRAY_LEN(s) RARRAY(s)->len
139#endif
140#ifndef RARRAY_PTR
141# define RARRAY_PTR(s) RARRAY(s)->ptr
142#endif
143#ifndef RSTRING_LEN
144# define RSTRING_LEN(s) RSTRING(s)->len
145#endif
146#ifndef RSTRING_PTR
147# define RSTRING_PTR(s) RSTRING(s)->ptr
148#endif
149
150#include "vim.h"
151#include "version.h"
152
153#if defined(PROTO) && !defined(FEAT_RUBY)
154/* Define these to be able to generate the function prototypes. */
155# define VALUE int
156# define RUBY_DATA_FUNC int
157#endif
158
159static int ruby_initialized = 0;
160static void *ruby_stack_start;
161static VALUE objtbl;
162
163static VALUE mVIM;
164static VALUE cBuffer;
165static VALUE cVimWindow;
166static VALUE eDeletedBufferError;
167static VALUE eDeletedWindowError;
168
169static int ensure_ruby_initialized(void);
170static void error_print(int);
171static void ruby_io_init(void);
172static void ruby_vim_init(void);
173
174#if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
175# if defined(__ia64) && !defined(ruby_init_stack)
176#  define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
177# endif
178#endif
179
180#if defined(DYNAMIC_RUBY) || defined(PROTO)
181# ifdef PROTO
182#  define HINSTANCE int		/* for generating prototypes */
183# endif
184
185/*
186 * Wrapper defines
187 */
188# define rb_assoc_new			dll_rb_assoc_new
189# define rb_cObject			(*dll_rb_cObject)
190# define rb_check_type			dll_rb_check_type
191# define rb_class_path			dll_rb_class_path
192# define rb_data_object_alloc		dll_rb_data_object_alloc
193# define rb_define_class_under		dll_rb_define_class_under
194# define rb_define_const			dll_rb_define_const
195# define rb_define_global_function	dll_rb_define_global_function
196# define rb_define_method		dll_rb_define_method
197# define rb_define_module		dll_rb_define_module
198# define rb_define_module_function	dll_rb_define_module_function
199# define rb_define_singleton_method	dll_rb_define_singleton_method
200# define rb_define_virtual_variable	dll_rb_define_virtual_variable
201# define rb_stdout			(*dll_rb_stdout)
202# define rb_eArgError			(*dll_rb_eArgError)
203# define rb_eIndexError			(*dll_rb_eIndexError)
204# define rb_eRuntimeError		(*dll_rb_eRuntimeError)
205# define rb_eStandardError		(*dll_rb_eStandardError)
206# define rb_eval_string_protect		dll_rb_eval_string_protect
207# define rb_global_variable		dll_rb_global_variable
208# define rb_hash_aset			dll_rb_hash_aset
209# define rb_hash_new			dll_rb_hash_new
210# define rb_inspect			dll_rb_inspect
211# define rb_int2inum			dll_rb_int2inum
212# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
213#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18
214#   define rb_fix2int			dll_rb_fix2int
215#   define rb_num2int			dll_rb_num2int
216#  endif
217#  define rb_num2uint			dll_rb_num2uint
218# endif
219# define rb_lastline_get			dll_rb_lastline_get
220# define rb_lastline_set			dll_rb_lastline_set
221# define rb_load_protect			dll_rb_load_protect
222# ifndef RUBY19_OR_LATER
223#  define rb_num2long			dll_rb_num2long
224# endif
225# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 19
226#  define rb_num2ulong			dll_rb_num2ulong
227# endif
228# define rb_obj_alloc			dll_rb_obj_alloc
229# define rb_obj_as_string		dll_rb_obj_as_string
230# define rb_obj_id			dll_rb_obj_id
231# define rb_raise			dll_rb_raise
232# define rb_str_cat			dll_rb_str_cat
233# define rb_str_concat			dll_rb_str_concat
234# define rb_str_new			dll_rb_str_new
235# ifdef rb_str_new2
236/* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
237#  define need_rb_str_new_cstr 1
238/* Ruby's headers #define rb_str_new_cstr to make use of GCC's
239 * __builtin_constant_p extension. */
240#  undef rb_str_new_cstr
241#  define rb_str_new_cstr		dll_rb_str_new_cstr
242# else
243#  define rb_str_new2			dll_rb_str_new2
244# endif
245# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
246#  define rb_string_value		dll_rb_string_value
247#  define rb_string_value_ptr		dll_rb_string_value_ptr
248#  define rb_float_new			dll_rb_float_new
249#  define rb_ary_new			dll_rb_ary_new
250#  define rb_ary_push			dll_rb_ary_push
251#  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
252#   ifdef __ia64
253#    define rb_ia64_bsp			dll_rb_ia64_bsp
254#    undef ruby_init_stack
255#    define ruby_init_stack(addr)	dll_ruby_init_stack((addr), rb_ia64_bsp())
256#   else
257#    define ruby_init_stack		dll_ruby_init_stack
258#   endif
259#  endif
260# else
261#  define rb_str2cstr			dll_rb_str2cstr
262# endif
263# ifdef RUBY19_OR_LATER
264#  define rb_errinfo			dll_rb_errinfo
265# else
266#  define ruby_errinfo			(*dll_ruby_errinfo)
267# endif
268# define ruby_init			dll_ruby_init
269# define ruby_init_loadpath		dll_ruby_init_loadpath
270# ifdef WIN3264
271#  define NtInitialize			dll_NtInitialize
272#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
273#   define rb_w32_snprintf		dll_rb_w32_snprintf
274#  endif
275# endif
276
277# ifdef RUBY19_OR_LATER
278#  define ruby_script			dll_ruby_script
279#  define rb_enc_find_index		dll_rb_enc_find_index
280#  define rb_enc_find			dll_rb_enc_find
281#  define rb_enc_str_new			dll_rb_enc_str_new
282#  define rb_sprintf			dll_rb_sprintf
283#  define rb_require			dll_rb_require
284#  define ruby_process_options		dll_ruby_process_options
285# endif
286
287/*
288 * Pointers for dynamic link
289 */
290static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
291VALUE *dll_rb_cFalseClass;
292VALUE *dll_rb_cFixnum;
293# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
294VALUE *dll_rb_cFloat;
295# endif
296VALUE *dll_rb_cNilClass;
297static VALUE *dll_rb_cObject;
298VALUE *dll_rb_cSymbol;
299VALUE *dll_rb_cTrueClass;
300static void (*dll_rb_check_type) (VALUE,int);
301static VALUE (*dll_rb_class_path) (VALUE);
302static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
303static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
304static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
305static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
306static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
307static VALUE (*dll_rb_define_module) (const char*);
308static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
309static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
310static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
311static VALUE *dll_rb_stdout;
312static VALUE *dll_rb_eArgError;
313static VALUE *dll_rb_eIndexError;
314static VALUE *dll_rb_eRuntimeError;
315static VALUE *dll_rb_eStandardError;
316static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
317static void (*dll_rb_global_variable) (VALUE*);
318static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
319static VALUE (*dll_rb_hash_new) (void);
320static VALUE (*dll_rb_inspect) (VALUE);
321static VALUE (*dll_rb_int2inum) (long);
322# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
323static long (*dll_rb_fix2int) (VALUE);
324static long (*dll_rb_num2int) (VALUE);
325static unsigned long (*dll_rb_num2uint) (VALUE);
326# endif
327static VALUE (*dll_rb_lastline_get) (void);
328static void (*dll_rb_lastline_set) (VALUE);
329static void (*dll_rb_load_protect) (VALUE, int, int*);
330static long (*dll_rb_num2long) (VALUE);
331static unsigned long (*dll_rb_num2ulong) (VALUE);
332static VALUE (*dll_rb_obj_alloc) (VALUE);
333static VALUE (*dll_rb_obj_as_string) (VALUE);
334static VALUE (*dll_rb_obj_id) (VALUE);
335static void (*dll_rb_raise) (VALUE, const char*, ...);
336# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
337static VALUE (*dll_rb_string_value) (volatile VALUE*);
338# else
339static char *(*dll_rb_str2cstr) (VALUE,int*);
340# endif
341static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
342static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
343static VALUE (*dll_rb_str_new) (const char*, long);
344# ifdef need_rb_str_new_cstr
345/* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
346static VALUE (*dll_rb_str_new_cstr) (const char*);
347# else
348static VALUE (*dll_rb_str_new2) (const char*);
349# endif
350# ifdef RUBY19_OR_LATER
351static VALUE (*dll_rb_errinfo) (void);
352# else
353static VALUE *dll_ruby_errinfo;
354# endif
355static void (*dll_ruby_init) (void);
356static void (*dll_ruby_init_loadpath) (void);
357# ifdef WIN3264
358static void (*dll_NtInitialize) (int*, char***);
359#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
360static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
361#  endif
362# endif
363# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
364static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
365static VALUE (*dll_rb_float_new) (double);
366static VALUE (*dll_rb_ary_new) (void);
367static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
368#  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
369#   ifdef __ia64
370static void * (*dll_rb_ia64_bsp) (void);
371static void (*dll_ruby_init_stack)(VALUE*, void*);
372#   else
373static void (*dll_ruby_init_stack)(VALUE*);
374#   endif
375#  endif
376# endif
377# ifdef RUBY19_OR_LATER
378static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
379# endif
380
381# ifdef RUBY19_OR_LATER
382static void (*dll_ruby_script) (const char*);
383static int (*dll_rb_enc_find_index) (const char*);
384static rb_encoding* (*dll_rb_enc_find) (const char*);
385static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
386static VALUE (*dll_rb_sprintf) (const char*, ...);
387static VALUE (*dll_rb_require) (const char*);
388static void* (*ruby_process_options)(int, char**);
389# endif
390
391# if defined(USE_RGENGC) && USE_RGENGC
392static void (*dll_rb_gc_writebarrier_unprotect_promoted)(VALUE);
393# endif
394
395# if defined(RUBY19_OR_LATER) && !defined(PROTO)
396SIGNED_VALUE rb_num2long_stub(VALUE x)
397{
398    return dll_rb_num2long(x);
399}
400VALUE rb_int2big_stub(SIGNED_VALUE x)
401{
402    return dll_rb_int2big(x);
403}
404#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
405	&& VIM_SIZEOF_INT < VIM_SIZEOF_LONG
406long rb_fix2int_stub(VALUE x)
407{
408    return dll_rb_fix2int(x);
409}
410long rb_num2int_stub(VALUE x)
411{
412    return dll_rb_num2int(x);
413}
414#  endif
415#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
416VALUE
417rb_float_new_in_heap(double d)
418{
419    return dll_rb_float_new(d);
420}
421VALUE rb_num2ulong(VALUE x)
422{
423    return (long)RSHIFT((SIGNED_VALUE)(x),1);
424}
425#  endif
426# endif
427
428# if defined(USE_RGENGC) && USE_RGENGC
429void rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj)
430{
431    return dll_rb_gc_writebarrier_unprotect_promoted(obj);
432}
433# endif
434
435static HINSTANCE hinstRuby = NULL; /* Instance of ruby.dll */
436
437/*
438 * Table of name to function pointer of ruby.
439 */
440static struct
441{
442    char *name;
443    RUBY_PROC *ptr;
444} ruby_funcname_table[] =
445{
446    {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
447    {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
448    {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
449# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
450    {"rb_cFloat", (RUBY_PROC*)&dll_rb_cFloat},
451# endif
452    {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
453    {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
454    {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
455    {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
456    {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
457    {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
458    {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
459    {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
460    {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
461    {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
462    {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
463    {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
464    {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
465    {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
466    {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
467    {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
468    {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
469    {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
470    {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
471    {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
472    {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
473    {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
474    {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
475    {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
476    {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
477    {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
478# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
479    {"rb_fix2int", (RUBY_PROC*)&dll_rb_fix2int},
480    {"rb_num2int", (RUBY_PROC*)&dll_rb_num2int},
481    {"rb_num2uint", (RUBY_PROC*)&dll_rb_num2uint},
482# endif
483    {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
484    {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
485    {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
486    {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
487    {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
488    {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
489    {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
490    {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
491    {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
492# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
493    {"rb_string_value", (RUBY_PROC*)&dll_rb_string_value},
494# else
495    {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
496# endif
497    {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
498    {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
499    {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
500# ifdef need_rb_str_new_cstr
501    {"rb_str_new_cstr", (RUBY_PROC*)&dll_rb_str_new_cstr},
502# else
503    {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
504# endif
505# ifdef RUBY19_OR_LATER
506    {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
507# else
508    {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
509# endif
510    {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
511    {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
512# ifdef WIN3264
513    {
514#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19
515    "NtInitialize",
516#  else
517    "ruby_sysinit",
518#  endif
519			(RUBY_PROC*)&dll_NtInitialize},
520#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
521    {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
522#  endif
523# endif
524# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
525    {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
526#  if DYNAMIC_RUBY_VER <= 19
527    {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
528#  else
529    {"rb_float_new_in_heap", (RUBY_PROC*)&dll_rb_float_new},
530#  endif
531    {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
532    {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
533# endif
534# ifdef RUBY19_OR_LATER
535    {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
536    {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
537    {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
538    {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
539    {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
540    {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
541    {"rb_require", (RUBY_PROC*)&dll_rb_require},
542    {"ruby_process_options", (RUBY_PROC*)&dll_ruby_process_options},
543# endif
544# if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
545#  ifdef __ia64
546    {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp},
547#  endif
548    {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
549# endif
550# if defined(USE_RGENGC) && USE_RGENGC
551    {"rb_gc_writebarrier_unprotect_promoted", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect_promoted},
552# endif
553    {"", NULL},
554};
555
556/*
557 * Free ruby.dll
558 */
559    static void
560end_dynamic_ruby()
561{
562    if (hinstRuby)
563    {
564	close_dll(hinstRuby);
565	hinstRuby = NULL;
566    }
567}
568
569/*
570 * Load library and get all pointers.
571 * Parameter 'libname' provides name of DLL.
572 * Return OK or FAIL.
573 */
574    static int
575ruby_runtime_link_init(char *libname, int verbose)
576{
577    int i;
578
579    if (hinstRuby)
580	return OK;
581    hinstRuby = load_dll(libname);
582    if (!hinstRuby)
583    {
584	if (verbose)
585	    EMSG2(_(e_loadlib), libname);
586	return FAIL;
587    }
588
589    for (i = 0; ruby_funcname_table[i].ptr; ++i)
590    {
591	if (!(*ruby_funcname_table[i].ptr = symbol_from_dll(hinstRuby,
592			ruby_funcname_table[i].name)))
593	{
594	    close_dll(hinstRuby);
595	    hinstRuby = NULL;
596	    if (verbose)
597		EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
598	    return FAIL;
599	}
600    }
601    return OK;
602}
603
604/*
605 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
606 * else FALSE.
607 */
608    int
609ruby_enabled(verbose)
610    int		verbose;
611{
612    return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
613}
614#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
615
616    void
617ruby_end()
618{
619#ifdef DYNAMIC_RUBY
620    end_dynamic_ruby();
621#endif
622}
623
624void ex_ruby(exarg_T *eap)
625{
626    int state;
627    char *script = NULL;
628
629    script = (char *)script_get(eap, eap->arg);
630    if (!eap->skip && ensure_ruby_initialized())
631    {
632	if (script == NULL)
633	    rb_eval_string_protect((char *)eap->arg, &state);
634	else
635	    rb_eval_string_protect(script, &state);
636	if (state)
637	    error_print(state);
638    }
639    vim_free(script);
640}
641
642/*
643 *  In Ruby 1.9 or later, ruby String object has encoding.
644 *  conversion buffer string of vim to ruby String object using
645 *  VIM encoding option.
646 */
647    static VALUE
648vim_str2rb_enc_str(const char *s)
649{
650#ifdef RUBY19_OR_LATER
651    int isnum;
652    long lval;
653    char_u *sval;
654    rb_encoding *enc;
655
656    isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
657    if (isnum == 0)
658    {
659	enc = rb_enc_find((char *)sval);
660	vim_free(sval);
661	if (enc) {
662	    return rb_enc_str_new(s, strlen(s), enc);
663	}
664    }
665#endif
666    return rb_str_new2(s);
667}
668
669    static VALUE
670eval_enc_string_protect(const char *str, int *state)
671{
672#ifdef RUBY19_OR_LATER
673    int isnum;
674    long lval;
675    char_u *sval;
676    rb_encoding *enc;
677    VALUE v;
678
679    isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
680    if (isnum == 0)
681    {
682	enc = rb_enc_find((char *)sval);
683	vim_free(sval);
684	if (enc)
685	{
686	    v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
687	    return rb_eval_string_protect(StringValuePtr(v), state);
688	}
689    }
690#endif
691    return rb_eval_string_protect(str, state);
692}
693
694void ex_rubydo(exarg_T *eap)
695{
696    int state;
697    linenr_T i;
698
699    if (ensure_ruby_initialized())
700    {
701	if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
702	    return;
703	for (i = eap->line1; i <= eap->line2; i++) {
704	    VALUE line;
705
706	    line = vim_str2rb_enc_str((char *)ml_get(i));
707	    rb_lastline_set(line);
708	    eval_enc_string_protect((char *) eap->arg, &state);
709	    if (state) {
710		error_print(state);
711		break;
712	    }
713	    line = rb_lastline_get();
714	    if (!NIL_P(line)) {
715		if (TYPE(line) != T_STRING) {
716		    EMSG(_("E265: $_ must be an instance of String"));
717		    return;
718		}
719		ml_replace(i, (char_u *) StringValuePtr(line), 1);
720		changed();
721#ifdef SYNTAX_HL
722		syn_changed(i); /* recompute syntax hl. for this line */
723#endif
724	    }
725	}
726	check_cursor();
727	update_curbuf(NOT_VALID);
728    }
729}
730
731void ex_rubyfile(exarg_T *eap)
732{
733    int state;
734
735    if (ensure_ruby_initialized())
736    {
737	rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
738	if (state) error_print(state);
739    }
740}
741
742void ruby_buffer_free(buf_T *buf)
743{
744    if (buf->b_ruby_ref)
745    {
746	rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
747	RDATA(buf->b_ruby_ref)->data = NULL;
748    }
749}
750
751void ruby_window_free(win_T *win)
752{
753    if (win->w_ruby_ref)
754    {
755	rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
756	RDATA(win->w_ruby_ref)->data = NULL;
757    }
758}
759
760static int ensure_ruby_initialized(void)
761{
762    if (!ruby_initialized)
763    {
764#ifdef DYNAMIC_RUBY
765	if (ruby_enabled(TRUE))
766	{
767#endif
768#ifdef _WIN32
769	    /* suggested by Ariya Mizutani */
770	    int argc = 1;
771	    char *argv[] = {"gvim.exe"};
772	    NtInitialize(&argc, &argv);
773#endif
774	    {
775#if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
776		ruby_init_stack(ruby_stack_start);
777#endif
778		ruby_init();
779	    }
780#ifdef RUBY19_OR_LATER
781	    {
782		int dummy_argc = 2;
783		char *dummy_argv[] = {"vim-ruby", "-e0"};
784		ruby_process_options(dummy_argc, dummy_argv);
785	    }
786	    ruby_script("vim-ruby");
787#else
788	    ruby_init_loadpath();
789#endif
790	    ruby_io_init();
791	    ruby_vim_init();
792	    ruby_initialized = 1;
793#ifdef DYNAMIC_RUBY
794	}
795	else
796	{
797	    EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
798	    return 0;
799	}
800#endif
801    }
802    return ruby_initialized;
803}
804
805static void error_print(int state)
806{
807#ifndef DYNAMIC_RUBY
808#if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
809    && !(defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
810    RUBYEXTERN VALUE ruby_errinfo;
811#endif
812#endif
813    VALUE eclass;
814    VALUE einfo;
815    char buff[BUFSIZ];
816
817#define TAG_RETURN	0x1
818#define TAG_BREAK	0x2
819#define TAG_NEXT	0x3
820#define TAG_RETRY	0x4
821#define TAG_REDO	0x5
822#define TAG_RAISE	0x6
823#define TAG_THROW	0x7
824#define TAG_FATAL	0x8
825#define TAG_MASK	0xf
826
827    switch (state) {
828    case TAG_RETURN:
829	EMSG(_("E267: unexpected return"));
830	break;
831    case TAG_NEXT:
832	EMSG(_("E268: unexpected next"));
833	break;
834    case TAG_BREAK:
835	EMSG(_("E269: unexpected break"));
836	break;
837    case TAG_REDO:
838	EMSG(_("E270: unexpected redo"));
839	break;
840    case TAG_RETRY:
841	EMSG(_("E271: retry outside of rescue clause"));
842	break;
843    case TAG_RAISE:
844    case TAG_FATAL:
845#ifdef RUBY19_OR_LATER
846	eclass = CLASS_OF(rb_errinfo());
847	einfo = rb_obj_as_string(rb_errinfo());
848#else
849	eclass = CLASS_OF(ruby_errinfo);
850	einfo = rb_obj_as_string(ruby_errinfo);
851#endif
852	if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) {
853	    EMSG(_("E272: unhandled exception"));
854	}
855	else {
856	    VALUE epath;
857	    char *p;
858
859	    epath = rb_class_path(eclass);
860	    vim_snprintf(buff, BUFSIZ, "%s: %s",
861		     RSTRING_PTR(epath), RSTRING_PTR(einfo));
862	    p = strchr(buff, '\n');
863	    if (p) *p = '\0';
864	    EMSG(buff);
865	}
866	break;
867    default:
868	vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
869	EMSG(buff);
870	break;
871    }
872}
873
874static VALUE vim_message(VALUE self UNUSED, VALUE str)
875{
876    char *buff, *p;
877
878    str = rb_obj_as_string(str);
879    if (RSTRING_LEN(str) > 0)
880    {
881	/* Only do this when the string isn't empty, alloc(0) causes trouble. */
882	buff = ALLOCA_N(char, RSTRING_LEN(str));
883	strcpy(buff, RSTRING_PTR(str));
884	p = strchr(buff, '\n');
885	if (p) *p = '\0';
886	MSG(buff);
887    }
888    else
889    {
890	MSG("");
891    }
892    return Qnil;
893}
894
895static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
896{
897    do_set((char_u *)StringValuePtr(str), 0);
898    update_screen(NOT_VALID);
899    return Qnil;
900}
901
902static VALUE vim_command(VALUE self UNUSED, VALUE str)
903{
904    do_cmdline_cmd((char_u *)StringValuePtr(str));
905    return Qnil;
906}
907
908#ifdef FEAT_EVAL
909static VALUE vim_to_ruby(typval_T *tv)
910{
911    VALUE result = Qnil;
912
913    if (tv->v_type == VAR_STRING)
914    {
915	result = rb_str_new2(tv->vval.v_string == NULL
916					  ? "" : (char *)(tv->vval.v_string));
917    }
918    else if (tv->v_type == VAR_NUMBER)
919    {
920	result = INT2NUM(tv->vval.v_number);
921    }
922# ifdef FEAT_FLOAT
923    else if (tv->v_type == VAR_FLOAT)
924    {
925	result = rb_float_new(tv->vval.v_float);
926    }
927# endif
928    else if (tv->v_type == VAR_LIST)
929    {
930	list_T      *list = tv->vval.v_list;
931	listitem_T  *curr;
932
933	result = rb_ary_new();
934
935	if (list != NULL)
936	{
937	    for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
938	    {
939		rb_ary_push(result, vim_to_ruby(&curr->li_tv));
940	    }
941	}
942    }
943    else if (tv->v_type == VAR_DICT)
944    {
945	result = rb_hash_new();
946
947	if (tv->vval.v_dict != NULL)
948	{
949	    hashtab_T   *ht = &tv->vval.v_dict->dv_hashtab;
950	    long_u      todo = ht->ht_used;
951	    hashitem_T  *hi;
952	    dictitem_T  *di;
953
954	    for (hi = ht->ht_array; todo > 0; ++hi)
955	    {
956		if (!HASHITEM_EMPTY(hi))
957		{
958		    --todo;
959
960		    di = dict_lookup(hi);
961		    rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
962						     vim_to_ruby(&di->di_tv));
963		}
964	    }
965	}
966    } /* else return Qnil; */
967
968    return result;
969}
970#endif
971
972static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
973{
974#ifdef FEAT_EVAL
975    typval_T    *tv;
976    VALUE       result;
977
978    tv = eval_expr((char_u *)StringValuePtr(str), NULL);
979    if (tv == NULL)
980    {
981	return Qnil;
982    }
983    result = vim_to_ruby(tv);
984
985    free_tv(tv);
986
987    return result;
988#else
989    return Qnil;
990#endif
991}
992
993static VALUE buffer_new(buf_T *buf)
994{
995    if (buf->b_ruby_ref)
996    {
997	return (VALUE) buf->b_ruby_ref;
998    }
999    else
1000    {
1001	VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
1002	buf->b_ruby_ref = (void *) obj;
1003	rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1004	return obj;
1005    }
1006}
1007
1008static buf_T *get_buf(VALUE obj)
1009{
1010    buf_T *buf;
1011
1012    Data_Get_Struct(obj, buf_T, buf);
1013    if (buf == NULL)
1014	rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
1015    return buf;
1016}
1017
1018static VALUE buffer_s_current()
1019{
1020    return buffer_new(curbuf);
1021}
1022
1023static VALUE buffer_s_count()
1024{
1025    buf_T *b;
1026    int n = 0;
1027
1028    for (b = firstbuf; b != NULL; b = b->b_next)
1029    {
1030	/*  Deleted buffers should not be counted
1031	 *    SegPhault - 01/07/05 */
1032	if (b->b_p_bl)
1033	    n++;
1034    }
1035
1036    return INT2NUM(n);
1037}
1038
1039static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
1040{
1041    buf_T *b;
1042    int n = NUM2INT(num);
1043
1044    for (b = firstbuf; b != NULL; b = b->b_next)
1045    {
1046	/*  Deleted buffers should not be counted
1047	 *    SegPhault - 01/07/05 */
1048	if (!b->b_p_bl)
1049	    continue;
1050
1051	if (n == 0)
1052	    return buffer_new(b);
1053
1054	n--;
1055    }
1056    return Qnil;
1057}
1058
1059static VALUE buffer_name(VALUE self)
1060{
1061    buf_T *buf = get_buf(self);
1062
1063    return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
1064}
1065
1066static VALUE buffer_number(VALUE self)
1067{
1068    buf_T *buf = get_buf(self);
1069
1070    return INT2NUM(buf->b_fnum);
1071}
1072
1073static VALUE buffer_count(VALUE self)
1074{
1075    buf_T *buf = get_buf(self);
1076
1077    return INT2NUM(buf->b_ml.ml_line_count);
1078}
1079
1080static VALUE get_buffer_line(buf_T *buf, linenr_T n)
1081{
1082    if (n <= 0 || n > buf->b_ml.ml_line_count)
1083	rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
1084    return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE));
1085}
1086
1087static VALUE buffer_aref(VALUE self, VALUE num)
1088{
1089    buf_T *buf = get_buf(self);
1090
1091    if (buf != NULL)
1092	return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
1093    return Qnil; /* For stop warning */
1094}
1095
1096static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
1097{
1098    char	*line = StringValuePtr(str);
1099    aco_save_T	aco;
1100
1101    if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
1102    {
1103	/* set curwin/curbuf for "buf" and save some things */
1104	aucmd_prepbuf(&aco, buf);
1105
1106	if (u_savesub(n) == OK) {
1107	    ml_replace(n, (char_u *)line, TRUE);
1108	    changed();
1109#ifdef SYNTAX_HL
1110	    syn_changed(n); /* recompute syntax hl. for this line */
1111#endif
1112	}
1113
1114	/* restore curwin/curbuf and a few other things */
1115	aucmd_restbuf(&aco);
1116	/* Careful: autocommands may have made "buf" invalid! */
1117
1118	update_curbuf(NOT_VALID);
1119    }
1120    else
1121    {
1122	rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
1123    }
1124    return str;
1125}
1126
1127static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
1128{
1129    buf_T *buf = get_buf(self);
1130
1131    if (buf != NULL)
1132	return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
1133    return str;
1134}
1135
1136static VALUE buffer_delete(VALUE self, VALUE num)
1137{
1138    buf_T	*buf = get_buf(self);
1139    long	n = NUM2LONG(num);
1140    aco_save_T	aco;
1141
1142    if (n > 0 && n <= buf->b_ml.ml_line_count)
1143    {
1144	/* set curwin/curbuf for "buf" and save some things */
1145	aucmd_prepbuf(&aco, buf);
1146
1147	if (u_savedel(n, 1) == OK) {
1148	    ml_delete(n, 0);
1149
1150	    /* Changes to non-active buffers should properly refresh
1151	     *   SegPhault - 01/09/05 */
1152	    deleted_lines_mark(n, 1L);
1153
1154	    changed();
1155	}
1156
1157	/* restore curwin/curbuf and a few other things */
1158	aucmd_restbuf(&aco);
1159	/* Careful: autocommands may have made "buf" invalid! */
1160
1161	update_curbuf(NOT_VALID);
1162    }
1163    else
1164    {
1165	rb_raise(rb_eIndexError, "line number %ld out of range", n);
1166    }
1167    return Qnil;
1168}
1169
1170static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
1171{
1172    buf_T	*buf = get_buf(self);
1173    char	*line = StringValuePtr(str);
1174    long	n = NUM2LONG(num);
1175    aco_save_T	aco;
1176
1177    if (line == NULL)
1178    {
1179	rb_raise(rb_eIndexError, "NULL line");
1180    }
1181    else if (n >= 0 && n <= buf->b_ml.ml_line_count)
1182    {
1183	/* set curwin/curbuf for "buf" and save some things */
1184	aucmd_prepbuf(&aco, buf);
1185
1186	if (u_inssub(n + 1) == OK) {
1187	    ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
1188
1189	    /*  Changes to non-active buffers should properly refresh screen
1190	     *    SegPhault - 12/20/04 */
1191	    appended_lines_mark(n, 1L);
1192
1193	    changed();
1194	}
1195
1196	/* restore curwin/curbuf and a few other things */
1197	aucmd_restbuf(&aco);
1198	/* Careful: autocommands may have made "buf" invalid! */
1199
1200	update_curbuf(NOT_VALID);
1201    }
1202    else
1203    {
1204	rb_raise(rb_eIndexError, "line number %ld out of range", n);
1205    }
1206    return str;
1207}
1208
1209static VALUE window_new(win_T *win)
1210{
1211    if (win->w_ruby_ref)
1212    {
1213	return (VALUE) win->w_ruby_ref;
1214    }
1215    else
1216    {
1217	VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
1218	win->w_ruby_ref = (void *) obj;
1219	rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1220	return obj;
1221    }
1222}
1223
1224static win_T *get_win(VALUE obj)
1225{
1226    win_T *win;
1227
1228    Data_Get_Struct(obj, win_T, win);
1229    if (win == NULL)
1230	rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1231    return win;
1232}
1233
1234static VALUE window_s_current()
1235{
1236    return window_new(curwin);
1237}
1238
1239/*
1240 * Added line manipulation functions
1241 *    SegPhault - 03/07/05
1242 */
1243static VALUE line_s_current()
1244{
1245    return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1246}
1247
1248static VALUE set_current_line(VALUE self UNUSED, VALUE str)
1249{
1250    return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1251}
1252
1253static VALUE current_line_number()
1254{
1255    return INT2FIX((int)curwin->w_cursor.lnum);
1256}
1257
1258
1259
1260static VALUE window_s_count()
1261{
1262#ifdef FEAT_WINDOWS
1263    win_T	*w;
1264    int n = 0;
1265
1266    for (w = firstwin; w != NULL; w = w->w_next)
1267	n++;
1268    return INT2NUM(n);
1269#else
1270    return INT2NUM(1);
1271#endif
1272}
1273
1274static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
1275{
1276    win_T *w;
1277    int n = NUM2INT(num);
1278
1279#ifndef FEAT_WINDOWS
1280    w = curwin;
1281#else
1282    for (w = firstwin; w != NULL; w = w->w_next, --n)
1283#endif
1284	if (n == 0)
1285	    return window_new(w);
1286    return Qnil;
1287}
1288
1289static VALUE window_buffer(VALUE self)
1290{
1291    win_T *win = get_win(self);
1292
1293    return buffer_new(win->w_buffer);
1294}
1295
1296static VALUE window_height(VALUE self)
1297{
1298    win_T *win = get_win(self);
1299
1300    return INT2NUM(win->w_height);
1301}
1302
1303static VALUE window_set_height(VALUE self, VALUE height)
1304{
1305    win_T *win = get_win(self);
1306    win_T *savewin = curwin;
1307
1308    curwin = win;
1309    win_setheight(NUM2INT(height));
1310    curwin = savewin;
1311    return height;
1312}
1313
1314static VALUE window_width(VALUE self UNUSED)
1315{
1316    return INT2NUM(W_WIDTH(get_win(self)));
1317}
1318
1319static VALUE window_set_width(VALUE self UNUSED, VALUE width)
1320{
1321#ifdef FEAT_VERTSPLIT
1322    win_T *win = get_win(self);
1323    win_T *savewin = curwin;
1324
1325    curwin = win;
1326    win_setwidth(NUM2INT(width));
1327    curwin = savewin;
1328#endif
1329    return width;
1330}
1331
1332static VALUE window_cursor(VALUE self)
1333{
1334    win_T *win = get_win(self);
1335
1336    return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1337}
1338
1339static VALUE window_set_cursor(VALUE self, VALUE pos)
1340{
1341    VALUE lnum, col;
1342    win_T *win = get_win(self);
1343
1344    Check_Type(pos, T_ARRAY);
1345    if (RARRAY_LEN(pos) != 2)
1346	rb_raise(rb_eArgError, "array length must be 2");
1347    lnum = RARRAY_PTR(pos)[0];
1348    col = RARRAY_PTR(pos)[1];
1349    win->w_cursor.lnum = NUM2LONG(lnum);
1350    win->w_cursor.col = NUM2UINT(col);
1351    check_cursor();		    /* put cursor on an existing line */
1352    update_screen(NOT_VALID);
1353    return Qnil;
1354}
1355
1356static VALUE f_nop(VALUE self UNUSED)
1357{
1358    return Qnil;
1359}
1360
1361static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
1362{
1363    int i;
1364    VALUE str = rb_str_new("", 0);
1365
1366    for (i = 0; i < argc; i++) {
1367	if (i > 0) rb_str_cat(str, ", ", 2);
1368	rb_str_concat(str, rb_inspect(argv[i]));
1369    }
1370    MSG(RSTRING_PTR(str));
1371    return Qnil;
1372}
1373
1374static void ruby_io_init(void)
1375{
1376#ifndef DYNAMIC_RUBY
1377    RUBYEXTERN VALUE rb_stdout;
1378#endif
1379
1380    rb_stdout = rb_obj_alloc(rb_cObject);
1381    rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1382    rb_define_singleton_method(rb_stdout, "flush", f_nop, 0);
1383    rb_define_global_function("p", f_p, -1);
1384}
1385
1386static void ruby_vim_init(void)
1387{
1388    objtbl = rb_hash_new();
1389    rb_global_variable(&objtbl);
1390
1391    /* The Vim module used to be called "VIM", but "Vim" is better.  Make an
1392     * alias "VIM" for backwards compatibility. */
1393    mVIM = rb_define_module("Vim");
1394    rb_define_const(rb_cObject, "VIM", mVIM);
1395    rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1396    rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1397    rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1398    rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1399    rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1400    rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1401    rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1402    rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1403    rb_define_module_function(mVIM, "message", vim_message, 1);
1404    rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1405    rb_define_module_function(mVIM, "command", vim_command, 1);
1406    rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1407
1408    eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1409						rb_eStandardError);
1410    eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1411						rb_eStandardError);
1412
1413    cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1414    rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1415    rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1416    rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1417    rb_define_method(cBuffer, "name", buffer_name, 0);
1418    rb_define_method(cBuffer, "number", buffer_number, 0);
1419    rb_define_method(cBuffer, "count", buffer_count, 0);
1420    rb_define_method(cBuffer, "length", buffer_count, 0);
1421    rb_define_method(cBuffer, "[]", buffer_aref, 1);
1422    rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1423    rb_define_method(cBuffer, "delete", buffer_delete, 1);
1424    rb_define_method(cBuffer, "append", buffer_append, 2);
1425
1426    /* Added line manipulation functions
1427     *   SegPhault - 03/07/05 */
1428    rb_define_method(cBuffer, "line_number", current_line_number, 0);
1429    rb_define_method(cBuffer, "line", line_s_current, 0);
1430    rb_define_method(cBuffer, "line=", set_current_line, 1);
1431
1432
1433    cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1434    rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1435    rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1436    rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1437    rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1438    rb_define_method(cVimWindow, "height", window_height, 0);
1439    rb_define_method(cVimWindow, "height=", window_set_height, 1);
1440    rb_define_method(cVimWindow, "width", window_width, 0);
1441    rb_define_method(cVimWindow, "width=", window_set_width, 1);
1442    rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1443    rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1444
1445    rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1446    rb_define_virtual_variable("$curwin", window_s_current, 0);
1447}
1448
1449void vim_ruby_init(void *stack_start)
1450{
1451    /* should get machine stack start address early in main function */
1452    ruby_stack_start = stack_start;
1453}
1454