//
// Copyright (c) 1997 Jean-Marc Zucconi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer
//    in this position and unchanged.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. The name of the author may not be used to endorse or promote products
//    derived from this software without specific prior written permission
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//  $Id: c++tk.cc,v 1.34 2003/12/25 13:37:27 jmz Exp $
//
#include <tcl.h>
#ifdef TIX
#include <tix.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>

int TkError = 0;
int CXX_Tk_diag = 0;

extern "C" {
    int Tk_Init (Tcl_Interp *);
#ifdef TIX
    int Tixsam_Init (Tcl_Interp *);
#endif
}

#include "c++tk.h"

#include "tcl_scripts.h"
#ifdef TIX
#include "tix_scripts.h"
#endif

typedef void (Proc)(int, char **);

static int init = 0;
extern char *__progname;
static struct Tcl_Interp *interp;
static char *xstr;
static int lstr;
#define VAR_SIZE 1000
static int **i_vars;
static int **w_vars, *W_vars;
static char **t_vars;
static int n_ivars, N_ivars, n_wvars, N_wvars, n_tvars, N_tvars;
static Tcl_HashTable htable;

#define JMPNAME "CXX_Tk_JumpTo"
#define VARNAME "CXX_Tk_Var"
static char varstr[30] = VARNAME;
static int trace_ok = 1;

#define ERRORCHECK if(CXX_Tk_diag && TkError != TCL_OK) printf ("C++TK: <%s> => <%s>\n", xstr, interp->result)
#define PNAME int tmp; Tcl_HashEntry *he=Tcl_CreateHashEntry(&htable,interp->result,&tmp);\
              if(tmp) Tcl_SetHashValue(he,o->pname=strdup(interp->result)); else\
              o->pname=(char *)Tcl_GetHashValue(he)

#define TEXTVARIABLE \
    sprintf (xstr, "%s%x", VARNAME, v);\
    Tcl_SetVar (interp, xstr, v, TCL_GLOBAL_ONLY);\
    sprintf (xstr, "%s configure -textvariable %s%x", pname, VARNAME, v);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK;\
    add_tvar (v)
#define VARIABLE \
    sprintf (xstr, "%s%x", VARNAME, v);\
    Tcl_SetVar (interp, xstr, *v? (const char *)"1":(const char *)"0", TCL_GLOBAL_ONLY);\
    sprintf (xstr, "%s configure -variable %s%x", pname, VARNAME, v);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    sprintf (xstr, "%s%x", VARNAME, v);\
    Tcl_TraceVar (interp, xstr, TCL_TRACE_WRITES, TraceVars, 0);\
    ERRORCHECK;\
    add_ivar (v)

#define ARG1 char *a
#define ARG2 char *a, char *b
#define ARG3 char *a, char *b, char *c
#define ARG4 char *a, char *b, char *c, char *d
#define ARG5 char *a, char *b, char *c, char *d, char *e

#define V_0ARG(name) \
    cat (pname, name); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK
#define V_1ARG(name) \
    cat (pname, name, a); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK
#define V_2ARG(name) \
    cat (pname, name, a, b); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK
#define V_3ARG(name) \
    cat (pname, name, a, b, c); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK
#define V_4ARG(name) \
    cat (pname, name, a, b, c, d); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK
#define V_5ARG(name) \
    cat (pname, name, a, b, c, d, e); \
    TkError = Tcl_GlobalEval (interp, xstr); \
    ERRORCHECK

#define C_0ARG(name) \
    cat (pname, name);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define C_1ARG(name) \
    cat (pname, name, a);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define C_2ARG(name) \
    cat (pname, name, a, b);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define C_3ARG(name) \
    cat (pname, name, a, b, c);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define C_4ARG(name) \
    cat (pname, name, a, b, c, d);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define C_5ARG(name) \
    cat (pname, name, a, b, c, d, e);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result

#define I_0ARG(name) \
    cat (pname, name);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return atoi (interp->result)
#define I_1ARG(name) \
    cat (pname, name, a);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return atoi (interp->result)
#define I_2ARG(name) \
    cat (pname, name, a,b);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return atoi (interp->result)
#define I_3ARG(name) \
    cat (pname, name, a, b, c);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return atoi (interp->result)
    
static void
a2a (unsigned long a)
{
    char *p = &varstr[20];
    char *s = &varstr[10];
    do {
	*--p = "0123456789abcdef"[a & 15];
	a >>= 4;
    } while (a);
    do 
	*s++ = *p;
    while (*p++);
}
static char *
i2a (int val)
{
    static char s[20] = {0};
    char *p = s+19;
    int neg = 0;
    if (val < 0) {
	val = -val;
	neg = 1;
    }
    if (val < 10) /* many numbers are 1 digit */
	*--p = val + '0';
    else
	do {
	    *--p = (val % 10) + '0';
	    val /= 10;
	} while (val);
    if (neg)
	*--p = '-';
    return p;
}
static int
Proc_Handler (ClientData _,  Tcl_Interp *__, int argc, char **argv)
{
    Proc *fcn = (Proc *) strtoul (argv[1], 0, 16);
    char *s, **args;
    int i;
    int bind = argv[1][1];
    argc -= 2;
    argv += 2;
    for (i = 0; i < n_tvars; i++) {
	if (!t_vars[i])
	    break;
	a2a ((unsigned long) t_vars[i]);
	trace_ok = 0;
	s = (char *) Tcl_GetVar (interp, varstr, TCL_GLOBAL_ONLY);
	strcpy (t_vars[i], s);
	trace_ok = 1;
    }
    if (bind == 'x')
	(*fcn) (argc, argv);
    else if (bind == '.')
	;
    else { 
	if (argc) {
	    int j;
	    Tcl_SplitList(interp, *argv++, &i, (const char ***) &args);
	    char **A = new char* [argc+i];
	    for (j = 0; j < i; j++)
		A[j] = args[j];
	    while (--argc)
		A[j++] = *argv++;
	    (*fcn) (j, A);
	    delete [] A;
	    free ((char *) args);
	} else
	    (*fcn) (0, args);
    }
    for (i = 0; i < n_ivars; i++) {
	if (!i_vars[i])
	    break;
	a2a ((unsigned long) i_vars[i]);
	trace_ok = 0;
	Tcl_SetVar (interp, varstr, i2a(*i_vars[i]), TCL_GLOBAL_ONLY);
	trace_ok = 1;
    }
    for (i = 0; i < n_tvars; i++) {
	if (!t_vars[i])
	    break;
	a2a ((unsigned long) t_vars[i]);
//	sprintf (xstr, "CXXTk_Var%x", t_vars[i]);
	trace_ok = 0;
	Tcl_SetVar (interp, varstr, t_vars[i], TCL_GLOBAL_ONLY);
	trace_ok = 1;
    }
    for (i = 0; i < n_wvars; i++) {
	if (!w_vars[i])
	    break;
	if (W_vars[i] != *(int *)w_vars[i]) {
	    a2a ((unsigned long) w_vars[i]);
	    trace_ok = 0;
	    Tcl_SetVar (interp, varstr, i2a(*w_vars[i]), TCL_GLOBAL_ONLY);
	    trace_ok = 1;
	}
    }
    return TCL_OK;
}
char *
TraceVars (ClientData _, Tcl_Interp *__, const char *name1, const char *name2, int flags)
{
    if (trace_ok && (flags & TCL_TRACE_WRITES)) {
	int i = atoi (Tcl_GetVar(interp, name1, TCL_GLOBAL_ONLY));
	unsigned long a = strtoul (name1+10, 0, 16);
	*(int *)a = i;
    }
    return 0;
}

