home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / emacs-19.16 / src / xrdb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-21  |  10.8 KB  |  539 lines

  1. /* Deal with the X Resource Manager.
  2.    Copyright (C) 1990, 1993 Free Software Foundation.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by jla, 4/90 */
  19.  
  20. #ifdef emacs
  21. #include "config.h"
  22. #endif
  23.  
  24. #if 1 /* I'd really appreciate it if this code could go away...  -JimB */
  25. /* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */
  26. #ifdef USG5
  27. #define SYSV
  28. #include <unistd.h>
  29. #endif /* USG5 */
  30.  
  31. #endif /* 1 */
  32.  
  33. /* This should be included before the X include files; otherwise, we get
  34.    warnings about redefining NULL under BSD 4.3.  */
  35. #include <sys/param.h>
  36.  
  37. #include <X11/Xlib.h>
  38. #include <X11/Xatom.h>
  39. #if 0
  40. #include <X11/Xos.h>
  41. #endif
  42. #include <X11/X.h>
  43. #include <X11/Xutil.h>
  44. #include <X11/Xresource.h>
  45. #ifdef VMS
  46. #include "vms-pwd.h"
  47. #else
  48. #include <pwd.h>
  49. #endif
  50. #include <sys/stat.h>
  51.  
  52. #ifndef MAXPATHLEN
  53. #define MAXPATHLEN    256
  54. #endif
  55.  
  56. extern char *getenv ();
  57.  
  58. /* This does cause trouble on AIX.  I'm going to take the comment at
  59.    face value.  */
  60. #if 0
  61. extern short getuid ();        /* If this causes portability problems,
  62.                    I think we should just delete it; it'll
  63.                    default to `int' anyway.  */
  64. #endif
  65.  
  66. #ifdef __bsdi__
  67. extern struct passwd *getpwuid (uid_t);
  68. extern struct passwd *getpwnam (const char *);
  69. #else
  70. extern struct passwd *getpwuid ();
  71. extern struct passwd *getpwnam ();
  72. #endif
  73.  
  74. static char *
  75. gethomedir (dirname)
  76.      char *dirname;
  77. {
  78.   int uid;
  79.   struct passwd *pw;
  80.   char *ptr;
  81.  
  82.   if ((ptr = getenv ("HOME")) == NULL)
  83.     {
  84.       if ((ptr = getenv ("USER")) != NULL)
  85.     pw = getpwnam (ptr);
  86.       else
  87.     {
  88.       uid = getuid ();
  89.       pw = getpwuid (uid);
  90.     }
  91.       if (pw)
  92.     ptr = pw->pw_dir;
  93.       else
  94.     {
  95.       ptr = NULL;
  96.       *dirname = '\0';
  97.     }
  98.     }
  99.  
  100.   if (ptr != NULL) 
  101.     strcpy (dirname, ptr);
  102.  
  103.   dirname += strlen (dirname);
  104.   *dirname = '/';
  105.   dirname++;
  106.   *dirname = '\0';
  107.  
  108.   return dirname;
  109. }
  110.  
  111. static int
  112. file_p (path)
  113.      char *path;
  114. {
  115.   struct stat status;
  116.  
  117.   return (access (path, 4) == 0            /* exists and is readable */
  118.       && stat (path, &status) == 0        /* get the status */
  119.       && (status.st_mode & S_IFDIR) == 0);    /* not a directory */
  120. }
  121.  
  122. #if 0
  123. #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
  124. #endif
  125.  
  126. /* Isn't this just disgusting? */
  127.  
  128. #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"
  129.  
  130. static int
  131. decode_magic (string, file, return_path)
  132.      char *string, *file, *return_path;
  133. {
  134.   char *p = string;
  135.   char *t = return_path;
  136.  
  137.   while (*p)
  138.     {
  139.       if (*p == '%')
  140.     switch (*++p)
  141.       {
  142.       case '%':
  143.         *t++ = '%';
  144.         p++;
  145.         break;
  146.  
  147.       case 'N':
  148.       case 'T':
  149.       case 'S':
  150.       case 'L':
  151.       case 'l':
  152.       case 't':
  153.       case 'c':
  154.       default:
  155.         p++;
  156.         if (*t == '/' && *p == '/')
  157.           p++;
  158.         break;
  159.       }
  160.       else
  161.     *t++ = *p++;
  162.     }
  163.   *t = '\0';
  164.   strcat (return_path, file);
  165.  
  166.   if (file_p (return_path))
  167.     return 1;
  168.  
  169.   return_path[0] = '\0';
  170.   return 0;
  171. }
  172.  
  173. static int
  174. magic_searchpath_decoder (incantation_string, file, return_path)
  175.      char *incantation_string, *return_path, *file;
  176. {
  177.   register char *s = incantation_string;
  178.   register char *p;
  179.  
  180.   /* Must be big enough for "%N%S".  */
  181.   register int string_size = MAXPATHLEN;
  182.   register char *string = (char *) alloca (string_size * sizeof (*string));
  183.  
  184.   while (*s)
  185.     {
  186.       p = s;
  187.  
  188.       while (*p && *p != ':')
  189.     p++;
  190.  
  191.       if (*p == ':' && *(p + 1) == ':')
  192.     {
  193.       /* We know string is big enough for this.  */
  194.       bcopy ("%N%S", string, 5);
  195.       if (decode_magic (string, file, return_path))
  196.         return 1;
  197.  
  198.       s = p + 1;
  199.       continue;
  200.     }
  201.  
  202.       if (p > s)
  203.     {
  204.       int len = p - s;
  205.  
  206.       if (string_size < len+1)
  207.         {
  208.           string_size = 2 * len;
  209.           string = (char *) alloca (string_size * sizeof (*string));
  210.         }
  211.       bcopy (s, string, len);
  212.       string[len] = '\0';
  213.       if (decode_magic (string, file, return_path))
  214.         return 1;
  215.     }
  216.  
  217.       if (p && *p != 0)
  218.     s = p + 1;
  219.       else
  220.     return 0;
  221.     }
  222.  
  223.   return 0;
  224. }
  225.  
  226. static XrmDatabase
  227. get_system_app (class)
  228.      char *class;
  229. {
  230.   XrmDatabase db;
  231.   char path[MAXPATHLEN];
  232.   char *p;
  233.  
  234.   if ((p = getenv ("XFILESEARCHPATH")) == NULL)
  235.     p = X_DEFAULT_SEARCH_PATH;
  236.  
  237.   if (! magic_searchpath_decoder (p, class, path))
  238.     return NULL;
  239.  
  240.   db = XrmGetFileDatabase (path);
  241.   return db;
  242. }
  243.  
  244. static XrmDatabase
  245. get_fallback (display)
  246.      Display *display;
  247. {
  248.   XrmDatabase db;
  249.  
  250.   return NULL;
  251. }
  252.  
  253. static XrmDatabase
  254. get_user_app (class)
  255.      char *class;
  256. {
  257.   XrmDatabase db;
  258.   char *magic_path;
  259.   char path[MAXPATHLEN];
  260.  
  261.   if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
  262.     {
  263.       char homedir[MAXPATHLEN];
  264.       char *default_magic;
  265.       char *p;
  266.  
  267.       gethomedir (homedir);
  268.  
  269.       if ((p = getenv ("XAPPLRESDIR")) == NULL)
  270.     {
  271.       default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
  272.       magic_path = (char *) alloca ((3 * strlen (homedir))
  273.                     + strlen (default_magic));
  274.       sprintf (magic_path, default_magic, homedir, homedir, homedir);
  275.     }
  276.       else
  277.     {
  278.       default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
  279.       magic_path = (char *) alloca ((3 * strlen (p))
  280.                     + strlen (default_magic)
  281.                     + strlen (homedir));
  282.       sprintf (magic_path, default_magic, p, p, p, homedir);
  283.     }
  284.     }
  285.  
  286.   if (! magic_searchpath_decoder (magic_path, class, path))
  287.     return NULL;
  288.   
  289.   db = XrmGetFileDatabase (path);
  290.   return db;
  291. }
  292.  
  293. static XrmDatabase
  294. get_user_db (display)
  295.      Display *display;
  296. {
  297.   XrmDatabase db;
  298.   char *xdefs;
  299.  
  300. #ifdef PBaseSize        /* Cheap way to test for X11R4 or later.  */
  301.   xdefs = XResourceManagerString (display);
  302. #else
  303.   xdefs = display->xdefaults;
  304. #endif
  305.  
  306.   if (xdefs != NULL)
  307.     db = XrmGetStringDatabase (xdefs);
  308.   else
  309.     {
  310.       char xdefault[MAXPATHLEN];
  311.  
  312.       gethomedir (xdefault);
  313.       strcat (xdefault, ".Xdefaults");
  314.       db = XrmGetFileDatabase (xdefault);
  315.     }
  316.  
  317. #ifdef XlibSpecificationRelease
  318. #if XlibSpecificationRelease >= 5
  319.   /* Get the screen-specific resources too.  */
  320.   xdefs = XScreenResourceString (DefaultScreenOfDisplay (display));
  321.   if (xdefs != NULL)
  322.     {
  323.       XrmMergeDatabases (XrmGetStringDatabase (xdefs), &db);
  324.       XFree (xdefs);
  325.     }
  326. #endif
  327. #endif
  328.  
  329.   return db;
  330. }
  331.  
  332. static XrmDatabase
  333. get_environ_db ()
  334. {
  335.   XrmDatabase db;
  336.   char *p;
  337.   char path[MAXPATHLEN];
  338.  
  339.   if ((p = getenv ("XENVIRONMENT")) == NULL)
  340.     {
  341.       gethomedir (path);
  342.       strcat (path, ".Xdefaults-");
  343.       gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
  344.       p = path;
  345.     }
  346.  
  347.   db = XrmGetFileDatabase (p);
  348.   return db;
  349. }
  350.  
  351. /* Types of values that we can find in a database */
  352.  
  353. #define XrmStringType "String"    /* String representation */
  354. XrmRepresentation x_rm_string;    /* Quark representation */
  355.  
  356. /* Load X resources based on the display and a possible -xrm option. */
  357.  
  358. XrmDatabase
  359. x_load_resources (display, xrm_string, myclass)
  360.      Display *display;
  361.      char *xrm_string, *myclass;
  362. {
  363.   char *xdefs;
  364.   XrmDatabase rdb;
  365.   XrmDatabase db;
  366.  
  367.   x_rm_string = XrmStringToQuark (XrmStringType);
  368.   XrmInitialize ();
  369.   rdb = XrmGetStringDatabase ("");
  370.  
  371.   /* Get application system defaults */
  372.   db = get_system_app (myclass);
  373.   if (db != NULL)
  374.     XrmMergeDatabases (db, &rdb);
  375.  
  376.   /* Get Fallback resources */
  377.   db = get_fallback (display);
  378.   if (db != NULL)
  379.     XrmMergeDatabases (db, &rdb);
  380.  
  381.   /* Get application user defaults */
  382.   db = get_user_app (myclass);
  383.   if (db != NULL)
  384.     XrmMergeDatabases (db, &rdb);
  385.  
  386.   /* get User defaults */
  387.   db = get_user_db (display);
  388.   if (db != NULL)
  389.     XrmMergeDatabases (db, &rdb);
  390.  
  391.   /* Get Environment defaults. */
  392.   db = get_environ_db ();
  393.   if (db != NULL)
  394.     XrmMergeDatabases (db, &rdb);
  395.   
  396.   /* Last, merge in any specification from the command line. */
  397.   if (xrm_string != NULL)
  398.     {
  399.       db = XrmGetStringDatabase (xrm_string);
  400.       if (db != NULL)
  401.     XrmMergeDatabases (db, &rdb);
  402.     }
  403.  
  404.   return rdb;
  405. }
  406.  
  407. /* Retrieve the value of the resource specified by NAME with class CLASS
  408.    and of type TYPE from database RDB.  The value is returned in RET_VALUE. */
  409.  
  410. int
  411. x_get_resource (rdb, name, class, expected_type, ret_value)
  412.      XrmDatabase rdb;
  413.      char *name, *class;
  414.      XrmRepresentation expected_type;
  415.      XrmValue *ret_value;
  416. {
  417.   XrmValue value;
  418.   XrmName namelist[100];
  419.   XrmClass classlist[100];
  420.   XrmRepresentation type;
  421.  
  422.   XrmStringToNameList(name, namelist);
  423.   XrmStringToClassList(class, classlist);
  424.  
  425.   if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
  426.       && (type == expected_type))
  427.     {
  428.       if (type == x_rm_string)
  429.     ret_value->addr = (char *) value.addr;
  430.       else
  431.     bcopy (value.addr, ret_value->addr, ret_value->size);
  432.  
  433.       return value.size;
  434.     }
  435.  
  436.   return 0;
  437. }
  438.  
  439. /* Retrieve the string resource specified by NAME with CLASS from
  440.    database RDB. */
  441.  
  442. char *
  443. x_get_string_resource (rdb, name, class)
  444.      XrmDatabase rdb;
  445.      char *name, *class;
  446. {
  447.   XrmValue value;
  448.  
  449.   if (x_get_resource (rdb, name, class, x_rm_string, &value))
  450.     return (char *) value.addr;
  451.  
  452.   return (char *) 0;
  453. }
  454.  
  455. #ifdef TESTRM
  456. #include <stdio.h>
  457. #include "arg-list.h"
  458.  
  459. static void
  460. fatal (msg, prog, x1, x2, x3, x4, x5)
  461.     char *msg, *prog;
  462.     int x1, x2, x3, x4, x5;
  463. {
  464.     extern int errno;
  465.  
  466.     if (errno)
  467.       perror (prog);
  468.  
  469.     (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
  470.     exit (1);
  471. }
  472.  
  473. main (argc, argv)
  474.     int argc;
  475.     char **argv;
  476. {
  477.   Display *display;
  478.   char *displayname, *resource_string, *class;
  479.   XrmDatabase xdb;
  480.   List *arg_list, *lp;
  481.  
  482.   arg_list = arg_listify (argc, argv);
  483.  
  484.   lp = member ("-d", arg_list);
  485.   if (!NIL (lp))
  486.     displayname = car (cdr (lp));
  487.   else
  488.     displayname = "localhost:0.0";
  489.  
  490.   lp = member ("-xrm", arg_list);
  491.   if (! NIL (lp))
  492.     resource_string = car (cdr (lp));
  493.   else
  494.     resource_string = (char *) 0;
  495.  
  496.   lp = member ("-c", arg_list);
  497.   if (! NIL (lp))
  498.     class = car (cdr (lp));
  499.   else
  500.     class = "Emacs";
  501.  
  502.   free_arglist (arg_list);
  503.  
  504.  
  505.  
  506.   if (!(display = XOpenDisplay (displayname)))
  507.     fatal ("Can't open display '%s'\n", XDisplayName (displayname));
  508.  
  509.   xdb = x_load_resources (display, resource_string, class);
  510.  
  511. #if 0
  512.   /* In a real program, you'd want to also do this: */
  513.   display->db = xdb;
  514. #endif
  515.  
  516.   while (1)
  517.     {
  518.       char line[90];
  519.  
  520.       printf ("String: ");
  521.       gets (line);
  522.       if (strlen (line))
  523.     {
  524.       char *value = x_get_string_resource (xdb, line, class);
  525.  
  526.       if (value != NULL)
  527.         printf ("\t%s:  %s\n\n", line, value);
  528.       else
  529.         printf ("\tNo Value.\n\n");
  530.     }
  531.       else
  532.     break;
  533.     }
  534.   printf ("\tExit.\n\n");
  535.  
  536.   XCloseDisplay (display);
  537. }
  538. #endif /* TESTRM */
  539.