# module TkUtil

### Constants

None
RELEASE_DATE

### Public Class Methods

_conv_args(*args) click to toggle source

    static VALUE
    tk_conv_args(argc, argv, self)
        int   argc;
        VALUE *argv; /* [0]:base_array, [1]:enc_mode, [2]..[n]:args */
        VALUE self;
    {
        int idx;
        long size;
        volatile VALUE dst;
        int thr_crit_bup;
        VALUE old_gc;

        if (argc < 2) {
          rb_raise(rb_eArgError, "too few arguments");
        }

        thr_crit_bup = rb_thread_critical;
        rb_thread_critical = Qtrue;
        old_gc = rb_gc_disable();

        for(size = 0, idx = 2; idx < argc; idx++) {
            if (RB_TYPE_P(argv[idx], T_HASH)) {
                size += 2 * RHASH_SIZE(argv[idx]);
            } else {
                size++;
            }
        }
        /* dst = rb_ary_new2(argc - 2); */
        dst = rb_ary_new2(size);
        for(idx = 2; idx < argc; idx++) {
            if (RB_TYPE_P(argv[idx], T_HASH)) {
                if (RTEST(argv[1])) {
                    hash2kv_enc(argv[idx], dst, self);
                } else {
                    hash2kv(argv[idx], dst, self);
                }
            } else if (argv[idx] != TK_None) {
                rb_ary_push(dst, get_eval_string_core(argv[idx], argv[1], self));
            }
        }

        if (old_gc == Qfalse) rb_gc_enable();
        rb_thread_critical = thr_crit_bup;

        return rb_ary_plus(argv[0], dst);
    }

_get_eval_enc_str(p1) click to toggle source

    static VALUE
    tk_get_eval_enc_str(self, obj)
        VALUE self;
        VALUE obj;
    {
        if (obj == TK_None) {
            return obj;
        } else {
            return get_eval_string_core(obj, Qtrue, self);
        }
    }

_get_eval_string(p1, p2 = v2) click to toggle source

    static VALUE
    tk_get_eval_string(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        VALUE obj, enc_flag;

        if (rb_scan_args(argc, argv, "11", &obj, &enc_flag) == 1) {
            enc_flag = Qnil;
        }

        return get_eval_string_core(obj, enc_flag, self);
    }

_symbolkey2str(p1) click to toggle source

    static VALUE
    tk_symbolkey2str(self, keys)
        VALUE self;
        VALUE keys;
    {
        volatile VALUE new_keys = rb_hash_new();

        if (NIL_P(keys)) return new_keys;
        keys = rb_convert_type(keys, T_HASH, "Hash", "to_hash");
        st_foreach_check(RHASH_TBL(keys), to_strkey, new_keys, Qundef);
        return new_keys;
    }

bool(p1) click to toggle source

/

    static VALUE
    tcl2rb_bool(self, value)
        VALUE self;
        VALUE value;
    {
        if (RB_TYPE_P(value, T_FIXNUM)) {
            if (NUM2INT(value) == 0) {
                return Qfalse;
            } else {
                return Qtrue;
            }
        }

        if (value == Qtrue || value == Qfalse) {
            return value;
        }

        rb_check_type(value, T_STRING);

        value = rb_funcall(value, ID_downcase, 0);

        if (RSTRING_PTR(value) == (char*)NULL) return Qnil;

        if (RSTRING_PTR(value)[0] == '\0'
            || strcmp(RSTRING_PTR(value), "0") == 0
            || strcmp(RSTRING_PTR(value), "no") == 0
            || strcmp(RSTRING_PTR(value), "off") == 0
            || strcmp(RSTRING_PTR(value), "false") == 0) {
            return Qfalse;
        } else {
            return Qtrue;
        }
    }

callback(p1, *args) click to toggle source

    static VALUE
    tk_do_callback(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
    #if 0
        volatile VALUE id;
        volatile VALUE rest;

        rb_scan_args(argc, argv, "1*", &id, &rest);
        return rb_apply(rb_hash_aref(CALLBACK_TABLE, id), ID_call, rest);
    #endif
        return rb_funcall2(rb_hash_aref(CALLBACK_TABLE, argv[0]),
                           ID_call, argc - 1, argv + 1);
    }

eval_cmd(p1, *args) click to toggle source

    static VALUE
    tk_eval_cmd(argc, argv, self)
        int argc;
        VALUE argv[];
        VALUE self;
    {
        VALUE cmd, rest;

        rb_scan_args(argc, argv, "1*", &cmd, &rest);
        return rb_eval_cmd(cmd, rest, 0);
    }

