/*
 *  wmconfig.c:		Input of WindowMaker config file	
 *
 *  Written by:		Ullrich Hafner
 *		
 *  Copyright (C) 1998 Ullrich Hafner <hafner@bigfoot.de>
 *
 *  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, USA.
 */

/*
 *  $Date: 2000/09/03 19:22:07 $
 *  $Author: hafner $
 *  $Revision: 1.65 $
 *  $State: Exp $
 */

#include "config.h"

#if HAVE_STDLIB_H
#	include <stdlib.h>
#endif /* not HAVE_STDLIB_H */
#if HAVE_STRING_H
#	include <string.h>
#else /* not HAVE_STRING_H */
#	include <strings.h>
#endif /* not HAVE_STRING_H */
#ifdef HAVE_LOCALE_H
#	include <locale.h>
#endif

#include "proplist_t.h"

#include <gtk/gtk.h>
#include <stdio.h>

#include "load.h"
#include "misc.h"
#include "window.h"

#include "error.h"

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

			       global variables
  
*******************************************************************************/

proplist_t plist_changed 	= NULL;	/* modified proplist keys */
proplist_t pl_yes        	= NULL;	/* dummy */
proplist_t orig_wmaker   	= NULL;	/* original WindowMaker file */
char       *orig_wmaker_fname 	= NULL;	/* original WindowMaker filename */
proplist_t orig_rootmenu 	= NULL;	/* original WMRootMenu file */
char       *orig_rootmenu_fname = NULL;	/* original WMRootMenu filename */
 
GtkWidget  *log_text      = NULL;

static GtkWidget *
make_log_window (void);
static void
usage(int status);

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

			       public code
  
*******************************************************************************/


