/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: template.c
 *	Created ..: Sunday 22-Dec-91 21:23:14
 *	Revision .: 1
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	02-Oct-92   Michael Bjerking       New realese, better Screen/Window editor
 *	31-Dec-91   Torsten Jürgeleit      new font management
 *	22-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Template part
 *
 * $Revision Header ********************************************************/

 /* Includes */

#include "includes.h"
#include "defines.h"
#include "imports.h"
#include "protos.h"

 /* Get current template by given ordinal number from list */

struct Template *
get_template_by_num(LONG num)
{
	struct Template *tp;

	for (tp = get_head((struct List *) & template_list.tl_Templates); tp; tp = get_succ(&tp->tp_Node))
	{
		if (!num--)
		{
			CopyMem((BYTE *) & tp->tp_Box, (BYTE *) & current_box, (LONG) sizeof(struct Box));
			break;
		}
	}

	selected_template = tp;
	return (tp);
}

 /* Get current template by given mouse pos from list */

struct Template *
get_template_by_pos(SHORT x, SHORT y)
{
	struct Template *tp;

	if (tp = find_template_by_pos(x, y))
	{
		CopyMem((BYTE *) & tp->tp_Box, (BYTE *) & current_box, (LONG)
				sizeof(struct Box));
	}
	selected_template = tp;
	return (tp);
}

 /* Find template by given mouse pos from list */

struct Template *
find_template_by_pos(SHORT x, SHORT y)
{
	struct Template *tp;
	struct Box *box;

	/* First check info template */
	if (info_displayed == TRUE)
	{
		tp = info_template;
		box = &tp->tp_Box;
		if (x >= box->bo_X1 && x <= box->bo_X2 && y >= box->bo_Y1 && y <=
			box->bo_Y2)
		{
			return (tp);
		}
	}

	/* Now check templates in list (from last to first) */
	for (tp = get_tail((struct List *) & template_list.tl_Templates); tp;
		 tp = get_pred(&tp->tp_Node))
	{
		box = &tp->tp_Box;
		if (x >= box->bo_X1 && x <= box->bo_X2 && y >= box->bo_Y1 && y <=
			box->bo_Y2)
		{
			return (tp);
		}
	}
	return (NULL);
}

 /* Fix bounds of current template */

VOID
fix_template_bounds(VOID)
{
	struct Box *box = &current_box;

	if (box->bo_X1 > box->bo_X2)
	{
		SHORT temp = box->bo_X2;

		box->bo_X2 = box->bo_X1;
		box->bo_X1 = temp;
	}
	if (box->bo_Y1 > box->bo_Y2)
	{
		SHORT temp = box->bo_Y2;

		box->bo_Y2 = box->bo_Y1;
		box->bo_Y1 = temp;
	}
	if (box->bo_X1 < 0)
	{
		box->bo_X1 = 0;
	}
	if (box->bo_Y1 < 0)
	{
		box->bo_Y1 = 0;
	}
	if (box->bo_X2 > pwin->Width)
	{
		box->bo_X2 = pwin->Width;
	}
	if (box->bo_Y2 > pwin->Height)
	{
		box->bo_Y2 = pwin->Height;
	}
}

 /* Get modify mode from selected position */

USHORT
get_modify_mode(SHORT x, SHORT y)
{
	struct Template *tp = selected_template;
	struct Box *box = &tp->tp_Box;
	UBYTE type = tp->tp_Type;
	USHORT part_width = (box->bo_X2 - box->bo_X1) / 8, part_height = (box->bo_Y2 - box->bo_Y1) / 4, modify_mode = MODIFY_MODE_MOVE;

	if (type != TEMPLATE_TYPE_TEXT && type != TEMPLATE_TYPE_CHECK &&
		type != TEMPLATE_TYPE_MX)
	{
		if (x >= (box->bo_X2 - part_width) && x <= box->bo_X2 &&
			y >= (box->bo_Y2 - part_height) && y <= box->bo_Y2)
		{
			modify_mode = MODIFY_MODE_RESIZE;
		}
	}
	return (modify_mode);
}

 /* Create new template and add it to template list */

