blob: 6e9f95d652f704dd698f53420bd7e6bd79c67974 [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
4 * Ruby interface by Shugo Maeda.
5 *
6 * Do ":help uganda" in Vim to read copying and usage conditions.
7 * Do ":help credits" in Vim to see a list of people who contributed.
8 * See README.txt for an overview of the Vim source code.
9 */
10
11#include <stdio.h>
12#include <string.h>
13
14#ifdef _WIN32
15# if !defined(DYNAMIC_RUBY_VER) || (DYNAMIC_RUBY_VER < 18)
16# define NT
17# endif
18# ifndef DYNAMIC_RUBY
19# define IMPORT /* For static dll usage __declspec(dllimport) */
20# define RUBYEXTERN __declspec(dllimport)
21# endif
22#endif
23#ifndef RUBYEXTERN
24# define RUBYEXTERN extern
25#endif
26
27/*
28 * This is tricky. In ruby.h there is (inline) function rb_class_of()
29 * definition. This function use these variables. But we want function to
30 * use dll_* variables.
31 */
32#ifdef DYNAMIC_RUBY
33# define rb_cFalseClass (*dll_rb_cFalseClass)
34# define rb_cFixnum (*dll_rb_cFixnum)
35# define rb_cNilClass (*dll_rb_cNilClass)
36# define rb_cSymbol (*dll_rb_cSymbol)
37# define rb_cTrueClass (*dll_rb_cTrueClass)
38# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
39/*
40 * On ver 1.8, all Ruby functions are exported with "__declspce(dllimport)"
41 * in ruby.h. But it cause trouble for these variables, because it is
42 * defined in this file. When defined this RUBY_EXPORT it modified to
43 * "extern" and be able to avoid this problem.
44 */
45# define RUBY_EXPORT
46# endif
47#endif
48
49#include <ruby.h>
50
51#undef EXTERN
52#undef _
53
54/* T_DATA defined both by Ruby and Mac header files, hack around it... */
55#ifdef FEAT_GUI_MAC
56# define __OPENTRANSPORT__
57# define __OPENTRANSPORTPROTOCOL__
58# define __OPENTRANSPORTPROVIDERS__
59#endif
60
61#include "vim.h"
62#include "version.h"
63
64#if defined(PROTO) && !defined(FEAT_RUBY)
65/* Define these to be able to generate the function prototypes. */
66# define VALUE int
67# define RUBY_DATA_FUNC int
68#endif
69
70static int ruby_initialized = 0;
71static VALUE objtbl;
72
73static VALUE mVIM;
74static VALUE cBuffer;
75static VALUE cVimWindow;
76static VALUE eDeletedBufferError;
77static VALUE eDeletedWindowError;
78
79static int ensure_ruby_initialized(void);
80static void error_print(int);
81static void ruby_io_init(void);
82static void ruby_vim_init(void);
83
84#if defined(DYNAMIC_RUBY) || defined(PROTO)
85#ifdef PROTO
86# define HINSTANCE int /* for generating prototypes */
87#endif
88
89/*
90 * Wrapper defines
91 */
92#define rb_assoc_new dll_rb_assoc_new
93#define rb_cObject (*dll_rb_cObject)
94#define rb_check_type dll_rb_check_type
95#define rb_class_path dll_rb_class_path
96#define rb_data_object_alloc dll_rb_data_object_alloc
97#define rb_define_class_under dll_rb_define_class_under
98#define rb_define_const dll_rb_define_const
99#define rb_define_global_function dll_rb_define_global_function
100#define rb_define_method dll_rb_define_method
101#define rb_define_module dll_rb_define_module
102#define rb_define_module_function dll_rb_define_module_function
103#define rb_define_singleton_method dll_rb_define_singleton_method
104#define rb_define_virtual_variable dll_rb_define_virtual_variable
105#define rb_stdout (*dll_rb_stdout)
106#define rb_eArgError (*dll_rb_eArgError)
107#define rb_eIndexError (*dll_rb_eIndexError)
108#define rb_eRuntimeError (*dll_rb_eRuntimeError)
109#define rb_eStandardError (*dll_rb_eStandardError)
110#define rb_eval_string_protect dll_rb_eval_string_protect
111#define rb_global_variable dll_rb_global_variable
112#define rb_hash_aset dll_rb_hash_aset
113#define rb_hash_new dll_rb_hash_new
114#define rb_inspect dll_rb_inspect
115#define rb_int2inum dll_rb_int2inum
116#define rb_lastline_get dll_rb_lastline_get
117#define rb_lastline_set dll_rb_lastline_set
118#define rb_load_protect dll_rb_load_protect
119#define rb_num2long dll_rb_num2long
120#define rb_num2ulong dll_rb_num2ulong
121#define rb_obj_alloc dll_rb_obj_alloc
122#define rb_obj_as_string dll_rb_obj_as_string
123#define rb_obj_id dll_rb_obj_id
124#define rb_raise dll_rb_raise
125#define rb_str2cstr dll_rb_str2cstr
126#define rb_str_cat dll_rb_str_cat
127#define rb_str_concat dll_rb_str_concat
128#define rb_str_new dll_rb_str_new
129#define rb_str_new2 dll_rb_str_new2
130#define ruby_errinfo (*dll_ruby_errinfo)
131#define ruby_init dll_ruby_init
132#define ruby_init_loadpath dll_ruby_init_loadpath
133#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
134# define rb_w32_snprintf dll_rb_w32_snprintf
135#endif
136
137/*
138 * Pointers for dynamic link
139 */
140static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
141static VALUE *dll_rb_cFalseClass;
142static VALUE *dll_rb_cFixnum;
143static VALUE *dll_rb_cNilClass;
144static VALUE *dll_rb_cObject;
145static VALUE *dll_rb_cSymbol;
146static VALUE *dll_rb_cTrueClass;
147static void (*dll_rb_check_type) (VALUE,int);
148static VALUE (*dll_rb_class_path) (VALUE);
149static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
150static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
151static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
152static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
153static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
154static VALUE (*dll_rb_define_module) (const char*);
155static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
156static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
157static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
158static VALUE *dll_rb_stdout;
159static VALUE *dll_rb_eArgError;
160static VALUE *dll_rb_eIndexError;
161static VALUE *dll_rb_eRuntimeError;
162static VALUE *dll_rb_eStandardError;
163static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
164static void (*dll_rb_global_variable) (VALUE*);
165static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
166static VALUE (*dll_rb_hash_new) (void);
167static VALUE (*dll_rb_inspect) (VALUE);
168static VALUE (*dll_rb_int2inum) (long);
169static VALUE (*dll_rb_int2inum) (long);
170static VALUE (*dll_rb_lastline_get) (void);
171static void (*dll_rb_lastline_set) (VALUE);
172static void (*dll_rb_load_protect) (VALUE, int, int*);
173static long (*dll_rb_num2long) (VALUE);
174static unsigned long (*dll_rb_num2ulong) (VALUE);
175static VALUE (*dll_rb_obj_alloc) (VALUE);
176static VALUE (*dll_rb_obj_as_string) (VALUE);
177static VALUE (*dll_rb_obj_id) (VALUE);
178static void (*dll_rb_raise) (VALUE, const char*, ...);
179static char *(*dll_rb_str2cstr) (VALUE,int*);
180static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
181static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
182static VALUE (*dll_rb_str_new) (const char*, long);
183static VALUE (*dll_rb_str_new2) (const char*);
184static VALUE *dll_ruby_errinfo;
185static void (*dll_ruby_init) (void);
186static void (*dll_ruby_init_loadpath) (void);
187#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
188static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
189#endif
190
191static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */
192
193/*
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000194 * Table of name to function pointer of ruby.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195 */
196#define RUBY_PROC FARPROC
197static struct
198{
199 char *name;
200 RUBY_PROC *ptr;
201} ruby_funcname_table[] =
202{
203 {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
204 {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
205 {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
206 {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
207 {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
208 {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
209 {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
210 {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
211 {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
212 {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
213 {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
214 {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
215 {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
216 {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
217 {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
218 {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
219 {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
220 {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
221 {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
222 {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
223 {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
224 {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
225 {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
226 {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
227 {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
228 {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
229 {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
230 {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
231 {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
232 {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
233 {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
234 {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
235 {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
236 {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
237 {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
238 {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
239 {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
240 {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
241 {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
242 {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
243 {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
244 {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
245 {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
246 {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
247 {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
248 {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
249#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
250 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
251#endif
252 {"", NULL},
253};
254
255/*
256 * Free ruby.dll
257 */
258 static void
259end_dynamic_ruby()
260{
261 if (hinstRuby)
262 {
263 FreeLibrary(hinstRuby);
264 hinstRuby = 0;
265 }
266}
267
268/*
269 * Load library and get all pointers.
270 * Parameter 'libname' provides name of DLL.
271 * Return OK or FAIL.
272 */
273 static int
274ruby_runtime_link_init(char *libname, int verbose)
275{
276 int i;
277
278 if (hinstRuby)
279 return OK;
280 hinstRuby = LoadLibrary(libname);
281 if (!hinstRuby)
282 {
283 if (verbose)
284 EMSG2(_(e_loadlib), libname);
285 return FAIL;
286 }
287
288 for (i = 0; ruby_funcname_table[i].ptr; ++i)
289 {
290 if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby,
291 ruby_funcname_table[i].name)))
292 {
293 FreeLibrary(hinstRuby);
294 hinstRuby = 0;
295 if (verbose)
296 EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
297 return FAIL;
298 }
299 }
300 return OK;
301}
302
303/*
304 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
305 * else FALSE.
306 */
307 int
308ruby_enabled(verbose)
309 int verbose;
310{
311 return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
312}
313#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
314
315 void
316ruby_end()
317{
318#ifdef DYNAMIC_RUBY
319 end_dynamic_ruby();
320#endif
321}
322
323void ex_ruby(exarg_T *eap)
324{
325 int state;
326 char *script = NULL;
327
328 script = script_get(eap, eap->arg);
329 if (!eap->skip && ensure_ruby_initialized())
330 {
331 if (script == NULL)
332 rb_eval_string_protect((char *)eap->arg, &state);
333 else
334 rb_eval_string_protect(script, &state);
335 if (state)
336 error_print(state);
337 }
338 vim_free(script);
339}
340
341void ex_rubydo(exarg_T *eap)
342{
343 int state;
344 linenr_T i;
345
346 if (ensure_ruby_initialized())
347 {
348 if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
349 return;
350 for (i = eap->line1; i <= eap->line2; i++) {
351 VALUE line, oldline;
352
353 line = oldline = rb_str_new2(ml_get(i));
354 rb_lastline_set(line);
355 rb_eval_string_protect((char *) eap->arg, &state);
356 if (state) {
357 error_print(state);
358 break;
359 }
360 line = rb_lastline_get();
361 if (!NIL_P(line)) {
362 if (TYPE(line) != T_STRING) {
363 EMSG("E265: $_ must be an instance of String");
364 return;
365 }
366 ml_replace(i, (char_u *) STR2CSTR(line), 1);
367 changed();
368#ifdef SYNTAX_HL
369 syn_changed(i); /* recompute syntax hl. for this line */
370#endif
371 }
372 }
373 check_cursor();
374 update_curbuf(NOT_VALID);
375 }
376}
377
378void ex_rubyfile(exarg_T *eap)
379{
380 int state;
381
382 if (ensure_ruby_initialized())
383 {
384 rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
385 if (state) error_print(state);
386 }
387}
388
389void ruby_buffer_free(buf_T *buf)
390{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000391 if (buf->b_ruby_ref)
392 {
393 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
394 RDATA(buf->b_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 }
396}
397
398void ruby_window_free(win_T *win)
399{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000400 if (win->w_ruby_ref)
401 {
402 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
403 RDATA(win->w_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404 }
405}
406
407static int ensure_ruby_initialized(void)
408{
409 if (!ruby_initialized)
410 {
411#ifdef DYNAMIC_RUBY
412 if (ruby_enabled(TRUE))
413 {
414#endif
415 ruby_init();
416 ruby_init_loadpath();
417 ruby_io_init();
418 ruby_vim_init();
419 ruby_initialized = 1;
420#ifdef DYNAMIC_RUBY
421 }
422 else
423 {
424 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
425 return 0;
426 }
427#endif
428 }
429 return ruby_initialized;
430}
431
432static void error_print(int state)
433{
434#ifndef DYNAMIC_RUBY
435 RUBYEXTERN VALUE ruby_errinfo;
436#endif
437 VALUE eclass;
438 VALUE einfo;
439 char buff[BUFSIZ];
440
441#define TAG_RETURN 0x1
442#define TAG_BREAK 0x2
443#define TAG_NEXT 0x3
444#define TAG_RETRY 0x4
445#define TAG_REDO 0x5
446#define TAG_RAISE 0x6
447#define TAG_THROW 0x7
448#define TAG_FATAL 0x8
449#define TAG_MASK 0xf
450
451 switch (state) {
452 case TAG_RETURN:
453 EMSG("E267: unexpected return");
454 break;
455 case TAG_NEXT:
456 EMSG("E268: unexpected next");
457 break;
458 case TAG_BREAK:
459 EMSG("E269: unexpected break");
460 break;
461 case TAG_REDO:
462 EMSG("E270: unexpected redo");
463 break;
464 case TAG_RETRY:
465 EMSG("E271: retry outside of rescue clause");
466 break;
467 case TAG_RAISE:
468 case TAG_FATAL:
469 eclass = CLASS_OF(ruby_errinfo);
470 einfo = rb_obj_as_string(ruby_errinfo);
471 if (eclass == rb_eRuntimeError && RSTRING(einfo)->len == 0) {
472 EMSG("E272: unhandled exception");
473 }
474 else {
475 VALUE epath;
476 char *p;
477
478 epath = rb_class_path(eclass);
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000479 vim_snprintf(buff, BUFSIZ, "%s: %s",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 RSTRING(epath)->ptr, RSTRING(einfo)->ptr);
481 p = strchr(buff, '\n');
482 if (p) *p = '\0';
483 EMSG(buff);
484 }
485 break;
486 default:
Bram Moolenaar9c13b352005-05-19 20:53:52 +0000487 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488 EMSG(buff);
489 break;
490 }
491}
492
493static VALUE vim_message(VALUE self, VALUE str)
494{
495 char *buff, *p;
496
497 str = rb_obj_as_string(str);
498 buff = ALLOCA_N(char, RSTRING(str)->len);
499 strcpy(buff, RSTRING(str)->ptr);
500 p = strchr(buff, '\n');
501 if (p) *p = '\0';
502 MSG(buff);
503 return Qnil;
504}
505
506static VALUE vim_set_option(VALUE self, VALUE str)
507{
508 do_set((char_u *)STR2CSTR(str), 0);
509 update_screen(NOT_VALID);
510 return Qnil;
511}
512
513static VALUE vim_command(VALUE self, VALUE str)
514{
515 do_cmdline_cmd((char_u *)STR2CSTR(str));
516 return Qnil;
517}
518
519static VALUE vim_evaluate(VALUE self, VALUE str)
520{
521#ifdef FEAT_EVAL
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000522 char_u *value = eval_to_string((char_u *)STR2CSTR(str), NULL, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523
524 if (value)
525 {
526 VALUE val = rb_str_new2(value);
527 vim_free(value);
528 return val;
529 }
530 else
531#endif
532 return Qnil;
533}
534
535static VALUE buffer_new(buf_T *buf)
536{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000537 if (buf->b_ruby_ref)
538 {
539 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000540 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000541 else
542 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000543 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000544 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000545 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
546 return obj;
547 }
548}
549
550static buf_T *get_buf(VALUE obj)
551{
552 buf_T *buf;
553
554 Data_Get_Struct(obj, buf_T, buf);
555 if (buf == NULL)
556 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
557 return buf;
558}
559
560static VALUE buffer_s_current()
561{
562 return buffer_new(curbuf);
563}
564
565static VALUE buffer_s_count()
566{
567 buf_T *b;
568 int n = 0;
569
570 for (b = firstbuf; b; b = b->b_next) n++;
571 return INT2NUM(n);
572}
573
574static VALUE buffer_s_aref(VALUE self, VALUE num)
575{
576 buf_T *b;
577 int n = NUM2INT(num);
578
579 for (b = firstbuf; b; b = b->b_next, --n) {
580 if (n == 0)
581 return buffer_new(b);
582 }
583 return Qnil;
584}
585
586static VALUE buffer_name(VALUE self)
587{
588 buf_T *buf = get_buf(self);
589
590 return buf->b_ffname ? rb_str_new2(buf->b_ffname) : Qnil;
591}
592
593static VALUE buffer_number(VALUE self)
594{
595 buf_T *buf = get_buf(self);
596
597 return INT2NUM(buf->b_fnum);
598}
599
600static VALUE buffer_count(VALUE self)
601{
602 buf_T *buf = get_buf(self);
603
604 return INT2NUM(buf->b_ml.ml_line_count);
605}
606
607static VALUE buffer_aref(VALUE self, VALUE num)
608{
609 buf_T *buf = get_buf(self);
610 long n = NUM2LONG(num);
611
612 if (n > 0 && n <= buf->b_ml.ml_line_count) {
613 char *line = ml_get_buf(buf, n, FALSE);
614 return line ? rb_str_new2(line) : Qnil;
615 }
616 else {
617 rb_raise(rb_eIndexError, "index %d out of buffer", n);
618 return Qnil; /* For stop warning */
619 }
620}
621
622static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
623{
624 buf_T *buf = get_buf(self);
625 buf_T *savebuf = curbuf;
626 char *line = STR2CSTR(str);
627 long n = NUM2LONG(num);
628
629 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
630 curbuf = buf;
631 if (u_savesub(n) == OK) {
632 ml_replace(n, (char_u *) line, TRUE);
633 changed();
634#ifdef SYNTAX_HL
635 syn_changed(n); /* recompute syntax hl. for this line */
636#endif
637 }
638 curbuf = savebuf;
639 update_curbuf(NOT_VALID);
640 }
641 else {
642 rb_raise(rb_eIndexError, "index %d out of buffer", n);
643 return Qnil; /* For stop warning */
644 }
645 return str;
646}
647
648static VALUE buffer_delete(VALUE self, VALUE num)
649{
650 buf_T *buf = get_buf(self);
651 buf_T *savebuf = curbuf;
652 long n = NUM2LONG(num);
653
654 if (n > 0 && n <= buf->b_ml.ml_line_count) {
655 curbuf = buf;
656 if (u_savedel(n, 1) == OK) {
657 mark_adjust(n, n, MAXLNUM, -1);
658 ml_delete(n, 0);
659 changed();
660 }
661 curbuf = savebuf;
662 update_curbuf(NOT_VALID);
663 }
664 else {
665 rb_raise(rb_eIndexError, "index %d out of buffer", n);
666 }
667 return Qnil;
668}
669
670static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
671{
672 buf_T *buf = get_buf(self);
673 buf_T *savebuf = curbuf;
674 char *line = STR2CSTR(str);
675 long n = NUM2LONG(num);
676
677 if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
678 curbuf = buf;
679 if (u_inssub(n + 1) == OK) {
680 mark_adjust(n + 1, MAXLNUM, 1L, 0L);
681 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
682 changed();
683 }
684 curbuf = savebuf;
685 update_curbuf(NOT_VALID);
686 }
687 else {
688 rb_raise(rb_eIndexError, "index %d out of buffer", n);
689 }
690 return str;
691}
692
693static VALUE window_new(win_T *win)
694{
Bram Moolenaare344bea2005-09-01 20:46:49 +0000695 if (win->w_ruby_ref)
696 {
697 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698 }
Bram Moolenaare344bea2005-09-01 20:46:49 +0000699 else
700 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaare344bea2005-09-01 20:46:49 +0000702 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
704 return obj;
705 }
706}
707
708static win_T *get_win(VALUE obj)
709{
710 win_T *win;
711
712 Data_Get_Struct(obj, win_T, win);
713 if (win == NULL)
714 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
715 return win;
716}
717
718static VALUE window_s_current()
719{
720 return window_new(curwin);
721}
722
723static VALUE window_s_count()
724{
725#ifdef FEAT_WINDOWS
726 win_T *w;
727 int n = 0;
728
Bram Moolenaarf740b292006-02-16 22:11:02 +0000729 for (w = firstwin; w != NULL; w = w->w_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730 n++;
731 return INT2NUM(n);
732#else
733 return INT2NUM(1);
734#endif
735}
736
737static VALUE window_s_aref(VALUE self, VALUE num)
738{
739 win_T *w;
740 int n = NUM2INT(num);
741
742#ifndef FEAT_WINDOWS
743 w = curwin;
744#else
745 for (w = firstwin; w != NULL; w = w->w_next, --n)
746#endif
747 if (n == 0)
748 return window_new(w);
749 return Qnil;
750}
751
752static VALUE window_buffer(VALUE self)
753{
754 win_T *win = get_win(self);
755
756 return buffer_new(win->w_buffer);
757}
758
759static VALUE window_height(VALUE self)
760{
761 win_T *win = get_win(self);
762
763 return INT2NUM(win->w_height);
764}
765
766static VALUE window_set_height(VALUE self, VALUE height)
767{
768 win_T *win = get_win(self);
769 win_T *savewin = curwin;
770
771 curwin = win;
772 win_setheight(NUM2INT(height));
773 curwin = savewin;
774 return height;
775}
776
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000777static VALUE window_width(VALUE self)
778{
779 win_T *win = get_win(self);
780
781 return INT2NUM(win->w_width);
782}
783
784static VALUE window_set_width(VALUE self, VALUE width)
785{
786 win_T *win = get_win(self);
787 win_T *savewin = curwin;
788
789 curwin = win;
790 win_setwidth(NUM2INT(width));
791 curwin = savewin;
792 return width;
793}
794
Bram Moolenaar071d4272004-06-13 20:20:40 +0000795static VALUE window_cursor(VALUE self)
796{
797 win_T *win = get_win(self);
798
799 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
800}
801
802static VALUE window_set_cursor(VALUE self, VALUE pos)
803{
804 VALUE lnum, col;
805 win_T *win = get_win(self);
806
807 Check_Type(pos, T_ARRAY);
808 if (RARRAY(pos)->len != 2)
809 rb_raise(rb_eArgError, "array length must be 2");
810 lnum = RARRAY(pos)->ptr[0];
811 col = RARRAY(pos)->ptr[1];
812 win->w_cursor.lnum = NUM2LONG(lnum);
813 win->w_cursor.col = NUM2UINT(col);
814 check_cursor(); /* put cursor on an existing line */
815 update_screen(NOT_VALID);
816 return Qnil;
817}
818
819static VALUE f_p(int argc, VALUE *argv, VALUE self)
820{
821 int i;
822 VALUE str = rb_str_new("", 0);
823
824 for (i = 0; i < argc; i++) {
825 if (i > 0) rb_str_cat(str, ", ", 2);
826 rb_str_concat(str, rb_inspect(argv[i]));
827 }
828 MSG(RSTRING(str)->ptr);
829 return Qnil;
830}
831
832static void ruby_io_init(void)
833{
834#ifndef DYNAMIC_RUBY
835 RUBYEXTERN VALUE rb_stdout;
836#endif
837
838 rb_stdout = rb_obj_alloc(rb_cObject);
839 rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
840 rb_define_global_function("p", f_p, -1);
841}
842
843static void ruby_vim_init(void)
844{
845 objtbl = rb_hash_new();
846 rb_global_variable(&objtbl);
847
848 mVIM = rb_define_module("VIM");
849 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
850 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
851 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
852 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
853 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
854 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
855 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
856 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
857 rb_define_module_function(mVIM, "message", vim_message, 1);
858 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
859 rb_define_module_function(mVIM, "command", vim_command, 1);
860 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
861
862 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
863 rb_eStandardError);
864 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
865 rb_eStandardError);
866
867 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
868 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
869 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
870 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
871 rb_define_method(cBuffer, "name", buffer_name, 0);
872 rb_define_method(cBuffer, "number", buffer_number, 0);
873 rb_define_method(cBuffer, "count", buffer_count, 0);
874 rb_define_method(cBuffer, "length", buffer_count, 0);
875 rb_define_method(cBuffer, "[]", buffer_aref, 1);
876 rb_define_method(cBuffer, "[]=", buffer_aset, 2);
877 rb_define_method(cBuffer, "delete", buffer_delete, 1);
878 rb_define_method(cBuffer, "append", buffer_append, 2);
879
880 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
881 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
882 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
883 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
884 rb_define_method(cVimWindow, "buffer", window_buffer, 0);
885 rb_define_method(cVimWindow, "height", window_height, 0);
886 rb_define_method(cVimWindow, "height=", window_set_height, 1);
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000887 rb_define_method(cVimWindow, "width", window_width, 0);
888 rb_define_method(cVimWindow, "width=", window_set_width, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 rb_define_method(cVimWindow, "cursor", window_cursor, 0);
890 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
891
892 rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
893 rb_define_virtual_variable("$curwin", window_s_current, 0);
894}