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 ruby. 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->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; 395 } 396 } 397 398 void ruby_window_free(win_T *win) 399 { 400 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; 404 } 405 } 406 407 static 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 432 static 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); 479 vim_snprintf(buff, BUFSIZ, "%s: %s", 480 RSTRING(epath)->ptr, RSTRING(einfo)->ptr); 481 p = strchr(buff, '\n'); 482 if (p) *p = '\0'; 483 EMSG(buff); 484 } 485 break; 486 default: 487 vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state); 488 EMSG(buff); 489 break; 490 } 491 } 492 493 static 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 506 static 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 513 static VALUE vim_command(VALUE self, VALUE str) 514 { 515 do_cmdline_cmd((char_u *)STR2CSTR(str)); 516 return Qnil; 517 } 518 519 static VALUE vim_evaluate(VALUE self, VALUE str) 520 { 521 #ifdef FEAT_EVAL 522 char_u *value = eval_to_string((char_u *)STR2CSTR(str), NULL); 523 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 535 static VALUE buffer_new(buf_T *buf) 536 { 537 if (buf->b_ruby_ref) 538 { 539 return (VALUE) buf->b_ruby_ref; 540 } 541 else 542 { 543 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf); 544 buf->b_ruby_ref = (void *) obj; 545 rb_hash_aset(objtbl, rb_obj_id(obj), obj); 546 return obj; 547 } 548 } 549 550 static 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 560 static VALUE buffer_s_current() 561 { 562 return buffer_new(curbuf); 563 } 564 565 static 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 574 static 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 586 static 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 593 static VALUE buffer_number(VALUE self) 594 { 595 buf_T *buf = get_buf(self); 596 597 return INT2NUM(buf->b_fnum); 598 } 599 600 static 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 607 static 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 622 static 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 648 static 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 670 static 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 693 static VALUE window_new(win_T *win) 694 { 695 if (win->w_ruby_ref) 696 { 697 return (VALUE) win->w_ruby_ref; 698 } 699 else 700 { 701 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win); 702 win->w_ruby_ref = (void *) obj; 703 rb_hash_aset(objtbl, rb_obj_id(obj), obj); 704 return obj; 705 } 706 } 707 708 static 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 718 static VALUE window_s_current() 719 { 720 return window_new(curwin); 721 } 722 723 static VALUE window_s_count() 724 { 725 #ifdef FEAT_WINDOWS 726 win_T *w; 727 int n = 0; 728 729 for (w = firstwin; w; w = w->w_next) 730 n++; 731 return INT2NUM(n); 732 #else 733 return INT2NUM(1); 734 #endif 735 } 736 737 static 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 752 static VALUE window_buffer(VALUE self) 753 { 754 win_T *win = get_win(self); 755 756 return buffer_new(win->w_buffer); 757 } 758 759 static VALUE window_height(VALUE self) 760 { 761 win_T *win = get_win(self); 762 763 return INT2NUM(win->w_height); 764 } 765 766 static 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 777 static VALUE window_width(VALUE self) 778 { 779 win_T *win = get_win(self); 780 781 return INT2NUM(win->w_width); 782 } 783 784 static 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 795 static 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 802 static 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 819 static 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 832 static 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 843 static 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); 887 rb_define_method(cVimWindow, "width", window_width, 0); 888 rb_define_method(cVimWindow, "width=", window_set_width, 1); 889 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 } 895