/* gnomeui-support.c -- helper functions for GNOME binding
   $Id: gnomeui-support.c,v 1.5 2000/07/23 22:52:49 john Exp $ */

#include <config.h>
#include <assert.h>
#include <gnome.h>
#include "rep-gtk.h"
#include "rep-gnome.h"
#include <string.h>
#include <signal.h>

DEFSYM(_gnome_app_id_, "*gnome-app-id*");
DEFSYM(_gnome_app_version_, "*gnome-app-version*");
DEFSYM(rep_version, "rep-version");

static int sgtk_gnomeui_inited;

/* grr.. */
guint
gnome_app_bar_get_type (void)
{
    return gnome_appbar_get_type ();
}


/* extra types */

void
sgtk_gnome_string_callback (gchar *string, gpointer data)
{
    rep_call_lisp1 (sgtk_get_protect (data),
		    string != 0 ? rep_string_dup (string) : Qnil);
}

void
sgtk_gnome_reply_callback (gint reply, gpointer data)
{
    rep_call_lisp1 (sgtk_get_protect (data), rep_MAKE_INT (reply));
}


/* helpers */

static int
list_length (repv list)
{
    repv len = Flength (list);
    return (len && rep_INTP (len)) ? rep_INT (len) : 0;
}

static char*
xstrdup (char *str)
{
  if (str)
    {
      char *newstr = rep_alloc (strlen(str)+1);
      strcpy (newstr, str);
      return newstr;
    }
  else
    return NULL;
}

static void
make_argv (repv list, int *argc, char ***argv)
{
  static char *argv_storage[1] = { "rep-gtk" };

  int c = list_length (list), i;
  char **v;

  *argv = argv_storage;
  *argc = 1;

  if (c < 0)
    return;

  v = (char **)rep_alloc ((c+1) * sizeof(char**));
  for (i = 0; i < c; i++, list = rep_CDR (list))
    {
      if (!rep_STRINGP (rep_CAR (list)))
	{
	  rep_free ((char *)v);
	  return;
	}
      v[i] = xstrdup (rep_STR (rep_CAR (list)));
    }
  v[c] = NULL;
  
  *argv = v;
  *argc = c;
}


/* client code, from guile-gnome/client.c */

/* Generated by gen-typeinfo func from "gnome.defs". */

typedef void set_prop_func (GnomeClient *client, gint argc, gchar *argv[]);
typedef GnomeClient *new_func (gint argc, gchar *argv[]);

/* Helper function.  */
static void
set_prop_from_arglist (GnomeClient *client, 
		       repv list, 
		       gchar *name, 
		       set_prop_func *func)
{
  char **argv;
  int argc, i;
  repv l, s;
  
  argc = 0;
  l = list;
  while (rep_CONSP (l))
    {
      if (!rep_CONSP (l)) return;
      s = rep_CAR (l);
      if (!rep_STRINGP (s)) return;
      ++argc;
      l = rep_CDR (l);
    }
  if (l != Qnil) return;
  
  argv = (gchar **) malloc (argc * sizeof (gchar *));
  for (i = 0, l = list; rep_CONSP (l); l = rep_CDR (l), ++i)
    argv[i] = rep_STR (rep_CAR (l));
  (*func) (client, argc, argv);
  free (argv);
}

DEFUN ("gnome-client-set-clone-command", Fgnome_client_set_clone_command,
       Sgnome_client_set_clone_command, (repv p_client, repv p_list), rep_Subr2)
{
  GnomeClient* c_client;
  rep_DECLARE (1, p_client, sgtk_is_a_gtkobj (gnome_client_get_type (), p_client));

  c_client = (GnomeClient*)sgtk_get_gtkobj (p_client);
  set_prop_from_arglist (c_client, p_list, 0, gnome_client_set_clone_command);

  return Qnil;
}

DEFUN ("gnome-client-set-environment", Fgnome_client_set_environment,
       Sgnome_client_set_environment, (repv p_client, repv p_list), rep_Subr2)
{
  GnomeClient* c_client;
  rep_DECLARE (1, p_client, sgtk_is_a_gtkobj (gnome_client_get_type (), p_client));

  c_client = (GnomeClient*)sgtk_get_gtkobj (p_client);
  set_prop_from_arglist (c_client, p_list, 0, gnome_client_set_environment);

  return Qnil;
}

DEFUN ("gnome-client-set-restart-command", Fgnome_client_set_restart_command,
       Sgnome_client_set_restart_command, (repv p_client, repv p_list), rep_Subr2)
{
  GnomeClient* c_client;
  rep_DECLARE (1, p_client, sgtk_is_a_gtkobj (gnome_client_get_type (), p_client));

  c_client = (GnomeClient*)sgtk_get_gtkobj (p_client);
  set_prop_from_arglist (c_client, p_list, 0, gnome_client_set_restart_command);

  return Qnil;
}

