extern U0 BgtRegen();

Bool BgtPutKey(CDoc *doc, U8 *, I64 ch, I64 sc)
{//ch=ASCII; sc=scan_code
	no_warn	sc;

	CBgtEntry		*tmpb, *tmpb1;
	CBgtTemplate	*tmpt, *tmpt1;
	CDocEntry		*doc_ce;
	U8				*st;

	switch (ch)
	{
		case '\n':
			if ((doc_ce = doc->cur_entry) && doc_ce != doc && doc_ce->type_u8 == DOCT_MENU_VAL)
			{
				tmpb = doc_ce->user_data;
				if (tmpt = tmpb->template)
				{
					if (tmpt1 = BgtTemplatePrompt(tmpt))
					{
						QueueRemove(tmpt);
						BgtTemplatePurge(tmpt);
						BgtEntryDel2(&tmpt->b);
						Free(tmpt);
						QueueInsert(tmpt1, t_head.last);
						BgtTemplateExpand(tmpt1);
						BgtRegen;
					}
				}
				else
				{
					if (tmpb1=BgtEntryPrompt(tmpb))
					{
						QueueRemove(tmpb);
						BgtEntryDel(tmpb);
						BgtIns(tmpb1);
						BgtRegen;
					}
				}
			}
			return TRUE;

		case CH_CTRLY:
			if ((doc_ce = doc->cur_entry) && doc_ce != doc && doc_ce->type_u8 == DOCT_MENU_VAL)
			{
				tmpb = doc_ce->user_data;
				if (tmpt = tmpb->template)
				{
					QueueRemove(tmpt);
					BgtTemplateDel(tmpt);
				}
				else
				{
					QueueRemove(tmpb);
					BgtEntryDel(tmpb);
				}
				BgtRegen;
			}
			return TRUE;

		case 'a':
			PopUpOk("Set the name and color of your accounts.\n"
					"To delete accounts, manually edit\n"
					"$$GREEN$$~/Budget/Accts.DD$$FG$$.");
			if (PopUpEd(bgt_accts_file, Fs))
			{
				BgtAcctsRead;
				BgtRegen;
			}
			return TRUE;

		case 'v':
			if ((st = BgtPopUpAcct("View Acct\n\n", view_acct)) >= 0)
			{
				StrCopy(view_acct, st);
				BgtRegen;
			}
			return TRUE;

		case 'n':
			if (tmpb1 = BgtEntryPrompt)
			{
				BgtIns(tmpb1);
				BgtRegen;
			}
			return TRUE;

		case 't':
			if (tmpt1 = BgtTemplatePrompt)
			{
				QueueInsert(tmpt1, t_head.last);
				BgtTemplateExpand(tmpt1);
				BgtRegen;
			}
			return TRUE;

		case 'c':
			if ((doc_ce = doc->cur_entry) && doc_ce != doc && doc_ce->type_u8 == DOCT_MENU_VAL)
				tmpb = doc_ce->user_data;
			else
				tmpb = NULL;
			if (tmpb1 = BgtEntryPrompt(tmpb))
			{
				BgtIns(tmpb1);
				BgtRegen;
			}
			return TRUE;

		case 'p':
			if ((doc_ce = doc->cur_entry) && doc_ce != doc && doc_ce->type_u8 == DOCT_MENU_VAL)
			{
				tmpb = doc_ce->user_data;
				if (tmpt1=BgtTemplatePrompt(, tmpb))
				{
					BgtTemplateExpand(tmpt1, TRUE);
					BgtTemplateDel(tmpt1);
					BgtRegen;
				}
			}
			return TRUE;
	}

	return FALSE;
}

