 /* 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 <clib/datatypes_protos.h>
#include <datatypes/datatypes.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.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;
extern	struct	IntuiBase	*IntuiBase;
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 *DataTypesBase;
struct	Library	*GadToolsBase;
UBYTE	flg_end,flg_modif;

USHORT	palette_deb[32],palette_end[32];
extern	USHORT	Palette[];
Object *o=0;
Object *old_o=0;

void  put_ea_cmap();

char	*p_text_info=
"This module allow you to make a little slide show\n"
"as a screen blanker\n"
"You must first select the files you want to see using\n"
"ADD (and SHOW to view the selected one)\n"
"This names wil be saved in a configuration file\n"
"in your s: directory, named\n"
"     s:slide_show.cfg\n"
"\n"
"Note that the images are show in a random order\n\n"
"Note also that if you have WB3.0 with datatypes,\n"
"slide show use these datatypes, so you can use\n"
"GIF pictures for ex. if you have the good datatype\n\n"
"Thomas 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
/*#define TWO_VIEW*/
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[]={
	{"I_mages",	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},
	{"_Tempo",	SLIDER,   90, 90, 200, 8,100,0,200,0,0},
#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}};

static  unsigned        int     seed;

unsigned        int     my_rand()
{
        
        seed=25173*seed+138490;
        return(seed);
}
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);
	}
}

/***********************/
/* 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){
			DCloseScreen(old_s);
		    }
	    }else{
		s=old_s;
		old_s=0;
	    }
	    free_planes(&info->bitmap);
	}else{
		s=old_s;
	}
	return(s);
}
/*********************************************************/
struct	Screen *New_Charge_Iff(char *pc,struct Screen *old_s)
{
    ULONG *cregs = NULL, numcolors, i, r, g, b;
    struct dtFrameBox dtf = {NULL};
    struct FrameInfo fri = {NULL};
    struct BitMapHeader *bmhd;
    ULONG modeid = INVALID_ID;
    struct gpLayout gpl;
    struct Screen *scr;
    struct BitMap *bm;
    struct RastPort rp;

    scr=0;
    o=0;
    if ((DataTypesBase)&&
	(GfxBase->LibNode.lib_Version>=37)&&
	(IntuiBase->LibNode.lib_Version>=37)
	){
		/* Obtain a pointer to the picture object */
		if (o = NewDTObject ((APTR) pc,
				     DTA_SourceType, DTST_FILE,
				     DTA_GroupID, GID_PICTURE,
				     PDTA_Remap, FALSE,
				     TAG_DONE))
		{
		    /* Ask the object what kind of environment it needs */
		    dtf.MethodID = DTM_FRAMEBOX;
		    dtf.dtf_FrameInfo = &fri;
		    dtf.dtf_ContentsInfo = &fri;
		    dtf.dtf_SizeFrameInfo = sizeof (struct FrameInfo);
		    if (DoMethodA (o, &dtf) && fri.fri_Dimensions.Depth)
		    {
			/* Layout the object on our process */
			gpl.MethodID = DTM_PROCLAYOUT;
			gpl.gpl_GInfo = NULL;
			gpl.gpl_Initial = 1;
			if (DoMethodA (o, &gpl))
			{
			    /* Get the object information */
			    GetDTAttrs (o,
					PDTA_ModeID, &modeid,
					PDTA_CRegs, &cregs,
					PDTA_NumColors, &numcolors,
					PDTA_BitMapHeader, &bmhd,
					PDTA_BitMap, &bm,
					TAG_DONE);

			    /* Make sure we have a bitmap to attach to the screen */
			    if (bm)
			    {
				/* Open the screen */
				if (scr = OpenScreenTags (NULL,
							  SA_Width, (ULONG) fri.fri_Dimensions.Width,
							  SA_Height, (ULONG) fri.fri_Dimensions.Height,
							  SA_Depth, (ULONG) fri.fri_Dimensions.Depth,
							  SA_DisplayID, modeid,
							  SA_ShowTitle, FALSE,
							  SA_Quiet, TRUE,
							  SA_Behind, TRUE,
/*							  SA_BitMap, bm,*/
							  TAG_DONE))
				{
				    InitRastPort(&rp);
			            rp.BitMap=bm;
				    ClipBlit( &rp, 0L, 0L,
					      &scr->RastPort, 0L, 0L,
					      fri.fri_Dimensions.Width,
					      fri.fri_Dimensions.Height,
					      (long)COPY_MINTERM);
				    /* Load the color map */
				    if (cregs)
				    {
					numcolors = 2 << (scr->RastPort.BitMap->Depth - 1);
					for (i = 0; i < numcolors; i++)
					{
					    r = cregs[i * 3 + 0];
					    g = cregs[i * 3 + 1];
					    b = cregs[i * 3 + 2];
					    SetRGB32 (&scr->ViewPort, i, r, g, b);
					}
				    }

				    /* Bring the screen to the front now */
				    ScreenToFront (scr);
				    DCloseScreen(old_s);
				    FreeSprite (0);
				    GfxBase->SpriteReserved|=1;

					
				}
			    }
			}
		    }
		    /* Get rid of the object */
	            DisposeDTObject (o);
		}
	}
	if(scr==0)scr=Charge_Iff(pc,old_s);
	return(scr);
}
/************************************************************/
/* 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	dark()
{
   struct	Screen	*s;
   char	buffer[LONG_DSIZE+LONG_FSIZE];
   int	i,n;
   UWORD	nb_image,num_image;
   struct	Node	*node;
   struct	my_node *my_n;

    o=0;
   /* Do we use 2view? */
