#include	<stdio.h>
#include	<string.h>
#include	<X11/xpm.h>
#include	"xqdtk.h"
#include	"xgroups.h"
#include	"trapsign.h"

/*
	first the objects for the xqdtk2 toolkit

	toplevel		the main window
	menu_bar		the menu bar
	e1 e2 e3		the menus (e3 is for the groups)
	beppe_window	a nice window is my mirror :-)
	icona_beppe		my face :-)
*/

Window toplevel;
MenuBar *menu_bar;
PulldownEntry e1[2], e2[5], e3[MAXGRUPPO+1];

PopUp beppe_window;
Programma icona_beppe;

/*
	Gruppo[]	a (x)group of programs
	NumIcone	the total number of icons in the window
	NumGruppi	the number of Groups (every group has a menu-entry
*/

Programma Gruppo[MAXGRUPPO];
int NumIcone=0;
int NumGruppi=0;

/*
	filename	the name of the group requested in the command line (or the
				default group). without path and/or extension

	fn			the file that is opened with path and extension
*/

char fn[PATH_MAX];
char filename[PATH_MAX];

/*
	popup or popdown the About window
*/

static void beppe_fn(int arg)
{
	switch(arg)
	{
		case 0:	x_popup(beppe_window); break;
		case 1: x_popdown(beppe_window); break;
	}
}

/*
	handle the functions of the 2th menu
*/

static void menu2_fn(int arg)
{
	char cmd[PATH_MAX];
	int status=0;
	int i;

	switch(arg)
	{
		case ADD_GRP:	sprintf(cmd,"xgroups_newg -g %s %s",fn,filename);
						status=system(cmd);
						break;
		case ADD_PRG:	sprintf(cmd,"xgroups_newg -p %s %s",fn,filename);
						status=system(cmd);
						break;
		case DEL_ITM:	for(i=0;i<=NumIcone;i++)
						{
							if (Gruppo[i].selected)
							{
								sprintf(cmd,"xgroups_newg -d %s %s \"%s\"",fn,filename,Gruppo[i].nome);
								status += system(cmd);
							}
						}
						break;
		case SEL_ALL:	for(i=0;i<=NumIcone;i++)
						{
							Select_icona(toplevel, &Gruppo[i]);
						}
						break;
		case SEL_NONE:	for(i=0;i<=NumIcone;i++)
						{
							UnSelect_icona(toplevel, &Gruppo[i]);
						}
						break;
	}

/*
	if xgroups_newg exits with status != 0, then I exec a my clone and suicide
*/

	if (status != 0)
	{
		sprintf(cmd,"xgroups %s &",filename);
		system(cmd);
		exit(0);
	}
}

/*
	exit ... bye bye baby
*/

static void exit_fn(int arg)
{
	int i;

	for(i=0;i<=NumIcone;i++)
	{
		Destroy_icona(&(Gruppo[i]));
	}

	Destroy_icona(&icona_beppe);

	exit (arg);
}

/*
	do the command associated to a icon
*/

static void do_exec_fn(int arg)
{
	char cmd[PATH_MAX];

	sprintf(cmd,"%s &",Gruppo[arg].comando);
	system(cmd);
}

static void do_cmd_fn(int arg)
{
	if (DoubleClick() == 2)
	{
		do_exec_fn(arg);
	}
	else
	{
		if (Gruppo[arg].selected)
		{
			UnSelect_icona(toplevel, &Gruppo[arg]);
		}
		else
		{
			Select_icona(toplevel, &Gruppo[arg]);
		}
	}
}

/*
	cut a slice of a string ... used in the parsing of the .grp file
*/

int cut_string(char *buffer, char *s,char *cs)
{
	if (strstr(s,cs)==NULL) return (-1);

	strcpy(buffer,strstr(s,cs)+strlen(cs));

	if (strchr(buffer,'\"') != NULL) *(strchr(buffer,'\"'))='\0';

	return(0);
}

/*
	read a .grp file and put the objects in the Gruppo[] structure
*/

void ReadGruppo(Window parent,char *fname)
{
	FILE *fd;
	char s[PATH_MAX];
	char n[PATH_MAX];
	char i[PATH_MAX];
	char c[PATH_MAX];

	fd=fopen(fname,"rt");
	if (fd==NULL)
	{
		fprintf(stderr,"Error opening the group %s\n",fname);
		exit(1);
	}

	NumIcone=-1;

	while(1)
	{
		fgets(s,sizeof(s),fd); if (s[0]=='#') continue;

		if ((strstr(s,"N=\"")!=NULL) || (strstr(s,"G=\"")!=NULL))
		{
			NumIcone++;
			if (NumIcone >MAXGRUPPO-1)
			{
				fprintf(stderr,"Error MAXGRUPPO exceeded in group %s\n",fname);
				NumIcone--;
				break;
			}

			cut_string(n,s,"N=\"");
			cut_string(i,s,"I=\"");
			
			if (strstr(s,"G=\"")!=NULL)
			{

				NumGruppi++;

				cut_string(c,s,"G=\"");

				strcpy(e3[NumGruppi-1].name, n);
				e3[NumGruppi-1].function = do_exec_fn;
				e3[NumGruppi-1].arg = NumIcone;
			}
			else
			{
				cut_string(c,s,"C=\"");
			}

			strcpy(Gruppo[NumIcone].nome,n);
			strcpy(Gruppo[NumIcone].file_icona,i);
			strcpy(Gruppo[NumIcone].comando,c);

			Gruppo[NumIcone].x= 5 + (WICONA+10) * (NumIcone % INAROW);
			Gruppo[NumIcone].y= 35 + (HICONA+20) * (NumIcone / INAROW);
		}

		if (feof(fd)) break;
	}

	fclose(fd);
}