DEFUN ("gnome-client-set-resign-command", Fgnome_client_set_resign_command,
       Sgnome_client_set_resign_command, (repv p_client, repv p_list), rep_Subr2)
{
  GnomeClient* c_client;
  rep_DECLARE (1, p_client, sgtk_is_a_gtkobj (gnome_client_get_type (), p_client));

  c_client = (GnomeClient*)sgtk_get_gtkobj (p_client);
  set_prop_from_arglist (c_client, p_list, 0, gnome_client_set_resign_command);

  return Qnil;
}

DEFUN ("gnome-client-set-shutdown-command", Fgnome_client_set_shutdown_command,
       Sgnome_client_set_shutdown_command, (repv p_client, repv p_list), rep_Subr2)
{
  GnomeClient* c_client;
  rep_DECLARE (1, p_client, sgtk_is_a_gtkobj (gnome_client_get_type (), p_client));

  c_client = (GnomeClient*)sgtk_get_gtkobj (p_client);
  set_prop_from_arglist (c_client, p_list, 0, gnome_client_set_shutdown_command);

  return Qnil;
}



int
sgtk_gnome_init (const char *app_id, const char *app_version)
{
  int argc;
  char **argv, *tem;
  repv head, *last;
  void (*fatal_signal_handler)();

  if (sgtk_gnomeui_inited)
    return 0;

  tem = getenv ("REP_GTK_DONT_INITIALIZE");
  if (tem != 0 && atoi (tem) != 0)
      return 0;

#if 0
  make_argv (Fcons (Fsymbol_value (Qprogram_name, Qt),
		    Fsymbol_value (Qcommand_line_args, Qt)), &argc, &argv);
#else
  /* fucking gnome gives error if it sees option it doesn't understand.. */
  make_argv (Fcons (Fsymbol_value (Qprogram_name, Qt), Qnil), &argc, &argv);
#endif

  /* preserve rep's error handlers */
  fatal_signal_handler = signal (SIGSEGV, SIG_DFL);

  gnome_init (app_id, app_version, argc, argv);

  if (fatal_signal_handler != SIG_ERR && fatal_signal_handler != SIG_IGN)
  {
#ifdef SIGFPE
      signal (SIGFPE, fatal_signal_handler);
#endif
#ifdef SIGILL
      signal (SIGILL, fatal_signal_handler);
#endif
#ifdef SIGSEGV
      signal (SIGSEGV, fatal_signal_handler);
#endif
#ifdef SIGBUS
      signal (SIGBUS, fatal_signal_handler);
#endif
#ifdef SIGQUIT
      signal (SIGQUIT, fatal_signal_handler);
#endif
#ifdef SIGABRT
      signal (SIGABRT, fatal_signal_handler);
#endif
  }

#if 0
  argc--; argv++;
  head = Qnil;
  last = &head;
  while(argc > 0)
  {
      *last = Fcons(rep_string_dup(*argv), Qnil);
      last = &rep_CDR(*last);
      argc--;
      argv++;
  }
  Fset (Qcommand_line_args, head);
#endif

  sgtk_gnomeui_inited = TRUE;
  return 1;
}


/* dl hooks / init */

repv
rep_dl_init (void)
{
    repv s = rep_push_structure ("gui.gnome.ui");
    repv id, version;

    /* ::alias:gnomeui gui.gnome.ui::
       ::alias:gui.gnome gui.gnome.ui:: */
    rep_alias_structure ("gui.gnome");
    rep_alias_structure ("gnomeui");

    sgtk_gnome_init_gnomeui_glue ();
    rep_ADD_SUBR (Sgnome_client_set_clone_command);
    rep_ADD_SUBR (Sgnome_client_set_environment);
    rep_ADD_SUBR (Sgnome_client_set_resign_command);
    rep_ADD_SUBR (Sgnome_client_set_restart_command);
    rep_ADD_SUBR (Sgnome_client_set_shutdown_command);

    rep_INTERN_SPECIAL(_gnome_app_id_);
    rep_INTERN_SPECIAL(_gnome_app_version_);
    id = Fsymbol_value (Q_gnome_app_id_, Qt);
    version = Fsymbol_value (Q_gnome_app_version_, Qt);

    if (rep_STRINGP (id) && rep_STRINGP (version))
	sgtk_gnome_init (rep_STR (id), rep_STR (version));
    else
    {
	rep_INTERN(rep_version);
	version = Fsymbol_value (Qrep_version, Qt);
	sgtk_gnome_init ("rep", rep_STRINGP (version)
			 ? (char *) rep_STR (version) : "0");
    }
    return rep_pop_structure (s);
}
