view src/xrdb.c @ 974:4f88a1b78a46

* xfns.c (x_get_arg): Return Qunbound for an unspecified resource, not nil. That way, we can tell the difference between a false resource and an unspecified resource. (x_default_error): Use DEFLT if x_get_arg returns Qunbound, not Qnil. (x_figure_window_size, x_icon, Fx_create_frame): Deal with Qunbound and Qnil properly. * xfns.c (Fx_create_frame): Pass the correct number of arguments to x_set_font. * xfns.c [not HAVE_X11] (Fx_create_frame): Delete section that's only included if we *do* have X11. Blind patching. * xfns.c (x_icon): Rewritten to call x_wm_set_icon_position and x_wm_set_window_state instead of calling XSetWMHints directly. (x_wm_set_window_state, x_wm_set_icon_pixmap, x_wm_set_icon_position): Use x_wm_hints. (x_term_init): Set the `input' field of x_wm_hints, and its flag. * xfns.c (x_default_parameter): Don't call store_frame_param here; it's already taken care of by x_set_frame_parameters. * xfns.c (Fx_create_frame): Check for the `icon-type', `auto-raise', and `auto-lower' parameters. Have `icon-type' default to t, indicating that we want the nifty gnu in our icons. (Qauto_lower): New symbol. * xfns.c (x_set_icon_type): UNBLOCK_INPUT before reporting the error, not after. error doesn't return, sklitch-brain. * xfns.c (x_set_frame_parameters): Properly recognize changes to the height of the frame. Recognize changes of the frame's position. * xfns.c (x_set_frame_parameters): Iterate over ALIST while the current element is cons, not while it's non-nil. (syms_of_xfns): Call init_x_parm_symbols after interning all the other atoms; init_x_parm_symbols expects Qx_frame_parameter to be initialized. * xfns.c (Qbackground_color, Qborder_color, Qborder_width, Qcursor_color, Qfont, Qforeground_color, Qgeometry, Qhorizontal_scroll_bar, Qicon_left, Qicon_top, Qiconic_startup, Qinternal_border_width, Qleft, Qmouse_color, Qparent_id, Qsuppress_icon, Qsuppress_initial_map, Qtop, Qundefined_color, Qvertical_scroll_bar, Qwindow_id, Qx_frame_parameter): New symbols, with lisp code to rebuild syms_of_xfns. (syms_of_xfns): Initialize and staticpro them. (Qheight, Qminibuffer, Qname, Qnone, Qonly, Qwidth, Qunsplittable): Add extern declaration for these. (x_init_parm_symbols): Don't initialize Qx_frame_parameter here; it's done in syms_of_xfns. (x_default_parameter): Change the argument char *PROPNAME into a Lisp_Object PROP; let the caller take care of interning the atom. (Fx_geometry, x_figure_window_size, x_icon, Fx_create_frame): Use the new Q... variables, instead of interning things. * xfns.c (x_set_frame_param): Replaced by x_set_frame_parameters. (x_set_frame_parameters): Process the alist of parameters here. Notice `width', `height', `top', and `left' parameters. Hold off changing the frame size and position until the end, so we can do both parameters at once when they are both specified. (x_default_parameter): Call x_set_frame_parameters, not x_set_frame_param. * xfns.c (x_figure_window_size): Indicate that this function returns an int, rather than just leaving it unstated. * xfns.c (Fx_create_frame): Call change_frame_size with a DELAY of 0.
author Jim Blandy <jimb@redhat.com>
date Wed, 12 Aug 1992 14:33:03 +0000
parents 88a29c720fa7
children aaa628aaf808
line wrap: on
line source

/* Deal with the X Resource Manager.
   Copyright (C) 1990, 1992 Free Software Foundation.

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, 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; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by jla, 4/90 */

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <X11/X.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <sys/param.h>
#ifdef VMS
#include "vms-pwd.h"
#else
#include <pwd.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>

#ifdef emacs
#include "config.h"
#endif

extern char *getenv ();
extern uid_t getuid ();
extern struct passwd *getpwuid ();
extern struct passwd *getpwnam ();

static char *
gethomedir (dirname)
     char *dirname;
{
  int uid;
  struct passwd *pw;
  char *ptr;

  if ((ptr = getenv ("HOME")) == NULL)
    {
      if ((ptr = getenv ("USER")) != NULL)
	pw = getpwnam (ptr);
      else
	{
	  uid = getuid ();
	  pw = getpwuid (uid);
	}
      if (pw)
	ptr = pw->pw_dir;
      else
	{
	  ptr = NULL;
	  *dirname = '\0';
	}
    }

  if (ptr != NULL) 
    strcpy (dirname, ptr);

  dirname += strlen (dirname);
  *dirname = '/';
  dirname++;
  *dirname = '\0';

  return dirname;
}

