//
//  iTableView.m
//  ColoredRowTableViewExample
//
//  Created by Bradford Brack on Tue May 14 2002.
//  Copyright (c) 2002 Apple. All rights reserved.
//
//  Modified by Tony Arnold on Sun Apr 27 2003.
//	Updated using code from http://www.cocoadev.com/index.pl?AlternatingRowColors created by Dave Thorup.
//	This should fix the resize problems.
//
//  Modified by Tony Arnold on Sun Aug 25 2002.
//	I've added:
//		* coloring of rows to reflect the current system preference;
//		* iTunes style row hightlighting.
//
//	Problems/Comments on this version, please contact tonyarnold@objc-source.org
//
//  Modified by Noah Sorscher on Sat Jun 12 2003
//	I've added:
//		* enter key exits editing without changing row selection
//		* column selection highlights all the cells in the column
//		* restored keyboard focus ring
//		* now asks NSApp delegate for color instead of data source (#define)
//		* allows delegate to set text color of cells (except selected row)
//	Sun Jun 29 2003:
//		* keep state variables for various respondsToSelector calls
//		so they don't have to be called for every redraw
//		(suggested by h.friederich@gmx.ch)
//      Sat Nov 29 2003:
//              * tableHeaderView sends optional tableView:rightClickWithEvent: to table delegate

#import "iTableView.h"

#define COLOR_SOURCE [NSApp delegate]
    // if COLOR_SOURCE is something other than the tableview's data source or delegate, the respondsToSelector information will not be accurate when changing it at runtime (like changing who the app delegate is).  It's all ok if the new COLOR_SOURCE implements the same methods as the old one though.
/*
@interface NSCell (additions)
- (int)imageRow;
- (void)setPictureTime:(BOOL)flag;
@end

@implementation NSCell (additions)
- (void)setWrapsObj:(NSNumber *)flag
{
    [self setWraps:[flag boolValue]];
}
@end

@interface NSTextView (additions)
- (void)setSelectedRangeData:(NSData *)range;
@end

@implementation NSTextView (additions)
- (void)setSelectedRangeData:(NSData *)range
{
    NSRange *p = (NSRange *)[range bytes];
    NSRange r = *p;
    int length = [[self string] length];
    if (r.location > length) r.location = length;
    if (r.location + r.length > length) r.length = length - r.location;
    [self setSelectedRange:r];
}
@end
*/
@implementation iTableView

- (void) awakeFromNib{
    //NSLog(@"iTableView");
    iTableHeaderView		*cthv;
    NSTableHeaderView 		*thv;
    
    thv = [self headerView];
    cthv = [[iTableHeaderView alloc] initWithFrame:[thv frame]];
    [cthv setTableView:self];
    [cthv retain];
    [self setHeaderView:cthv];
    
    //	for the keyboard focus ring
    rowFocus = colFocus = -1;
    lastEditedColumn = 0;
    
    NSString *aName = [self autosaveName];
    
    grows = YES;
    //sorting = NO;
    sizesToFit = YES;
    editsOnEnter = NO;
    didDelete = NO;
    
    oldDataSource = oldDelegate = nil;
    partialString = nil;
    
    curEditedText = nil;
    
    [self queryDataAndColorSources];
}

- (id) init{
    [super init];
    return self;
}
- (id) initWithFrame:(NSRect) r{
    [super initWithFrame:r];
    return self;
}
- (id) initWithCoder:(NSCoder *) coder{
    [super initWithCoder:coder];
    return self;
}
- (void) dealloc {
    [[self headerView] release];
    [super dealloc];
}

- (IBAction)clear:(id)sender
{
    if (rowFocus != -1 ) // a cell is being edited, let it take over cut/copy/paste
        return;
    if ([[self delegate] respondsToSelector:@selector(clearTableView:)])
        [[self delegate] clearTableView:self];
}

- (IBAction)cut:(id)sender
{
    if (rowFocus != -1 ) // a cell is being edited, let it take over cut/copy/paste
        return;
    if ([[self delegate] respondsToSelector:@selector(cutTableView:)])
        [[self delegate] cutTableView:self];
}

- (void)setGrowsFrames:(BOOL)flag
{
    grows = flag;
}

- (BOOL)growsFrames
{
    return grows;
}

- (void)setSizesToFit:(BOOL)flag
{   sizesToFit = flag;  }

