blob: 8003d4c88c1edc80fb56bf5f556d068e38ce64f8 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00004 *
5 * Ruby interface by Shugo Maeda
6 * with improvements by SegPhault (Ryan Paul)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007 *
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/*
Bram Moolenaar42d57f02010-03-10 12:47:00 +010042 * 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
Bram Moolenaar071d4272004-06-13 20:20:40 +000044 * 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
Bram Moolenaar0b69c732010-02-17 15:11:50 +010051/* suggested by Ariya Mizutani */
52#if (_MSC_VER == 1200)
53# undef _WIN32_WINNT
54#endif
55
Bram Moolenaar639a2552010-03-17 18:15:23 +010056#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
Bram Moolenaar42d57f02010-03-10 12:47:00 +010061#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
Bram Moolenaar071d4272004-06-13 20:20:40 +000068#include <ruby.h>
Bram Moolenaar639a2552010-03-17 18:15:23 +010069#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +010070# include <ruby/encoding.h>
71#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000072
73#undef EXTERN
74#undef _
75
76/* T_DATA defined both by Ruby and Mac header files, hack around it... */
Bram Moolenaarcb635362007-05-12 13:02:42 +000077#if defined(MACOS_X_UNIX) || defined(macintosh)
Bram Moolenaar071d4272004-06-13 20:20:40 +000078# define __OPENTRANSPORT__
79# define __OPENTRANSPORTPROTOCOL__
80# define __OPENTRANSPORTPROVIDERS__
81#endif
82
Bram Moolenaar165641d2010-02-17 16:23:09 +010083/*
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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105#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
114static int ruby_initialized = 0;
115static VALUE objtbl;
116
117static VALUE mVIM;
118static VALUE cBuffer;
119static VALUE cVimWindow;
120static VALUE eDeletedBufferError;
121static VALUE eDeletedWindowError;
122
123static int ensure_ruby_initialized(void);
124static void error_print(int);
125static void ruby_io_init(void);
126static 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
Bram Moolenaar218116c2010-05-20 21:46:00 +0200173/* Ruby may also define rb_str_new2. */
174#ifndef rb_str_new2
175# define rb_str_new2 dll_rb_str_new2
176#endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100177#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
178# define rb_string_value_ptr dll_rb_string_value_ptr
179# define rb_float_new dll_rb_float_new
180# define rb_ary_new dll_rb_ary_new
181# define rb_ary_push dll_rb_ary_push
182#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100183#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100184# define rb_errinfo dll_rb_errinfo
185#else
186# define ruby_errinfo (*dll_ruby_errinfo)
187#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000188#define ruby_init dll_ruby_init
189#define ruby_init_loadpath dll_ruby_init_loadpath
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100190#define NtInitialize dll_NtInitialize
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
192# define rb_w32_snprintf dll_rb_w32_snprintf
193#endif
194
Bram Moolenaar639a2552010-03-17 18:15:23 +0100195#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100196# define ruby_script dll_ruby_script
197# define rb_enc_find_index dll_rb_enc_find_index
198# define rb_enc_find dll_rb_enc_find
199# define rb_enc_str_new dll_rb_enc_str_new
200# define rb_sprintf dll_rb_sprintf
Bram Moolenaar639a2552010-03-17 18:15:23 +0100201# define ruby_init_stack dll_ruby_init_stack
Bram Moolenaar165641d2010-02-17 16:23:09 +0100202#endif
203
Bram Moolenaar071d4272004-06-13 20:20:40 +0000204/*
205 * Pointers for dynamic link
206 */
207static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
208static VALUE *dll_rb_cFalseClass;
209static VALUE *dll_rb_cFixnum;
210static VALUE *dll_rb_cNilClass;
211static VALUE *dll_rb_cObject;
212static VALUE *dll_rb_cSymbol;
213static VALUE *dll_rb_cTrueClass;
214static void (*dll_rb_check_type) (VALUE,int);
215static VALUE (*dll_rb_class_path) (VALUE);
216static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
217static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
218static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
219static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
220static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
221static VALUE (*dll_rb_define_module) (const char*);
222static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
223static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
224static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
225static VALUE *dll_rb_stdout;
226static VALUE *dll_rb_eArgError;
227static VALUE *dll_rb_eIndexError;
228static VALUE *dll_rb_eRuntimeError;
229static VALUE *dll_rb_eStandardError;
230static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
231static void (*dll_rb_global_variable) (VALUE*);
232static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
233static VALUE (*dll_rb_hash_new) (void);
234static VALUE (*dll_rb_inspect) (VALUE);
235static VALUE (*dll_rb_int2inum) (long);
236static VALUE (*dll_rb_int2inum) (long);
237static VALUE (*dll_rb_lastline_get) (void);
238static void (*dll_rb_lastline_set) (VALUE);
239static void (*dll_rb_load_protect) (VALUE, int, int*);
240static long (*dll_rb_num2long) (VALUE);
241static unsigned long (*dll_rb_num2ulong) (VALUE);
242static VALUE (*dll_rb_obj_alloc) (VALUE);
243static VALUE (*dll_rb_obj_as_string) (VALUE);
244static VALUE (*dll_rb_obj_id) (VALUE);
245static void (*dll_rb_raise) (VALUE, const char*, ...);
246static char *(*dll_rb_str2cstr) (VALUE,int*);
247static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
248static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
249static VALUE (*dll_rb_str_new) (const char*, long);
250static VALUE (*dll_rb_str_new2) (const char*);
Bram Moolenaar639a2552010-03-17 18:15:23 +0100251#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100252static VALUE (*dll_rb_errinfo) (void);
253#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000254static VALUE *dll_ruby_errinfo;
Bram Moolenaar165641d2010-02-17 16:23:09 +0100255#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256static void (*dll_ruby_init) (void);
257static void (*dll_ruby_init_loadpath) (void);
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100258static void (*dll_NtInitialize) (int*, char***);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100260static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
261static VALUE (*dll_rb_float_new) (double);
262static VALUE (*dll_rb_ary_new) (void);
263static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
264#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100265#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100266static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
267#endif
268#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
270#endif
271
Bram Moolenaar639a2552010-03-17 18:15:23 +0100272#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100273static void (*dll_ruby_script) (const char*);
274static int (*dll_rb_enc_find_index) (const char*);
275static rb_encoding* (*dll_rb_enc_find) (const char*);
276static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
277static VALUE (*dll_rb_sprintf) (const char*, ...);
Bram Moolenaar639a2552010-03-17 18:15:23 +0100278static void (*ruby_init_stack)(VALUE*);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100279#endif
280
Bram Moolenaar639a2552010-03-17 18:15:23 +0100281#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100282static SIGNED_VALUE rb_num2long_stub(VALUE x)
283{
284 return dll_rb_num2long(x);
285}
286static VALUE rb_int2big_stub(SIGNED_VALUE x)
287{
288 return dll_rb_int2big(x);
289}
290#endif
291
Bram Moolenaar071d4272004-06-13 20:20:40 +0000292static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */
293
294/*
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000295 * Table of name to function pointer of ruby.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000296 */
297#define RUBY_PROC FARPROC
298static struct
299{
300 char *name;
301 RUBY_PROC *ptr;
302} ruby_funcname_table[] =
303{
304 {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
305 {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
306 {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
307 {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
308 {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
309 {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
310 {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
311 {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
312 {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
313 {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
314 {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
315 {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
316 {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
317 {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
318 {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
319 {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
320 {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
321 {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
322 {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
323 {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
324 {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
325 {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
326 {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
327 {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
328 {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
329 {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
330 {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
331 {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
332 {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
333 {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
334 {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
335 {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
336 {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
337 {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
338 {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
339 {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
340 {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
341 {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
342 {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
343 {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
344 {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
345 {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
346 {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
Bram Moolenaar639a2552010-03-17 18:15:23 +0100347#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100348 {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
349#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000350 {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100351#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000352 {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
353 {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100354 {
355#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19
356 "NtInitialize",
357#else
358 "ruby_sysinit",
359#endif
360 (RUBY_PROC*)&dll_NtInitialize},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
362 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
363#endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100364#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
365 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
366 {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
367 {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
368 {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
369#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100370#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100371 {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100372 {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
373 {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
374 {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
375 {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
376 {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
Bram Moolenaar639a2552010-03-17 18:15:23 +0100377 {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100378#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000379 {"", NULL},
380};
381
382/*
383 * Free ruby.dll
384 */
385 static void
386end_dynamic_ruby()
387{
388 if (hinstRuby)
389 {
390 FreeLibrary(hinstRuby);
391 hinstRuby = 0;
392 }
393}
394
395/*
396 * Load library and get all pointers.
397 * Parameter 'libname' provides name of DLL.
398 * Return OK or FAIL.
399 */
400 static int
401ruby_runtime_link_init(char *libname, int verbose)
402{
403 int i;
404
405 if (hinstRuby)
406 return OK;
407 hinstRuby = LoadLibrary(libname);
408 if (!hinstRuby)
409 {
410 if (verbose)
411 EMSG2(_(e_loadlib), libname);
412 return FAIL;
413 }
414
415 for (i = 0; ruby_funcname_table[i].ptr; ++i)
416 {
417 if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby,
418 ruby_funcname_table[i].name)))
419 {
420 FreeLibrary(hinstRuby);
421 hinstRuby = 0;
422 if (verbose)
423 EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
424 return FAIL;
425 }
426 }
427 return OK;
428}
429
430/*
431 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
432 * else FALSE.
433 */
434 int
435ruby_enabled(verbose)
436 int verbose;
437{
438 return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
439}
440#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
441
442 void
443ruby_end()
444{
445#ifdef DYNAMIC_RUBY
446 end_dynamic_ruby();
447#endif
448}
449
450void ex_ruby(exarg_T *eap)
451{
452 int state;
453 char *script = NULL;
454
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000455 script = (char *)script_get(eap, eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000456 if (!eap->skip && ensure_ruby_initialized())
457 {
458 if (script == NULL)
459 rb_eval_string_protect((char *)eap->arg, &state);
460 else
461 rb_eval_string_protect(script, &state);
462 if (state)
463 error_print(state);
464 }
465 vim_free(script);
466}
467
Bram Moolenaar165641d2010-02-17 16:23:09 +0100468/*
469 * In Ruby 1.9 or later, ruby String object has encoding.
470 * conversion buffer string of vim to ruby String object using
471 * VIM encoding option.
472 */
473 static VALUE
474vim_str2rb_enc_str(const char *s)
475{
Bram Moolenaar639a2552010-03-17 18:15:23 +0100476#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100477 int isnum;
478 long lval;
479 char_u *sval;
480 rb_encoding *enc;
481
482 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
483 if (isnum == 0)
484 {
485 enc = rb_enc_find((char *)sval);
486 vim_free(sval);
487 if (enc) {
488 return rb_enc_str_new(s, strlen(s), enc);
489 }
490 }
491#endif
492 return rb_str_new2(s);
493}
494
495 static VALUE
496eval_enc_string_protect(const char *str, int *state)
497{
Bram Moolenaar639a2552010-03-17 18:15:23 +0100498#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100499 int isnum;
500 long lval;
501 char_u *sval;
502 rb_encoding *enc;
503 VALUE v;
504
505 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
506 if (isnum == 0)
507 {
508 enc = rb_enc_find((char *)sval);
509 vim_free(sval);
510 if (enc)
511 {
512 v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
513 return rb_eval_string_protect(StringValuePtr(v), state);
514 }
515 }
516#endif
517 return rb_eval_string_protect(str, state);
518}
519
Bram Moolenaar071d4272004-06-13 20:20:40 +0000520void ex_rubydo(exarg_T *eap)
521{
522 int state;
523 linenr_T i;
524
525 if (ensure_ruby_initialized())
526 {
527 if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
528 return;
529 for (i = eap->line1; i <= eap->line2; i++) {
530 VALUE line, oldline;
531
Bram Moolenaar165641d2010-02-17 16:23:09 +0100532 line = oldline = vim_str2rb_enc_str((char *)ml_get(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533 rb_lastline_set(line);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100534 eval_enc_string_protect((char *) eap->arg, &state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000535 if (state) {
536 error_print(state);
537 break;
538 }
539 line = rb_lastline_get();
540 if (!NIL_P(line)) {
541 if (TYPE(line) != T_STRING) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000542 EMSG(_("E265: $_ must be an instance of String"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000543 return;
544 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100545 ml_replace(i, (char_u *) StringValuePtr(line), 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000546 changed();
547#ifdef SYNTAX_HL
548 syn_changed(i); /* recompute syntax hl. for this line */
549#endif
550 }
551 }
552 check_cursor();
553 update_curbuf(NOT_VALID);
554 }
555}
556
557void ex_rubyfile(exarg_T *eap)
558{
559 int state;
560
561 if (ensure_ruby_initialized())
562 {
563 rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
564 if (state) error_print(state);
565 }
566}
567
568void ruby_buffer_free(buf_T *buf)
569{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000570 if (buf->b_ruby_ref)
571 {
572 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
573 RDATA(buf->b_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 }
575}
576
577void ruby_window_free(win_T *win)
578{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000579 if (win->w_ruby_ref)
580 {
581 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
582 RDATA(win->w_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000583 }
584}
585
586static int ensure_ruby_initialized(void)
587{
588 if (!ruby_initialized)
589 {
590#ifdef DYNAMIC_RUBY
591 if (ruby_enabled(TRUE))
592 {
593#endif
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100594#ifdef _WIN32
595 /* suggested by Ariya Mizutani */
596 int argc = 1;
597 char *argv[] = {"gvim.exe"};
598 NtInitialize(&argc, &argv);
599#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100600#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100601 RUBY_INIT_STACK;
602#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000603 ruby_init();
Bram Moolenaar639a2552010-03-17 18:15:23 +0100604#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100605 ruby_script("vim-ruby");
606#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000607 ruby_init_loadpath();
608 ruby_io_init();
Bram Moolenaar639a2552010-03-17 18:15:23 +0100609#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100610 rb_enc_find_index("encdb");
611#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612 ruby_vim_init();
613 ruby_initialized = 1;
614#ifdef DYNAMIC_RUBY
615 }
616 else
617 {
618 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
619 return 0;
620 }
621#endif
622 }
623 return ruby_initialized;
624}
625
626static void error_print(int state)
627{
628#ifndef DYNAMIC_RUBY
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100629#if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
630 && !(defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 RUBYEXTERN VALUE ruby_errinfo;
632#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100633#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 VALUE eclass;
635 VALUE einfo;
636 char buff[BUFSIZ];
637
638#define TAG_RETURN 0x1
639#define TAG_BREAK 0x2
640#define TAG_NEXT 0x3
641#define TAG_RETRY 0x4
642#define TAG_REDO 0x5
643#define TAG_RAISE 0x6
644#define TAG_THROW 0x7
645#define TAG_FATAL 0x8
646#define TAG_MASK 0xf
647
648 switch (state) {
649 case TAG_RETURN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000650 EMSG(_("E267: unexpected return"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651 break;
652 case TAG_NEXT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000653 EMSG(_("E268: unexpected next"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 break;
655 case TAG_BREAK:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000656 EMSG(_("E269: unexpected break"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000657 break;
658 case TAG_REDO:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000659 EMSG(_("E270: unexpected redo"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660 break;
661 case TAG_RETRY:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000662 EMSG(_("E271: retry outside of rescue clause"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000663 break;
664 case TAG_RAISE:
665 case TAG_FATAL:
Bram Moolenaar639a2552010-03-17 18:15:23 +0100666#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100667 eclass = CLASS_OF(rb_errinfo());
668 einfo = rb_obj_as_string(rb_errinfo());
669#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 eclass = CLASS_OF(ruby_errinfo);
671 einfo = rb_obj_as_string(ruby_errinfo);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100672#endif
673 if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000674 EMSG(_("E272: unhandled exception"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000675 }
676 else {
677 VALUE epath;
678 char *p;
679
680 epath = rb_class_path(eclass);
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000681 vim_snprintf(buff, BUFSIZ, "%s: %s",
Bram Moolenaar165641d2010-02-17 16:23:09 +0100682 RSTRING_PTR(epath), RSTRING_PTR(einfo));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683 p = strchr(buff, '\n');
684 if (p) *p = '\0';
685 EMSG(buff);
686 }
687 break;
688 default:
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000689 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690 EMSG(buff);
691 break;
692 }
693}
694
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000695static VALUE vim_message(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000696{
697 char *buff, *p;
698
699 str = rb_obj_as_string(str);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100700 buff = ALLOCA_N(char, RSTRING_LEN(str));
701 strcpy(buff, RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 p = strchr(buff, '\n');
703 if (p) *p = '\0';
704 MSG(buff);
705 return Qnil;
706}
707
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000708static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100710 do_set((char_u *)StringValuePtr(str), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000711 update_screen(NOT_VALID);
712 return Qnil;
713}
714
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000715static VALUE vim_command(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100717 do_cmdline_cmd((char_u *)StringValuePtr(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 return Qnil;
719}
720
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100721#ifdef FEAT_EVAL
722static VALUE vim_to_ruby(typval_T *tv)
723{
724 VALUE result = Qnil;
725
726 if (tv->v_type == VAR_STRING)
727 {
Bram Moolenaar94127e42010-03-19 23:08:48 +0100728 result = rb_str_new2(tv->vval.v_string == NULL
729 ? "" : (char *)(tv->vval.v_string));
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100730 }
731 else if (tv->v_type == VAR_NUMBER)
732 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100733 result = INT2NUM(tv->vval.v_number);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100734 }
735# ifdef FEAT_FLOAT
736 else if (tv->v_type == VAR_FLOAT)
737 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100738 result = rb_float_new(tv->vval.v_float);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100739 }
740# endif
741 else if (tv->v_type == VAR_LIST)
742 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100743 list_T *list = tv->vval.v_list;
744 listitem_T *curr;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100745
Bram Moolenaar639a2552010-03-17 18:15:23 +0100746 result = rb_ary_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100747
Bram Moolenaar639a2552010-03-17 18:15:23 +0100748 if (list != NULL)
749 {
750 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
751 {
752 rb_ary_push(result, vim_to_ruby(&curr->li_tv));
753 }
754 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100755 }
756 else if (tv->v_type == VAR_DICT)
757 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100758 result = rb_hash_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100759
Bram Moolenaar639a2552010-03-17 18:15:23 +0100760 if (tv->vval.v_dict != NULL)
761 {
762 hashtab_T *ht = &tv->vval.v_dict->dv_hashtab;
763 long_u todo = ht->ht_used;
764 hashitem_T *hi;
765 dictitem_T *di;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100766
Bram Moolenaar639a2552010-03-17 18:15:23 +0100767 for (hi = ht->ht_array; todo > 0; ++hi)
768 {
769 if (!HASHITEM_EMPTY(hi))
770 {
771 --todo;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100772
Bram Moolenaar639a2552010-03-17 18:15:23 +0100773 di = dict_lookup(hi);
774 rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100775 vim_to_ruby(&di->di_tv));
Bram Moolenaar639a2552010-03-17 18:15:23 +0100776 }
777 }
778 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100779 } /* else return Qnil; */
780
781 return result;
782}
783#endif
784
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000785static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786{
787#ifdef FEAT_EVAL
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100788 typval_T *tv;
789 VALUE result;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100791 tv = eval_expr((char_u *)StringValuePtr(str), NULL);
792 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100794 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000795 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100796 result = vim_to_ruby(tv);
797
798 free_tv(tv);
799
800 return result;
801#else
802 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804}
805
806static VALUE buffer_new(buf_T *buf)
807{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000808 if (buf->b_ruby_ref)
809 {
810 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000811 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000812 else
813 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000814 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000815 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
817 return obj;
818 }
819}
820
821static buf_T *get_buf(VALUE obj)
822{
823 buf_T *buf;
824
825 Data_Get_Struct(obj, buf_T, buf);
826 if (buf == NULL)
827 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
828 return buf;
829}
830
831static VALUE buffer_s_current()
832{
833 return buffer_new(curbuf);
834}
835
836static VALUE buffer_s_count()
837{
838 buf_T *b;
839 int n = 0;
840
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000841 for (b = firstbuf; b != NULL; b = b->b_next)
842 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000843 /* Deleted buffers should not be counted
844 * SegPhault - 01/07/05 */
845 if (b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000846 n++;
847 }
848
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 return INT2NUM(n);
850}
851
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000852static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853{
854 buf_T *b;
855 int n = NUM2INT(num);
856
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000857 for (b = firstbuf; b != NULL; b = b->b_next)
858 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000859 /* Deleted buffers should not be counted
860 * SegPhault - 01/07/05 */
861 if (!b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000862 continue;
863
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000864 if (n == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 return buffer_new(b);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000866
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000867 n--;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868 }
869 return Qnil;
870}
871
872static VALUE buffer_name(VALUE self)
873{
874 buf_T *buf = get_buf(self);
875
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000876 return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877}
878
879static VALUE buffer_number(VALUE self)
880{
881 buf_T *buf = get_buf(self);
882
883 return INT2NUM(buf->b_fnum);
884}
885
886static VALUE buffer_count(VALUE self)
887{
888 buf_T *buf = get_buf(self);
889
890 return INT2NUM(buf->b_ml.ml_line_count);
891}
892
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000893static VALUE get_buffer_line(buf_T *buf, linenr_T n)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894{
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000895 if (n > 0 && n <= buf->b_ml.ml_line_count)
896 {
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000897 char *line = (char *)ml_get_buf(buf, n, FALSE);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100898 return line ? vim_str2rb_enc_str(line) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100900 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000901#ifndef __GNUC__
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000902 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000903#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000904}
905
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000906static VALUE buffer_aref(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000907{
908 buf_T *buf = get_buf(self);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000909
910 if (buf != NULL)
911 return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
912 return Qnil; /* For stop warning */
913}
914
915static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
916{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100917 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000918 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000920 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
921 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000922 /* set curwin/curbuf for "buf" and save some things */
923 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000924
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925 if (u_savesub(n) == OK) {
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000926 ml_replace(n, (char_u *)line, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 changed();
928#ifdef SYNTAX_HL
929 syn_changed(n); /* recompute syntax hl. for this line */
930#endif
931 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000932
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000933 /* restore curwin/curbuf and a few other things */
934 aucmd_restbuf(&aco);
935 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000936
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 update_curbuf(NOT_VALID);
938 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000939 else
940 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100941 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000942#ifndef __GNUC__
Bram Moolenaar071d4272004-06-13 20:20:40 +0000943 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000944#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945 }
946 return str;
947}
948
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000949static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
950{
951 buf_T *buf = get_buf(self);
952
953 if (buf != NULL)
954 return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
955 return str;
956}
957
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958static VALUE buffer_delete(VALUE self, VALUE num)
959{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000960 buf_T *buf = get_buf(self);
961 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000962 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000964 if (n > 0 && n <= buf->b_ml.ml_line_count)
965 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000966 /* set curwin/curbuf for "buf" and save some things */
967 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000968
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969 if (u_savedel(n, 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 ml_delete(n, 0);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000971
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000972 /* Changes to non-active buffers should properly refresh
973 * SegPhault - 01/09/05 */
974 deleted_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000975
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976 changed();
977 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000978
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000979 /* restore curwin/curbuf and a few other things */
980 aucmd_restbuf(&aco);
981 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000982
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 update_curbuf(NOT_VALID);
984 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000985 else
986 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100987 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988 }
989 return Qnil;
990}
991
992static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
993{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000994 buf_T *buf = get_buf(self);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100995 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000996 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000997 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998
Bram Moolenaar83bac8b2010-02-18 15:53:29 +0100999 if (line == NULL) {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001000 rb_raise(rb_eIndexError, "NULL line");
1001 }
1002 else if (n >= 0 && n <= buf->b_ml.ml_line_count)
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001003 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001004 /* set curwin/curbuf for "buf" and save some things */
1005 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001006
Bram Moolenaar071d4272004-06-13 20:20:40 +00001007 if (u_inssub(n + 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001009
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001010 /* Changes to non-active buffers should properly refresh screen
1011 * SegPhault - 12/20/04 */
1012 appended_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001013
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001014 changed();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001016
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001017 /* restore curwin/curbuf and a few other things */
1018 aucmd_restbuf(&aco);
1019 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00001020
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 update_curbuf(NOT_VALID);
1022 }
1023 else {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001024 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 }
1026 return str;
1027}
1028
1029static VALUE window_new(win_T *win)
1030{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001031 if (win->w_ruby_ref)
1032 {
1033 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001035 else
1036 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001037 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaare344bea2005-09-01 20:46:49 +00001038 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1040 return obj;
1041 }
1042}
1043
1044static win_T *get_win(VALUE obj)
1045{
1046 win_T *win;
1047
1048 Data_Get_Struct(obj, win_T, win);
1049 if (win == NULL)
1050 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1051 return win;
1052}
1053
1054static VALUE window_s_current()
1055{
1056 return window_new(curwin);
1057}
1058
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001059/*
1060 * Added line manipulation functions
1061 * SegPhault - 03/07/05
1062 */
1063static VALUE line_s_current()
1064{
1065 return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1066}
1067
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001068static VALUE set_current_line(VALUE self UNUSED, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001069{
1070 return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1071}
1072
1073static VALUE current_line_number()
1074{
1075 return INT2FIX((int)curwin->w_cursor.lnum);
1076}
1077
1078
1079
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080static VALUE window_s_count()
1081{
1082#ifdef FEAT_WINDOWS
1083 win_T *w;
1084 int n = 0;
1085
Bram Moolenaarf740b292006-02-16 22:11:02 +00001086 for (w = firstwin; w != NULL; w = w->w_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 n++;
1088 return INT2NUM(n);
1089#else
1090 return INT2NUM(1);
1091#endif
1092}
1093
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001094static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095{
1096 win_T *w;
1097 int n = NUM2INT(num);
1098
1099#ifndef FEAT_WINDOWS
1100 w = curwin;
1101#else
1102 for (w = firstwin; w != NULL; w = w->w_next, --n)
1103#endif
1104 if (n == 0)
1105 return window_new(w);
1106 return Qnil;
1107}
1108
1109static VALUE window_buffer(VALUE self)
1110{
1111 win_T *win = get_win(self);
1112
1113 return buffer_new(win->w_buffer);
1114}
1115
1116static VALUE window_height(VALUE self)
1117{
1118 win_T *win = get_win(self);
1119
1120 return INT2NUM(win->w_height);
1121}
1122
1123static VALUE window_set_height(VALUE self, VALUE height)
1124{
1125 win_T *win = get_win(self);
1126 win_T *savewin = curwin;
1127
1128 curwin = win;
1129 win_setheight(NUM2INT(height));
1130 curwin = savewin;
1131 return height;
1132}
1133
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001134static VALUE window_width(VALUE self)
1135{
1136 win_T *win = get_win(self);
1137
1138 return INT2NUM(win->w_width);
1139}
1140
1141static VALUE window_set_width(VALUE self, VALUE width)
1142{
1143 win_T *win = get_win(self);
1144 win_T *savewin = curwin;
1145
1146 curwin = win;
1147 win_setwidth(NUM2INT(width));
1148 curwin = savewin;
1149 return width;
1150}
1151
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152static VALUE window_cursor(VALUE self)
1153{
1154 win_T *win = get_win(self);
1155
1156 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1157}
1158
1159static VALUE window_set_cursor(VALUE self, VALUE pos)
1160{
1161 VALUE lnum, col;
1162 win_T *win = get_win(self);
1163
1164 Check_Type(pos, T_ARRAY);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001165 if (RARRAY_LEN(pos) != 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166 rb_raise(rb_eArgError, "array length must be 2");
Bram Moolenaar165641d2010-02-17 16:23:09 +01001167 lnum = RARRAY_PTR(pos)[0];
1168 col = RARRAY_PTR(pos)[1];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169 win->w_cursor.lnum = NUM2LONG(lnum);
1170 win->w_cursor.col = NUM2UINT(col);
1171 check_cursor(); /* put cursor on an existing line */
1172 update_screen(NOT_VALID);
1173 return Qnil;
1174}
1175
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001176static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177{
1178 int i;
1179 VALUE str = rb_str_new("", 0);
1180
1181 for (i = 0; i < argc; i++) {
1182 if (i > 0) rb_str_cat(str, ", ", 2);
1183 rb_str_concat(str, rb_inspect(argv[i]));
1184 }
Bram Moolenaar165641d2010-02-17 16:23:09 +01001185 MSG(RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001186 return Qnil;
1187}
1188
1189static void ruby_io_init(void)
1190{
1191#ifndef DYNAMIC_RUBY
1192 RUBYEXTERN VALUE rb_stdout;
1193#endif
1194
1195 rb_stdout = rb_obj_alloc(rb_cObject);
1196 rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1197 rb_define_global_function("p", f_p, -1);
1198}
1199
1200static void ruby_vim_init(void)
1201{
1202 objtbl = rb_hash_new();
1203 rb_global_variable(&objtbl);
1204
Bram Moolenaarf711faf2007-05-10 16:48:19 +00001205 /* The Vim module used to be called "VIM", but "Vim" is better. Make an
1206 * alias "VIM" for backwards compatiblity. */
1207 mVIM = rb_define_module("Vim");
1208 rb_define_const(rb_cObject, "VIM", mVIM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001209 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1210 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1211 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1212 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1213 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1214 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1215 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1216 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1217 rb_define_module_function(mVIM, "message", vim_message, 1);
1218 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1219 rb_define_module_function(mVIM, "command", vim_command, 1);
1220 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1221
1222 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1223 rb_eStandardError);
1224 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1225 rb_eStandardError);
1226
1227 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1228 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1229 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1230 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1231 rb_define_method(cBuffer, "name", buffer_name, 0);
1232 rb_define_method(cBuffer, "number", buffer_number, 0);
1233 rb_define_method(cBuffer, "count", buffer_count, 0);
1234 rb_define_method(cBuffer, "length", buffer_count, 0);
1235 rb_define_method(cBuffer, "[]", buffer_aref, 1);
1236 rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1237 rb_define_method(cBuffer, "delete", buffer_delete, 1);
1238 rb_define_method(cBuffer, "append", buffer_append, 2);
1239
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001240 /* Added line manipulation functions
1241 * SegPhault - 03/07/05 */
1242 rb_define_method(cBuffer, "line_number", current_line_number, 0);
1243 rb_define_method(cBuffer, "line", line_s_current, 0);
1244 rb_define_method(cBuffer, "line=", set_current_line, 1);
1245
1246
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1248 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1249 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1250 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1251 rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1252 rb_define_method(cVimWindow, "height", window_height, 0);
1253 rb_define_method(cVimWindow, "height=", window_set_height, 1);
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001254 rb_define_method(cVimWindow, "width", window_width, 0);
1255 rb_define_method(cVimWindow, "width=", window_set_width, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256 rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1257 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1258
1259 rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1260 rb_define_virtual_variable("$curwin", window_s_current, 0);
1261}