U0 BgtTemplatePurge(CBgtTemplate *tmpt)
{
	CBgtEntry *tmpb, *tmpb1;

	tmpb=b_head.next;
	while (tmpb != &b_head)
	{
		tmpb1 = tmpb->next;
		if (tmpb->template == tmpt)
		{
			QueueRemove(tmpb);
			BgtEntryDel2(tmpb);
			Free(tmpb);
		}
		tmpb = tmpb1;
	}
}

U0 BgtTemplateDel(CBgtTemplate *tmpt)
{
	BgtTemplatePurge(tmpt);
	BgtEntryDel2(&tmpt->b);
	Free(tmpt);
}

U0 BgtTemplateExpand(CBgtTemplate *tmpt, Bool periodic_copy=FALSE)
{
	CDate		 d, start, end;
	CDateStruct  ds;
	CBgtEntry 	*tmpb;
	Bool		 first = TRUE;

	start = MyStr2Date(tmpt->start_date);
	end   = MyStr2Date(tmpt->end_date);
	tmpt->b.template = tmpt;
	switch (tmpt->type)
	{
		case BT_INTERVAL:
			d = start;
			while (d <= end)
			{
				if (!first || !periodic_copy)
				{
					tmpb = BgtEntryCopy(&tmpt->b, periodic_copy);
					tmpb->date = d;
					if (periodic_copy)
						tmpb->template = NULL;
					else
						tmpb->type = BE_TEMPLATE_COPY;
					BgtIns(tmpb);
				}
				d += tmpt->period * 0x100000000;
				first = FALSE;
			}
			break;

		case BT_MONTHLY:
			Date2Struct(&ds, start);
			while (TRUE)
			{
				d = Struct2Date(&ds);
				if (d <= end)
				{
					if (!first || !periodic_copy)
					{
						tmpb = BgtEntryCopy(&tmpt->b, periodic_copy);
						tmpb->date = d;
						if (periodic_copy)
							tmpb->template = NULL;
						else
							tmpb->type = BE_TEMPLATE_COPY;
						BgtIns(tmpb);
					}
				}
				else
					break;
				if (++ds.mon > 12)
				{
					ds.mon = 1;
					ds.year++;
				}
				first = FALSE;
			}
			break;

		case BT_BIMONTHLY:
			Date2Struct(&ds, start);
			while (TRUE)
			{
				d = Struct2Date(&ds);
				if (d <= end)
				{
					if (!first || !periodic_copy)
					{
						tmpb = BgtEntryCopy(&tmpt->b, periodic_copy);
						tmpb->date = d;
						if (periodic_copy)
							tmpb->template = NULL;
						else
							tmpb->type = BE_TEMPLATE_COPY;
						BgtIns(tmpb);
					}
				}
				else
					break;

				ds.mon += 2;
				if (ds.mon > 12)
				{
					ds.mon -= 12;
					ds.year++;
				}
				first = FALSE;
			}
			break;

		case BT_SEMIANNUAL:
			Date2Struct(&ds, start);
			while (TRUE)
			{
				d = Struct2Date(&ds);
				if (d <= end)
				{
					if (!first || !periodic_copy)
					{
						tmpb = BgtEntryCopy(&tmpt->b, periodic_copy);
						tmpb->date = d;
						if (periodic_copy)
							tmpb->template = NULL;
						else
							tmpb->type = BE_TEMPLATE_COPY;
						BgtIns(tmpb);
					}
				}
				else
					break;
				ds.mon += 6;
				if (ds.mon>12)
				{
					ds.mon -= 12;
					ds.year++;
				}
				first = FALSE;
			}
			break;

		case BT_ANNUAL:
			Date2Struct(&ds, start);
			while (TRUE)
			{
				d = Struct2Date(&ds);
				if (d <= end)
				{
					if (!first || !periodic_copy)
					{
						tmpb = BgtEntryCopy(&tmpt->b, periodic_copy);
						tmpb->date = d;
						if (periodic_copy)
							tmpb->template = NULL;
						else
							tmpb->type = BE_TEMPLATE_COPY;
						BgtIns(tmpb);
					}
				}
				else
					break;
				ds.year++;
				first = FALSE;
			}
			break;
	}
}

U0 CBgtTemplatesExpand()
{
	CBgtTemplate *tmpt = t_head.next;

	while (tmpt != &t_head)
	{
		BgtTemplateExpand(tmpt);
		tmpt = tmpt->next;
	}
}

CBgtTemplate *BgtTemplatePrompt(CBgtTemplate *default_t=NULL, CBgtEntry *default_b=NULL)
{
	CBgtTemplate	 t, *tmpt;
	CBgtEntry 		*tmpb;

	MemSet(&t, 0, sizeof(CBgtTemplate));
	if (default_t)
	{
		MemCopy(&t.start, &default_t->start, BT_SIZE);
		default_b = &default_t->b;
	}
	else
	{
		t.type = BT_INTERVAL;
		if (default_b)
			StrPrint(&t.start_date, "%D", default_b->date);
		else
			StrCopy(&t.start_date, "[");
		StrCopy(&t.end_date, "]");
	}
	while (TRUE)
		if (PopUpForm(&t) && ((t.type == BT_INTERVAL && t.period > 0) || t.type > BT_INTERVAL))
		{
			if (tmpb = BgtEntryPrompt(default_b))
			{
				tmpt = CAlloc(sizeof(CBgtTemplate));
				MemCopy(&tmpt->start, &t.start, BT_SIZE);
				MemCopy(&tmpt->b, tmpb, sizeof(CBgtEntry));
				Free(tmpb);
				return tmpt;
			}
		}
		else
			break;

	return NULL;
}