struct Template *
create_template(struct TemplateList *tl)
{
	struct Template *tp;
	SHORT status = EDITOR_STATUS_NORMAL;

	if (!(tp = AllocMem((LONG) sizeof(struct Template),
						 (LONG) MEMF_PUBLIC | MEMF_CLEAR)))
	{
		status = EDITOR_ERROR_OUT_OF_MEM;
	}
	else
	{

		/* Init template */
		tp->tp_Node.ln_Name = &tp->tp_TemplateName[0];
		tp->tp_Type = template_type;
		CopyMem((BYTE *) & current_box, (BYTE *) & tp->tp_Box, (LONG)
				sizeof(struct Box));
		NewList(&tp->tp_TextList);
		if ((status = init_default_template_data(tl, tp, FALSE)) !=
			EDITOR_STATUS_NORMAL)
		{
			free_template(tl, tp);
			tp = NULL;
		}
		else
		{

			/* Add new template to list and refresh list view */
			add_template_to_list(tl, tp, TRUE);
			ISetGadgetAttributes(egl, EDITOR_GADGET_TEMPLATES, 0L, 0L,
								 USE_CURRENT_VALUE, USE_CURRENT_VALUE, &tl->tl_Templates);
		}
	}
	show_error(status);
	return (tp);
}

 /* Add template to list */

VOID
add_template_to_list(struct TemplateList * tl, struct Template * tp,
					 BOOL default_name)
{
	struct List *list = (struct List *) & tl->tl_Templates;
	USHORT num, pos;

	/* Get group data */
	switch (TEMPLATE_GROUP(tp))
	{
	case TEMPLATE_GROUP_BORDER:
		num = ++tl->tl_BorderTemplates;
		pos = num - 1;
		break;

	case TEMPLATE_GROUP_TEXT:
		num = ++tl->tl_TextTemplates;
		pos = tl->tl_BorderTemplates + num - 1;
		break;

	case TEMPLATE_GROUP_GADGET:
		num = ++tl->tl_GadgetTemplates;
		pos = tl->tl_BorderTemplates + tl->tl_TextTemplates + num - 1;
		break;
	}

	/* Init template and insert it into template list */
	tp->tp_GroupEntryNum = num;
	if (default_name == TRUE)
	{
		build_default_template_name(tl, tp);
	}
	Insert(list, &tp->tp_Node, (pos ? get_node(list, pos - 1) : NULL));
}

 /* Build default template name */

VOID
build_default_template_name(struct TemplateList *tl, struct Template *tp)
{
	BYTE *fmt;

	switch (TEMPLATE_GROUP(tp))
	{
	case TEMPLATE_GROUP_BORDER:
		fmt = "BORDER%d";
		break;

	case TEMPLATE_GROUP_TEXT:
		fmt = "TEXT%d";
		break;

	case TEMPLATE_GROUP_GADGET:
		fmt = "GADGET%d";
		break;
	}
	sprintf(&tp->tp_TemplateName[0], fmt, tp->tp_GroupEntryNum);
	tp->tp_Flags = TEMPLATE_FLAG_DEFAULT_NAME;
}

 /* Init default template data */