- (BOOL)sizesToFit
{   return sizesToFit;  }

- (void)sizeLastColumnToFit
{
    if (!sizesToFit)
        return;  // now we just want to disable this resizing
    //float lastWidth = [[[self tableColumns] lastObject] width];
    [super sizeLastColumnToFit];
    //float newWidth = [[[self tableColumns] lastObject] width];
    //if (lastWidth > newWidth)
    //    [[[self tableColumns] lastObject] setWidth:lastWidth];
}


// ----------------------------------------------------------------------------------------
// Animated Sort support -- from "TableTester" at http://www.gigliwood.com/tabletester/
// ----------------------------------------------------------------------------------------
/*
- (void) setSorting:(BOOL)flag
{
    sorting = flag;
}

/*"	Override NSTableView's method.  Let the delegate determine what the rectangle for a given row is, if that delegate responds to the selector to do so.  If animation is going on, it will probably return a value other than the default.
"* /
- (NSRect)rectOfRow:(int)rowIndex
{
	NSRect theDefaultRect = [super rectOfRow:rowIndex];
        //NSLog(@"rectOfRow -> %@", [[self delegate] className]);
        //return theDefaultRect;
	if ([[self delegate] respondsToSelector:@selector(tableView:rectOfRow:defaultRect:)])
	{
            //NSLog(@"rightCall");
		return [[self delegate] tableView:self rectOfRow:rowIndex defaultRect:theDefaultRect];
	}
	else
	{
            //NSLog(@"wrongCall");
		return theDefaultRect;
	}
}

/*"	Return the default NSTableView's version of the rectangle for a given row; this method is provided so we can determine the rectangle as if animation weren't happening.
"* /
- (NSRect)unanimatedRectOfRow:(int)rowIndex
{
	return [super rectOfRow:rowIndex];
}

/*"	Override NSTableView's method.  Let the delegate determine what the range of rows is for a given rectangle, if that delegate responds to the selector to do so.  If animation is going on, it will probably return a value other than the default.
"* /
- (NSRange)rowsInRect:(NSRect)inRect

{
	NSRange theDefaultRange = [super rowsInRect:inRect];
        //return theDefaultRange;
	if ([[self delegate] respondsToSelector:@selector(tableView:rowsInRect:defaultRange:)])
	{
		return [[self delegate] tableView:self rowsInRect:inRect defaultRange:theDefaultRange];
	}
	else
	{
		return theDefaultRange;
	}
}

// end animated sort support*/
/*
// This is handled by the cell's drawRect now.
- (void)drawGridInClipRect:(NSRect)rect
{
    //Do nothing...
}
*/
- (void)drawFocusRing
{
//	draw the keyboard focus ring for the cell that is being edited
    if (rowFocus == -1 || colFocus == -1) return;
    NSRect cellFrame = [self frameOfCellAtColumn:colFocus row:rowFocus];
    //NSLog(@"%g, %g, %gx%g", cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
    [NSGraphicsContext saveGraphicsState];
    NSSetFocusRingStyle(NSFocusRingOnly);
    NSRectFillUsingOperation(cellFrame, NSCompositeSourceOver);
    [NSGraphicsContext restoreGraphicsState];
}
/*
// Draw the empty areas
- (void) drawRect:(NSRect)rect{
    //NSLog(@"drawRect:%gx%g(%g,%g)", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
    // if (sorting) return [super drawRect:rect];
    NSRect 	rowRect, nextRect;
    NSSize	cellSpacing;
    int		countRows, row;
    float	height;
    BOOL	isOddRow;
    float	firstBlankRowYPos;
    NSColor	*rowColor;

    // draw the populated rows
    [super drawRect:rect];

    // draw remaining lines in blank area
    countRows = [[self dataSource] numberOfRowsInTableView:self];
    rowRect = [self rectOfRow:countRows-1];
    cellSpacing = [self intercellSpacing];
    height = [self rowHeight]+cellSpacing.height;
    nextRect.origin.x = rect.origin.x;
    nextRect.origin.y = rowRect.origin.y+height;
    nextRect.size.width = rect.size.width;
    nextRect.size.height=height;
    if (countRows==0) {
        isOddRow = TRUE;
        nextRect.origin.y = 0;
    } else {
        isOddRow = ((countRows%2)==0); // next row is odd if last row is even
    }

    firstBlankRowYPos = nextRect.origin.y;
    row = countRows;
    while (nextRect.origin.y<(rect.origin.y+rect.size.height)) {
        if (colorSourceBackgroundColor)
            rowColor = [COLOR_SOURCE tableView:self backgroundColorForRow:row];
        else
            if (isOddRow) {
                rowColor = [[NSColor alternateSelectedControlColor] highlightWithLevel:0.90];
            } else {
                rowColor = [self backgroundColor];
            }

        [rowColor set];
        [NSBezierPath fillRect:nextRect];
        isOddRow = !isOddRow;
        nextRect.origin.y += height;
        row++;	
	
    }

    NSRange columnRange = [self columnsInRect:rect];
    int i;
    [[[NSColor gridColor] colorWithAlphaComponent:0.5] set];

    for ( i = columnRange.location; i < NSMaxRange(columnRange); i++ ) {
	NSRect colRect = [self rectOfColumn:i];
	int rightEdge = (int) 0.5 + colRect.origin.x + colRect.size.width;
	[NSBezierPath strokeLineFromPoint: NSMakePoint(-0.5+rightEdge, -0.5+rect.origin.y) toPoint: NSMakePoint(-0.5+rightEdge, -0.5+rect.origin.y + rect.size.height)];
    }
    
    //NSLog(@"row: %d, col: %d", rowFocus, colFocus);
    [self drawFocusRing];
}
*/
/*
// Draw the content
- (void) drawRow:(int) row clipRect:(NSRect)r{
    // if (sorting) return [super drawRow:row clipRect:r];
    NSArray 		*tcs = [self tableColumns];
    NSTableColumn 	*tc;
    id			cell;
    NSRect		cellFrame, rowRect;
    id			dataSource = [self dataSource];
    int 		i;
    NSColor		*rowColor;
    
    
    if ([self isRowSelected:row]) {
        if (colorSourceHighlightColor) {
            if (![self numberOfSelectedColumns] > 0) {
                rowColor = [COLOR_SOURCE tableView:self highlightColorForRow:row];
            } else if (colorSourceBackgroundColor) {
                rowColor = [COLOR_SOURCE tableView:self backgroundColorForRow:row];
            } else if (!(row & 1)) {
                rowColor = [[NSColor alternateSelectedControlColor] highlightWithLevel:0.90];
            } else {
                rowColor = [self backgroundColor];
            }
        } else {
            rowColor = [NSColor alternateSelectedControlColor];
        }
    } else if (colorSourceBackgroundColor) {
        rowColor = [COLOR_SOURCE tableView:self backgroundColorForRow:row];
    } else if (!(row & 1)) {
        rowColor = [[NSColor alternateSelectedControlColor] highlightWithLevel:0.90];
    } else {
        rowColor = [self backgroundColor];
    }

    [rowColor set];
    rowRect = [self rectOfRow:row];
    if (!sorting)
        [NSBezierPath fillRect:rowRect];
    
    // make that little white line at the top of selected rows, but not the top row
    if (row && [self isRowSelected:row]) {
        [[self backgroundColor] set];
        //rowRect.origin.y = rowRect.size.height - 0.5;
        rowRect.size.height = 0.5;
        [NSBezierPath fillRect:rowRect];
    }

    for (i=0;i<[tcs count];i++) {
        tc = [tcs objectAtIndex:i];
        cell = [tc dataCellForRow:row];
        cellFrame = [self smallFrameOfCellAtColumn:i row:row];
        if (colFocus == i)
            cellFrame = [self frameOfCellAtColumn:i row:row];
        [cell setObjectValue:[dataSource tableView:self objectValueForTableColumn:tc row:row]];

        // Tell the actual cell not to draw a BG so that the row color shows through
        if ([cell respondsToSelector:@selector(setDrawsBackground:)]) {
            [cell setDrawsBackground:NO];
        }

        // Set text color
        if ([cell respondsToSelector:@selector(setTextColor:)]) {
            if ([self isRowSelected:row] && i != colFocus) { // || [self isColumnSelected:i]) {
                [cell setTextColor:[NSColor whiteColor]];
            } else {
                [cell setTextColor:[NSColor blackColor]];
            }
        }
        
        //	highlights the rows of the column that is selected, if any
        
        //[cell setHighlighted:[self isColumnSelected:i]];
        
        if ([[self delegate] respondsToSelector:@selector(tableView:willDisplayCell:forTableColumn:row:)] && ![self isRowSelected:row])
            [[self delegate] tableView:self willDisplayCell:cell forTableColumn:tc row:row];
        if ([cell respondsToSelector:@selector(imageRow)] && [cell respondsToSelector:@selector(setPictureTime:)]) {
            if ([cell imageRow] == row) [cell setPictureTime:YES];
            else [cell setPictureTime:NO];
        }
        [cell drawWithFrame:cellFrame inView:self];
    }
}
*/

