ftp.nice.ch/pub/next/text/tex/apps/Bibliography.1.2a.s.tar.gz#/Bibliography.1.2a/DragView.m

This is DragView.m in view mode; [Download] [Up]

//	Copyright H. Giesen, University of Koblenz-Landau 1996


#import "Controller.h"
#import "DragView.h"
#import "BibTeXObject.h"
#import "MyBrowserCell.h"
#import "Shelf.h"
#import "Preferences.h"
#import "BufferClass.h"
#import "BibliographicFile.h"
#import "BrowserController.h"


static const char * dragTypes[3];
NXAtom	MyListPboardType;

NXImage	*entryImage = nil;
NXImage	*entryImageH;
NXImage	*entryImageMulti;
NXImage	*entryImageMultiH;
NXImage	*fileImage = nil;
NXImage	*fileImageH;
NXImage	*fileImageMulti;
NXImage	*fileImageMultiH;
NXImage	*alertImage;
NXImage	*closedBag;
NXImage	*smallImage;


#define ENTRY		1
#define BIBOBJECT	2
#define BIBFILE		3
#define TXTOBJECT	4

#define NAMETEXTTAG	6
#define DRAGVIEWTAG	7


static BufferClass	*globalBuffer;


@implementation DragView


- initialize
{
	if( entryImage==nil ){	// set class variables

		MyListPboardType = NXUniqueString( "My List Pboard Type" );

		entryImage = [NXImage findImageNamed:"Images/text"];
		entryImageH = [NXImage findImageNamed:"Images/text"];
		entryImageMulti = [NXImage findImageNamed:"Images/multiEntries"];
		entryImageMultiH = [NXImage findImageNamed:"Images/multiEntries"];

		fileImage = [NXImage findImageNamed:"Images/bibA"];
		fileImageH = [NXImage findImageNamed:"Images/bibB"];
		fileImageMulti = [NXImage findImageNamed:"Images/multiBook"];
		fileImageMultiH = [NXImage findImageNamed:"Images/multiBook"];
		
		smallImage = [NXImage findImageNamed:"Images/smallIcon"];
		alertImage = [NXImage findImageNamed:"Images/bibAlert"];
		closedBag = [NXImage findImageNamed:"Images/closedBag"];

		globalBuffer = [[BufferClass alloc] initBufferSize:128];
	}
	theObject = [[List alloc] init];
	theCell = [[MyBrowserCell alloc] initTextCell:"empty"];
	preferences = [Preferences new];
	oldMask = 0xafffe;
	return self;
}


- initFrame:(const NXRect *)frameRect
{ 
	[super initFrame:frameRect]; 
	isSelected = NO;
	return [self initialize];
}


- setShelf:(View *)theShelf
{
	shelf = theShelf;
	return self;
}


- awake	// called when unarchived
{ 
	return [self initialize];
}


- free
{
	[self clear];
	[theObject free];
	[theCell free];
	if( fileName ) free( fileName );
	return [super free];
}


- display
{
	char locBuf[64];
	char *fName;

	TextField	*titleField = [[self superview] findViewWithTag:NAMETEXTTAG];

	if( titleField==nil ) return [super display];

	if( theType == BIBFILE ){
		fName = rindex( fileName, '/' );
		if( fName )
			 [titleField setStringValue:fName+1];
		else [titleField setStringValue:fileName];
		return [super display];
	}

	if( theImage==nil ) [titleField setStringValue:NULL];
	else
	if( [theObject count]>1 ){
		sprintf( locBuf, "%d selected", [theObject count] );
		[titleField setStringValue:locBuf];
	}
	else
		if( theType ){
			[titleField setStringValue:
					[[theObject objectAt:0] stringValue]];
		}
	[super display];
	return self;
}


- (void) setFilename:(const char *)fName
{
	if( fileName ) free( fileName );
	fileName = NXCopyStringBuffer( fName );
	[theCell setObject:nil inFile:nil];
	theImage = anImage = fileImage;
	anImageH = fileImageH;
	anImageMulti = fileImageMulti;
	anImageMultiH = fileImageMultiH;
	theType = BIBFILE;
	[theObject empty];
	theImage = closedBag;
	if( access( fName, R_OK)<0 ){	// cannot read from file
		theImage = alertImage;
	}

	[self display];
}


