/* diatypes.c
 * Copyright (C) 2001, Arjan Molenaar
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <glib-object.h>
#include "dia-geometry.h"
#include "dia-canvas.h"
#include "dia-shape.h"
#include "dia-event.h"

/*
 * Types from dia-geometry.h
 */
static gpointer dia_point_copy (gpointer p);

GType
dia_point_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaPoint",
						     dia_point_copy,
						     g_free);
	}
	return type;
}
       
static gpointer
dia_point_copy (gpointer p)
{
	DiaPoint *newp = g_new (DiaPoint, 1);
	*newp = *((DiaPoint*) p);

	return newp;
}

static gpointer dia_rectangle_copy (gpointer r);

GType
dia_rectangle_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaRectangle",
						     dia_rectangle_copy,
						     g_free);
	}
	return type;
}

static gpointer
dia_rectangle_copy (gpointer r)
{
	DiaRectangle *newr = g_new (DiaRectangle, 1);

	*newr = *((DiaRectangle*) r);

	return newr;
}

/*
 * Types in dia-shape.h
 */

static gpointer dia_shape_copy (gpointer l);

GType
dia_shape_path_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaShapePath",
						     dia_shape_copy,
						     (GBoxedFreeFunc) dia_shape_free);
	}
	return type;
}

GType
dia_shape_bezier_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaShapeBezier",
						     dia_shape_copy,
						     (GBoxedFreeFunc) dia_shape_free);
	}
	return type;
}

GType
dia_shape_ellipse_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaShapeEllipse",
						     dia_shape_copy,
						     (GBoxedFreeFunc) dia_shape_free);
	}
	return type;
}

GType
dia_shape_text_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaShapeText",
						     dia_shape_copy,
						     (GBoxedFreeFunc) dia_shape_free);
	}
	return type;
}

GType
dia_shape_image_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaShapeImage",
						     dia_shape_copy,
						     (GBoxedFreeFunc) dia_shape_free);
	}
	return type;
}

static gpointer
dia_shape_copy (gpointer l)
{
	g_assert_not_reached();
	return NULL;
}

#define DASH_SIZE(n_dash) (sizeof (DiaDashStyle) + sizeof (gdouble) * MAX (0, (n_dash) - 1))

static gpointer dia_dash_style_copy (gpointer l);

GType
dia_dash_style_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaDashStyle",
						     dia_dash_style_copy,
						     (GBoxedFreeFunc) dia_dash_style_free);
	}
	return type;
}

/**
 * dia_dash_style_new:
 * @n_dash: number of dashes to follow
 * @dash1: dash value 1 (greater than 0.0)
 * @...: second, third, etc. dash value.
 *
 * Create a new DiaDashStyle structure.
 *
 * Return value: A new DiaDashStyle
 **/
DiaDashStyle*
dia_dash_style_new (gint n_dash, gdouble dash1, ...)
{
	DiaDashStyle *dash_style;
	va_list va_args;
	gint i = 1;

	g_return_val_if_fail (n_dash > 0, NULL);

	dash_style = g_malloc (DASH_SIZE (n_dash));

	dash_style->n_dash = n_dash;

	dash_style->dash[0] = dash1;

	va_start (va_args, dash1);
	while (i < n_dash) {
		dash_style->dash[i++] = va_arg (va_args, gdouble);
	}
	va_end (va_args);

	return dash_style;
}

void
dia_dash_style_free (DiaDashStyle *dash_style)
{
	g_return_if_fail (dash_style != NULL);

	g_free (dash_style);
}

static gpointer
dia_dash_style_copy (gpointer l)
{
	gpointer new_dash;
	gint size = DASH_SIZE (((DiaDashStyle*) l)->n_dash);

	new_dash = g_malloc (size);
	g_assert (new_dash != NULL);

	memcpy (new_dash, l, size);

	return new_dash;
}


/*
 * Types from dia-canvas.h
 */

static gpointer dia_canvas_iter_copy (gpointer r);

GType
dia_canvas_iter_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaCanvasIter",
						     dia_canvas_iter_copy,
						     g_free);
	}
	return type;
}

static gpointer
dia_canvas_iter_copy (gpointer r)
{
	DiaCanvasIter *newi = g_new (DiaCanvasIter, 1);

	*newi = *((DiaCanvasIter*) r);

	return newi;
}

static gpointer dia_affine_copy (gpointer l);

GType
dia_canvas_item_affine_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaCanvasItemAffine",
						     dia_affine_copy,
						     g_free);
	}
	return type;
}

static gpointer
dia_affine_copy (gpointer l)
{
	gpointer new_affine;

	new_affine = g_new (gdouble, 6);
	g_assert (new_affine != NULL);

	memcpy (new_affine, l, sizeof(gdouble) * 6);

	return new_affine;
}

/* dia-event.h */

static gpointer dia_event_copy (gpointer l);

GType
dia_event_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaEvent",
						     dia_event_copy,
						     g_free);
	}
	return type;
}

static gpointer
dia_event_copy (gpointer l)
{
	gpointer new_event;

	new_event = g_new (DiaEvent, 1);
	g_assert (new_event != NULL);

	memcpy (new_event, l, sizeof(DiaEvent));

	return new_event;
}

static gpointer g_list_o_objects_copy (gpointer l);
static void	g_list_o_objects_free (gpointer l);

GType
dia_canvas_item_handles_get_type (void)
{
	static GType type = 0;
	
	if (!type) {
		type = g_boxed_type_register_static ("DiaCanvasItemHandles",
						     g_list_o_objects_copy,
						     g_list_o_objects_free);
	}
	return type;
}

static gpointer
g_list_o_objects_copy (gpointer l)
{
	GList *orig, *newl = NULL;
	
	for (orig = g_list_last (l); orig != NULL; orig = orig->prev) {
		g_object_ref (orig->data);
		newl = g_list_prepend (newl, orig->data);
	}
	return newl;
}
	
static void
g_list_o_objects_free (gpointer l)
{
	g_list_foreach (l, (GFunc) g_object_unref, NULL);
	g_list_free (l);
}