SHORT
init_default_template_data(struct TemplateList *tl, struct Template *tp,
						   BOOL default_name)
{
	struct Box *box = &tp->tp_Box;
	struct BorderData *bd;
	struct TextData *td;
	struct GadgetData *gd;
	USHORT width = box->bo_X2 - box->bo_X1 + 1, height = box->bo_Y2 - box->bo_Y1 + 1;
	SHORT status = EDITOR_STATUS_NORMAL;

	/* Init default template name */
	if (default_name == TRUE)
	{
		build_default_template_name(tl, tp);
	}

	/* Init default template data */
	switch (TEMPLATE_GROUP(tp))
	{
	case TEMPLATE_GROUP_BORDER:
		bd = &tp->tp_Data.tp_BorderData;
		bd->bd_Type = BORDER_DATA_TYPE_BOX2_IN;
		bd->bd_LeftEdge = box->bo_X1;
		bd->bd_TopEdge = box->bo_Y1;
		bd->bd_Width = width;
		bd->bd_Height = height;

		/* Mark end of border data */
		(bd + 1)->bd_Type = INTUISUP_DATA_END;
		break;

	case TEMPLATE_GROUP_TEXT:
		td = &tp->tp_Data.tp_TextData;
		td->td_Type = TEXT_DATA_TYPE_TEXT;
		td->td_Flags = 0;
		td->td_LeftEdge = box->bo_X1;
		td->td_TopEdge = box->bo_Y1;
		if (!(td->td_TextAttr = open_template_font_by_attributes(tl,
																 DEFAULT_FONT_NAME, DEFAULT_FONT_YSIZE)))
		{
			status = EDITOR_ERROR_INVALID_FONT;
		}
		else
		{
			if ((status = duplicate_string("Text", &td->td_Text)) ==
				EDITOR_STATUS_NORMAL)
			{
				/* Calc size of text for template box */
				box = &tp->tp_Box;
				box->bo_X2 = box->bo_X1 + IPrintText(pri, pwin, td->td_Text,
													 td->td_LeftEdge, td->td_TopEdge, td->td_Type,
													 TEXT_DATA_FLAG_NO_PRINT, td->td_TextAttr) - 1;
				box->bo_Y2 = box->bo_Y1 + td->td_TextAttr->ta_YSize - 1;
			}

			/* Mark end of text data */
			(td + 1)->td_Type = INTUISUP_DATA_END;
		}
		break;

	case TEMPLATE_GROUP_GADGET:
		gd = &tp->tp_Data.tp_GadgetData;
		gd->gd_Type = tp->tp_Type - FIRST_GADGET_TEMPLATE_TYPE + 1;
		gd->gd_Flags = 0;
		gd->gd_LeftEdge = box->bo_X1;
		gd->gd_TopEdge = box->bo_Y1;
		gd->gd_Width = width;
		gd->gd_Height = height;
		gd->gd_Text = NULL;
		if (!(gd->gd_TextAttr = open_template_font_by_attributes(tl,
																 DEFAULT_FONT_NAME, DEFAULT_FONT_YSIZE)))
		{
			status = EDITOR_ERROR_INVALID_FONT;
		}
		else
		{
			switch (gd->gd_Type)
			{
			case GADGET_DATA_TYPE_BUTTON:
				status = duplicate_string("Button", &gd->gd_Text);
				break;

			case GADGET_DATA_TYPE_CHECK:
				gd->gd_SpecialData.gd_CheckData.gd_CheckSelected = 1;
				break;

			case GADGET_DATA_TYPE_MX:
				gd->gd_Flags |= GADGET_DATA_FLAG_TEXT_LEFT;
				gd->gd_SpecialData.gd_MXData.gd_MXSpacing = 1;
				gd->gd_SpecialData.gd_MXData.gd_MXActiveEntry = 0;
				if ((status = build_template_text_list(tp,
													   &default_mx_text_array[0])) ==
					EDITOR_STATUS_NORMAL)
				{
					status = build_template_text_array(tp);
				}
				break;

			case GADGET_DATA_TYPE_STRING:
				gd->gd_SpecialData.gd_InputData.gd_InputLen = 10;
				gd->gd_SpecialData.gd_InputData.gd_InputActivateNext = 0;
				gd->gd_SpecialData.gd_InputData.gd_InputActivatePrev = 0;
				status = duplicate_string("String",
										  &gd->gd_SpecialData.gd_InputData.gd_InputDefault);
				break;

			case GADGET_DATA_TYPE_INTEGER:
				gd->gd_SpecialData.gd_InputData.gd_InputLen = 10;
				gd->gd_SpecialData.gd_InputData.gd_InputActivateNext = 0;
				gd->gd_SpecialData.gd_InputData.gd_InputActivatePrev = 0;
				gd->gd_SpecialData.gd_InputData.gd_InputDefault = (BYTE *) 123;
				break;

			case GADGET_DATA_TYPE_SLIDER:
				if (width / 2 < height)
				{
					gd->gd_Flags = GADGET_DATA_FLAG_ORIENTATION_VERT;
				}
				gd->gd_SpecialData.gd_SliderData.gd_SliderMin = 0;
				gd->gd_SpecialData.gd_SliderData.gd_SliderMax = 10;
				gd->gd_SpecialData.gd_SliderData.gd_SliderLevel = 5;
				break;

			case GADGET_DATA_TYPE_SCROLLER:
				if (width / 2 < height)
				{
					gd->gd_Flags = GADGET_DATA_FLAG_ORIENTATION_VERT;
				}
				gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerVisible = 2;
				gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerTotal = 10;
				gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerTop = 5;
				break;

			case GADGET_DATA_TYPE_CYCLE:
				gd->gd_SpecialData.gd_CycleData.gd_CycleActive = 0;
				if ((status = build_template_text_list(tp,
													   &default_cycle_text_array[0])) ==
					EDITOR_STATUS_NORMAL)
				{
					status = build_template_text_array(tp);
				}
				break;

			case GADGET_DATA_TYPE_COUNT:
				gd->gd_SpecialData.gd_CountData.gd_CountMin = 10;
				gd->gd_SpecialData.gd_CountData.gd_CountMax = 50;
				gd->gd_SpecialData.gd_CountData.gd_CountValue = 30;
				break;

			case GADGET_DATA_TYPE_LISTVIEW:
				gd->gd_Flags |= GADGET_DATA_FLAG_TEXT_ABOVE;
				gd->gd_SpecialData.gd_ListViewData.gd_ListViewSpacing = 0;
				gd->gd_SpecialData.gd_ListViewData.gd_ListViewTop = 0;
				gd->gd_SpecialData.gd_ListViewData.gd_ListViewList = &tp->tp_TextList;
				status = build_template_text_list(tp,
												  &default_listview_text_array[0]);
				break;

			case GADGET_DATA_TYPE_PALETTE:
				if (width / 2 < height)
				{
					gd->gd_Flags |= GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP;
				}
				gd->gd_Flags |= GADGET_DATA_FLAG_TEXT_ABOVE;
				gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth = 2;
				gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset = 0;
				gd->gd_SpecialData.gd_PaletteData.gd_PaletteActiveColor = 2;
				break;
			}

			/* Mark end of gadget data */
			(gd + 1)->gd_Type = INTUISUP_DATA_END;
		}
		break;
	}
	return (status);
}

 /* Clone template and optional add it to template list */