int
main (int argc, char **argv)
{
   proplist_t global_windowmaker;	/* global defined options */
   proplist_t windowmaker;		/* user defined options in WindowMaker */
   proplist_t wmconfig;			/* WindowMaker attributes */
   proplist_t wmpanel;			/* Panel */
   proplist_t wmakerconf;
   GtkWidget  *window;
   const char *conffile 		 = PKGDATADIR "/WMWmakerconf";   
   bool_t      no_inet 			 = NO;
   /* -1 => unspec, 0 => disallow, 1=>allow*/
   int	       sections_restriction_type = -1;
   node	      *sections 		 = NULL;	
   
   WMPLSetCaseSensitive(FALSE);
   
   
   gtk_set_locale ();
   gtk_init (&argc, &argv);

   /*
    *  I18n
    */
#ifdef HAVE_SETLOCALE
   setlocale (LC_ALL, "");
#endif
   bindtextdomain (PACKAGE, LOCALEDIR);
   bindtextdomain ("wmakerconf-data", LOCALEDIR);
   /* GTK+ 2 insists upon receiving Unicode: */
   bind_textdomain_codeset (PACKAGE, "UTF-8");
   bind_textdomain_codeset ("wmakerconf-data", "UTF-8");
   textdomain (PACKAGE);

   /*
    *  Parse command line
    */
   {
      int argidx;
      
      for (argidx = 1; argidx < argc; argidx++)
      {
	 char   *arg 	   = argv [argidx];
	 char   *nextarg   = argv [argidx + 1];
	 bool_t  more_args = argc - argidx - 1;
	    
	 if (streq (arg, "--version"))
	 {
	    fprintf(stderr, PACKAGE " " VERSION "\n");
	    return 0;
	 }
	 else if (streq (arg, "--help"))
	 {
	    usage (0);	
	 }
	 else if (streq (arg, "--config"))
	 {
	    if (!more_args)
	       usage (1);
	    else
	    {
	       conffile = nextarg;
	       ++argidx;
	    }
	 }
	 else if (streq (arg, "--no-inet"))
	 {
	    no_inet = YES;
	 }
	 else if (streq (arg, "--show") || streq (arg, "--hide") )
	 {
	    int   arg_is_allow = streq (arg, "--show");
	    node *newnode      = Calloc (1, sizeof(node));
		
	    if (!more_args)
	       usage (1);
		
	    if (!sections)
	    {
	       sections_restriction_type = arg_is_allow;
	    }
	    else if (sections_restriction_type != arg_is_allow)
	    {
	       /* we allow either --allow or --disallow for given invokation */
	       usage (1);
	    }
	    newnode->next   = sections;
	    newnode->name   = nextarg;		
	    newnode->length = strlen (nextarg);
	    sections 	    = newnode;
	    ++argidx;
	 }
	 else
	 {
	    usage (1);
	 };
      };
   }

   window = make_log_window ();
   
   /*
    *  Read control file of wmakerconf
    */
   {
      proplist_t plpanel  = WMCreatePLString ("Panel");
      proplist_t plwmaker = WMCreatePLString ("WindowMaker");
      
      wmakerconf = read_proplist (conffile);
      if (!wmakerconf)
	 error (_("Can't read file '%s'"), conffile);
      
      wmconfig = WMGetFromPLDictionary (wmakerconf, plwmaker);
      if (!wmconfig)
	 error (_("'%s': parse error."), conffile);

      wmpanel = WMGetFromPLDictionary (wmakerconf, plpanel);
      if (!wmpanel)
	 error (_("'%s': parse error."), conffile);

      WMReleasePropList (plpanel);
      WMReleasePropList (plwmaker);
   }
   
   /*
    *  Read 'WMRootMenu' file
    */
   {
      orig_rootmenu_fname = get_gnustep_path ("Defaults/WMRootMenu");
      orig_rootmenu = read_proplist (orig_rootmenu_fname);
      if (orig_rootmenu)
      {
	 char *new = g_strconcat (orig_rootmenu_fname, ".bak", NULL);
	 
	 /*
	  *  Generate backup file "'path'.bak"
	  */
	 if (WMWritePropListToFile (orig_rootmenu, new, YES))
	    message (_("Backupfile `%s' generated."), new);
	 else
	    error (_("Can't write backupfile `%s'."), new);
	 Free (new);
      }
   }
   
   /*
    *  Open 'WindowMaker' file
    */
   orig_wmaker_fname = get_gnustep_path ("Defaults/WindowMaker");
   windowmaker = read_proplist (orig_wmaker_fname);

   plist_changed = WMCreatePLDictionary (NULL, NULL, NULL);
   pl_yes	 = WMCreatePLString ("Yes");
   
   if (windowmaker && WMIsPLDictionary (windowmaker))
   {
      proplist_t keys  = WMGetPLDictionaryKeys (windowmaker);
      unsigned	 n;
      
      for (n = 0; n < WMGetPropListItemCount (keys); n++)
	 WMPutInPLDictionary (plist_changed, WMGetFromPLArray (keys, n),
				  pl_yes);

      WMReleasePropList (keys);
      orig_wmaker = WMDeepCopyPropList (windowmaker);
   }
   
   /*
    *  Open system 'WindowMaker' file
    */
   {
      unsigned	dir;
      char	*path[] = {WMAKERDIR,
			   "/usr/share/WindowMaker/Defaults",
			   "/usr/etc/WindowMaker",
			   "/usr/local/share/WindowMaker/Defaults",
			   "/usr/etc/WindowMaker",
			   "/usr/X11R6/lib/X11/WindowMaker"};
      
      for (dir = 0; dir < sizeof (path) / sizeof (path [0]); dir++)
      {
	 char *global_file = g_strconcat (path [dir], "/WindowMaker", NULL);
	 char *filename    = expand_tilde (global_file);
      
	 global_windowmaker = read_proplist (filename);
	 Free (global_file);
	 Free (filename);
	 if (global_windowmaker)
	    break;
      }
   }
   
   if (!global_windowmaker)
   {
      warning (_("Can't open global WindowMaker configuration file."));
      global_windowmaker = WMCreatePLDictionary (NULL, NULL, NULL);
   }
   
   if (!windowmaker)
   {
      windowmaker = global_windowmaker;
      if (WMWritePropListToFile (windowmaker, orig_wmaker_fname, YES))
	 warning (_("New WindowMaker configuration file `%s' created."),
		  orig_wmaker_fname);
      else
	 error (_("Can't generate configuration file `%s'."), orig_wmaker_fname);
   }
   else
   {
      char *new = g_strconcat (orig_wmaker_fname,
			       ".bak", NULL); /* backup filename */

      /*
       *  Generate backup file "'path'.bak"
       */
      if (WMWritePropListToFile (windowmaker, new, YES))
	 message (_("Backupfile `%s' generated."), new);
      else
	 error (_("Can't write backupfile `%s'."), new);
      Free (new);

      WMMergePLDictionaries (global_windowmaker, windowmaker, True /*recurse*/);
      windowmaker = global_windowmaker;
   }
   
   /*
    *  Fill WindowMaker attributes not defined by the user with system defaults
    */
   {
      proplist_t keys  = WMGetPLDictionaryKeys (wmconfig);
      proplist_t pldef = WMCreatePLString ("Default");
      unsigned	 n;
      
      for (n = 0; n < WMGetPropListItemCount (keys); n++)
      {
	 proplist_t attribute = WMGetFromPLArray (keys, n);
	 
	 if (!WMGetFromPLDictionary (windowmaker, attribute)) /* not defined */
	 {
	    proplist_t apl = WMGetFromPLDictionary (wmconfig, attribute);
	    proplist_t val = WMGetFromPLDictionary (apl, pldef);
	    
	    WMPutInPLDictionary (windowmaker, attribute, val);
	 }
      }

      WMReleasePropList (pldef);
      WMReleasePropList (keys);
   }

   root_window (conffile,sections, sections_restriction_type, no_inet, 
		window, wmconfig, wmpanel, windowmaker);

   WMReleasePropList (wmakerconf);
   WMReleasePropList (windowmaker);
   if (orig_rootmenu)
      WMReleasePropList (orig_rootmenu);
   if (orig_wmaker)
      WMReleasePropList (orig_wmaker);
   WMReleasePropList (plist_changed);
   WMReleasePropList (pl_yes);

   Free (orig_rootmenu_fname);
   Free (orig_wmaker_fname);
   
   g_mem_profile ();
   
   return 0;
}

