V9/jtools/src/cip/edit.c

/*
  %Z%  %M%  version %I% %Q%of %H% %T%
  Last Delta:  %G% %U% to %P%
*/

#include "cip.h"

editThing(m,p,t)  
Point m;			/* Mouse location */
Point p; 			/* Offset */
register struct thing *t;	/* Thing to be edited */
{
  register int d,dx,dy,u;  
  Point o, np; 
  if (t != TNULL) {
	  o = t->origin;
    switch(t->type) {
      case CIRCLE: {
	d = norm(o.x-m.x,o.y-m.y,0);
	if (d< (t->otherValues.radius>>1)) {
	  track(m,p,MOVE,t); 
	}
	else {
	  track(m,p,GROWCIRCLE,t);
	}
	d = t->otherValues.radius;
	break;
      }
      case BOX: {
	np = t->otherValues.corner;
	dx = (np.x - o.x)>>2;
	dy = (np.y - o.y)>>2;
	if (ptinrect(m,Rect(o.x+dx,o.y+dy,np.x-dx,np.y-dy))) {
	  if (t->boorder != SOLID) {
	    draw(t,p);
	    xbox(raddp(t->bb,p));
	  }
	  t->bb = moveBox(m,t->bb,t,p);
	  t->otherValues.corner = t->bb.corner;
	  t->origin = t->bb.origin;
	  xbox(raddp(t->bb,p));
	}
	else {
	  draw(t,p);
	  t->origin.x = 0;
	  t->origin.y = 0;
	  t->bb.origin = t->origin;
	  t->bb.corner = t->origin;
	  t->otherValues.corner = t->origin;
	  if (!ptinrect(m,Rect(o.x-dx,o.y-dy,o.x+dx,o.y-dy))) {
	    if (ptinrect(m,Rect(o.x-dx,np.y-dy,o.x+dx,np.y+dy))) {
	      np.y = o.y;
	    }
	    else {
	      if (ptinrect(m,Rect(np.x-dx,np.y-dy,np.x+dx,np.y+dy))) {
	        np = o;
	      }
	      else {
		if (ptinrect(m,Rect(np.x-dx,o.y-dy,np.x+dx,o.y+dy))) {
		  np.x = o.x;
		}
	      }
	    }
	  }
	  o = track(np,p,BOX,t);
	  t->origin.x = min(o.x,np.x);
	  t->origin.y = min(o.y,np.y);
	  t->otherValues.corner.x = max(o.x,np.x);
	  t->otherValues.corner.y = max(o.y,np.y);
	}		
	break;
      }
      case ELLIPSE: {
	dx = abs(m.x - o.x);  
	dy = abs(m.y - o.y);
	d = norm(dx,dy,0);
	if ((dx > dy) && (d > (t->otherValues.ellipse.wid>>2))) {
	  track(m,p,GROWEWID,t); 
	}
	else {
	  if ((dx < dy) && (d > (t->otherValues.ellipse.ht>>2))) {
	    track(m,p,GROWEHT,t); 
	  }
	  else {
	    track(m,p,MOVE,t); 
	  }
	}
	break;
      }
      case LINE: {
	np=t->otherValues.end;
	draw(t,p);
	if (distance(m,o)<distance(m,np)) {
	  t->origin = track(np,p,LINE,t);
	}
	else {
	  t->otherValues.end = track(o,p,LINE,t);
	}
	break;
      }
      case ARC: {
	d = (distance(o,t->otherValues.arc.start))>>1;
	if (distance(o,m)<d)  {
	  arcOrigin(t,p);
	}
	else {
	  if (distance(m,t->otherValues.arc.start)<
	      distance(m,t->otherValues.arc.end)) {
		arcStart(t,p);
	  }
	  else {
	    arcEnd(t,p);
	  }
	}
	break;
      }
      case MACRO: {
	draw(t,p);
	xbox(raddp(t->bb,p));
	t->bb = moveBox(m,t->bb,t,p);
	t->origin = t->bb.origin;
	xbox(raddp(t->bb,p));
	break;
      }
      case TEXT: {
	track(m,p,MOVE,t);
	break;
      }
      case SPLINE: {
	u = t->otherValues.spline.used;
	d=findNearestPoint(m,t->otherValues.spline.plist,u);
	if ((t->arrow==startARROW)||(t->arrow==doubleARROW)) {
	  arrow(add(p,t->otherValues.spline.plist[2]),
	        add(p,t->otherValues.spline.plist[1]));
	}
	if ((t->arrow==endARROW)||(t->arrow==doubleARROW)) {
	  arrow(add(p,t->otherValues.spline.plist[u-2]),
	        add(p,t->otherValues.spline.plist[u-1]));
	}
	if ((d == u-1) || (d==1)) {
	  xsegment
	      (add(p,t->otherValues.spline.plist[(d==1)?1:(d-1)]),
	       add(p,t->otherValues.spline.plist[(d==1)?2:d]));
	  np=track(t->otherValues.spline.plist[(d==1)?2:(d-1)],
	      p,(d==1)?REVLINE:LINE,t);	/* See note 1 in track.c */
	}
	else {
	  np=track2(p,t->otherValues.spline.plist[d-1],
	              t->otherValues.spline.plist[d+1],
	              t->otherValues.spline.plist[d]);
	}
	xspline(p,t->otherValues.spline.plist,u);
	t->otherValues.spline.plist[d]=np;
	t->origin=t->otherValues.spline.plist[1];
	break;
      }
    } /* end switch */
    BoundingBox(t);
    switch (t->type) {
      case TEXT:
      case CIRCLE:
      case ARC:
      case ELLIPSE: {
	break;
      }
      default: {
	draw(t,p);	
	break;
      }
    }
  }
} 
    
