/*
Pencil V2.0, Copyright 1994, 95 by Florian Marquardt.
This program may be distributed under the terms of the GNU general
public license (Start Pencil and select "Copyright" in the Help panel for a copy of the
license).
Pencil has a built-in TCL interpreter (tcl 7.3 by John Ousterhout). This is under a separate
license (see "Copyright").
*/
// Pencil uses a tcl interpreter (tcl 7.3 by John Ousterhout)
// Note: The tcl7.3 distribution is not part of the Pencil source code distribution,
// you must get it to compile PencilTWO (See README)
// THIS IS THE COPYRIGHT NOTICE CONCERNING TCL:
/*
 * Copyright (c) 1993 The Regents of the University of California.
 * All rights reserved.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */
// END OF COPYRIGHT NOTICE FOR TCL

#import "PencilView.h"
#import "PencilGraphic.h"
#import "MultipleSelection.h"
#import "Group.h"
#import "PencilImage.h"
#import "PencilText.h"
#import "GUI.h"

#define EX te->location.x
#define EY te->location.y

#define EDITED if(!edited) { edited=YES; [window setDocEdited:YES]; }

BOOL movementStatus=0;	// currently moving a graphic? (EPS images only redrawn when move finished)
extern BOOL globalTermination;
id globalText=nil; // used for drawing RichText
int globWillDispCG=NO;
BOOL globalClearBG=YES;
char *globBuf=NULL;
int globLen, globMaxLen;

float *fpts=NULL;	// array for points for freehand drawing... global since there is only one mouse
int maxfpts=200;	// arraysize=2*maxfpts*sizeof(float)
float athresh, sumthresh;

extern unsigned char currentLayer;  // in PencilInspector.m
extern Tcl_Interp *TCLip;

extern unsigned long long int layersVisible1;
extern unsigned long long int layersVisible2;
extern unsigned long long int layersSelectable1;
extern unsigned long long int layersSelectable2;

extern id globGUI; // in PencilTCL.m

#define DISPLAY(r) globWillDispCG=YES; [self display: r: 1]; globWillDispCG=NO

@implementation PencilView
+ initialize
{
	[self setVersion: 2];
	return self;
}

- initFrame:(const NXRect *)re
{
	const char *mytype[2] = {NXAsciiPboardType, NXFilenamePboardType};

	[super initFrame:re];
	glist=[[List alloc] init];
	myPrintInfo=[[PrintInfo alloc] init];
	[NXApp setPrintInfo: myPrintInfo];
	docInfo=NULL;
	scale=100;
	if(fpts==NULL)
	{	fpts=(float *)malloc(sizeof(float)*2*maxfpts);  }
	if(!globalText)
	{
	globalText=[[Text alloc] init];
	[globalText setMonoFont:NO];
	[globalText setEditable:NO];
	[globalText setSelectable:NO];
	[globalText setFlipped:YES];
	[globalText setClipping:NO];
	}
	if(flippedView=[[View alloc] initFrame:&bounds]) // for RichText editing
	{
		[flippedView setFlipped:YES];
	}
	[[NXApp printInfo] setHorizPagination: NX_AUTOPAGINATION];
	[[NXApp printInfo] setVertPagination: NX_AUTOPAGINATION];
	[self registerForDraggedTypes:mytype count:2];
	return self;
}

- (BOOL)acceptsFirstResponder { [NXApp setPrintInfo: myPrintInfo]; return YES; }

- awakeFromNib
{
	[window makeKeyAndOrderFront:self];
	[inspector inspectForView:self];
	return self;
}

- free
{
	int i;

	if(glist) {
	i=[glist count];
	while(i--) [[glist objectAt:i] free];	
	[glist free];
	}
	if(customDef)	free(customDef);
	if(docname) free(docname);
	[myPrintInfo free];
	[NXApp setPrintInfo: nil];
	if(docInfo) free(docInfo);
	return [super free];
}

- (BOOL)acceptsFirstMouse { return YES; }

- drawSelf:(const NXRect *)re:(int)co
{
	int i,c; id g;
	
	if(!initialized || NXDrawingStatus!=NX_DRAWING)
	{
	if(NXDrawingStatus==NX_DRAWING)
	{
		Tcl_GlobalEval( TCLip, "P_PSdraw");
		initialized=YES;
	}
	else
	{
		Tcl_GlobalEval( TCLip, "P_PSprint");
		if(customDef) DPSPrintf(DPSGetCurrentContext(), " %s\n ", customDef);
	}
	}
	[window disableFlushWindow];
	PSsetgray(1);
	if(re)	{ NXRectClip(re); if(globalClearBG) NXRectFill(re); } else if(globalClearBG) NXRectFill(&bounds);
	c=[glist count];
	if(NXDrawingStatus!=NX_DRAWING)
		for(i=0;i<c;i++) [[glist objectAt:i] draw:re];
	else
		for(i=0;i<c;i++) if(![(g=[glist objectAt:i]) selected]) [g draw:re];
	if(NXDrawingStatus!=NX_DRAWING)
		Tcl_GlobalEval( TCLip, "P_PSprintend");
	[window reenableFlushWindow];
	if(!globWillDispCG) {
		if(!editingRichText)
			[self perform: @selector(dispCurGr:) with: nil afterDelay: 0 cancelPrevious: YES];
	}
	return self;
}

- displayCurrentGraphic
{
	if(currentGraphic)
	{
	[self lockFocus];
		PSsetinstance(YES);
		PSnewinstance();
		[currentGraphic drawControl:NULL:curPt:500/scale];
		PSsetinstance(NO);
	[self unlockFocus];
	}
	return self;
}

- dispCurGr: sender
{
	return [self displayCurrentGraphic];
}

- displayWithCurrentGraphic
{
	globWillDispCG=YES;
	[self display];
	globWillDispCG=NO;
	[self displayCurrentGraphic];
	return self;
}

