blob: 4fd54e285fac587ca25fd4c4358eedb998f399f4 [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 Moolenaar1d2beae2010-05-22 21:56:55 +0200173#ifdef rb_str_new2
174/* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
175# define need_rb_str_new_cstr 1
176# define rb_str_new_cstr dll_rb_str_new_cstr
177#else
Bram Moolenaar218116c2010-05-20 21:46:00 +0200178# define rb_str_new2 dll_rb_str_new2
179#endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100180#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
181# define rb_string_value_ptr dll_rb_string_value_ptr
182# define rb_float_new dll_rb_float_new
183# define rb_ary_new dll_rb_ary_new
184# define rb_ary_push dll_rb_ary_push
185#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100186#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100187# define rb_errinfo dll_rb_errinfo
188#else
189# define ruby_errinfo (*dll_ruby_errinfo)
190#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191#define ruby_init dll_ruby_init
192#define ruby_init_loadpath dll_ruby_init_loadpath
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100193#define NtInitialize dll_NtInitialize
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
195# define rb_w32_snprintf dll_rb_w32_snprintf
196#endif
197
Bram Moolenaar639a2552010-03-17 18:15:23 +0100198#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100199# define ruby_script dll_ruby_script
200# define rb_enc_find_index dll_rb_enc_find_index
201# define rb_enc_find dll_rb_enc_find
202# define rb_enc_str_new dll_rb_enc_str_new
203# define rb_sprintf dll_rb_sprintf
Bram Moolenaar639a2552010-03-17 18:15:23 +0100204# define ruby_init_stack dll_ruby_init_stack
Bram Moolenaar165641d2010-02-17 16:23:09 +0100205#endif
206
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207/*
208 * Pointers for dynamic link
209 */
210static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
211static VALUE *dll_rb_cFalseClass;
212static VALUE *dll_rb_cFixnum;
213static VALUE *dll_rb_cNilClass;
214static VALUE *dll_rb_cObject;
215static VALUE *dll_rb_cSymbol;
216static VALUE *dll_rb_cTrueClass;
217static void (*dll_rb_check_type) (VALUE,int);
218static VALUE (*dll_rb_class_path) (VALUE);
219static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
220static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
221static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
222static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
223static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
224static VALUE (*dll_rb_define_module) (const char*);
225static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
226static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
227static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
228static VALUE *dll_rb_stdout;
229static VALUE *dll_rb_eArgError;
230static VALUE *dll_rb_eIndexError;
231static VALUE *dll_rb_eRuntimeError;
232static VALUE *dll_rb_eStandardError;
233static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
234static void (*dll_rb_global_variable) (VALUE*);
235static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
236static VALUE (*dll_rb_hash_new) (void);
237static VALUE (*dll_rb_inspect) (VALUE);
238static VALUE (*dll_rb_int2inum) (long);
239static VALUE (*dll_rb_int2inum) (long);
240static VALUE (*dll_rb_lastline_get) (void);
241static void (*dll_rb_lastline_set) (VALUE);
242static void (*dll_rb_load_protect) (VALUE, int, int*);
243static long (*dll_rb_num2long) (VALUE);
244static unsigned long (*dll_rb_num2ulong) (VALUE);
245static VALUE (*dll_rb_obj_alloc) (VALUE);
246static VALUE (*dll_rb_obj_as_string) (VALUE);
247static VALUE (*dll_rb_obj_id) (VALUE);
248static void (*dll_rb_raise) (VALUE, const char*, ...);
249static char *(*dll_rb_str2cstr) (VALUE,int*);
250static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
251static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
252static VALUE (*dll_rb_str_new) (const char*, long);
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200253#ifdef need_rb_str_new_cstr
254/* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
255static VALUE (*dll_rb_str_new_cstr) (const char*);
256#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257static VALUE (*dll_rb_str_new2) (const char*);
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200258#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100259#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100260static VALUE (*dll_rb_errinfo) (void);
261#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262static VALUE *dll_ruby_errinfo;
Bram Moolenaar165641d2010-02-17 16:23:09 +0100263#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264static void (*dll_ruby_init) (void);
265static void (*dll_ruby_init_loadpath) (void);
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100266static void (*dll_NtInitialize) (int*, char***);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000267#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100268static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
269static VALUE (*dll_rb_float_new) (double);
270static VALUE (*dll_rb_ary_new) (void);
271static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
272#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100273#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100274static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
275#endif
276#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar071d4272004-06-13 20:20:40 +0000277static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
278#endif
279
Bram Moolenaar639a2552010-03-17 18:15:23 +0100280#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100281static void (*dll_ruby_script) (const char*);
282static int (*dll_rb_enc_find_index) (const char*);
283static rb_encoding* (*dll_rb_enc_find) (const char*);
284static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
285static VALUE (*dll_rb_sprintf) (const char*, ...);
Bram Moolenaar639a2552010-03-17 18:15:23 +0100286static void (*ruby_init_stack)(VALUE*);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100287#endif
288
Bram Moolenaar639a2552010-03-17 18:15:23 +0100289#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100290static SIGNED_VALUE rb_num2long_stub(VALUE x)
291{
292 return dll_rb_num2long(x);
293}
294static VALUE rb_int2big_stub(SIGNED_VALUE x)
295{
296 return dll_rb_int2big(x);
297}
298#endif
299
Bram Moolenaar071d4272004-06-13 20:20:40 +0000300static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */
301
302/*
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000303 * Table of name to function pointer of ruby.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000304 */
305#define RUBY_PROC FARPROC
306static struct
307{
308 char *name;
309 RUBY_PROC *ptr;
310} ruby_funcname_table[] =
311{
312 {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
313 {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
314 {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
315 {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
316 {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
317 {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
318 {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
319 {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
320 {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
321 {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
322 {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
323 {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
324 {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
325 {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
326 {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
327 {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
328 {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
329 {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
330 {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
331 {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
332 {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
333 {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
334 {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
335 {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
336 {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
337 {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
338 {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
339 {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
340 {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
341 {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
342 {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
343 {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
344 {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
345 {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
346 {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
347 {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
348 {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
349 {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
350 {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
351 {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
352 {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
353 {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200354#ifdef need_rb_str_new_cstr
355 {"rb_str_new_cstr", (RUBY_PROC*)&dll_rb_str_new_cstr},
356#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357 {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200358#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100359#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100360 {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
361#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000362 {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100363#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
365 {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100366 {
367#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19
368 "NtInitialize",
369#else
370 "ruby_sysinit",
371#endif
372 (RUBY_PROC*)&dll_NtInitialize},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
374 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
375#endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100376#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
377 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
378 {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
379 {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
380 {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
381#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100382#ifdef RUBY19_OR_LATER
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100383 {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100384 {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
385 {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
386 {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
387 {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
388 {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
Bram Moolenaar639a2552010-03-17 18:15:23 +0100389 {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100390#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000391 {"", NULL},
392};
393
394/*
395 * Free ruby.dll
396 */
397 static void
398end_dynamic_ruby()
399{
400 if (hinstRuby)
401 {
402 FreeLibrary(hinstRuby);
403 hinstRuby = 0;
404 }
405}
406
407/*
408 * Load library and get all pointers.
409 * Parameter 'libname' provides name of DLL.
410 * Return OK or FAIL.
411 */
412 static int
413ruby_runtime_link_init(char *libname, int verbose)
414{
415 int i;
416
417 if (hinstRuby)
418 return OK;
419 hinstRuby = LoadLibrary(libname);
420 if (!hinstRuby)
421 {
422 if (verbose)
423 EMSG2(_(e_loadlib), libname);
424 return FAIL;
425 }
426
427 for (i = 0; ruby_funcname_table[i].ptr; ++i)
428 {
429 if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby,
430 ruby_funcname_table[i].name)))
431 {
432 FreeLibrary(hinstRuby);
433 hinstRuby = 0;
434 if (verbose)
435 EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
436 return FAIL;
437 }
438 }
439 return OK;
440}
441
442/*
443 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
444 * else FALSE.
445 */
446 int
447ruby_enabled(verbose)
448 int verbose;
449{
450 return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
451}
452#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
453
454 void
455ruby_end()
456{
457#ifdef DYNAMIC_RUBY
458 end_dynamic_ruby();
459#endif
460}
461
462void ex_ruby(exarg_T *eap)
463{
464 int state;
465 char *script = NULL;
466
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000467 script = (char *)script_get(eap, eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000468 if (!eap->skip && ensure_ruby_initialized())
469 {
470 if (script == NULL)
471 rb_eval_string_protect((char *)eap->arg, &state);
472 else
473 rb_eval_string_protect(script, &state);
474 if (state)
475 error_print(state);
476 }
477 vim_free(script);
478}
479
Bram Moolenaar165641d2010-02-17 16:23:09 +0100480/*
481 * In Ruby 1.9 or later, ruby String object has encoding.
482 * conversion buffer string of vim to ruby String object using
483 * VIM encoding option.
484 */
485 static VALUE
486vim_str2rb_enc_str(const char *s)
487{
Bram Moolenaar639a2552010-03-17 18:15:23 +0100488#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100489 int isnum;
490 long lval;
491 char_u *sval;
492 rb_encoding *enc;
493
494 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
495 if (isnum == 0)
496 {
497 enc = rb_enc_find((char *)sval);
498 vim_free(sval);
499 if (enc) {
500 return rb_enc_str_new(s, strlen(s), enc);
501 }
502 }
503#endif
504 return rb_str_new2(s);
505}
506
507 static VALUE
508eval_enc_string_protect(const char *str, int *state)
509{
Bram Moolenaar639a2552010-03-17 18:15:23 +0100510#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100511 int isnum;
512 long lval;
513 char_u *sval;
514 rb_encoding *enc;
515 VALUE v;
516
517 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
518 if (isnum == 0)
519 {
520 enc = rb_enc_find((char *)sval);
521 vim_free(sval);
522 if (enc)
523 {
524 v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
525 return rb_eval_string_protect(StringValuePtr(v), state);
526 }
527 }
528#endif
529 return rb_eval_string_protect(str, state);
530}
531
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532void ex_rubydo(exarg_T *eap)
533{
534 int state;
535 linenr_T i;
536
537 if (ensure_ruby_initialized())
538 {
539 if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
540 return;
541 for (i = eap->line1; i <= eap->line2; i++) {
542 VALUE line, oldline;
543
Bram Moolenaar165641d2010-02-17 16:23:09 +0100544 line = oldline = vim_str2rb_enc_str((char *)ml_get(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000545 rb_lastline_set(line);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100546 eval_enc_string_protect((char *) eap->arg, &state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000547 if (state) {
548 error_print(state);
549 break;
550 }
551 line = rb_lastline_get();
552 if (!NIL_P(line)) {
553 if (TYPE(line) != T_STRING) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000554 EMSG(_("E265: $_ must be an instance of String"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000555 return;
556 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100557 ml_replace(i, (char_u *) StringValuePtr(line), 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 changed();
559#ifdef SYNTAX_HL
560 syn_changed(i); /* recompute syntax hl. for this line */
561#endif
562 }
563 }
564 check_cursor();
565 update_curbuf(NOT_VALID);
566 }
567}
568
569void ex_rubyfile(exarg_T *eap)
570{
571 int state;
572
573 if (ensure_ruby_initialized())
574 {
575 rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
576 if (state) error_print(state);
577 }
578}
579
580void ruby_buffer_free(buf_T *buf)
581{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000582 if (buf->b_ruby_ref)
583 {
584 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
585 RDATA(buf->b_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000586 }
587}
588
589void ruby_window_free(win_T *win)
590{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000591 if (win->w_ruby_ref)
592 {
593 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
594 RDATA(win->w_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000595 }
596}
597
598static int ensure_ruby_initialized(void)
599{
600 if (!ruby_initialized)
601 {
602#ifdef DYNAMIC_RUBY
603 if (ruby_enabled(TRUE))
604 {
605#endif
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100606#ifdef _WIN32
607 /* suggested by Ariya Mizutani */
608 int argc = 1;
609 char *argv[] = {"gvim.exe"};
610 NtInitialize(&argc, &argv);
611#endif
Bram Moolenaar639a2552010-03-17 18:15:23 +0100612#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100613 RUBY_INIT_STACK;
614#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 ruby_init();
Bram Moolenaar639a2552010-03-17 18:15:23 +0100616#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100617 ruby_script("vim-ruby");
618#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000619 ruby_init_loadpath();
620 ruby_io_init();
Bram Moolenaar639a2552010-03-17 18:15:23 +0100621#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100622 rb_enc_find_index("encdb");
623#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624 ruby_vim_init();
625 ruby_initialized = 1;
626#ifdef DYNAMIC_RUBY
627 }
628 else
629 {
630 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
631 return 0;
632 }
633#endif
634 }
635 return ruby_initialized;
636}
637
638static void error_print(int state)
639{
640#ifndef DYNAMIC_RUBY
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100641#if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
642 && !(defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000643 RUBYEXTERN VALUE ruby_errinfo;
644#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100645#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000646 VALUE eclass;
647 VALUE einfo;
648 char buff[BUFSIZ];
649
650#define TAG_RETURN 0x1
651#define TAG_BREAK 0x2
652#define TAG_NEXT 0x3
653#define TAG_RETRY 0x4
654#define TAG_REDO 0x5
655#define TAG_RAISE 0x6
656#define TAG_THROW 0x7
657#define TAG_FATAL 0x8
658#define TAG_MASK 0xf
659
660 switch (state) {
661 case TAG_RETURN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000662 EMSG(_("E267: unexpected return"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000663 break;
664 case TAG_NEXT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000665 EMSG(_("E268: unexpected next"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000666 break;
667 case TAG_BREAK:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000668 EMSG(_("E269: unexpected break"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000669 break;
670 case TAG_REDO:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000671 EMSG(_("E270: unexpected redo"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 break;
673 case TAG_RETRY:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000674 EMSG(_("E271: retry outside of rescue clause"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000675 break;
676 case TAG_RAISE:
677 case TAG_FATAL:
Bram Moolenaar639a2552010-03-17 18:15:23 +0100678#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100679 eclass = CLASS_OF(rb_errinfo());
680 einfo = rb_obj_as_string(rb_errinfo());
681#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 eclass = CLASS_OF(ruby_errinfo);
683 einfo = rb_obj_as_string(ruby_errinfo);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100684#endif
685 if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000686 EMSG(_("E272: unhandled exception"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687 }
688 else {
689 VALUE epath;
690 char *p;
691
692 epath = rb_class_path(eclass);
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000693 vim_snprintf(buff, BUFSIZ, "%s: %s",
Bram Moolenaar165641d2010-02-17 16:23:09 +0100694 RSTRING_PTR(epath), RSTRING_PTR(einfo));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000695 p = strchr(buff, '\n');
696 if (p) *p = '\0';
697 EMSG(buff);
698 }
699 break;
700 default:
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000701 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 EMSG(buff);
703 break;
704 }
705}
706
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000707static VALUE vim_message(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000708{
709 char *buff, *p;
710
711 str = rb_obj_as_string(str);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100712 buff = ALLOCA_N(char, RSTRING_LEN(str));
713 strcpy(buff, RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000714 p = strchr(buff, '\n');
715 if (p) *p = '\0';
716 MSG(buff);
717 return Qnil;
718}
719
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000720static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000721{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100722 do_set((char_u *)StringValuePtr(str), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723 update_screen(NOT_VALID);
724 return Qnil;
725}
726
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000727static VALUE vim_command(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000728{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100729 do_cmdline_cmd((char_u *)StringValuePtr(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730 return Qnil;
731}
732
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100733#ifdef FEAT_EVAL
734static VALUE vim_to_ruby(typval_T *tv)
735{
736 VALUE result = Qnil;
737
738 if (tv->v_type == VAR_STRING)
739 {
Bram Moolenaar94127e42010-03-19 23:08:48 +0100740 result = rb_str_new2(tv->vval.v_string == NULL
741 ? "" : (char *)(tv->vval.v_string));
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100742 }
743 else if (tv->v_type == VAR_NUMBER)
744 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100745 result = INT2NUM(tv->vval.v_number);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100746 }
747# ifdef FEAT_FLOAT
748 else if (tv->v_type == VAR_FLOAT)
749 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100750 result = rb_float_new(tv->vval.v_float);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100751 }
752# endif
753 else if (tv->v_type == VAR_LIST)
754 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100755 list_T *list = tv->vval.v_list;
756 listitem_T *curr;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100757
Bram Moolenaar639a2552010-03-17 18:15:23 +0100758 result = rb_ary_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100759
Bram Moolenaar639a2552010-03-17 18:15:23 +0100760 if (list != NULL)
761 {
762 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
763 {
764 rb_ary_push(result, vim_to_ruby(&curr->li_tv));
765 }
766 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100767 }
768 else if (tv->v_type == VAR_DICT)
769 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100770 result = rb_hash_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100771
Bram Moolenaar639a2552010-03-17 18:15:23 +0100772 if (tv->vval.v_dict != NULL)
773 {
774 hashtab_T *ht = &tv->vval.v_dict->dv_hashtab;
775 long_u todo = ht->ht_used;
776 hashitem_T *hi;
777 dictitem_T *di;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100778
Bram Moolenaar639a2552010-03-17 18:15:23 +0100779 for (hi = ht->ht_array; todo > 0; ++hi)
780 {
781 if (!HASHITEM_EMPTY(hi))
782 {
783 --todo;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100784
Bram Moolenaar639a2552010-03-17 18:15:23 +0100785 di = dict_lookup(hi);
786 rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100787 vim_to_ruby(&di->di_tv));
Bram Moolenaar639a2552010-03-17 18:15:23 +0100788 }
789 }
790 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100791 } /* else return Qnil; */
792
793 return result;
794}
795#endif
796
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000797static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798{
799#ifdef FEAT_EVAL
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100800 typval_T *tv;
801 VALUE result;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100803 tv = eval_expr((char_u *)StringValuePtr(str), NULL);
804 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100806 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100808 result = vim_to_ruby(tv);
809
810 free_tv(tv);
811
812 return result;
813#else
814 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816}
817
818static VALUE buffer_new(buf_T *buf)
819{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000820 if (buf->b_ruby_ref)
821 {
822 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000824 else
825 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000827 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
829 return obj;
830 }
831}
832
833static buf_T *get_buf(VALUE obj)
834{
835 buf_T *buf;
836
837 Data_Get_Struct(obj, buf_T, buf);
838 if (buf == NULL)
839 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
840 return buf;
841}
842
843static VALUE buffer_s_current()
844{
845 return buffer_new(curbuf);
846}
847
848static VALUE buffer_s_count()
849{
850 buf_T *b;
851 int n = 0;
852
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000853 for (b = firstbuf; b != NULL; b = b->b_next)
854 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000855 /* Deleted buffers should not be counted
856 * SegPhault - 01/07/05 */
857 if (b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000858 n++;
859 }
860
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 return INT2NUM(n);
862}
863
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000864static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865{
866 buf_T *b;
867 int n = NUM2INT(num);
868
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000869 for (b = firstbuf; b != NULL; b = b->b_next)
870 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000871 /* Deleted buffers should not be counted
872 * SegPhault - 01/07/05 */
873 if (!b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000874 continue;
875
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000876 if (n == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 return buffer_new(b);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000878
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000879 n--;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880 }
881 return Qnil;
882}
883
884static VALUE buffer_name(VALUE self)
885{
886 buf_T *buf = get_buf(self);
887
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000888 return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889}
890
891static VALUE buffer_number(VALUE self)
892{
893 buf_T *buf = get_buf(self);
894
895 return INT2NUM(buf->b_fnum);
896}
897
898static VALUE buffer_count(VALUE self)
899{
900 buf_T *buf = get_buf(self);
901
902 return INT2NUM(buf->b_ml.ml_line_count);
903}
904
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000905static VALUE get_buffer_line(buf_T *buf, linenr_T n)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906{
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000907 if (n > 0 && n <= buf->b_ml.ml_line_count)
908 {
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000909 char *line = (char *)ml_get_buf(buf, n, FALSE);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100910 return line ? vim_str2rb_enc_str(line) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100912 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000913#ifndef __GNUC__
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000914 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000915#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000916}
917
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000918static VALUE buffer_aref(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919{
920 buf_T *buf = get_buf(self);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000921
922 if (buf != NULL)
923 return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
924 return Qnil; /* For stop warning */
925}
926
927static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
928{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100929 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000930 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000932 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
933 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000934 /* set curwin/curbuf for "buf" and save some things */
935 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000936
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 if (u_savesub(n) == OK) {
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000938 ml_replace(n, (char_u *)line, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 changed();
940#ifdef SYNTAX_HL
941 syn_changed(n); /* recompute syntax hl. for this line */
942#endif
943 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000944
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000945 /* restore curwin/curbuf and a few other things */
946 aucmd_restbuf(&aco);
947 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000948
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 update_curbuf(NOT_VALID);
950 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000951 else
952 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100953 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000954#ifndef __GNUC__
Bram Moolenaar071d4272004-06-13 20:20:40 +0000955 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000956#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 }
958 return str;
959}
960
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000961static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
962{
963 buf_T *buf = get_buf(self);
964
965 if (buf != NULL)
966 return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
967 return str;
968}
969
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970static VALUE buffer_delete(VALUE self, VALUE num)
971{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000972 buf_T *buf = get_buf(self);
973 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000974 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000976 if (n > 0 && n <= buf->b_ml.ml_line_count)
977 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000978 /* set curwin/curbuf for "buf" and save some things */
979 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000980
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981 if (u_savedel(n, 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 ml_delete(n, 0);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000983
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000984 /* Changes to non-active buffers should properly refresh
985 * SegPhault - 01/09/05 */
986 deleted_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000987
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988 changed();
989 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000990
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000991 /* restore curwin/curbuf and a few other things */
992 aucmd_restbuf(&aco);
993 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000994
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995 update_curbuf(NOT_VALID);
996 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000997 else
998 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100999 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000 }
1001 return Qnil;
1002}
1003
1004static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
1005{
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001006 buf_T *buf = get_buf(self);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001007 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001008 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001009 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001010
Bram Moolenaar83bac8b2010-02-18 15:53:29 +01001011 if (line == NULL) {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001012 rb_raise(rb_eIndexError, "NULL line");
1013 }
1014 else if (n >= 0 && n <= buf->b_ml.ml_line_count)
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001015 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001016 /* set curwin/curbuf for "buf" and save some things */
1017 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001018
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 if (u_inssub(n + 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001021
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001022 /* Changes to non-active buffers should properly refresh screen
1023 * SegPhault - 12/20/04 */
1024 appended_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001025
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001026 changed();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001027 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001028
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001029 /* restore curwin/curbuf and a few other things */
1030 aucmd_restbuf(&aco);
1031 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00001032
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 update_curbuf(NOT_VALID);
1034 }
1035 else {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001036 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001037 }
1038 return str;
1039}
1040
1041static VALUE window_new(win_T *win)
1042{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001043 if (win->w_ruby_ref)
1044 {
1045 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001046 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001047 else
1048 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaare344bea2005-09-01 20:46:49 +00001050 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1052 return obj;
1053 }
1054}
1055
1056static win_T *get_win(VALUE obj)
1057{
1058 win_T *win;
1059
1060 Data_Get_Struct(obj, win_T, win);
1061 if (win == NULL)
1062 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1063 return win;
1064}
1065
1066static VALUE window_s_current()
1067{
1068 return window_new(curwin);
1069}
1070
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001071/*
1072 * Added line manipulation functions
1073 * SegPhault - 03/07/05
1074 */
1075static VALUE line_s_current()
1076{
1077 return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1078}
1079
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001080static VALUE set_current_line(VALUE self UNUSED, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001081{
1082 return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1083}
1084
1085static VALUE current_line_number()
1086{
1087 return INT2FIX((int)curwin->w_cursor.lnum);
1088}
1089
1090
1091
Bram Moolenaar071d4272004-06-13 20:20:40 +00001092static VALUE window_s_count()
1093{
1094#ifdef FEAT_WINDOWS
1095 win_T *w;
1096 int n = 0;
1097
Bram Moolenaarf740b292006-02-16 22:11:02 +00001098 for (w = firstwin; w != NULL; w = w->w_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 n++;
1100 return INT2NUM(n);
1101#else
1102 return INT2NUM(1);
1103#endif
1104}
1105
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001106static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001107{
1108 win_T *w;
1109 int n = NUM2INT(num);
1110
1111#ifndef FEAT_WINDOWS
1112 w = curwin;
1113#else
1114 for (w = firstwin; w != NULL; w = w->w_next, --n)
1115#endif
1116 if (n == 0)
1117 return window_new(w);
1118 return Qnil;
1119}
1120
1121static VALUE window_buffer(VALUE self)
1122{
1123 win_T *win = get_win(self);
1124
1125 return buffer_new(win->w_buffer);
1126}
1127
1128static VALUE window_height(VALUE self)
1129{
1130 win_T *win = get_win(self);
1131
1132 return INT2NUM(win->w_height);
1133}
1134
1135static VALUE window_set_height(VALUE self, VALUE height)
1136{
1137 win_T *win = get_win(self);
1138 win_T *savewin = curwin;
1139
1140 curwin = win;
1141 win_setheight(NUM2INT(height));
1142 curwin = savewin;
1143 return height;
1144}
1145
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001146static VALUE window_width(VALUE self)
1147{
1148 win_T *win = get_win(self);
1149
1150 return INT2NUM(win->w_width);
1151}
1152
1153static VALUE window_set_width(VALUE self, VALUE width)
1154{
1155 win_T *win = get_win(self);
1156 win_T *savewin = curwin;
1157
1158 curwin = win;
1159 win_setwidth(NUM2INT(width));
1160 curwin = savewin;
1161 return width;
1162}
1163
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164static VALUE window_cursor(VALUE self)
1165{
1166 win_T *win = get_win(self);
1167
1168 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1169}
1170
1171static VALUE window_set_cursor(VALUE self, VALUE pos)
1172{
1173 VALUE lnum, col;
1174 win_T *win = get_win(self);
1175
1176 Check_Type(pos, T_ARRAY);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001177 if (RARRAY_LEN(pos) != 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001178 rb_raise(rb_eArgError, "array length must be 2");
Bram Moolenaar165641d2010-02-17 16:23:09 +01001179 lnum = RARRAY_PTR(pos)[0];
1180 col = RARRAY_PTR(pos)[1];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001181 win->w_cursor.lnum = NUM2LONG(lnum);
1182 win->w_cursor.col = NUM2UINT(col);
1183 check_cursor(); /* put cursor on an existing line */
1184 update_screen(NOT_VALID);
1185 return Qnil;
1186}
1187
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001188static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189{
1190 int i;
1191 VALUE str = rb_str_new("", 0);
1192
1193 for (i = 0; i < argc; i++) {
1194 if (i > 0) rb_str_cat(str, ", ", 2);
1195 rb_str_concat(str, rb_inspect(argv[i]));
1196 }
Bram Moolenaar165641d2010-02-17 16:23:09 +01001197 MSG(RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198 return Qnil;
1199}
1200
1201static void ruby_io_init(void)
1202{
1203#ifndef DYNAMIC_RUBY
1204 RUBYEXTERN VALUE rb_stdout;
1205#endif
1206
1207 rb_stdout = rb_obj_alloc(rb_cObject);
1208 rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1209 rb_define_global_function("p", f_p, -1);
1210}
1211
1212static void ruby_vim_init(void)
1213{
1214 objtbl = rb_hash_new();
1215 rb_global_variable(&objtbl);
1216
Bram Moolenaarf711faf2007-05-10 16:48:19 +00001217 /* The Vim module used to be called "VIM", but "Vim" is better. Make an
1218 * alias "VIM" for backwards compatiblity. */
1219 mVIM = rb_define_module("Vim");
1220 rb_define_const(rb_cObject, "VIM", mVIM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001221 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1222 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1223 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1224 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1225 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1226 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1227 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1228 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1229 rb_define_module_function(mVIM, "message", vim_message, 1);
1230 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1231 rb_define_module_function(mVIM, "command", vim_command, 1);
1232 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1233
1234 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1235 rb_eStandardError);
1236 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1237 rb_eStandardError);
1238
1239 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1240 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1241 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1242 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1243 rb_define_method(cBuffer, "name", buffer_name, 0);
1244 rb_define_method(cBuffer, "number", buffer_number, 0);
1245 rb_define_method(cBuffer, "count", buffer_count, 0);
1246 rb_define_method(cBuffer, "length", buffer_count, 0);
1247 rb_define_method(cBuffer, "[]", buffer_aref, 1);
1248 rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1249 rb_define_method(cBuffer, "delete", buffer_delete, 1);
1250 rb_define_method(cBuffer, "append", buffer_append, 2);
1251
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001252 /* Added line manipulation functions
1253 * SegPhault - 03/07/05 */
1254 rb_define_method(cBuffer, "line_number", current_line_number, 0);
1255 rb_define_method(cBuffer, "line", line_s_current, 0);
1256 rb_define_method(cBuffer, "line=", set_current_line, 1);
1257
1258
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1260 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1261 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1262 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1263 rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1264 rb_define_method(cVimWindow, "height", window_height, 0);
1265 rb_define_method(cVimWindow, "height=", window_set_height, 1);
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001266 rb_define_method(cVimWindow, "width", window_width, 0);
1267 rb_define_method(cVimWindow, "width=", window_set_width, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268 rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1269 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1270
1271 rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1272 rb_define_virtual_variable("$curwin", window_s_current, 0);
1273}