blob: 802e1c1c7c07b0d81554d06ccf6c8119f1dca076 [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 Moolenaar42d57f02010-03-10 12:47:00 +010056#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
57/* Ruby 1.9 defines a number of static functions which use rb_num2long and
58 * rb_int2big */
59# define rb_num2long rb_num2long_stub
60# define rb_int2big rb_int2big_stub
61#endif
62
Bram Moolenaar071d4272004-06-13 20:20:40 +000063#include <ruby.h>
Bram Moolenaar165641d2010-02-17 16:23:09 +010064#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
65# include <ruby/encoding.h>
66#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000067
68#undef EXTERN
69#undef _
70
71/* T_DATA defined both by Ruby and Mac header files, hack around it... */
Bram Moolenaarcb635362007-05-12 13:02:42 +000072#if defined(MACOS_X_UNIX) || defined(macintosh)
Bram Moolenaar071d4272004-06-13 20:20:40 +000073# define __OPENTRANSPORT__
74# define __OPENTRANSPORTPROTOCOL__
75# define __OPENTRANSPORTPROVIDERS__
76#endif
77
Bram Moolenaar165641d2010-02-17 16:23:09 +010078/*
79 * Backward compatiblity for Ruby 1.8 and earlier.
80 * Ruby 1.9 does not provide STR2CSTR, instead StringValuePtr is provided.
81 * Ruby 1.9 does not provide RXXX(s)->len and RXXX(s)->ptr, instead
82 * RXXX_LEN(s) and RXXX_PTR(s) are provided.
83 */
84#ifndef StringValuePtr
85# define StringValuePtr(s) STR2CSTR(s)
86#endif
87#ifndef RARRAY_LEN
88# define RARRAY_LEN(s) RARRAY(s)->len
89#endif
90#ifndef RARRAY_PTR
91# define RARRAY_PTR(s) RARRAY(s)->ptr
92#endif
93#ifndef RSTRING_LEN
94# define RSTRING_LEN(s) RSTRING(s)->len
95#endif
96#ifndef RSTRING_PTR
97# define RSTRING_PTR(s) RSTRING(s)->ptr
98#endif
99
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100#include "vim.h"
101#include "version.h"
102
103#if defined(PROTO) && !defined(FEAT_RUBY)
104/* Define these to be able to generate the function prototypes. */
105# define VALUE int
106# define RUBY_DATA_FUNC int
107#endif
108
109static int ruby_initialized = 0;
110static VALUE objtbl;
111
112static VALUE mVIM;
113static VALUE cBuffer;
114static VALUE cVimWindow;
115static VALUE eDeletedBufferError;
116static VALUE eDeletedWindowError;
117
118static int ensure_ruby_initialized(void);
119static void error_print(int);
120static void ruby_io_init(void);
121static void ruby_vim_init(void);
122
123#if defined(DYNAMIC_RUBY) || defined(PROTO)
124#ifdef PROTO
125# define HINSTANCE int /* for generating prototypes */
126#endif
127
128/*
129 * Wrapper defines
130 */
131#define rb_assoc_new dll_rb_assoc_new
132#define rb_cObject (*dll_rb_cObject)
133#define rb_check_type dll_rb_check_type
134#define rb_class_path dll_rb_class_path
135#define rb_data_object_alloc dll_rb_data_object_alloc
136#define rb_define_class_under dll_rb_define_class_under
137#define rb_define_const dll_rb_define_const
138#define rb_define_global_function dll_rb_define_global_function
139#define rb_define_method dll_rb_define_method
140#define rb_define_module dll_rb_define_module
141#define rb_define_module_function dll_rb_define_module_function
142#define rb_define_singleton_method dll_rb_define_singleton_method
143#define rb_define_virtual_variable dll_rb_define_virtual_variable
144#define rb_stdout (*dll_rb_stdout)
145#define rb_eArgError (*dll_rb_eArgError)
146#define rb_eIndexError (*dll_rb_eIndexError)
147#define rb_eRuntimeError (*dll_rb_eRuntimeError)
148#define rb_eStandardError (*dll_rb_eStandardError)
149#define rb_eval_string_protect dll_rb_eval_string_protect
150#define rb_global_variable dll_rb_global_variable
151#define rb_hash_aset dll_rb_hash_aset
152#define rb_hash_new dll_rb_hash_new
153#define rb_inspect dll_rb_inspect
154#define rb_int2inum dll_rb_int2inum
155#define rb_lastline_get dll_rb_lastline_get
156#define rb_lastline_set dll_rb_lastline_set
157#define rb_load_protect dll_rb_load_protect
158#define rb_num2long dll_rb_num2long
159#define rb_num2ulong dll_rb_num2ulong
160#define rb_obj_alloc dll_rb_obj_alloc
161#define rb_obj_as_string dll_rb_obj_as_string
162#define rb_obj_id dll_rb_obj_id
163#define rb_raise dll_rb_raise
164#define rb_str2cstr dll_rb_str2cstr
165#define rb_str_cat dll_rb_str_cat
166#define rb_str_concat dll_rb_str_concat
167#define rb_str_new dll_rb_str_new
168#define rb_str_new2 dll_rb_str_new2
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100169#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
170# define rb_string_value_ptr dll_rb_string_value_ptr
171# define rb_float_new dll_rb_float_new
172# define rb_ary_new dll_rb_ary_new
173# define rb_ary_push dll_rb_ary_push
174#endif
175#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 \
176 || defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
Bram Moolenaar165641d2010-02-17 16:23:09 +0100177# define rb_errinfo dll_rb_errinfo
178#else
179# define ruby_errinfo (*dll_ruby_errinfo)
180#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000181#define ruby_init dll_ruby_init
182#define ruby_init_loadpath dll_ruby_init_loadpath
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100183#define NtInitialize dll_NtInitialize
Bram Moolenaar071d4272004-06-13 20:20:40 +0000184#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
185# define rb_w32_snprintf dll_rb_w32_snprintf
186#endif
187
Bram Moolenaar165641d2010-02-17 16:23:09 +0100188#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
189# define ruby_script dll_ruby_script
190# define rb_enc_find_index dll_rb_enc_find_index
191# define rb_enc_find dll_rb_enc_find
192# define rb_enc_str_new dll_rb_enc_str_new
193# define rb_sprintf dll_rb_sprintf
194#endif
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196/*
197 * Pointers for dynamic link
198 */
199static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
200static VALUE *dll_rb_cFalseClass;
201static VALUE *dll_rb_cFixnum;
202static VALUE *dll_rb_cNilClass;
203static VALUE *dll_rb_cObject;
204static VALUE *dll_rb_cSymbol;
205static VALUE *dll_rb_cTrueClass;
206static void (*dll_rb_check_type) (VALUE,int);
207static VALUE (*dll_rb_class_path) (VALUE);
208static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
209static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
210static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
211static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
212static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
213static VALUE (*dll_rb_define_module) (const char*);
214static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
215static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
216static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
217static VALUE *dll_rb_stdout;
218static VALUE *dll_rb_eArgError;
219static VALUE *dll_rb_eIndexError;
220static VALUE *dll_rb_eRuntimeError;
221static VALUE *dll_rb_eStandardError;
222static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
223static void (*dll_rb_global_variable) (VALUE*);
224static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
225static VALUE (*dll_rb_hash_new) (void);
226static VALUE (*dll_rb_inspect) (VALUE);
227static VALUE (*dll_rb_int2inum) (long);
228static VALUE (*dll_rb_int2inum) (long);
229static VALUE (*dll_rb_lastline_get) (void);
230static void (*dll_rb_lastline_set) (VALUE);
231static void (*dll_rb_load_protect) (VALUE, int, int*);
232static long (*dll_rb_num2long) (VALUE);
233static unsigned long (*dll_rb_num2ulong) (VALUE);
234static VALUE (*dll_rb_obj_alloc) (VALUE);
235static VALUE (*dll_rb_obj_as_string) (VALUE);
236static VALUE (*dll_rb_obj_id) (VALUE);
237static void (*dll_rb_raise) (VALUE, const char*, ...);
238static char *(*dll_rb_str2cstr) (VALUE,int*);
239static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
240static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
241static VALUE (*dll_rb_str_new) (const char*, long);
242static VALUE (*dll_rb_str_new2) (const char*);
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100243#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 \
244 || defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
Bram Moolenaar165641d2010-02-17 16:23:09 +0100245static VALUE (*dll_rb_errinfo) (void);
246#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247static VALUE *dll_ruby_errinfo;
Bram Moolenaar165641d2010-02-17 16:23:09 +0100248#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249static void (*dll_ruby_init) (void);
250static void (*dll_ruby_init_loadpath) (void);
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100251static void (*dll_NtInitialize) (int*, char***);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000252#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100253static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
254static VALUE (*dll_rb_float_new) (double);
255static VALUE (*dll_rb_ary_new) (void);
256static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
257#endif
258#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
259static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
260#endif
261#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
263#endif
264
Bram Moolenaar165641d2010-02-17 16:23:09 +0100265#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
266static void (*dll_ruby_script) (const char*);
267static int (*dll_rb_enc_find_index) (const char*);
268static rb_encoding* (*dll_rb_enc_find) (const char*);
269static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
270static VALUE (*dll_rb_sprintf) (const char*, ...);
271#endif
272
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100273#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
274static SIGNED_VALUE rb_num2long_stub(VALUE x)
275{
276 return dll_rb_num2long(x);
277}
278static VALUE rb_int2big_stub(SIGNED_VALUE x)
279{
280 return dll_rb_int2big(x);
281}
282#endif
283
Bram Moolenaar071d4272004-06-13 20:20:40 +0000284static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */
285
286/*
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000287 * Table of name to function pointer of ruby.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288 */
289#define RUBY_PROC FARPROC
290static struct
291{
292 char *name;
293 RUBY_PROC *ptr;
294} ruby_funcname_table[] =
295{
296 {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
297 {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
298 {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
299 {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
300 {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
301 {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
302 {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
303 {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
304 {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
305 {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
306 {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
307 {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
308 {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
309 {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
310 {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
311 {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
312 {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
313 {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
314 {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
315 {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
316 {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
317 {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
318 {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
319 {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
320 {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
321 {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
322 {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
323 {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
324 {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
325 {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
326 {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
327 {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
328 {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
329 {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
330 {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
331 {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
332 {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
333 {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
334 {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
335 {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
336 {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
337 {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
338 {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100339#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 \
340 || defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
Bram Moolenaar165641d2010-02-17 16:23:09 +0100341 {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
342#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343 {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100344#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000345 {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
346 {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100347 {
348#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19
349 "NtInitialize",
350#else
351 "ruby_sysinit",
352#endif
353 (RUBY_PROC*)&dll_NtInitialize},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000354#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
355 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
356#endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100357#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
358 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
359 {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
360 {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
361 {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
362#endif
363#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
364 {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
365#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100366#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
367 {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
368 {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
369 {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
370 {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
371 {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
372#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373 {"", NULL},
374};
375
376/*
377 * Free ruby.dll
378 */
379 static void
380end_dynamic_ruby()
381{
382 if (hinstRuby)
383 {
384 FreeLibrary(hinstRuby);
385 hinstRuby = 0;
386 }
387}
388
389/*
390 * Load library and get all pointers.
391 * Parameter 'libname' provides name of DLL.
392 * Return OK or FAIL.
393 */
394 static int
395ruby_runtime_link_init(char *libname, int verbose)
396{
397 int i;
398
399 if (hinstRuby)
400 return OK;
401 hinstRuby = LoadLibrary(libname);
402 if (!hinstRuby)
403 {
404 if (verbose)
405 EMSG2(_(e_loadlib), libname);
406 return FAIL;
407 }
408
409 for (i = 0; ruby_funcname_table[i].ptr; ++i)
410 {
411 if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby,
412 ruby_funcname_table[i].name)))
413 {
414 FreeLibrary(hinstRuby);
415 hinstRuby = 0;
416 if (verbose)
417 EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
418 return FAIL;
419 }
420 }
421 return OK;
422}
423
424/*
425 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
426 * else FALSE.
427 */
428 int
429ruby_enabled(verbose)
430 int verbose;
431{
432 return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
433}
434#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
435
436 void
437ruby_end()
438{
439#ifdef DYNAMIC_RUBY
440 end_dynamic_ruby();
441#endif
442}
443
444void ex_ruby(exarg_T *eap)
445{
446 int state;
447 char *script = NULL;
448
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000449 script = (char *)script_get(eap, eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 if (!eap->skip && ensure_ruby_initialized())
451 {
452 if (script == NULL)
453 rb_eval_string_protect((char *)eap->arg, &state);
454 else
455 rb_eval_string_protect(script, &state);
456 if (state)
457 error_print(state);
458 }
459 vim_free(script);
460}
461
Bram Moolenaar165641d2010-02-17 16:23:09 +0100462/*
463 * In Ruby 1.9 or later, ruby String object has encoding.
464 * conversion buffer string of vim to ruby String object using
465 * VIM encoding option.
466 */
467 static VALUE
468vim_str2rb_enc_str(const char *s)
469{
470#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
471 int isnum;
472 long lval;
473 char_u *sval;
474 rb_encoding *enc;
475
476 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
477 if (isnum == 0)
478 {
479 enc = rb_enc_find((char *)sval);
480 vim_free(sval);
481 if (enc) {
482 return rb_enc_str_new(s, strlen(s), enc);
483 }
484 }
485#endif
486 return rb_str_new2(s);
487}
488
489 static VALUE
490eval_enc_string_protect(const char *str, int *state)
491{
492#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
493 int isnum;
494 long lval;
495 char_u *sval;
496 rb_encoding *enc;
497 VALUE v;
498
499 isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
500 if (isnum == 0)
501 {
502 enc = rb_enc_find((char *)sval);
503 vim_free(sval);
504 if (enc)
505 {
506 v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
507 return rb_eval_string_protect(StringValuePtr(v), state);
508 }
509 }
510#endif
511 return rb_eval_string_protect(str, state);
512}
513
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514void ex_rubydo(exarg_T *eap)
515{
516 int state;
517 linenr_T i;
518
519 if (ensure_ruby_initialized())
520 {
521 if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
522 return;
523 for (i = eap->line1; i <= eap->line2; i++) {
524 VALUE line, oldline;
525
Bram Moolenaar165641d2010-02-17 16:23:09 +0100526 line = oldline = vim_str2rb_enc_str((char *)ml_get(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 rb_lastline_set(line);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100528 eval_enc_string_protect((char *) eap->arg, &state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 if (state) {
530 error_print(state);
531 break;
532 }
533 line = rb_lastline_get();
534 if (!NIL_P(line)) {
535 if (TYPE(line) != T_STRING) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000536 EMSG(_("E265: $_ must be an instance of String"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537 return;
538 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100539 ml_replace(i, (char_u *) StringValuePtr(line), 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000540 changed();
541#ifdef SYNTAX_HL
542 syn_changed(i); /* recompute syntax hl. for this line */
543#endif
544 }
545 }
546 check_cursor();
547 update_curbuf(NOT_VALID);
548 }
549}
550
551void ex_rubyfile(exarg_T *eap)
552{
553 int state;
554
555 if (ensure_ruby_initialized())
556 {
557 rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
558 if (state) error_print(state);
559 }
560}
561
562void ruby_buffer_free(buf_T *buf)
563{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000564 if (buf->b_ruby_ref)
565 {
566 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
567 RDATA(buf->b_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568 }
569}
570
571void ruby_window_free(win_T *win)
572{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000573 if (win->w_ruby_ref)
574 {
575 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
576 RDATA(win->w_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577 }
578}
579
580static int ensure_ruby_initialized(void)
581{
582 if (!ruby_initialized)
583 {
584#ifdef DYNAMIC_RUBY
585 if (ruby_enabled(TRUE))
586 {
587#endif
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100588#ifdef _WIN32
589 /* suggested by Ariya Mizutani */
590 int argc = 1;
591 char *argv[] = {"gvim.exe"};
592 NtInitialize(&argc, &argv);
593#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100594#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
595 RUBY_INIT_STACK;
596#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597 ruby_init();
Bram Moolenaar165641d2010-02-17 16:23:09 +0100598#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
599 ruby_script("vim-ruby");
600#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000601 ruby_init_loadpath();
602 ruby_io_init();
Bram Moolenaar165641d2010-02-17 16:23:09 +0100603#if defined(RUBY_VERSION) && RUBY_VERSION >= 19
604 rb_enc_find_index("encdb");
605#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606 ruby_vim_init();
607 ruby_initialized = 1;
608#ifdef DYNAMIC_RUBY
609 }
610 else
611 {
612 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
613 return 0;
614 }
615#endif
616 }
617 return ruby_initialized;
618}
619
620static void error_print(int state)
621{
622#ifndef DYNAMIC_RUBY
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100623#if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
624 && !(defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000625 RUBYEXTERN VALUE ruby_errinfo;
626#endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100627#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628 VALUE eclass;
629 VALUE einfo;
630 char buff[BUFSIZ];
631
632#define TAG_RETURN 0x1
633#define TAG_BREAK 0x2
634#define TAG_NEXT 0x3
635#define TAG_RETRY 0x4
636#define TAG_REDO 0x5
637#define TAG_RAISE 0x6
638#define TAG_THROW 0x7
639#define TAG_FATAL 0x8
640#define TAG_MASK 0xf
641
642 switch (state) {
643 case TAG_RETURN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000644 EMSG(_("E267: unexpected return"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000645 break;
646 case TAG_NEXT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000647 EMSG(_("E268: unexpected next"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000648 break;
649 case TAG_BREAK:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000650 EMSG(_("E269: unexpected break"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651 break;
652 case TAG_REDO:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000653 EMSG(_("E270: unexpected redo"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 break;
655 case TAG_RETRY:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000656 EMSG(_("E271: retry outside of rescue clause"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000657 break;
658 case TAG_RAISE:
659 case TAG_FATAL:
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100660#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 \
661 || defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
Bram Moolenaar165641d2010-02-17 16:23:09 +0100662 eclass = CLASS_OF(rb_errinfo());
663 einfo = rb_obj_as_string(rb_errinfo());
664#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 eclass = CLASS_OF(ruby_errinfo);
666 einfo = rb_obj_as_string(ruby_errinfo);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100667#endif
668 if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000669 EMSG(_("E272: unhandled exception"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 }
671 else {
672 VALUE epath;
673 char *p;
674
675 epath = rb_class_path(eclass);
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000676 vim_snprintf(buff, BUFSIZ, "%s: %s",
Bram Moolenaar165641d2010-02-17 16:23:09 +0100677 RSTRING_PTR(epath), RSTRING_PTR(einfo));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 p = strchr(buff, '\n');
679 if (p) *p = '\0';
680 EMSG(buff);
681 }
682 break;
683 default:
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000684 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 EMSG(buff);
686 break;
687 }
688}
689
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000690static VALUE vim_message(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691{
692 char *buff, *p;
693
694 str = rb_obj_as_string(str);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100695 buff = ALLOCA_N(char, RSTRING_LEN(str));
696 strcpy(buff, RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000697 p = strchr(buff, '\n');
698 if (p) *p = '\0';
699 MSG(buff);
700 return Qnil;
701}
702
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000703static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100705 do_set((char_u *)StringValuePtr(str), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706 update_screen(NOT_VALID);
707 return Qnil;
708}
709
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000710static VALUE vim_command(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000711{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100712 do_cmdline_cmd((char_u *)StringValuePtr(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 return Qnil;
714}
715
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100716#ifdef FEAT_EVAL
717static VALUE vim_to_ruby(typval_T *tv)
718{
719 VALUE result = Qnil;
720
721 if (tv->v_type == VAR_STRING)
722 {
723 result = rb_str_new2((char *)tv->vval.v_string);
724 }
725 else if (tv->v_type == VAR_NUMBER)
726 {
727 result = INT2NUM(tv->vval.v_number);
728 }
729# ifdef FEAT_FLOAT
730 else if (tv->v_type == VAR_FLOAT)
731 {
732 result = rb_float_new(tv->vval.v_float);
733 }
734# endif
735 else if (tv->v_type == VAR_LIST)
736 {
737 list_T *list = tv->vval.v_list;
738 listitem_T *curr;
739
740 result = rb_ary_new();
741
742 if (list != NULL)
743 {
744 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
745 {
746 rb_ary_push(result, vim_to_ruby(&curr->li_tv));
747 }
748 }
749 }
750 else if (tv->v_type == VAR_DICT)
751 {
752 result = rb_hash_new();
753
754 if (tv->vval.v_dict != NULL)
755 {
756 hashtab_T *ht = &tv->vval.v_dict->dv_hashtab;
757 long_u todo = ht->ht_used;
758 hashitem_T *hi;
759 dictitem_T *di;
760
761 for (hi = ht->ht_array; todo > 0; ++hi)
762 {
763 if (!HASHITEM_EMPTY(hi))
764 {
765 --todo;
766
767 di = dict_lookup(hi);
768 rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
769 vim_to_ruby(&di->di_tv));
770 }
771 }
772 }
773 } /* else return Qnil; */
774
775 return result;
776}
777#endif
778
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000779static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780{
781#ifdef FEAT_EVAL
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100782 typval_T *tv;
783 VALUE result;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100785 tv = eval_expr((char_u *)StringValuePtr(str), NULL);
786 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 {
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100788 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +0100790 result = vim_to_ruby(tv);
791
792 free_tv(tv);
793
794 return result;
795#else
796 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798}
799
800static VALUE buffer_new(buf_T *buf)
801{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000802 if (buf->b_ruby_ref)
803 {
804 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000806 else
807 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000809 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
811 return obj;
812 }
813}
814
815static buf_T *get_buf(VALUE obj)
816{
817 buf_T *buf;
818
819 Data_Get_Struct(obj, buf_T, buf);
820 if (buf == NULL)
821 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
822 return buf;
823}
824
825static VALUE buffer_s_current()
826{
827 return buffer_new(curbuf);
828}
829
830static VALUE buffer_s_count()
831{
832 buf_T *b;
833 int n = 0;
834
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000835 for (b = firstbuf; b != NULL; b = b->b_next)
836 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000837 /* Deleted buffers should not be counted
838 * SegPhault - 01/07/05 */
839 if (b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000840 n++;
841 }
842
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843 return INT2NUM(n);
844}
845
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000846static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847{
848 buf_T *b;
849 int n = NUM2INT(num);
850
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000851 for (b = firstbuf; b != NULL; b = b->b_next)
852 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000853 /* Deleted buffers should not be counted
854 * SegPhault - 01/07/05 */
855 if (!b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000856 continue;
857
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000858 if (n == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 return buffer_new(b);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000860
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000861 n--;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 }
863 return Qnil;
864}
865
866static VALUE buffer_name(VALUE self)
867{
868 buf_T *buf = get_buf(self);
869
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000870 return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871}
872
873static VALUE buffer_number(VALUE self)
874{
875 buf_T *buf = get_buf(self);
876
877 return INT2NUM(buf->b_fnum);
878}
879
880static VALUE buffer_count(VALUE self)
881{
882 buf_T *buf = get_buf(self);
883
884 return INT2NUM(buf->b_ml.ml_line_count);
885}
886
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000887static VALUE get_buffer_line(buf_T *buf, linenr_T n)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888{
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000889 if (n > 0 && n <= buf->b_ml.ml_line_count)
890 {
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000891 char *line = (char *)ml_get_buf(buf, n, FALSE);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100892 return line ? vim_str2rb_enc_str(line) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100894 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000895#ifndef __GNUC__
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000896 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000897#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898}
899
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000900static VALUE buffer_aref(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901{
902 buf_T *buf = get_buf(self);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000903
904 if (buf != NULL)
905 return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
906 return Qnil; /* For stop warning */
907}
908
909static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
910{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100911 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000912 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000914 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
915 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000916 /* set curwin/curbuf for "buf" and save some things */
917 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000918
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 if (u_savesub(n) == OK) {
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000920 ml_replace(n, (char_u *)line, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 changed();
922#ifdef SYNTAX_HL
923 syn_changed(n); /* recompute syntax hl. for this line */
924#endif
925 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000926
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000927 /* restore curwin/curbuf and a few other things */
928 aucmd_restbuf(&aco);
929 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000930
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931 update_curbuf(NOT_VALID);
932 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000933 else
934 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100935 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000936#ifndef __GNUC__
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 return Qnil; /* For stop warning */
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +0000938#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 }
940 return str;
941}
942
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000943static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
944{
945 buf_T *buf = get_buf(self);
946
947 if (buf != NULL)
948 return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
949 return str;
950}
951
Bram Moolenaar071d4272004-06-13 20:20:40 +0000952static VALUE buffer_delete(VALUE self, VALUE num)
953{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000954 buf_T *buf = get_buf(self);
955 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000956 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000958 if (n > 0 && n <= buf->b_ml.ml_line_count)
959 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000960 /* set curwin/curbuf for "buf" and save some things */
961 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000962
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 if (u_savedel(n, 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 ml_delete(n, 0);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000965
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000966 /* Changes to non-active buffers should properly refresh
967 * SegPhault - 01/09/05 */
968 deleted_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +0000969
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 changed();
971 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000972
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000973 /* restore curwin/curbuf and a few other things */
974 aucmd_restbuf(&aco);
975 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +0000976
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 update_curbuf(NOT_VALID);
978 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000979 else
980 {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100981 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 }
983 return Qnil;
984}
985
986static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
987{
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000988 buf_T *buf = get_buf(self);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100989 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000990 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000991 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992
Bram Moolenaar83bac8b2010-02-18 15:53:29 +0100993 if (line == NULL) {
Bram Moolenaar165641d2010-02-17 16:23:09 +0100994 rb_raise(rb_eIndexError, "NULL line");
995 }
996 else if (n >= 0 && n <= buf->b_ml.ml_line_count)
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000997 {
Bram Moolenaar20ff7922006-06-20 19:10:43 +0000998 /* set curwin/curbuf for "buf" and save some things */
999 aucmd_prepbuf(&aco, buf);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001000
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001 if (u_inssub(n + 1) == OK) {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001003
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001004 /* Changes to non-active buffers should properly refresh screen
1005 * SegPhault - 12/20/04 */
1006 appended_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001007
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001008 changed();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001010
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001011 /* restore curwin/curbuf and a few other things */
1012 aucmd_restbuf(&aco);
1013 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00001014
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015 update_curbuf(NOT_VALID);
1016 }
1017 else {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001018 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 }
1020 return str;
1021}
1022
1023static VALUE window_new(win_T *win)
1024{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001025 if (win->w_ruby_ref)
1026 {
1027 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001029 else
1030 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaare344bea2005-09-01 20:46:49 +00001032 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1034 return obj;
1035 }
1036}
1037
1038static win_T *get_win(VALUE obj)
1039{
1040 win_T *win;
1041
1042 Data_Get_Struct(obj, win_T, win);
1043 if (win == NULL)
1044 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1045 return win;
1046}
1047
1048static VALUE window_s_current()
1049{
1050 return window_new(curwin);
1051}
1052
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001053/*
1054 * Added line manipulation functions
1055 * SegPhault - 03/07/05
1056 */
1057static VALUE line_s_current()
1058{
1059 return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1060}
1061
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001062static VALUE set_current_line(VALUE self UNUSED, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001063{
1064 return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1065}
1066
1067static VALUE current_line_number()
1068{
1069 return INT2FIX((int)curwin->w_cursor.lnum);
1070}
1071
1072
1073
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074static VALUE window_s_count()
1075{
1076#ifdef FEAT_WINDOWS
1077 win_T *w;
1078 int n = 0;
1079
Bram Moolenaarf740b292006-02-16 22:11:02 +00001080 for (w = firstwin; w != NULL; w = w->w_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081 n++;
1082 return INT2NUM(n);
1083#else
1084 return INT2NUM(1);
1085#endif
1086}
1087
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001088static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089{
1090 win_T *w;
1091 int n = NUM2INT(num);
1092
1093#ifndef FEAT_WINDOWS
1094 w = curwin;
1095#else
1096 for (w = firstwin; w != NULL; w = w->w_next, --n)
1097#endif
1098 if (n == 0)
1099 return window_new(w);
1100 return Qnil;
1101}
1102
1103static VALUE window_buffer(VALUE self)
1104{
1105 win_T *win = get_win(self);
1106
1107 return buffer_new(win->w_buffer);
1108}
1109
1110static VALUE window_height(VALUE self)
1111{
1112 win_T *win = get_win(self);
1113
1114 return INT2NUM(win->w_height);
1115}
1116
1117static VALUE window_set_height(VALUE self, VALUE height)
1118{
1119 win_T *win = get_win(self);
1120 win_T *savewin = curwin;
1121
1122 curwin = win;
1123 win_setheight(NUM2INT(height));
1124 curwin = savewin;
1125 return height;
1126}
1127
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001128static VALUE window_width(VALUE self)
1129{
1130 win_T *win = get_win(self);
1131
1132 return INT2NUM(win->w_width);
1133}
1134
1135static VALUE window_set_width(VALUE self, VALUE width)
1136{
1137 win_T *win = get_win(self);
1138 win_T *savewin = curwin;
1139
1140 curwin = win;
1141 win_setwidth(NUM2INT(width));
1142 curwin = savewin;
1143 return width;
1144}
1145
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146static VALUE window_cursor(VALUE self)
1147{
1148 win_T *win = get_win(self);
1149
1150 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1151}
1152
1153static VALUE window_set_cursor(VALUE self, VALUE pos)
1154{
1155 VALUE lnum, col;
1156 win_T *win = get_win(self);
1157
1158 Check_Type(pos, T_ARRAY);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001159 if (RARRAY_LEN(pos) != 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160 rb_raise(rb_eArgError, "array length must be 2");
Bram Moolenaar165641d2010-02-17 16:23:09 +01001161 lnum = RARRAY_PTR(pos)[0];
1162 col = RARRAY_PTR(pos)[1];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163 win->w_cursor.lnum = NUM2LONG(lnum);
1164 win->w_cursor.col = NUM2UINT(col);
1165 check_cursor(); /* put cursor on an existing line */
1166 update_screen(NOT_VALID);
1167 return Qnil;
1168}
1169
Bram Moolenaarcd8b20a2009-05-22 16:20:57 +00001170static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001171{
1172 int i;
1173 VALUE str = rb_str_new("", 0);
1174
1175 for (i = 0; i < argc; i++) {
1176 if (i > 0) rb_str_cat(str, ", ", 2);
1177 rb_str_concat(str, rb_inspect(argv[i]));
1178 }
Bram Moolenaar165641d2010-02-17 16:23:09 +01001179 MSG(RSTRING_PTR(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180 return Qnil;
1181}
1182
1183static void ruby_io_init(void)
1184{
1185#ifndef DYNAMIC_RUBY
1186 RUBYEXTERN VALUE rb_stdout;
1187#endif
1188
1189 rb_stdout = rb_obj_alloc(rb_cObject);
1190 rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1191 rb_define_global_function("p", f_p, -1);
1192}
1193
1194static void ruby_vim_init(void)
1195{
1196 objtbl = rb_hash_new();
1197 rb_global_variable(&objtbl);
1198
Bram Moolenaarf711faf2007-05-10 16:48:19 +00001199 /* The Vim module used to be called "VIM", but "Vim" is better. Make an
1200 * alias "VIM" for backwards compatiblity. */
1201 mVIM = rb_define_module("Vim");
1202 rb_define_const(rb_cObject, "VIM", mVIM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001203 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1204 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1205 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1206 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1207 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1208 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1209 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1210 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1211 rb_define_module_function(mVIM, "message", vim_message, 1);
1212 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1213 rb_define_module_function(mVIM, "command", vim_command, 1);
1214 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1215
1216 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1217 rb_eStandardError);
1218 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1219 rb_eStandardError);
1220
1221 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1222 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1223 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1224 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1225 rb_define_method(cBuffer, "name", buffer_name, 0);
1226 rb_define_method(cBuffer, "number", buffer_number, 0);
1227 rb_define_method(cBuffer, "count", buffer_count, 0);
1228 rb_define_method(cBuffer, "length", buffer_count, 0);
1229 rb_define_method(cBuffer, "[]", buffer_aref, 1);
1230 rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1231 rb_define_method(cBuffer, "delete", buffer_delete, 1);
1232 rb_define_method(cBuffer, "append", buffer_append, 2);
1233
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001234 /* Added line manipulation functions
1235 * SegPhault - 03/07/05 */
1236 rb_define_method(cBuffer, "line_number", current_line_number, 0);
1237 rb_define_method(cBuffer, "line", line_s_current, 0);
1238 rb_define_method(cBuffer, "line=", set_current_line, 1);
1239
1240
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1242 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1243 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1244 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1245 rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1246 rb_define_method(cVimWindow, "height", window_height, 0);
1247 rb_define_method(cVimWindow, "height=", window_set_height, 1);
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001248 rb_define_method(cVimWindow, "width", window_width, 0);
1249 rb_define_method(cVimWindow, "width=", window_set_width, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250 rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1251 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1252
1253 rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1254 rb_define_virtual_variable("$curwin", window_s_current, 0);
1255}