/******************************************************************************
 * Steve Rider - stever@transmission23.com
 * QuickPics
 *   Image galleries for the web made easy
 *
 * dir.c - directory structures and routines for storing image information
 *
 *****************************************************************************/
/* 18 February 98 */

#include "qp.h"
#include "utility.h"
#include "dir.h"
#include <math.h>


/****************************************************************************
 *
 * QPDir object definitions
 *
 ****************************************************************************/

void QPDir_Init()
{
	/* initialize */
	QPDir.dirs = NULL;
	QPDir.last = NULL;

	QPDir.num_dirs = 0;
	strcpy(QPDir.title,"My QuickPics Image Gallery");
	strcpy(QPDir.heading,"Description of my gallery.");
	QPDir.dir_count = 0;
	QPDir.img_count = 0;
	QPDir.flags = 0L;
}

void QPDir_AppendDir(dirrec *dir)
{
	dirrec_append(&QPDir.dirs, &QPDir.last, dir);
	QPDir.num_dirs++;
}

void QPDir_DeleteDir(dirrec *dir)
{
	dirrec_delete(&QPDir.dirs, &QPDir.last, dir);
	QPDir.num_dirs--;
}

void QPDir_AppendSubDir(dirrec *dir, dirrec *subdir)
{
	dirrec_append(&dir->subdirs, &dir->subdirs_last, subdir);
	dir->num_subdirs++;
}

void QPDir_DeleteSubDir(dirrec *dir, dirrec *subdir)
{
	dirrec_delete(&dir->subdirs, &dir->subdirs_last, subdir);
	dir->num_subdirs--;
}

void QPDir_AppendImage(dirrec *dir, imgrec *img)
{
	imgrec_append(&dir->images, &dir->images_last, img);
	dir->num_images++;
}

void QPDir_DeleteImage(dirrec *dir, imgrec *img)
{
	imgrec_delete(&dir->images, &dir->images_last, img);
	dir->num_images--;
}




/****************************************************************************/
/* object QPDir high-level implementation-specific function definitions. */

u_long QPDir_AvgBytes(dirrec *dir)
{
	imgrec *x;
	u_long tot = 0;

	for(x=dir->images; x; x=x->next)
		tot += x->bytes;

	return dir->num_images == 0 ? 0 : tot / dir->num_images;
}

dirrec *QPDir_AddNewDir(const char *name)
{
	dirrec *x;

	/* Allocate memory for new node */
	x = dirrec_new();

	/* Assign it some data */
	dirrec_setpath(x,name);
	dirrec_setname(x,name);

	/* Default description */
	dirrec_setdescription(x,"No description file.");


	/* Append the record */
	QPDir_AppendDir(x);

	return x;
}

imgrec *QPDir_AddNewImage(dirrec *dir, const char *name)
{
	imgrec	*x;

	/* Allocate memory for new node */
	x = imgrec_new();

	/* Assign it some data */
	imgrec_setname(x,name);
/*
	imgrec_setdescription(x,name);
*/

	/* Append the record */
	QPDir_AppendImage(dir,x);

	return x;
}

dirrec *QPDir_AddNewSubDir(dirrec *dir, const char *name)
{
	dirrec	*x;
	char	path[MAXFILENAMELEN];

	/* Allocate memory for new node */
	x = dirrec_new();

	/* Assign it some data */
	dirrec_setname(x,name);
	sprintf(path,"%s/%s",dir->path,name);
	dirrec_setpath(x,path);

	/* Default description */
	dirrec_setdescription(x,"No description file.");

	/* Default folder name */
	dirrec_setalias(x,name);

	/* Append the record */
	QPDir_AppendSubDir(dir,x);

	return x;
}


/*
 * We create the directory tree from the current working directory, which
 * we set to be the target pics path on initialization.  This makes it
 * easier to work with relative paths instead of absolute paths.
 */