- (char *) fileName
{
	if( theType==BIBFILE) return fileName;
	if( (theType==BIBOBJECT) && ([theObject count]==1) )
		return [[[theObject objectAt:0] fileObject] fullPath];

	return NULL;
}


- (void) setList:(List *)aList	// aList is a list of NXBrowsercells
{
	int	newType;

	if( aList!=theObject ){
		[theObject empty];
		[theObject appendList:aList];
	}
	if( aList==nil ){
		[self clear];
		return;
	}
	if( [[aList objectAt:0] object] ){	// bib_entry exist
		newType = ENTRY;
	}
	else newType = BIBOBJECT;

	if( newType!=theType ){
	  switch( newType ){
		  case ENTRY : anImage = entryImage;
					 anImageH = entryImageH;
					 anImageMulti = entryImageMulti;
					 anImageMultiH = entryImageMultiH;
					 break;
		  case BIBOBJECT: anImage = fileImage;
					 anImageH = fileImageH;
					 anImageMulti = fileImageMulti;
					 anImageMultiH = fileImageMultiH;
					 break;
		  default: break;
	  }	
	  theType = newType;
	}

	if( [theObject count]==1 ) theImage = anImage;
	else theImage = anImageMulti;
	[self display];
}


- getList	// returns a list of NXBrowsercells
{
	return theObject;
}


- (unsigned int) count
{
	return [theObject count];
}


- (void) setTextObject:(Text *)aText
{
	[theObject empty];
	[theObject addObject:aText];
	theType = TXTOBJECT;
	theImage = smallImage;
	anImage = theImage;
	anImageH = theImage;
	anImageMulti = theImage;
	anImageMultiH = theImage;
	[self display];

}


- (void )setFileObject:(BibliographicFile *)aFile
{
	// use a NXBrowserCell for compatibility
	[theCell setObject:nil inFile:aFile];
	[theCell setStringValue:[aFile fileName]];
	[theObject empty];
	[theObject addObject:theCell];
	[self setList:theObject];
}


- (int)tag
{
	return DRAGVIEWTAG;
}


- drawSelf:(const NXRect *)rects :(int)rectCount
{
	if( isSelected ) PSsetgray( NX_WHITE );
	else	PSsetgray( NX_LTGRAY );	
	NXRectFill( &bounds );
	if( theImage ){
		[theImage composite:NX_SOVER toPoint:&bounds.origin];	// was &r.org
	}
	return self;
}


- (void) clear
{
	theImage = nil;
	[theObject empty];
	if( shelf ) [[NXApp delegate] shelfText:NULL];
	[self display];
}


- unregister
{
	if( theType!=BIBOBJECT ) return self;
	theType = BIBFILE;
	theImage = closedBag;
	[self unregisterDraggedTypes];
	[self display];
	return self;
}


//vvvvvvvvvvvvvvvvv		receiving  dragging

// includesType() returns YES if type is included within types.

static BOOL includesType (const NXAtom *types, NXAtom type)
{
	if (types)
		while (*types){
			//fprintf( stderr, "%s\n", *types );
			if (*types++ == type) return YES;
		}
	return NO;
}


- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{
	NXDragOperation rtn = [self draggingUpdated:sender];
	if( (rtn==NX_DragOperationGeneric) || (rtn==NX_DragOperationCopy) ){
		// change the Image
		theImage = anImageH;
		[self display];
	}
	return rtn;
}


