/* Subroutines to handle the X-defaults processing */

/*
   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990
                 Free Software Foundation, Inc.

This file is part of Epoch, a modified version of GNU Emacs.

Epoch is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the GNU Emacs General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
Epoch, but only under the conditions described in the
GNU Emacs General Public License.   A copy of this license is
supposed to have been given to you along with Epoch so you
can know your rights and responsibilities.  It should be in a
file named COPYING.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */

#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include "config.h"
#undef NULL
#include "lisp.h"
/* X-window stuff */
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>

#include "xdefault.h"

#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 1024
#endif
extern char * XD_resource_name;
extern char * XD_resource_class;
extern char * XD_display_name;
extern Display *XD_display;
extern int XD_plane;
extern Atom XA_resource_manager;

struct Default_Set XD_screen,XD_minibuf;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static XrmDatabase Xdb;
static XrmDatabase Xdb_comm;

/* There's a reason for this weirdness. We need to be able to grab these
 * before doing any other processing. These names provide defaults that can
 * be attached in the option descriptor table, without significant chance
 * of collision.
 */
#define R_NAME	".potrzebiename"
#define R_CLASS ".potrzebieclass"

/* defines for parsing the command line */
static XrmOptionDescRec optable[] =
    {
    { "-background",	"*background",	XrmoptionSepArg, (caddr_t)0},
    { "-bg",		"*background",	XrmoptionSepArg, (caddr_t)0},
    { "-foreground",	"*foreground",	XrmoptionSepArg, (caddr_t)0},
    { "-fg",		"*foreground",	XrmoptionSepArg, (caddr_t)0},
    { "-rn",		R_NAME,		XrmoptionSepArg, (caddr_t)0},
    { "-resource",	R_NAME,		XrmoptionSepArg, (caddr_t)0},
    { "-cn",		R_CLASS,	XrmoptionSepArg, (caddr_t)0},
    { "-class",		R_CLASS,	XrmoptionSepArg, (caddr_t)0},
    { "-geometry",	"*screen.geometry", XrmoptionSepArg, (caddr_t)0},
    { "-font",		"*font",	XrmoptionSepArg, (caddr_t)0},
    { "-fn",		"*font",	XrmoptionSepArg, (caddr_t)0},
    { "-wn",		"*name",	XrmoptionSepArg, (caddr_t)0},
    { "-window",	"*name",	XrmoptionSepArg, (caddr_t)0},
    { "-d",		"*display",	XrmoptionSepArg, (caddr_t)0},
    { "-display",	"*display",	XrmoptionSepArg, (caddr_t)0},
    { "-r",		"*reverse",	XrmoptionNoArg,  (caddr_t) "on"},
    { "-R",		"*reverse",	XrmoptionNoArg,  (caddr_t) "off"},
    { "-motion",	"*motion",	XrmoptionNoArg,  (caddr_t) "on"},
    { "-xrm",           0,		XrmoptionResArg, (caddr_t)0},
    };

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char * strtolower(s) char *s;
    {
    char *p = s;
    while (*p)
	*p++ |= 0x20;		/* tolower didn't work, do it dirty instead */
    return s;
    }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* [cjl] attempt to load "name" as defaults db; merge if successful */     