U0 BgtRegen()
{
	I64			 timeout_jiffy, c, color = COLOR_INVALID;
	F64			 balance = 0;
	CDoc		*doc, *pdoc, *ddoc;
	CDocEntry	*doc_ce;
	CBgtEntry	*tmpb = b_head.next, *tmpb_ce;

	doc = DocNew;
	doc->flags |= DOCF_FORM;
	while (tmpb != &b_head)
	{
		if (!StrCompare(view_acct, tmpb->credit))
			balance -= tmpb->amount;
		if (!StrCompare(view_acct, tmpb->debit))
			balance += tmpb->amount;
		c=BgtAcctColor(tmpb->credit);
		if (c != color)
		{
			color = c;
			DocPrint(doc, "$$FG,%d$$", color);
		}
		tmpb->doc_e = DocPrint(doc, "$$MU-UL,\"%D %8ts %8ts:%8.2f %8.2f:%$$Q\",U=0x%X$$\n", 
								tmpb->date, tmpb->credit, tmpb->debit, balance, tmpb->amount, tmpb->desc, tmpb);
		tmpb = tmpb->next;
	}
	DocRecalc(doc);

	if (pdoc = Fs->put_doc)
	{
		DocLock(pdoc);
		//Now, we want to preserve old position in doc, using ugly brute force.
		//It's tricky -- can't use old line num because of editor filters.

		//The price we pay for using the standard document editor is this kludge.
		//When I originally wrote my budget program, I did not have separate budget
		//and line entries, so we never had to resync.

		doc_ce = pdoc->cur_entry;
		timeout_jiffy = counts.jiffies + JIFFY_FREQ; //Max one second.
		while (doc_ce != pdoc && counts.jiffies < timeout_jiffy)
		{
			while (doc_ce->type_u8 != DOCT_MENU_VAL || !(tmpb_ce = doc_ce->user_data))
			{
				doc_ce = doc_ce->next;
				if (doc_ce == pdoc)
					goto br_cont;
			}
			tmpb = b_head.next;
			while (tmpb != &b_head)
			{
				if (tmpb == tmpb_ce)
				{
					doc->cur_entry = tmpb->doc_e;
					doc->cur_col = 0;
					DocCenter(doc);
					goto br_cont;
				}
				tmpb = tmpb->next;
			}
			doc_ce = doc_ce->next;
		}
	}

	br_cont:
	ddoc = Fs->display_doc;
	Fs->put_doc 	 =doc;
	Fs->display_doc=doc;
	DocDel(pdoc);
	if (pdoc != ddoc)
		DocDel(ddoc);
	doc->user_put_key = &BgtPutKey;
}

U0 Budget(U8 *dirname="~/Budget")
{
	CDoc *pdoc, *ddoc, *old_put, *old_display;

	Cd(dirname);
	bgt_string_file	= FileNameAbs("Strs.DD");
	bgt_accts_file	= FileNameAbs("Accts.DD");
	bgt_data_file	= FileNameAbs("Bgt.DATA");

	BgtAcctsRead;
	BgtDataRead;
	CBgtTemplatesExpand;
	SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
	AutoComplete;
	WinBorder;
	WinMax;
	MenuPush(	"File {"
				"  Abort(,CH_SHIFT_ESC);"
				"  Exit(,CH_ESC);"
				"}"
				"Edit {"
				"  NewEntry(,'n');"
				"  CopyEntry(,'c');"
				"  PeriodicEntry(,'p');"
				"  EditEntry(,'\n');"
				"  DeleteEntry(,CH_CTRLY);"
				"  NewTemplate(,'t');"
				"  AcctsFile(,'a');"
				"}"
				"View {"
				"  ViewAcct(,'v');"
				"}"
				);
	StrCopy(view_acct, "BANK");
	DocMax;
	old_put 	= Fs->put_doc;
	old_display = Fs->display_doc;
	Fs->put_doc = NULL;
	Fs->display_doc = NULL;
	BgtRegen;
	try
		if (View)
		{
			BgtDataWrite;
			BgtAcctsWrite;
		}
	catch
		PutExcept;

	pdoc = Fs->put_doc;
	ddoc = Fs->display_doc;
	Fs->put_doc		= old_put;
	Fs->display_doc	= old_display;
	DocDel(pdoc);
	if (pdoc != ddoc)
		DocDel(ddoc);

	SettingsPop;
	BgtDel;
	MenuPop;
}
