/* $Id: guppi-paths.c,v 1.29 2002/01/19 02:45:26 trow Exp $ */

/*
 * guppi-paths.c
 *
 * Copyright (C) 1999, 2000 EMC Capital Management, Inc.
 *
 * Developed by Jon Trowbridge <trow@gnu.org>
 * and Havoc Pennington <hp@pobox.com>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <config.h>
#include "guppi-paths.h"

/* #include <gnome.h> */
#include <stdlib.h>

#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-util.h>

#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include "guppi-convenient.h"
#include "guppi-debug.h"
#include "guppi-dialogs.h"
#include "guppi-memory.h"

/*
 * We want to be able to run guppi w/o having done "make install",
 * usually for testing during development.  So if we seem to be
 * in the src/guppi directory (i.e. if guppi.c and guppi-app.c
 * are present in the current directory), return TRUE.
 */
static gboolean forced_dph = FALSE;

void
force_development_path_hacks (void)
{
  forced_dph = TRUE;
}

gboolean
development_path_hacks (void)
{
  return forced_dph || (g_file_exists ("./guppi.c") && g_file_exists ("./guppi-app.c"));
}

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

static GList *pixmap_path_list = NULL;

void
guppi_pixmap_path_add (const gchar * filename)
{
  pixmap_path_list = g_list_append (pixmap_path_list, guppi_strdup (filename));
}