static int
file_p (path)
     char *path;
{
  struct stat status;

  return (access (path, R_OK) == 0		/* exists and is readable */
	  && stat (path, &status) == 0		/* get the status */
	  && (status.st_mode & S_IFDIR) == 0);	/* not a directory */
}

#if 0
#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
#endif

/* Isn't this just disgusting? */

#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"

static int
decode_magic (string, file, return_path)
     char *string, *file, *return_path;
{
  char *p = string;
  char *t = return_path;

  while (*p)
    {
      if (*p == '%')
	switch (*++p)
	  {
	  case '%':
	    *t++ = '%';
	    p++;
	    break;

	  case 'N':
	  case 'T':
	  case 'S':
	  case 'L':
	  case 'l':
	  case 't':
	  case 'c':
	  default:
	    p++;
	    if (*t == '/' && *p == '/')
	      p++;
	    break;
	  }
      else
	*t++ = *p++;
    }
  *t = '\0';
  strcat (return_path, file);

  if (file_p (return_path))
    return 1;

  return_path[0] = '\0';
  return 0;
}

static int
magic_searchpath_decoder (incantation_string, file, return_path)
     char *incantation_string, *return_path, *file;
{
  register char *s = incantation_string;
  register char *p;

  /* Must be big enough for "%N%S".  */
  register int string_size = MAXPATHLEN;
  register char *string = (char *) alloca (string_size * sizeof (*string));

  while (*s)
    {
      p = s;

      while (*p && *p != ':')
	p++;

      if (*p == ':' && *(p + 1) == ':')
	{
	  /* We know string is big enough for this.  */
	  bcopy ("%N%S", string, 5);
	  if (decode_magic (string, file, return_path))
	    return 1;

	  s = p + 1;
	  continue;
	}

      if (p > s)
	{
	  int len = p - s;

	  if (string_size < len+1)
	    {
	      string_size = 2 * len;
	      string = (char *) alloca (string_size * sizeof (*string));
	    }
	  bcopy (s, string, len);
	  string[len + 1] = '\0';
	  if (decode_magic (string, file, return_path))
	    return 1;
	}

      if (p)
	s = p + 1;
      else
	return 0;
    }

  return 0;
}

static XrmDatabase
get_system_app (class)
     char *class;
{
  XrmDatabase db;
  char path[MAXPATHLEN];
  char *p;

  if ((p = getenv ("XFILESEARCHPATH")) == NULL)
    p = X_DEFAULT_SEARCH_PATH;

  if (! magic_searchpath_decoder (p, class, path))
    return NULL;

  db = XrmGetFileDatabase (path);
  return db;
}

static XrmDatabase
get_fallback (display)
     Display *display;
{
  XrmDatabase db;

  return NULL;
}

static XrmDatabase
get_user_app (class)
     char *class;
{
  XrmDatabase db;
  char *magic_path;
  char path[MAXPATHLEN];

  if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
    {
      char homedir[MAXPATHLEN];
      char *default_magic;
      char *p;

      gethomedir (homedir);

      if ((p = getenv ("XAPPLRESDIR")) == NULL)
	{
	  default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
	  magic_path = (char *) alloca ((3 * strlen (homedir))
					+ strlen (default_magic));
	  sprintf (magic_path, default_magic, homedir, homedir, homedir);
	}
      else
	{
	  default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
	  magic_path = (char *) alloca ((3 * strlen (p))
					+ strlen (default_magic)
					+ strlen (homedir));
	  sprintf (magic_path, default_magic, p, p, p, homedir);
	}
    }

  if (! magic_searchpath_decoder (magic_path, class, path))
    return NULL;
  
  db = XrmGetFileDatabase (path);
  return db;
}

static XrmDatabase
get_user_db (display)
     Display *display;
{
  XrmDatabase db;
  char *xdefs;

  xdefs = XResourceManagerString (display);
  if (xdefs != NULL)
    db = XrmGetStringDatabase (xdefs);
  else
    {
      char xdefault[MAXPATHLEN];

      gethomedir (xdefault);
      strcat (xdefault, ".Xdefaults");
      db = XrmGetFileDatabase (xdefault);
    }

  return db;
}

static XrmDatabase
get_environ_db ()
{
  XrmDatabase db;
  char *p;
  char path[MAXPATHLEN];

  if ((p = getenv ("XENVIRONMENT")) == NULL)
    {
      gethomedir (path);
      strcat (path, ".Xdefaults-");
      gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
      p = path;
    }

  db = XrmGetFileDatabase (p);
  return db;
}