- (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender
{
	Pasteboard *pboard = [sender draggingPasteboard];
	char *data, *lastDot, *file, *tab;
	int length;
	
	if( [theObject count]!=1 ) return NX_DragOperationNone;

	if( [sender draggingSource]==self ){
		fprintf( stderr, "it's me\n" );
		return NX_DragOperationNone;
	}

	if( ([sender draggingSourceOperationMask] & NX_DragOperationGeneric) 
	  ||([sender draggingSourceOperationMask] & NX_DragOperationCopy) ){

		if( includesType([pboard types], MyListPboardType) ){		
			//fprintf( stderr, "MyListPboardType in fileDragView\n" );
			return NX_DragOperationCopy;
		}
		else
		if( includesType([pboard types], NXAsciiPboardType) ){		
			//fprintf( stderr, "NXAsciiPboardType in fileDragView\n" );
			return NX_DragOperationCopy;
		}
		else
		if( includesType([pboard types], NXFilenamePboardType) ){		
			//fprintf( stderr, "NXFilenamePboardType in fileDragView\n" );
			[pboard readType:NXFilenamePboardType data:&data length:&length];
			// is it a list of files ?
			file = data;
			while (file) {
				if( tab = strchr(file, '\t') ) { *tab = '\0'; }
				lastDot = rindex( file, '.' );
				if( lastDot ){ 
					if( strcmp( lastDot, ".bib" ) ) {	// only .bib allowed
						return NX_DragOperationNone;
					}
				}
				else return NX_DragOperationNone;	// no suffix -> invalid
				file = (tab) ? ++tab : NULL;
			}
			return NX_DragOperationGeneric;
		}
	}
	fprintf( stderr, "komisch\n" );
	return NX_DragOperationNone;
}


- draggingExited:sender
{
	//fprintf( stderr, "DragView draggingExited\n" );
	if( [theObject count]!=1 ) return self;
	theImage = anImage;
	[self display];
	return self;
}


- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
	char *data;
	id	*aList;
	int length;
	BOOL	rtn = NO;

	Pasteboard *pboard = [sender draggingPasteboard];
		
	if (includesType([pboard types], MyListPboardType)) {
		[pboard readType:MyListPboardType data:&data  length:&length];
		aList = (id *)data;

		// theObject is a list of one NXBrowsercell
		// we extract the fileObject from the first NXBrowserCell
		// send a list of entryObjects to the fileObject
		[[[theObject objectAt:0] fileObject] addObjects:*aList];

		rtn = YES;
	}
	else
	  if (includesType([pboard types], NXAsciiPboardType)) {
		[pboard readType:NXAsciiPboardType data:&data  length:&length];

		// theObject is a list of one NXBrowsercell
		// we extract the fileObject from the first NXBrowserCell
		// we send the ASCII - text to the fileObject
		[[[theObject objectAt:0] fileObject]
			appendNewText:length :data];
		
		[pboard deallocatePasteboardData:data length:length];
		rtn = YES;
	  }

	// change the Image
	theImage = anImage;
	[self display];

	return rtn;
}


//^^^^^^^^^^^^^^^^^		end of receiving  dragging

//  |  |  |		active  dragging
//  V  V  V

- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
	return NX_DragOperationGeneric | NX_DragOperationCopy;
}


- (void) convertBoundsToScreen:(NXRect *)screenRect
{
	NXRect	theRect;
	theRect = bounds;

	[self convertRect:&theRect toView:nil];
	[[self window] convertBaseToScreen:&theRect.origin];
	*screenRect = theRect;
}


- mouseDown:(NXEvent *)e
{
	NXPoint startPoint = e->location;
	int		nrOfClicks = e->data.mouse.click;

	savedEvent = *e;
	oldMask = [[self window] addToEventMask:NX_MOUSEDRAGGEDMASK];
	[self convertPoint:&startPoint fromView:nil];

	if( theType == TXTOBJECT ){
		//fprintf( stderr, "mouse down for text\n" );
		return self;
	}

	if( nrOfClicks==12345 ){
		isSelected = YES;
		[self display];
		return self;
	}

	if( isSelected ){
		isSelected = NO;
		[self display];
	}

	return self;
}


- mouseUp:(NXEvent *)e
{
	int		nrOfClicks = e->data.mouse.click;

	//	'help' = '?' sends mouseUp but no mouseDown --> error:
	//	 "Assertion failed:
	//	setting NX_KEYDOWN mask while window is visible is illegal"
	//	we avoid this situation by looking for (mouseDown-mouseUp) pair
	if( oldMask == 0xafffe ) return self; 	// something is wrong, no mouseDown

	if( nrOfClicks==1 ){
		char *theName;
		isSelected = NO;	//YES;
		if( shelf==nil ) return self;

		if( theType == BIBFILE ) theName = fileName;
		else theName = [[[theObject objectAt:0] fileObject] fullPath];
		[[NXApp delegate] shelfText:theName];

		if( theType == BIBFILE ){
			int	okFlag;
			[NXApp openFile:fileName ok:&okFlag];
		}
		//	start animation
		{
			NXRect sourceRect;
			NXRect destRect;
			id	theView = [[NXApp delegate] fileDragView];

			[self convertBoundsToScreen:&sourceRect];
			[theView convertBoundsToScreen:&destRect];
			[[Application workspace] slideImage:theImage 
					from:&sourceRect.origin to:&destRect.origin];
		}
		[[[NXApp delegate] browserController]
			selectFile:[[theObject objectAt:0] fileObject]];

	}
	[[self window] setEventMask:oldMask];
	oldMask = 0xafffe;
	return self;
}


