1 /* 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 70 static int ruby_initialized = 0; 71 static VALUE objtbl; 72 73 static VALUE mVIM; 74 static VALUE cBuffer; 75 static VALUE cVimWindow; 76 static VALUE eDeletedBufferError; 77 static VALUE eDeletedWindowError; 78 79 static int ensure_ruby_initialized(void); 80 static void error_print(int); 81 static void ruby_io_init(void); 82 static 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 */ 140 static VALUE (*dll_rb_assoc_new) (VALUE, VALUE); 141 static VALUE *dll_rb_cFalseClass; 142 static VALUE *dll_rb_cFixnum; 143 static VALUE *dll_rb_cNilClass; 144 static VALUE *dll_rb_cObject; 145 static VALUE *dll_rb_cSymbol; 146 static VALUE *dll_rb_cTrueClass; 147 static void (*dll_rb_check_type) (VALUE,int); 148 static VALUE (*dll_rb_class_path) (VALUE); 149 static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC); 150 static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE); 151 static void (*dll_rb_define_const) (VALUE,const char*,VALUE); 152 static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int); 153 static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int); 154 static VALUE (*dll_rb_define_module) (const char*); 155 static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int); 156 static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int); 157 static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)()); 158 static VALUE *dll_rb_stdout; 159 static VALUE *dll_rb_eArgError; 160 static VALUE *dll_rb_eIndexError; 161 static VALUE *dll_rb_eRuntimeError; 162 static VALUE *dll_rb_eStandardError; 163 static VALUE (*dll_rb_eval_string_protect) (const char*, int*); 164 static void (*dll_rb_global_variable) (VALUE*); 165 static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE); 166 static VALUE (*dll_rb_hash_new) (void); 167 static VALUE (*dll_rb_inspect) (VALUE); 168 static VALUE (*dll_rb_int2inum) (long); 169 static VALUE (*dll_rb_int2inum) (long); 170 static VALUE (*dll_rb_lastline_get) (void); 171 static void (*dll_rb_lastline_set) (VALUE); 172 static void (*dll_rb_load_protect) (VALUE, int, int*); 173 static long (*dll_rb_num2long) (VALUE); 174 static unsigned long (*dll_rb_num2ulong) (VALUE); 175 static VALUE (*dll_rb_obj_alloc) (VALUE); 176 static VALUE (*dll_rb_obj_as_string) (VALUE); 177 static VALUE (*dll_rb_obj_id) (VALUE); 178 static void (*dll_rb_raise) (VALUE, const char*, ...); 179 static char *(*dll_rb_str2cstr) (VALUE,int*); 180 static VALUE (*dll_rb_str_cat) (VALUE, const char*, long); 181 static VALUE (*dll_rb_str_concat) (VALUE, VALUE); 182 static VALUE (*dll_rb_str_new) (const char*, long); 183 static VALUE (*dll_rb_str_new2) (const char*); 184 static VALUE *dll_ruby_errinfo; 185 static void (*dll_ruby_init) (void); 186 static void (*dll_ruby_init_loadpath) (void); 187 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 188 static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...); 189 #endif 190 191 static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */ 192 193 /* 194 * Table of name to function pointer of python. 195 */ 196 #define RUBY_PROC FARPROC 197 static 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 259 end_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 274 ruby_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 308 ruby_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 316 ruby_end() 317 { 318 #ifdef DYNAMIC_RUBY 319 end_dynamic_ruby(); 320 #endif 321 } 322 323 void 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 341 void 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 378 void 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 389 void ruby_buffer_free(buf_T *buf) 390 { 391 if (buf->ruby_ref) { 392 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->ruby_ref), Qnil); 393 RDATA(buf->ruby_ref)->data = NULL; 394 } 395 } 396 397 void ruby_window_free(win_T *win) 398 { 399 if (win->ruby_ref) { 400 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->ruby_ref), Qnil); 401 RDATA(win->ruby_ref)->data = NULL; 402 } 403 } 404 405 static int ensure_ruby_initialized(void) 406 { 407 if (!ruby_initialized) 408 { 409 #ifdef DYNAMIC_RUBY 410 if (ruby_enabled(TRUE)) 411 { 412 #endif 413 ruby_init(); 414 ruby_init_loadpath(); 415 ruby_io_init(); 416 ruby_vim_init(); 417 ruby_initialized = 1; 418 #ifdef DYNAMIC_RUBY 419 } 420 else 421 { 422 EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded.")); 423 return 0; 424 } 425 #endif 426 } 427 return ruby_initialized; 428 } 429 430 static void error_print(int state) 431 { 432 #ifndef DYNAMIC_RUBY 433 RUBYEXTERN VALUE ruby_errinfo; 434 #endif 435 VALUE eclass; 436 VALUE einfo; 437 char buff[BUFSIZ]; 438 439 #define TAG_RETURN 0x1 440 #define TAG_BREAK 0x2 441 #define TAG_NEXT 0x3 442 #define TAG_RETRY 0x4 443 #define TAG_REDO 0x5 444 #define TAG_RAISE 0x6 445 #define TAG_THROW 0x7 446 #define TAG_FATAL 0x8 447 #define TAG_MASK 0xf 448 449 switch (state) { 450 case TAG_RETURN: 451 EMSG("E267: unexpected return"); 452 break; 453 case TAG_NEXT: 454 EMSG("E268: unexpected next"); 455 break; 456 case TAG_BREAK: 457 EMSG("E269: unexpected break"); 458 break; 459 case TAG_REDO: 460 EMSG("E270: unexpected redo"); 461 break; 462 case TAG_RETRY: 463 EMSG("E271: retry outside of rescue clause"); 464 break; 465 case TAG_RAISE: 466 case TAG_FATAL: 467 eclass = CLASS_OF(ruby_errinfo); 468 einfo = rb_obj_as_string(ruby_errinfo); 469 if (eclass == rb_eRuntimeError && RSTRING(einfo)->len == 0) { 470 EMSG("E272: unhandled exception"); 471 } 472 else { 473 VALUE epath; 474 char *p; 475 476 epath = rb_class_path(eclass); 477 vim_snprintf(buff, BUFSIZ, "%s: %s", 478 RSTRING(epath)->ptr, RSTRING(einfo)->ptr); 479 p = strchr(buff, '\n'); 480 if (p) *p = '\0'; 481 EMSG(buff); 482 } 483 break; 484 default: 485 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state); 486 EMSG(buff); 487 break; 488 } 489 } 490 491 static VALUE vim_message(VALUE self, VALUE str) 492 { 493 char *buff, *p; 494 495 str = rb_obj_as_string(str); 496 buff = ALLOCA_N(char, RSTRING(str)->len); 497 strcpy(buff, RSTRING(str)->ptr); 498 p = strchr(buff, '\n'); 499 if (p) *p = '\0'; 500 MSG(buff); 501 return Qnil; 502 } 503 504 static VALUE vim_set_option(VALUE self, VALUE str) 505 { 506 do_set((char_u *)STR2CSTR(str), 0); 507 update_screen(NOT_VALID); 508 return Qnil; 509 } 510 511 static VALUE vim_command(VALUE self, VALUE str) 512 { 513 do_cmdline_cmd((char_u *)STR2CSTR(str)); 514 return Qnil; 515 } 516 517 static VALUE vim_evaluate(VALUE self, VALUE str) 518 { 519 #ifdef FEAT_EVAL 520 char_u *value = eval_to_string((char_u *)STR2CSTR(str), NULL); 521 522 if (value) 523 { 524 VALUE val = rb_str_new2(value); 525 vim_free(value); 526 return val; 527 } 528 else 529 #endif 530 return Qnil; 531 } 532 533 static VALUE buffer_new(buf_T *buf) 534 { 535 if (buf->ruby_ref) { 536 return (VALUE) buf->ruby_ref; 537 } 538 else { 539 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf); 540 buf->ruby_ref = (void *) obj; 541 rb_hash_aset(objtbl, rb_obj_id(obj), obj); 542 return obj; 543 } 544 } 545 546 static buf_T *get_buf(VALUE obj) 547 { 548 buf_T *buf; 549 550 Data_Get_Struct(obj, buf_T, buf); 551 if (buf == NULL) 552 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer"); 553 return buf; 554 } 555 556 static VALUE buffer_s_current() 557 { 558 return buffer_new(curbuf); 559 } 560 561 static VALUE buffer_s_count() 562 { 563 buf_T *b; 564 int n = 0; 565 566 for (b = firstbuf; b; b = b->b_next) n++; 567 return INT2NUM(n); 568 } 569 570 static VALUE buffer_s_aref(VALUE self, VALUE num) 571 { 572 buf_T *b; 573 int n = NUM2INT(num); 574 575 for (b = firstbuf; b; b = b->b_next, --n) { 576 if (n == 0) 577 return buffer_new(b); 578 } 579 return Qnil; 580 } 581 582 static VALUE buffer_name(VALUE self) 583 { 584 buf_T *buf = get_buf(self); 585 586 return buf->b_ffname ? rb_str_new2(buf->b_ffname) : Qnil; 587 } 588 589 static VALUE buffer_number(VALUE self) 590 { 591 buf_T *buf = get_buf(self); 592 593 return INT2NUM(buf->b_fnum); 594 } 595 596 static VALUE buffer_count(VALUE self) 597 { 598 buf_T *buf = get_buf(self); 599 600 return INT2NUM(buf->b_ml.ml_line_count); 601 } 602 603 static VALUE buffer_aref(VALUE self, VALUE num) 604 { 605 buf_T *buf = get_buf(self); 606 long n = NUM2LONG(num); 607 608 if (n > 0 && n <= buf->b_ml.ml_line_count) { 609 char *line = ml_get_buf(buf, n, FALSE); 610 return line ? rb_str_new2(line) : Qnil; 611 } 612 else { 613 rb_raise(rb_eIndexError, "index %d out of buffer", n); 614 return Qnil; /* For stop warning */ 615 } 616 } 617 618 static VALUE buffer_aset(VALUE self, VALUE num, VALUE str) 619 { 620 buf_T *buf = get_buf(self); 621 buf_T *savebuf = curbuf; 622 char *line = STR2CSTR(str); 623 long n = NUM2LONG(num); 624 625 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) { 626 curbuf = buf; 627 if (u_savesub(n) == OK) { 628 ml_replace(n, (char_u *) line, TRUE); 629 changed(); 630 #ifdef SYNTAX_HL 631 syn_changed(n); /* recompute syntax hl. for this line */ 632 #endif 633 } 634 curbuf = savebuf; 635 update_curbuf(NOT_VALID); 636 } 637 else { 638 rb_raise(rb_eIndexError, "index %d out of buffer", n); 639 return Qnil; /* For stop warning */ 640 } 641 return str; 642 } 643 644 static VALUE buffer_delete(VALUE self, VALUE num) 645 { 646 buf_T *buf = get_buf(self); 647 buf_T *savebuf = curbuf; 648 long n = NUM2LONG(num); 649 650 if (n > 0 && n <= buf->b_ml.ml_line_count) { 651 curbuf = buf; 652 if (u_savedel(n, 1) == OK) { 653 mark_adjust(n, n, MAXLNUM, -1); 654 ml_delete(n, 0); 655 changed(); 656 } 657 curbuf = savebuf; 658 update_curbuf(NOT_VALID); 659 } 660 else { 661 rb_raise(rb_eIndexError, "index %d out of buffer", n); 662 } 663 return Qnil; 664 } 665 666 static VALUE buffer_append(VALUE self, VALUE num, VALUE str) 667 { 668 buf_T *buf = get_buf(self); 669 buf_T *savebuf = curbuf; 670 char *line = STR2CSTR(str); 671 long n = NUM2LONG(num); 672 673 if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) { 674 curbuf = buf; 675 if (u_inssub(n + 1) == OK) { 676 mark_adjust(n + 1, MAXLNUM, 1L, 0L); 677 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE); 678 changed(); 679 } 680 curbuf = savebuf; 681 update_curbuf(NOT_VALID); 682 } 683 else { 684 rb_raise(rb_eIndexError, "index %d out of buffer", n); 685 } 686 return str; 687 } 688 689 static VALUE window_new(win_T *win) 690 { 691 if (win->ruby_ref) { 692 return (VALUE) win->ruby_ref; 693 } 694 else { 695 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win); 696 win->ruby_ref = (void *) obj; 697 rb_hash_aset(objtbl, rb_obj_id(obj), obj); 698 return obj; 699 } 700 } 701 702 static win_T *get_win(VALUE obj) 703 { 704 win_T *win; 705 706 Data_Get_Struct(obj, win_T, win); 707 if (win == NULL) 708 rb_raise(eDeletedWindowError, "attempt to refer to deleted window"); 709 return win; 710 } 711 712 static VALUE window_s_current() 713 { 714 return window_new(curwin); 715 } 716 717 static VALUE window_s_count() 718 { 719 #ifdef FEAT_WINDOWS 720 win_T *w; 721 int n = 0; 722 723 for (w = firstwin; w; w = w->w_next) 724 n++; 725 return INT2NUM(n); 726 #else 727 return INT2NUM(1); 728 #endif 729 } 730 731 static VALUE window_s_aref(VALUE self, VALUE num) 732 { 733 win_T *w; 734 int n = NUM2INT(num); 735 736 #ifndef FEAT_WINDOWS 737 w = curwin; 738 #else 739 for (w = firstwin; w != NULL; w = w->w_next, --n) 740 #endif 741 if (n == 0) 742 return window_new(w); 743 return Qnil; 744 } 745 746 static VALUE window_buffer(VALUE self) 747 { 748 win_T *win = get_win(self); 749 750 return buffer_new(win->w_buffer); 751 } 752 753 static VALUE window_height(VALUE self) 754 { 755 win_T *win = get_win(self); 756 757 return INT2NUM(win->w_height); 758 } 759 760 static VALUE window_set_height(VALUE self, VALUE height) 761 { 762 win_T *win = get_win(self); 763 win_T *savewin = curwin; 764 765 curwin = win; 766 win_setheight(NUM2INT(height)); 767 curwin = savewin; 768 return height; 769 } 770 771 static VALUE window_cursor(VALUE self) 772 { 773 win_T *win = get_win(self); 774 775 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col)); 776 } 777 778 static VALUE window_set_cursor(VALUE self, VALUE pos) 779 { 780 VALUE lnum, col; 781 win_T *win = get_win(self); 782 783 Check_Type(pos, T_ARRAY); 784 if (RARRAY(pos)->len != 2) 785 rb_raise(rb_eArgError, "array length must be 2"); 786 lnum = RARRAY(pos)->ptr[0]; 787 col = RARRAY(pos)->ptr[1]; 788 win->w_cursor.lnum = NUM2LONG(lnum); 789 win->w_cursor.col = NUM2UINT(col); 790 check_cursor(); /* put cursor on an existing line */ 791 update_screen(NOT_VALID); 792 return Qnil; 793 } 794 795 static VALUE f_p(int argc, VALUE *argv, VALUE self) 796 { 797 int i; 798 VALUE str = rb_str_new("", 0); 799 800 for (i = 0; i < argc; i++) { 801 if (i > 0) rb_str_cat(str, ", ", 2); 802 rb_str_concat(str, rb_inspect(argv[i])); 803 } 804 MSG(RSTRING(str)->ptr); 805 return Qnil; 806 } 807 808 static void ruby_io_init(void) 809 { 810 #ifndef DYNAMIC_RUBY 811 RUBYEXTERN VALUE rb_stdout; 812 #endif 813 814 rb_stdout = rb_obj_alloc(rb_cObject); 815 rb_define_singleton_method(rb_stdout, "write", vim_message, 1); 816 rb_define_global_function("p", f_p, -1); 817 } 818 819 static void ruby_vim_init(void) 820 { 821 objtbl = rb_hash_new(); 822 rb_global_variable(&objtbl); 823 824 mVIM = rb_define_module("VIM"); 825 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR)); 826 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR)); 827 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD)); 828 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL)); 829 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT)); 830 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM)); 831 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG)); 832 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE)); 833 rb_define_module_function(mVIM, "message", vim_message, 1); 834 rb_define_module_function(mVIM, "set_option", vim_set_option, 1); 835 rb_define_module_function(mVIM, "command", vim_command, 1); 836 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1); 837 838 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError", 839 rb_eStandardError); 840 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError", 841 rb_eStandardError); 842 843 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject); 844 rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0); 845 rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0); 846 rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1); 847 rb_define_method(cBuffer, "name", buffer_name, 0); 848 rb_define_method(cBuffer, "number", buffer_number, 0); 849 rb_define_method(cBuffer, "count", buffer_count, 0); 850 rb_define_method(cBuffer, "length", buffer_count, 0); 851 rb_define_method(cBuffer, "[]", buffer_aref, 1); 852 rb_define_method(cBuffer, "[]=", buffer_aset, 2); 853 rb_define_method(cBuffer, "delete", buffer_delete, 1); 854 rb_define_method(cBuffer, "append", buffer_append, 2); 855 856 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject); 857 rb_define_singleton_method(cVimWindow, "current", window_s_current, 0); 858 rb_define_singleton_method(cVimWindow, "count", window_s_count, 0); 859 rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1); 860 rb_define_method(cVimWindow, "buffer", window_buffer, 0); 861 rb_define_method(cVimWindow, "height", window_height, 0); 862 rb_define_method(cVimWindow, "height=", window_set_height, 1); 863 rb_define_method(cVimWindow, "cursor", window_cursor, 0); 864 rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1); 865 866 rb_define_virtual_variable("$curbuf", buffer_s_current, 0); 867 rb_define_virtual_variable("$curwin", window_s_current, 0); 868 } 869