/* Types of values that we can find in a database */

#define XrmStringType "String"	/* String representation */
XrmRepresentation x_rm_string;	/* Quark representation */

/* Load X resources based on the display and a possible -xrm option. */

XrmDatabase
x_load_resources (display, xrm_string, myclass)
     Display *display;
     char *xrm_string, *myclass;
{
  char *xdefs;
  XrmDatabase rdb;
  XrmDatabase db;

  x_rm_string = XrmStringToQuark (XrmStringType);
  XrmInitialize ();
  rdb = XrmGetStringDatabase ("");

  /* Get application system defaults */
  db = get_system_app (myclass);
  if (db != NULL)
    XrmMergeDatabases (db, &rdb);

  /* Get Fallback resources */
  db = get_fallback (display);
  if (db != NULL)
    XrmMergeDatabases (db, &rdb);

  /* Get application user defaults */
  db = get_user_app (myclass);
  if (db != NULL)
    XrmMergeDatabases (db, &rdb);

  /* get User defaults */
  db = get_user_db (display);
  if (db != NULL)
    XrmMergeDatabases (db, &rdb);

  /* Get Environment defaults. */
  db = get_environ_db ();
  if (db != NULL)
    XrmMergeDatabases (db, &rdb);
  
  /* Last, merge in any specification from the command line. */
  if (xrm_string != NULL)
    {
      db = XrmGetStringDatabase (xrm_string);
      if (db != NULL)
	XrmMergeDatabases (db, &rdb);
    }

  return rdb;
}

/* Retrieve the value of the resource specified by NAME with class CLASS
   and of type TYPE from database RDB.  The value is returned in RET_VALUE. */

int
x_get_resource (rdb, name, class, expected_type, ret_value)
     XrmDatabase rdb;
     char *name, *class;
     XrmRepresentation expected_type;
     XrmValue *ret_value;
{
  XrmValue value;
  XrmName namelist[100];
  XrmClass classlist[100];
  XrmRepresentation type;

  XrmStringToNameList(name, namelist);
  XrmStringToClassList(class, classlist);

  if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
      && (type == expected_type))
    {
      if (type == x_rm_string)
	(char *) ret_value->addr = value.addr;
      else
	bcopy (value.addr, ret_value->addr, ret_value->size);

      return value.size;
    }

  return 0;
}

/* Retrieve the string resource specified by NAME with CLASS from
   database RDB. */

char *
x_get_string_resource (rdb, name, class)
     XrmDatabase rdb;
     char *name, *class;
{
  XrmValue value;

  if (x_get_resource (rdb, name, class, x_rm_string, &value))
    return (char *) value.addr;

  return (char *) 0;
}

#ifdef TESTRM
#include <stdio.h>
#include "arg-list.h"

static void
fatal (msg, prog, x1, x2, x3, x4, x5)
    char *msg, *prog;
    int x1, x2, x3, x4, x5;
{
    extern int errno;

    if (errno)
      perror (prog);

    (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
    exit (1);
}

main (argc, argv)
    int argc;
    char **argv;
{
  Display *display;
  char *displayname, *resource_string, *class;
  XrmDatabase xdb;
  List *arg_list, *lp;

  arg_list = arg_listify (argc, argv);

  lp = member ("-d", arg_list);
  if (!NIL (lp))
    displayname = car (cdr (lp));
  else
    displayname = "localhost:0.0";

  lp = member ("-xrm", arg_list);
  if (! NIL (lp))
    resource_string = car (cdr (lp));
  else
    resource_string = (char *) 0;

  lp = member ("-c", arg_list);
  if (! NIL (lp))
    class = car (cdr (lp));
  else
    class = "Emacs";

  free_arglist (arg_list);



  if (!(display = XOpenDisplay (displayname)))
    fatal ("Can't open display '%s'\n", XDisplayName (displayname));

  xdb = x_load_resources (display, resource_string, class);

#if 0
  /* In a real program, you'd want to also do this: */
  display->db = xdb;
#endif

  while (1)
    {
      char line[90];

      printf ("String: ");
      gets (line);
      if (strlen (line))
	{
	  char *value = x_get_string_resource (xdb, line, class);

	  if (value != NULL)
	    printf ("\t%s:  %s\n\n", line, value);
	  else
	    printf ("\tNo Value.\n\n");
	}
      else
	break;
    }
  printf ("\tExit.\n\n");

  XCloseDisplay (display);
}
#endif /* TESTRM */