- (NSRect)frameOfCellAtColumn:(int)columnIndex row:(int)rowIndex
{
    NSTableColumn *col = [[self tableColumns] objectAtIndex:columnIndex];
    NSRect r = [super frameOfCellAtColumn:columnIndex row:rowIndex];
    if (!grows /*|| sorting*/) return r;
    //NSCell *cell = [[[self tableColumns] objectAtIndex:columnIndex] dataCellForRow:rowIndex];
    NSString *string = [[self dataSource] tableView:self objectValueForTableColumn:col row:rowIndex];
    //NSLog(@"old: %@", string);
    if (curEditedText) {
        string = curEditedText;
        //NSLog(string);
    }
    if (![string isKindOfClass:[NSString class]])
        string = [string description];
    NSAttributedString *aString = nil;
    if ([string length]) {
        NSAttributedString *displayString = [[col dataCell] attributedStringValue];
        NSDictionary *attributes = [displayString attributesAtIndex:0 effectiveRange:nil];
        aString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
    }
    NSSize s = [self sizeOfString:aString];
    //NSLog (@"old: %g x %g, new: %g x %g", r.size.width, r.size.height, s.width, s.height);
    if (s.width > r.size.width) r.size.width = s.width;
    if (s.height > r.size.height) r.size.height = s.height;
    NSRect frame = [self visibleRect];
    //NSLog(@"%g, %g, %g x %g", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
    if (r.size.width > frame.size.width - 10)
        r.size.width = frame.size.width - 10;
    if (r.size.height > frame.size.height - 10)
        r.size.height = frame.size.height - 10;
    float x = r.origin.x + r.size.width - frame.size.width - frame.origin.x + 5;
    if (x > 0) r.origin.x -= x;
    float y = r.origin.y + r.size.height - frame.size.height - frame.origin.y + 5;
    if (y > 0) r.size.height -= y;
    //NSLog(@"frameOfCell %dx%d: (%gx%g)%gx%g", columnIndex, rowIndex, r.origin.x, r.origin.y, r.size.width, r.size.height);
    return r;
}

