/* 
   Matrix.m

   Matrices for Workspace's browser

   Copyright (C) 1998 Free Software Foundation, Inc.

   Author:  Felipe A. Rodriguez <far@pcmagic.net>
   Date:	August 1998
   
   This file is part of the mySTEP Library and is provided
   under the terms of the GNU Library General Public License.
*/ 

#include <Foundation/NSObject.h>
#include <AppKit/xraw/XR.h>

#include "Controller.h"
#include "Matrix.h"
#include "Cell.h"

// Class variables
ShelfCell *__ghostCell = nil;
ShelfCell *__openCell = nil;
NSArray *__types = nil;
NSRect openCellRect;
BOOL __doAnimation = NO;
BOOL __needsUnlockFocus = NO;
static NSString *__dragSourcePath = nil;
static NSMutableDictionary *__pbPropList = nil;


@implementation Matrix

- (void) viewWillMoveToWindow:(NSWindow *)newWindow
{
	[window endEditingFor:nil];
	[super viewWillMoveToWindow:newWindow];

	if (newWindow)
		{
		if (!__types)
			__types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
		[self registerForDraggedTypes:__types];
		}
}

- (NSArray *) saveState
{
int i, j;
NSString *p;
NSMutableArray *array = [NSMutableArray array];

	for (i = 0; i < _numRows; i++) 
		for (j = 0; j < _numCols; j++)
			if (p = [[_cells objectAtIndex:((i * _numCols) + j)] path])
			   [array addObject:[NSString stringWithFormat:@"%d %d %@",i,j,p]];

	return array;
}

- (void) restoreState
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSFileManager *fm = [NSFileManager defaultManager];
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
int i, j, k = 1, ii = 0, jj = 0, count;
NSArray *array;
char path[1024];
NSString *p;

	if(!(array = [defaults objectForKey: @"Shelf"]))
		return;

	count = [array count];
	for (i = 0; i < _numRows; i++) 
		for (j = 0; j < _numCols; j++)
			{
			if(i == ii && j == jj)
				{
				if(i > 0)
					{
					BOOL isDir = NO;

					if ([fm fileExistsAtPath:p isDirectory:&isDir])
						{
						id c = [_cells objectAtIndex:((i * _numCols) + j)];

						if (isDir)
							[c setBranchImage: [ws iconForFile:p]];
						else
							[c setLeafImage: [ws iconForFile:p]];

						[c _setPath: p];
						[c setStringValue: [p lastPathComponent]];
					}	}

				if(k < count)
					{
					p = [array objectAtIndex: k++];
					if(sscanf([p cString], "%d %d %s", &ii, &jj, path) != 3)
						NSLog(@"Unable to restore shelf matrix state\n");
					p = [NSString stringWithCString: path];
			}	}	}
}

- (void) selectCell:(NSCell *)aCell withRect:(NSRect)rect
{
NSCell *browserText = [(ShelfCell *)aCell browserText];
float titleWidth = [browserText cellSize].width - 4;
NSRect titleRect = rect;
		
	titleRect.size.height = 17;							// Determine title rect
	titleRect.origin.y = NSMaxY(rect) - 15;		
	titleRect.origin.x += (titleRect.size.width - titleWidth) / 2;
	titleRect.size.width = titleWidth;
	if (NSMaxX(titleRect) > NSMaxX(frame))
		titleRect.origin.x += (NSMaxX(frame) - NSMaxX(titleRect));
	titleRect.origin.x = MAX(NSMinX(titleRect), 1);

	if(_m.mode == NSHighlightModeMatrix)				// not in shelf mode
		return;
	if(_m.mode == NSRadioModeMatrix)					// not in selector mode
		return;

	[browserText selectWithFrame:titleRect				// edit browser cell's
				 inView:self							// text
				 editor:[window fieldEditor:YES forObject:browserText]	
				 delegate:self	
				 start:(int)0	 
				 length:(int)0];
}

