blob: 2608f1f79963d3fbdf8fd8488156723e79aef9e6 [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);
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200211VALUE *dll_rb_cFalseClass;
212VALUE *dll_rb_cFixnum;
213VALUE *dll_rb_cNilClass;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214static VALUE *dll_rb_cObject;
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200215VALUE *dll_rb_cSymbol;
216VALUE *dll_rb_cTrueClass;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217static 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 Moolenaarba52cde2010-06-25 04:29:11 +0200290SIGNED_VALUE rb_num2long_stub(VALUE x)
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100291{
292 return dll_rb_num2long(x);
293}
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200294VALUE rb_int2big_stub(SIGNED_VALUE x)
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100295{
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 Moolenaarb2c03502010-07-02 20:20:09 +0200612 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100613#ifdef RUBY19_OR_LATER
Bram Moolenaarb2c03502010-07-02 20:20:09 +0200614 RUBY_INIT_STACK;
Bram Moolenaar165641d2010-02-17 16:23:09 +0100615#endif
Bram Moolenaarb2c03502010-07-02 20:20:09 +0200616 ruby_init();
617 }
Bram Moolenaar639a2552010-03-17 18:15:23 +0100618#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100619 ruby_script("vim-ruby");
620#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000621 ruby_init_loadpath();
622 ruby_io_init();
Bram Moolenaar639a2552010-03-17 18:15:23 +0100623#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100624 rb_enc_find_index("encdb");
625#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 ruby_vim_init();
627 ruby_initialized = 1;
628#ifdef DYNAMIC_RUBY
629 }
630 else
631 {
632 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
633 return 0;
634 }
635#endif
636 }
637 return ruby_initialized;
638}
639
640static void error_print(int state)
641{
642#ifndef DYNAMIC_RUBY
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100643#if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
644 && !(defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000645 RUBYEXTERN VALUE ruby_errinfo;
646#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100647#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000648 VALUE eclass;
649 VALUE einfo;
650 char buff[BUFSIZ];
651
652#define TAG_RETURN 0x1
653#define TAG_BREAK 0x2
654#define TAG_NEXT 0x3
655#define TAG_RETRY 0x4
656#define TAG_REDO 0x5
657#define TAG_RAISE 0x6
658#define TAG_THROW 0x7
659#define TAG_FATAL 0x8
660#define TAG_MASK 0xf
661
662 switch (state) {
663 case TAG_RETURN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000664 EMSG(_("E267: unexpected return"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 break;
666 case TAG_NEXT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000667 EMSG(_("E268: unexpected next"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000668 break;
669 case TAG_BREAK:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000670 EMSG(_("E269: unexpected break"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000671 break;
672 case TAG_REDO:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000673 EMSG(_("E270: unexpected redo"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674 break;
675 case TAG_RETRY:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000676 EMSG(_("E271: retry outside of rescue clause"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677 break;
678 case TAG_RAISE:
679 case TAG_FATAL:
Bram Moolenaar639a2552010-03-17 18:15:23 +0100680#ifdef RUBY19_OR_LATER
Bram Moolenaar165641d2010-02-17 16:23:09 +0100681 eclass = CLASS_OF(rb_errinfo());
682 einfo = rb_obj_as_string(rb_errinfo());
683#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684 eclass = CLASS_OF(ruby_errinfo);
685 einfo = rb_obj_as_string(ruby_errinfo);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100686#endif
687 if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000688 EMSG(_("E272: unhandled exception"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000689 }
690 else {
691 VALUE epath;
692 char *p;
693
694 epath = rb_class_path(eclass);
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000695 vim_snprintf(buff, BUFSIZ, "%s: %s",
Bram Moolenaar165641d2010-02-17 16:23:09 +0100696 RSTRING_PTR(epath), RSTRING_PTR(einfo));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000697 p = strchr(buff, '\n');
698 if (p) *p = '\0';
699 EMSG(buff);
700 }
701 break;
702 default:
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000703 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704 EMSG(buff);
705 break;
706 }
707}
708
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000709static VALUE vim_message(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710{
711 char *buff, *p;
712
713 str = rb_obj_as_string(str);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100714 buff = ALLOCA_N(char, RSTRING_LEN(str));
715 strcpy(buff, RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716 p = strchr(buff, '\n');
717 if (p) *p = '\0';
718 MSG(buff);
719 return Qnil;
720}
721
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000722static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100724 do_set((char_u *)StringValuePtr(str), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725 update_screen(NOT_VALID);
726 return Qnil;
727}
728
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000729static VALUE vim_command(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100731 do_cmdline_cmd((char_u *)StringValuePtr(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 return Qnil;
733}
734
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100735#ifdef FEAT_EVAL
736static VALUE vim_to_ruby(typval_T *tv)
737{
738 VALUE result = Qnil;
739
740 if (tv->v_type == VAR_STRING)
741 {
Bram Moolenaar94127e42010-03-19 23:08:48 +0100742 result = rb_str_new2(tv->vval.v_string == NULL
743 ? "" : (char *)(tv->vval.v_string));
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100744 }
745 else if (tv->v_type == VAR_NUMBER)
746 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100747 result = INT2NUM(tv->vval.v_number);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100748 }
749# ifdef FEAT_FLOAT
750 else if (tv->v_type == VAR_FLOAT)
751 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100752 result = rb_float_new(tv->vval.v_float);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100753 }
754# endif
755 else if (tv->v_type == VAR_LIST)
756 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100757 list_T *list = tv->vval.v_list;
758 listitem_T *curr;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100759
Bram Moolenaar639a2552010-03-17 18:15:23 +0100760 result = rb_ary_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100761
Bram Moolenaar639a2552010-03-17 18:15:23 +0100762 if (list != NULL)
763 {
764 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
765 {
766 rb_ary_push(result, vim_to_ruby(&curr->li_tv));
767 }
768 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100769 }
770 else if (tv->v_type == VAR_DICT)
771 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100772 result = rb_hash_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100773
Bram Moolenaar639a2552010-03-17 18:15:23 +0100774 if (tv->vval.v_dict != NULL)
775 {
776 hashtab_T *ht = &tv->vval.v_dict->dv_hashtab;
777 long_u todo = ht->ht_used;
778 hashitem_T *hi;
779 dictitem_T *di;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100780
Bram Moolenaar639a2552010-03-17 18:15:23 +0100781 for (hi = ht->ht_array; todo > 0; ++hi)
782 {
783 if (!HASHITEM_EMPTY(hi))
784 {
785 --todo;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100786
Bram Moolenaar639a2552010-03-17 18:15:23 +0100787 di = dict_lookup(hi);
788 rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100789 vim_to_ruby(&di->di_tv));
Bram Moolenaar639a2552010-03-17 18:15:23 +0100790 }
791 }
792 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100793 } /* else return Qnil; */
794
795 return result;
796}
797#endif
798
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000799static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800{
801#ifdef FEAT_EVAL
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100802 typval_T *tv;
803 VALUE result;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100805 tv = eval_expr((char_u *)StringValuePtr(str), NULL);
806 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807 {
Bram Moolenaar639a2552010-03-17 18:15:23 +0100808 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100810 result = vim_to_ruby(tv);
811
812 free_tv(tv);
813
814 return result;
815#else
816 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818}
819
820static VALUE buffer_new(buf_T *buf)
821{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000822 if (buf->b_ruby_ref)
823 {
824 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000826 else
827 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000829 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
831 return obj;
832 }
833}
834
835static buf_T *get_buf(VALUE obj)
836{
837 buf_T *buf;
838
839 Data_Get_Struct(obj, buf_T, buf);
840 if (buf == NULL)
841 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
842 return buf;
843}
844
845static VALUE buffer_s_current()
846{
847 return buffer_new(curbuf);
848}
849
850static VALUE buffer_s_count()
851{
852 buf_T *b;
853 int n = 0;
854
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000855 for (b = firstbuf; b != NULL; b = b->b_next)
856 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000857 /* Deleted buffers should not be counted
858 * SegPhault - 01/07/05 */
859 if (b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000860 n++;
861 }
862
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 return INT2NUM(n);
864}
865
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000866static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867{
868 buf_T *b;
869 int n = NUM2INT(num);
870
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000871 for (b = firstbuf; b != NULL; b = b->b_next)
872 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000873 /* Deleted buffers should not be counted
874 * SegPhault - 01/07/05 */
875 if (!b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000876 continue;
877
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000878 if (n == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879 return buffer_new(b);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000880
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000881 n--;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 }
883 return Qnil;
884}
885
886static VALUE buffer_name(VALUE self)
887{
888 buf_T *buf = get_buf(self);
889
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000890 return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891}
892
893static VALUE buffer_number(VALUE self)
894{
895 buf_T *buf = get_buf(self);
896
897 return INT2NUM(buf->b_fnum);
898}
899
900static VALUE buffer_count(VALUE self)
901{
902 buf_T *buf = get_buf(self);
903
904 return INT2NUM(buf->b_ml.ml_line_count);
905}
906
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000907static VALUE get_buffer_line(buf_T *buf, linenr_T n)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908{
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000909 if (n > 0 && n <= buf->b_ml.ml_line_count)
910 {
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000911 char *line = (char *)ml_get_buf(buf, n, FALSE);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100912 return line ? vim_str2rb_enc_str(line) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100914 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000915#ifndef __GNUC__
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000916 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000917#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918}
919
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000920static VALUE buffer_aref(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921{
922 buf_T *buf = get_buf(self);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000923
924 if (buf != NULL)
925 return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
926 return Qnil; /* For stop warning */
927}
928
929static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
930{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100931 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000932 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000934 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
935 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000936 /* set curwin/curbuf for "buf" and save some things */
937 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000938
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 if (u_savesub(n) == OK) {
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000940 ml_replace(n, (char_u *)line, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941 changed();
942#ifdef SYNTAX_HL
943 syn_changed(n); /* recompute syntax hl. for this line */
944#endif
945 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000946
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000947 /* restore curwin/curbuf and a few other things */
948 aucmd_restbuf(&aco);
949 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000950
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 update_curbuf(NOT_VALID);
952 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000953 else
954 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100955 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000956#ifndef __GNUC__
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000958#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 }
960 return str;
961}
962
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000963static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
964{
965 buf_T *buf = get_buf(self);
966
967 if (buf != NULL)
968 return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
969 return str;
970}
971
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972static VALUE buffer_delete(VALUE self, VALUE num)
973{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000974 buf_T *buf = get_buf(self);
975 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000976 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000978 if (n > 0 && n <= buf->b_ml.ml_line_count)
979 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000980 /* set curwin/curbuf for "buf" and save some things */
981 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000982
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 if (u_savedel(n, 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984 ml_delete(n, 0);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000985
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000986 /* Changes to non-active buffers should properly refresh
987 * SegPhault - 01/09/05 */
988 deleted_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000989
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 changed();
991 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000992
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000993 /* restore curwin/curbuf and a few other things */
994 aucmd_restbuf(&aco);
995 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000996
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997 update_curbuf(NOT_VALID);
998 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000999 else
1000 {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001001 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 }
1003 return Qnil;
1004}
1005
1006static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
1007{
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001008 buf_T *buf = get_buf(self);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001009 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001010 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001011 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012
Bram Moolenaar83bac8b2010-02-18 15:53:29 +01001013 if (line == NULL) {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001014 rb_raise(rb_eIndexError, "NULL line");
1015 }
1016 else if (n >= 0 && n <= buf->b_ml.ml_line_count)
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001017 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001018 /* set curwin/curbuf for "buf" and save some things */
1019 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001020
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 if (u_inssub(n + 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001023
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001024 /* Changes to non-active buffers should properly refresh screen
1025 * SegPhault - 12/20/04 */
1026 appended_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001027
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001028 changed();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001030
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001031 /* restore curwin/curbuf and a few other things */
1032 aucmd_restbuf(&aco);
1033 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00001034
Bram Moolenaar071d4272004-06-13 20:20:40 +00001035 update_curbuf(NOT_VALID);
1036 }
1037 else {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001038 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 }
1040 return str;
1041}
1042
1043static VALUE window_new(win_T *win)
1044{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001045 if (win->w_ruby_ref)
1046 {
1047 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001049 else
1050 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaare344bea2005-09-01 20:46:49 +00001052 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1054 return obj;
1055 }
1056}
1057
1058static win_T *get_win(VALUE obj)
1059{
1060 win_T *win;
1061
1062 Data_Get_Struct(obj, win_T, win);
1063 if (win == NULL)
1064 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1065 return win;
1066}
1067
1068static VALUE window_s_current()
1069{
1070 return window_new(curwin);
1071}
1072
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001073/*
1074 * Added line manipulation functions
1075 * SegPhault - 03/07/05
1076 */
1077static VALUE line_s_current()
1078{
1079 return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1080}
1081
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001082static VALUE set_current_line(VALUE self UNUSED, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001083{
1084 return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1085}
1086
1087static VALUE current_line_number()
1088{
1089 return INT2FIX((int)curwin->w_cursor.lnum);
1090}
1091
1092
1093
Bram Moolenaar071d4272004-06-13 20:20:40 +00001094static VALUE window_s_count()
1095{
1096#ifdef FEAT_WINDOWS
1097 win_T *w;
1098 int n = 0;
1099
Bram Moolenaarf740b292006-02-16 22:11:02 +00001100 for (w = firstwin; w != NULL; w = w->w_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001101 n++;
1102 return INT2NUM(n);
1103#else
1104 return INT2NUM(1);
1105#endif
1106}
1107
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001108static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109{
1110 win_T *w;
1111 int n = NUM2INT(num);
1112
1113#ifndef FEAT_WINDOWS
1114 w = curwin;
1115#else
1116 for (w = firstwin; w != NULL; w = w->w_next, --n)
1117#endif
1118 if (n == 0)
1119 return window_new(w);
1120 return Qnil;
1121}
1122
1123static VALUE window_buffer(VALUE self)
1124{
1125 win_T *win = get_win(self);
1126
1127 return buffer_new(win->w_buffer);
1128}
1129
1130static VALUE window_height(VALUE self)
1131{
1132 win_T *win = get_win(self);
1133
1134 return INT2NUM(win->w_height);
1135}
1136
1137static VALUE window_set_height(VALUE self, VALUE height)
1138{
1139 win_T *win = get_win(self);
1140 win_T *savewin = curwin;
1141
1142 curwin = win;
1143 win_setheight(NUM2INT(height));
1144 curwin = savewin;
1145 return height;
1146}
1147
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001148static VALUE window_width(VALUE self)
1149{
1150 win_T *win = get_win(self);
1151
1152 return INT2NUM(win->w_width);
1153}
1154
1155static VALUE window_set_width(VALUE self, VALUE width)
1156{
1157 win_T *win = get_win(self);
1158 win_T *savewin = curwin;
1159
1160 curwin = win;
1161 win_setwidth(NUM2INT(width));
1162 curwin = savewin;
1163 return width;
1164}
1165
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166static VALUE window_cursor(VALUE self)
1167{
1168 win_T *win = get_win(self);
1169
1170 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1171}
1172
1173static VALUE window_set_cursor(VALUE self, VALUE pos)
1174{
1175 VALUE lnum, col;
1176 win_T *win = get_win(self);
1177
1178 Check_Type(pos, T_ARRAY);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001179 if (RARRAY_LEN(pos) != 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180 rb_raise(rb_eArgError, "array length must be 2");
Bram Moolenaar165641d2010-02-17 16:23:09 +01001181 lnum = RARRAY_PTR(pos)[0];
1182 col = RARRAY_PTR(pos)[1];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001183 win->w_cursor.lnum = NUM2LONG(lnum);
1184 win->w_cursor.col = NUM2UINT(col);
1185 check_cursor(); /* put cursor on an existing line */
1186 update_screen(NOT_VALID);
1187 return Qnil;
1188}
1189
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001190static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001191{
1192 int i;
1193 VALUE str = rb_str_new("", 0);
1194
1195 for (i = 0; i < argc; i++) {
1196 if (i > 0) rb_str_cat(str, ", ", 2);
1197 rb_str_concat(str, rb_inspect(argv[i]));
1198 }
Bram Moolenaar165641d2010-02-17 16:23:09 +01001199 MSG(RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001200 return Qnil;
1201}
1202
1203static void ruby_io_init(void)
1204{
1205#ifndef DYNAMIC_RUBY
1206 RUBYEXTERN VALUE rb_stdout;
1207#endif
1208
1209 rb_stdout = rb_obj_alloc(rb_cObject);
1210 rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1211 rb_define_global_function("p", f_p, -1);
1212}
1213
1214static void ruby_vim_init(void)
1215{
1216 objtbl = rb_hash_new();
1217 rb_global_variable(&objtbl);
1218
Bram Moolenaarf711faf2007-05-10 16:48:19 +00001219 /* The Vim module used to be called "VIM", but "Vim" is better. Make an
1220 * alias "VIM" for backwards compatiblity. */
1221 mVIM = rb_define_module("Vim");
1222 rb_define_const(rb_cObject, "VIM", mVIM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001223 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1224 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1225 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1226 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1227 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1228 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1229 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1230 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1231 rb_define_module_function(mVIM, "message", vim_message, 1);
1232 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1233 rb_define_module_function(mVIM, "command", vim_command, 1);
1234 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1235
1236 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1237 rb_eStandardError);
1238 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1239 rb_eStandardError);
1240
1241 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1242 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1243 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1244 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1245 rb_define_method(cBuffer, "name", buffer_name, 0);
1246 rb_define_method(cBuffer, "number", buffer_number, 0);
1247 rb_define_method(cBuffer, "count", buffer_count, 0);
1248 rb_define_method(cBuffer, "length", buffer_count, 0);
1249 rb_define_method(cBuffer, "[]", buffer_aref, 1);
1250 rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1251 rb_define_method(cBuffer, "delete", buffer_delete, 1);
1252 rb_define_method(cBuffer, "append", buffer_append, 2);
1253
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001254 /* Added line manipulation functions
1255 * SegPhault - 03/07/05 */
1256 rb_define_method(cBuffer, "line_number", current_line_number, 0);
1257 rb_define_method(cBuffer, "line", line_s_current, 0);
1258 rb_define_method(cBuffer, "line=", set_current_line, 1);
1259
1260
Bram Moolenaar071d4272004-06-13 20:20:40 +00001261 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1262 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1263 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1264 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1265 rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1266 rb_define_method(cVimWindow, "height", window_height, 0);
1267 rb_define_method(cVimWindow, "height=", window_set_height, 1);
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001268 rb_define_method(cVimWindow, "width", window_width, 0);
1269 rb_define_method(cVimWindow, "width=", window_set_width, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001270 rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1271 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1272
1273 rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1274 rb_define_virtual_variable("$curwin", window_s_current, 0);
1275}