- (NSSize)sizeOfString:(NSAttributedString *)string
{
    if (!string || ![string length]) return NSZeroSize;
    int threash = 60;
    NSMutableString *outString = [NSMutableString string];
    int index = 0, tally = 0;
    while (YES) {
        if (index >= [string length])
            break;
        char ch = [[string string] characterAtIndex:index];
        [outString appendFormat:@"%c", ch];
        if (ch == '\n' || ch == '\r')
            tally = 0;
        tally++;
        index++;
        if (tally >= threash) {
            NSRange aRange = [outString rangeOfString:@" " options:NSBackwardsSearch];
            if (aRange.length)
                [outString replaceCharactersInRange:aRange withString:@"\n"];
            tally = 0;
        }
    }
    NSSize s = [[[NSAttributedString alloc] initWithString:outString attributes:[string attributesAtIndex:0 effectiveRange:nil]] size];
    int extra = [string length];
    if (extra > threash) extra = threash;
    s.width += extra;
    s.height += 5;
    return s;
}

- (NSRect)smallFrameOfCellAtColumn:(int)c row:(int)r
{
    return [super frameOfCellAtColumn:c row:r];
}

- (void)unEdit:(NSNumber *)row
{
    [self selectRow:[row intValue] byExtendingSelection:NO];
}
/*
- (void) drawRect
{
    [self drawRect:[self frame]];
}
*/
- (int)numberOfRowsInTableView:(NSTableView *)tview
{
    //NSLog(@"numberOfRows");
    return [oldDataSource numberOfRowsInTableView:tview];
}

BOOL textEditVar = YES;

- (id)tableView:(NSTableView *)tview objectValueForTableColumn:(NSTableColumn *)tcol row:(int)rowIndex
{
    //NSLog(@"objectValue: %@, %d", [tcol identifier], rowIndex);
    //if (textEditVar)
    //    return [oldDataSource tableView:tview objectValueForTableColumn:tcol row:rowIndex];
    //else
        return partialString;
}