- (void) selectRect:(NSRect)rect
{
int i, j;
int row1, col1;								// cell at the upper left corner
int row2, col2;								// cell at the lower right corner
NSRect cellRect, upperLeftRect;
NSPoint p = {NSMaxX(rect), NSMaxY(rect)}; 
NSSize inc = {_cellSize.width + _interCell.width,
			  _cellSize.height + _interCell.height};

	[self getRow:&row1 column:&col1 forPoint:rect.origin];
	[self getRow:&row2 column:&col2 forPoint:p];

	NSLog (@"sel cells between (%d, %d) and (%d, %d)", row1,col1, row2,col2);

	cellRect = upperLeftRect = [self cellFrameAtRow:row1 column:col1];
	for (i = row1; i <= row2; i++)
		{												// Select cells within
		for (j = col1; j <= col2; j++)					// the rectangle
			{
			if (NSIntersectsRect(rect, cellRect))
				{
				NSCell *aCell = [_cells objectAtIndex:((i * _numCols) + j)];

				if ([aCell image])
					{
					[aCell setState:1];
					[aCell highlight:YES withFrame:cellRect inView:self];
					((tMatrix)selectedCells)->matrix[i][j] =YES;
					selectedCell = aCell;
				}	}
			cellRect.origin.x += inc.width;
			}
		cellRect.origin.x = upperLeftRect.origin.x;
		cellRect.origin.y += inc.height;
		}

	selectedRow = i;					
	selectedColumn = j;

	[window flushWindow];
}

- (NSRect) selectWithRubberBand:(NSEvent*)event
{
NSEventType type;
NSPoint op, cp = [event locationInWindow];
NSPoint t, p = [self convertPoint:cp fromView:nil];
NSRect nr = (NSRect){p,{0,0}};
NSRect or = nr;

	[[NSColor lightGrayColor] set];

	while((type = [event type]) != NSLeftMouseUp)
		{
		if (type == NSPeriodic)
			{
			if (!NSEqualPoints(op, cp))
				{
				op = cp;
				t = nr.origin = [self convertPoint:cp fromView:nil];

				nr.size = (NSSize){MAX(p.x - nr.origin.x, nr.origin.x - p.x),
								   MAX(p.y - nr.origin.y, nr.origin.y - p.y)};
				if (nr.origin.x > p.x)
					nr.origin.x = p.x;
				if (nr.origin.y > p.y)
					nr.origin.y = p.y;

				if(or.size.width != 0)
					NSFrameRectWithWidthUsingOperation(or,1., NSCompositeXOR);
				[self scrollRectToVisible:(NSRect){t,{2.,2.}}];
				NSFrameRectWithWidthUsingOperation(nr,1., NSCompositeXOR);
				[window flushWindow];
				or = nr;
			}	}
		else
			cp = [event locationInWindow];

		event = [NSApp nextEventMatchingMask:GSTrackingLoopMask
					   untilDate:[NSDate distantFuture]
					   inMode:NSEventTrackingRunLoopMode 
					   dequeue:YES];
		}

	if(or.size.width != 0)
		{
		NSFrameRectWithWidthUsingOperation(or,1., NSCompositeXOR);
		[window flushWindow];
		}

	return nr;
}

- (void) setIsFinderShelf:(BOOL)flag			{ _isFinderShelf = flag; }
- (BOOL) acceptsFirstResponder					{ return NO; }
- (BOOL) acceptsFirstMouse:(NSEvent *)event		{ return YES; }

