/*	This file is part of the XText package (version 0.8)
	Mike Dixon, April 1992
	
	Copyright (c) 1992 Xerox Corporation.  All rights reserved.

	Use and copying of this software and preparation of derivative works based
	upon this software are permitted.  This software is made available AS IS,
	and Xerox Corporation makes no warranty about the software or its
	performance.
*/

#import "XTAction.h"
#import "XText.h"
#import "ErrorStream.h"
#import <appkit/Application.h>
#import <stdio.h>
#import <string.h>

@implementation XTAction

static id undefined_action = 0;

+ undefinedAction
{
	if (!undefined_action)
		undefined_action = [[XTAction allocFromZone:[NXApp zone]] init];
	return undefined_action;
}

- applyTo:xtext event:(NXEvent *)event
{
	[xtext unboundKey];
	return self;
}

@end

@implementation XTMsg0Action

- initSel:(SEL)sel
{
	[super init];
	action_sel = sel;
	return self;
}

- applyTo:xtext event:(NXEvent *)event
{
	return [xtext perform:action_sel];
}

@end

@implementation XTMsg1Action

- initSel:(SEL)sel arg:(int)arg
{
	[super init];
	action_sel = sel;
	action_arg = arg;
	return self;
}

- applyTo: xtext event:(NXEvent *)event
{
	return [xtext perform:action_sel with:(id)action_arg];
}

@end

@implementation XTMsg2Action

- initSel:(SEL)sel arg:(int)arg1 arg:(int)arg2
{
	[super init];
	action_sel = sel;
	action_arg1 = arg1;
	action_arg2 = arg2;
	return self;
}

- applyTo: xtext event:(NXEvent *)event
{
	return [xtext perform:action_sel
					with:(id)action_arg1 with:(id)action_arg2];
}

@end

@implementation XTDispatchAction

- initBase:(const char *)base estream:errs
{
	keyCode k;

	[super init];
	for (k=0; k<KEY_CODES; ++k)
		actions[k] = nil;
	if (!strcmp(base,"none")) {}
//	else if (!strcmp(base,"other_base"))
//		initbase_other_base(actions)
	else {
		if ((*base != 0) && strcmp(base,"emacs")) {
			char msg[100];
			
			sprintf(msg, "Unknown base '%.32s', using emacs instead", base);
			[(errs ? errs : [ErrorStream default]) report:msg];
		}
		initbase_emacs(actions, [self zone]);
	}
	return self;
}

- bindKey:(keyCode)key toAction:action estream:errs
{
	if ((key < 0) || (key >= KEY_CODES)) {
		char msg[40];
		sprintf(msg, "Invalid key code: %d", key);
		[(errs ? errs : [ErrorStream default]) report:msg];
	} else
		actions[key] = action;
	return self;
}

- applyTo:xtext event:(NXEvent *)event
{
	keyCode k = (event->data.key.keyCode << 4);
	id action;

	if ((k >= 0) && (k < KEY_CODES)) {
		if (event->flags & NX_CONTROLMASK)   k += 1;
		if (event->flags & NX_SHIFTMASK)     k += 2;
		if (event->flags & NX_ALTERNATEMASK) k += 4;
		if (event->flags & NX_COMMANDMASK)   k += 8;
		action = actions[k];
		if (action)
			return [action applyTo:xtext event:event];
	}
	return nil;
}

@end

@implementation XTEventMsgAction

- initSel:(SEL)sel
{
	[super init];
	action_sel = sel;
	return self;
}

- applyTo:xtext event:(NXEvent *)event
{
	return [xtext perform:action_sel with:(id)event];
}

@end

@implementation XTSeqAction

- initLength:(int)len actions:(XTAction **)acts
{
	[super init];
	length = len;
	actions = acts;
	return self;
}

- applyTo:xtext event:(NXEvent *)event
{
	int i;

	for (i=0; i<length; ++i)
		[actions[i] applyTo:xtext event:event];
	return self;
}

@end