- (void)tableView:(NSTableView *)tview setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tcol row:(int)rowIndex
{
    //NSLog(@"setObjectValue: %@, %@, %d", anObject, [tcol identifier], rowIndex);
    //if (textEditVar) {
    //    partialString = nil;
   //     [oldDataSource tableView:tview setObjectValue:anObject forTableColumn:tcol row:rowIndex];
    //} else
        partialString = anObject;
}

- (void)resizeTextView:(NSTextView *)t
{
    int row = rowFocus, col = colFocus;
    if (row < 0 || row >= [self numberOfRows] || col < 0 || col >= [self numberOfColumns]) return;
    oldDataSource = [self dataSource];
    oldDelegate = [self delegate];
    //NSLog(@"resizeTextView: setting data source to self");
    [self setDataSource:self];
    //NSLog(@"1");
    [self setDelegate:self];
    //NSLog(@"2");
    NSTableColumn *tcol = [[self tableColumns] objectAtIndex:col];
    //NSLog(@"3");
    textEditVar = NO;
    //NSLog(@"4");
    NSRange r = [t selectedRange];
   // NSLog(@"selecting row: %d", row);
    [self selectRow:row byExtendingSelection:NO];
    //NSLog(@"editing row: %d", row);
    [self edit:[NSNumber numberWithInt:row]];
    //NSLog(@"5");
    [t setSelectedRange:r];
    //NSLog(@"6");
    NSCell *cell = [tcol dataCell];
    //NSLog(@"7");
    [cell setWraps:YES];
    //NSLog(@"8");
    //[cell setScrollable:YES];
    rowFocus = row;
    //NSLog(@"9");
    colFocus = col;
    //NSLog(@"10");
    textEditVar = YES;
    //NSLog(@"resizeTextView: setting data source back");
    [self setDelegate:oldDelegate];
    [self setDataSource:oldDataSource];
    [self setNeedsDisplay:YES];
    oldDataSource = oldDelegate = nil;
}

- (void)textDidChange:(NSNotification *)aNotification
{
    NSTextView *t = [aNotification object];
    
    [super textDidChange:aNotification];
    
    [curEditedText release];
    curEditedText = [[NSString alloc] initWithString:[t string]];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resizeTextView:) object:nil];
    [self performSelector:@selector(resizeTextView:) withObject:t afterDelay:1];
}

- (void)textDidEndEditing:(NSNotification *)aNotification
{
    //NSLog(@"textDidEndEditing");
    int colIndex = colFocus;
    if (colIndex < 0) colIndex = [self editedColumn];
    NSTableColumn *col = nil;
    if (colIndex >= 0 && colIndex < [self numberOfColumns]) col = [[self tableColumns] objectAtIndex:colIndex];
    if (textEditVar) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resizeTextView:) object:nil];
        [curEditedText release];
        curEditedText = nil;
        [[col dataCell] setWraps:NO];
        [[col dataCell] setScrollable:YES];
    }
    //	on end editing, we remember that no cells are being edited
    rowFocus = colFocus = -1;
    [self setNeedsDisplay:YES];
    
    //	On return end editing instead of tabbing downwards
    int keyType = [[[aNotification userInfo] objectForKey:@"NSTextMovement"] intValue];
    int row = [self editedRow];
    if (NSReturnTextMovement == keyType) {
        if ([[self delegate] respondsToSelector:@selector(tableViewSelectionWontChange:)])
            [[self delegate] tableViewSelectionWontChange:nil];
        [super textDidEndEditing:aNotification];
        //[self selectColumn:0 byExtendingSelection:NO];
        [self selectRow:row byExtendingSelection:NO];
        [self scrollRowToVisible:row];
        if ([[self delegate] respondsToSelector:@selector(tableViewSelectionWillChangeAgain:)])
            [[self delegate] tableViewSelectionWillChangeAgain:nil];
        // here we have to reset that no cells are being edited since super changed the selection and we're changing it back
        rowFocus = colFocus = -1;
        [self setNeedsDisplay:YES];
    } else {
        [super textDidEndEditing:aNotification];
    }
    if (textEditVar && [[self delegate] respondsToSelector:@selector(tableView:didEndEditingTableColumn:row:)])
        [[self delegate] tableView:self didEndEditingTableColumn:col row:row];
}