- (void) mouseDown:(NSEvent*)event
{
BOOL inCell, done = NO;
int row, column, clickCount;
NSPoint location;
NSRect rect, previousCellRect;
id aCell, previousCell = nil;
static NSPoint selectedLocation;

//	fprintf(stderr, "mouseDown:(NSEvent*)event\n");

	if ((clickCount = [event clickCount]) > 1)
		{
		if(_target && _doubleAction && clickCount == 2)			// double click
			[_target performSelector:_doubleAction withObject:self];

		return;
		}

	[window endEditingFor:nil];

	if ((_m.mode != NSTrackModeMatrix) && (_m.mode != NSHighlightModeMatrix)) 
		[NSEvent startPeriodicEventsAfterDelay:0.03 withPeriod:0.03];

	[self lockFocus];					// selection involves two steps, first
										// a loop that continues until the left
	while (!done) 						// mouse goes up; then a series of 
		{								// steps which send actions and display
		BOOL shouldProceedEvent = NO;	// the cell as it should appear after
										// the selection process is complete
		location = [self convertPoint:[event locationInWindow] fromView:nil];

		if ((inCell = [self getRow:&row column:&column forPoint:location])) 			
			{											 
      		aCell = [self cellAtRow:row column:column];
      		rect = [self cellFrameAtRow:row column:column];

      		switch (_m.mode) 
				{
				case NSRadioModeMatrix:				// Path selection mode
	  				if (previousCell == aCell)
						{
						if((location.x > selectedLocation.x + 4.0)
								|| (location.x < selectedLocation.x - 4.0)
								|| (location.y > selectedLocation.y + 4.0) 
								|| (location.y < selectedLocation.y - 4.0))
							{		
							NSPasteboard *p;
							NSArray *t = [NSArray arrayWithObjects:
											NSFilenamesPboardType, nil];
							NSSize offset = {(NSWidth(rect)-80.0)/2.0,-40.0};
													// adjust off for last loc
							offset.width -= (location.x - NSMinX(rect)-17);
							offset.height += (location.y - NSMinY(rect)-15);

 							p = [NSPasteboard pasteboardWithName:NSDragPboard];
							[p declareTypes:t owner:self];
							ASSIGN(__dragSourcePath, nil);

							[NSEvent stopPeriodicEvents];
							[self unlockFocus];
													// perform drag mechanics
							[self dragImage:[aCell image]
								  at:location
								  offset:offset
								  event:event
								  pasteboard:p
								  source:self
								  slideBack:YES];
							[self lockFocus];
							done = YES;			
							}

	    				break;		
						}	
					
					if(selectedCell)					
						{
						[selectedCell setState:0];		// deselect previously
						if (!previousCell)				// selected cell
							previousCellRect = [self cellFrameAtRow:selectedRow 
									  			 	 column:selectedColumn];
						[selectedCell highlight:NO 			
									  withFrame:previousCellRect 
									  inView:self];
	  					((tMatrix)selectedCells)->matrix[selectedRow]
														[selectedColumn] = NO;	
						}			
					selectedCell = aCell;				// select current cell
					selectedRow = row;					
					selectedColumn = column;
					selectedLocation = location;	
					[aCell setState:1];	
					[aCell highlight:YES withFrame:rect inView:self];
	  				((tMatrix)selectedCells)->matrix[row][column] = YES;				
					[window flushWindow];

				case NSTrackModeMatrix:				
					break;									

				case NSHighlightModeMatrix:				// Shelf mode
					{
					NSString *path;
					NSPoint b = { MAX(rect.origin.x, location.x - 4.0), 
								  MAX(rect.origin.y, location.y - 4.0) };
					NSRect dragRect = {b, MIN( 8.0, NSMaxX(rect) - b.x),
										  MIN( 8.0, NSMaxY(rect) - b.y) };

					if (_isFinderShelf)		// clear existing selection unless
						{					// Alt or Shift is held down.
						unsigned modifiers = [event modifierFlags];

						if (!(modifiers & NSShiftKeyMask) && 
								!(modifiers & NSAlternateKeyMask))
	      					[self deselectAllCells];
						}
													// Highlight mode is like
					[aCell setState:1];				// Track mode except that
					selectedCell = aCell;			// the cell is lit before
					selectedRow = row;				// it begins tracking and
					selectedColumn = column;		// unlit afterwards
					((tMatrix)selectedCells)->matrix[row][column] = YES;
					[aCell highlight:YES withFrame:rect inView:self];
					[window flushWindow];

					if([aCell trackMouse:event			 
							  inRect:dragRect					
							  ofView:self				
							  untilMouseUp:YES])			// YES if mouse 
						done = YES;							// went up in cell
					else
						{									// user is dragging
						if((path = [aCell path]))			// a cell from the
							{								// shelf
							NSImage *cellImage = [aCell image];
							NSPasteboard *p;
							NSSize offset = {(NSWidth(rect) - 48.0)/2.0,-56.0};
							NSArray *t = [NSArray arrayWithObjects:
											NSFilenamesPboardType, nil];
	
							p = [NSPasteboard pasteboardWithName:NSDragPboard];
							[p declareTypes:t owner:self];
							ASSIGN(__dragSourcePath, [aCell path]);

							[aCell setState:0];	
							[aCell setImage:nil];												  
							[aCell _setPath:nil];												  
							[self displayRectIgnoringOpacity: rect];
							[self unlockFocus];
													// perform drag mechanics
							[self dragImage:cellImage
								  at:rect.origin
								  offset:offset
								  event:event
								  pasteboard:p
								  source:self
								  slideBack:NO];
							done = YES;			
							[self lockFocus];
	
							break;		
						}	}
					NSDebugLog(@"mouse is up");

					if(_delegate)
						if([_delegate respondsToSelector:@selector(setPath:)]
								&& (path = [aCell path]) 
								&& ![path isEqualToString:[_delegate path]])
							{
							NSString *a, *t;
							NSWorkspace *ws = [NSWorkspace sharedWorkspace];

							if([ws getInfoForFile:path application:&a type:&t]
									&& t == NSDirectoryFileType)
								[_delegate setPath:path];
							}

					if (!_isFinderShelf)
						{
						[aCell setState:0];
						((tMatrix)selectedCells)->matrix[row][column] = NO;
						[aCell highlight: NO withFrame: rect inView: self];
						}
					[window flushWindow];
					}
					break;

				case NSListModeMatrix: 			 	// File browser mode
					{
	  				unsigned modifiers = [event modifierFlags];
													// drag op if mouse moves
	  				if (previousCell == aCell)		// more than x pixels while
						{							// left mouse is down
						if((location.x > selectedLocation.x + 4.0)
								|| (location.x < selectedLocation.x - 4.0)
								|| (location.y > selectedLocation.y + 4.0)
								|| (location.y < selectedLocation.y - 4.0))
							{					// offset compensates for the
												// pos of the image cell within 
												// the larger browser cell
							NSSize offset = {(NSWidth(rect) - 48.0)/2.0,-48.0};
							NSPasteboard *p;
							NSArray *t = [NSArray arrayWithObjects:
											NSFilenamesPboardType, nil];

							p = [NSPasteboard pasteboardWithName:NSDragPboard];
							[p declareTypes:t owner:self];
							ASSIGN(__dragSourcePath, nil);

							[NSEvent stopPeriodicEvents];
													// perform drag mechanics
							[self unlockFocus];
							[self dragImage:[aCell image]
								  at:previousCellRect.origin
								  offset:offset
								  event:event
								  pasteboard:p
								  source:self
								  slideBack:YES];
							done = YES;
							[self lockFocus];
							}

	    				break;
						}

					if(selectedCell == aCell)		// Edit browsercell's text
						{
						if([aCell trackMouse:event
								  inRect:rect
								  ofView:self
								  untilMouseUp:YES])
							done = YES;				// YES if mouse up in aCell

						if(done)
							break;
						}				// When the user first clicks on a cell 
										// we clear the existing selection 
					if (!previousCell) 	// unless the Alternate or Shift keys
						{				// have been pressed.
						if (!(modifiers & NSShiftKeyMask) && 
								!(modifiers & NSAlternateKeyMask))
	      					[self deselectAllCells];

	    				if (!(modifiers & NSAlternateKeyMask) && [aCell image])
							{
							selectedCell = aCell;		// select current cell
							selectedRow = row;
							selectedColumn = column;
							selectedLocation = location;	

							[aCell setState:1];
							[aCell highlight:YES withFrame:rect inView:self];
							[self selectCell:aCell withRect:rect];

							((tMatrix)selectedCells)->matrix[row][column] =YES;
							[self sendAction];
							[window flushWindow];
							break;
							}
	  					}

					done = YES;			

					[window flushWindow];
					break;
					}
      			}
			previousCell = aCell;
			previousCellRect = rect;
//			[self scrollRectToVisible:rect];
    		}
		else
			if (_m.mode == NSListModeMatrix)
				{
				NSRect s = [self selectWithRubberBand: event];

				[self deselectAllCells];
				if (!NSIsEmptyRect(s))
					[self selectRect: s];
				[self sendAction];
				done = YES;			
				}

    	if (done)										// if done break out of
      		break;										// the selection loop

		while (!shouldProceedEvent) 					
			{											// Get the next event
			NSEvent *e;

      		e = [NSApp nextEventMatchingMask:GSTrackingLoopMask
					   untilDate:[NSDate distantFuture]
					   inMode:NSEventTrackingRunLoopMode
					   dequeue:YES];

			NSDebugLog(@"Matrix: got event of type: %d\n", [event type]);
      		switch ([e type])
				{
				case NSMouseMoved:
				case NSLeftMouseUp:
					done = YES;
				case NSPeriodic:						// it's time to cycle
					shouldProceedEvent = YES;			// thru the loop again
					break;				// Track and Highlight modes do not use		
				case NSLeftMouseDown:	// periodic events so we must break out
				default:				// and check if the mouse is in a cell
					if ((_m.mode == NSTrackModeMatrix)
							|| (_m.mode == NSHighlightModeMatrix))
				  		shouldProceedEvent = YES;
					event = e;
					continue;
		}	}	}

	if(selectedCell && (_m.mode == NSRadioModeMatrix))	// single click action
		[self sendAction];			// in Track & Highlight modes single click
									// was already sent by cell to it's target
	if (!selectedCell && _m.mode == NSListModeMatrix)
		{
      	selectedCell = _cellPrototype;					// click on blank cell
		[self sendAction];
      	selectedCell = nil;
		}

	[self unlockFocus];

	if ((_m.mode != NSTrackModeMatrix) && (_m.mode != NSHighlightModeMatrix))
		[NSEvent stopPeriodicEvents];
}

