/* $Id: Resources.c,v 1.1 1997/04/15 10:09:46 archer Exp $
 *	RESOURCES.C - Manage user preferences
 *
 * This uses the X11 databases mechanisms to load various sources and files
 * and provide resource naming to users.
 */
#include <Widget/WidgetsP.h>
#include <Widget/colorsP.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <X11/Xresource.h>
#include "Resource_path.h"


/**
 ** Private variables
 **/
static XrmDatabase	resources;
static char		*resource_naming;
static char		*resource_classing;
static int		resource_name_l,
			resource_class_l;
static char		name_buffer[1024];
static char		class_buffer[1024];


/**
 ** Generic program options
 **/
static char	xbg[]		= ".background";
static char	xon[]		= "on";
static XrmOptionDescRec opTable[] = {
	{ "-bg",	xbg,		XrmoptionSepArg, (caddr_t)NULL },
	{ "-background",xbg,		XrmoptionSepArg, (caddr_t)NULL },
	{ "-width",	".main.width",	XrmoptionSepArg, (caddr_t)NULL },
	{ "-height",	".main.height",	XrmoptionSepArg, (caddr_t)NULL },
	{ "-x",		".main.x",	XrmoptionSepArg, (caddr_t)NULL },
	{ "-y",		".main.y",	XrmoptionSepArg, (caddr_t)NULL },
	{ "-geometry",	".main.geometry",XrmoptionSepArg,(caddr_t)NULL },
	{ "-mono",	".monochrome",	XrmoptionNoArg,  (caddr_t)xon },
	{ "-sync",	".synchronous",	XrmoptionNoArg,  (caddr_t)xon },
	{ "-nosignal",	".signal",	XrmoptionNoArg,  (caddr_t)"off" },
	{ "-xrm",	NULL,		XrmoptionResArg, (caddr_t)NULL } };
#define NB_OPTABLE		11


/**
 ** X11_RESOURCE_INITIALIZE
 **	Initialize the X11 resources management
 **/
void x11__resource_init(char *name, char *file, int *argc, char **argv)
{
XrmDatabase	db;
char		*d, *s;
int		l;
/*
 * Initialize all
 */
	XrmInitialize();
/*
 * Fetch resource from application default file
 */
	snprintf(name_buffer, sizeof(name_buffer), "%s/%s", X11_RSC_NAME, name);
	resources = XrmGetFileDatabase(name_buffer);
/*
 * Application class and name
 */
	x11__widget_root->class = strdup(name);
	d = x11__widget_root->name;
	l = sizeof(x11__widget_root->name)-1;
	for (s = name; *s; s++)
		if (l--)
			if (isupper(*s))
				*d++ = *s | 0x20;
			else
				*d++ = *s;
		else
			break;
	*d = '\0';
/*
 * Return database in screen or user's Xdefaults
 */
	if ((s = XResourceManagerString(x11__screen)) != 0)
		db = XrmGetStringDatabase(s);
	else {
		if ((s = getenv("HOME")) == 0)
			s = ".";
		snprintf(name_buffer, sizeof(name_buffer), "%s/.Xdefaults", s);
		db = XrmGetFileDatabase(name_buffer);
	}
	if (db)
		XrmMergeDatabases(db, &resources);
/*
 * Add private XENVIRONMENT
 */
	if ((s = getenv("XENVIRONMENT")) == 0) {
		if ((s = getenv("HOME")) == 0)
			s = ".";
		snprintf(name_buffer, sizeof(name_buffer), "%s/.Xdefaults-", s);
		gethostname(name_buffer + strlen(name_buffer),
				sizeof(name_buffer) - strlen(name_buffer));
		s = name_buffer;
	}
	db = XrmGetFileDatabase(s);
	if (db)
		XrmMergeDatabases(db, &resources);
/*
 * User-supplied database
 */
	if (file) {
		db = XrmGetFileDatabase(file);
		if (db)
			XrmMergeDatabases(db, &resources);
	}
/*
 * Parse command line options
 */
	db = 0;
	XrmParseCommand(&db, opTable, NB_OPTABLE, name, argc, argv);
	if (db)
		XrmMergeDatabases(db, &resources);
/*
 * Default database
 */
	if (!resources)
		resources = XrmGetStringDatabase("*.resource: none");
/*
 * Monochrome specification
 */
	x11__resource_lookup(x11__widget_root);
}