- setCurrentGraphicAndDisplay:(id)gr
{
	currentGraphic=gr;
	[self displayCurrentGraphic];
	return self;
}

#define IFCUR if(currentGraphic)
#define CUR currentGraphic

const char *txtinit="/text (Text) def /fontsize 32 def /font (Helvetica) def";

#define ADJUST [self convertPoint:&te->location fromView:nil]
// The mouseDown method: the largest method in Pencil 
// Don't ask me how it works (I hope it does)
// Of course, this isn't good programming style; but once upon a while, it started out as
// a little, understandable method and then it grew and grew...
- mouseDown:(NXEvent *)te
{
	// command-click: create new graphic
	// click: if currentGraphic selected: select/move pts or move graphic
	// 		if not: try to select/move graphic
	// control-click: rotate
	// control-shift-click: scale uniformly, control-shift-alt-click: scale x/y
	
	if(!editingRichText)
	{
	if(te->flags & NX_COMMANDMASK) // create
	{
		char *mname; NXColor c1; NXColor c2; float lw; char *dm; char *fm; char *sm; char *ud; NXRect rec; BOOL displ; 

		if(!(currentLayer<=63 ? (layersSelectable1&(1ULL<<currentLayer)): (layersSelectable2&(1ULL<<(currentLayer-64)))))
			[inspector correctCurLayer];
		EDITED;
		IFCUR { [CUR calculateBoundingBox:self]; [CUR giveBounds:&rec]; [CUR select:NO]; displ=YES;  }
			else	displ=NO;
		[inspector giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
		if(!currentGraphic && !strncmp(mname,"charP", 5))
		{
					[inspector setUserDef:txtinit];
					ud=txtinit;
		}
		if(!strcmp(mname,"RT"))
			[glist addObject:CUR=[[[[PencilText alloc] init] initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud] setLayer: currentLayer]];
		else
			[glist addObject:CUR=[[[[PencilGraphic alloc] init] initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud] setLayer: currentLayer]];
		curGrPos=[glist count]-1;
		[CUR select:YES];
		if(displ) { DISPLAY(&rec); }
		// if RichText desired
		if(!strcmp(mname,"RT"))
		{
			editingRichText=YES;
			[self addSubview:flippedView];
			[flippedView setFrame:&bounds];
			[CUR editText:te:self:flippedView];
		}
		else
		{
		if([[[[[inspector creationType] target] itemList] selectedCell] tag]==1)
		{
			athresh=[[ inspector athreshField] floatValue];
			sumthresh=[[inspector sthreshField] floatValue];
			if(athresh<.1) athresh=1.5;
			if(sumthresh<.1)	sumthresh=.9;
			[CUR createPolyFreehand:te:&curPt:self:500/scale];
		}
		else
		{
			[CUR create:te:&curPt:self:500/scale];
		}
		}
	}
	else	// select graphic/point, move point
	{
		[self convertPoint:&te->location fromView:nil];

		IFCUR
		{
			if([CUR isMemberOf:[PencilText class]])
			{
				if(te->data.mouse.click==2)				{
					editingRichText=YES;
					EDITED;
					[self addSubview:flippedView];
					[flippedView setFrame:&bounds];
					[CUR editText:te:self:flippedView];
					return self;
				}
			}

			if(!(te->flags & NX_CONTROLMASK)) { // not rotating/scaling
			// select pt, move it
			if([CUR move:te:&curPt:self:500/scale])	{ EDITED; return self; }
			}
		}

		{	// select graphic
			int i, selCount=0;
			id curcur=currentGraphic;

			IFCUR {[CUR calculateBoundingBox: self];}
			if(!CUR && !(te->flags & NX_CONTROLMASK)) te->flags&=(~NX_SHIFTMASK);
			
			// removed: && ![CUR isMemberOf:[MultipleSelection class]] :
			
			[self lockFocus];
			if(CUR && ((te->flags & NX_CONTROLMASK) || (!(te->flags&NX_SHIFTMASK)  && (!(te->flags & NX_ALTERNATEMASK))  && [CUR selected: te: &curPt: self])))
			{
				i=curGrPos; // selected old one... move it.
				if([CUR isMemberOf: [MultipleSelection class]]) i=[glist count]+1;
			}
			else
			{
				id g;

				i=[glist count]; while(i--) { if([g=[glist objectAt:i] selected]) ++selCount; if([g selected:te:&curPt:self] && (i<curGrPos || !(te->flags & NX_ALTERNATEMASK))) break; }
			}
			[self unlockFocus];
			if(i>=0)
			{
				char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
				NXRect rec; BOOL multipleSelChanged=NO;

				if((te->flags & NX_SHIFTMASK) && !(te->flags & NX_CONTROLMASK)) // multiple selection
				{
				if(![[glist objectAt:i] selected])
				{
					if(!CUR || ![CUR isMemberOf:[MultipleSelection class]])
					{
						IFCUR {
						CUR=[[MultipleSelection alloc] initWithGraphic:CUR];
						[CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:selCount];
						}
						else
						{
							CUR=[[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];
						}
					}
					else
						[CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:selCount];
					multipleSelChanged=YES;
				}
				}
				else
				{
					if(!CUR || ![CUR isMemberOf:[MultipleSelection class]] || (i<[glist count] && ![[glist objectAt:i] selected]))
					{
					CUR=[glist objectAt:i];
					curGrPos=i;
					[CUR select:YES];
					}
				}
				if(curcur!=CUR && curcur!=nil && (!multipleSelChanged || ![CUR partOfSelection:curcur]))
				{
					[curcur calculateBoundingBox:self];
					[curcur giveBounds:&rec];
					[curcur select:NO];
					DISPLAY(&rec);
				}
				if(curcur!=CUR   || multipleSelChanged)
				{
					[CUR calculateBoundingBox:self];
					[CUR giveBounds:&rec];
					DISPLAY(&rec);
				}
				[self lockFocus];
				PSsetinstance(YES);
				if(curcur!=CUR   || multipleSelChanged)
				{
				PSnewinstance();
				[currentGraphic drawControl:NULL:curPt:500/scale];
				}
				if(curcur!=CUR)
				{
				[CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
				[inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
				[inspector takeLayer: [CUR getLayer]];
				}
				{	// moving/rotating/scaling the selection
	
			if(te->flags & NX_CONTROLMASK) // rotate or scale
				{
			if(te->flags & NX_SHIFTMASK) // scale
			{
 	int	oldMask;
	BOOL shouldLoop=YES;
	float dx,dy, oldscalex=1, oldscaley=1, newscalex, newscaley;
	NXEvent thisEvent;
	
	EDITED;
	
    	oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];

	dx=te->location.x; dy=te->location.y;

    while (shouldLoop) {
        do {
	te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
                                         NX_LMOUSEDRAGGEDMASK)];
    	} while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));

   	ADJUST;
	newscalex=(EX-dx)/20+1;
	if(!(te->flags & NX_ALTERNATEMASK)) newscaley=newscalex; else newscaley=(EY-dy)/20+1;
	if(fabs(newscalex)<1e-3) newscalex=1e-3;
	if(fabs(newscaley)<1e-3) newscaley=1e-3;
	[CUR scaleCenter:dx:dy by:newscalex/oldscalex:newscaley/oldscaley];
	oldscalex=newscalex;
	oldscaley=newscaley;
	PSnewinstance();
	[CUR drawControl:NULL:curPt:500/scale];
	PSflushgraphics();
	NXPing();
	if(te->type==NX_LMOUSEUP) shouldLoop=NO;
    }
	PSnewinstance();
	[CUR drawControl:NULL:curPt:500/scale];
	PSflushgraphics();
	NXPing();
	PSsetinstance(NO);
	[self unlockFocus];
    [window setEventMask:oldMask];
	return self;
			}
			else
			{
  	int	oldMask;
	BOOL shouldLoop=YES;
	float dx,dy;
	BOOL placingHorizontal=YES;
	NXPoint pt0, pt1;
	NXEvent thisEvent;
	
    	oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];

	dx=te->location.x; dy=te->location.y;


    while (shouldLoop) {
            do {
	te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
                                         NX_LMOUSEDRAGGEDMASK | NX_LMOUSEDOWNMASK)];
    	} while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));

   	ADJUST;
		if(placingHorizontal)
		{
			PSnewinstance();
			[CUR drawControl:NULL:curPt:500/scale];
			PSsetgray(0);
			PSmoveto(dx-5,dy);
			PSrlineto(10,0); PSstroke();
			PSmoveto(dx, dy-5);
			PSrlineto(0,10); PSstroke();
			PSmoveto(dx,dy);
			PSlineto(te->location.x, te->location.y);
			PSstroke();
			PSflushgraphics();
			NXPing();
		}
		else
		{
			[CUR rotateAroundCenter:dx:dy fromPoint:&pt1 toPoint:&te->location];
			pt1=te->location;
			PSnewinstance();
			[CUR drawControl:NULL:curPt:500/scale];
			PSsetgray(.5);
			PSmoveto(dx-5,dy);
			PSrlineto(10,0); PSstroke();
			PSmoveto(dx, dy-5);
			PSrlineto(0,10); PSstroke();
			PSmoveto(dx,dy);
			PSlineto(pt0.x, pt0.y);
			PSstroke();
			PSflushgraphics();
			NXPing();
		}
		if(te->type==NX_LMOUSEUP)
		{
			if(placingHorizontal)
			{
				placingHorizontal=NO;
				pt0=pt1=te->location;
				if(pt0.x==dx && pt0.y==dy) { pt0.x+=30; pt1=pt0; }
			}
			else
				shouldLoop=NO;
		}
    }
	PSnewinstance();
	[CUR drawControl:NULL:curPt:500/scale];
	PSflushgraphics();
	NXPing();
	PSsetinstance(NO);
	[self unlockFocus];
    [window setEventMask:oldMask];
	return self;
}
}
else
{
  	int	oldMask;
	BOOL shouldLoop=YES;
	float dx,dy;
	NXEvent thisEvent;
	
    	oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];

	dx=te->location.x; dy=te->location.y;

    while (shouldLoop) {
        do {
	te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
                                         NX_LMOUSEDRAGGEDMASK)];
    	} while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));

   	ADJUST;
	if(EX!=dx || EY!=dy)
	{
	movementStatus=1;
	EDITED;
	[CUR addTranslation:EX-dx:EY-dy];
	dx=EX; dy=EY;
	PSnewinstance();
	[CUR drawControl:NULL:curPt:500/scale];
	PSflushgraphics();
	NXPing();
	}
	if(te->type==NX_LMOUSEUP)
		shouldLoop=NO; 

    }
    	if(movementStatus) {
		movementStatus=0;
		[CUR drawIfNeeded:NULL:curPt:500/scale];
	}
	PSsetinstance(NO);
	[self unlockFocus];
    [window setEventMask:oldMask];
    }
}
			}
			else		// no graphic selected
			{
				IFCUR
				{
					NXRect rec;

					[CUR calculateBoundingBox:self];
					[CUR giveBounds:&rec];
					[CUR select:NO];
					CUR=nil; curGrPos=-1;
					DISPLAY(&rec);
					[self lockFocus]; PSnewinstance(); [self unlockFocus];
					[inspector clearUserDef:nil];
				}
				// drag selection
{	  int	oldMask;
	BOOL shouldLoop=YES;
	float dx,dy;
	int c=[glist count];
	NXRect theSel, thebounds;

    	oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];

	dx=te->location.x; dy=te->location.y;

	[self lockFocus];
	PSsetinstance(YES);
	
    while (shouldLoop) {
        te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
                                         NX_LMOUSEDRAGGEDMASK)];

   	ADJUST;
	if(EX!=dx || EY!=dy)
	{
	PSnewinstance();
	PSsetgray(.5);
	PSrectstroke(dx,dy,EX-dx,EY-dy);
	PSflushgraphics();
	}
	if(te->type==NX_LMOUSEUP)
		shouldLoop=NO; 

    }
	PSsetinstance(NO);
	PSnewinstance();
	[self unlockFocus];
    [window setEventMask:oldMask];
	
	if(dx<EX) { theSel.origin.x=dx;  theSel.size.width=EX-dx; } else { theSel.origin.x=EX; theSel.size.width=dx-EX; }
	if(dy<EY) { theSel.origin.y=dy; theSel.size.height=EY-dy; } else { theSel.origin.y=EY; theSel.size.height=dy-EY; }
	if(theSel.size.width>=1 && theSel.size.height>=1)
	{
	id obj;
	
	for(i=0;i<c;i++)	{
	if([obj=[glist objectAt: i] selectable]) {
	[obj giveBounds:&thebounds];
	if(NXIntersectsRect(&theSel, &thebounds))
	{
		IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
		else
		{	[CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];
		 }
	}
	}
	}
	IFCUR {
	[CUR calculateBoundingBox:self];
	[CUR giveBounds:&thebounds];
	DISPLAY(&thebounds);
	[self displayCurrentGraphic];
	}
	}
}
			}
		}
	}
	}
	else
		[window endEditingFor:self];
	return self;
}