struct thing *
copyThing(t,p,offset) 
register struct thing *t; 
Point p, offset;
{
  register struct thing *c; 
  Point *pl; 
  int i, n; 

  if (t != TNULL) {
    switch(t->type) {
      case CIRCLE: {
	if ((c = newCircle(p)) != TNULL) {
	  c->otherValues.radius = t->otherValues.radius;
	}
	break;
      }
      case BOX: {
	if ((c=newBox(Rpt(p,add(p,sub(t->bb.corner,t->origin))))) 
	      != TNULL) {
	  c->boorder = t->boorder;
	}
	break;
      }
      case ELLIPSE: {
	if ((c = newEllipse(p)) != TNULL) {
	  c->otherValues = t->otherValues;
	}
	break;
      }
      case LINE: {
	if ((c = newLine(p,add(p,sub(t->otherValues.end,t->origin))))
	       != TNULL) {
	  c->boorder = t->boorder;
	  c->arrow = t->arrow;
	}
	break;
      }
      case ARC: {
	c = newArc(p,add(p, sub(t->otherValues.arc.end,
				t->otherValues.arc.start)));
	break;
      }
      case SPLINE: {
	n = t->otherValues.spline.used;
	c = TNULL;
	if ((pl = (Point *) getSpace ((n+2)*sizeof(Point)))
	     != (Point *)NULL){
	  p = sub(p, t->origin);
	  for (i=1; i<=n; i++) {
	    pl[i]=add(p,t->otherValues.spline.plist[i]);
	  }
	  c = newSpline(n,n,pl);		
	}
	break;
      }
      case TEXT: {
	if ((c = newText(p,t->otherValues.text.s)) != TNULL) {
	  c->otherValues.text.f = t->otherValues.text.f;
	  c->otherValues.text.just = t->otherValues.text.just;
	}
	break;
      }
      case MACRO: {
	c = newMacro(p,t->otherValues.list);
	break;
      }
    }
    if (c == TNULL) {
      return (c);
    }
    BoundingBox(c);
    draw(c,offset);
    return(c);
  }
  else {
    return(t);
  }
}

/* Returns the index of the point, in plist p, closest to point */
/* given by o. */

int 
findNearestPoint(o,p,n)
register Point *p;	/* Plist of spline points */
int n;			/* Number of points in Plist */
Point o;		/* Mouse location */
{
  register int i; 
  int f;		/* Plist index to point closest to o */
  int d;		/* Distance between point and o */
  int mind = -1;	/* Minimum distance */

  if (p != (Point *) NULL) {
    for (i=1; i<=n; i++) {
      d = norm(o.x-p[i].x, o.y-p[i].y, 0);
      if ((mind<0) || (mind>d)) {
	mind = d;
	f = i;
      }
    }
    return(f);
  }
  else {
    return(-1);
  }
}