- citation
{
	int	i;
	int	mode = [preferences citeMode];
	char buffer[1024];
	BibTeXObject *texObj;
	
	//	theObject is a list of browsercells of Class MyBrowserCell
	//	[theObject objectAt:i] is a cell (odf class MyBrowserCell)
	if( mode==1 )	// cite{..} cite{..} cite{..} . . .
		for( i=0; i<[theObject count]; i++ ){
			texObj = [[theObject objectAt:i] object];
			NXPrintf( dragStream, [preferences citeText] );
			NXPrintf( dragStream, "%c", LBRACE );
			[texObj copyRange:[texObj key] toBuffer:buffer];
			NXPrintf( dragStream, "%s", buffer );
			NXPrintf( dragStream, "%c", RBRACE );
			if( i!=([theObject count]-1) )
				NXPrintf( dragStream, "%s", ", " );
		}

	if( mode==2 ){	// cite{ .., .., . . . }
		NXPrintf( dragStream, [preferences citeText] );
		NXPrintf( dragStream, "%c", LBRACE );
		for( i=0; i<[theObject count]; i++ ){
			texObj = [[theObject objectAt:i] object];
			[texObj copyRange:[texObj key] toBuffer:buffer];
			NXPrintf( dragStream, "%s", buffer );
			if( i!=([theObject count]-1) )
				NXPrintf( dragStream, "%s", "," ); // no space allowed!!
		}
		NXPrintf( dragStream, "%c", RBRACE );
	}

	if( mode==3 ){	// drag the text of the selected entries 
		NXPrintf( dragStream, "\n" );
		for( i=0; i<[theObject count]; i++ ){
			texObj = [[theObject objectAt:i] object];
			[texObj copyRange:[texObj range] toStream:dragStream];

			NXPrintf( dragStream, "\n\n" );
		}
		NXPrintf( dragStream, "\n\n" );
	}

	return self;
}


- copyCitation:sender
{
	Pasteboard *pboard = [Pasteboard newName:NXGeneralPboard];

	if( !dragStream )
		dragStream = NXOpenMemory(NULL, 0, NX_READWRITE);
	NXSeek(dragStream, 0, NX_FROMSTART);

	// prepare the citation text
	[self citation];

	/*  place the citation-text on the ascii-pasteboard. */
	[pboard declareTypes:&NXAsciiPboardType num:1 owner:nil];
	[pboard writeType:NXAsciiPboardType fromStream:dragStream];

	NXCloseMemory( dragStream, NX_FREEBUFFER );
	dragStream = NULL;
	return self;
}


