# HG changeset patch # User Jim Blandy # Date 663102183 0 # Node ID e7abb99c2a38363e3022855a5cc047c640bc7aab # Parent a4e766535a971ef7deaeabcbe102c270b02a4f65 Initial revision diff -r a4e766535a97 -r e7abb99c2a38 src/=xselect.c.old --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/=xselect.c.old Sat Jan 05 19:03:03 1991 +0000 @@ -0,0 +1,666 @@ +/* X Selection processing for emacs + Copyright (C) 1990 Free Software Foundation. + +This file is part of GNU Emacs. + +GNU Emacs 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 1, or (at your option) +any later version. + +GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" +#include "lisp.h" +#include "xterm.h" +#include "screen.h" + +#ifdef HAVE_X11 + +/* Macros for X Selections */ +#define MAX_SELECTION(dpy) (((dpy)->max_request_size << 3) - 100) +#define SELECTION_LENGTH(len,format) ((len) * ((format) >> 3)) + +/* The last 23 bits of the timestamp of the last mouse button event. */ +extern Time mouse_timestamp; + +/* t if a mouse button is depressed. */ + +extern Lisp_Object Vmouse_grabbed; + +/* When emacs became the PRIMARY selection owner. */ +Time x_begin_selection_own; + +/* When emacs became the CLIPBOARD selection owner. */ +Time x_begin_clipboard_own; + +/* The value of the current CLIPBOARD selection. */ +Lisp_Object Vx_clipboard_value; + +/* The value of the current PRIMARY selection. */ +Lisp_Object Vx_selection_value; + +/* Emacs' selection property identifier. */ +Atom Xatom_emacs_selection; + +/* Clipboard selection atom. */ +Atom Xatom_clipboard_selection; + +/* Clipboard atom. */ +Atom Xatom_clipboard; + +/* Atom for indicating incremental selection transfer. */ +Atom Xatom_incremental; + +/* Atom for indicating multiple selection request list */ +Atom Xatom_multiple; + +/* Atom for what targets emacs handles. */ +Atom Xatom_targets; + +/* Atom for indicating timstamp selection request */ +Atom Xatom_timestamp; + +/* Atom requesting we delete our selection. */ +Atom Xatom_delete; + +/* Selection magic. */ +Atom Xatom_insert_selection; + +/* Type of property for INSERT_SELECTION. */ +Atom Xatom_pair; + +/* More selection magic. */ +Atom Xatom_insert_property; + +/* Atom for indicating property type TEXT */ +Atom Xatom_text; + +/* These are to handle incremental selection transfer. */ +Window incr_requestor; +Atom incr_property; +int incr_nbytes; +unsigned char *incr_value; +unsigned char *incr_ptr; + +/* SELECTION OWNER CODE */ + +/* Become the selection owner and make our data the selection value. + If we are already the owner, merely change data and timestamp values. + This avoids generating SelectionClear events for ourselves. */ + +DEFUN ("x-own-selection", Fx_own_selection, Sx_own_selection, + 1, 1, "sStore text for pasting: ", + "Stores string STRING for pasting in another X window.\n\ +This is done with the X11 selection mechanism.") + (string) + register Lisp_Object string; +{ + Window owner_window, selecting_window; + Time event_time; + + CHECK_STRING (string, 0); + + BLOCK_INPUT; + selecting_window = selected_screen->display.x->window_desc; + + if (EQ (Qnil, Vx_selection_value)) /* We are not the owner. */ + { + event_time = mouse_timestamp; + XSetSelectionOwner (x_current_display, XA_PRIMARY, + selecting_window, event_time); + owner_window = XGetSelectionOwner (x_current_display, XA_PRIMARY); + + if (owner_window != selecting_window) + { + UNBLOCK_INPUT; + error ("X error: could not acquire selection ownership"); + } + } + + x_begin_selection_own = event_time; + Vx_selection_value = string; + UNBLOCK_INPUT; + + return Qnil; +} + +/* CLIPBOARD OWNERSHIP */ + +DEFUN ("x-own-clipboard", Fx_own_clipboard, Sx_own_clipboard, + 1, 1, "sCLIPBOARD string: ", + "Assert X clipboard ownership with value STRING.") + (string) + register Lisp_Object string; +{ + Window owner_window, selecting_window; + Time event_time; + + CHECK_STRING (string, 0); + + BLOCK_INPUT; + selecting_window = selected_screen->display.x->window_desc; + + if (EQ (Qnil, Vx_clipboard_value)) + { + event_time = mouse_timestamp; + XSetSelectionOwner (x_current_display, Xatom_clipboard, + selecting_window, event_time); + owner_window = XGetSelectionOwner (x_current_display, Xatom_clipboard); + + if (owner_window != selecting_window) + { + UNBLOCK_INPUT; + error ("X error: could not acquire selection ownership"); + } + } + + x_begin_clipboard_own = event_time; + Vx_clipboard_value = string; + UNBLOCK_INPUT; + + return Qnil; +} + +/* Clear our selection ownership data, as some other client has + become the owner. */ + +void +x_disown_selection (old_owner, selection, changed_owner_time) + Window *old_owner; + Atom selection; + Time changed_owner_time; +{ + struct screen *s = x_window_to_screen (old_owner); + + if (s) /* We are the owner */ + { + if (selection == XA_PRIMARY) + { + x_begin_selection_own = 0; + Vx_selection_value = Qnil; + } + else if (selection == Xatom_clipboard) + { + x_begin_clipboard_own = 0; + Vx_clipboard_value = Qnil; + } + else + abort (); + } + else + abort (); /* Inconsistent state. */ +} + +int x_selection_alloc_error; +int x_converting_selection; + +/* Reply to some client's request for our selection data. Data is + placed in a propery supplied by the requesting window. + + If the data exceeds the maximum amount the server can send, + then prepare to send it incrementally, and reply to the client with + the total size of the data. + + But first, check for all the other crufty stuff we could get. */ + +void +x_answer_selection_request (event) + XSelectionRequestEvent event; +{ + Time emacs_own_time; + Lisp_Object selection_value; + XSelectionEvent evt; + int format = 8; /* We have only byte sized (text) data. */ + + evt.type = SelectionNotify; /* Construct reply event */ + evt.display = event.display; + evt.requestor = event.requestor; + evt.selection = event.selection; + evt.time = event.time; + evt.target = event.target; + + if (event.selection == XA_PRIMARY) + { + emacs_own_time = x_begin_selection_own; + selection_value = Vx_selection_value; + } + else if (event.selection == Xatom_clipboard) + { + emacs_own_time = x_begin_clipboard_own; + selection_value = Vx_clipboard_value; + } + else + abort (); + + if (event.time != CurrentTime + && event.time < emacs_own_time) + evt.property = None; + else + { + if (event.property == None) /* obsolete client */ + evt.property = event.target; + else + evt.property = event.property; + } + + if (event.target == Xatom_targets) /* Send List of target atoms */ + { + } + else if (event.target == Xatom_multiple) /* Recvd list: */ + { + Atom type; + int return_format; + unsigned long items, bytes_left; + unsigned char *data; + int result, i; + + if (event.property == 0 /* 0 == NULL */ + || event.property == None) + return; + + result = XGetWindowProperty (event.display, event.requestor, + event.property, 0L, 10000000L, + True, Xatom_pair, &type, &return_format, + &items, &bytes_left, &data); + + if (result == Success && type == Xatom_pair) + for (i = items; i > 0; i--) + { + /* Convert each element of the list. */ + } + + (void) XSendEvent (x_current_display, evt.requestor, False, + 0L, (XEvent *) &evt); + return; + } + else if (event.target == Xatom_timestamp) /* Send ownership timestamp */ + { + if (! emacs_own_time) + abort (); + + format = 32; + XChangeProperty (evt.display, evt.requestor, evt.property, + evt.target, format, PropModeReplace, + (unsigned char *) &emacs_own_time, format); + return; + } + else if (event.target == Xatom_delete) /* Delete our selection. */ + { + if (EQ (Qnil, selection_value)) + abort (); + + x_disown_selection (event.owner, event.selection, event.time); + + /* Now return property of type NULL, length 0. */ + XChangeProperty (event.display, event.requestor, event.property, + 0, format, PropModeReplace, (unsigned char *) 0, 0); + return; + } + else if (event.target == Xatom_insert_selection) + { + Atom type; + int return_format; + unsigned long items, bytes_left; + unsigned char *data; + int result = XGetWindowProperty (event.display, event.requestor, + event.property, 0L, 10000000L, + True, Xatom_pair, &type, &return_format, + &items, &bytes_left, &data); + if (result == Success && type == Xatom_pair) + { + /* Convert the first atom to (a selection) to the target + indicated by the second atom. */ + } + } + else if (event.target == Xatom_insert_property) + { + Atom type; + int return_format; + unsigned long items, bytes_left; + unsigned char *data; + int result = XGetWindowProperty (event.display, event.requestor, + event.property, 0L, 10000000L, + True, XA_STRING, &type, &return_format, + &items, &bytes_left, &data); + + if (result == Success && type == XA_STRING && return_format == 8) + { + if (event.selection == Xatom_emacs_selection) + Vx_selection_value = make_string (data); + else if (event.selection == Xatom_clipboard_selection) + Vx_clipboard_value = make_string (data); + else + abort (); + } + + return; + } + else if ((event.target == Xatom_text + || event.target == XA_STRING)) + { + int size = XSTRING (selection_value)->size; + unsigned char *data = XSTRING (selection_value)->data; + + if (EQ (Qnil, selection_value)) + abort (); + + /* Place data on requestor window's property. */ + if (SELECTION_LENGTH (size, format) + <= MAX_SELECTION (x_current_display)) + { + x_converting_selection = 1; + XChangeProperty (evt.display, evt.requestor, evt.property, + evt.target, format, PropModeReplace, + data, size); + if (x_selection_alloc_error) + { + x_selection_alloc_error = 0; + abort (); + } + x_converting_selection = 0; + } + else /* Send incrementally */ + { + evt.target = Xatom_incremental; + incr_requestor = evt.requestor; + incr_property = evt.property; + x_converting_selection = 1; + + /* Need to handle Alloc errors on these requests. */ + XChangeProperty (evt.display, incr_requestor, incr_property, + Xatom_incremental, 32, + PropModeReplace, + (unsigned char *) &size, 1); + if (x_selection_alloc_error) + { + x_selection_alloc_error = 0; + x_converting_selection = 0; + abort (); + /* Now abort the send. */ + } + + incr_nbytes = size; + incr_value = data; + incr_ptr = data; + + /* Ask for notification when requestor deletes property. */ + XSelectInput (x_current_display, incr_requestor, PropertyChangeMask); + + /* If we're sending incrementally, perhaps block here + until all sent? */ + } + } + else + evt.property = None; + + /* Don't do this if there was an Alloc error: abort the transfer + by sending None. */ + (void) XSendEvent (x_current_display, evt.requestor, False, + 0L, (XEvent *) &evt); +} + +/* Send an increment of selection data in response to a PropertyNotify event. + The increment is placed in a property on the requestor's window. + When the requestor has processed the increment, it deletes the property, + which sends us another PropertyNotify event. + + When there is no more data to send, we send a zero-length increment. */ + +void +x_send_incremental (event) + XPropertyEvent event; +{ + if (incr_requestor + && incr_requestor == event.window + && incr_property == event.atom + && event.state == PropertyDelete) + { + int format = 8; + int length = MAX_SELECTION (x_current_display); + int bytes_left = (incr_nbytes - (incr_ptr - incr_value)); + + if (length > bytes_left) /* Also sends 0 len when finished. */ + length = bytes_left; + XChangeProperty (x_current_display, incr_requestor, + incr_property, XA_STRING, format, + PropModeAppend, incr_ptr, length); + if (x_selection_alloc_error) + { + x_selection_alloc_error = 0; + x_converting_selection = 0; + /* Abandon the transmission. */ + abort (); + } + if (length > 0) + incr_ptr += length; + else + { /* Everything's sent */ + XSelectInput (x_current_display, incr_requestor, 0L); + incr_requestor = (Window) 0; + incr_property = (Atom) 0; + incr_nbytes = 0; + incr_value = (unsigned char *) 0; + incr_ptr = (unsigned char *) 0; + x_converting_selection = 0; + } + } +} + +/* SELECTION REQUESTOR CODE */ + +/* Predicate function used to match a requested event. */ + +Bool +XCheckSelectionEvent (dpy, event, window) + Display *dpy; + XEvent *event; + char *window; +{ + if (event->type == SelectionNotify) + if (event->xselection.requestor == (Window) window) + return True; + + return False; +} + +/* Request the selection value from the owner. If we are the owner, + simply return our selection value. If we are not the owner, this + will block until all of the data has arrived. */ + +DEFUN ("x-get-selection", Fx_get_selection, Sx_get_selection, 0, 0, 0, + "Return text selected from some X window.\n\ +This is done with the X11 selection mechanism.") + () +{ + XEvent event; + Lisp_Object val; + Time requestor_time; /* Timestamp of selection request. */ + Window requestor_window; + + if (!EQ (Qnil, Vx_selection_value)) /* We are the owner */ + return Vx_selection_value; + + BLOCK_INPUT; + requestor_time = mouse_timestamp; + requestor_window = selected_screen->display.x->window_desc; + XConvertSelection (x_current_display, XA_PRIMARY, XA_STRING, + Xatom_emacs_selection, requestor_window, requestor_time); + XIfEvent (x_current_display, + &event, + XCheckSelectionEvent, + (char *) requestor_window); + val = x_selection_arrival (&event, requestor_window, requestor_time); + UNBLOCK_INPUT; + + return val; +} + +/* Request the clipboard contents from its owner. If we are the owner, + simply return the clipboard string. */ + +DEFUN ("x-get-clipboard", Fx_get_clipboard, Sx_get_clipboard, 0, 0, 0, + "Return text pasted to the clipboard.\n\ +This is done with the X11 selection mechanism.") + () +{ + XEvent event; + Lisp_Object val; + Time requestor_time; /* Timestamp of selection request. */ + Window requestor_window; + + if (!EQ (Qnil, Vx_clipboard_value)) /* We are the owner */ + return Vx_selection_value; + + BLOCK_INPUT; + requestor_time = mouse_timestamp; + requestor_window = selected_screen->display.x->window_desc; + XConvertSelection (x_current_display, Xatom_clipboard, XA_STRING, + Xatom_clipboard_selection, + requestor_window, requestor_time); + XIfEvent (x_current_display, + &event, + XCheckSelectionEvent, + (char *) requestor_window); + val = x_selection_arrival (&event, requestor_window, requestor_time); + UNBLOCK_INPUT; + + return val; +} + +Lisp_Object +x_selection_arrival (event, requestor_window, requestor_time) + register XSelectionEvent *event; + Window requestor_window; + Time requestor_time; +{ + int result; + Atom type, selection; + int format; + unsigned long items; + unsigned long bytes_left; + unsigned char *data = 0; + int offset = 0; + + if (event->selection == XA_PRIMARY) + selection = Xatom_emacs_selection; + else if (event->selection == Xatom_clipboard) + selection = Xatom_clipboard_selection; + else + abort (); + + if (event->requestor == requestor_window + && event->time == requestor_time + && event->property != None) + if (event->target != Xatom_incremental) + { + unsigned char *return_string = + (unsigned char *) alloca (MAX_SELECTION (x_current_display)); + + do + { + result = XGetWindowProperty (x_current_display, + requestor_window, + event->property, 0L, + 10000000L, True, XA_STRING, + &type, &format, &items, + &bytes_left, &data); + if (result == Success && type == XA_STRING && format == 8 + && offset < MAX_SELECTION (x_current_display)) + { + bcopy (data, return_string + offset, items); + offset += items; + } + XFree ((char *) data); + } + while (bytes_left); + + return make_string (return_string, offset); + } + else /* Prepare incremental transfer. */ + { + unsigned char *increment_value; + unsigned char *increment_ptr; + int total_size; + int *increment_nbytes = 0; + + result = XGetWindowProperty (x_current_display, requestor_window, + selection, 0L, 10000000L, False, + event->property, &type, &format, + &items, &bytes_left, + (unsigned char **) &increment_nbytes); + if (result == Success) + { + XPropertyEvent property_event; + + total_size = *increment_nbytes; + increment_value = (unsigned char *) alloca (total_size); + increment_ptr = increment_value; + + XDeleteProperty (x_current_display, event->requestor, + event->property); + XFlush (x_current_display); + XFree ((char *) increment_nbytes); + + do + { /* NOTE: this blocks. */ + XWindowEvent (x_current_display, requestor_window, + PropertyChangeMask, + (XEvent *) &property_event); + + if (property_event.atom == selection + && property_event.state == PropertyNewValue) + do + { + result = XGetWindowProperty (x_current_display, + requestor_window, + selection, 0L, + 10000000L, True, + AnyPropertyType, + &type, &format, + &items, &bytes_left, + &data); + if (result == Success && type == XA_STRING + && format == 8) + { + bcopy (data, increment_ptr, items); + increment_ptr += items; + } + } + while (bytes_left); + + } + while (increment_ptr < (increment_value + total_size)); + + return make_string (increment_value, + (increment_ptr - increment_value)); + } + } + + return Qnil; +} + +void +syms_of_xselect () +{ + DEFVAR_LISP ("x-selection-value", &Vx_selection_value, + "The value of emacs' last cut-string."); + Vx_selection_value = Qnil; + + DEFVAR_LISP ("x-clipboard-value", &Vx_clipboard_value, + "The string emacs last sent to the clipboard."); + Vx_clipboard_value = Qnil; + + defsubr (&Sx_own_selection); + defsubr (&Sx_get_selection); + defsubr (&Sx_own_clipboard); + defsubr (&Sx_get_clipboard); +} +#endif /* X11 */ diff -r a4e766535a97 -r e7abb99c2a38 src/xrdb.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xrdb.c Sat Jan 05 19:03:03 1991 +0000 @@ -0,0 +1,477 @@ +/* Deal with the X Resource Manager. + Copyright (C) 1990 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 1, 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef emacs +#include "config.h" +#endif + +extern char *getenv (); +extern int 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; + register char string[MAXPATHLEN]; + + while (*s) + { + p = s; + + while (*p && *p != ':') + p++; + + if (*p == ':' && *(p + 1) == ':') + { + 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; + + 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 +#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 */