static GtkWidget *
make_log_window (void)
{
   GtkWidget *window;
   GtkWidget *button;
   
   window = gtk_dialog_new ();
   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
   gtk_window_set_title (GTK_WINDOW (window), _("Messages"));

   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
		       GTK_SIGNAL_FUNC (gtk_true), NULL);
   gtk_signal_connect_object (GTK_OBJECT (window), "delete_event",
			      GTK_SIGNAL_FUNC (gtk_widget_hide),
			      GTK_OBJECT (window));

   button = gtk_button_new_with_label (_("Close"));
   gtk_widget_show (button);
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
		       TRUE, TRUE, 0);
   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
			      (GtkSignalFunc) gtk_widget_hide,
			      GTK_OBJECT (window));
   
   {
      GtkWidget *text_view, *scrollw;

      scrollw = gtk_scrolled_window_new (NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollw),
				      GTK_POLICY_AUTOMATIC,
				      GTK_POLICY_AUTOMATIC);
      gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (window)->vbox),
				      5);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), scrollw,
			  TRUE, TRUE, 5);

      text_view = gtk_text_view_new ();
      gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
      gtk_container_add (GTK_CONTAINER (scrollw), text_view);
      gtk_widget_show (text_view);
      
      gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), NO);
      log_text = text_view;
   }
   gtk_widget_set_usize (window, 600, 400);
   
   return window;
}

static void
usage (int status)
{
    fprintf (stderr, PACKAGE " " VERSION "\n");    
    fprintf (stderr,
	     "Usage: wmakerconf [OPTION] [[--show SectionName ...] | "
	     "[--hide SectionName ...]]\n"
	     "where options can be one of:\n"
	     "	--config PathToConfigFile\n"
	     "	--no-inet\n"
	     "	--help\n"
	     "	--version\n");	  
    exit (status);    
}
