/****************************************************************************
 *
 * Copyright (c) 2005 Sasha Vasko <sasha at aftercode.net>
 *
 * 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.
 *
 ****************************************************************************/

#define LOCAL_DEBUG
#include "../configure.h"

#include "asapp.h"
#include "../libAfterBase/xml.h"
#include "afterstep.h"
#include "wmprops.h"
#include "desktop_category.h"
#include "kde.h"

/* KDE IPC implementation : */

void 
KIPC_sendMessage(KIPC_Message msg, Window w, int data)
{
    XEvent ev;
    ev.xclient.type = ClientMessage;
    ev.xclient.display = dpy;
    ev.xclient.window = w;
    ev.xclient.message_type = _KIPC_COMM_ATOM;
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = msg;
    ev.xclient.data.l[1] = data;
    XSendEvent(dpy, w, False, 0L, &ev);
}

#define KDE_CONFIG_MAKE_TAG2(var,kind) 	do{  	(var)=xml_elem_new(); \
												(var)->tag = mystrdup(#kind); \
												(var)->tag_id = KDEConfig_##kind ; }while(0)

#define KDE_CONFIG_MAKE_TAG(kind) KDE_CONFIG_MAKE_TAG2(kind,kind)

static xml_elem_t*
make_kde_config_group_tag( const char *name ) 
{
	xml_elem_t *group = NULL ; 
	int name_len = 0 ; 
	if( name ) 
		while( name[name_len] != ']' && name[name_len] != '\0' && name[name_len] != '\n') ++name_len;
	KDE_CONFIG_MAKE_TAG(group);
	if( name_len > 0 ) 
	{	
		group->parm = safemalloc( 4+1+1+name_len+1+1 );
		sprintf( group->parm, "name=\"%*.*s\"", name_len, name_len, name );
	} 		                   /* WE ALLOW SECTIONS WITH NO NAMES */
	return group;
}	   

static xml_elem_t*
make_kde_config_comment_tag() 
{
	xml_elem_t *comment = NULL ; 
	KDE_CONFIG_MAKE_TAG(comment);
	return comment;
}	   

static xml_elem_t*
make_kde_config_item_tag( const char *name, int *name_len_return ) 
{
	xml_elem_t *item = NULL ; 
	if( name ) 
	{	
		int name_len = 0 ; 
		while( name[name_len] != '=' && name[name_len] != '\0' && name[name_len] != '\n') ++name_len;
		if( name_len > 0 ) 
		{	
			KDE_CONFIG_MAKE_TAG(item);
			item->parm = safemalloc( 4+1+1+name_len+1+1 );
			sprintf( item->parm, "name=\"%*.*s\"", name_len, name_len, name );
		}
		if( name_len_return ) 
			*name_len_return = name_len ;
	}		
	return item;
}	   


xml_elem_t* load_KDE_config(const char* realfilename) 
{
	xml_elem_t* config = create_CONTAINER_tag();
	FILE *fp = fopen( realfilename, "r" );
	
	if( fp != NULL ) 
	{	
		char buffer[8192];
		xml_elem_t* group = NULL ; 
		
		while(fgets(&buffer[0], sizeof(buffer), fp) != NULL)
		{
			xml_elem_t* tag ; 
			int i = 0; 

			while( isspace(buffer[i]) ) ++i ;
			if( buffer[i] == '#' )
			{
 				if( (tag = make_kde_config_comment_tag()) != NULL )
				{	
					++i ;
					int len = strlen( &buffer[i] ) ;
					while( len > 0 && isspace( buffer[i+len-1] ) ) --len ;
					if( len > 0 ) 
					{
						tag->child = create_CDATA_tag();	  
						tag->child->parm = mystrndup( &buffer[i], len );
					}
					if( group == NULL ) 
					{
						group = make_kde_config_group_tag(NULL);		   
						config->child = group;
					}
					xml_insert( group, tag );
				}
			}else if( buffer[i] == '[' ) 
			{
			 	if( (tag = make_kde_config_group_tag(&buffer[i+1])) != NULL )
				{	
					if( group ) 
						group->next = tag ; 
					else
						config->child = tag ;						
					group = tag ;
				}
			}else if( buffer[i] != '\0' )
			{
				int name_len ; 
				tag = make_kde_config_item_tag(&buffer[i], &name_len);
				if( tag ) 
				{              /* now we need to parse value and then possibly a comment : */
					char *val = stripcpy(&buffer[i+name_len+1] );
					if( group == NULL ) 
					{
						group = make_kde_config_group_tag(NULL);		   
						config->child = group;
					}

					xml_insert( group, tag );
					
					if( val ) 
					{
						if( val[0] != '\0' ) 
						{	
							tag->child = create_CDATA_tag();
							tag->child->parm = val ; 
						}else
							free( val );
					}	 
				}	 
			}			 
		}	 

		fclose( fp );
	}
	return config;
}

static char *
strip_name_value( char *parm )
{					   
	if( parm ) 
	{	
		int parm_len = strlen(parm);	  
		if( parm_len > 7 && strncmp( parm, "name=\"", 6) == 0 )  
		{
			return mystrndup(parm+6, parm_len - 7);
		}
	}
	return NULL;
}

Bool save_KDE_config(const char* realfilename, xml_elem_t *elem ) 
{
	FILE *fp ;
	int sect_count = 0 ;
	
	if( elem == NULL ) 
		return False; 
	if( elem->tag_id == XML_CONTAINER_ID ) 
		if( (elem = elem->child) == NULL ) 
			return False;
	
	if( (fp = fopen( realfilename, "w" )) == NULL ) 
		return False;
	
	do
	{
		if( elem->tag_id == KDEConfig_group ) 	
		{
			xml_elem_t *child = elem->child ; 
			char *name ; 
			++sect_count ;
			name = strip_name_value( elem->parm );
			if( name != NULL ) 
			{
				if( sect_count > 1 ) 
					fputc( '\n', fp );	  
				fprintf( fp, "[%s]\n", name );
				free( name );
			}
			
			while( child ) 
			{
				if( child->tag_id == KDEConfig_comment ) 
				{
			  		if( IsTagCDATA(child->child) )
						fprintf( fp, "#%s\n", child->child->parm );
					else
						fprintf( fp, "#\n" );
				}else if( child->tag_id == KDEConfig_item ) 
				{
			  		name = strip_name_value( child->parm );
					if( name != NULL ) 
					{
						fprintf( fp, "%s=", name );	  
						if( IsTagCDATA(child->child) )
							fprintf( fp, "%s\n", child->child->parm );
						else
							fprintf( fp, "\n" );
						free( name );
					}
				}
				child = child->next ; 	
			}	 
		}	 
	}while( (elem = elem->next) != NULL ); 
	fclose( fp ); 
	return True;
}

static xml_elem_t *
find_KDE_config_item_by_key( xml_elem_t *group, const char *key, Bool create_if_missing )
{	
 	xml_elem_t *item = group->child;			   
 	while( item ) 
	{
		if( item->tag_id == KDEConfig_item && item->parm) 
			if( strcmp(item->parm, key) == 0 )
				break;
		item = item->next ; 	 		
	}	 

	if( item != NULL && item->tag_id != KDEConfig_item ) 
		item = NULL ; 
	if( item == NULL && create_if_missing ) 
	{
		KDE_CONFIG_MAKE_TAG(item);
		item->parm = mystrdup(key);
		xml_insert( group, item );
	}	 
		
	return item;
}

static void
set_KDE_config_item_value( xml_elem_t *item, const char *value )
{
	while( item->child != NULL ) 
		xml_elem_delete(&(item->child), item->child);
	if( value ) 
	{	
		item->child = create_CDATA_tag();
		item->child->parm = mystrdup(value); 
	}
}

void 
merge_KDE_config_groups( xml_elem_t *from, xml_elem_t *to )
{
	
	if( from != NULL && to != NULL && from != to ) 
	{	
		xml_elem_t *src_child = from->child;
		while( src_child ) 
		{
			if( src_child->tag_id == KDEConfig_item && src_child->parm) 
			{
				xml_elem_t *dst_child ;			   
				char *val = NULL ;
				
				dst_child = find_KDE_config_item_by_key(to, src_child->parm, True);			   
				if( src_child->child && src_child->child->tag_id == XML_CDATA_ID )
					val = src_child->child->parm ;
				set_KDE_config_item_value( dst_child, val );   			   
			}	 
			src_child = src_child->next ; 	 
		}			  
	}
}	 

static char *
make_xml_name_key( const char *name )
{
	char *key = NULL ;
	if( name ) 
	{	
		key = safemalloc( 4+1+1+strlen(name)+1+1 );
		sprintf( key, "name=\"%s\"", name );
	}
	return key;
}

xml_elem_t *
get_KDE_config_group( xml_elem_t *config, const char *name, Bool create_if_missing )
{
	char *key ; 
	xml_elem_t *group = config;
	if( config == NULL ) 
		return False; 

	if( config->tag_id == XML_CONTAINER_ID ) 
		if( (group = config->child) == NULL ) 
			return False;

	key = make_xml_name_key( name );
	
	do
	{
		if( group->tag_id == KDEConfig_group ) 	
		{
			if( key == NULL && group->parm == NULL ) 
				break;
			if( key != NULL && group->parm != NULL ) 
				if( strcmp( key, group->parm) == 0 ) 
					break;
		}
	}while( (group = group->next) != NULL ); 

	if( group != NULL && group->tag_id != KDEConfig_group) 
		group = NULL ; 
	
	if( group == NULL && create_if_missing ) 
	{
		KDE_CONFIG_MAKE_TAG(group);
		group->parm = key;
		key = NULL ; 
		if( config->tag_id == XML_CONTAINER_ID ) 
			xml_insert( config, group );
		else
			group->next = config ; 
	}		   
	if( key ) 
		free( key );
	return group;
}

void 
set_KDE_config_group_item( xml_elem_t *group, const char *item_name, const char *value )
{
	if( group != NULL &&  group->tag_id == KDEConfig_group ) 
	{	
		char *key  = make_xml_name_key( item_name );
		if( key ) 
		{	
			xml_elem_t *item = find_KDE_config_item_by_key(group, key, True);			   
			set_KDE_config_item_value( item, value );   			   
			free( key );
		}
	}
}

Bool
add_KDE_colorscheme( const char *new_cs_file ) 
{
	Bool success = False; 
#define KDE_CSRC_PATH  		"$KDEHOME/share/apps/kdisplay/color-schemes/"
	
	if( new_cs_file ) 
	{	
		int i = 1;
		char *dst_path ;
		char *dst_full_fname ; 
		char *fname  = NULL ; 

		parse_file_name(new_cs_file, NULL, &fname );
		dst_path = copy_replace_envvar( KDE_CSRC_PATH );
		
		while( dst_path[i] != '\0' ) 
		{	
			if( dst_path[i] == '/' ) 
			{
				char t = dst_path[i];
				dst_path[i] = '\0' ; 
				if (CheckDir (dst_path) != 0)
					mkdir (dst_path, 0755);
				dst_path[i] = t ;
			}
			++i;
		}			   

		dst_full_fname = safemalloc( i+strlen(fname)+1 );
		sprintf( dst_full_fname, "%s%s", dst_path, fname );
		success = (CopyFile( new_cs_file, dst_full_fname )==0);

		free( dst_full_fname );
		free( dst_path );
		free( fname );
	}

	return success;
}

