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;
}