
#import "SCMTextView.h"
#import "SchemeDelegate.h"

@implementation NSTextView (Misc)

- placeCursorAtEnd
{
    NSRange range = { [[self string] length], 0 };
    [self setSelectedRange:range];
    return self;
}

- selectLineAtPos:(int)pos
{
    NSString *data = [self string];
    
    unsigned startInd, endInd;
    [data getLineStart:&startInd end:&endInd 
	  contentsEnd:NULL forRange:NSMakeRange(pos, 0)];
    [self setSelectedRange:NSMakeRange(startInd, endInd-startInd)];

    return self;
}

@end

@implementation SCMTextView

- (void)insertText:(id)aString
{
    int inslen = [aString length];
    unichar ch = [aString characterAtIndex:0];
    NSString *modified = @"", *single;

    if(inslen == 1 && ch==NSNewlineCharacter){
        NSString *data = [self string];
        NSRange range = [self selectedRange];
        NSCharacterSet *charset = 
            [NSCharacterSet whitespaceAndNewlineCharacterSet];
        int pos = range.location;
        BOOL newline = NO;
        
        while(pos>0){
            pos--;
            if([data characterAtIndex:pos]==NSNewlineCharacter){
                newline = YES;
                break;
            }
        }

        if(newline == YES){
            int len = 0; int max = [data length];
            while(pos+len<max &&
                  [charset characterIsMember:
                               (ch = [data characterAtIndex:(pos+len)])]){
                single = [[NSString alloc] initWithCharacters:&ch length:1];
                modified = [modified stringByAppendingString:single];
                // [single autorelease];
                                  
                len++;
            }

            return [super insertText:modified];
        }
    }
    else if(inslen==1 && ch==NSTabCharacter){
        ch = ' ';
        single = [[NSString alloc] initWithCharacters:&ch length:1];
        modified = [modified stringByAppendingString:single];
        modified = [modified stringByAppendingString:single];
        // [single autorelease];
        return [super insertText:modified];
    }

    return [super insertText:aString];
}

@end

@implementation SCMInteractive

- (id)initWithFrame:(NSRect)frameRect
{
    lastRetrieved = 0;
    return [super initWithFrame:frameRect];
}


- (void)insertText:(id)aString
{
    if([self selectedRange].location<lastRetrieved){
	NSRange range = { [[self string] length], 0 };
	[self setSelectedRange:range];
    }

    [super insertText:aString];
}

- (void)paste:(id)sender
{
    if([self selectedRange].location<lastRetrieved){
	NSRange range = { [[self string] length], 0 };
	[self setSelectedRange:range];
    }

    [super paste:sender];
}

- (NSString *)getSuffix
{
    NSString *str = [super string];
    NSString *suffix = [str substringFromIndex:lastRetrieved];
    
    lastRetrieved = [str length];
    return suffix;
}

- (void)setString:(NSString *)aString
{
    lastRetrieved = [aString length];
    [super setString:aString];
}

- (void)appendString:(NSString *)aString
{
    unsigned int len = [[super string] length];
    NSRange range = {len, 0};

    lastRetrieved += [aString length];
    [self replaceCharactersInRange:range withString:aString];
}

- (void)keyDown:(NSEvent *)theEvent
{
    NSString *chars = [theEvent characters];
    unsigned modifiers = [theEvent modifierFlags];
    int len = [chars length];
    unichar ch = [chars characterAtIndex:0];
    BOOL rep = [theEvent isARepeat];
    
    if((ch==NSNewlineCharacter || ch==NSCarriageReturnCharacter) &&
       len==1 && (modifiers & NSControlKeyMask)){
	NSString *sfx = [self getSuffix];

	NSPasteboard *pb = [NSPasteboard generalPasteboard];
	[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType]
	    owner:nil];
	[pb setString:sfx forType:NSStringPboardType];

        BOOL res = 
	    [[self delegate] processString:sfx
			     mode:MODE_INTERACTIVE];
        if(res==NO){
            NSRunAlertPanel(@"Error", [(VScheme *)[self delegate] errmsg], 
                            @"Ok", nil, nil);
        }
        return;
    }
    else if(ch==NSBackspaceCharacter && 
            (len==1 || rep==YES) &&
            [self selectedRange].location<lastRetrieved+len){
        NSBeep();
        return;
    }
    else if(ch==NSDeleteFunctionKey &&
            (len==1 || rep==YES) &&
            [self selectedRange].location<lastRetrieved){
        NSBeep();
        return;
    }

    return [super keyDown:theEvent];
}

- (void)delete:(id)sender
{
    NSRange range = [self rangeForUserTextChange];
    if(range.location != NSNotFound &&
       range.location >= lastRetrieved){
        [super delete:sender];
    }
    else{
        NSBeep();
    }
}

@end

