/* 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.  */

/*
 * $Revision: 1.12 $
 * $Source: /import/kaplan/stable/distrib/epoch-4.2/src/RCS/xdefault.c,v $
 * $Date: 92/04/03 11:59:02 $
 * $Author: love $
 */
#ifndef LINT
static char rcsid[] = "$Author: love $ $Date: 92/04/03 11:59:02 $ $Source: /import/kaplan/stable/distrib/epoch-4.2/src/RCS/xdefault.c,v $ $Revision: 1.12 $";
#endif
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include "config.h"
#include "paths.h"
#undef NULL
#include "lisp.h"
/* X-window stuff */
#ifdef IBMAIX
#define _POSIX_SOURCE
#include <sys/types.h>
#endif
#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;
extern char XD_use_defaults;

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},
    { "-name",		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},
    { "-nm",		"*nonlocal.minibuf", XrmoptionNoArg, (caddr_t) "off"}
  };

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char * strtolower(s)
     char *s;
{
  char *p = s;
  while (*p)
    *p++ |= 0x20;		/* tolower didn't work, do it dirty instead */
  return s;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
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,*buf,*app;
#ifdef MAXPATHLEN
  char app_defaults[MAXPATHLEN];
#else
  char app_defaults[1024];
#endif /* MAXPATHLEN */
  char host[MAXHOSTNAMELEN];
#ifndef NeXT
  extern char *getenv ();
#endif  
#if !defined(NeXT) && !defined(AIX)
  extern char *rindex();
#endif  

  XrmInitialize();
  if (!XD_resource_class)
    XD_resource_class = "Emacs";
  if (!XD_resource_name)
    {
      XD_resource_name = argv[0];
      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;			/* Zero out  */
  XrmParseCommand(&Xdb_comm,optable,sizeof(optable)/sizeof(XrmOptionDescRec),
		  XD_resource_name,pargc,argv);

  /* display option is handled special */
  {
    char disp_name[100],disp_class[100];
    sprintf(disp_name,"%s.display",XD_resource_name);
    sprintf(disp_class,"%s.Display",XD_resource_class);

    XD_display_name =
      XrmGetResource(Xdb_comm,disp_name,disp_class,&type,&val)
	? (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 = getenv("XAPPLRESDIR");
  if (!app) app = PATH_APPDEFAULTS;
  /* handle adding "/" to end of string */
  file_name_as_directory(app_defaults,app);

  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';

  if (XD_use_defaults)
    {
      /* This isn't politically correct, so only do it if
       * user requests w/cmd-line arg "-ud"
       * 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
   */

  /* 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") ||
		  !strcmp((char *)val.addr,"true"))
		*((char *)xd->addr) = 1;
	      else if (!strcmp((char *)val.addr,"off") ||
		       !strcmp((char *)val.addr,"false"))
		*((char *)xd->addr) = 0;
	      else
		*((char *)xd->addr) = (xd->type == XDT_BoolT);
	      break;
		    
	    }
	}
      else			/* didn't find it */
	switch (xd->type)
	  {
	  case XDT_BoolT : *((char *)xd->addr) = 1; break;
	  case XDT_BoolF : *((char *)xd->addr) = 0; break;
	  }
    }
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
epoch_get_default(name,class)
     char *name,*class;
{
  XrmValue val;		/* option value return */
  char *type;

  if (XrmGetResource(Xdb_comm,name,class,&type,&val))
    return (char *) val.addr;
  if (XrmGetResource(Xdb,name,class,&type,&val))
    return (char *) val.addr;

  return (char *) 0;
}
