home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / if_ruby.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-04-19  |  22.0 KB  |  843 lines

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