struct Template *
clone_template(struct TemplateList *tl, struct Template *old_tp,
			   BOOL full_clone)
{
	struct Template *new_tp;
	SHORT status = EDITOR_STATUS_NORMAL;

	if (!(new_tp = AllocMem((LONG) sizeof(struct Template),
							 (LONG) MEMF_PUBLIC | MEMF_CLEAR)))
	{
		status = EDITOR_ERROR_OUT_OF_MEM;
	}
	else
	{

		/* Init template */
		CopyMem((BYTE *) old_tp, (BYTE *) new_tp, (LONG) sizeof(struct Template));
		new_tp->tp_Node.ln_Name = &new_tp->tp_TemplateName[0];
		NewList(&new_tp->tp_TextList);
		if (full_clone == FALSE)
		{
			CopyMem((BYTE *) & current_box, (BYTE *) & new_tp->tp_Box, (LONG)
					sizeof(struct Box));
		}
		if ((status = clone_template_data(tl, old_tp, new_tp)) !=
			EDITOR_STATUS_NORMAL)
		{
			free_template(tl, new_tp);
			new_tp = NULL;
		}
		else
		{
			if (full_clone == FALSE)
			{

				/* Add new template to list and refresh list view */
				add_template_to_list(tl, new_tp, TRUE);
				ISetGadgetAttributes(egl, EDITOR_GADGET_TEMPLATES, 0L, 0L,
									 USE_CURRENT_VALUE, USE_CURRENT_VALUE, &tl->tl_Templates);
			}
		}
	}
	show_error(status);
	return (new_tp);
}

 /* Clone template data */

STATIC SHORT
clone_template_data(struct TemplateList * tl, struct Template * old_tp,
					struct Template * new_tp)
{
	struct BorderData *new_bd;
	struct TextData *old_td, *new_td;
	struct GadgetData *old_gd, *new_gd;
	struct Box *box = &new_tp->tp_Box;
	SHORT status = EDITOR_STATUS_NORMAL;

