 /* Fichier slide_show.dark.c				*/
/* Module appele par le programme principal	*/
/* pour effectuer un effet defini..appele par	*/
/* loadseg					*/

#include <exec/types.h>
#include <exec/nodes.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <graphics/displayinfo.h>
#include <graphics/display.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/asl_protos.h>

#include <rexx/storage.h>
#include <rexx/errors.h>

#include <libraries/asl.h>
#include "/includes/struct.h"
#include "/iff/jiff.h"
#include "/includes/tom_gadget.h"

struct	FileRequester	*my_req=0;
extern	char	*malloc();
extern	struct	GfxBase	*GfxBase;
char	*name_file="S:Slide_show.cfg";
char	*p_choose="Select file to show...";

extern	struct my_data	*p_info;
extern	struct	appel_proc	*p_data_proc;
struct	RastPort	*rp,*rps;
struct	Screen	*s;
extern	char	*hd;

struct	Library	*GadToolsBase;
UBYTE	flg_end,flg_modif;

USHORT	palette_deb[32],palette_end[32];
extern	USHORT	Palette[];

void  put_ea_cmap();

char	*p_text_info="This module allow you to make a little slide show\nas a screen blanker\nYou must first select the files you want to see using\nADD (and SHOW to view the selected one)\nThis names wil be saved in a configuration file\nin your s: directory, named\n     s:slide_show.cfg\n\nThomas landspurg...";

struct	Gadget	__saveds	*init_gadg();
void	__saveds	press_gadg();
int	__saveds	press_add();
void	__saveds	end_gadg();
int	__saveds	press_del();
int	__saveds	press_show();


#define	WIDTH	320
#define	HEIGHT	256

UWORD	cmap[32];

char	buffer2[100];
struct TagItem    ScreenTags[] = {
    SA_Left,          0,
    SA_Top,           0,
    SA_Width,         WIDTH,
    SA_Height,        HEIGHT,
    SA_Depth,         5,
    SA_Type,          CUSTOMSCREEN,
    SA_DisplayID,     PAL_MONITOR_ID,
    TAG_DONE };

struct	Library *AslBase=0;

struct List ImagesList = {
	(struct Node *)&ImagesList.lh_Tail,
	(struct Node *)0l,
	(struct Node *)&ImagesList.lh_Head,0,0 };

#define	MY_MAX_NOM	20
char	*p_nom[MY_MAX_NOM];
char	*p_dir[MY_MAX_NOM];

typedef struct my_node{
	struct Node	node;
	int	num;
};
#define	LONG_DSIZE	80
#define	LONG_FSIZE	80

static	int	num=0;
static	char	*p_null="non alloue";

#define	TAILLE_BUF	100
char	buffer_name[TAILLE_BUF]="";
struct	tom_gadget	my_gadg[]={
	{"_Images",	LISTVIEW, 90, 16, 200,56, 0,0,0,0,(char *)&ImagesList},
	{"^^_Delete^^",	BUTTON , 107, 75, 113,11, 0,0,0,0,(char *)&press_del},
	{"_Add",	BUTTON ,  41, 75,  61,11, 0,0,0,0,(char *)&press_add},
	{"_Show",	BUTTON , 227, 75,  80,11, 0,0,0,0,(char *)&press_show},
#ifdef	TWO_VIEW
	{"_Use_2view",	CHECKBOX, 90, 90,  10,10,FALSE,0,0,0,0},
	{"_2viewName",	STRING,  200, 90,  70,14,0,TAILLE_BUF,0,0,buffer_name},
#endif
	{0,		END_LISTE, 0,  0,   0, 0, 0,0,0,0,		    0}};

void	my_text(rp,x,y,p_c)
struct	RastPort	*rp;
int	x,y;
char	*p_c;
{
	Move(rp,x,y);
	Text(rp,p_c,strlen(p_c));
}

