Ejemplo n.º 1
0
func (ir *interpreter) unregister_commands(name string) error {
	if _, ok := ir.methods[name]; !ok {
		return errors.New("gothic: trying to unregister a non-existent method set")
	}
	val := ir.methods[name]
	t := reflect.TypeOf(val)
	for i, n := 0, t.NumMethod(); i < n; i++ {
		m := t.Method(i)
		if !strings.HasPrefix(m.Name, "TCL") {
			continue
		}

		subname := m.Name[3:]
		if strings.HasPrefix(m.Name, "TCL_") {
			subname = m.Name[4:]
		}

		cname := C.CString(name + "::" + subname)
		status := C.Tcl_DeleteCommand(ir.C, cname)
		C.free(unsafe.Pointer(cname))
		if status != C.TCL_OK {
			return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
		}
	}
	delete(ir.methods, name)
	for _, id := range ir.method_handles[name] {
		ir.handles.free_handle(id)
	}
	delete(ir.method_handles, name)
	return nil
}
Ejemplo n.º 2
0
func (ir *interpreter) eval(script []byte) error {
	if len(script) == 0 {
		return nil
	}
	status := C.Tcl_EvalEx(ir.C, (*C.char)(unsafe.Pointer(&script[0])),
		C.int(len(script)), 0)
	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 3
0
func (ir *Interpreter) UnregisterChannel(name string) {
	if _, ok := ir.channels[name]; !ok {
		return
	}
	cname := C.CString(name)
	status := C.Tcl_DeleteCommand(ir.C, cname)
	C.free_string(cname)
	if status != C.TCL_OK {
		panic(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
}
Ejemplo n.º 4
0
func (ir *interpreter) eval(args ...interface{}) error {
	ir.cmdbuf.Reset()
	fmt.Fprint(&ir.cmdbuf, args...)
	ir.cmdbuf.WriteByte(0)

	status := C.Tcl_Eval(ir.C, (*C.char)(unsafe.Pointer(&ir.cmdbuf.Bytes()[0])))
	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 5
0
func NewInterpreter() (*Interpreter, os.Error) {
	ir := &Interpreter{
		C:         C.Tcl_CreateInterp(),
		callbacks: make(map[string]interface{}),
		channels:  make(map[string]interface{}),
		valuesbuf: make([]reflect.Value, 0, 10),
		queue:     make(chan string, 50),
	}

	status := C.Tcl_Init(ir.C)
	if status != C.TCL_OK {
		return nil, os.NewError(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	status = C.Tk_Init(ir.C)
	if status != C.TCL_OK {
		return nil, os.NewError(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	return ir, nil
}
Ejemplo n.º 6
0
func (ir *interpreter) unregister_command(name string) error {
	if _, ok := ir.commands[name]; !ok {
		return errors.New("gothic: trying to unregister a non-existent command")
	}
	cname := C.CString(name)
	status := C.Tcl_DeleteCommand(ir.C, cname)
	C.free(unsafe.Pointer(cname))
	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 7
0
func new_interpreter(init interface{}) (*interpreter, error) {
	ir := &interpreter{
		C:              C.Tcl_CreateInterp(),
		errfilt:        func(err error) error { return err },
		commands:       make(map[string]interface{}),
		methods:        make(map[string]interface{}),
		method_handles: make(map[string][]int),
		valuesbuf:      make([]reflect.Value, 0, 10),
		queue:          make(chan async_action, 50),
		thread:         C.Tcl_GetCurrentThread(),
	}

	C.Tcl_FindExecutable(C.CString(os.Args[0]))

	switch realinit := init.(type) {
	case string:
		err := ir.eval([]byte(realinit))
		if err != nil {
			panic(err)
		}
	case func(*interpreter):
		realinit(ir)
	}

	status := C.Tcl_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	status = C.Tk_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	ir.id = global_handles.get_handle_for_value(ir)
	runtime.SetFinalizer(ir, release_interpreter)
	return ir, nil
}
Ejemplo n.º 8
0
func (ir *interpreter) upload_image(name string, img image.Image) error {
	var buf bytes.Buffer
	err := sprintf(&buf, "image create photo %{}", name)
	if err != nil {
		return err
	}

	nrgba, ok := img.(*image.NRGBA)
	if !ok {
		// let's do it slowpoke
		bounds := img.Bounds()
		nrgba = image.NewNRGBA(bounds)
		for x := 0; x < bounds.Max.X; x++ {
			for y := 0; y < bounds.Max.Y; y++ {
				nrgba.Set(x, y, img.At(x, y))
			}
		}
	}

	cname := C.CString(name)
	handle := C.Tk_FindPhoto(ir.C, cname)
	if handle == nil {
		err := ir.eval(buf.Bytes())
		if err != nil {
			return err
		}
		handle = C.Tk_FindPhoto(ir.C, cname)
		if handle == nil {
			return errors.New("failed to create an image handle")
		}
	}
	C.free(unsafe.Pointer(cname))
	block := C.Tk_PhotoImageBlock{
		(*C.uchar)(unsafe.Pointer(&nrgba.Pix[0])),
		C.int(nrgba.Rect.Max.X),
		C.int(nrgba.Rect.Max.Y),
		C.int(nrgba.Stride),
		4,
		[...]C.int{0, 1, 2, 3},
	}

	status := C.Tk_PhotoPutBlock(ir.C, handle, &block, 0, 0,
		C.int(nrgba.Rect.Max.X), C.int(nrgba.Rect.Max.Y),
		C.TK_PHOTO_COMPOSITE_SET) // alpha should be non-zero or you may get peculiar slowdowns
	// Note: C.TK_PHOTO_COMPOSITE_OVERLAY would overlay an existing image
	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 9
0
func (ir *interpreter) set(name string, value interface{}) error {
	obj := go_value_to_tcl_obj(value, ir)
	if obj == nil {
		return errors.New("gothic: cannot convert Go value to TCL object")
	}

	cname := C.CString(name)
	obj = C.Tcl_SetVar2Ex(ir.C, cname, nil, obj, C.TCL_LEAVE_ERR_MSG)
	C.free(unsafe.Pointer(cname))
	if obj == nil {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 10
0
func new_interpreter() (*interpreter, error) {
	ir := &interpreter{
		C:         C.Tcl_CreateInterp(),
		errfilt:   func(err error) error { return err },
		commands:  make(map[string]interface{}),
		channels:  make(map[string]interface{}),
		valuesbuf: make([]reflect.Value, 0, 10),
		queue:     make(chan async_action, 50),
		thread:    C.Tcl_GetCurrentThread(),
	}

	status := C.Tcl_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	status = C.Tk_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	return ir, nil
}
Ejemplo n.º 11
0
func (ir *Interpreter) NewIntVar(name string) *IntVar {
	iv := new(IntVar)
	iv.ir = ir
	iv.name = name
	iv.data = 0

	cname := C.CString(name)
	status := C.Tcl_LinkVar(ir.C, cname, (*C.char)(unsafe.Pointer(&iv.data)),
		C.TCL_LINK_WIDE_INT)
	C.free_string(cname)
	if status != C.TCL_OK {
		panic(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return iv
}
Ejemplo n.º 12
0
func (ir *Interpreter) NewFloatVar(name string) *FloatVar {
	fv := new(FloatVar)
	fv.ir = ir
	fv.name = name
	fv.data = 0.0

	cname := C.CString(name)
	status := C.Tcl_LinkVar(ir.C, cname, (*C.char)(unsafe.Pointer(&fv.data)),
		C.TCL_LINK_DOUBLE)
	C.free_string(cname)
	if status != C.TCL_OK {
		panic(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return fv
}
Ejemplo n.º 13
0
func (ir *Interpreter) NewStringVar(name string) *StringVar {
	sv := new(StringVar)
	sv.ir = ir
	sv.name = name
	sv.data = C.Tcl_Alloc(1)
	(*((*[alot]byte)(unsafe.Pointer(sv.data))))[0] = 0

	cname := C.CString(name)
	status := C.Tcl_LinkVar(ir.C, cname, (*C.char)(unsafe.Pointer(&sv.data)),
		C.TCL_LINK_STRING)
	C.free_string(cname)
	if status != C.TCL_OK {
		panic(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return sv
}
Ejemplo n.º 14
0
func (ir *Interpreter) Eval(args ...string) {
	for _, arg := range args {
		ir.cmdbuf.WriteString(arg)
		ir.cmdbuf.WriteString(" ")
	}

	s := ir.cmdbuf.String()
	ir.cmdbuf.Reset()

	if debug {
		println(s)
	}

	cs := C.CString(s)
	status := C.Tcl_Eval(ir.C, cs)
	C.free_string(cs)
	if status != C.TCL_OK {
		fmt.Fprintln(os.Stderr, C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
}
Ejemplo n.º 15
0
func (ir *interpreter) tcl_obj_to_go_value(obj *C.Tcl_Obj, v reflect.Value) error {
	var status C.int

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		var out C.Tcl_WideInt
		status = C.Tcl_GetWideIntFromObj(ir.C, obj, &out)
		if status == C.TCL_OK {
			v.SetInt(int64(out))
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		var out C.Tcl_WideInt
		status = C.Tcl_GetWideIntFromObj(ir.C, obj, &out)
		if status == C.TCL_OK {
			v.SetUint(uint64(out))
		}
	case reflect.String:
		var n C.int
		out := C.Tcl_GetStringFromObj(obj, &n)
		v.SetString(C.GoStringN(out, n))
	case reflect.Float32, reflect.Float64:
		var out C.double
		status = C.Tcl_GetDoubleFromObj(ir.C, obj, &out)
		if status == C.TCL_OK {
			v.SetFloat(float64(out))
		}
	case reflect.Bool:
		var out C.int
		status = C.Tcl_GetBooleanFromObj(ir.C, obj, &out)
		if status == C.TCL_OK {
			v.SetBool(out == 1)
		}
	default:
		return fmt.Errorf("gothic: cannot convert TCL object to Go type: %s", v.Type())
	}

	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}
Ejemplo n.º 16
0
func (ir *interpreter) upload_image(name string, img image.Image) error {
	nrgba, ok := img.(*image.NRGBA)
	if !ok {
		// let's do it slowpoke
		bounds := img.Bounds()
		nrgba = image.NewNRGBA(bounds)
		for x := 0; x < bounds.Max.X; x++ {
			for y := 0; y < bounds.Max.Y; y++ {
				nrgba.Set(x, y, img.At(x, y))
			}
		}
	}

	cname := C.CString(name)
	handle := C.Tk_FindPhoto(ir.C, cname)
	if handle == nil {
		ir.eval("image create photo ", name)
		handle = C.Tk_FindPhoto(ir.C, cname)
		if handle == nil {
			return errors.New("failed to create an image handle")
		}
	}
	C.free(unsafe.Pointer(cname))
	block := C.Tk_PhotoImageBlock{
		(*C.uchar)(unsafe.Pointer(&nrgba.Pix[0])),
		C.int(nrgba.Rect.Max.X),
		C.int(nrgba.Rect.Max.Y),
		C.int(nrgba.Stride),
		4,
		[...]C.int{0, 1, 2, 3},
	}

	status := C.Tk_PhotoPutBlock(ir.C, handle, &block, 0, 0,
		C.int(nrgba.Rect.Max.X), C.int(nrgba.Rect.Max.Y),
		C.TK_PHOTO_COMPOSITE_SET)
	if status != C.TCL_OK {
		return errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}
	return nil
}