	/* Clear data pointers */
	switch (TEMPLATE_GROUP(new_tp))
	{
	case TEMPLATE_GROUP_BORDER:
		new_bd = &new_tp->tp_Data.tp_BorderData;
		break;

	case TEMPLATE_GROUP_TEXT:
		old_td = &old_tp->tp_Data.tp_TextData;
		new_td = &new_tp->tp_Data.tp_TextData;
		if (new_td->td_Type == TEXT_DATA_TYPE_TEXT)
		{
			new_td->td_Text = NULL;
		}
		new_td->td_TextAttr = NULL;
		break;

	case TEMPLATE_GROUP_GADGET:
		old_gd = &old_tp->tp_Data.tp_GadgetData;
		new_gd = &new_tp->tp_Data.tp_GadgetData;
		new_gd->gd_Text = NULL;
		new_gd->gd_TextAttr = NULL;
		switch (new_gd->gd_Type)
		{
		case GADGET_DATA_TYPE_BUTTON:
		case GADGET_DATA_TYPE_CHECK:
		case GADGET_DATA_TYPE_INTEGER:
		case GADGET_DATA_TYPE_SLIDER:
		case GADGET_DATA_TYPE_SCROLLER:
		case GADGET_DATA_TYPE_COUNT:
		case GADGET_DATA_TYPE_PALETTE:
			break;

		case GADGET_DATA_TYPE_MX:
			new_gd->gd_SpecialData.gd_MXData.gd_MXTextArray = NULL;
			break;

		case GADGET_DATA_TYPE_CYCLE:
			new_gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray = NULL;
			break;

		case GADGET_DATA_TYPE_STRING:
			new_gd->gd_SpecialData.gd_InputData.gd_InputDefault = NULL;
			break;

		case GADGET_DATA_TYPE_LISTVIEW:
			new_gd->gd_SpecialData.gd_ListViewData.gd_ListViewList = &new_tp->tp_TextList;
			break;
		}
		break;
	}

	/* Allocate new data */
	switch (TEMPLATE_GROUP(new_tp))
	{
	case TEMPLATE_GROUP_BORDER:
		new_bd->bd_LeftEdge = box->bo_X1;
		new_bd->bd_TopEdge = box->bo_Y1;
		break;

	case TEMPLATE_GROUP_TEXT:
		new_td->td_LeftEdge = box->bo_X1;
		new_td->td_TopEdge = box->bo_Y1;
		if (!(new_td->td_TextAttr = open_template_font_by_attributes(tl,
																	 (BYTE *) old_td->td_TextAttr->ta_Name,
																	 old_td->td_TextAttr->ta_YSize)))
		{
			status = EDITOR_ERROR_INVALID_FONT;
		}
		else
		{
			if (new_td->td_Type == TEXT_DATA_TYPE_TEXT)
			{
				status = duplicate_string(old_td->td_Text, &new_td->td_Text);
			}
		}
		break;

	case TEMPLATE_GROUP_GADGET:
		new_gd->gd_LeftEdge = box->bo_X1;
		new_gd->gd_TopEdge = box->bo_Y1;
		if (!(new_gd->gd_TextAttr = open_template_font_by_attributes(tl,
																	 (BYTE *) old_gd->gd_TextAttr->ta_Name,
																	 old_gd->gd_TextAttr->ta_YSize)))
		{
			status = EDITOR_ERROR_INVALID_FONT;
		}
		else
		{
			if ((status = duplicate_string(old_gd->gd_Text,
										   &new_gd->gd_Text)) == EDITOR_STATUS_NORMAL)
			{
				switch (new_gd->gd_Type)
				{
				case GADGET_DATA_TYPE_BUTTON:
				case GADGET_DATA_TYPE_CHECK:
				case GADGET_DATA_TYPE_INTEGER:
				case GADGET_DATA_TYPE_SLIDER:
				case GADGET_DATA_TYPE_SCROLLER:
				case GADGET_DATA_TYPE_COUNT:
				case GADGET_DATA_TYPE_PALETTE:
					break;

				case GADGET_DATA_TYPE_MX:
				case GADGET_DATA_TYPE_CYCLE:
					if ((status = duplicate_text_list(old_tp, new_tp)) ==
						EDITOR_STATUS_NORMAL)
					{
						status = build_template_text_array(new_tp);
					}
					break;

				case GADGET_DATA_TYPE_STRING:
					status = duplicate_string(old_gd->gd_SpecialData.gd_InputData.gd_InputDefault, &new_gd->gd_SpecialData.gd_InputData.gd_InputDefault);
					break;

				case GADGET_DATA_TYPE_LISTVIEW:
					status = duplicate_text_list(old_tp, new_tp);
					break;
				}
			}
		}
		break;
	}
	return (status);
}

 /* Display template */