void x_get_database(name, db)
char *name;
XrmDatabase *db;
{
  XrmDatabase dbtmp = 0;

  dbtmp = XrmGetFileDatabase(name);
  if (dbtmp)
    XrmMergeDatabases(dbtmp, db);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void x_load_defaults(pargc,argv)
int *pargc;
char **argv;
    {
    XrmValue val;
    char *type,*ptr;
    char fname[512],*evar,*home_dir,*app_defaults;
    char host[MAXHOSTNAMELEN];
    XrmDatabase dbtmp = 0;		/* tmp load place before merge */
    extern char *getenv(), *rindex();

    XrmInitialize();

    XD_resource_name = argv[0];
    XD_resource_class = "Emacs";
    if ( (ptr=rindex(XD_resource_name,'/')))
        XD_resource_name = ptr+1;  /* clip path */
    
    /* now, process the command line options, storing in separate db */
    Xdb_comm = 0;		/* 0 out  */
    XrmParseCommand(&Xdb_comm,optable,sizeof(optable)/sizeof(XrmOptionDescRec),
		    "",pargc,argv);

    /* display option is handled special */
    XD_display_name =
	XrmGetResource(Xdb_comm,".display",".Display",&type,&val)
	    ? (char *) val.addr : "";

    /* check if command line value supercedes name or class */
    if (XrmGetResource(Xdb_comm,R_NAME,"",&type,&val))
	XD_resource_name = (char *)(val.addr);
    if (XrmGetResource(Xdb_comm,R_CLASS,"",&type,&val))
	XD_resource_class = (char *)(val.addr);

    /*
     * Initialize our database
     */
    Xdb = XrmGetStringDatabase("*:");
    
    /* There a number of places to try and find files, step through them
     * one by one
     */

    /* Path to app-defaults files - usually /usr/lib/X11/app-defaults/ */
    app_defaults = getenv("XAPPLRESDIR");
    if (!app_defaults) app_defaults = "/usr/lib/X11/app-defaults/";

    strcat(strcpy(fname,app_defaults),XD_resource_name);
    x_get_database(fname,&Xdb);

    strcat(strcpy(fname,app_defaults),XD_resource_class);
    x_get_database(fname,&Xdb);

    /* set up some defaults we'll need */
    home_dir = getenv("HOME");
    if (gethostname(host,MAXHOSTNAMELEN) < 0)
	{
	perror("Couldn't get host name - this system is in deep weeds");
	exit(2);
	}
    /* clip out just the basic host name, no domain */
    if ( (evar = strchr(host,'.')) != 0) *evar = '\0';

    /* first, check for .Xdefaults in home directory */
    if (home_dir != 0)
	{
	strcat(strcpy(fname,home_dir),"/.Xdefaults");
	x_get_database(fname,&Xdb);
	}

    /* additional defaults are in file in XENVIRONMENT
     * or in .Xdefaults-sysname
     */
    if ( (evar = getenv("XENVIRONMENT")) != 0)
	{
	  x_get_database(evar,&Xdb);
	}
    else if (home_dir != 0)
	{
	  strcat(strcat(strcpy(fname,home_dir),"/.Xdefaults-"),host);
	  x_get_database(fname,&Xdb);
	}
    }	
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void x_get_defaults(table,count,pargc,argv)
	struct XDefaultEntry *table;
	int count;
	int *pargc;
	char ** argv;
    {
    int i;
    int zret;			/* return value holder */
    XrmValue val;		/* option value return */
    char *type;			/* option type return */
    char name[256],class[256];
    struct XDefaultEntry *xd;
    XrmDatabase dbtmp = 0;		/* tmp load place before merge */
    Lisp_Object rdb;			/* Resource database string */
    extern Lisp_Object raw_get_property();

    /* The resource and class name for defaults may be changed on the command
     * line. Check it for these options, and override internal defaults if
     * set
     */
#if 0	/* [cjl] - do this in x_load_defaults() to establish things earlier */
    if (XrmGetResource(Xdb_comm,R_NAME,"",&type,&val))
	XD_resource_name = (char *)(val.addr);
    if (XrmGetResource(Xdb_comm,R_CLASS,"",&type,&val))
	XD_resource_class = (char *)(val.addr);
#endif

    /* There is one more source of defaults we must get. This is the
     * RESOURCE_MANAGER property on the root window. My plan is to try for
     * the screen root window, and if that doesn't work, use the default
     * screen root window.
     */
    rdb = raw_get_property(XD_display,RootWindow(XD_display,XD_plane),
			   XA_resource_manager);
    if (!STRINGP(rdb) && XD_plane != 0)
      rdb = raw_get_property(XD_display,RootWindow(XD_display,0),
			     XA_resource_manager);
    if (!STRINGP(rdb) && !EQ(rdb,Qnil))
      {
	fprintf(stderr,"Epoch: Resource Manager Property type not STRING\n");
	return;
      }
    
    if (STRINGP(rdb))
	{
	dbtmp = XrmGetStringDatabase(XSTRING(rdb)->data);
	XrmMergeDatabases(dbtmp,&Xdb);
	}

    /* Loop through our table (in xd.h) of all the options that get set.
     * To add more options, put them in the table. The resource name/class
     * are set by x_init_defaults and the special hacks at the start of
     * this function so that they can be overridden by command line options.
     */
    for ( i = 0 ; i < count ; ++i )
	{
	xd = table+i;
	strcat(strcpy(name,XD_resource_name),xd->name);
	strcat(strcpy(class,XD_resource_class),xd->class);
	if (XrmGetResource(Xdb_comm,name,class,&type,&val)
	    || XrmGetResource(Xdb,name,class,&type,&val))
	    {
	    switch (xd->type)
		{
		case XDT_Int :
		    *((int *)xd->addr) = atoi(val.addr);
		    break;
		case XDT_String :
		    *((char **)xd->addr) = (char *)val.addr;
		    break;
		case XDT_Flag : *((char *)xd->addr) = 1; break;
		case XDT_BoolT :
		case XDT_BoolF :
		    if (!strcmp(strtolower((char *)val.addr),"on"))
			*((char *)xd->addr) = 1;
		    else if (!strcmp((char *)val.addr,"off"))
			*((char *)xd->addr) = 0;
		    else
			*((char *)xd->addr) = (xd->type == XDT_BoolT);
		    break;
		    
		}
	    }
	else /* didn't find it */
	    switch (xd->type)
		{
		/*
	        case XDT_Int : *((int *)xd->addr) = 0; break;
		case XDT_String : *((char **)xd->addr) = (char *) 0; break;
		*/
		case XDT_BoolT : *((char *)xd->addr) = 1; break;
		case XDT_BoolF :
		/* case XDT_Flag : */
		    *((char *)xd->addr) = 0; break;
		}
	}
    }

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */




