form_wrap.c in ncursesw-1.2.4.3 vs form_wrap.c in ncursesw-1.4.0.0
- old
+ new
@@ -1,14 +1,15 @@
/*
* This is a curses forms wrapper as part of ncurses-ruby
* Contributed by Simon Kaczor <skaczor@cox.net>
* Prognosoft Inc. <http://www.prognosoft.biz>
* Copyright 2004
- *
+ *
* Changes:
* (C) 2004 Tobias Peters
* (C) 2005 2009 Tobias Herzke
+ * (C) 2013 Gaute Hope <eg@gaute.vetsj.com>
*
* This module is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
@@ -20,25 +21,29 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this module; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
+ * Changes
+ * (C) 2011 Tobias Herzke
*/
-#ifdef HAVE_FORM_H
+#if defined(HAVE_FORM_H) || defined(HAVE_NCURSESW_FORM_H)
+# include <wchar.h>
+
#include "form_wrap.h"
#include "ncurses_wrap.h"
#include "compat.h"
VALUE mForm;
VALUE cFIELD;
VALUE cFIELDTYPE;
VALUE cFORM;
-void init_err_codes()
+void init_err_codes()
{
/* The routine succeeded. */
FORM_DEF_CONST(E_OK);
/* The field is already connected to a form. */
FORM_DEF_CONST(E_CONNECTED);
@@ -358,18 +363,18 @@
}
return hash;
}
/*
- * Returns an existing Ruby Proc for a given owning "object" and hook type.
+ * Returns an existing Ruby Proc for a given owning "object" and hook type.
* Qnil will be returned if no Proc was associated with the owner
*/
static VALUE get_proc(void* owner, int hook) {
if (owner == 0) return Qnil;
{
VALUE owner_adress = INT2NUM((long)(owner));
- VALUE proc_hash = get_proc_hash(hook);
+ VALUE proc_hash = get_proc_hash(hook);
VALUE proc = rb_hash_aref(proc_hash, owner_adress);
return proc;
}
}
/*
@@ -396,16 +401,16 @@
static VALUE rbncurs_m_new_form(VALUE dummy, VALUE rb_field_array)
{
long n = rbncurs_array_length(rb_field_array);
/* Will ncurses free this array? If not, must do it after calling free_form(). */
FIELD** fields = ALLOC_N(FIELD*, (n+1));
- long i;
+ long i;
for (i=0; i<n; i++){
- fields[i] = get_field(rb_ary_entry(rb_field_array, i));
+ fields[i] = get_field(rb_ary_entry(rb_field_array, i));
}
fields[n] = NULL;
- return wrap_form(new_form(fields));
+ return wrap_form(new_form(fields));
}
static VALUE rbncurs_c_free_form(VALUE rb_form) {
VALUE forms_hash = rb_iv_get(mForm, "@forms_hash");
FORM* form = get_form(rb_form);
@@ -442,16 +447,26 @@
return INT2NUM(form_driver(form, NUM2INT(c)));
}
static VALUE rbncurs_m_form_driver(VALUE dummy, VALUE rb_form, VALUE c)
{ return rbncurs_c_form_driver(rb_form, c); }
+# ifdef HAVE_FORM_DRIVER_W
+/* Form driver W */
+static VALUE rbncurs_c_form_driver_w(VALUE rb_form, VALUE type, VALUE c) {
+ FORM* form = get_form(rb_form);
+ return INT2NUM(form_driver_w(form, NUM2INT(type), NUM2INT(c)));
+}
+static VALUE rbncurs_m_form_driver_w(VALUE dummy, VALUE rb_form, VALUE type, VALUE c)
+{ return rbncurs_c_form_driver_w(rb_form, type, c); }
+# endif
+
/*
* form_page(3x)
*/
static VALUE rbncurs_c_set_current_field(VALUE rb_form, VALUE rb_field) {
FORM* form = get_form(rb_form);
- FIELD* field = get_field(rb_field);
+ FIELD* field = get_field(rb_field);
return INT2NUM(set_current_field(form, field));
}
static VALUE rbncurs_m_set_current_field(VALUE dummy, VALUE rb_form, VALUE rb_field)
{ return rbncurs_c_set_current_field(rb_form, rb_field); }
@@ -536,16 +551,16 @@
rb_iv_set(rb_field, "@destroyed", Qtrue);
return INT2NUM(free_field(field));
}
static VALUE rbncurs_m_free_field(VALUE dummy, VALUE rb_field)
{ return rbncurs_c_free_field(rb_field); }
-
+
/*
* form_field_info(3x)
*/
-static VALUE rbncurs_c_field_info(VALUE rb_field, VALUE rows, VALUE cols,
+static VALUE rbncurs_c_field_info(VALUE rb_field, VALUE rows, VALUE cols,
VALUE frow, VALUE fcol, VALUE nrow, VALUE nbuf) {
if (rb_obj_is_instance_of(rows, rb_cArray) != Qtrue
|| rb_obj_is_instance_of(cols, rb_cArray) != Qtrue
|| rb_obj_is_instance_of(frow, rb_cArray) != Qtrue
|| rb_obj_is_instance_of(fcol, rb_cArray) != Qtrue
@@ -556,46 +571,46 @@
return Qnil;
}
else {
FIELD* field = get_field(rb_field);
int vals[6] = {0,0,0,0,0,0};
-
+
int result = field_info(field, &vals[0],&vals[1],&vals[2],&vals[3],&vals[4],&vals[5]);
rb_ary_push(rows, INT2NUM(vals[0]));
rb_ary_push(cols, INT2NUM(vals[1]));
rb_ary_push(frow, INT2NUM(vals[2]));
rb_ary_push(fcol, INT2NUM(vals[3]));
rb_ary_push(nrow, INT2NUM(vals[4]));
rb_ary_push(nbuf, INT2NUM(vals[5]));
return INT2NUM(result);
}
}
-static VALUE rbncurs_m_field_info(VALUE dummy, VALUE rb_field, VALUE rows, VALUE cols,
+static VALUE rbncurs_m_field_info(VALUE dummy, VALUE rb_field, VALUE rows, VALUE cols,
VALUE frow, VALUE fcol, VALUE nrow, VALUE nbuf)
{ return rbncurs_c_field_info(rb_field, rows, cols, frow, fcol, nrow, nbuf); }
-static VALUE rbncurs_c_dynamic_field_info(VALUE rb_field, VALUE rows, VALUE cols,
+static VALUE rbncurs_c_dynamic_field_info(VALUE rb_field, VALUE rows, VALUE cols,
VALUE max) {
if (rb_obj_is_instance_of(rows, rb_cArray) != Qtrue
|| rb_obj_is_instance_of(cols, rb_cArray) != Qtrue
- || rb_obj_is_instance_of(max, rb_cArray) != Qtrue) {
+ || rb_obj_is_instance_of(max, rb_cArray) != Qtrue) {
rb_raise(rb_eArgError,
"rows, cols and max arguments must be empty Arrays");
return Qnil;
}
else {
FIELD* field = get_field(rb_field);
int vals[3] = {0,0,0};
-
+
int result = dynamic_field_info(field, &vals[0],&vals[1],&vals[2]);
rb_ary_push(rows, INT2NUM(vals[0]));
rb_ary_push(cols, INT2NUM(vals[1]));
rb_ary_push(max, INT2NUM(vals[2]));
return INT2NUM(result);
}
}
-static VALUE rbncurs_m_dynamic_field_info(VALUE dummy, VALUE rb_field, VALUE rows, VALUE cols,
+static VALUE rbncurs_m_dynamic_field_info(VALUE dummy, VALUE rb_field, VALUE rows, VALUE cols,
VALUE max)
{ return rbncurs_c_dynamic_field_info(rb_field, rows, cols, max); }
/*
* field_validation
*/
@@ -604,76 +619,76 @@
FIELD* field = get_field(rb_field);
FIELDTYPE* ftype = NULL;
rb_scan_args(argc, argv, "13", &rb_fieldtype, &arg3, &arg4, &arg5);
ftype = get_fieldtype(rb_fieldtype);
-
+
if (ftype == TYPE_ALNUM ||
ftype == TYPE_ALPHA) {
if (argc != 2)
rb_raise(rb_eArgError, "TYPE_ALNUM and TYPE_ALPHA require one additional argument");
- return INT2NUM(set_field_type(field, ftype,
+ return INT2NUM(set_field_type(field, ftype,
NUM2INT(arg3)));
}
if (ftype == TYPE_ENUM) {
if (argc != 4) {
rb_raise(rb_eArgError, "TYPE_ENUM requires three additional arguments");
}
else {
- int n = rbncurs_array_length(arg3);
+ int n = (int) rbncurs_array_length(arg3);
/* Will ncurses free this array of strings in free_field()? */
char** list = ALLOC_N(char*, n+1);
int i;
for (i = 0; i < n; i++) {
list[i] = STR2CSTR(rb_ary_entry(arg3, (long)i));
}
list[n] = NULL;
- return INT2NUM(set_field_type(field, ftype,
+ return INT2NUM(set_field_type(field, ftype,
list,
RTEST(arg4),
RTEST(arg5)));
}
}
else if (ftype == TYPE_INTEGER) {
if (argc != 4)
rb_raise(rb_eArgError, "TYPE_INTEGER requires three additional arguments");
- return INT2NUM(set_field_type(field, ftype,
+ return INT2NUM(set_field_type(field, ftype,
NUM2INT(arg3),
NUM2LONG(arg4),
NUM2LONG(arg5)));
}
else if (ftype == TYPE_NUMERIC) {
if (argc != 4)
rb_raise(rb_eArgError, "TYPE_NUMERIC requires three additional arguments");
- return INT2NUM(set_field_type(field, ftype,
+ return INT2NUM(set_field_type(field, ftype,
NUM2INT(arg3),
NUM2DBL(arg4),
NUM2DBL(arg5)));
}
else if (ftype == TYPE_REGEXP){
if (argc != 2)
rb_raise(rb_eArgError, "TYPE_REGEXP requires one additional argument");
- return INT2NUM(set_field_type(field, ftype,
+ return INT2NUM(set_field_type(field, ftype,
STR2CSTR(arg3)));
}
- else if (ftype == TYPE_IPV4){
+ else if (ftype == TYPE_IPV4){
if (argc != 1)
rb_raise(rb_eArgError, "TYPE_IPV4 has no additional arguments");
return INT2NUM(set_field_type(field, ftype));
}
- else {
+ else {
/* It is a user-defined field type. */
/* Will store the arguments associated with this field */
/* for use in the callback function. */
VALUE rest;
rb_scan_args(argc, argv, "1*", &rb_fieldtype, &rest);
reg_proc(field, FIELDTYPE_ARGS, rest);
/* Pass field as an optional parameter so that make_arg can create */
/* the block-argument used in finding the appropriate Ruby Proc */
return INT2NUM(set_field_type(field, ftype, field));
}
-
+
}
static VALUE rbncurs_m_set_field_type(int argc, VALUE* argv, VALUE dummy)
{ return rbncurs_c_set_field_type(argc-1, argv+1, argv[0]); }
static VALUE rbncurs_c_field_type(VALUE rb_field) {
@@ -694,11 +709,11 @@
/*
* field_attributes
*/
static VALUE rbncurs_c_set_field_fore(VALUE rb_field, VALUE attr) {
FIELD* field = get_field(rb_field);
- return INT2NUM(set_field_fore(field, NUM2ULONG(attr)));
+ return INT2NUM(set_field_fore(field, (int) NUM2ULONG(attr)));
}
static VALUE rbncurs_m_set_field_fore(VALUE dummy, VALUE rb_field, VALUE attr)
{ return rbncurs_c_set_field_fore(rb_field, attr); }
static VALUE rbncurs_c_field_fore(VALUE rb_field) {
@@ -708,11 +723,11 @@
static VALUE rbncurs_m_field_fore(VALUE dummy, VALUE rb_field)
{ return rbncurs_c_field_fore(rb_field); }
static VALUE rbncurs_c_set_field_back(VALUE rb_field, VALUE attr) {
FIELD* field = get_field(rb_field);
- return INT2NUM(set_field_back(field, NUM2ULONG(attr)));
+ return INT2NUM(set_field_back(field, (int) NUM2ULONG(attr)));
}
static VALUE rbncurs_m_set_field_back(VALUE dummy, VALUE rb_field, VALUE attr)
{ return rbncurs_c_set_field_back(rb_field, attr); }
static VALUE rbncurs_c_field_back(VALUE rb_field) {
@@ -783,11 +798,11 @@
/* we will have to do it now. */
FIELD** fields = ALLOC_N(FIELD*, (n+1));
long i;
FORM* form = NULL;
for (i=0; i<n; i++){
- fields[i] = get_field(rb_ary_entry(rb_field_array, i));
+ fields[i] = get_field(rb_ary_entry(rb_field_array, i));
}
fields[n] = NULL;
form = get_form(rb_form);
return INT2NUM(set_form_fields(form, fields));
}
@@ -797,11 +812,11 @@
static VALUE rbncurs_c_form_fields(VALUE rb_form) {
FORM* form = get_form(rb_form);
FIELD** fields = form_fields(form);
VALUE arr = Qundef;
int i;
- if (fields == NULL)
+ if (fields == NULL)
rb_raise(rb_eRuntimeError, "Error retrieving form fields");
arr = rb_ary_new();
i=0;
while (fields[i] != NULL)
{
@@ -839,16 +854,16 @@
}
}
static VALUE rbncurs_c_set_field_init(VALUE rb_form, VALUE proc) {
FORM* form = NULL;
if (!rb_obj_is_kind_of(rb_form, cFORM))
- rb_raise(rb_eArgError, "arg1 must be a FORM object");
+ rb_raise(rb_eArgError, "arg1 must be a FORM object");
if (!rb_obj_is_kind_of(proc, rb_cProc))
- rb_raise(rb_eArgError, "arg2 must be a Proc object");
+ rb_raise(rb_eArgError, "arg2 must be a Proc object");
form = get_form(rb_form);
reg_proc(form, FIELD_INIT_HOOK, proc);
- if (proc != Qnil) {
+ if (proc != Qnil) {
return INT2NUM(set_field_init(form, field_init_hook));
}
else {
return INT2NUM(set_field_init(form, NULL));
}
@@ -872,16 +887,16 @@
}
}
static VALUE rbncurs_c_set_field_term(VALUE rb_form, VALUE proc) {
FORM * form = NULL;
if (!rb_obj_is_kind_of(rb_form, cFORM))
- rb_raise(rb_eArgError, "arg1 must be a FORM object");
+ rb_raise(rb_eArgError, "arg1 must be a FORM object");
if (!rb_obj_is_kind_of(proc, rb_cProc))
- rb_raise(rb_eArgError, "arg2 must be a Proc object");
+ rb_raise(rb_eArgError, "arg2 must be a Proc object");
form = get_form(rb_form);
reg_proc(form, FIELD_TERM_HOOK, proc);
- if (proc != Qnil) {
+ if (proc != Qnil) {
return INT2NUM(set_field_term(form, field_term_hook));
}
else {
return INT2NUM(set_field_term(form, NULL));
}
@@ -905,16 +920,16 @@
}
}
static VALUE rbncurs_c_set_form_init(VALUE rb_form, VALUE proc) {
FORM * form = NULL;
if (!rb_obj_is_kind_of(rb_form, cFORM))
- rb_raise(rb_eArgError, "arg1 must be a FORM object");
+ rb_raise(rb_eArgError, "arg1 must be a FORM object");
if (!rb_obj_is_kind_of(proc, rb_cProc))
- rb_raise(rb_eArgError, "arg2 must be a Proc object");
+ rb_raise(rb_eArgError, "arg2 must be a Proc object");
form = get_form(rb_form);
reg_proc(form, FORM_INIT_HOOK, proc);
- if (proc != Qnil) {
+ if (proc != Qnil) {
return INT2NUM(set_form_init(form, form_init_hook));
}
else {
return INT2NUM(set_form_init(form, NULL));
}
@@ -938,16 +953,16 @@
}
}
static VALUE rbncurs_c_set_form_term(VALUE rb_form, VALUE proc) {
FORM * form = NULL;
if (!rb_obj_is_kind_of(rb_form, cFORM))
- rb_raise(rb_eArgError, "arg1 must be a FORM object");
+ rb_raise(rb_eArgError, "arg1 must be a FORM object");
if (!rb_obj_is_kind_of(proc, rb_cProc))
- rb_raise(rb_eArgError, "arg2 must be a Proc object");
+ rb_raise(rb_eArgError, "arg2 must be a Proc object");
form = get_form(rb_form);
reg_proc(form, FORM_TERM_HOOK, proc);
- if (proc != Qnil) {
+ if (proc != Qnil) {
return INT2NUM(set_form_term(form, form_term_hook));
}
else {
return INT2NUM(set_form_term(form, NULL));
}
@@ -1096,11 +1111,11 @@
rb_raise(rb_eArgError,
"rows and columns arguments must be empty Arrays");
return Qnil;
}
else {
- int vals[2] = {0,0};
+ int vals[2] = {0,0};
int result = scale_form(form, &vals[0],&vals[1]);
rb_ary_push(rows, INT2NUM(vals[0]));
rb_ary_push(columns, INT2NUM(vals[1]));
return INT2NUM(result);
}
@@ -1109,44 +1124,44 @@
{ return rbncurs_c_scale_form(rb_form, rows, columns); }
/*
* form_fieldtype
*/
-static void* make_arg(va_list* ap) {
+static void* make_arg(va_list* ap) {
/* This method creates a list of arguments to be passed */
/* to the validation functions (char_check and field_check). */
- FIELD* field = va_arg(*ap, FIELD*);
+ FIELD* field = va_arg(*ap, FIELD*);
FIELDTYPE* fieldtype = field_type(field);
VALUE proc = get_proc(fieldtype, FIELDTYPE_FIELD_CHECK_HOOK);
if (proc == Qnil) {
proc = get_proc(fieldtype, FIELDTYPE_CHAR_CHECK_HOOK);
}
-
+
/* Compare number of arguments in Ruby Proc with that of set_field_type */
- if (proc != Qnil) {
+ if (proc != Qnil) {
VALUE argc = rb_funcall(proc, rb_intern("arity"),0);
VALUE args = get_proc(field, FIELDTYPE_ARGS);
- if (args != Qnil) {
- if (NUM2INT(argc)-1 != rbncurs_array_length(args)) {
+ if (args != Qnil) {
+ if (NUM2INT(argc)-1 != rbncurs_array_length(args)) {
char msg[500];
- snprintf(msg, 500, "The validation functions for this field type need %d additional arguments.",NUM2INT(argc)-1);
+ snprintf(msg, 500, "The validation functions for this field type need %d additional arguments.",(int)(NUM2INT(argc)-1));
msg[499]=0;
- rb_raise(rb_eArgError, msg);
+ rb_raise(rb_eArgError, "%s", msg);
}
- }
+ }
}
/* field will be the only argument in field_check/char_check callback */
/* and will be used to locate the appropriate Ruby Proc */
return field;
}
static bool field_check(FIELD* field, const void* argblock) {
FIELDTYPE* fieldtype = field_type(field);
VALUE proc = get_proc(fieldtype, FIELDTYPE_FIELD_CHECK_HOOK);
- if (proc != Qnil)
+ if (proc != Qnil)
{
VALUE args = rb_ary_dup(get_proc(field, FIELDTYPE_ARGS));
- rb_ary_unshift(args, wrap_field(field));
+ rb_ary_unshift(args, wrap_field(field));
return RTEST(rb_apply(proc, rb_intern("call"), args));
}
return 1;
}
static bool char_check(int c, const void* argblock) {
@@ -1161,22 +1176,22 @@
rb_ary_unshift(args, rb_str_new2(str));
return RTEST(rb_apply(proc, rb_intern("call"), args));
}
return 1;
}
-static VALUE rbncurs_m_new_fieldtype(VALUE dummy, VALUE field_check_proc, VALUE char_check_proc)
+static VALUE rbncurs_m_new_fieldtype(VALUE dummy, VALUE field_check_proc, VALUE char_check_proc)
{
FIELDTYPE* fieldtype = new_fieldtype(field_check_proc == Qnil ? NULL : field_check,
- char_check_proc == Qnil ? NULL : char_check);
+ char_check_proc == Qnil ? NULL : char_check);
set_fieldtype_arg(fieldtype, make_arg, NULL, NULL);
if (field_check_proc != Qnil) {
reg_proc(fieldtype, FIELDTYPE_FIELD_CHECK_HOOK, field_check_proc);
- }
+ }
if (char_check_proc != Qnil) {
reg_proc(fieldtype, FIELDTYPE_CHAR_CHECK_HOOK, char_check_proc);
}
-
+
return wrap_fieldtype(fieldtype);
}
static VALUE rbncurs_c_free_fieldtype(VALUE rb_fieldtype) {
FIELDTYPE* fieldtype = get_fieldtype(rb_fieldtype);
@@ -1204,17 +1219,17 @@
return 1;
}
static VALUE rbncurs_c_set_fieldtype_choice(VALUE rb_fieldtype, VALUE next_choice_proc, VALUE prev_choice_proc) {
FIELDTYPE* fieldtype = get_fieldtype(rb_fieldtype);
- int result = set_fieldtype_choice(fieldtype,
- next_choice_proc == Qnil ? NULL : next_choice,
+ int result = set_fieldtype_choice(fieldtype,
+ next_choice_proc == Qnil ? NULL : next_choice,
prev_choice_proc == Qnil ? NULL : prev_choice);
if (next_choice_proc != Qnil)
reg_proc(fieldtype, FIELDTYPE_NEXT_CHOICE_HOOK, next_choice_proc);
if (prev_choice_proc != Qnil)
- reg_proc(fieldtype, FIELDTYPE_PREV_CHOICE_HOOK, prev_choice_proc);
+ reg_proc(fieldtype, FIELDTYPE_PREV_CHOICE_HOOK, prev_choice_proc);
return INT2NUM(result);
}
static VALUE rbncurs_m_set_fieldtype_choice(VALUE dummy, VALUE rb_fieldtype, VALUE next_choice_proc, VALUE prev_choice_proc)
{ return rbncurs_c_set_fieldtype_choice(rb_fieldtype, next_choice_proc, prev_choice_proc); }
@@ -1250,13 +1265,13 @@
static VALUE rbncurs_m_pos_form_cursor(VALUE dummy, VALUE rb_form)
{ return rbncurs_c_pos_form_cursor(rb_form); }
void init_form(void)
{
-
+
mForm = rb_define_module_under(mNcurses, "Form");
-
+
FORM_SNG_FUNC(current_field,1);
FORM_SNG_FUNC(data_ahead,1);
FORM_SNG_FUNC(data_behind,1);
FORM_SNG_FUNC(dup_field,3);
FORM_SNG_FUNC(dynamic_field_info,4);
@@ -1276,10 +1291,15 @@
FORM_SNG_FUNC(field_status,1);
FORM_SNG_FUNC(field_term,1);
FORM_SNG_FUNC(field_type,1);
/* FORM_SNG_FUNC(field_userptr,1); */
FORM_SNG_FUNC(form_driver,2);
+
+ # ifdef HAVE_FORM_DRIVER_W
+ FORM_SNG_FUNC(form_driver_w,3);
+ #endif
+
FORM_SNG_FUNC(form_fields,1);
FORM_SNG_FUNC(form_init,1);
FORM_SNG_FUNC(form_opts,1);
FORM_SNG_FUNC(form_opts_off,2);
FORM_SNG_FUNC(form_opts_on,2);
@@ -1331,11 +1351,11 @@
init_err_codes();
init_req_constants();
init_opts_constants();
init_just_constants();
init_form_opts_constants();
-
+
/* Hashes to store registered blocks (Proc) */
{
VALUE hashes = rb_iv_set(mForm, "@proc_hashes", rb_ary_new());
int i;
for (i = 0; i < PROC_HASHES_COUNT; i++)
@@ -1356,9 +1376,14 @@
RB_CLASS_METH(cFORM, NULL, dup_field,2);
RB_CLASS_METH(cFORM, NULL, field_count,0);
RB_CLASS_METH(cFORM, NULL, field_init,0);
RB_CLASS_METH(cFORM, NULL, field_term,0);
RB_CLASS_METH(cFORM, "driver", form_driver,1);
+
+ # ifdef HAVE_FORM_DRIVER_W
+ RB_CLASS_METH(cFORM, "driver_w", form_driver_w,2);
+ #endif
+
RB_CLASS_METH(cFORM, "fields", form_fields,0);
RB_CLASS_METH(cFORM, "init", form_init,0);
RB_CLASS_METH(cFORM, "opts", form_opts,0);
RB_CLASS_METH(cFORM, "opts_off", form_opts_off,1);
RB_CLASS_METH(cFORM, "opts_on", form_opts_on,1);