gchar *
guppi_find_pixmap (const gchar * filename)
{
  gchar *env;
  gchar *path = NULL;
  GList *iter;

#ifdef GUPPI_PIXMAPS
  path = g_concat_dir_and_file (GUPPI_PIXMAPS, filename);
  guppi_outside_alloc (path);
  if (!g_file_exists (path)) {
    guppi_free (path);
    path = NULL;
  } else {
    return path;
  }
#endif

  env = getenv ("GUPPI_PIXMAP_PATH");
  if (env) {
    path = g_concat_dir_and_file (env, filename);
    guppi_outside_alloc (path);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

  /* This will work iff you are running an uninstalled guppi out of
     the src/guppi directory. */
  if (development_path_hacks ()) {
    path = guppi_strdup_printf ("../../pixmaps/%s", filename);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

  for (iter = pixmap_path_list; iter != NULL; iter = g_list_next (iter)) {
    path = g_concat_dir_and_file ((gchar *) iter->data, filename);
    guppi_outside_alloc (path);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

  return NULL;
}

const gchar *
guppi_logo_graphic_path (void)
{
  static gchar *path = NULL;

  if (path == NULL) {
    path = guppi_find_pixmap ("guppi-splash.png");
    guppi_permanent_alloc (path);
    if (path == NULL)
      g_warning ("Couldn't find guppi-splash.png");
  }

  return path;
}

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

static GList *script_path_list = NULL;

void
guppi_script_path_add (const gchar * filename)
{
  script_path_list = g_list_append (script_path_list, guppi_strdup (filename));
}


gchar *
guppi_find_script (const gchar * filename)
{
  gchar *env;
  gchar *path = NULL;
  GList *iter;

  if (g_file_exists (filename))
    return guppi_strdup (filename);

  if (development_path_hacks ()) {
    path = g_concat_dir_and_file ("../libguppiuseful", filename);
    guppi_outside_alloc (path);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

#ifdef GUPPI_SCRIPTS
  path = g_concat_dir_and_file (GUPPI_SCRIPTS, filename);
  guppi_outside_alloc (path);
  if (!g_file_exists (path)) {
    guppi_free (path);
    path = NULL;
  } else {
    return path;
  }
#endif

  env = getenv ("GUPPI_SCRIPT_PATH");
  if (env) {
    path = g_concat_dir_and_file (env, filename);
    guppi_outside_alloc (path);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

  for (iter = script_path_list; iter != NULL; iter = g_list_next (iter)) {
    path = g_concat_dir_and_file ((gchar *) iter->data, filename);
    guppi_outside_alloc (path);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    } else {
      return path;
    }
  }

  return NULL;
}

gchar *
guppi_find_guile_script (const gchar * filename)
{
  return guppi_find_script (filename);
}

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

/* This code can leak a little memory, but the amount of leakage
   is strictly bounded... */

static GList *glade_path_list = NULL;
static gboolean glade_path_initialized = FALSE;
static GHashTable *glade_path_hash = NULL;

static void
guppi_glade_path_register (const gchar * file, const gchar * path)
{
  gpointer data;

  if (glade_path_hash == NULL) {
    glade_path_hash = g_hash_table_new (g_str_hash, g_str_equal);
  }

  data = g_hash_table_lookup (glade_path_hash, file);
  /* Silently ignore collisions... */
  if (data != NULL) {
    guppi_free ((gpointer) path);
    return;
  }

  g_hash_table_insert (glade_path_hash, (gchar *) file, (gpointer) path);
}

static const gchar *
guppi_glade_path_lookup (const gchar * file)
{
  if (glade_path_hash == NULL)
    return NULL;

  return (const gchar *) g_hash_table_lookup (glade_path_hash, file);
}

static void
guppi_glade_path_scan_dir (const gchar * path_orig, gboolean recursive)
{
  DIR *dir;
  struct dirent *dirent;
  struct stat buf;
  gchar path[1024];
  gchar *str;
  gint i = 0, j = 0;

  /*
     If we are handed something like
     /home/foo/plug-ins:/bar/plug-ins:/usr/local/plug-ins
     we should do the right thing and load from all three.
   */
  while (path_orig[i]) {
    if (path_orig[i] == ':') {
      path[j] = '\0';
      guppi_glade_path_scan_dir (path, recursive);
      j = 0;
    } else {
      path[j] = path_orig[i];
      ++j;
    }
    ++i;
  }
  path[j] = '\0';

  dir = opendir (path);
  if (dir == NULL)
    return;

  errno = 0;

  while ((dirent = readdir (dir)) != NULL) {

    if (recursive &&
	strcmp (dirent->d_name, ".") && strcmp (dirent->d_name, "..")) {
      str = guppi_strdup_printf ("%s/%s", path, dirent->d_name);
      if (stat (str, &buf) < 0) {
	if (guppi_is_very_verbose ())
	  g_message ("stat() on %s failed", str);
      } else if (S_ISDIR (buf.st_mode) && recursive)
	guppi_glade_path_scan_dir (str, recursive);
      guppi_free (str);
    }

    if (!strcmp (g_extension_pointer (dirent->d_name), "glade")) {
      str = guppi_strdup_printf ("%s/%s", path, dirent->d_name);
      guppi_glade_path_register (g_filename_pointer (str), str);
    }

    errno = 0;
  }
  if (errno) {
    g_message ("An error occured while reading %s", path);
  }

  closedir (dir);
}

void
guppi_glade_path_add (const gchar * filename)
{
  glade_path_list = g_list_append (glade_path_list, guppi_strdup (filename));
  if (glade_path_initialized)
    guppi_glade_path_scan_dir (filename, FALSE);
}



const gchar *
guppi_glade_path (const gchar * filename)
{
  const gchar *path;
  gchar *env;

  if (!glade_path_initialized) {
    GList *iter;

    if (development_path_hacks ()) {
      guppi_glade_path_scan_dir ("../../plug-ins", TRUE);
      guppi_glade_path_scan_dir ("..", TRUE);
    } else {
#ifdef GUPPI_GLADE_DIR
      guppi_glade_path_scan_dir (GUPPI_GLADE_DIR, TRUE);
#endif
    }

    env = getenv ("GUPPI_GLADE_PATH");
    if (env)
      guppi_glade_path_scan_dir (env, TRUE);

    for (iter = glade_path_list; iter != NULL; iter = g_list_next (iter))
      guppi_glade_path_scan_dir ((gchar *) iter->data, FALSE);

    glade_path_initialized = TRUE;
  }

  path = guppi_glade_path_lookup (filename);

  if (path == NULL)
    g_warning ("Couldn't file \"%s\"", filename);

  return path;
}

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

const gchar *
gnome_guile_repl_path (void)
{
  static gchar *path = NULL;
  gboolean was_null = (path == NULL);

  if (path == NULL) {
    path = gnome_is_program_in_path ("gnome-guile-repl");
  }

  /* Maybe we built guppi with some funny prefix and $(prefix)/bin isn't
     in our path. */
  if (path == NULL) {
    path = guppi_strdup_printf ("%s/gnome-guile-repl", GUPPI_PREFIX);
    if (!g_file_exists (path)) {
      guppi_free (path);
      path = NULL;
    }
  }

  /* Try the hard-wired path, in case we haven't installed yet and
     are running out of src/guppi. */
  if (path == NULL && development_path_hacks ()) {
    path = "../guile-server/gnome-guile-repl";
    if (!g_file_exists (path))
      path = NULL;
  }

  if (path == NULL)
    guppi_error_dialog ( _("The program \"gnome-guile-repl\" is not in your $PATH.\nWithout it, you cannot access the guile terminal."));

  if (was_null && path)
    guppi_permanent_alloc (path);

  return path;
}

void
guppi_paths_init (void)
{

}

/* $Id: guppi-paths.c,v 1.29 2002/01/19 02:45:26 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1