#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <dirent.h>

#include <gtk/gtk.h>

#include "support.h"
#include "datafiles.h"

GList * gimp_path_parse                 (gchar     *path,
					 gint       max_paths,
					 gboolean   check,
					 GList    **check_failed);

static gboolean    filestat_valid = FALSE;
static struct stat filestat;

/**
 * gimp_path_free:
 * @path: A list of directories as returned by gimp_path_parse().
 *
 * This function frees the memory allocated for the list and it's strings.
 **/
void
gimp_path_free (GList *path)
{
  GList *list;

  if (path)
    {
      for (list = path; list; list = g_list_next (list))
	{
	  g_free (list->data);
	}

      g_list_free (path);
    }
}

void
datafiles_read_directories (gchar                  *path_str,
			    GimpDataFileLoaderFunc  loader_func,
			    GimpDataFileFlags       flags)
{
  gchar *local_path;
  GList *path;
  GList *list;
  gchar *filename;
  gint   err;
  DIR   *dir;
  struct dirent *dir_ent;

  if (path_str == NULL)
    return;

  local_path = g_strdup (path_str);

#ifdef __EMX__
  /*
   *  Change drive so opendir works.
   */
  if (local_path[1] == ':')
    {
      _chdrive (local_path[0]);
    }
#endif  

  path = gimp_path_parse (local_path, 16, TRUE, NULL);

  for (list = path; list; list = g_list_next (list))
    {
      /* Open directory */
      dir = opendir ((gchar *) list->data);

      if (!dir)
	{
	  g_message ("error reading datafiles directory \"%s\"",
		     (gchar *) list->data);
	}
      else
	{
	  while ((dir_ent = readdir (dir)))
	    {
	      filename = g_strdup_printf ("%s%s",
					  (gchar *) list->data,
					  dir_ent->d_name);

	      /* Check the file and see that it is not a sub-directory */
	      err = stat (filename, &filestat);

	      if (!err && S_ISREG (filestat.st_mode) &&
		  (!(flags & MODE_EXECUTABLE) ||
		   (filestat.st_mode & S_IXUSR)))
		{
		  filestat_valid = TRUE;
		  (*loader_func) (filename);
		  filestat_valid = FALSE;
		}

	      g_free (filename);
	    }

	  closedir (dir);
	}
    }

  gimp_path_free (path);
  g_free (local_path);
}


/**
 * gimp_path_parse:
 * @path: A list of directories separated by #G_SEARCHPATH_SEPARATOR.
 * @max_paths: The maximum number of directories to return.
 * @check: #TRUE if you want the directories to be checked.
 * @check_failed: Returns a #GList of path elements for which the
 *                check failed. Each list element is guaranteed
 *		  to end with a #G_PATH_SEPARATOR.
 *
 * Returns: A #GList of all directories in @path. Each list element
 *	    is guaranteed to end with a #G_PATH_SEPARATOR.
 **/
GList *
gimp_path_parse (gchar     *path,
		 gint       max_paths,
		 gboolean   check,
		 GList    **check_failed)
{
  gchar  *home;
  gchar **patharray;
  GList  *list = NULL;
  GList  *fail_list = NULL;
  gint    i;

  struct stat filestat;
  gint        err = FALSE;

  if (!path || !*path || max_paths < 1 || max_paths > 256)
    return NULL;

  home = g_get_home_dir ();

  patharray = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, max_paths);

  for (i = 0; i < max_paths; i++)
    {
      GString *dir;

      if (!patharray[i])
	break;

#ifndef G_OS_WIN32
      if (*patharray[i] == '~')
	{
	  dir = g_string_new (home);
	  g_string_append (dir, patharray[i] + 1);
	}
      else
#endif
	{
	  dir = g_string_new (patharray[i]);
	}

#ifdef __EMX__
      _fnslashify (dir);
#endif

      if (check)
	{
	  /*  check if directory exists  */
	  err = stat (dir->str, &filestat);

	  if (!err && S_ISDIR (filestat.st_mode))
	    {
	      if (dir->str[dir->len - 1] != G_DIR_SEPARATOR)
		g_string_append_c (dir, G_DIR_SEPARATOR);
	    }
	}

      if (!err)
	list = g_list_prepend (list, g_strdup (dir->str));
      else if (check_failed)
	fail_list = g_list_prepend (fail_list, g_strdup (dir->str));

      g_string_free (dir, TRUE);
    }

  g_strfreev (patharray);

  list = g_list_reverse (list);

  if (check && check_failed)
    {
      fail_list = g_list_reverse (fail_list);
      *check_failed = fail_list;
    }

  return list;
}



syntax highlighted by Code2HTML, v. 0.9.1