#ifdef	TWO_VIEW
   if(my_gadg[5].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){
		nb_image=0;
		while(node!=0){
			nb_image++;
			node=node->ln_Succ;
		}
		while(tst_end()==FALSE){

			num_image=my_rand()%nb_image;
			node=ImagesList.lh_Head;
			for(i=0;i<num_image;i++)node=node->ln_Succ;
/*
			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=New_Charge_Iff(buffer,s);
				for(i=0;(i<my_gadg[4].value)&&(tst_end()==FALSE);i++){
					Delay(1);
				}
	
			}
/*
			node=node->ln_Succ;
*/
		}
	}
	DCloseScreen(s);
#ifdef	TWO_VIEW
    }else{
	if(my_gadg[6].p_data[0]!=0){
		SPrintF(buffer,"run %s FROM %s SECS 5\n",my_gadg[6].p_data,
							"s:slide_show.cfg");
		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=New_Charge_Iff(buffer,0);
	Delay(100);
	DCloseScreen(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;
}
char *alloc_dir(char *p_dir_req)
{
	int	len_dir;
	char	*pc;

	len_dir=strlen(p_dir_req);
	if((p_dir_req[len_dir-1]!='/')&&(p_dir_req[len_dir-1]!=':')){
		pc=(char *)malloc(len_dir+2);
		strcpy(pc,p_dir_req);
		pc[len_dir++]='/';
		pc[len_dir]=0;
	}else{
		pc=(char *)malloc(len_dir+1);
		strcpy(pc,p_dir_req);
	}
	return(pc);
}

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

	/* 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)AslRequest(my_req,0L);

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

	if(res!=0){
		GT_SetGadgetAttrs(gad,wnd,NULL,GTLV_Labels,~0,TAG_DONE);
		wbarg=my_req->rf_ArgList;
		if(my_req->rf_NumArgs){
	           for(i=0;(i<my_req->rf_NumArgs)&&((my_node=add_node(my_gadg[0].value))!=NULL);i++){
			num=my_node->num;
			p_nom[num]=(char *)malloc(strlen(wbarg->wa_Name)+1);
			strcpy(p_nom[num],wbarg->wa_Name);
			p_dir[num]=alloc_dir(my_req->rf_Dir);
			my_node->node.ln_Name=p_nom[num];
			wbarg++;
		   }
		}else{
	        	my_node=add_node(my_gadg[0].value);
			if(my_node){
				num=my_node->num;
				p_dir[num]=alloc_dir(my_req->rf_Dir);
				p_nom[num]=(char *)malloc(strlen(my_req->rf_File)+1);
				strcpy(p_nom[num],my_req->rf_File);
				my_node->node.ln_Name=p_nom[num];

			}
		}
		GT_SetGadgetAttrs(gad,wnd,NULL,	GTLV_Labels,&ImagesList,
						GTLV_Selected,my_gadg[0].value,
						TAG_DONE);
	}
	return(FALSE);
}


void	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;
	}
	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=AllocAslRequestTags(	ASL_FileRequest,
					ASL_FuncFlags,FILF_MULTISELECT,
					TAG_DONE);
	}
	GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",0);
	if(GadToolsBase==0){
		my_req=0;
	}

}

void	proc_init()
{
	DataTypesBase = OpenLibrary ("datatypes.library", 39);
	load_data();
        seed=VBeamPos();
	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){
		FreeAslRequest(my_req);
	}
	if(AslBase!=0){
		CloseLibrary(AslBase);
	}
	if(GadToolsBase!=0){
		CloseLibrary(GadToolsBase);
	}
	if(DataTypesBase)CloseLibrary (DataTypesBase);
}

