#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "X10.h"
#include <math.h>
#include "Xcv.h"
extern XContext circuit_data; /* from diagram.c */
extern GC mainGC; /* from diagram.c */
extern Display *dpy;

Vertex vlist[50];
XSegment slist[50];
int addv_next, adds_next;

draw_capacitor(w, x0, y0, x1, y1, width)/* ANY screen orientation!*/
Window w;
int x0, y0; /* start coordinates (connection site) */
int x1, y1; /* end of ground symbol */
int width; /* width of parallel lines */
{
  int dx, dy;
  double length;

  dx = x1-x0; dy = y1-y0;
  length = sqrt((double)(dx*dx + dy*dy));

  addv_next = 0;
  addv(x0, y0, VertexDontDraw); /*location of connection */
  addv((int)(dx*2./5.),(int)(dy*2./5.), VertexRelative); 
  /* connecting wire segment */
  addv((int)(-width/2.*dy/length),(int)(width/2.*dx/length), 
       VertexRelative | VertexDontDraw); /*to end of plate*/
  addv((int)(width*dy/length),(int)(-width*dx/length), 
       VertexRelative );/*1st*/
  addv(dx/10, dy/10, VertexRelative | VertexDontDraw);/*to next plate end*/
  addv((int)(-width*dy/length),(int)(width*dx/length), 
       VertexRelative );/*2nd*/
  addv((int)(x0+5./10.*dx),(int)(y0+5./10.*dy), VertexDontDraw);
  /*mid of plate end*/
  addv((int)(x0+4.5/5.*dx),(int)(y0+4.5/5.*dy), 0);
  /*draw wire from cap to ground*/
  addv((int)(-width/4.*dy/length),(int)(width/4.*dx/length), 
       VertexRelative | VertexDontDraw);/*pos to end of big ground plate*/
  addv((int)(width/2.*dy/length),(int)(-width/2.*dx/length), 
       VertexRelative ); /*1st ground plate*/
  addv((int)(x0+4.75/5.*dx),(int)(y0+4.75/5.*dy),VertexDontDraw);
  addv((int)(-width/8.*dy/length),(int)(width/8.*dx/length), 
       VertexRelative | VertexDontDraw);
  addv((int)(width/4.*dy/length),(int)(-width/4.*dx/length), 
       VertexRelative ); /*2nd ground plate*/
  addv(x1, y1, VertexDontDraw);
  addv((int)(-width/16.*dy/length),(int)(width/16.*dx/length), 
       VertexRelative | VertexDontDraw);
  addv((int)(width/8.*dy/length),(int)(-width/8.*dx/length), VertexRelative
      );/*last ground plate*/
  XDraw(dpy, w, mainGC, vlist, addv_next);
}

draw_diode(w, x0, y0, x1, y1, width) /* up or down ONLY! (x1==x0) */
Window w;
int x0, y0; /* inflow connection site */
int x1, y1; /* outflow connection site */
{
  if (x0 != x1) return; /* Can only draw vertical diodes */
  addv_next=0;
  addv((int)(x1-width/2), y1, VertexDontDraw);
  addv((int)(x1+width/2), y1, 0);
  addv(x1, y1, VertexDontDraw);
  addv((int)(x1+width/2), y0, 0);
  addv((int)(x1-width/2), y0, 0);
  addv(x1, y1, 0);
  XDraw(dpy, w, mainGC, vlist, addv_next);
/*NEW ... not quite right.
  adds_next=0;
  adds((int)(x1-width/2), y1, (int)(x1+width/2), y1);
  adds(x1, y1, (int)(x1+width/2), y0);
  adds((int)(x1-width/2), y0, x1, y1);
  XDrawSegments(dpy, w, mainGC, slist, adds_next);
*/
}