void QPDir_ReadDirectoryTree()
{
	char	**filelist;
	int	number_files, j;
	dirrec	*dir;

	/* First, read root title and description */
	QPDir_GetGalleryName();
	QPDir_GetGalleryDescription();

	/* We can write it right away too */
	QPDir_WriteGalleryConfig();

	/* Read directory into filelist */
	filelist = ListFiles(".",&number_files);
	if(filelist == NULL)
	{
		printf("  Unable to read directory: %s\n",QP.rootdir);
		return;
	}

	/* Iterate the list */
	for(j=0; j<number_files; j++)
	{
		/* Add directories.  We'll explore them recursively in a sec. */
		if(IsDirectory(filelist[j]))
			QPDir_AddNewDir(filelist[j]);
	}

	/* Don't forget to release */
	for(j=0; j<number_files; j++)
		nfree(filelist[j]);
	nfree(filelist);

	/* Now we go recursive */
	for(dir=QPDir.dirs; dir; dir=dir->next)
		QPDir_ExploreDir(dir, "..", dir);

	printf("  --\n");
	printf("  Total: %d director%s, %d image%s\n",QPDir.dir_count,QPDir.dir_count == 1 ? "y" : "ies",QPDir.img_count,QPDir.img_count == 1 ? "" : "s");
	printf("\n");
}

void QPDir_ExploreDir(dirrec *dir, char *path_home, dirrec *oldest_parent)
{
	char	**filelist;
	char	filepath[MAXFILENAMELEN], new_path_home[MAXFILENAMELEN];
	char	base[MAXFILENAMELEN], ident[MAXFILENAMELEN];
	int	number_files, j, type;
	dirrec	*subdir;
	imgrec	*img;

	/* Read directory */
	filelist = ListFiles(dir->path, &number_files);
	if(filelist == NULL)
	{
		printf("  Unable to read directory: %s\n",dir->path);
		return;
	}

	QPDir.dir_count++;
	printf("  Reading directory: %s/%s\n",BaseFilename(QP.rootdir),dir->path);

	/* Check for foldername */
	QPDir_GetFolderName(dir);

	/* Check for folder description */
	QPDir_GetFolderDescription(dir);

	/* Set relative path home and oldest parent */
	dirrec_setpath_home(dir,path_home);
	dir->oldest_parent = oldest_parent;

	/* Add image files */
	for(j=0; j<number_files; j++)
	{
		/* Build relative path to image */
		strcpy(filepath,dir->path);
		strcat(filepath,"/");
		strcat(filepath,filelist[j]);

		/* Add directories */
		if(IsDirectory(filepath))
		{
			/* Create new node and add it to this dir */
			subdir = QPDir_AddNewSubDir(dir,filelist[j]);

			/* Tack on another level to path home */
			sprintf(new_path_home,"%s/..",dir->path_home);

			/* Explore (recursive call) */
			QPDir_ExploreDir(subdir, new_path_home, oldest_parent);

			continue;
		}

		/* Add images */
		strcpy(base,BaseFilename(filepath));
		strcpy(ident,&base[strlen(base)-3 >= 0 ? strlen(base)-3 : 0]);
		if(isequal(ident,QP.thumbnail_identifier))
			continue;

		if(IsImage(filepath,&type))
		{
			/* Got one! Create a node. */
			img = QPDir_AddNewImage(dir,filelist[j]);
			if(img == NULL)
				break;

			/* Set image type */
			img->type = type;

			/* Set image size */
			img->bytes = GetFilesize(filepath);

			/* Get image dimensions */
			Image_GetDimensions(filepath,&img->width,&img->height);

			/* Get description from file or prompt */
			QPDir_GetImageDescriptions(dir,img);

			QPDir.img_count++;
		}
	}

	/* Check for folder main image */
	QPDir_GetFolderMainImage(dir);

	/* Before we go, write a folder config file back to disk */
	QPDir_WriteFolderConfig(dir);

	/* Don't forget to free the list */
	for(j=0; j<number_files; j++)
		nfree(filelist[j]);
	nfree(filelist);
}

