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