draw_resistor(w, x0, y0, x1, y1, width)/* up->down or left->right only*/
Window w;
int x0, y0;
int x1, y1;
{
  int delta;

  addv_next = 0;
  addv(x0, y0, VertexDontDraw);
  if (y0==y1) {
    delta = (x1-x0)/6;
    addv((int)(delta/2), (int)(-width/2), VertexRelative);
    addv(delta, width, VertexRelative);
    addv(delta, -width, VertexRelative);
    addv(delta, width, VertexRelative);
    addv(delta, -width, VertexRelative);
    addv(delta, width, VertexRelative);
    addv(x1, y1, 0);
  } else {
    delta = (y1-y0)/6;
    addv((int)(-width/2), (int)(delta/2), VertexRelative);
    addv(width, delta, VertexRelative);
    addv( -width, delta, VertexRelative); 
    addv(width, delta, VertexRelative);
    addv( -width, delta, VertexRelative); 
    addv(width, delta, VertexRelative);
    addv(x1, y1, 0);
  }
  XDraw(dpy, w, mainGC, vlist, addv_next);
/*NEW ... not quite right
  adds_next = 0;
  if (y0==y1) {
    delta = (x1-x0)/6;
    adds(x0, y0, (int)(delta/2), (int)(-width/2));
    adds(delta, width, delta, -width);
    adds(delta, width, x1, y1);
  } else {
    delta = (y1-y0)/6;
    adds(x0, y0, (int)(-width/2), (int)(delta/2));
    adds(width, delta, -width, delta);
    adds(width, delta, x1, y1);
  }
  XDrawSegments(dpy, w, mainGC, slist, adds_next);
*/
}

addv(x, y, flags)
int x, y, flags;
{
  vlist[addv_next].x = x;
  vlist[addv_next].y = y;
  vlist[addv_next++].flags = flags;
}

adds(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
  slist[adds_next].x1 = x1;
  slist[adds_next].y1 = y1;
  slist[adds_next].x2 = x2;
  slist[adds_next++].y2 = y2;
}

mk_heart(w, x0, y0, x1, y1, ym, rev, heartMap)
Window w;
int x0, y0, x1, y1, ym, rev;
Pixmap heartMap;
{
  int dx, dy, xmid, tmp;
  CircInfo *cinfo;

  if (!heartMap) return;
  if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) {
    dx = x1-x0;
    dy = y1-y0;
    
    XCopyArea(dpy, heartMap, w, mainGC,0,0, cinfo->width, cinfo->height, 0, 0);
    switch (cinfo->type) {
    case IconWindow:
      mk_icn(w);
      break;
    case CircuitWindow:
      if (rev) {tmp = x0; x0 = x1; x1 = tmp;}
      rev = rev ? -1 : 1;
      xmid = x0+rev*(int)(0.5*dx);
      dy = ym-y0;
      if (rev == -1) {tmp = ym; ym = y0; y0 = tmp;}
      XDrawLine(dpy, w, mainGC, xmid, y0, xmid, (int)(y0+rev*dy/5));
      draw_diode(w, xmid, (int)(y0+rev*dy/5), 
		 xmid, (int)(y0+rev*dy/5+rev*dy/15), (int)(dy/12));
      XDrawLine(dpy, w, mainGC, xmid, (int)(y0+rev*dy/5+rev*dy/15), 
    		xmid, (int)(y0+2*rev*dy/5));
      draw_diode(w, xmid, (int)(y0+rev*2*dy/5), 
		 xmid,  (int)(y0+rev*2*dy/5+rev*dy/15), (int)(dy/12));
      XDrawLine(dpy, w, mainGC, xmid, (int)(y0+rev*2*dy/5+rev*dy/15), 
    		xmid, ym-rev*20-rev*15);
      draw_resistor(w, xmid, ym-rev*20-rev*15, xmid, ym-rev*20, 8);
      XDrawLine(dpy, w, mainGC, xmid, ym-rev*20, xmid, ym);
      tmp = y0+rev*dy/5+rev*dy/10+rev*dy/30;
      draw_capacitor(w, xmid, tmp, x0+rev*5, tmp, (int)(dy/10));
      break;
    }
  }
}