VOID
display_template(struct Template * tp)
{
	struct TextData *td;
	struct GadgetData *gd;
	APTR gl;

	switch (TEMPLATE_GROUP(tp))
	{
	case TEMPLATE_GROUP_BORDER:
		IDisplayBorders(pri, pwin, &tp->tp_Data.tp_BorderData, 0, 0);
		break;

	case TEMPLATE_GROUP_TEXT:
		td = &tp->tp_Data.tp_TextData;
		IDisplayTexts(pri, pwin, td, 0, 0, NULL);
		break;

	case TEMPLATE_GROUP_GADGET:
		gd = &tp->tp_Data.tp_GadgetData;
		if (!(gl = ICreateGadgets(pri, gd, 0, 0, NULL)))
		{
			show_error(EDITOR_ERROR_OUT_OF_MEM);
		}
		else
		{
			USHORT *dim = (USHORT *) (IGadgetAddress(gl, 0) + 1);

			/* Update template box with gadget size */
			IDisplayGadgets(pwin, gl);
			switch (gd->gd_Type)
			{
			case GADGET_DATA_TYPE_CHECK:
			case GADGET_DATA_TYPE_MX:
			case GADGET_DATA_TYPE_PALETTE:
			case GADGET_DATA_TYPE_LISTVIEW:
				tp->tp_Box.bo_X2 = tp->tp_Box.bo_X1 + dim[0] - 1;
				tp->tp_Box.bo_Y2 = tp->tp_Box.bo_Y1 + dim[1] - 1;
				break;

			case GADGET_DATA_TYPE_STRING:
			case GADGET_DATA_TYPE_INTEGER:
				tp->tp_Box.bo_X2 = tp->tp_Box.bo_X1 + dim[0] - 1;
				if (gd->gd_Flags & GADGET_DATA_FLAG_NO_BORDER)
				{
/*	old!!   tp->tp_Box.bo_Y2 = tp->tp_Box.bo_Y1 + dim[1] - 1; */
					tp->tp_Box.bo_Y2 = tp->tp_Box.bo_Y1 + dim[1] - 1;
				}
				else
				{
/*	old!!   tp->tp_Box.bo_Y2 = tp->tp_Box.bo_Y1 + dim[1] + 5; */
					tp->tp_Box.bo_Y2 = tp->tp_Box.bo_Y1 + dim[1] - 1;
				}
				break;
			}
			IRemoveGadgets(gl);
			IFreeGadgets(gl);
		}
		break;
	}
}

 /* Refresh all templates */

VOID
refresh_all_templates(VOID)
{
	struct TemplateList *tl = &template_list;
	struct Template *tp;

	clear_project_window(tl->tl_Flags);
	print_project_window_title();
	if (editor_mode == EDITOR_MODE_USE)
	{
		IRefreshGadgets(use_gl);

		/* Refresh non gadget templates */
		for (tp = get_head((struct List *) & tl->tl_Templates); tp;
			 tp = get_succ(&tp->tp_Node))
		{
			if (TEMPLATE_GROUP(tp) != TEMPLATE_GROUP_GADGET)
			{
				display_template(tp);
			}
		}
	}
	else
	{
		for (tp = get_head((struct List *) & tl->tl_Templates); tp;
			 tp = get_succ(&tp->tp_Node))
		{
			display_template(tp);
		}
	}
}

 /* Free template list */