hash_kv(*args) click to toggle source

    static VALUE
    tk_hash_kv(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        volatile VALUE hash, enc_flag, ary;

        ary = Qnil;
        enc_flag = Qnil;
        switch(argc) {
        case 3:
            ary = argv[2];
            if (!NIL_P(ary)) Check_Type(ary, T_ARRAY);
        case 2:
            enc_flag = argv[1];
        case 1:
            hash = argv[0];
            break;
        case 0:
            rb_raise(rb_eArgError, "too few arguments");
        default: /* >= 3 */
            rb_raise(rb_eArgError, "too many arguments");
        }

        switch(TYPE(hash)) {
        case T_ARRAY:
            if (RTEST(enc_flag)) {
                return assoc2kv_enc(hash, ary, self);
            } else {
                return assoc2kv(hash, ary, self);
            }

        case T_HASH:
            if (RTEST(enc_flag)) {
                return hash2kv_enc(hash, ary, self);
            } else {
                return hash2kv(hash, ary, self);
            }

        case T_NIL:
            if (NIL_P(ary)) {
                return rb_ary_new();
            } else {
                return ary;
            }

        default:
            if (hash == TK_None) {
                if (NIL_P(ary)) {
                    return rb_ary_new();
                } else {
                    return ary;
                }
            }
            rb_raise(rb_eArgError, "Hash is expected for 1st argument");
        }

        UNREACHABLE;
    }

install_cmd(p1 = v1) click to toggle source

    static VALUE
    tk_install_cmd(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        volatile VALUE cmd;

    #if 0
        if (rb_scan_args(argc, argv, "01", &cmd) == 0) {
            cmd = rb_block_proc();
        }
        return tk_install_cmd_core(cmd);
    #endif
        if (argc == 0) {
            cmd = rb_block_proc();
        } else {
            cmd = argv[0];
        }
        return tk_install_cmd_core(cmd);
    }

num_or_nil(p1) click to toggle source

    static VALUE
    tcl2rb_num_or_nil(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_LEN(value) == 0) return Qnil;

        return tkstr_to_number(value);
    }

num_or_str(p1) click to toggle source

    static VALUE
    tcl2rb_num_or_str(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_PTR(value) == (char*)NULL) return rb_tainted_str_new2("");

        return rb_rescue2(tkstr_to_number, value,
                          tkstr_to_str, value,
                          rb_eArgError, 0);
    }

number(p1) click to toggle source

    static VALUE
    tcl2rb_number(self, value)
        VALUE self;
        VALUE value;
    {
        return tkstr_to_number(value);
    }

string(p1) click to toggle source

    static VALUE
    tcl2rb_string(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_PTR(value) == (char*)NULL) return rb_tainted_str_new2("");

        return tkstr_to_str(value);
    }

uninstall_cmd(p1) click to toggle source

    static VALUE
    tk_uninstall_cmd(self, cmd_id)
        VALUE self;
        VALUE cmd_id;
    {
        size_t head_len = strlen(cmd_id_head);
        size_t prefix_len = strlen(cmd_id_prefix);

        StringValue(cmd_id);
        if (strncmp(cmd_id_head, RSTRING_PTR(cmd_id), head_len) != 0) {
            return Qnil;
        }
        if (strncmp(cmd_id_prefix,
                    RSTRING_PTR(cmd_id) + head_len, prefix_len) != 0) {
            return Qnil;
        }

        return rb_hash_delete(CALLBACK_TABLE,
                              rb_str_new2(RSTRING_PTR(cmd_id) + head_len));
    }

untrust(p1) click to toggle source

/

    static VALUE
    tk_obj_untrust(self, obj)
        VALUE self;
        VALUE obj;
    {
    #ifdef HAVE_RB_OBJ_TAINT
      rb_obj_taint(obj);
    #endif
    #ifdef HAVE_RB_OBJ_UNTRUST
      rb_obj_untrust(obj);
    #endif

      return obj;
    }

### Public Instance Methods

_conv_args(*args) click to toggle source

    static VALUE
    tk_conv_args(argc, argv, self)
        int   argc;
        VALUE *argv; /* [0]:base_array, [1]:enc_mode, [2]..[n]:args */
        VALUE self;
    {
        int idx;
        long size;
        volatile VALUE dst;
        int thr_crit_bup;
        VALUE old_gc;

        if (argc < 2) {
          rb_raise(rb_eArgError, "too few arguments");
        }

        thr_crit_bup = rb_thread_critical;
        rb_thread_critical = Qtrue;
        old_gc = rb_gc_disable();

        for(size = 0, idx = 2; idx < argc; idx++) {
            if (RB_TYPE_P(argv[idx], T_HASH)) {
                size += 2 * RHASH_SIZE(argv[idx]);
            } else {
                size++;
            }
        }
        /* dst = rb_ary_new2(argc - 2); */
        dst = rb_ary_new2(size);
        for(idx = 2; idx < argc; idx++) {
            if (RB_TYPE_P(argv[idx], T_HASH)) {
                if (RTEST(argv[1])) {
                    hash2kv_enc(argv[idx], dst, self);
                } else {
                    hash2kv(argv[idx], dst, self);
                }
            } else if (argv[idx] != TK_None) {
                rb_ary_push(dst, get_eval_string_core(argv[idx], argv[1], self));
            }
        }

        if (old_gc == Qfalse) rb_gc_enable();
        rb_thread_critical = thr_crit_bup;

        return rb_ary_plus(argv[0], dst);
    }