- (void)edit:(NSNumber *)row
{
    if ([row intValue] < 0 || [row intValue] >= [self numberOfRows]) return;
    if ([[self delegate] respondsToSelector:@selector(shouldEditTableColumn:row:)])
        [[self delegate] shouldEditTableColumn:[[self tableColumns] objectAtIndex:lastEditedColumn] row:[row intValue]];
    [self selectRow:[row intValue] byExtendingSelection:NO];
    int numCols = [[self tableColumns] count];
    if (numCols) {
        if (lastEditedColumn >= numCols) lastEditedColumn = 0;
        //NSLog(@"lastCol: %d, selRow: %d", lastEditedColumn, [self selectedRow]);
        [self editColumn:lastEditedColumn row:[row intValue] withEvent:nil select:YES];
    }
}

- (void)editColumn:(int)columnIndex row:(int)rowIndex withEvent:(NSEvent *)theEvent select:(BOOL)flag
{
    //	on beginning editing, we remember which cell is being edited
    if (rowIndex < 0 || rowIndex >= [self numberOfRows] || columnIndex < 0 || columnIndex >= [self numberOfColumns]) return;
    rowFocus = rowIndex;
    colFocus = columnIndex;
    lastEditedColumn = colFocus;
    NSCell *cell = [[[self tableColumns] objectAtIndex:columnIndex] dataCell];
    [cell setWraps:YES];
    //if ([cell respondsToSelector:@selector(setTextColor:)])
    //    [(NSTextFieldCell *)cell setTextColor:[NSColor blackColor]];
    //NSText *aText = [[self window] fieldEditor:YES forObject:nil];
    //[aText setBackgroundColor:[NSColor redColor]];
    [super editColumn:columnIndex row:rowIndex withEvent:theEvent select:flag];
}
/* // these seem to be triggering a lot of crashes for some reason, and I'm not using them anyway
- (void)setDataSource:(id)anObject
{
    [super setDataSource:anObject];
    [self queryDataAndColorSources];
}

- (void)setDelegate:(id)anObject
{
    [super setDelegate:anObject];
    [self queryDataAndColorSources];
}
*/
- (void)queryDataAndColorSources
{
    colorSourceBackgroundColor = [COLOR_SOURCE respondsToSelector:@selector(tableView:backgroundColorForRow:)];
    colorSourceHighlightColor = [COLOR_SOURCE respondsToSelector:@selector(tableView:highlightColorForRow:)];
    delegateWillDisplayCell = [[self delegate] respondsToSelector:@selector(tableView:willDisplayCell:forTableColumn:row:)];
}

- (void)setEditsOnEnter:(BOOL)flag
{
    //NSLog(@"set edits: %d, %@", flag, [self autosaveName]);
    editsOnEnter = flag;
}

- (void)setEditsOnEnterObj:(NSNumber *)flag
{
    //NSLog(@"set edits: %d, %@", [flag boolValue], [self autosaveName]);
    editsOnEnter = [flag boolValue];
}

- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
    NSString *chars = [theEvent characters];
    unichar uch = [chars characterAtIndex:0];
    if (uch == 127 && // delete
        [[self window] firstResponder] == self  &&
        !([theEvent modifierFlags] & NSControlKeyMask) &&
        !([theEvent modifierFlags] & NSAlternateKeyMask) &&
        !([theEvent modifierFlags] & NSShiftKeyMask)) {
            if ([theEvent modifierFlags] & NSCommandKeyMask) {
                if ([[self delegate] respondsToSelector:@selector(commandDeleteForTableView:)])
                    return [[self delegate] commandDeleteForTableView:self];
            } else {
                if ([[self delegate] respondsToSelector:@selector(deleteForTableView:)])
                    return [[self delegate] deleteForTableView:self];
            }
    } else if (uch == 3 || uch == 13) { // Enter and Return, respectively
        //NSLog(@"return, %@", [self autosaveName]);
        if (editsOnEnter) {
            [self performSelector:@selector(edit:) withObject:[NSNumber numberWithInt:[self selectedRow]] afterDelay:0];
            //NSLog(@"edit, %@", [self autosaveName]);
            return YES;
        }
    }
    return [super performKeyEquivalent:theEvent];
}

- (int)selectedRow
{
    int sup = [super selectedRow];
    if (-1 == sup && -1 != rowFocus)
        sup = rowFocus;
    return sup;
}

