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