/*
 *                            COPYRIGHT
 *
 *  PCB, interactive printed circuit board design
 *  Copyright (C) 1994,1995,1996 Thomas Nau
 *
 *  This module, drill.c, was written and is Copyright (C) 1997 harry eaton
 *
 *  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.
 *
 *  Contact addresses for paper mail and Email:
 *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
 *  Thomas.Nau@rz.uni-ulm.de
 *
 */

static  char    *rcsid = "$Id: drill.c,v 144.1 1997/07/30 07:08:17 nau Exp $";

#include "data.h"
#include "error.h"
#include "mymem.h"

/*
 * some local prototypes
 */
static void FillDrill(DrillTypePtr, ElementTypePtr, PinTypePtr);
static void InitializeDrill(DrillTypePtr, PinTypePtr, ElementTypePtr);


static void FillDrill(DrillTypePtr Drill, ElementTypePtr Element, PinTypePtr Pin)
{
	Cardinal n;
	ElementTypeHandle ptr;
	PinTypeHandle pin;

	pin = GetDrillPinMemory(Drill);
	*pin = Pin;
	if (Element)
	{	
		Drill->PinCount++;
		for (n = Drill->ElementN - 1; n != -1; n--)
			if (Drill->Element[n] == Element)
				break;
		if (n == -1)
		{
			ptr = GetDrillElementMemory(Drill);
			*ptr = Element;
		}
	}
	else
		Drill->ViaCount++;
}

static void InitializeDrill(DrillTypePtr drill, PinTypePtr pin, ElementTypePtr element)
{
	void *ptr;

	drill->DrillSize = pin->DrillingHole;
	drill->ElementN = 0;
	drill->ViaCount = 0;
	drill->ElementMax = 0;
	drill->Element = NULL;
	drill->PinN = 0;
	drill->Pin = NULL;
	drill->PinMax = 0;
	ptr = (void *) GetDrillElementMemory(drill);
	*((ElementTypeHandle) ptr) = element;
	ptr = (void *) GetDrillPinMemory(drill);
	*((PinTypeHandle) ptr) = pin;
	drill->PinCount = 1;
}

DrillInfoTypePtr	GetDrillInfo(DataTypePtr top)
{
	DrillInfoTypePtr	AllDrills;
	DrillTypePtr		Drill;
	DrillType			savedrill, swapdrill;
	Boolean				DrillFound = False;
	Boolean				NewDrill;

	AllDrills = MyCalloc(1, sizeof(DrillInfoType), "GetAllDrillInfo()");
	ALLPIN_LOOP(top, {
		if (!DrillFound)
		{
			DrillFound = True;
			Drill = GetDrillInfoDrillMemory(AllDrills);
			InitializeDrill(Drill, pin, element);
		}
		else
		{
			if (Drill->DrillSize == pin->DrillingHole)
				FillDrill(Drill, element, pin);
			else
			{
				NewDrill = False;
				DRILL_LOOP(AllDrills, 
					if (drill->DrillSize == pin->DrillingHole)
					{
						Drill = drill;
						FillDrill(Drill, element, pin);
						break;
					}
					else if (drill->DrillSize > pin->DrillingHole)
					{
						if (!NewDrill)
						{
							NewDrill = True;
							InitializeDrill(&swapdrill, pin, element);
							Drill = GetDrillInfoDrillMemory(AllDrills);
							Drill->DrillSize = pin->DrillingHole + 1;
							Drill = drill;
						}
						savedrill = *drill;
						*drill = swapdrill;
						swapdrill = savedrill;
					}
				);
				if (AllDrills->Drill[ AllDrills->DrillN -1 ].DrillSize < pin->DrillingHole)
				{
					Drill = GetDrillInfoDrillMemory(AllDrills);
					InitializeDrill(Drill, pin, element);
				}
			}
		}
	});
	VIA_LOOP(top, {
		if (!DrillFound)
		{
			DrillFound = True;
			Drill = GetDrillInfoDrillMemory(AllDrills);
			Drill->DrillSize = via->DrillingHole;
			FillDrill(Drill, NULL, via);
		}
		else
		{
			if (Drill->DrillSize != via->DrillingHole)
			{
				DRILL_LOOP(AllDrills, 
					if (drill->DrillSize == via->DrillingHole)
					{
						Drill = drill;
						FillDrill(Drill, NULL, via);
						break;
					}
				);
				if (Drill->DrillSize != via->DrillingHole)
				{
					Drill = GetDrillInfoDrillMemory(AllDrills);
					Drill->DrillSize = via->DrillingHole;
					FillDrill(Drill, NULL, via);
				}
			}
			else
				FillDrill(Drill, NULL, via);
		}
	});
	return(AllDrills);
}

void FreeDrillInfo(DrillInfoTypePtr Drills)
{
	DRILL_LOOP(Drills, {
		MyFree((char **)&drill->Element);
		MyFree((char **)&drill->Pin);
	});
	MyFree((char **)&Drills->Drill);
	SaveFree(Drills);
}
