// Tcl interpreter object.
// Copyright 1991 Manticore, Inc.  All Rights Reserved.
// 
// You may freely copy, distribute and reuse the code in this example.
// Manticore disclaims any warranty of any kind, expressed or
// implied, as to its fitness for any particular use.

#import "TclObj.h"
#import "TclTV.h"
#import "TclApp.h"
#import <appkit/Application.h>
#import <objc/typedstream.h>
#import <objc/NXStringTable.h>
#import <appkit/FontManager.h>
#import <objc/HashTable.h>
#import <string.h>
#import <ldsyms.h>
#import <sys/loader.h>

// this is here 'cause I don't want to include libc.h ... too slow
extern char *getsectdata(	const char *segname, 
	const char *sectname, 
	int *size);


@implementation TclObj:Object

- init
{
	char buf[32];
	char *init;
	int size;

	
	[super init];
	textView = NULL;
	tvList = [[List alloc] init];

	// create a tcl interpreter
	tclinterp = Tcl_CreateInterp();
	if (tclinterp == NULL) {
		fprintf(stderr, "Failed to create tcl interpreter\n");
	} else {
		addTclCmds(tclinterp, self);
		sprintf(buf, "%d", self);
		Tcl_SetVar(tclinterp, "TclObj", buf, 1);
		sprintf(buf, "%d", NXApp);
		Tcl_SetVar(tclinterp, "NXApp", buf, 1);
		if (init = (char *)getsectdata("TCL", "init", &size)) {
			[self doCmd:init:NULL];
		}
	}
	return self;
}
	
- msg:sender
{
	char buf[32];
	
	sprintf(buf, "msg %d", sender);
	[self doCmd:buf:NULL];
    return self;
}

- createTextView:sender
{   
	NXRect wRect;
	id newText;
	
	wRect.origin.x = wRect.origin.y = 200.0;
	wRect.size.width = 500.0;
	wRect.size.height = 300.0;
	newText = [[TclTV alloc] initFrame:&wRect];
	[[newText window] setDelegate:self];
	[newText setCmdHandler:self];
	
	[tvList addObject:newText];
	if (textView == NULL) {
		textView = newText;
	}   
    return self;
}

- doCmd:(const char *)cmd :(id)tv
{
	int result;
	char num[10];
	
	if (tclinterp) {
		result = Tcl_Eval(tclinterp, cmd, 0, NULL);
		if (tv == NULL) {
			tv = textView;
		}
		if (tv) {
			if (result == TCL_OK) {
				if (*tclinterp->result != 0) {
					[tv addText:tclinterp->result];
					[tv addText:"\n"];
				}
			} else {
				[tv addText:"Error "];
				if (result != TCL_ERROR) {
					sprintf(num, "(%d) ", result);
					[tv addText:num];
				}
				if (*tclinterp->result != 0) {
					[tv addText:tclinterp->result];
				}
				[tv addText:"\n"];
			}
			[tv cursorVisible];
		}
	}
	return self;
}

- addText:(const char *)text
{

	if (textView) {
		[textView addText:text];
	}
	return self;
}

- cursorVisible
{

	if (textView) {
		[textView cursorVisible];
	}
	return self;
}

- viewLeaving:sender
{

	[tvList removeObject:sender];
	if (sender == textView) {
		textView = [tvList objectAt:0];
	}
	return self;
}

- forward:(SEL)aSelector :(marg_list)argFrame
{
	char buf[32];
	
	sprintf(buf, "forward %d", (int)aSelector);
	[self doCmd:buf:NULL];
    return self;
}

- free
{

	[[tvList freeObjects] free];
	Tcl_DeleteInterp(tclinterp);
    return [super free];
}

@end