static void
initialize ()
{
    int argc = 1;
    char *argv[2] = {__progname, 0};

    // inital length must be >= length(longest pathname) + 50
    lstr = 1000;
    xstr = new char [lstr];

    Tcl_FindExecutable (__progname);
    interp = Tcl_CreateInterp ();
    Tcl_GlobalEval(interp, "set argc 1");
    sprintf (xstr, "set tcl_interactive %d", isatty (0));
    Tcl_GlobalEval(interp, xstr);
    Tk_Init (interp);
    Tcl_StaticPackage (interp, "Tk", Tk_Init, 0);
    for (init = 0; packages[init]; init++)
	Tcl_GlobalEval (interp, packages[init]);
#ifdef TIX
    if (Tixsam_Init (interp) != TCL_OK ) {
        fprintf(stderr,"Can't initialize the Tix extension: %s.\n", interp->result);
        exit(1);
    }
#endif
#ifdef TIX
    for (init = 0; tix_packages[init]; init++)
	Tcl_GlobalEval (interp, tix_packages[init]);
#endif
    Tcl_CreateCommand (interp, JMPNAME, 
		   (Tcl_CmdProc *) Proc_Handler, 
		   (void *)Tk_MainWindow (interp), 0);
    w_vars = new int * [VAR_SIZE];
    W_vars = new int [VAR_SIZE];
    i_vars = new int * [VAR_SIZE];
    t_vars = new char * [VAR_SIZE];
    n_ivars = 0;
    n_wvars = 0;
    N_wvars = VAR_SIZE;
    n_tvars = 0;
    N_tvars = VAR_SIZE;
    N_ivars = VAR_SIZE;
    for (argc = 0; argc < VAR_SIZE; argc++) {
	w_vars[argc] = 0;
	t_vars[argc] = 0;
	i_vars[argc] = 0;
    }
    Tcl_InitHashTable (&htable, TCL_STRING_KEYS); 
}
static void
cat (char *a, char *b = 0, char *c = 0, char *d = 0, char *e = 0, char *f = 0,
     char *g = 0, char *h = 0, char *i = 0, char *j = 0)
{
    char *s;
    int l = strlen (a);
    if (b) {
	l += strlen (b) + 1;
	if (c) {
	    l += strlen (c) + 1;
	    if (d) {
		l += strlen (d) + 1;
		if (e) {
		    l += strlen (e) + 1;
		    if (f) {
			l += strlen (f) + 1;
			if (g) {
			    l += strlen (g) + 1;
			    if (h) {
				l += strlen (h) + 1;
				if (i) {
				    l += strlen (i) + 1;
				    if (j)
					l += strlen (j) + 1;
				}
			    }
			}
		    }
		}
	    }
	}
    }
    if (l >= lstr ) {
	delete [] xstr;
	xstr = new char [++l];
	lstr = l;
    }
    s = xstr;
    while (*s++ = *a++);
    if (!b)
	return;
    s[-1] = ' ';
    while (*s++ = *b++);
    if (!c)
	return;
    s[-1] = ' ';
    while (*s++ = *c++);
    if (!d)
	return;
    s[-1] = ' ';
    while (*s++ = *d++);
    if (!e)
	return;
    s[-1] = ' ';
    while (*s++ = *e++);
    if (!f)
	return;
    s[-1] = ' ';
    while (*s++ = *f++);
    if (!g)
	return;
    s[-1] = ' ';
    while (*s++ = *g++);
    if (!h)
	return;
    s[-1] = ' ';
    while (*s++ = *h++);
    if (!i)
	return;
    s[-1] = ' ';
    while (*s++ = *i++);
    if (!j)
	return;
    s[-1] = ' ';
    while (*s++ = *j++);
}
static void
cat2 (char *a, char *b, char *c, char *d, char *e)
{
    char *s;
    int l;
    s = d;
    while (*s && (*s == ' ' || *s == '\t'))
	   s++;
    if (*d == '{') {
	if (e) {
	    s = e;
	    while (*s && (*s == ' ' || *s == '\t'))
		s++;
	    if (*s != '{')
		cat (a, b, c, d, "{", e, "}");
	    else
		cat (a, b, c, d, e);
	} else
	    cat (a, b, c, d);
    } else {
	if (e) {
	    s = e;
	    while (*s && (*s == ' ' || *s == '\t'))
		s++;
	    if (*s != '{')
		cat (a, b, c, " ", d, "  {", e, "}");
	    else
		cat (a, b, c, " ", d, " ", e);
	} else
	    cat (a, b, c, " ", d, " ");
	l = strlen (a)+ strlen(b)+strlen(c)+4;
	xstr[l] = '"';
	l += strlen (d);
	xstr[l+1] = '"';
    }
}