VOID
free_template_list(struct TemplateList *tl)
{
	struct Template *tp;
	struct List *list = (struct List *) & tl->tl_Templates;

	free_font_list(tl);
	while (tp = (struct Template *) RemHead(list))
	{
		switch (TEMPLATE_GROUP(tp))
		{
		case TEMPLATE_GROUP_BORDER:
			tl->tl_BorderTemplates--;
			break;

		case TEMPLATE_GROUP_TEXT:
			tl->tl_TextTemplates--;
			break;

		case TEMPLATE_GROUP_GADGET:
			tl->tl_GadgetTemplates--;
			break;
		}
		free_template(tl, tp);
	}
	tl->tl_Flags &= ~TEMPLATE_LIST_FLAG_CHANGED;
	MWCheck();
}

 /* Free template */

VOID
free_template(struct TemplateList *tl, struct Template *tp)
{
	if (tl && tp)
	{
		free_template_data(tl, tp);
		FreeMem(tp, (LONG) sizeof(struct Template));
	}
}

 /* Free template data */

VOID
free_template_data(struct TemplateList *tl, struct Template *tp)
{
	struct TextData *td;
	struct GadgetData *gd;

	switch (TEMPLATE_GROUP(tp))
	{
	case TEMPLATE_GROUP_BORDER:
		break;

	case TEMPLATE_GROUP_TEXT:
		td = &tp->tp_Data.tp_TextData;
		close_template_font(tl, td->td_TextAttr);
		if (td->td_Type == TEXT_DATA_TYPE_TEXT)
		{
			free(td->td_Text);
		}
		td->td_Text = NULL;
		break;

	case TEMPLATE_GROUP_GADGET:
		gd = &tp->tp_Data.tp_GadgetData;
		close_template_font(tl, gd->gd_TextAttr);
		free(gd->gd_Text);
		gd->gd_Text = NULL;
		switch (gd->gd_Type)
		{
		case GADGET_DATA_TYPE_BUTTON:
		case GADGET_DATA_TYPE_CHECK:
		case GADGET_DATA_TYPE_INTEGER:
		case GADGET_DATA_TYPE_SLIDER:
		case GADGET_DATA_TYPE_SCROLLER:
		case GADGET_DATA_TYPE_COUNT:
		case GADGET_DATA_TYPE_PALETTE:
			break;

		case GADGET_DATA_TYPE_MX:
		case GADGET_DATA_TYPE_CYCLE:
			free_template_text_array(tp);
		case GADGET_DATA_TYPE_LISTVIEW:
			free_template_text_list(tp);
			break;

		case GADGET_DATA_TYPE_STRING:
			free(gd->gd_SpecialData.gd_InputData.gd_InputDefault);
			break;
		}
		break;
	}
}

 /* Delete template */

VOID
delete_template(struct Template *tp)
{
	struct TemplateList *tl = &template_list;
	struct Template *succ_tp;
	UBYTE group = TEMPLATE_GROUP(tp);

	/* Remove template from list, decrement counters and free template */
	succ_tp = get_succ(&tp->tp_Node);
	Remove(&tp->tp_Node);
	switch (group)
	{
	case TEMPLATE_GROUP_BORDER:
		tl->tl_BorderTemplates--;
		break;

	case TEMPLATE_GROUP_TEXT:
		tl->tl_TextTemplates--;
		break;

	case TEMPLATE_GROUP_GADGET:
		tl->tl_GadgetTemplates--;
		break;
	}
	free_template(tl, tp);

	/* Update default template names and refresh template list */
	for (tp = succ_tp; tp; tp = get_succ(&tp->tp_Node))
	{
		if (TEMPLATE_GROUP(tp) == group)
		{
			tp->tp_GroupEntryNum--;
			if (tp->tp_Flags & TEMPLATE_FLAG_DEFAULT_NAME)
			{
				build_default_template_name(tl, tp);
			}
		}
	}
	ISetGadgetAttributes(egl, EDITOR_GADGET_TEMPLATES, 0L, 0L,
						 USE_CURRENT_VALUE, USE_CURRENT_VALUE, &tl->tl_Templates);
	refresh_all_templates();
	tl->tl_Flags |= TEMPLATE_LIST_FLAG_CHANGED;
}
