/* ----------------------------------------------------------------------------
 * onyx a 4gl for GNU project            (c) M.Koehne <kraehe@bakunin.north.de>
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include "twin.h"
#include "Onyx.h"
#include "Definitions.h"
#include "Transactions.h"

/*-------------------------------------------------------------------------- */

extern void create_menu(char *pname);

/* ------------------------------------------------------------------------- */

ViewRoot	VRoot("GNU-4GL");
ViewMenu	MainMenu(".",0,0);
ViewFramedText	MainMessages("Messages",0,2,max_y-5,max_x-3,5);
ViewFramedText	MainKeys("Keys",0,0,max_y-2,max_x,3);

/* ------------------------------------------------------------------------- */

char MainDatabase[128];
char MainProgram[128];
char *menuname;

List MainMenus(16);
HashList MainMasks(16);
HashList MainCursors(16);
HashList MainFields(256,211);
HashList MainTransactions(16);
Text MainMessageText(16);
Text MainKeysText(1);

SqlManager MainSql;

int menuflag = 0;
int userflag = 1;
int message_verbose=0;

/*-------------------------------------------------------------------------- */

static int ExecTransCount = 0;

int ExecTransaction(char *transaction)
{	Transactions *trans_parser;
	Text *trans_text;
	char **p;
	ViewBack *vb;
	char line[80];

	if (!transaction) return(0);
	if (!ExecTransCount) MainMessageText.purge();

	memset(line,'-',79); line[80]=0;
	memcpy(line+38-strlen(transaction)/2,transaction,strlen(transaction));
	MainMessageText.add_line(line);

	trans_text = (Text *) MainTransactions.get_buck(transaction);
	if (!trans_text) return(0);

	ExecTransCount++;

	vb = (ViewBack*)(MainMessages.panner);

	p=trans_text->lines;
	while (*p) MainMessageText.add_line(*p++);
	vb->background = MainMessageText.lines;
	vb->h = MainMessageText.nlines;
	MainMessages.cur_y = 0;
	MainMessages.yo = 0;

	trans_parser = new Transactions();
	trans_parser->NewStream(trans_text);
	trans_parser->grammar();

	if (trans_parser->p_error && trans_parser->p_error->nlines) {
		p=trans_parser->p_error->lines;
		while (*p) MainMessageText.add_line(*p++);
		vb->background = MainMessageText.lines;
		vb->h = MainMessageText.nlines;
		MainMessages.cur_y = 0;
		MainMessages.yo = 0;
		}

	delete trans_parser;

	ExecTransCount--;
	 
	if (MainMessages.visible) {
		if (MainMessageText.nlines > 0) 
			MainMessages.cur_y = MainMessageText.nlines -1;
		if (MainMessageText.nlines > MainMessages.h-2)
			MainMessages.yo = MainMessageText.nlines -
				(MainMessages.h-2);
		if (!ExecTransCount || message_verbose) {
			MainMessages.full_expose(); 
			VRoot.full_expose(); tw_term_refresh(); 
			}
		}

	return(1);
	}

void DoTransaction(View *m,int ch)
{	if (ch != TERM_CR) return;

	ExecTransaction(m->transaction);
	VRoot.full_expose();
	}

void MaskCheck(View *m,int ch)
{	ViewCursor *vc;
	char str[81];
	int i;
	ViewBack *vb;

	if (m->transaction && (ch == TERM_PGUP) || (ch == TERM_PGDN))
		ExecTransaction(m->transaction);

	if ((ch >= TERM_F1) && (ch <= TERM_F10)) {
		vc = (ViewCursor *)m;
		if (vc && vc->vcd && vc->vcd->keys[ch-TERM_F1])
			ExecTransaction(vc->vcd->keys[ch-TERM_F1]);
		}

	if (ch == TERM_CR) {
		vc = (ViewCursor *)m;
		memset(str,' ',80);
		str[80]=0;
		char *p;

		for (i=0;i<10;i++) {
			if ((p=vc->vcd->keynames[i]))
				memcpy(str+i*8,p,strlen(p)<8 ? strlen(p):7);
				if (i) str[i*8-1]='|';
				}
		MainKeysText.purge();
		MainKeysText.add_line(str);
		vb = (ViewBack*)(MainKeys.panner);
		vb->background = MainKeysText.lines;
		}

	VRoot.full_expose();
	}