void	rotate()
{
	static	unsigned	int	compt=0;
	unsigned	int	n,i;

	n=compt;
	for(i=1;i<32;i++){
		n=n%31;
/*
		SetRGB4(&s->ViewPort,i,ScreenColors[n+1].Red,ScreenColors[n+1].Green,ScreenColors[n+1].Blue);
*/
		n++;
	}
	compt++;
}

#ifdef	TWO_VIEW
/*************************************************************************/

send_msg(buf)
char *buf;
{
	struct	RexxMsg	rx_message;
	struct	MsgPort *rexx_port = NULL;
	struct	MsgPort *reply_port = NULL;
	int	code_ret;

   if(mystrlen(buf)!=0){
	code_ret=0;
	Forbid();
	if( (rexx_port=FindPort ("2View.1") ==NULL){
		Permit();
		code_ret=-1;
	}else if((reply_port=(struct MsgPort *)CreatePort ("Reply port", 0L))==NULL){
		Permit();
		code_ret=-1;
	}else{
		rx_message.rm_Args[0]=buf;
		rx_message.rm_Args[1]=NULL;
		rx_message.rm_Args[2]=NULL;
		rx_message.rm_Action=RXCOMM;
		rx_message.rm_Node.mn_ReplyPort=reply_port;
		rx_message.rm_Node.mn_Node.ln_Type=NT_MESSAGE;

		PutMsg(rexx_port,&rx_message);
		Permit();
		WaitPort(reply_port);
		DeletePort(reply_port);
		if(rx_message.rm_Result1!=RC_OK)code_ret=-1;
	}
	return(code_ret);
   }
}
#endif

/* Ajoute un noeud dans la liste, et retourne le noeau alloue */
/* 0 si pas possbile (deja plein par exemple				*/

struct	my_node	*add_node(int	pos)
{
	struct my_node *pn;
	struct	Node	*node,*pre;
	int	i;

	i=0;
	while((p_nom[i]!=0)&&(i<MY_MAX_NOM)){
		i++;
	}
	if(i<MY_MAX_NOM){
		pn=(struct my_node *)malloc(sizeof(struct my_node));
		node=&pn->node;

		node->ln_Pred=0;;
		node->ln_Succ=0;;
		node->ln_Name=p_null;
		node->ln_Type=0;
		pn->num=i;
		if(pos==-1){
			AddTail(&ImagesList,node);
		}else{
			pre=ImagesList.lh_Head;
			for(i=0;i<pos;i++){
				if(pre!=NULL)pre=pre->ln_Succ;
			}
			Insert(&ImagesList,node,pre);			
		}

	}else{
		MyWrite("add_node: liste plein!\n");
		pn=0;
	}
	return(pn);
}

/***************************************************** del_node() ********/

/*******************************/
/* retire un noeud de la liste */
/*******************************/

void	del_node(struct my_node *pn)
{
	p_nom[pn->num]=0;
	if(pn!=0){
		Remove(&pn->node);
		free(pn);
	}
}
/******************************************************* test_iff() *****/
int	test_iff(char *p_name)
{
	BPTR	hd;
	char	buffer[4+4+4];
	int	ret;

	ret=FALSE;
	hd=Open(p_name,MODE_OLDFILE);
	if(hd!=NULL){
		Read(hd,buffer,sizeof(buffer));
		if((strncmp(buffer,"FORM",4)==0)&&(strncmp(&buffer[8],"ILBM",4)==0)){
			ret=TRUE;
		}
		Close(hd);
	}
	return ret;
}


/***********************/
/* Call the IFF loader */
/***********************/

struct	Screen	*Charge_Iff(name,old_s)
char	*name;
struct	Screen	*old_s;
{
	struct	ILBM_info	*info;
	struct	RastPort	EcranRastPort;
	struct	Screen	*s;

	SPrintF(buffer2,"Charge iff de:%s\n",name);
	MyWrite(buffer2);

	InitRastPort(&EcranRastPort);
	if ( (info = read_iff(name,0) ) != NULL){
	    ScreenTags[2].ti_Data=(ULONG)info->header.w;
	    ScreenTags[3].ti_Data=(ULONG)info->header.h;
	    ScreenTags[4].ti_Data=(ULONG)info->header.nPlanes;
 	    ScreenTags[6].ti_Data=PAL_MONITOR_ID;
	    if(info->header.w>320){
		ScreenTags[6].ti_Data|=MODE_640;
		}
	    if(info->header.h>256){
		ScreenTags[6].ti_Data|=INTERLACE;
		}
	    if(info->header.nPlanes==6){
		ScreenTags[6].ti_Data|=HOLDNMODIFY;
		}
/*
	    ScreenTags[6].ti_Data|=info->camg;
*/
            if ( ( s = OpenScreenTagList( 0l, ScreenTags ))!=0){
		FreeSprite (0);
		GfxBase->SpriteReserved|=1;
		rp = &(s->RastPort);
/*

		SetAPen(rp,0);
		RectFill(rp,0,0,rp->BitMap->BytesPerRow*8,rp->BitMap->Rows);
*/
		put_ea_cmap(&info->cmap,32 );
		EcranRastPort.BitMap = &info->bitmap;
		ClipBlit( &EcranRastPort, 0L, 0L,
			rp, 0L, 0L,
			(rp->BitMap->BytesPerRow)*8,
			rp->BitMap->Rows, (long)COPY_MINTERM);
		LoadRGB4(&s->ViewPort,&palette_end,32);
		    if(old_s!=0){
			CloseScreen(old_s);
			old_s=0;
		    }
	    }else{
		s=old_s;
		old_s=0;
	    }
	    free_planes(&info->bitmap);
	}else{
		s=old_s;
	}
	return(s);
}

/************************************************************/
/* Procedure to put the colors of the picture on the screen */
/************************************************************/

void put_ea_cmap(cmap, colors)
unsigned char *cmap;
int colors;
{
	int i;

	if (colors > MAXCOL)	/*color clipping*/
		colors = MAXCOL;
	for (i=0; i<colors; i++)
	{
		palette_end[i] = 
			((cmap[0] & 0xf0) << 4) + (cmap[1] & 0xf0) + ((cmap[2] & 0xf0) >> 4);
		cmap += 3;
	}
}

void	__saveds	dark()
{
   struct	Screen	*s;
   char	buffer[LONG_DSIZE+LONG_FSIZE];
   int	i,n;
   struct	Node	*node;
   struct	my_node *my_n;

   /* Do we use 2view? */
#ifdef	TWO_VIEW
   if(my_gadg[4].value==FALSE){
#endif
	n=0;
	s=0;
	node=ImagesList.lh_Head;
	/* Y a t'il au moins un element dans la liste? */
	if(node!=(struct Node *)&ImagesList.lh_Tail){
		while(tst_end()==FALSE){
			if(node==0){
				node=ImagesList.lh_Head;
			}
			my_n=(struct my_node *)node;
			n=my_n->num;
			n=n%MY_MAX_NOM;
			if(p_nom[n]!=p_null){
				sprintf(buffer,"%s%s",p_dir[n],p_nom[n]);
				s=Charge_Iff(buffer,s);
				for(i=0;(i<100)&&(tst_end()==FALSE);i++){
					Delay(1);
				}
	
			}
			node=node->ln_Succ;
		}
	}
	if(s!=0)CloseScreen(s);
#ifdef	TWO_VIEW
    }else{
	if(my_gadg[5].p_data[0]!=0){
		SPrintF(buffer,"run %s FROM %s SECS 5\n",my_gadg[5].p_data,
							name_file);
		Execute(buffer,NULL,NULL);
		wait_end();
		send_msg("QUIT");
	    }
	}
#endif

}

struct	Gadget	*get_listview_id(struct	contexe *ctx)
{
	return my_gadg[0].p_gadg;
}
struct	my_node	*get_node(int	num)
{
	int	i;
	struct	Node	*pre;

	pre=ImagesList.lh_Head;

	for(i=0;i<num;i++){
		if(pre!=NULL)pre=pre->ln_Succ;
	}

	return (struct my_node *)pre;
}

int	__saveds	press_show(pg,p_t,ctx)
struct	Gadget	*pg;
struct	tom_gadget	*p_t;
struct	contexe	*ctx;
{
	struct	Screen	*s;
	struct	my_node	*my_n;
	char	buffer[LONG_DSIZE+LONG_FSIZE];

	my_n=get_node(my_gadg[0].value);
	SPrintF(buffer,"%s%s",p_dir[my_n->num],p_nom[my_n->num]);
	s=Charge_Iff(buffer,0);
	Delay(100);
	if(s!=0)CloseScreen(s);
	return FALSE;
}

int	__saveds	press_del(pg,p_t,ctx)
struct	Gadget	*pg;
struct	tom_gadget	*p_t;
struct	contexe	*ctx;
{
	int	num;
	struct	Window	*wnd;
	struct	my_node	*my_n;
	struct	Gadget	*gad;

	wnd=ctx->Wnd;

	num=my_gadg[0].value;

	my_n=get_node(num);
	num=my_n->num;

	gad=get_listview_id(ctx);
	GT_SetGadgetAttrs(gad,wnd,NULL,GTLV_Labels,~0,TAG_DONE);
	if(p_nom[num]!=0){
		(char *)free(p_nom[num]);
		(char *)free(p_dir[num]);
		p_nom[num]=0;
		del_node(my_n);
	}
	GT_SetGadgetAttrs(gad,wnd,NULL,GTLV_Labels,&ImagesList,TAG_DONE);
	/* on ne sort pas...*/
	return FALSE;
}

int	__saveds	press_add(pg,p_t,ctx)
struct	Gadget	*pg;
struct	tom_gadget	*p_t;
struct	contexe	*ctx;
{
	struct	Window	*wnd;
	int	len_dir;
	int	res;
	struct	Gadget	*gad;
	struct	my_node	*my_node,*node_sel;

	char	buffer[LONG_DSIZE+LONG_FSIZE];

	/* A t'on pu obtenir le requester? si non, on sort...		*/
	if(my_req==0)return -1;

	/* Pour un objet de type listview, on met le ptr sur le gadg	*/
	gad=get_listview_id(ctx);
	wnd=ctx->Wnd;

	/* Je fais une copie du repertoire courant... */
	node_sel=get_node(my_gadg[0].value);
	if((my_req->rf_Dir!=0)&&(p_nom[node_sel->num]!=0)){
		strcpy(my_req->rf_Dir,p_dir[node_sel->num]);
	}


	/* Ouverture du requester de fichier pour l'utilisateur */
/*
	my_req->rf_Hail=p_choose;
*/
	res=(int)RequestFile(my_req);

	/* Si l'utilisateur a choisi qq chose, et si il reste de la place */

	if((res!=0)&&((my_node=add_node(my_gadg[0].value))!=0)){
		GT_SetGadgetAttrs(gad,wnd,NULL,GTLV_Labels,~0,TAG_DONE);

		num=my_node->num;
		p_nom[num]=(char *)malloc(strlen(my_req->rf_File)+1);
		strcpy(p_nom[num],my_req->rf_File);

		len_dir=strlen(my_req->rf_Dir);

		/* Test si le dernier caractere du rep contient l'antislash */
		if((my_req->rf_Dir[len_dir-1]!='/')&&(my_req->rf_Dir[len_dir-1]!=':')){
			p_dir[num]=(char *)malloc(len_dir+2);
			strcpy(p_dir[num],my_req->rf_Dir);
			p_dir[num][len_dir++]='/';
			p_dir[num][len_dir]=0;
		}else{
			p_dir[num]=(char *)malloc(len_dir+1);
			strcpy(p_dir[num],my_req->rf_Dir);
		}
		my_node->node.ln_Name=p_nom[num];
		sprintf(buffer,"%s%s",p_dir[num],p_nom[num]);
		if(test_iff(buffer)==FALSE){
			MyWrite(buffer);
			MyWrite(" n'est pas un fichier IFF!\n");
			del_node(my_node);
		}
		GT_SetGadgetAttrs(gad,wnd,NULL,	GTLV_Labels,&ImagesList,
						GTLV_Selected,my_gadg[0].value,
						TAG_DONE);
	}
	return(FALSE);
}


load_data()
{
	int i,taille,pos_dir,n;
	UWORD	flg_end;
	char	buffer[100];
	BPTR	slide_hd;
	struct	my_node	*pn;


	GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",0);
	if(GadToolsBase==0){
		return -1;
	}
	slide_hd=Open(name_file,MODE_OLDFILE);
	flg_end=FALSE;
	if(slide_hd!=0){
		for(i=0;i<MY_MAX_NOM;i++){
			p_nom[i]=0;
			p_dir[i]=0;
		}
		for(i=0;((i<MY_MAX_NOM)&&(flg_end==FALSE));i++){
			n=-1;
			do{
				n++;
				if(Read(slide_hd,&buffer[n],1)!=1){
					flg_end=TRUE;
				}
			}while((buffer[n]!='\n')&&(flg_end==FALSE));

			if(flg_end==FALSE){
				pn=add_node(-1);
				if(pn==0){
					flg_end=TRUE;
				}
			}
			if(flg_end==FALSE){
				taille=n;
				pos_dir=n;
				while((buffer[n]!='/')&&(buffer[n]!=':')&&(n!=0)){
					n--;
				}
				pos_dir=n+1;
				if(taille!=pos_dir){
					p_nom[i]=malloc(taille-pos_dir);
					strncpy(p_nom[i],&buffer[pos_dir],taille-pos_dir);
					p_nom[i][taille-pos_dir]=0;
					pn->node.ln_Name=p_nom[i];

					if(pos_dir!=0){
						p_dir[i]=malloc(pos_dir);
						strncpy(p_dir[i],buffer,pos_dir);
						p_dir[i][pos_dir]=0;

					}else{
						p_dir[i]=0;
					}

				}else{
					p_nom[i]=0;
				}
			}
		}
		Close(slide_hd);
	}
	AslBase=(struct Library *)OpenLibrary(AslName,0);
	if(AslBase!=0){
		my_req=AllocFileRequest();
	}
	GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",0);
	if(GadToolsBase==0){
		my_req=0;
	}

}

proc_init()
{
	load_data();
	p_data_proc->code_ret=DARK_WB_20;
}

void	proc_end()
{
	BPTR	slide_hd;
	int	i,len;

	slide_hd=Open(name_file,MODE_NEWFILE);
	if(slide_hd!=0){
		for(i=0;i<MY_MAX_NOM;i++){
			if(p_nom[i]!=0){
				len=strlen(p_dir[i]);
				if(p_dir[i]!=NULL){
					Write(slide_hd,p_dir[i],len);
				}
				if(p_dir[i][len-1]!='/'){
					Write(slide_hd,"/",1);
				}

				Write(slide_hd,p_nom[i],strlen(p_nom[i]));
				Write(slide_hd,"\n",1);
			}
		}
		Close(slide_hd);
	}
	/* Enleve les noeuds..*/
	while(ImagesList.lh_Head!=(struct Node *)&ImagesList.lh_Tail){
		del_node((struct my_node *)ImagesList.lh_Head);
	}
	if(my_req!=0){
		FreeFileRequest(my_req);
	}
	if(AslBase!=0){
		CloseLibrary(AslBase);
	}
	if(GadToolsBase!=0){
		CloseLibrary(GadToolsBase);
	}
}

