/*
 *                            COPYRIGHT
 *
 *  PCB, interactive printed circuit board design
 *  Copyright (C) 1994,1995,1996 Thomas Nau
 *
 *  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: insert.c,v 145.1 1997/07/26 12:56:22 nau Exp $";

/* functions used to insert points into objects
 */

#include "global.h"

#include "copy.h"
#include "create.h"
#include "data.h"
#include "draw.h"
#include "insert.h"
#include "misc.h"
#include "move.h"
#include "select.h"
#include "set.h"
#include "undo.h"

/* ---------------------------------------------------------------------------
 * some local prototypes
 */
static	void	*InsertPointIntoLine(LayerTypePtr, LineTypePtr);
static	void	*InsertPointIntoPolygon(LayerTypePtr, PolygonTypePtr);

/* ---------------------------------------------------------------------------
 * some local identifiers
 */
static	Position			InsertX,	/* used by local routines as offset */
							InsertY;
static	Cardinal		InsertAt;
static	ObjectFunctionType	InsertFunctions = {
	InsertPointIntoLine,
	NULL,
	InsertPointIntoPolygon,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL };

/* ---------------------------------------------------------------------------
 * inserts a point into a line
 */
static void *InsertPointIntoLine(LayerTypePtr Layer, LineTypePtr Line)
{
	LineTypePtr	line;

        if (((Line->Point1.X == InsertX) && (Line->Point1.Y == InsertY)) ||
            ((Line->Point2.X == InsertX) && (Line->Point2.Y == InsertY)))
                return(NULL);
                /* Create a new line in the correct place, then modify the original */
                /* clear the rat-line flag in case a rat is being modified */
        if (TEST_FLAG(RATFLAG, Line))
        {
                AddObjectToFlagUndoList(LINE_TYPE, Layer, Line, Line);
                CLEAR_FLAG(RATFLAG, Line);
        }
        line = CreateNewLineOnLayer(Layer, InsertX, InsertY,
                Line->Point2.X, Line->Point2.Y, Line->Thickness, Line->Flags & ~RATFLAG);
	AddObjectToMoveUndoList(LINEPOINT_TYPE, Layer, Line, &Line->Point2,
			InsertX - Line->Point2.X, InsertY - Line->Point2.Y);
	EraseLine(Line);
        Line->Point2.X = InsertX;
	Line->Point2.Y = InsertY;
        AddObjectToCreateUndoList(LINE_TYPE, Layer, line, line);
	IncrementUndoSerialNumber();
	DrawLine(Layer, Line, 0);
        DrawLine(Layer, line, 0);
        return(line);
}

/* ---------------------------------------------------------------------------
 * inserts a point into a polygon
 */
static void *InsertPointIntoPolygon(LayerTypePtr Layer, PolygonTypePtr Polygon)
{
	PointType	save;
	Cardinal	n;

	ErasePolygon(Polygon);

		/* first of all get the index where the new point is to be
		 * inserted; this is necessary because 'CreateNewPointInPolygon()'
		 * may change some pointers
		 *
		 * second move all points of greater index up by one
		 */
	save = *CreateNewPointInPolygon(Polygon, InsertX, InsertY);
	for (n = Polygon->PointN-1; n > InsertAt; n--)
		Polygon->Points[n] = Polygon->Points[n-1];
	Polygon->Points[InsertAt] = save;
	SetPolygonBoundingBox(Polygon);
	DrawPolygon(Layer, Polygon, 0);
	SetChangedFlag(True);
	AddObjectToInsertPointUndoList(POLYGONPOINT_TYPE, Layer, Polygon,
		&Polygon->Points[InsertAt]);
	return(Polygon);
}

/* ---------------------------------------------------------------------------
 * inserts point into objects
 */
void *InsertPointIntoObject(int Type, void *Ptr1, void *Ptr2, Cardinal *Ptr3,
	Position DX, Position DY)
{
	void	*ptr;

		/* setup offset */
	InsertX = DX;
	InsertY = DY;
	InsertAt = *Ptr3;

		/* the operation insert the points to the undo-list */
	ptr = ObjectOperation(&InsertFunctions, Type, Ptr1, Ptr2, Ptr3);
	if (ptr != NULL)
		IncrementUndoSerialNumber();
	return(ptr);
}