_get_eval_enc_str(p1) click to toggle source

    static VALUE
    tk_get_eval_enc_str(self, obj)
        VALUE self;
        VALUE obj;
    {
        if (obj == TK_None) {
            return obj;
        } else {
            return get_eval_string_core(obj, Qtrue, self);
        }
    }

_get_eval_string(p1, p2 = v2) click to toggle source

    static VALUE
    tk_get_eval_string(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        VALUE obj, enc_flag;

        if (rb_scan_args(argc, argv, "11", &obj, &enc_flag) == 1) {
            enc_flag = Qnil;
        }

        return get_eval_string_core(obj, enc_flag, self);
    }

_symbolkey2str(p1) click to toggle source

    static VALUE
    tk_symbolkey2str(self, keys)
        VALUE self;
        VALUE keys;
    {
        volatile VALUE new_keys = rb_hash_new();

        if (NIL_P(keys)) return new_keys;
        keys = rb_convert_type(keys, T_HASH, "Hash", "to_hash");
        st_foreach_check(RHASH_TBL(keys), to_strkey, new_keys, Qundef);
        return new_keys;
    }

hash_kv(*args) click to toggle source

    static VALUE
    tk_hash_kv(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        volatile VALUE hash, enc_flag, ary;

        ary = Qnil;
        enc_flag = Qnil;
        switch(argc) {
        case 3:
            ary = argv[2];
            if (!NIL_P(ary)) Check_Type(ary, T_ARRAY);
        case 2:
            enc_flag = argv[1];
        case 1:
            hash = argv[0];
            break;
        case 0:
            rb_raise(rb_eArgError, "too few arguments");
        default: /* >= 3 */
            rb_raise(rb_eArgError, "too many arguments");
        }

        switch(TYPE(hash)) {
        case T_ARRAY:
            if (RTEST(enc_flag)) {
                return assoc2kv_enc(hash, ary, self);
            } else {
                return assoc2kv(hash, ary, self);
            }

        case T_HASH:
            if (RTEST(enc_flag)) {
                return hash2kv_enc(hash, ary, self);
            } else {
                return hash2kv(hash, ary, self);
            }

        case T_NIL:
            if (NIL_P(ary)) {
                return rb_ary_new();
            } else {
                return ary;
            }

        default:
            if (hash == TK_None) {
                if (NIL_P(ary)) {
                    return rb_ary_new();
                } else {
                    return ary;
                }
            }
            rb_raise(rb_eArgError, "Hash is expected for 1st argument");
        }

        UNREACHABLE;
    }

### Private Instance Methods

_fromUTF8(*args) click to toggle source

    static VALUE
    tk_fromUTF8(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        return rb_funcall2(cTclTkLib, ID_fromUTF8, argc, argv);
    }

_toUTF8(*args) click to toggle source

    static VALUE
    tk_toUTF8(argc, argv, self)
        int   argc;
        VALUE *argv;
        VALUE self;
    {
        return rb_funcall2(cTclTkLib, ID_toUTF8, argc, argv);
    }

bool(p1) click to toggle source

/

    static VALUE
    tcl2rb_bool(self, value)
        VALUE self;
        VALUE value;
    {
        if (RB_TYPE_P(value, T_FIXNUM)) {
            if (NUM2INT(value) == 0) {
                return Qfalse;
            } else {
                return Qtrue;
            }
        }

        if (value == Qtrue || value == Qfalse) {
            return value;
        }

        rb_check_type(value, T_STRING);

        value = rb_funcall(value, ID_downcase, 0);

        if (RSTRING_PTR(value) == (char*)NULL) return Qnil;

        if (RSTRING_PTR(value)[0] == '\0'
            || strcmp(RSTRING_PTR(value), "0") == 0
            || strcmp(RSTRING_PTR(value), "no") == 0
            || strcmp(RSTRING_PTR(value), "off") == 0
            || strcmp(RSTRING_PTR(value), "false") == 0) {
            return Qfalse;
        } else {
            return Qtrue;
        }
    }

num_or_nil(p1) click to toggle source

    static VALUE
    tcl2rb_num_or_nil(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_LEN(value) == 0) return Qnil;

        return tkstr_to_number(value);
    }

num_or_str(p1) click to toggle source

    static VALUE
    tcl2rb_num_or_str(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_PTR(value) == (char*)NULL) return rb_tainted_str_new2("");

        return rb_rescue2(tkstr_to_number, value,
                          tkstr_to_str, value,
                          rb_eArgError, 0);
    }

number(p1) click to toggle source

    static VALUE
    tcl2rb_number(self, value)
        VALUE self;
        VALUE value;
    {
        return tkstr_to_number(value);
    }

string(p1) click to toggle source

    static VALUE
    tcl2rb_string(self, value)
        VALUE self;
        VALUE value;
    {
        rb_check_type(value, T_STRING);

        if (RSTRING_PTR(value) == (char*)NULL) return rb_tainted_str_new2("");

        return tkstr_to_str(value);
    }