- (void) pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type
{
	if (type == NSFilenamesPboardType)
		{
		NSArray *cells = [self selectedCells];
		NSEnumerator *e = [cells objectEnumerator];
		NSMutableArray *files = [NSMutableArray new];
		NSBrowserCell *cell;

		for(;(cell = [e nextObject]);)
			[files addObject:[cell stringValue]];

		if (!__dragSourcePath)
			{
			NSBrowser *b = [[NSApp mainWindow] browser];
			NSString *s = [b pathToColumn:[b selectedColumn]];
			NSString *n = [files objectAtIndex: 0];

			ASSIGN(__dragSourcePath, [s stringByAppendingPathComponent: n]);
	NSLog (@"__dragSourcePath ref count: '%d'\n", [__dragSourcePath retainCount]);

[__dragSourcePath retain];
			}
		if (!__pbPropList)
			__pbPropList = [NSMutableDictionary new];

	NSLog (@"__dragSourcePath: '%@'\n", __dragSourcePath);
		[__pbPropList setObject:__dragSourcePath forKey:@"SourcePath"];
	NSLog (@"__dragSourcePath ref count 2: '%d'\n", [__dragSourcePath retainCount]);
		[__pbPropList setObject:files forKey:@"SelectedFiles"];

		[sender setPropertyList:__pbPropList forType:NSFilenamesPboardType];
		}
}