- (int)selectedColumn
{
    int sup = [super selectedColumn];
    if (-1 == sup && -1 != colFocus)
        sup = colFocus;
    return sup;
}

- (void)selectRow:(int)rowIndex byExtendingSelection:(BOOL)flag
{
    int col = [super selectedColumn];
    //NSLog(@"selectRow start (%d)", col);
    [super selectRow:rowIndex byExtendingSelection:flag];
    if (col >= 0)
        [self setHighlightedTableColumn:[[self tableColumns] objectAtIndex:col]];
    //NSLog(@"selectRow end");
}

- (void)mouseDown:(NSEvent *)event
{
    if ([event modifierFlags] & NSControlKeyMask)
        [self rightMouseDown:event];
    else [super mouseDown:event];
}

- (void)rightMouseDown:(NSEvent *)theEvent
{
    if ([[self delegate] respondsToSelector:@selector(tableView:rightClickWithEvent:)])
        [[self delegate] tableView:self rightClickWithEvent:theEvent];
}

@end

@implementation iTableHeaderView


/* Track column resizing */
- (void) mouseDown: (NSEvent *) theEvent{
    if ([theEvent modifierFlags] & NSControlKeyMask) {
	[self rightMouseDown:theEvent];
	return;
    }
    NSPoint 		origPoint, lastPoint, lastPointOffset;
    NSTableView		*tv = [self tableView];
    NSArray 		*tcs = [tv tableColumns];
    BOOL		clickedInColumnSeparator;
    int			colAtFirstPoint, colAtFirstPointOffset, columnToResize;
    origPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
    /* check to see if mouse clicked on a column separator */
    lastPoint = origPoint;
    colAtFirstPoint = [tv columnAtPoint:lastPoint];
    if ([tv allowsColumnSelection]) [tv setHighlightedTableColumn:[[tv tableColumns] objectAtIndex:colAtFirstPoint]];
    columnToResize = colAtFirstPoint;
    lastPointOffset = lastPoint;
    lastPointOffset.x+=2;
    colAtFirstPointOffset = [tv columnAtPoint:lastPointOffset];
    if (colAtFirstPoint == colAtFirstPointOffset) { // offset to the left
        lastPointOffset.x-=3;
        colAtFirstPointOffset = [tv columnAtPoint:lastPointOffset];
        columnToResize = colAtFirstPoint-1; // clicked on a pixel to the right of the separator, resize column is prev column
    }
    clickedInColumnSeparator = ((colAtFirstPointOffset != -1) && (colAtFirstPoint != colAtFirstPointOffset));
    if (clickedInColumnSeparator) {
        NSRect 		tvVisibleRect = [tv visibleRect];
        NSPoint		origWindowPoint = [theEvent locationInWindow], curWindowPoint;
        NSPoint		newOrigin = tvVisibleRect.origin;
        NSTableColumn	*col = [tcs objectAtIndex: columnToResize];
        int		origWidth = [col width];
        while (1) {
            int		newWidth;
            NSPoint	curPoint;
            theEvent = [[self window] nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
            curWindowPoint = [theEvent locationInWindow];
            curPoint = [self convertPoint:curWindowPoint fromView:nil];
            newWidth = origWidth+curWindowPoint.x-origWindowPoint.x;
            // move scroll point if necessary
            if (((newWidth >= [col minWidth]) && (newWidth <= [col maxWidth])) && (newWidth != [col width])) {
                tvVisibleRect = [tv visibleRect];
                // keep scroll line position constant
                if (curPoint.x >= tvVisibleRect.origin.x+tvVisibleRect.size.width-60) {
                    newOrigin.x = tvVisibleRect.origin.x+newWidth-[col width];
                    [tv scrollPoint:newOrigin];
                }
                [col setWidth:newWidth];
            }
            if ([theEvent type] == NSLeftMouseUp)
                break;
        }
    }
    else {
        [super mouseDown:theEvent];
    }
    [[[self tableView] window] makeFirstResponder:[self tableView]];
}

- (void)rightMouseDown:(NSEvent *)theEvent
{
    if ([[[self tableView] delegate] respondsToSelector:@selector(tableView:headerRightClickWithEvent:)])
        [[[self tableView] delegate] tableView:[self tableView] headerRightClickWithEvent:theEvent];
}

@end
