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