void QPDir_GetFolderName(dirrec *dir)
{
	FILE	*f;
	char	foldername[MAXFILENAMELEN], path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",dir->path,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,"n") && s[0])
			{
				dirrec_setalias(dir,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		printf("    Folder name? [%s]: ",dir->name);
		fflush(stdout);
		fflush(stdin);
		fgets(foldername,MAXFILENAMELEN-1,stdin);
		rmspace(foldername);
		if(!foldername[0])
			strcpy(foldername,dir->name);
		dirrec_setalias(dir,foldername);

	}
}

void QPDir_GetFolderDescription(dirrec *dir)
{
	FILE	*f;
	char	description[MAXTEXTLEN], path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",dir->path,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,"d") && s[0])
			{
				dirrec_setdescription(dir,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		if(QP.prompt_for_description)
		{
			printf("  Folder description? [Pictures of %s.]: ",
				dir->alias);
			fflush(stdout);
			fflush(stdin);
			fgets(description, MAXTEXTLEN-1, stdin);
			rmspace(description);
			if(!description[0])
			{
				sprintf(description,"Pictures of %s.",
					dir->alias);
			}
		}
		else
			sprintf(description,"Pictures of %s.",dir->alias);

		dirrec_setdescription(dir,description);
	}
}

void QPDir_GetFolderMainImage(dirrec *dir)
{
	FILE	*f;
	char	path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",dir->path,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,"m") && s[0])
			{
				dirrec_setmainimage(dir,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		/* Get first image from folder */
		if(dir->images)
			dirrec_setmainimage(dir, dir->images->name);
	}
}

void QPDir_GetImageDescriptions(dirrec *dir, imgrec *img)
{
	FILE	*f;
	char	description[MAXTEXTLEN], path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",dir->path,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,img->name))
			{
				imgrec_setdescription(img,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		if(QP.prompt_for_description)
		{
			printf("    Description of %s? ",img->name);
			fflush(stdout);
			fflush(stdin);
			fgets(description, MAXTEXTLEN-1, stdin);
			rmspace(description);
			if(!description[0])
			{
				sprintf(description,"Description of %s goes here.",
					img->name);
			}
		}
		else
			sprintf(description,"Description of %s goes here.",
				img->name);

		imgrec_setdescription(img,description);
	}

	/* TODO */
	imgrec_setdate(img,"");
}

void QPDir_GetGalleryName()
{
	FILE	*f;
	char	foldername[MAXFILENAMELEN], path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",QP.rootdir,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,"n") && s[0])
			{
				strcpy(QPDir.title,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		printf("Gallery name? [my gallery]: ");
		fflush(stdout);
		fflush(stdin);
		fgets(foldername,MAXFILENAMELEN-1,stdin);
		rmspace(foldername);
		if(!foldername[0])
			strcpy(foldername,"my gallery");
		strcpy(QPDir.title,foldername);

	}
}

void QPDir_GetGalleryDescription()
{
	FILE	*f;
	char	description[MAXTEXTLEN], path[MAXFILENAMELEN];
	char	s[MAXTEXTLEN], ident[MAXTEXTLEN];
	int	foundit = 0;

	/* Make foldername file path */
	sprintf(path,"%s/%s",QP.rootdir,QP.folder_configfile);
	f = fopen(path,"r");
	if(f)
	{
		/* File exists.  Read it until we find our entry */
		while(readline(f,s))
		{
			/* Skip comments */
			if(s[0] == '#')
				continue;
	
			split(ident,s);
			rmspace(ident);
			rmspace(s);
			if(isequalcase(ident,"d") && s[0])
			{
				strcpy(QPDir.heading,s);
				foundit = 1;
				break;
			}
		}
		fclose(f);
	}

	if(!foundit)
	{
		if(QP.prompt_for_description)
		{
			printf("Gallery description? [My pictures]: ");
			fflush(stdout);
			fflush(stdin);
			fgets(description, MAXTEXTLEN-1, stdin);
			rmspace(description);
			if(!description[0])
			{
				strcpy(description,"My pictures");
			}
		}
		else
			strcpy(description,"My pictures");

		strcpy(QPDir.heading,description);
	}
}

void QPDir_WriteGalleryConfig()
{
	FILE	*f;
	char	path[MAXFILENAMELEN], date[MAXTEXTLEN];

	sprintf(path,"%s",QP.folder_configfile);
	f = fopen(path,"w");
	if(f == NULL)
	{
		printf("Unable to write gallery information file: %s\n",path);
		return;
	}
	timet_to_date_short(time(NULL),date);
	fprintf(f,"##############################################################################\n");
	fprintf(f,"## QuickPics %s - Information file\n",QP.build);
	fprintf(f,"## Current directory: <main>\n");
	fprintf(f,"## Creation time: %s\n",date);
	fprintf(f,"##############################################################################\n");
	fprintf(f,"\n");
	fprintf(f,"# Gallery name\n");
	fprintf(f,"n %s\n",QPDir.title);
	fprintf(f,"\n");
	fprintf(f,"# Gallery description\n");
	fprintf(f,"d %s\n",QPDir.heading);

	fclose(f);
}
		
void QPDir_WriteFolderConfig(dirrec *dir)
{
	FILE	*f;
	imgrec	*img;
	char	path[MAXFILENAMELEN], date[MAXTEXTLEN];

	sprintf(path,"%s/%s",dir->path,QP.folder_configfile);
	f = fopen(path,"w");
	if(f == NULL)
	{
		printf("Unable to write folder information file: %s\n",path);
		return;
	}

	timet_to_date_short(time(NULL),date);
	fprintf(f,"##############################################################################\n");
	fprintf(f,"## QuickPics %s - Information file\n",QP.build);
	fprintf(f,"## Current directory: %s\n",dir->name);
	fprintf(f,"## Creation time: %s\n",date);
	fprintf(f,"##############################################################################\n");
	fprintf(f,"\n");
	fprintf(f,"# Folder name\n");
	fprintf(f,"n %s\n",dir->alias);
	fprintf(f,"\n");
	fprintf(f,"# Folder description\n");
	fprintf(f,"d %s\n",dir->description);
	fprintf(f,"\n");
	fprintf(f,"# Image chosen for main page\n");
	fprintf(f,"m %s\n",dir->mainimage ? dir->mainimage : "");
	fprintf(f,"\n");
	fprintf(f,"# Image descriptions\n");
	for(img=dir->images; img; img=img->next)
		fprintf(f,"%s %s\n",img->name,img->description);

	fclose(f);
}
		
	
void QPDir_MakeAllThumbnails(int make_thumbnails)
{
	dirrec	*dir;

	for(dir=QPDir.dirs; dir; dir=dir->next)
		QPDir_MakeThumbnails(dir,QP.thumbnailsize,make_thumbnails);

	printf("\n");
}

void QPDir_MakeThumbnails(dirrec *dir, int target_size, int make_thumbnails)
{
	imgrec	*img;
	dirrec	*subdir;
	char	in_path[MAXFILENAMELEN], out_path[MAXFILENAMELEN];
	char	thumb_name[MAXFILENAMELEN], buf[MAXFILENAMELEN];
	float	ratio;
	int	target_input, scale, count = 0, dots_per_largedot = 1;
	int	using_large_dot = 0, allowable_dots;

	/* Go recursive on subdirectories */
	for(subdir=dir->subdirs; subdir; subdir=subdir->next)
		QPDir_MakeThumbnails(subdir,target_size, make_thumbnails);

	sprintf(buf,"  %s/%s: (%d)",BaseFilename(QP.rootdir),
		dir->path, dir->num_images);
	printf(buf);
	fflush(stdout);

	allowable_dots = 80 - (strlen(buf) + 2);
	if(dir->num_images > allowable_dots)
	{
		using_large_dot = 1;
		dots_per_largedot = (dir->num_images / allowable_dots) + 1;
		count = 0;
	}

	/* Create thumbnails for all images */
	for(img=dir->images; img; img=img->next)
	{
		/* Set thumbnail name */
		sprintf(thumb_name,"%s%s.%s",BaseFilename(img->name),
			QP.thumbnail_identifier, FilenameExtension(img->name));
		imgrec_setthumbnailname(img,thumb_name);

		/* set in and out paths */
		sprintf(in_path,"%s/%s",dir->path,img->name);
		sprintf(out_path,"%s/%s",dir->path,img->thumbnail_name);

		if(make_thumbnails)
		{
			/* Set scale */
			target_input = img->width * img->height;
			ratio = sqrt(target_input / (target_size*target_size));
	
			/* ratio can only be 1, 2, 4, 8 */
			if(ratio >= 8.0)
				scale = 8;
			else if(ratio >= 4.0)
				scale = nearest(ratio,4,8);
			else if(ratio >= 2.0)
				scale = nearest(ratio,2,4);
			else if(ratio >= 1.0)
				scale = nearest(ratio,1,2);
			else
				scale = 1;
			
			/* Ready to resize to thumbnail */
			Image_Scale(in_path,out_path,scale,QP.quality,
				&img->thumbnail_width, &img->thumbnail_height);
		}
		else
			Image_GetDimensions(out_path,
				&img->thumbnail_width, &img->thumbnail_height);

		/* Make sure images are world readable */
		chmod(in_path,0644);
		chmod(out_path,0644);

/*
		printf("  %s (%dx%d) --> %s (%dx%d)\n",img->name,
			img->width, img->height, img->thumbnail_name,
			img->thumbnail_width, img->thumbnail_height);
*/
		if(using_large_dot)
		{
			count++;
			if(count >= dots_per_largedot)
			{
				count = 0;
				printf("o");
			}
		}
		else
			printf(".");
		fflush(stdout);
	}

	printf("\n");
	/* Make this directory world-executable */
	chmod(dir->path,0755);
}
			
	

/* ASDF */
/***************************************************************************
 *
 * dir record definitions.  No changes should be made to new(),
 * append(), delete(), or movetofront().
 *
 ****************************************************************************/

dirrec *dirrec_new()
{
	dirrec *x;

	/* allocate memory */
	x = (dirrec *)nmalloc(sizeof(dirrec));

	/* initialize */
	x->next = NULL;

	dirrec_init(x);

	return x;
}

void dirrec_append(dirrec **list, dirrec **last, dirrec *entry)
{
	dirrec *lastentry = *last;

	if(*list == NULL)
		*list = entry;
	else
		lastentry->next = entry;

	*last = entry;
	entry->next = NULL;
}

void dirrec_delete(dirrec **list, dirrec **last, dirrec *x)
{
	dirrec *c, *lastchecked = NULL;

	c = *list;
	while(c != NULL)
	{
		if(c == x)
		{
			if(lastchecked == NULL)
			{
				*list = c->next;
				if(c == *last)
					*last = NULL;
			}
			else
			{
				lastchecked->next = c->next;
				if(c == *last)
					*last = lastchecked;
			}

			dirrec_free(c);
			return;
		}

		lastchecked = c;
		c = c->next;
	}
}

void dirrec_movetofront(dirrec **list, dirrec **last, dirrec *lastchecked, dirrec *x)
{
	if(lastchecked != NULL)
	{
		if(*last == x)
			*last = lastchecked;

		lastchecked->next = x->next;
		x->next = *list;
		*list = x;
	}
}

/****************************************************************************/
/* record dirrec low-level data-specific function declarations. */


void dirrec_init(dirrec *dir)
{
	/* initialize */
	dir->name = NULL;
	dir->alias = NULL;
	dir->path = NULL;
	dir->path_home = NULL;
	dir->description = NULL;
	dir->mainimage = NULL;

	dir->oldest_parent = NULL;
	dir->subdirs = NULL;
	dir->subdirs_last = NULL;
	dir->num_subdirs = 0;

	dir->images = NULL;
	dir->images_last = NULL;
	dir->num_images = 0;

	dir->flags = 0L;
	dir->order = 0;
}

void dirrec_free(dirrec *dir)
{
	mfree(dir->name);
	mfree(dir->alias);
	mfree(dir->path);
	mfree(dir->path_home);
	mfree(dir->description);
	mfree(dir->mainimage);

	/* QPDir_freeallimages(dir); */

	mfree(dir);
}

void dirrec_setname(dirrec *dir, const char *name)
{
	mstrcpy(&dir->name,name);
}

void dirrec_setalias(dirrec *dir, const char *alias)
{
	mstrcpy(&dir->alias,alias);
}

void dirrec_setpath(dirrec *dir, const char *path)
{
	mstrcpy(&dir->path,path);
}

void dirrec_setdescription(dirrec *dir, const char *description)
{
	mstrcpy(&dir->description,description);
}

void dirrec_setmainimage(dirrec *dir, const char *mainimage)
{
	mstrcpy(&dir->mainimage,mainimage);
}

void dirrec_setpath_home(dirrec *dir, const char *path_home)
{
	mstrcpy(&dir->path_home,path_home);
}

dirrec *dirrec_dir(dirrec **list, dirrec **last, char *name)
{
	dirrec *x, *lastchecked = NULL;

	for(x=*list; x!=NULL; x=x->next)
	{
		if(isequal(x->name,name))
		{
			/* No movetofront's for this list */
			/* dirrec_movetofront(list,last,lastchecked,x); */

			return x;
		}
		lastchecked = x;
	}

	return NULL;
}



/***************************************************************************n
 *
 * image record definitions.  No changes should be made to new(),
 * append(), delete(), or movetofront().
 *
 ****************************************************************************/

imgrec *imgrec_new()
{
	imgrec *x;

	/* allocate memory */
	x = (imgrec *)nmalloc(sizeof(imgrec));

	/* initialize */
	x->next = NULL;

	imgrec_init(x);

	return x;
}

void imgrec_append(imgrec **list, imgrec **last, imgrec *entry)
{
	imgrec *lastentry = *last;

	if(*list == NULL)
		*list = entry;
	else
		lastentry->next = entry;

	*last = entry;
	entry->next = NULL;
}

void imgrec_delete(imgrec **list, imgrec **last, imgrec *x)
{
	imgrec *m, *lastchecked = NULL;

	m = *list;
	while(m != NULL)
	{
		if(m == x)
		{
			if(lastchecked == NULL)
			{
				*list = m->next;
				if(m == *last)
					*last = NULL;
			}
			else
			{
				lastchecked->next = m->next;
				if(m == *last)
					*last = lastchecked;
			}

			imgrec_free(m);
			return;
		}

		lastchecked = m;
		m = m->next;
	}
}

void imgrec_movetofront(imgrec **list, imgrec **last, imgrec *lastchecked, imgrec *x)
{
	if(lastchecked != NULL)
	{
		if(*last == x)
			*last = lastchecked;

		lastchecked->next = x->next;
		x->next = *list;
		*list = x;
	}
}

/****************************************************************************/

void imgrec_init(imgrec *img)
{
	/* initialize */
	img->type = 0;
	img->name = NULL;
	img->description = NULL;
	img->date = NULL;
	img->width = 0;
	img->height = 0;
	img->thumbnail_name = NULL;
	img->thumbnail_width = 0;
	img->thumbnail_height = 0;
	img->bytes = 0L;
	img->order = 0;
}

void imgrec_free(imgrec *img)
{
	mfree(img->name);
	mfree(img->description);
	mfree(img->date);
	mfree(img->thumbnail_name);

	mfree(img);
}

void imgrec_setname(imgrec *img, const char *name)
{
	mstrcpy(&img->name,name);
}

void imgrec_setthumbnailname(imgrec *img, const char *name)
{
	mstrcpy(&img->thumbnail_name,name);
}

void imgrec_setdescription(imgrec *img, const char *description)
{
	mstrcpy(&img->description, description);
}

void imgrec_setdate(imgrec *img, const char *date)
{
	mstrcpy(&img->date,date);
}

imgrec *imgrec_image(imgrec *list, char *name)
{
	imgrec *x;

	for(x=list; x!=NULL; x=x->next)
	{
		if(isequal(x->name,name))
			return x;
	}

	return NULL;
}