/*-------------------------------------------------------------------------- */

void create_menu(char *pname)
{	ViewMenu *men;
	MenuButton *but;
	struct MenuLoad *m;
	int i, b, x;
	struct ViewList *vl;

	if (!*pname) {
		fprintf(stderr,"Missing Program statement\n");
		exit(0);
		}

	if (parser_debug) fprintf(stderr,"Menugeneration %s ",pname);

	vl = MainMenu.viewlist; x=-1;
	while (vl) {
		x=vl->view->x+strlen(vl->view->name);
		vl = vl->next;
		}

	if (!MainMenus.nlines && (x>0)) return;

	men = new ViewMenu(pname,&MainMenu,0);
	b=0; i = 0;
	while(i<MainMenus.nlines) {
		m = (struct MenuLoad *)MainMenus.lines[i];
		but = new MenuButton(m->name,m->fnc,m->param,1,
			i+1,strlen(m->name),1);
		if (m->trans) but->transaction=m->trans;

		men->add(but); but->map(men);

		if ((int)strlen(m->name)>b) b=strlen(m->name);
		i++;
		}

	if (x<0) {
		but = new MenuButton("Messages",MapMask,&MainMessages,1,i+1,4,1);
		men->add(but); but->map(men);
		but = new MenuButton("Quit",TwinExit,0,1,i+2,4,1);
		men->add(but); but->map(men);
		if (b<8) b=8;
		}

	men->h = (x<0 ? 4:2)+MainMenus.nlines;
	men->b = 2+b;

	but = new MenuButton(pname,SubMenu,men,x+1,0, strlen(pname),1);
	MainMenu.add(but); but->map(&MainMenu); 

	if (parser_debug) fprintf(stderr,"OK\n");
	}

/*-------------------------------------------------------------------------- */

main(int argc,char **argv)
{	FileStream *prgm;
	Definitions *parser;
	char *infilename;

	*MainProgram=0;
	*MainDatabase=0;

	infilename = 0;

	tw_term_cleanexit=0; tw_term_refresh();

	parser = new Definitions(0);		

	while (--argc) {
		argv++;

		if (!memcmp(*argv,"-v",2)) message_verbose=1;
		else
		if (!memcmp(*argv,"-d",2)) parser_debug=1;
		else {	infilename = *argv;
			fprintf(stderr,"Parsing %s\n",infilename);

			prgm = new FileStream(infilename,O_RDONLY);

			if (prgm->fd>=0) {
				parser->NewStream(prgm);
				if (!parser->grammar()) { }

				if (parser->p_error->nlines) {
					char **p;

					p=parser->p_error->lines;
					while (*p) {
						fprintf(stderr,"%s\n",*p);
						p++;
						}
					}
				}
			else {	fprintf(stderr,"No stdin ?\n");
				exit(0);
				}

			delete prgm;
			}
		}

	delete parser;

	tw_term_cleanexit=1;

	if (*MainProgram) {
		ViewBack *vb;
		create_menu(MainProgram);

		VRoot.add(&MainMenu); MainMenu.map();

		MainKeys.header=1;
		MainKeys.footer=0;
		MainKeys.border=0;

		vb = (ViewBack*)(MainKeys.panner);
		MainKeysText.add_line(" ");
		vb->background = MainKeysText.lines;
		vb->h = MainKeysText.nlines;
		MainKeys.cur_y = 0;
		MainKeys.yo = 0;

		VRoot.add(&MainKeys); MainKeys.map();

		MainMasks.add_buck("Messages",(char *)&MainMessages);
		MainMasks.add_buck("Menu",(char *)&MainMenu);

		ExecTransaction("init");
		while (VRoot.eventloop());
		ExecTransaction("exit");
		}
	}