- (BOOL)makeGroup
{
	id oldcur;

	if(CUR && [CUR isMemberOf:[MultipleSelection class]])
	{
	EDITED;
	oldcur=CUR;
	[glist addObject:CUR=[[[Group alloc] initEmpty] select:YES]];
	[oldcur moveElementsFrom:glist to:[CUR slist]];
	[oldcur select:NO];
	[CUR select: YES];
	curGrPos= [glist count]-1;
	return YES;
	}
	else
		return NO;
}

- ungroup
{
	if(CUR && [CUR isKindOf:[Group class]])
	{
		id sl, old;
		int i,c,pos;
	
		EDITED;
		sl=[old=CUR slist];
		c=[sl count];
		pos=[glist indexOf:CUR];
		[glist removeObject:CUR];
		CUR=[[MultipleSelection alloc] initEmpty];
		[old addElementsTo:[CUR slist]];
		for(i=0;i<c;i++)	[glist insertObject:[sl objectAt:i] at:pos+i];
		[old freeLeafObjects];
	}
	return self;
}

- ungroup:sender
{
	[self ungroup];
	[self displayWithCurrentGraphic];
	return self;
}

- makeStandardGroup:sender
{
	if([self makeGroup])
	{
		[CUR setGroupType:PENCIL_STANDARD_GROUP];
		[self displayCurrentGraphic];
	}
	return self;
}

