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