- (void) draggingExited:(id <NSDraggingInfo>)sender
{
	if(__openCell)
		{
		[__openCell setImage:[NSImage imageNamed: @"folder.tiff"]];
		[__openCell drawInteriorWithFrame:openCellRect inView:self];
		[window flushWindow];
		__openCell = nil;
		}
	if(__ghostCell)
		{
		[__ghostCell setImage:nil];
		[self displayRectIgnoringOpacity: openCellRect];
		[window flushWindow];
		__ghostCell = nil;
		}
	if(__needsUnlockFocus)
		{
		__needsUnlockFocus = NO;
		[self unlockFocus];
		}
}

- (unsigned int) draggingUpdated:(id <NSDraggingInfo>)sender
{
unsigned int ret = NSDragOperationNone;
NSPoint p = [sender draggingLocation];
int row, col;

	NSDebugLog(@"draggingUpdated ptr window coords: '%f, %f'\n", p.x, p.y);

	p = [[window contentView] convertPoint:p toView:self];

	NSDebugLog(@"draggingUpdated target view coords: '%f, %f'\n", p.x, p.y);

	if([self getRow:&row column:&col forPoint:p])
		{
		ShelfCell *c = [self cellAtRow:row column:col];
		BOOL needsFlush = NO;

		NSDebugLog(@"draggingUpdated cell at: '%d, %d'\n", row, col);

		if(__openCell && (__openCell != c))
			{
			[__openCell setImage:[NSImage imageNamed: @"folder.tiff"]];
			[__openCell drawInteriorWithFrame:openCellRect inView:self];
			needsFlush = YES;
			__openCell = nil;
			}

		if(__ghostCell && (__ghostCell != c))
			{
			[__ghostCell setImage:nil];
//			[__ghostCell drawInteriorWithFrame:openCellRect inView:self];
			[self displayRectIgnoringOpacity: openCellRect];
			needsFlush = YES;
			__ghostCell = nil;
			}

		if(![c isLeaf] && c != selectedCell)				// cell is a folder
			{
			openCellRect = [self cellFrameAtRow:row column:col];

			if (_m.mode != NSRadioModeMatrix || col < selectedColumn - 1)
				[c setImage:[NSImage imageNamed: @"openFolder.tiff"]];

			if(!__needsUnlockFocus)
				[self lockFocus];
			__needsUnlockFocus = YES;
			needsFlush = YES;
			__openCell = c;
			[c drawInteriorWithFrame:openCellRect inView:self];
//			ret = NSDragOperationCopy;

			if (_m.mode != NSRadioModeMatrix || col < selectedColumn - 1)
				ret = [sender draggingSourceOperationMask];
			}
		else
			{
			if(![c image])								// cell must be blank
				{
				__ghostCell = c;
				openCellRect = [self cellFrameAtRow:row column:col];
				[c setLeafImage:[sender draggedImage]];
				if(!__needsUnlockFocus)
					[self lockFocus];
				__needsUnlockFocus = YES;
				needsFlush = YES;
				[c drawLightInteriorWithFrame:openCellRect inView:self];
				ret = NSDragOperationGeneric;
			}	}

		if(needsFlush)
			[window flushWindow];
		}

	return ret;
}