- makeClipGroup:sender
{
	if([self makeGroup])
	{
		[CUR setGroupType:PENCIL_CLIP_GROUP];
		[self displayCurrentGraphic];
	}
	return self;
}

- deselectAll:sender
{
				IFCUR
				{
					NXRect rec;

					if(editingRichText)
					{
						[window endEditingFor:self];
						editingRichText=NO;
					}

					[CUR calculateBoundingBox:self];
					[CUR giveBounds:&rec];
					[CUR select:NO];
					CUR=nil; curGrPos=-1; 
					DISPLAY(&rec);
					[self lockFocus]; PSnewinstance(); [self unlockFocus];
					[inspector clearUserDef:nil];
				}
	return self;
}
- selectAll:sender
{
	int c=[glist count], i;
	NXRect thebounds;
	id obj;
	
	IFCUR { [CUR select:NO]; CUR=nil; curGrPos=-1; }
	for(i=0;i<c;i++)	{
		if([obj=[glist objectAt: i] selectable]) {
		IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
		else
		{	[CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];  }
		}
	}
	[CUR calculateBoundingBox:self];
	[CUR giveBounds:&thebounds];
	NXIntersectionRect(&bounds,&thebounds);
	DISPLAY(&thebounds);
	[self displayCurrentGraphic];
	return self;
}
- setMethodname:(char*)name { IFCUR { if(!strcmp(name, "RT") && ![CUR isMemberOf: [PencilText class]]) return nil; else { [CUR setMethodname:name]; EDITED; } } return [self displayCurrentGraphic]; }
- setDrawingMethod:(char *)name { IFCUR  { [CUR setDrawingMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
- setStrokeMethod:(char *)name { IFCUR { [CUR setStrokeMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
- setFillMethod:(char *)name { IFCUR { [CUR setFillMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
- setSpecialAttributes:(char *)name { IFCUR { [CUR setSpecialAttributes:name]; EDITED; } return [self displayCurrentGraphic]; }
- setColor1:(NXColor)col { IFCUR { [CUR setColor1:col]; EDITED; } return [self displayCurrentGraphic];}
- setColor2:(NXColor)col { IFCUR { [CUR setColor2:col]; EDITED; } return [self displayCurrentGraphic]; }
- setLineWidth:(float)lw { IFCUR { [CUR setLineWidth:lw]; EDITED; } return [self displayCurrentGraphic]; }
- changeScale:sender
{
	float sc;

	sc=atoi([[sender selectedCell] title]);
	if(sc>0)
	{
	[self setScale: sc];
//	[self display];
	}
	return self;
}
- scroll:sender
{
	switch([sender tag])
	{
	case 0: [self translate:0:bounds.size.height*[scrollFactor floatValue]]; break;
	case 1: [self translate:0:bounds.size.height*(-[scrollFactor floatValue])]; break;
	case 2: [self translate:bounds.size.width*(-[scrollFactor floatValue]):0]; break;
	case 3: [self translate:bounds.size.width*[scrollFactor floatValue]:0]; break;
	}
	[self display];
	return self;
}
- toFront:sender
{
	IFCUR
	{
		EDITED;
		if([CUR isMemberOf:[MultipleSelection class]])
			[CUR toFrontIn:glist];
		else
		{
		if(curGrPos!=[glist count]-1)
		{
			[glist removeObjectAt:curGrPos];
			[glist addObject:currentGraphic];
		}
		}
	}
	return self;
}
- toBack:sender
{
	IFCUR
	{
		EDITED;
		if([CUR isMemberOf:[MultipleSelection class]])
			[CUR toBackIn:glist];
		else
		{
		if(curGrPos!=0)
		{
			[glist removeObjectAt:curGrPos];
			[glist insertObject:currentGraphic at:0];
		}
		}
	}
	return self;
}
- insertPoint:sender
{
	IFCUR	{	EDITED; [(PencilGraphic *)currentGraphic insertPoint:&curPt]; [self displayCurrentGraphic]; }
	return self;
}
- insertNextPoint:sender
{
	IFCUR	{	EDITED; [(PencilGraphic *)currentGraphic insertNextPoint:&curPt]; [self displayCurrentGraphic]; }
	return self;
}
- deletePoint:sender
{
	IFCUR	{	EDITED; [(PencilGraphic *)currentGraphic deletePoint:&curPt]; [self displayCurrentGraphic]; }
	return self;
}

- insertThreePoints:sender
{
	IFCUR	{	EDITED; [(PencilGraphic *)currentGraphic insertThreePoints:&curPt]; [self displayCurrentGraphic]; }
	return self;
}
- alignThreePoints:sender
{
	IFCUR	{	EDITED; [(PencilGraphic *)currentGraphic alignThreePoints:&curPt]; [self displayCurrentGraphic]; }
	return self;
}

- keyDown:(NXEvent *)te
{
	if(te->data.key.charCode==127)
		[self deleteGraphic:self];
	else
	{
	switch((char)(te->data.key.charCode))
	{
	case '8': [self translate:0:bounds.size.height*[scrollFactor floatValue]]; break;
	case '2': [self translate:0:bounds.size.height*(-[scrollFactor floatValue])]; break;
	case '4': [self translate:bounds.size.width*(-[scrollFactor floatValue]):0];  break;
	case '6': [self translate:bounds.size.width*[scrollFactor floatValue]:0];  break;
	case ' ' :
	case 13: return [self paste:self:YES]; break;
	}
	[self display];
	}
	return self;
}

- deleteGraphic:sender
{
	IFCUR {
		EDITED;
		if([CUR isMemberOf:[MultipleSelection class]])
   			[CUR deleteThemIn:glist];
		else {
			[glist removeObjectAt:curGrPos];
			[CUR free];
		}
 		curGrPos=-1;
		currentGraphic=nil;
		[self lockFocus];
		PSnewinstance();
		[self unlockFocus];
	}
	return self;
}

- writeDoc:(NXTypedStream *)stream
{
	int n, i;
	NXRect wframe;

	[window getFrame:&wframe];
	NXWriteRect(stream, &wframe);
	NXWriteRect(stream, &bounds);
	NXWriteRect(stream, &frame);
	n=-[glist count]; // why minus? because we don't have a version number *^)
	NXWriteTypes(stream,"f*i",&scale, &customDef, &n);
	NXWriteRootObject( stream, myPrintInfo);
	NXWriteType( stream, "*", &docInfo);
	for(i=0;i<-n;i++)
		NXWriteRootObject(stream, [glist objectAt:i]);
	return self;
}

- readDoc:(NXTypedStream *)stream
{
	int n;
	NXRect nbounds, nframe, wframe;

	NXReadRect(stream, &wframe);
	NXReadRect(stream, &nbounds);
	NXReadRect(stream, &nframe);
	NXReadTypes(stream,"f*i",&scale, &customDef,&n);
	if(n<0) {
		myPrintInfo=NXReadObject(stream);
		NXReadType(stream, "*", &docInfo);
		n=-n;
	} else myPrintInfo=[[PrintInfo alloc] init];
	[glist=[List alloc] setAvailableCapacity:n];
	while(n--) [glist addObject:NXReadObject(stream)];
	[self notifyAncestorWhenFrameChanged: YES];
	[window disableDisplay];
	[window placeWindow:&wframe];
	[self setFrame:&nframe];
	[self setDrawSize:nbounds.size.width:nbounds.size.height];
	[self setDrawOrigin:nbounds.origin.x: nbounds.origin.y];
	[window reenableDisplay];
	[NXApp setPrintInfo: myPrintInfo];
	return self;
}

- doSave:(char *)filename
{
	NXTypedStream *st;
	
	if(st=NXOpenTypedStreamForFile(filename, NX_WRITEONLY))
	{
	edited=NO;
	[window setDocEdited:NO];
	[self writeDoc:st];
	NXCloseTypedStream(st);
	}
	return self;
}

- saveAs:sender
{
	[[SavePanel new] setRequiredFileType:"pencil"];
	if([[SavePanel new] runModal]==NX_OKTAG)
	{
	if([[SavePanel new] filename])
	{
	if(docname) free(docname);
	docname=(char *)malloc(sizeof(char)*(strlen([[SavePanel new] filename])+1));
	strcpy(docname, [[SavePanel new] filename]);
	[window setTitleAsFilename:docname];
	[self doSave:docname];
	}
	}
	return self;
}

- save:sender
{
	if(docname) [self doSave:docname]; else [self saveAs:sender];
	return self;
}

- readFromFilename:(char *)name
{
	int i;
	NXStream *st;
	
	if(st=NXOpenTypedStreamForFile(name, NX_READONLY))
	{
	if(glist) {
	i=[glist count];
	while(i--) [[glist objectAt:i] free];	
	[glist free];
	}
	if(customDef)	free(customDef);
	if(docname) free(docname);
	docname=(char *)malloc(sizeof(char)*(strlen(name)+1));
	strcpy(docname, name);
	[window setTitleAsFilename:docname];
	[self readDoc:st];
	NXCloseTypedStream(st);
	[self sendCustom];
	// [self display];
	[window display];
	}
	return self;
}

- windowDidBecomeMain:sender
{
	char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;

	[inspector inspectForView:self];
	IFCUR { 				[CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
				[inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
}
    	[NXApp setPrintInfo: myPrintInfo];
	return self;
}

- updateInspector
{
	char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;

	IFCUR { 	
		[CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
		[inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
	}
	return self;
}

- changeCUR
{
	char *name; NXColor co1; NXColor co2; float lw; char *dm, *fm, *sm, *ud;
	
	[inspector giveSettings:&name:&co1:&co2:&lw:&dm:&fm:&sm:&ud];
	[CUR setMethodname:name];
	[CUR setColor1:co1];
	[CUR setColor2:co2];
	[CUR setLineWidth:lw];
	[CUR setDrawingMethod:dm];
	[CUR setFillMethod:fm];
	[CUR setStrokeMethod:sm];
	[CUR setSpecialAttributes:ud];
	[CUR setLayer: currentLayer];
	return self;
}

- windowWillClose:sender
{
	int ch;

	if(!globalTermination)
	{
	if(edited)
	{
	if(docname)
		ch=NXRunAlertPanel("Close Document", "Do you want to save \"%s\" before closing it?", "Save","Don't save","Cancel", docname);
	else
		ch=NXRunAlertPanel("Close Document", "Do you want to save the yet unnamed document before closing it?", "Save","Don't save","Cancel");
	switch(ch)
	{
	case 0: [inspector viewVanished:self]; return self;
	case 1: [self save:self]; [inspector viewVanished:self]; return self;
	case -1: return nil;
	}
	}
	}
	else
	{
	if(edited)
	{
	if(docname)
		ch=NXRunAlertPanel("Close Document", "Do you want to save \"%s\" before quitting?", "Save","Don't save","Cancel", docname);
	else
		ch=NXRunAlertPanel("Close Document", "Do you want to save the yet unnamed document before quitting?", "Save","Don't save","Cancel");
	switch(ch)
	{
	case 0: [inspector viewVanished:self]; return self;
	case 1: [self save:self]; [inspector viewVanished:self]; return self;
	case -1: globalTermination=NO; return nil;
	}
	}
	}
	[inspector viewVanished:self]; return self;
}

-copy:sender
{
    const char  *const types[1] = {"PencilPBoardType"};
    id           pb = [Pasteboard new];
    char        *data;
    int          length;

	if(currentGraphic)
	{
	[CUR calculateBoundingBox:self];
    [pb declareTypes:types num:1 owner:nil];
    data = NXWriteRootObjectToBuffer(currentGraphic, &length);
    [pb writeType:types[0] data:data length:length];
    NXFreeObjectBuffer(data, length);
	}  
  return self;
}

- copyAsPostScript:sender
{
    const char  *const types[1] = {NXPostScriptPboardType};
	NXRect vis;
	
	[[Pasteboard new] declareTypes:types num:1 owner:nil];
	IFCUR {
		[CUR calculateBoundingBox: self];
		[CUR giveBounds: &vis];
	} else {
		[self getVisibleRect: &vis];
	}
	[self writePSCodeInside:&vis to:[Pasteboard new]];
  return self;
}

- cut:sender
{
	[self copy:sender];
	[self deleteGraphic:sender];
	return self;
}

- paste:sender
{
	return [self paste:sender:NO]; // no centering
}

-paste:sender:(BOOL)flag
{
    char  **type;
    id      pb = [Pasteboard new];
    char   *data;
    int     length;

    for(type = [pb types];*type;type++) {
        if(!strcmp(*type,"PencilPBoardType"))
            break;
    }
    if(*type) {
				char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;

				IFCUR
				{
					NXRect rec;

					[CUR calculateBoundingBox:self];
					[CUR giveBounds:&rec];
					[CUR select:NO];
					CUR=nil;
					curGrPos=-1;
					DISPLAY(&rec);
					[self lockFocus]; PSnewinstance(); [self unlockFocus];
				}

        [pb readType:*type data:&data length:&length];
         currentGraphic =NXReadObjectFromBuffer(data, length);
	if([CUR isMemberOf:[MultipleSelection class]])
		[CUR addElementsTo:glist];
	else
		[glist addObject:CUR];
    NXFreeObjectBuffer(data, length);
	if(flag)
	{
		NXPoint c;
		
		[window getMouseLocation:&c];
		[self convertPoint:&c fromView:nil];
		[CUR centerAt:&c];
	}
	else
		[currentGraphic addTranslation:-10:-10];
	curGrPos=[glist count]-1;
		[CUR select:YES];
				[self lockFocus];
				PSsetinstance(YES);
				PSnewinstance();
				[currentGraphic drawControl:NULL:curPt:500/scale];
				[CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
				[inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
				PSsetinstance(NO);
				[self unlockFocus];
		EDITED;
	}
    return self;
}

- sendCustom
{
	[self lockFocus];
	DPSPrintf(DPSGetCurrentContext(), " %s\n ", customDef);
	[self unlockFocus];
	return self;
}

- takeCustomFrom:(id)text
{
	if(customDef) free(customDef);
	customDef=(char *)malloc(sizeof(char)*([text textLength]+1));
	[text getSubstring:customDef start:0 length:[text textLength]+1];
	[self sendCustom];
	[self display];
	EDITED;
	return self;
}

- giveCustomTo:(id)text
{
	[text setText:(const char *)customDef];
	return self;
}

- importImage:sender
{
	const char *types[]={ "tiff", "eps", "rib", NULL };

	if([[OpenPanel new] runModalForTypes:types]==NX_OKTAG)
	{
		Tcl_GlobalEval( TCLip, "P_beforeImgImport");
		[self importImageFromFile:[[OpenPanel new] filename]:bounds.origin.x+5:bounds.origin.y+5];
		Tcl_GlobalEval( TCLip, "P_afterImgImport");
		[self displayCurrentGraphic];
	}
	return self;
}

- importImageFromFile:(char *)name:(float)posx:(float)posy
{
		char *mname; NXColor c1; NXColor c2; float lw; char *dm; char *fm; char *sm; char *ud;
		[self deselectAll:self];
		[inspector giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
		if(CUR=[[PencilImage alloc] initFromFile:name])
		{
			curGrPos=[glist count];
			[glist addObject:CUR];
			[CUR select:YES];
			[CUR initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud];
			[CUR addTranslation:posx:posy];
			[CUR calculateBoundingBox:self];
			EDITED;
		}
		return self;
}

- richTextEnded:sender
{
	editingRichText=NO;
	[flippedView removeFromSuperview];
	return self;
}

- convertToCharPath:sender
{
	IFCUR {
		// is it a RichText?
		if([currentGraphic isKindOf:[PencilText class]])
		{
		id newtxt;
		char *mname; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
		
		[window endEditingFor:self];
		EDITED;
		newtxt=[[PencilGraphic alloc] init];
		[CUR makeCharacterPath: self: newtxt]; // RichTxt will initialize CharP
		[glist addObject:newtxt];
		[self deleteGraphic:self];
		CUR=newtxt;
		curGrPos=[glist count]-1;
		[CUR select:YES];
		[self displayWithCurrentGraphic];
		{
				[CUR giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
				[inspector takeSettings:mname:c1:c2:lw:dm:fm:sm:ud];
		}
		}
	}
	return self;
}

// for TCL:
- (int)objectcount { return [glist count]; }
- (void)descFor: (int)num: (Tcl_Interp *)interp
{
	if(num>=0 && num<[glist count]) {
		[[glist objectAt:num] giveDescription: interp];
	}
}
- (void)giveSelection: (Tcl_Interp *)interp
{
	char string[10];

	IFCUR {
		if([CUR isMemberOf:[MultipleSelection class]]) {
			id slist;
			int i;
			
			slist=[CUR slist];
			for(i=0;i<[slist count];i++) {
				sprintf(string, "%d", [glist indexOf:[slist objectAt:i]]);
				Tcl_AppendElement( interp, string);
			}
		} else {
		sprintf(string, "%d", curGrPos);
		Tcl_AppendResult( interp, string, NULL);
		}
	}
}
- (void)deleteObj: (int)num
{
		EDITED;
		[self deselectAll:self];
		[glist removeObjectAt:num];
}
- (void)giveName: (Tcl_Interp *)interp
{
	if(docname)
		Tcl_AppendResult( interp, docname, NULL);
}
- (void)setScale: (float)dx
{
	NXRect nframe;
	float ox, oy;
	NXRect vis;
	id scv;
	
	ox=bounds.origin.x;
	oy=bounds.origin.y;
/*	printf("scale: f: %g %g %g %g\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
	printf(" b: %g %g %g %g\n", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); */
	
	[[self superview] getVisibleRect: &vis];
	[window disableDisplay];
	[self scale:dx/scale:dx/scale];
	nframe=frame;
	nframe.size.width*=dx/scale;
	nframe.size.height*=dx/scale;
	[self setFrame: &nframe];
	[self setDrawOrigin: ox: oy];
	[[self superview] setDrawOrigin: (vis.origin.x+vis.size.width*(1-scale/dx)/2)*dx/scale: (vis.origin.y+vis.size.height*(1-scale/dx)/2)*dx/scale];
	[window reenableDisplay];
/*	printf("after: f: %g %g %g %g\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
	printf(" b: %g %g %g %g\n", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); */
	[scv=[[self superview] superview] reflectScroll: [self superview]];
/*	[[scv horizScroller] display];
	[[scv vertScroller] display]; */
	[scv display];
	scale=dx;
}

- (void)display1: (int)num
{
	NXRect rec;
	id g;
	
	if(num>=0 && num<[glist count]) {
		g=[glist objectAt: num];	
		[g calculateBoundingBox: self];
		[g giveBounds: &rec];
		DISPLAY(&rec);
	}
}
- (int)select1: (int) num
{
	NXRect rec;
	
	IFCUR { [self deselectAll:self]; }
	if(num>=0 && num<[glist count]) {
	CUR=[glist objectAt: num];
	[CUR select:YES];
	curGrPos=num;
	[CUR calculateBoundingBox: self];
	[CUR giveBounds: &rec];
	DISPLAY(&rec);
	}
	return TCL_OK;
}
- (int)select: (Tcl_Interp *)interp: (int) argc: (char **)argv
{
	int  i, j, c=[glist count];
	NXRect rec;
	
	IFCUR { [self deselectAll:self]; }
	for(j=1;j<argc;j++)	{
		i=atoi(argv[j]);
		if(i>=0 && i<c)
		{
		IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
		else
		{	[CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];  }
		}
	}
	IFCUR {
	[CUR calculateBoundingBox:self];
	[CUR giveBounds: &rec];
	DISPLAY(&rec);
	}
	return TCL_OK;
}
- (id)curGraphic { return CUR; }
- (int)addObject: (int)type: (int)where
{
	id g;
	
	EDITED;
		switch(type)
		{
			case 0: g=[PencilGraphic alloc]; break;
			case 1: g=[PencilText alloc]; break;
			default: return -1;
		}
		if(where<0)
		{
			[glist addObject: g];
			return [glist count]-1;
		}
		else
		{
			[glist insertObject: g at: where];
			return where;
		}
}
- (void)changeobject: (Tcl_Interp *)interp: (int)num: (char *)desc
{ 
	id g;
	
	EDITED;
		if(num>=0 && num<[glist count])
		{
			g=[glist objectAt: num];
			[g initFromDescription: interp: desc];
			[g calculateBoundingBox:self];
			sprintf(interp->result, "%d", num);
		}
}

- (void)performForObject: (id)obj: (char *)what
{
	if([obj isKindOf: [MultipleSelection class]]) {
		id sl=[obj slist];
		int i;
		
		i=[sl count];
		while(i--) {
			[self performForObject: [sl objectAt: i]: what];
		}
	} else {
		Tcl_ResetResult(TCLip);
		[obj giveDescription: TCLip];
		Tcl_SetVar( TCLip, "OBJ", TCLip->result, 0);
		if(Tcl_VarEval( TCLip, what, NULL)==TCL_OK) {
		[obj initFromDescription: TCLip: Tcl_GetVar( TCLip, "OBJ", 0)];
		[obj calculateBoundingBox: self];
		}
	}
}

- (void)setEdited { EDITED; }

- (void)writeObject: (int)num to: (char *)file
{
	NXTypedStream *ts=NULL;
	NXStream *s=NULL;
	
	if(num==-1 || (num>=0 && num<[glist count])) {
	if(file[0]=='-') {
		if(s=NXOpenMemory( NULL, 0, NX_WRITEONLY))
			ts=NXOpenTypedStream(s, NX_WRITEONLY);
	} else
		ts=NXOpenTypedStreamForFile( file, NX_WRITEONLY);
	if(ts) {
		id obj;
		
		if(num==-1) obj=CUR; else obj=[glist objectAt: num];
		NXWriteRootObject( ts, obj);
		NXCloseTypedStream( ts);
	}
	if(s) {
		if(globBuf)
			vm_deallocate(task_self(), (vm_address_t)globBuf,
        globMaxLen);
		NXGetMemoryBuffer(s, &globBuf, &globLen, &globMaxLen);
		NXCloseMemory(s, NX_SAVEBUFFER);
	}
	}
}

- (void)readObjectFrom: (char *)file
{
	NXTypedStream *ts=NULL;
	NXStream *s=NULL;
	
	if(file[0]=='-') {
		if(globBuf)
			if(s=NXOpenMemory( globBuf, globLen, NX_READONLY))
				ts=NXOpenTypedStream(s, NX_READONLY);
	} else
		ts=NXOpenTypedStreamForFile( file, NX_READONLY);

	if(ts) {
		[glist addObject: [NXReadObject( ts) select:NO]];
		NXCloseTypedStream( ts);
		EDITED;
	}
	if(s) NXClose(s);
}

- (void)writePSIn: (float)x: (float)y: (float)w: (float) h: (char *)file
{
	NXStream *s;
	
	if(s=NXOpenMemory( NULL, 0, NX_WRITEONLY)) {
		NXRect re;
		
		re.origin.x=x;
		re.origin.y=y;
		re.size.width=w;
		re.size.height=h;
		[self copyPSCodeInside: &re to: s];
		NXSaveToFile( s, file);
		NXClose( s);
	}
}

- (id)glist { return glist; }

- getLayers: (unsigned long long int *)lv1:(unsigned long long int *)lv2: (unsigned long long int *)ls1:(unsigned long long int *)ls2
{
	*lv1=layersVis1;
	*lv2=layersVis2;
	*ls1=layersSel1;
	*ls2=layersSel2;
	return self;
}
- (char *)performCommand:(const char *)cmd
{
	return "";
}

- setLayers: (unsigned long long int)lv1:(unsigned long long int)lv2: (unsigned long long int)ls1:(unsigned long long int)ls2
{
	layersVis1=lv1;
	layersVis2=lv2;
	layersSel1=ls1;
	layersSel2=ls2;
	return self;
}

- takeLayer: (unsigned char) ly
{
	IFCUR {
		[CUR setLayer: ly];
	}
	return self;
}

- runPageLayout: sender
{
	NXRect *pr;
	float l, r, t, b;
	char str[100];
	
	if([[PageLayout new] runModal]) {
	pr=[[NXApp printInfo] paperRect];
	[[NXApp printInfo] getMarginLeft: &l right: &r top: &t bottom: &b];
	sprintf(str, "P_pageLayout %g %g %g %g %g %g\n", pr->size.width, pr->size.height, l, r, t, b);
	Tcl_GlobalEval( TCLip, str);
	}
	return self;
}

- (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
{  return YES; }

- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
	Pasteboard *pboard;
	NXPoint loc;
	
	pboard=[sender draggingPasteboard];
	loc=[sender draggedImageLocation];
	[self convertPoint: &loc fromView: nil];
	if([globGUI takeDrag: pboard: &loc: "P"])
		return YES;
	else
		return NO;
}

- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{
	return NX_DragOperationCopy|NX_DragOperationGeneric;
}

// from Draw:
- windowWillResize:sender toSize:(NXSize *)size
{
    NXRect fRect, cRect;

    [ScrollView getFrameSize:&cRect.size
	      forContentSize:&frame.size
	       horizScroller:YES vertScroller:YES
		  borderType:NX_NOBORDER];
		 cRect.origin.x=cRect.origin.y=0;
    [Window getFrameRect:&fRect forContentRect:&cRect style:[window style]];
//    printf("%g %g %g %g %g %g\n", frame.size.width, frame.size.height, cRect.size.width, cRect.size.height, fRect.size.width, fRect.size.height);
    size->width = MIN(fRect.size.width, size->width);
    size->height = MIN(fRect.size.height+23, size->height);
    size->width = MAX(250, size->width);
    size->height = MAX(150, size->height);
    return self;
}

- windowDidMove: sender
{
	return [self displayCurrentGraphic];
}
@end