/*
	fill the menus e1 and e2
*/

void crea_menu()
{
	strcpy(e1[0].name, "About");
	e1[0].function = beppe_fn;
	e1[0].arg = 0;

	strcpy(e1[1].name, "Exit");
	e1[1].function = exit_fn;
	e1[1].arg = 0;
 
	strcpy(e2[0].name, "New Group");
	e2[0].function = menu2_fn;
	e2[0].arg = ADD_GRP;

	strcpy(e2[1].name, "New Program");
	e2[1].function = menu2_fn;
	e2[1].arg = ADD_PRG;

	strcpy(e2[2].name, "Delete Entry");
	e2[2].function = menu2_fn;
	e2[2].arg = DEL_ITM;

	strcpy(e2[3].name, "Select All");
	e2[3].function = menu2_fn;
	e2[3].arg = SEL_ALL;

	strcpy(e2[4].name, "UnSelect All");
	e2[4].function = menu2_fn;
	e2[4].arg = SEL_NONE;
}

/*
	return 1 if the file fn exists
*/

int esiste(char *fn)
{
	FILE *fd;

    if ( (fd=fopen(fn,"rt")) == NULL) return(0);

	fclose(fd);

	return(1);
}

/*
	the main program
*/

main(int argc, char *argv[])
{
	XEvent event;
	int altezza, larghezza, i;

/*
	install a signal handler to trap some exceptions
*/

	InstallSignalHandler();
	XSetErrorHandler(myhandler);

/*
	command line options and filenames
*/

	if (argc <= 1)
	{
		sprintf(filename,"%s",STARTGRP);
	}
	else
	{
		sprintf(filename,"%s",argv[1]);
	}

/*
	find the most appropriate file.gpr for a named group: first in the
	current directory, then in the $HOME/.xgroups, and last in the "xgroups
	directory"
*/

	sprintf(fn,"./%s.grp",filename);
    if (!esiste(fn))
    {
		sprintf(fn,"%s/.xgroups/%s.grp",getenv("HOME"),filename);
    	if (!esiste(fn))
		{
			sprintf(fn,"%s/%s.grp",GRPDIR,filename);
    		if (!esiste(fn))
			{
				fprintf(stderr,"cannot open group %s\n",filename);
				exit(1);
			}
		}
	}

/*
	read the .grp file and prepare the informations for the generic icon
	geometry
*/

	ReadGruppo(toplevel, fn);

	larghezza=(WICONA+10) * (NumIcone % INAROW + 1); if (NumIcone > (INAROW-1)) larghezza=100*(INAROW-1);
	if (larghezza <160) larghezza=160;
	altezza=40 + (HICONA+20) * ((NumIcone / INAROW) + 1);

/*
	create the main window, fill and create the menus
*/

	toplevel = x_init(filename, 200, 200, larghezza, altezza, argc, argv);

	crea_menu();

	menu_bar = x_create_menubar(toplevel, 0, 0, 1024, 30, 2+(NumGruppi>0));
	x_create_pulldown(menu_bar, "Commands",   2, e1);
	x_create_pulldown(menu_bar, "Options", 5, e2);
	if (NumGruppi>0) x_create_pulldown(menu_bar, "Groups", NumGruppi, e3);

/*
	now i paint the icons
*/

	for(i=0;i<=NumIcone;i++)
	{
		Read_icona(toplevel, Gruppo[i].file_icona, &(Gruppo[i]));
		Paint_icona(toplevel,&Gruppo[i],do_cmd_fn,i);
	}

/*
	I make the About window and related buttons ... and my face
*/

	beppe_window = x_create_popup(DefaultRootWindow(display), 160, 100, 300, 120);
	x_labeled_button(beppe_window, "Dismiss", 240, 15, 50, 20, beppe_fn, 1);

	x_label(beppe_window, VERSION, 120, 30, 100, 20);
	x_label(beppe_window, "(c)1993 by Giuseppe Zanetti", 120, 60, 100, 20);
	x_label(beppe_window, "beppe@maya.dei.unipd.it", 120, 90, 100, 20);

	icona_beppe.x=30;
	icona_beppe.y=30;
	strcpy(icona_beppe.nome,"Beppe");
	Read_icona(beppe_window,BEPPE,&icona_beppe);
	Paint_icona(beppe_window,&icona_beppe,beppe_fn,1);

/*
	wait for a event
*/

	x_event_loop();
}
