/****************************************************************************
    Copyright (C) 1987-2005 by Jeffery P. Hansen

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************/
#include <stdio.h>
#include <assert.h>
#include "tkgate.h"

GWire *wire_root(GWireNode *n)
{
  GWire *w;
  int i;

  w = wirenode_driver(n);
  if (w->gate)
    switch (w->gate->typeinfo->Code) {
    case JOINT :
      for (i=0;i<4;i++)
	if (w->gate->wires[i] &&
	    (w->gate->wires[i]->nodes->in))
	  return wire_root(w->gate->wires[i]->nodes);
      break;
    case TAP :
      if (w->gate->wires[TAP_TAP] != w)
	return wire_root(w->gate->wires[TAP_IN]->nodes);
      break;
    }
  return w;
}

/*
 * Set the size of the selected wire to the current wire size
 */
void setwiresize(EditState *es)
{
  GWire *r;
  int size;

  ob_touch(XGate.circuit);

  if (!(XGate.circuit->wnsel = wire_hit(XGate.ed->tx,XGate.ed->ty,es->env->wires)))
    XGate.circuit->wnsel = wire_iohit(XGate.ed->tx,XGate.ed->ty,es->env->wires);

  if (XGate.circuit->wnsel) {
    const char *str_size = Tcl_GetVar(XGate.tcl,"tkg_bitWidth",TCL_GLOBAL_ONLY);

    size = 1;
    assert(str_size);
    sscanf(str_size,"%d",&size);

    XGate.circuit->wsel = wirenode_driver(XGate.circuit->wnsel);
    r = wire_root(XGate.circuit->wnsel);
    wire_drawnet(r);
    net_setSize(r->net,size);
    wire_drawnet(r);
    SetModified();
  }
}

void wire_drawnet_aux(GWire *w,int isFirst)
{
  int i;

  w = wire_other(w);

  if (!isFirst) {
    wire_draw(wire_driver(w)->nodes);
    if (w->gate && w->gate->typeinfo->Flags.WireProps) gate_draw(w->gate,GD_NOWIRE);
  }

  if (w->gate) {
    switch (w->gate->typeinfo->Code) {
    case JOINT :
      gate_draw(w->gate,GD_NOWIRE);
      for (i=0;i<4;i++)
	if (w->gate->wires[i] && (w->gate->wires[i] != w))
	  wire_drawnet_aux(w->gate->wires[i],0);
      break;
    case TAP :
      if (w == w->gate->wires[TAP_OUT])
	wire_drawnet_aux(w->gate->wires[TAP_IN],0);
      else if (w == w->gate->wires[TAP_IN])
	wire_drawnet_aux(w->gate->wires[TAP_OUT],0);
      break;
    case LED :
      gate_draw(w->gate,GD_NOWIRE);
      break;
    }
  }
}

void wire_drawnet(GWire *w)
{
  GWire *o_w;

  if (!w) return;

  o_w = wire_other(w);

  wire_drawnet_aux(w,0);
  wire_drawnet_aux(o_w,1);

  if (w->gate && w->gate->typeinfo->Flags.WireProps) gate_draw(w->gate,GD_NOWIRE);
}