/**
 ** X11_RESOURCE_LOOKUP
 **	Setup lookup for resources on a widget. This is recursive
 **/
void x11__resource_lookup(X11_widget o)
{
char	*s;
/*
 * End of recursion
 */
	if (o == 0) {
		resource_naming   = name_buffer;
		resource_name_l   = sizeof(name_buffer)-2;
		resource_classing = class_buffer;
		resource_class_l  = sizeof(class_buffer)-2;
		return;
	}
/*
 * Recursion first
 */
	x11__resource_lookup(o->parent);
/*
 * Class and name empty?
 */
	if (!o->name || !o->name[0] || !o->class[0])
		return;
/*
 * Append name
 */
	for (s = o->name; *s; s++)
		if (resource_name_l-- > 0)
			*resource_naming++ = *s;
		else
			break;
	*resource_naming++ = '.';
	resource_name_l--;
/*
 * Append class
 */
	for (s = o->class; *s; s++)
		if (resource_class_l-- > 0)
			*resource_classing++ = *s;
		else
			break;
	*resource_classing++ = '.';
	resource_class_l--;
}


/**
 ** X11_RESOURCE_VALUE
 **	Return the value (if any) of a resource
 **/
char *x11__resource_value(char *name)
{
static char	work[1024];
char		*str_type;
XrmValue	value;
int		l;
/*
 * Build key pair
 */
	strncpy(resource_classing, name, resource_class_l);
	strncpy(resource_naming, name, resource_name_l);
	if (isupper(*name))
		*resource_naming = *name | 0x20;
	resource_classing[resource_class_l] = '\0';
	resource_naming[resource_name_l] = '\0';
/*
 * Any resource?
 */
	if (XrmGetResource(resources, name_buffer, class_buffer,
				&str_type, &value)) {
		l = value.size;
		if (l > sizeof(work)-1)
			l = sizeof(work)-1;
		strncpy(work, value.addr, l);
		work[l] = '\0';
		return work;
	}
/*
 * No value
 */
	return 0;
}


/**
 ** X11_RESOURCE_INTEGER
 **	Integer resources for widget
 **/
int x11__resource_integer(char *name, int value)
{
char	*s;

	if ((s = x11__resource_value(name)) != 0 && isdigit(*s))
		return atoi(s);
	return value;
}


/**
 ** X11_RESOURCE_BASIC
 **	Basic resources for widget, once hard-coded defaults are known
 **/
void x11__resource_basic(X11_widget o)
{
char	*s;
/*
 * Color properties
 */
	o->background = x11__color_resource("Background", o->background);
	o->foreground = x11__color_resource("Foreground", o->foreground);
/*
 * Border
 */
	o->border_color = x11__color_resource("BorderColor", o->border_color);
	o->border2 = 2 * x11__resource_integer("BorderThickness", o->border2/2);
/*
 * Active colors
 */
	o->active_bk = x11__color_resource("ActiveBackground", o->active_bk);
	o->active_fg = x11__color_resource("ActiveForeground", o->active_fg);
/*
 * Shadow style
 */
	o->tl_color = x11__color_resource("TopLeftColor", o->tl_color);
	o->br_color = x11__color_resource("BottomRightColor", o->br_color);
	o->shadow_thickness = x11__resource_integer("ShadowThickness",
							o->shadow_thickness);
/*
 * Focus style
 */
	o->focus_color = x11__color_resource("FocusColor", o->focus_color);
	o->focus_thickness = x11__resource_integer("FocusThickness",
							o->focus_thickness);
/*
 * Margin resources
 */
	o->margin_w = x11__resource_integer("MarginX", o->margin_w);
	o->margin_h = x11__resource_integer("MarginY", o->margin_h);
	o->margin_inside = x11__resource_integer("MarginInside",
						 o->margin_inside);
/*
 * Positional hint resources
 */
	if ((s = x11__resource_value("Geometry")) != 0)
		XParseGeometry(s, &o->hint_x, &o->hint_y,
				  &o->hint_w, &o->hint_h);
	o->hint_x = x11__resource_integer("X", o->hint_x);
	o->hint_y = x11__resource_integer("Y", o->hint_y);
	o->hint_w = x11__resource_integer("Width", o->hint_w);
	o->hint_h = x11__resource_integer("Height", o->hint_h);
}