static void
new_command (char *pathname, Proc *fcn, char *cmd, char *p)
{
    // another possibility is to declare fcn(void*, void*, int, char **)
    // and then to go through our handler: sprintf (x, "Proc_%08x", fcn);
    //  Tcl_CreateCommand (interp, x, fcn, ...);
    //  sprintf (x, "%s configure -command Proc_%08x", pathname, fcn);
    //  Tcl_GlobalEval (interp, x);
    char s[500];
    sprintf (s, "%s configure %s {%s %x", pathname, cmd, JMPNAME, fcn);
    if (!p)
	cat (s, "}");
    else
	cat (s, "\"", p, "\"}");
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
static void
add_ivar (int *v)
{
    if (n_ivars == N_ivars) {
	int **i;
	N_ivars += VAR_SIZE;
	i = new int * [N_ivars];
	bcopy (i_vars, i, n_ivars*sizeof (int *));
	delete [] i_vars;
	i_vars = i;
    }
    i_vars[n_ivars++] = v;
}	
static void
add_tvar (char *v)
{
    if (n_tvars == N_tvars) {
	char **t;
	N_tvars += VAR_SIZE;
	t = new char * [N_tvars];
	bcopy (t_vars, t, n_tvars*sizeof (char *));
	delete [] t_vars;
	t_vars = t;
    }
    t_vars[n_tvars++] = v;
}
static void
add_wvar (int *v)
{
    if (n_wvars == N_wvars) {
	int **i, *j;
	N_wvars += VAR_SIZE;
	i = new int * [N_wvars];
	bcopy (w_vars, i, n_wvars*sizeof (int *));
	delete [] w_vars;
	w_vars = i;
	j = new int [N_wvars];
	bcopy (W_vars, j, n_wvars*sizeof (int));
	delete [] W_vars;
	W_vars = j;
    }
    w_vars[n_wvars] = v;
    W_vars[n_wvars++] = *v;
}

char *
Button::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Button::configure (ARG2)
{
    C_2ARG("configure");
}
void
Button::command (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-command", p);
//    char x[strlen(pathname)+50];
//    sprintf (x, "Proc_%08x", fcn);
//    Tcl_CreateCommand (interp, x, (Tcl_CmdProc *)fcn, Tk_MainWindow (interp), 0);
//    sprintf (x, "%s configure -command Proc_%08x", pathname, fcn);
//    TkError = Tcl_GlobalEval (interp, x);
}
void
Button::flash ()
{
    V_0ARG("flash");
}
void
Button::invoke ()
{
    V_0ARG("invoke");
}
void
Button::textvariable (char *v)
{
    TEXTVARIABLE;
}
char *
Entry::configure (ARG2)
{
    C_2ARG("configure");
}
void
Entry::xscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-xscrollcommand", p);
}
Bbox 
Entry::bbox (char *s)
{
    Bbox b;
    cat (pname, "bbox", s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%d %d %d %d", &b.x, &b.y, &b.width, &b.height);
    return b;
}
char *
Entry::cget (ARG1)
{
    C_1ARG("cget");
}
void
Entry::delet (ARG2)
{
    V_2ARG("delete");
}
char *
Entry::get ()
{
    C_0ARG("get");
}
int
Entry::icursor (ARG1)
{
    I_1ARG("icursor");
}
int
Entry::index (ARG1)
{
    I_1ARG("index");
}
void
Entry::insert (ARG2)
{
    V_2ARG("insert");
}
void
Entry::scan (char *s, int i)
{
    char x[10];
    sprintf (x, "%d", i);
    cat (pname, "scan", s, x);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
int
Entry::selection (ARG3)
{
    I_3ARG("selection");
}
void
Entry::textvariable (char *v)
{
    TEXTVARIABLE;
}
Fraction 
Entry::xview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "xview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
Fraction
Entry::xview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return xview (s, x);
}

char *
Frame::configure (ARG1)
{
    C_1ARG("configure");
}
char *
Frame::cget (ARG1)
{
    C_1ARG("cget");
}


char *
Toplevel::configure (ARG1)
{
    C_1ARG("configure");
}
char *
Toplevel::cget (ARG1)
{
    C_1ARG("cget");
}

char *
Label::configure (ARG4)
{
    C_4ARG ("configure");
}
char *
Label::cget (ARG1)
{
    C_1ARG("cget");
}
void
Label::textvariable (char *v)
{
    TEXTVARIABLE;
}

char *
Checkbutton::cget (ARG1)
{
    C_1ARG ("cget");
}
char *
Checkbutton::configure (ARG3)
{
    C_3ARG("configure");
}
void
Checkbutton::command (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-command", p);
}
void
Checkbutton::deselect ()
{
    V_0ARG("deselect");
}
void
Checkbutton::flash ()
{
    V_0ARG ("flash");
}
void
Checkbutton::invoke ()
{
    V_0ARG ("invoke");
}
void
Checkbutton::toggle ()
{
    V_0ARG("toggle");
}
void
Checkbutton::select ()
{
    V_0ARG("select");
}
void
Checkbutton::variable (int *v)
{
    VARIABLE;
}
void
Checkbutton::textvariable (char *v)
{
    TEXTVARIABLE;
}
char *
Radiobutton::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Radiobutton::configure (ARG1)
{
    C_1ARG("configure");
}
void
Radiobutton::command (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-command", p);
}
void
Radiobutton::flash ()
{
    V_0ARG("flash");
}
void
Radiobutton::invoke ()
{
    V_0ARG("invoke");
}
void
Radiobutton::deselect ()
{
    V_0ARG("deselect");
}
void
Radiobutton::select ()
{
    V_0ARG("select");
}
void
Radiobutton::textvariable (char *v)
{
    TEXTVARIABLE;
}
void
Radiobutton::variable (int *v)
{
    VARIABLE;
}
char *
Message::configure (ARG1)
{
    C_1ARG("configure");
}
char *
Message::cget (ARG1)
{
    C_1ARG("cget");
}
void
Scrollbar::command (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-command", p);
}
char *
Scrollbar::configure (ARG1)
{
    C_1ARG("configure");
}
char *
Scrollbar::activate ()
{
    V_0ARG("activate");
}
char *
Scrollbar::cget (ARG1)
{
    C_1ARG ("cget");
}
float
Scrollbar::delta (int i, int j)
{
    sprintf (xstr, "%s delta %d %d", pname, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return atof (interp->result);
}
char *
Scrollbar::get ()
{
    C_0ARG("get");
}
char *
Scrollbar::identify (int i, int j)
{
    sprintf (xstr, "%s identify %d %d", pname, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
Scrollbar:: set (float a, float b)
{
    sprintf (xstr, "%s set %f %f", pname, a, b);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}

void
Listbox::activate (ARG1)
{
    V_1ARG("activate");
}
Bbox 
Listbox::bbox (ARG1)
{
    Bbox b;
    cat (pname, "bbox", a);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%d %d %d %d", &b.x, &b.y, &b.width, &b.height);
    return b;
}
char *
Listbox::cget (ARG1)
{
    C_1ARG ("cget");
}
char *
Listbox::curselection ()
{
    C_0ARG("curselection");
}
void
Listbox::delet (ARG2)
{
    V_2ARG("delete");
}
char *
Listbox::get (ARG1)
{
    C_1ARG ("get");
}
int
Listbox::index (ARG1)
{
    I_1ARG ("index");
}
void
Listbox::insert (ARG3)
{
    V_3ARG("insert");
}
int
Listbox::nearest (int i)
{
    cat (pname, "nearest", i2a(i));
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return atoi (interp->result);
}
void
Listbox::scan (char *s, int i, int j)
{
    char x[20];
    sprintf (x, "%d %d", i, j);
    cat (pname, "scan", s, x);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Listbox::see (ARG1)
{
    V_1ARG("see");
}
int
Listbox::selection (ARG3)
{
    I_3ARG("selection");
}
int
Listbox::size ()
{
    I_0ARG("size");
}
Fraction
Listbox::xview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return xview (s, x);
}
Fraction 
Listbox::xview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "xview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
Fraction
Listbox::yview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return yview (s, x);
}
Fraction 
Listbox::yview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "yview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
void
Listbox::xscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-xscrollcommand", p);
}
void
Listbox::yscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-yscrollcommand", p);
}
char *
Image::configure (ARG1)
{
    C_1ARG("configure");
}
Bbox 
Text::bbox (ARG1)
{
    Bbox b;
    cat (pname, "bbox", a);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%d %d %d %d", &b.x, &b.y, &b.width, &b.height);
    return b;
}
char *
Text::cget (ARG1)
{
    C_1ARG("cget");
}
char * 
Text::configure (ARG2)
{
    C_2ARG("configure");
}

void
Text::delet (ARG2)
{
    V_2ARG("delete");
}
Area
Text::dlineinfo (ARG1)
{
    Area A;
    cat (pname, "dlineinfo", a);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%d %d %d %d %d", &A.x, &A.y, &A.width, &A.height, &A.baseline);
    return A;
}
char *
Text::dump (ARG3)
{
    C_3ARG("dump");
}
char *
Text::get (ARG2)
{
    C_2ARG("get");
}
char *
Text::image (ARG3)
{
    C_3ARG ("image");
}
char *
Text::index (ARG1)
{
    C_1ARG("index");
}
void
Text::insert (ARG3)
{
    V_3ARG("insert");
}
void
Text::mark (ARG3)
{
    V_3ARG("mark");
}
void
Text::scan (char *s, int i, int j)
{
    char x[20];
    sprintf (x, "%d %d", i, j);
    cat (pname, "scan", s, x);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
char *
Text::search (ARG4)
{
    C_4ARG("search");
}
void
Text::see (ARG1)
{
    V_1ARG("see");
}
void
Text::tag (ARG5)
{
    V_5ARG("tag");
}    
void 
Text::tag (char *s, char *p, char *q, void (*fcn)(int, char **), char *r)
{
    char y[34+(r?strlen(r):0)];
    int plus = 0;
    if (r && *r == '+')
	plus = *r++;
    if (!fcn)
	sprintf (y, "{}");
    else
	sprintf (y, "%s{%s 0x%x %s}", plus?"+":"", JMPNAME, fcn, r?r:"");
    cat (pname, "tag", s, p, q, y);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Text::window (ARG4)
{
    V_4ARG("window");
}    
Fraction
Text::xview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return xview (s, x);
}
Fraction 
Text::xview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "xview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
Fraction
Text::yview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return yview (s, x);
}
Fraction 
Text::yview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "yview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
void
Text::xscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-xscrollcommand", p);
}
void
Text::yscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-yscrollcommand", p);
}
void
Canvas::addtag (ARG2)
{
    V_2ARG("addtag");
}
Bbox 
Canvas::bbox (char *s, char *p, char *q)
{
    Bbox b;
    cat (pname, "bbox", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%d %d %d %d", &b.x, &b.y, &b.width, &b.height);
    return b;
}
void
Canvas::bind (ARG1)
{
    V_1ARG("bind");
}
void
Canvas::bind (char *s, char *q, Proc *fcn, char *p)
{
    char y[34+(p?strlen(p):0)];
    int plus= 0;
    if (p && *p == '+')
	plus = *p++;
    if (!fcn)
	strcpy (y, "{}");
    else
	sprintf (y, "%s{%s 0x%x %s}", plus?"+":"", JMPNAME, fcn, p?p:"");
    cat (pname, "bind", s, q, y);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
int
Canvas::canvasx (int a, int b)
{
    sprintf (xstr, "%s canvasx %d %d", pname, a, b);
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK;
    return atoi (interp->result);
}
int
Canvas::canvasy (int a, int b)
{
    sprintf (xstr, "%s canvasy %d %d", pname, a, b);
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK;
    return atoi (interp->result);
}
int
Canvas::canvasx (int a)
{
    sprintf (xstr, "%s canvasx %d", pname, a);
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK;
    return atoi (interp->result);
}
int
Canvas::canvasy (int a)
{
    sprintf (xstr, "%s canvasy %d", pname, a);
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK;
    return atoi (interp->result);
}
char *
Canvas::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Canvas::configure (ARG2)
{
    C_2ARG("configure");
}

void
Canvas::delet (ARG2)
{
    V_2ARG("delete");
}
char *
Canvas::coords (ARG2)
{
    C_2ARG("coords");
}
int
Canvas::create (ARG2)
{
    I_2ARG("create");
}
void
Canvas::dchars (ARG3)
{
    V_3ARG ("dchars");
}
char *
Canvas::find (ARG4)
{
    C_4ARG ("find");
}
int
Canvas::index (ARG2)
{
    I_2ARG("index");
}
void
Canvas::insert (ARG3)
{
    V_3ARG("insert");
}
char *
Canvas::itemcget (ARG2)
{
    C_2ARG("itemcget");
}
char *
Canvas::itemconfigure (ARG5)
{
    C_5ARG("itemconfigure");
}
void
Canvas::mark (ARG3)
{
    V_3ARG("mark");
}
void
Canvas::move (char *s, int i, int j)
{
    sprintf (xstr, "%s move %s %d %d", pname, s, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Canvas::move (ARG2)
{
    V_2ARG("move");
}
char *
Canvas::postscript (ARG3)
{
    C_3ARG ("postscript");
}
void
Canvas::scan (char *s, int i, int j)
{
    char x[20];
    sprintf (x, "%d %d", i, j);
    cat (pname, "scan", s, x);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
char *
Canvas::type (ARG1)
{
    C_1ARG("type");
}
void
Canvas::window (ARG4)
{
    V_4ARG("window");
}    
Fraction
Canvas::xview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return xview (s, x);
}
Fraction 
Canvas::xview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "xview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
Fraction
Canvas::yview (char *s, float f)
{
    char x[20];
    sprintf (x, "%0.3f", f);
    return yview (s, x);
}
Fraction 
Canvas::yview (char *s, char *p, char *q)
{
    Fraction b;
    cat (pname, "yview", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    sscanf (interp->result, "%f %f", &b.a, &b.b);
    return b;
}
void
Canvas::xscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-xscrollcommand", p);
}
void
Canvas::yscrollcommand (Proc *fcn, char *p)
{
    new_command (pname, fcn, "-yscrollcommand", p);
}

void
Scale::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
void
Scale::variable (int *v)
{
    VARIABLE;
}
char *
Scale::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Scale::configure (ARG2)
{
    C_2ARG("configure");
}
char *
Scale::coords (ARG2)
{
    C_2ARG("coords");
}
char *
Scale::get ()
{
    C_0ARG("get");
}
char *
Scale::get (int i, int j)
{
    sprintf (xstr, "%s get %d %d", pname, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
Scale::identify (int i, int j)
{
    sprintf (xstr, "%s identify %d %d", pname, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
Scale:: set (int i)
{
    sprintf (xstr, "%s set %d", pname, i);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Scale:: set (float f)
{
    sprintf (xstr, "%s set %g", pname, f);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Menubutton::textvariable (char *v)
{
    TEXTVARIABLE;
}
char *
Menubutton::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Menubutton::configure (ARG2)
{
    C_2ARG("configure");
}
void
Menu::postcommand (void (*fcn)())
{
}
void
Menu::tearoffcommand (Proc *fcn)
{
}
char *
Menu::configure (ARG2)
{
    C_2ARG("configure");
}
void
Menu::activate (ARG1)
{
    V_1ARG("activate");
}
void
Menu::add (ARG3)
{
    V_3ARG("add");
}
void
Menu::add (char *s, void (*fcn)(int , char **), char *a)
{
    char y[38+(a?strlen(a):0)];
    sprintf (y, "-command {%s 0x%x %s}",  JMPNAME, fcn, a?a:"");
    cat (pname, "add", s, y);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
char *
Menu::cget (ARG1)
{
    C_1ARG("cget");
}
void
Menu::delet (ARG2)
{
    V_2ARG("delete");
}
char *
Menu::entrycget (ARG1)
{
    C_1ARG("entrycget");
}
char *
Menu::entryconfigure (ARG2)
{
    C_2ARG("entryconfigure");
}
int 
Menu::index (ARG1)
{
    I_1ARG("index");
}
void
Menu::insert (ARG3)
{
    V_3ARG("insert");
}
char *
Menu::invoke (ARG1)
{
    V_1ARG("invoke");
}
void
Menu::post (int i, int j)
{
    sprintf (xstr, "%s post %d %d", pname, i, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
Menu::postcascade (ARG1)
{
    V_1ARG("postcascade");
}
char * 
Menu::type (ARG1)
{
    C_1ARG("type");
}
void
Menu::unpost ()
{
    V_0ARG("unpost");
}
void
Menu::yposition (ARG1)
{
    V_1ARG("yposition");
}
#ifdef TIX
#define C_2ARGT(x) \
    cat (pname, "subwidget", name, x, a, b);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result
#define SUBWIDGET\
    if (!sub)\
	sub = new tixsubwidget ();\
    sub->_ (pname, a);\
    return sub
#define SUBWIDGET2\
    cat (pname, "subwidget", a, b, c);\
    TkError = Tcl_GlobalEval (interp, xstr);\
    ERRORCHECK; \
    return interp->result

static void
new_tixcommand (char *pathname, char *name, Proc *fcn, char *cmd, char *p)
{
    char s[500];
    sprintf (s, "%s subwidget %s configure %s {%s %x", 
	     pathname, name, cmd, JMPNAME, fcn);
    if (!p)
	cat (s, "}");
    else
	cat (s, "\"", p, "\"}");
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}

char *
tixsubwidget::configure (ARG2)
{
    C_2ARGT("configure");
}
void
tixsubwidget::command (Proc *fcn, char *p)
{
    new_tixcommand (pname, name, fcn, "-command", p);
}
void
tixsubwidget::browsecmd (Proc *fcn, char *p)
{
    new_tixcommand (pname, name, fcn, "-browsecmd", p);
}

char *
DirList::cget (ARG1)
{
    C_1ARG("cget");
}
char *
DirList::chdir (ARG1)
{
    C_1ARG("chdir");
}
char *
DirList::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
DirList::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
DirList::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
Balloon::bind (ARG2)
{
    V_2ARG("bind");
}
char *
Balloon::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Balloon::configure (ARG2)
{
    C_2ARG("configure");
}
void
Balloon::unbind (ARG2)
{
    V_2ARG("unbind");
}

tixsubwidget *
Balloon::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
Balloon::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
ButtonBox::add (ARG2)
{
    V_2ARG("add");
}
char *
ButtonBox::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ButtonBox::configure (ARG2)
{
    C_2ARG("configure");
}
void
ButtonBox::invoke (ARG1)
{
    V_1ARG("invoke");
}
tixsubwidget *
ButtonBox::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ButtonBox::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
CheckList::getselection (ARG1)
{
    C_1ARG("getselection");
}
char *
CheckList::getstatus (ARG1)
{
    C_1ARG("getstatus");
}
tixsubwidget *
CheckList::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
CheckList::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
ComboBox::addhistory (ARG1)
{
    V_1ARG("addhistory");
}
char *
ComboBox::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ComboBox::configure (ARG2)
{
    C_2ARG("configure");
}
void
ComboBox::flash (ARG2)
{
    V_2ARG("flash");
}
void
ComboBox::insert (ARG2)
{
    V_2ARG("flash");
}
void
ComboBox::pick (ARG1)
{
    V_1ARG("pick");
}
tixsubwidget *
ComboBox::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ComboBox::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
DirSelectDialog::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
char *
DirSelectDialog::cget (ARG1)
{
    C_1ARG("cget");
}
char *
DirSelectDialog::configure (ARG2)
{
    C_2ARG("configure");
}
void
DirSelectDialog::popup ()
{
    V_0ARG("popup");
}
tixsubwidget *
DirSelectDialog::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
DirSelectDialog::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
LabelEntry::cget (ARG1)
{
    C_1ARG("cget");
}
char *
LabelEntry::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
LabelEntry::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
LabelEntry::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
FileSelectDialog::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
char *
FileSelectDialog::cget (ARG1)
{
    C_1ARG("cget");
}
char *
FileSelectDialog::configure (ARG2)
{
    C_2ARG("configure");
}
void
FileSelectDialog::popup ()
{
    V_0ARG("popup");
}
void
FileSelectDialog::popdown ()
{
    V_0ARG("popup");
}
tixsubwidget *
FileSelectDialog::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
FileSelectDialog::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
FileSelectBox::browsecmd (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-browsecmd", s);
}
void
FileSelectBox::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
char *
FileSelectBox::cget (ARG1)
{
    C_1ARG("cget");
}
char *
FileSelectBox::configure (ARG2)
{
    C_2ARG("configure");
}
void
FileSelectBox::filter ()
{
    V_0ARG("filter");
}
void
FileSelectBox::invoke ()
{
    V_0ARG("invoke");
}
tixsubwidget *
FileSelectBox::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
FileSelectBox::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
ExFileSelectBox2::browsecmd (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-browsecmd", s);
}
void
ExFileSelectBox2::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
char *
ExFileSelectBox2::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ExFileSelectBox2::configure (ARG2)
{
    C_2ARG("configure");
}
void
ExFileSelectBox2::filter ()
{
    V_0ARG("filter");
}
void
ExFileSelectBox2::invoke ()
{
    V_0ARG("invoke");
}
tixsubwidget *
ExFileSelectBox2::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ExFileSelectBox2::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
ScrolledTList::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ScrolledTList::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
ScrolledTList::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ScrolledTList::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
ScrolledHList::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ScrolledHList::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
ScrolledHList::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ScrolledHList::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
ScrolledListBox::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ScrolledListBox::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
ScrolledListBox::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ScrolledListBox::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
Meter::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Meter::configure (ARG2)
{
    C_2ARG("configure");
}
void
OptionMenu::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
void
OptionMenu::add (ARG2)
{
    V_2ARG("add");
}
char *
OptionMenu::cget (ARG1)
{
    C_1ARG("cget");
}
char *
OptionMenu::configure (ARG2)
{
    C_2ARG("configure");
}
void
OptionMenu::delet (ARG1)
{
    V_1ARG("delete");
}
void
OptionMenu::disable (ARG1)
{
    V_1ARG("disable");
}
void
OptionMenu::enable (ARG1)
{
    V_1ARG("enable");
}
char *
OptionMenu::entrycget (ARG2)
{
    C_2ARG("entrycget");
}
char *
OptionMenu::entryconfigure (ARG2)
{
    C_2ARG("entryconfigure");
}
char *
OptionMenu::entries ()
{
    C_0ARG("entries");
}
tixsubwidget *
OptionMenu::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
OptionMenu::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
ScrolledWindow::cget (ARG1)
{
    C_1ARG("cget");
}
char *
ScrolledWindow::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
ScrolledWindow::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
ScrolledWindow::subwidget (ARG3)
{
    SUBWIDGET2;
}
char *
Control::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Control::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
Control::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
Control::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
Control::update ()
{
    V_0ARG ("update");
}
void
Control::invoke ()
{
    V_0ARG ("invoke");
}
void
Control::decr ()
{
    V_0ARG ("decr");
}
void
Control::incr ()
{
    V_0ARG ("incr");
}
void
Control::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
void
Control::decrcmd (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-decrcmd", s);
}
void
Control::validatecmd (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-validatecmd", s);
}
void
Control::variable (char *v)
{
    TEXTVARIABLE;
}
char *
Select::cget (ARG1)
{
    C_1ARG("cget");
}
char *
Select::configure (ARG2)
{
    C_2ARG("configure");
}
tixsubwidget *
Select::subwidget (ARG1)
{
    SUBWIDGET;
}
char *
Select::subwidget (ARG3)
{
    SUBWIDGET2;
}
void
Select::invoke ()
{
    V_0ARG ("invoke");
}
void
Select::command (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-command", s);
}
void
Select::validatecmd (Proc *fcn, char *s)
{
    new_command (pname, fcn, "-validatecmd", s);
}
void
Select::variable (char *v)
{
    TEXTVARIABLE;
}
void
Select::add (ARG2)
{
    V_2ARG("add");
}
#endif // TIX

Button
TkButton (char *s, char *p)
{
    static Button *o = new Button;
    if (!init)
	initialize ();
    cat ("button", s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}

Entry
TkEntry (char *s, char *p, char *q)
{
    static Entry *o = new Entry;
    if (!init)
	initialize ();
    cat ("entry", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Frame
TkFrame (char *s, char *p)
{
    static Frame *o = new Frame;
    if (!init)
	initialize ();
    cat ("frame" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Toplevel
TkToplevel (char *s, char *p)
{
    static Toplevel *o = new Toplevel;
    if (!init)
	initialize ();
    cat ("toplevel", s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Label
TkLabel (char *s, char *p, char *q, char *r)
{
    static Label *o = new Label;
    if (!init)
	initialize ();
    cat ("label" , s, p, q, r);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Checkbutton
TkCheckbutton (char *s, char *p)
{
    static Checkbutton *o = new Checkbutton;
    if (!init)
	initialize ();
    cat ("checkbutton", s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Radiobutton
TkRadiobutton (char *s, char *p, char *q, char *r, char *t)
{
    static Radiobutton *o = new Radiobutton;
    if (!init)
	initialize ();
    cat ("radiobutton", s, p, q, r, t);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Message
TkMessage (char *s, char *p)
{
    static Message *o = new Message;
    if (!init)
	initialize ();
    cat ("message" , p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Scrollbar
TkScrollbar (char *s, char *p)
{
    static Scrollbar *o = new Scrollbar;
    if (!init)
	initialize ();
    cat ("scrollbar" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Listbox
TkListbox (char *s, char *p)
{
    static Listbox *o = new Listbox;
    if (!init)
	initialize ();
    cat ("listbox" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Image
TkImage (char *s, char *p, char *q)
{
    static Image *o = new Image;
    if (!init)
	initialize ();
    cat ("image", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Text
TkText (char *s, char *p, char *q)
{
    static Text *o = new Text;
    if (!init)
	initialize ();
    cat ("text" , s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Canvas
TkCanvas (char *s, char *p, char *q)
{
    static Canvas *o = new Canvas;
    if (!init)
	initialize ();
    cat ("canvas" , s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Scale
TkScale (char *s, char *p)
{
    static Scale *o = new Scale;
    if (!init)
	initialize ();
    cat ("scale" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Menubutton
TkMenubutton (char *s, char *p)
{
    static Menubutton *o = new Menubutton;
    if (!init)
	initialize ();
    cat ("menubutton" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
Menu
TkMenu (char *s, char *p)
{
    static Menu *o = new Menu;
    if (!init)
	initialize ();
    cat ("menu" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;
}
#ifdef TIX
DirList 
tixDirList (char *s, char *p)
{
    static DirList *o = new DirList;
    if (!init)
	initialize ();
    cat ("tixDirList" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
Balloon
tixBalloon (char *s, char *p)
{
    static Balloon *o = new Balloon;
    if (!init)
	initialize ();
    cat ("tixBalloon" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ButtonBox 
tixButtonBox(char *s, char *p)
{
    static ButtonBox *o = new ButtonBox;
    if (!init)
	initialize ();
    cat ("tixButtonBox" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
CheckList 
tixCheckList (char *s, char *p)
{
    static CheckList *o = new CheckList;
    if (!init)
	initialize ();
    cat ("tixCheckList" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ComboBox 
tixComboBox (char *s, char *p)
{
    static ComboBox *o = new ComboBox;
    if (!init)
	initialize ();
    cat ("tixComboBox" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
DirSelectDialog
tixDirSelectDialog (char *s, char *p)
{
    static DirSelectDialog *o = new DirSelectDialog;
    if (!init)
	initialize ();
    cat ("tixDirSelectDialog" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
LabelEntry
tixLabelEntry (char *s, char *p)
{
   static LabelEntry *o = new LabelEntry;
     if (!init)
	initialize ();
    cat ("tixLabelEntry" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
FileSelectDialog
tixFileSelectDialog (char *s, char *p)
{
    static FileSelectDialog *o = new FileSelectDialog;
    if (!init)
	initialize ();
    cat ("tixFileSelectDialog" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
FileSelectBox
tixFileSelectBox (char *s, char *p)
{
    static FileSelectBox *o = new FileSelectBox;
    if (!init)
	initialize ();
    cat ("tixFileSelectBox" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ExFileSelectBox2
tixExFileSelectBox2 (char *s, char *p)
{
    static ExFileSelectBox2 *o = new ExFileSelectBox2;
    if (!init)
	initialize ();
    cat ("tixExFileSelectBox2" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ScrolledTList
tixScrolledTList (char *s, char *p)
{
    static ScrolledTList *o = new ScrolledTList;
    if (!init)
	initialize ();
    cat ("tixScrolledTList" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ScrolledHList
tixScrolledHList (char *s, char *p)
{
    static ScrolledHList *o = new ScrolledHList;
    if (!init)
	initialize ();
    cat ("tixScrolledHList" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ScrolledListBox
tixScrolledListBox (char *s, char *p)
{
    static ScrolledListBox *o = new ScrolledListBox;
    if (!init)
	initialize ();
    cat ("tixScrolledListBox" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
Meter
tixMeter (char *s, char *p)
{
    static Meter *o = new Meter;
    if (!init)
	initialize ();
    cat ("tixMeter" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
OptionMenu 
tixOptionMenu (char *s, char *p)
{
    static OptionMenu *o = new OptionMenu;
    if (!init)
	initialize ();
    cat ("tixOptionMenu" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
ScrolledWindow
tixScrolledWindow (char *s, char *p)
{
    static ScrolledWindow *o = new ScrolledWindow;
    if (!init)
	initialize ();
    cat ("tixScrolledWindow" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
Control
tixControl (char *s, char *p)
{
    static Control *o = new Control;
    if (!init)
	initialize ();
    cat ("tixControl" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
Select
tixSelect (char *s, char *p)
{
    static Select *o = new Select;
    if (!init)
	initialize ();
    cat ("tixSelect" , s, p);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    PNAME;
    return *o;   
}
char *
tixForm (char *a, char *b, char *c)
{
    cat ("tixForm", a, b, c);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
#endif // TIX

char *
TkBind (char *tag, char *s)
{
    if (!init)
	initialize ();
    cat ("bind", tag, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkFocus (char *p, char *s)
{
    if (!init)
	initialize ();
    cat ("focus", p, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}

char *
TkBind (char *tag, char *s, Proc *fcn, char *p)
{
    char y[34+(p?strlen(p):0)];
    int plus= 0;
    if (p && *p == '+')
	plus = *p++;
    if (!fcn)
	strcpy (y, "{}");
    else
	sprintf (y, "%s{%s 0x%x %s}", plus?"+":"", JMPNAME, fcn, p?p:"");
    if (!init)
	initialize ();
    cat ("bind", tag, s, y);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    //    alternative: char *argv[4];
    //    int argc = 4;
    //    argv[0] = "bind"; argv[1] = tag; argv[2]= s; argv[3] = y;
    //    Tk_BindCmd(Tk_MainWindow (interp), interp, argc, argv);
    return "";
}
char *
TkWm (char *s, char *p, char *q)
{
    if (!init)
	initialize ();
    cat ("wm", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkDestroy (char *s, char *p, char *q)
{
    if (!init)
	initialize ();
    cat ("destroy", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
TkPack (char *s, char *p, char *q)
{
    if (!init)
	initialize ();
    cat ("pack", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
TkPlace (char *s, char *p, char *q)
{
    if (!init)
	initialize ();
    cat ("place", s, p, q);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
char *
TkAfter (int i, void (*fcn)())
{
    if (!init)
	initialize ();
    if (!fcn)
	sprintf (xstr, "after %d", i);
    else
	sprintf (xstr, "after %d {%s %x}", i, JMPNAME, fcn);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkAfter (int i, char *s, int j)
{
    if (!init)
	initialize ();
    sprintf (xstr, "after %d %s %d", i, s, j);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkAfter (int i, char *s)
{
    if (!init)
	initialize ();
    sprintf (xstr, "after %d %s", i, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkWinfo (char *p, char *s)
{
    if (!init)
	initialize ();
    cat ("winfo", p, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
TkBell ()    
{
    if (!init)
	initialize ();
    strcpy (xstr, "bell");
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
void
TkWait (int *v)
{
    char s[20];
    sprintf (s, "%s%x", VARNAME, v);
    Tcl_TraceVar (interp, s, TCL_TRACE_WRITES, TraceVars, 0);
    add_wvar (v);
    cat ("tkwait variable", s);
    TkError = Tcl_GlobalEval (interp, xstr);
//    ERRORCHECK;
}
void
TkWait (char *p, char *s)
{
    cat ("tkwait", p, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}

char *
TkGrab (char *p, char *s)
{
    cat ("grab", p, s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
TkPopup (char *p, char *s, char *t, char *u)
{
    cat ("tk_popup", p, s, t, u);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
}
char *
TkClock (char *s)
{
    if (!init)
	initialize ();
    cat ("clock", s);
    TkError = Tcl_GlobalEval (interp, xstr);
    ERRORCHECK;
    return interp->result;
}
void
TkUpdate (char *s)
{
    char *argv[] = {"..", ".."};
    char x[40]; // don't use xstr !!!!!
    strcpy (x, "update ");
    if (s)
	strcat (x, s);
    TkError = Tcl_GlobalEval (interp, x);
    ERRORCHECK;
    Proc_Handler (0, 0, 0, argv);
}   
char *
TkTcl (char *s, Proc *f1, Proc *f2, Proc *f3, Proc *f4, Proc *f5)
{
    Proc *f[5] = {f1, f2, f3, f4, f5};
    char script[strlen(s)+130], cmd[25];
    char *p = script;
    char *ss = s;
    int n;

    if (!init)
	initialize ();

    while (*s) {
	if (*s == '%' && s[1] == '_') {
	    n = s[2] - '0';
	    if (n > 5 || n < 1 || !f[n-1]) {
		fprintf(stderr, "Wrong function call in script: %s\n", ss);
		exit (1);
	    } else {
		char *q = cmd;
		sprintf (cmd, "%s %x", JMPNAME, f[n-1]);
		while (*q)
		    *p++ = *q++;
		s += 3;
	    }
	} else
	    *p++ = *s++;
    }
    *p = 0;
    TkError = Tcl_GlobalEval (interp, script);
    ERRORCHECK;
    return interp->result;
}
int 
TkDialog (char *w, char *t, char *txt, char *b, int d, char *s1, char *s2,
	  char *s3, char *s4)
{
    cat ("tk_dialog", w, t, txt, *b ? b : (char *)"{}", i2a (d), s1, s2, s3, s4);
    TkError = Tcl_GlobalEval(interp, xstr);
    ERRORCHECK;
    return atoi (interp->result);
}
char *
TkGetOpenFile (char *a, char *b, char *c)
{
    cat ("tk_getOpenFile", a, b, c);
    TkError = Tcl_GlobalEval(interp, xstr);
    ERRORCHECK;
    return interp->result;
}
char *
TkGetSaveFile (char *a, char *b, char *c)
{
    cat ("tk_getSaveFile", a, b, c);
    TkError = Tcl_GlobalEval(interp, xstr);
    ERRORCHECK;
    return interp->result;
}
    

char *
CXXTkIndex::n (int i)
{
    return i2a (i);
}
char *
CXXTkIndex::x (int i)
{
    char *s = i2a (i);
    *--s = '@';
    return s;
}
char *
CXXTkIndex::xy (int i, int j)
{
    static char x[20];
    char *s = i2a (i);
    *--s = '@';
    strcpy (x, s);
    s = i2a (j);
    *--s = ',';
    strcat (x, s);
    return x;
}
char *
CXXTkIndex::lc (int i, int j)
{
    static char x[20];
    char *s = i2a (i);
    strcpy (x, s);
    s = i2a (j);
    *--s = '.';
    strcat (x, s);
    return x;
}
void
TkSelect (int fd, char *mode, Tcl_FileProc proc)
{
    if (!mode)
	Tcl_DeleteFileHandler (fd);
    else {
	int mask = 0;
	while (*mode) {
	    if (*mode == 'r')
		mask |= TCL_READABLE;
	    else if (*mode == 'w')
		mask |= TCL_WRITABLE;
	    else if (*mode == 'e')
		mask |= TCL_EXCEPTION;
	    mode++;
	}
	Tcl_CreateFileHandler (fd, mask, proc, 0);
    }
}
void
TkDiag (int i) {CXX_Tk_diag = i;}
int Tk_error () {return TkError;}
void
TkResult (char *s, char *append)
{
    if (!append)
	Tcl_SetResult (interp, s, TCL_VOLATILE);
    else
	Tcl_AppendResult (interp, s, append, 0);
}