- mouseDragged:(NXEvent *)theEvent
{
	int	i;
	NXPoint	point = theEvent->location;
	NXPoint	origin = {0.0, 0.0};
	char	fName[128];
	Pasteboard *pboard;

	if( !theObject ) return self;

	[NXApp preventWindowOrdering];
	
	[self convertPoint:&point fromView:nil];
	//[super mouseDown:&savedEvent];
	
/* You always use the NXDragPboard pasteboard when dragging. */
	pboard = [Pasteboard newName:NXDragPboard];

	switch( theType ){
	
	case 0:	return self;

	case BIBOBJECT:
		/*  place the name of the file on the pasteboard. */
			[pboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
			// theObject is a list of one NXBrowsercell
			// first we write the names into a stream
			if( !dragStream )
				dragStream = NXOpenMemory(NULL, 0, NX_READWRITE);
			NXSeek(dragStream, 0, NX_FROMSTART);

			for( i=0; i<[theObject count]; i++ ){
				NXPrintf( dragStream, "%s",
					[[[theObject objectAt:i] fileObject] fullPath] );
				if( i==[theObject count]-1 )  NXPutc(dragStream, '\0');
				else  NXPutc(dragStream, '\t');
			}
			[pboard writeType:NXFilenamePboardType fromStream:dragStream];
			NXCloseMemory( dragStream, NX_FREEBUFFER );
			dragStream = NULL;
			break;
	
	case ENTRY:	{
			if( !dragStream )
				dragStream = NXOpenMemory(NULL, 0, NX_READWRITE);
			NXSeek(dragStream, 0, NX_FROMSTART);

		// prepare the citation text
			[self citation];

		if( strcmp( [preferences theEditor], "Edit" )==0 ){	//Edit.app
		/*  place the citation-text on the ascii-pasteboard. */
			[pboard declareTypes:&NXAsciiPboardType num:1 owner:nil];
			[pboard writeType:NXAsciiPboardType fromStream:dragStream];
		}
		else{	// emacs or so	
			sprintf( fName, "%s/citeFile", [preferences tempDirectory] );
			// copy the text to a file
			NXSaveToFile( dragStream, fName );
		/*  place the filename on the filename-pasteboard. */
			[pboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
			sprintf( [globalBuffer buffer], fName );
			[pboard writeType:NXFilenamePboardType
				data:[globalBuffer buffer]
				length:strlen( [globalBuffer buffer] )+1];
		}
		/*  place also the list of entries on my private pasteboard. */
			[pboard addTypes:&MyListPboardType num:1 owner:self];
			[pboard writeType:MyListPboardType
				data:(const char *)(&theObject) length:sizeof(id) ];

			NXCloseMemory( dragStream, NX_FREEBUFFER );
			dragStream = NULL;

			break;
			}

	case BIBFILE:
		/*  place the name of the file on the pasteboard. */
			[pboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
			[pboard writeType:NXFilenamePboardType
				data:fileName length:strlen( fileName )+1];
			break;


	case TXTOBJECT:{
			int		length;
			Text	*theText = [theObject objectAt:0];
			NXSelPt	start, end;
	
			if( theText==nil ) return self;
			[theText getSel:&start :&end];
			if( start.cp<0 ){	// text is not first responder
				return self;
			}
			length = end.cp - start.cp;
			if( length<=0 ){
				[theText selectAll:self];
			}
			/*  place the selected text on the pasteboard. */
			dragTypes[0] = NXAsciiPboardType;
			dragTypes[1] = NULL;
			[pboard declareTypes:dragTypes num:1 owner:nil];
			if( [theText writeSelectionToPasteboard:pboard types:dragTypes] ){
				break;
			}

			NXRunAlertPanel("Bibliography",
					"could not write to pasteboard",
					"  OK ",	// 1: default button
					NULL,		// 0: alternate
					NULL 		//-1: other
				);

			break;
		}

	default : fprintf( stderr, "unknown case %d\n", theType );
	 
	}


/* Now invoke dragImage: */
	[self dragImage:theImage
			at:&origin			offset:NULL		event:&savedEvent
			pasteboard:pboard	source:self		slideBack:NO];
	return self;
}


- draggedImage : (NXImage *)image 
	   endedAt : (NXPoint *)screenPoint
	 deposited : (BOOL)didDeposit
{
	NXRect winRect;

	if( didDeposit ) return self;
	if( shelf==nil ) return self;	// shall not remove

	[[self window] getFrame:&winRect];

	if( NXPointInRect(screenPoint,&winRect) ){
		return self;
	}
	if(0)fprintf( stderr, "x=%d y=%d   %d\n",
		(int)screenPoint->x, (int)screenPoint->y, didDeposit );
	theType = 0;
	[shelf removeBoxWithIcon:self];
	return self;
}



- (BOOL)shouldDelayWindowOrderingForEvent:(NXEvent *)theEvent
{
 	// This is the other portion of the new appkit functionality
	// which allows you to drag a partially obscure object without
	// making the source window become main, and without making the
	// source application the current app.
	return YES;
}


- (BOOL)acceptsFirstMouse
{
	return YES;
}


//^^^^^^^^^^^^^^^^^		end of active  dragging

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.