- (void) concludeDragOperation:(id <NSDraggingInfo>)sender
{
	if(__doAnimation)
		{
		__doAnimation = NO;
		[NSTimer scheduledTimerWithTimeInterval: 0.4
				 target: self
				 selector: @selector(draggingExited:)
				 userInfo: nil
				 repeats: NO];

	NSLog (@"View concludeDragOperation: op: '%d'\n",
			[sender draggingSourceOperationMask]);

		switch ([sender draggingSourceOperationMask])
			{
			case NSDragOperationCopy:
				[[NSApp delegate] performFileOperation:NSWorkspaceCopyOperation
								  destination: [__openCell path]];
				break;
			case NSDragOperationLink:
				[[NSApp delegate] performFileOperation:NSWorkspaceLinkOperation
								  destination: [__openCell path]];
				break;
			case NSDragOperationGeneric:
			case NSDragOperationPrivate:
				[[NSApp delegate] performFileOperation:NSWorkspaceMoveOperation
								  destination: [__openCell path]];
			case NSDragOperationAll:
			case NSDragOperationNone:
				break;
			}

		return;
		}

	__ghostCell = nil;
	if(__openCell || __needsUnlockFocus)
		[self draggingExited:nil];

	NSLog (@"View concludeDragOperation: view description: '%s'\n",
			[[self description] cString]);
}

- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender
{
int row, col;
NSPoint p = [sender draggingLocation];
NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSDragPboard];
NSDictionary *d = [pb propertyListForType:NSFilenamesPboardType];
NSString *browserPath = [d objectForKey:@"SourcePath"];
ShelfCell *aCell;
NSRect rect;

	if(!_dragTypes)
		return NO;

	NSLog (@"View performDragOperation: view description: '%s'\n",
			[[self description] cString]);
									// drag op; currently just for Workspace

	fprintf(stderr," mouse went up in window that triggered drag\n");
	fprintf (stderr,"pointer window coords: '%f, %f'\n", p.x, p.y);

	p = [[window contentView] convertPoint:p toView:self];

	fprintf (stderr,"pointer target view coords: '%f, %f'\n", p.x,p.y);

	[self getRow:&row column:&col forPoint:p];
	
	aCell = (ShelfCell *)[self cellAtRow:row column:col];

//	if([aCell path] || _m.mode == NSListModeMatrix)
	if([aCell path])
		{
fprintf (stderr,"[aCell path]\n");
		if(![aCell isLeaf] && aCell != selectedCell)
			{
			__doAnimation = YES;
			[aCell setImage:[NSImage imageNamed: @"depositFolder.tiff"]];
			}
		else
			{							// can't drop onto an occupied leaf,
fprintf (stderr,"can't drop onto an occupied leaf\n");
			return NO;					// drag cell should slide back
		}	}  
	else
		{
		NSImage *draggedImage = [sender draggedImage];
NSString *s, *n;

		if(__ghostCell && (__ghostCell != aCell))
			aCell = __ghostCell;

		if(draggedImage == [NSImage imageNamed: @"folder.tiff"])
			[aCell setBranchImage: draggedImage];
		else
			[aCell setLeafImage: draggedImage];

s = [d objectForKey:@"SourcePath"];
n = [[d objectForKey:@"SelectedFiles"] objectAtIndex: 0];

fprintf (stderr,"XRWindow set cell path: '%s'\n",[s cString]);
fprintf (stderr,"XRWindow cell at: '%d, %d'\n",row,col);

//		[aCell _setPath: browserPath];
//		[aCell setStringValue: [browserPath lastPathComponent]];

		[aCell _setPath: s];
		[aCell setStringValue: n];
		}

	if(!__needsUnlockFocus)
		[self lockFocus];
	__needsUnlockFocus = YES;
	if(__ghostCell == aCell)
		rect = openCellRect;
	else
		rect = [self cellFrameAtRow:row column:col];
	[aCell drawInteriorWithFrame:rect inView:self];
	[window flushWindow];

	return YES;
}

- (NSDragOperation) draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
	return NSDragOperationGeneric|NSDragOperationLink|NSDragOperationCopy;
//	return NSDragOperationGeneric;
}

- (void) setFrame:(NSRect)frameRect
{
  	[super setFrame:frameRect];

	if(_m.mode == NSHighlightModeMatrix)				// only in shelf mode
		{
		int rows = (int)(NSHeight(frame) / CELL_HEIGHT);
		int cols = (int)(NSWidth(frame) / CELL_WIDTH);

		if(rows != _numRows || cols != _numCols)
			[self renewRows:rows columns:cols];
// 		[self sizeToCells];
		}
}

@end /* Matrix */

//*****************************************************************************
//
// 		SelectionMatrix 
//
//*****************************************************************************

@implementation SelectionMatrix

- (void) sizeToCells
{
NSSize new = {-_interCell.width, -_interCell.height};

	new.width += MAX(_numCols, 1) * (_cellSize.width + _interCell.width);
	new.height += MAX(_numRows, 1) * (_cellSize.height + _interCell.height);
	[self setFrameSize: new];
}

@end /* SelectionMatrix */
