unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [RFC] Using a display_info union instead of a typedef Display_Info
@ 2019-04-12 16:50 Alex Gramiak
  2019-04-12 17:06 ` Alex Gramiak
  2019-04-12 17:55 ` Eli Zaretskii
  0 siblings, 2 replies; 12+ messages in thread
From: Alex Gramiak @ 2019-04-12 16:50 UTC (permalink / raw)
  To: emacs-devel; +Cc: Eli Zaretskii, Stefan Monnier

[-- Attachment #1: Type: text/plain, Size: 1180 bytes --]

In the process of doing the bulk rename of non-X x_* procedures, the
issue of using multiple display types independently has come up in the
discussions. It has now also come up in generalizing of the GUI resource
database part of frame.c. I created a new topic here to discuss this
work as it involves introducing a (significant in the long-term) new
global type.

The jist of the attached patch is that generalizes x_get_string_resource
into a terminal hook, and in the process changes several procedures to
use union display_info instead of the typedef Display_Info, which is
display system-dependent. One uses DISPLAY_INFO (dpyinfo) to access the
common structure of the union, and there are macros
U_DISPLAY_INFO_<suffix> to convert from a specific display_info to the
union. There is also a procedure gui_frame_display_info, that grabs a
window system display_info from a frame.

I've also included a new procedure decode_display_info, which takes the
role of the display system-dependent check_x_display_info. I've left out
the removal of the check_x_display_info since I'm not sure if this patch
will be accepted. I've also left out NS support until a later stage.

WDYT?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: union display_info --]
[-- Type: text/x-patch, Size: 56562 bytes --]

From 1f60b0a69282d52528e9e43d83c7e205fa18f86a Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Fri, 12 Apr 2019 00:09:21 -0600
Subject: [PATCH] Generalize x_get_arg to multiple display types

* src/termhooks.c (display_info): Move the union to global scope.
(get_string_resource_hook): New terminal hook.

* src/terminal.c (decode_display_info): New procedure.

* src/dispnew.c (gui_initial_output_method): New global variable used
when the selected frame is not a graphical frame.

* src/frame.c (xrdb_get_resource): Rename to display_x_get_resource
and remove the old definition of that name. Use the display_info union
instead of a typedef.
(x_get_arg): Rename to gui_display_get_arg.

* src/frame.c:
* src/xfns.c:
* src/w32fns.c: Rename x_get_arg to gui_display_get_arg.

* src/xterm.c (x_create_terminal):
* src/w32term.c (w32_create_terminal):
* src/nsterm.c (ns_create_terminal): Set terminal
get_string_resource_hook.

* srx/xterm.c (x_get_string_resource): Change first argument type to
  void*.

* src/w32reg.c (w32_get_string_resource): Rename to
w32_get_string_resource_1.
(x_get_string_resource): Rename to w32_get_string_resource. Change
first argument type to void*.

* src/nsterm.c (x_get_string_resource): Rename to
  ns_get_string_resource. Change first argument type to void*.
---
 src/dispextern.h |  12 +++--
 src/dispnew.c    |   8 ++++
 src/frame.c      |  95 ++++++++++++++++++++++++--------------
 src/frame.h      |   2 +-
 src/nsfns.m      |  12 ++---
 src/nsgui.h      |   3 --
 src/nsterm.h     |  19 +++++++-
 src/nsterm.m     |   1 +
 src/termchar.h   |   6 +--
 src/termhooks.h  |  36 ++++++++++++---
 src/terminal.c   |  71 +++++++++++++++++++++++++++++
 src/w32fns.c     | 116 +++++++++++++++++++++++++++++------------------
 src/w32gui.h     |   2 -
 src/w32reg.c     |  16 +++----
 src/w32term.c    |   1 +
 src/w32term.h    |  18 +++++++-
 src/xfaces.c     |   2 +-
 src/xfns.c       |  91 +++++++++++++++++++++++--------------
 src/xrdb.c       |  18 ++++----
 src/xterm.c      |  22 ++++++---
 src/xterm.h      |  11 +++++
 21 files changed, 398 insertions(+), 164 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 1a53656353..79a97f6d6d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -23,6 +23,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #define DISPEXTERN_H_INCLUDED
 
 #include "character.h"
+#include "termhooks.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -3539,6 +3540,9 @@ extern void insert_glyphs (struct frame *, struct glyph *, int);
 extern void delete_glyphs (struct frame *, int);
 extern void ins_del_lines (struct frame *, int, int);
 
+extern union display_info decode_display_info (Lisp_Object object,
+                                               enum output_method method);
+
 extern struct terminal *init_initial_terminal (void);
 
 
@@ -3586,9 +3590,9 @@ enum resource_types
 };
 
 extern Display_Info *check_x_display_info (Lisp_Object);
-extern Lisp_Object x_get_arg (Display_Info *, Lisp_Object,
-                              Lisp_Object, const char *, const char *class,
-                              enum resource_types);
+extern Lisp_Object gui_display_get_arg (union display_info, Lisp_Object,
+                                        Lisp_Object, const char *,
+                                        const char *, enum resource_types);
 extern Lisp_Object x_frame_get_and_record_arg (struct frame *, Lisp_Object,
                                                Lisp_Object,
 					       const char *, const char *,
@@ -3597,8 +3601,6 @@ extern Lisp_Object x_default_parameter (struct frame *, Lisp_Object,
                                         Lisp_Object, Lisp_Object,
                                         const char *, const char *,
                                         enum resource_types);
-extern char *x_get_string_resource (XrmDatabase, const char *,
-				    const char *);
 
 #ifndef HAVE_NS /* These both used on W32 and X only.  */
 extern bool x_mouse_grabbed (Display_Info *);
diff --git a/src/dispnew.c b/src/dispnew.c
index ccb08ec1b9..ae57e12062 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5985,6 +5985,10 @@ pass nil for VARIABLE.  */)
 			    Initialization
 ***********************************************************************/
 
+/* For the initial terminal, use this output method for
+   device-dependent procedures.  */
+enum output_method gui_initial_output_method;
+
 static void
 init_faces_initial (void)
 {
@@ -6017,6 +6021,7 @@ init_display_interactive (void)
   /* Now is the time to initialize this; it's used by init_sys_modes
      during startup.  */
   Vinitial_window_system = Qnil;
+  gui_initial_output_method = output_nothing;
 
   /* SIGWINCH needs to be handled no matter what display we start
      with.  Otherwise newly opened tty frames will not resize
@@ -6074,6 +6079,7 @@ init_display_interactive (void)
   if (!inhibit_window_system && display_arg)
     {
       Vinitial_window_system = Qx;
+      gui_initial_output_method = output_x_window;
 #ifdef HAVE_X11
       Vwindow_system_version = make_fixnum (11);
 #endif
@@ -6091,6 +6097,7 @@ init_display_interactive (void)
   if (!inhibit_window_system)
     {
       Vinitial_window_system = Qw32;
+      gui_initial_output_method = output_w32;
       Vwindow_system_version = make_fixnum (1);
       return;
     }
@@ -6100,6 +6107,7 @@ init_display_interactive (void)
   if (!inhibit_window_system && !will_dump_p ())
     {
       Vinitial_window_system = Qns;
+      gui_initial_output_method = output_ns;
       Vwindow_system_version = make_fixnum (10);
       return;
     }
diff --git a/src/frame.c b/src/frame.c
index 192ef4244f..371d95c064 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3719,6 +3719,35 @@ static const struct frame_parm_table frame_parms[] =
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+static union display_info
+gui_frame_display_info (struct frame *f)
+{
+  union display_info info;
+
+  switch (f->output_method)
+    {
+#ifdef HAVE_X_WINDOWS
+    case output_x_window:
+      info.x = f->output_data.x->display_info;
+      break;
+#endif
+#ifdef HAVE_NTGUI
+    case output_w32:
+      info.w32 = f->output_data.w32->display_info;
+      break;
+#endif
+#ifdef HAVE_NS
+    case output_ns:
+      info.ns = f->output_data.ns->display_info;
+      break;
+#endif
+    default:
+      error ("Non-graphical window system frame specified");
+    }
+
+  return info;
+}
+
 /* Enumeration type for switch in frame_float.  */
 enum frame_float_type
 {
@@ -4928,8 +4957,10 @@ validate_x_resource_name (void)
 /* Get specified attribute from resource database RDB.
    See Fx_get_resource below for other parameters.  */
 
-static Lisp_Object
-xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
+Lisp_Object
+display_x_get_resource (union display_info dpyinfo, Lisp_Object attribute,
+                        Lisp_Object class, Lisp_Object component,
+                        Lisp_Object subclass)
 {
   CHECK_STRING (attribute);
   CHECK_STRING (class);
@@ -4982,7 +5013,11 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
   *nz++ = '.';
   lispstpcpy (nz, attribute);
 
-  char *value = x_get_string_resource (rdb, name_key, class_key);
+  void *rdb = &DISPLAY_INFO (dpyinfo)->xrdb;
+  const char *value =
+    DISPLAY_INFO(dpyinfo)->terminal->get_string_resource_hook (rdb,
+                                                               name_key,
+                                                               class_key);
   SAFE_FREE();
 
   if (value && *value)
@@ -4991,7 +5026,6 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
     return Qnil;
 }
 
-
 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
        doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
@@ -5007,19 +5041,9 @@ and the class is `Emacs.CLASS.SUBCLASS'.  */)
 {
   check_window_system (NULL);
 
-  return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
-			    attribute, class, component, subclass);
-}
-
-/* Get an X resource, like Fx_get_resource, but for display DPYINFO.  */
-
-Lisp_Object
-display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
-			Lisp_Object class, Lisp_Object component,
-			Lisp_Object subclass)
-{
-  return xrdb_get_resource (dpyinfo->xrdb,
-			    attribute, class, component, subclass);
+  return display_x_get_resource (decode_display_info
+                                 (Qnil, gui_initial_output_method),
+                                 attribute, class, component, subclass);
 }
 
 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
@@ -5045,7 +5069,7 @@ x_get_resource_string (const char *attribute, const char *class)
   esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
-  result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
+  result = x_get_string_resource (&FRAME_DISPLAY_INFO (sf)->xrdb,
 				  name_key, class_key);
   SAFE_FREE ();
   return result;
@@ -5060,12 +5084,14 @@ x_get_resource_string (const char *attribute, const char *class)
    Convert the resource to the type specified by desired_type.
 
    If no default is specified, return Qunbound.  If you call
-   x_get_arg, make sure you deal with Qunbound in a reasonable way,
-   and don't let it get stored in any Lisp-visible variables!  */
+   gui_display_get_arg, make sure you deal with Qunbound in a
+   reasonable way, and don't let it get stored in any Lisp-visible
+   variables!  */
 
 Lisp_Object
-x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
-	   const char *attribute, const char *class, enum resource_types type)
+gui_display_get_arg (union display_info dpyinfo, Lisp_Object alist,
+                     Lisp_Object param, const char *attribute,
+                     const char *class, enum resource_types type)
 {
   Lisp_Object tem;
 
@@ -5091,7 +5117,7 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
      look in the X resources.  */
   if (NILP (tem))
     {
-      if (attribute && dpyinfo)
+      if (attribute && DISPLAY_INFO (dpyinfo))
 	{
 	  AUTO_STRING (at, attribute);
 	  AUTO_STRING (cl, class);
@@ -5166,8 +5192,8 @@ x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
 		 const char *attribute, const char *class,
 		 enum resource_types type)
 {
-  return x_get_arg (FRAME_DISPLAY_INFO (f),
-		    alist, param, attribute, class, type);
+  return gui_display_get_arg (gui_frame_display_info (f),
+                              alist, param, attribute, class, type);
 }
 
 /* Like x_frame_get_arg, but also record the value in f->param_alist.  */
@@ -5180,8 +5206,8 @@ x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
 {
   Lisp_Object value;
 
-  value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
-		     attribute, class, type);
+  value = gui_display_get_arg (gui_frame_display_info (f), alist, param,
+                               attribute, class, type);
   if (! NILP (value) && ! EQ (value, Qunbound))
     store_frame_param (f, param, value);
 
@@ -5385,7 +5411,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
 {
   Lisp_Object height, width, user_size, top, left, user_position;
   long window_prompting = 0;
-  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
+  union display_info dpyinfo = gui_frame_display_info (f);
   int parent_done = -1, outer_done = -1;
 
   /* Default values if we fall through.
@@ -5435,8 +5461,8 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
      override what we specify below.  */
   f->new_width = f->new_height = 0;
 
-  height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
-  width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+  height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+  width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
   if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
     {
       if (!EQ (width, Qunbound))
@@ -5513,16 +5539,17 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
 	    }
 	}
 
-      user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+      user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
       if (!NILP (user_size) && !EQ (user_size, Qunbound))
 	window_prompting |= USSize;
       else
 	window_prompting |= PSize;
     }
 
-  top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
-  left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
-  user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+  top = gui_display_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+  left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+  user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0,
+                                       RES_TYPE_NUMBER);
   if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
     {
       if (EQ (top, Qminus))
diff --git a/src/frame.h b/src/frame.h
index ec8f61465f..499ed1a51d 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1578,7 +1578,7 @@ extern void x_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
 
 extern void validate_x_resource_name (void);
 
-extern Lisp_Object display_x_get_resource (Display_Info *,
+extern Lisp_Object display_x_get_resource (union display_info,
 					   Lisp_Object attribute,
 					   Lisp_Object class,
 					   Lisp_Object component,
diff --git a/src/nsfns.m b/src/nsfns.m
index ee7598a1c7..5968b38e28 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2248,8 +2248,8 @@ Frames are listed from topmost (first) to bottommost (last).  */)
 }
 
 /* Terms implement this instead of x-get-resource directly.  */
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+ns_get_string_resource (void *_rdb, const char *name, const char *class)
 {
   /* remove appname prefix; TODO: allow for !="Emacs" */
   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
@@ -2261,10 +2261,10 @@ Frames are listed from topmost (first) to bottommost (last).  */)
     return NULL;
 
   res = ns_get_defaults_value (toCheck);
-  return (char *) (!res ? NULL
-		   : !c_strncasecmp (res, "YES", 3) ? "true"
-		   : !c_strncasecmp (res, "NO", 2) ? "false"
-		   : res);
+  return (const char *) (!res ? NULL
+                         : !c_strncasecmp (res, "YES", 3) ? "true"
+                         : !c_strncasecmp (res, "NO", 2) ? "false"
+                         : res);
 }
 
 
diff --git a/src/nsgui.h b/src/nsgui.h
index c857d77d9c..c147f4dec4 100644
--- a/src/nsgui.h
+++ b/src/nsgui.h
@@ -117,9 +117,6 @@ typedef void * Color;
 typedef int Window;
 typedef int Display;
 
-/* Xism */
-typedef Lisp_Object XrmDatabase;
-
 
 /* Some sort of attempt to normalize rectangle handling.  Seems a bit
    much for what is accomplished.  */
diff --git a/src/nsterm.h b/src/nsterm.h
index 78ce608554..8b6d6dfd17 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -25,6 +25,9 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "sysselect.h"
 
 #ifdef HAVE_NS
+
+INLINE_HEADER_BEGIN
+
 #ifdef __OBJC__
 
 /* CGFloat on GNUstep may be 4 or 8 byte, but functions expect float* for some
@@ -869,7 +872,7 @@ struct ns_display_info
   Window root_window;
 
   /* Xism */
-  XrmDatabase xrdb;
+  Lisp_Object xrdb;
 
   /* The cursor to use for vertical scroll bars.  */
   Cursor vertical_scroll_bar_cursor;
@@ -909,6 +912,14 @@ struct ns_display_info
 #endif
 };
 
+INLINE union display_info
+U_DISPLAY_INFO_NS (struct ns_display_info *dpyinfo)
+{
+  union display_info info = { .ns = dpyinfo };
+
+  return info;
+}
+
 /* This is a chain of structures for all the NS displays currently in use.  */
 extern struct ns_display_info *x_display_list;
 
@@ -1142,6 +1153,11 @@ ns_defined_color (struct frame *f,
 extern void
 ns_query_color (void *col, XColor *color_def, int setPixel);
 
+/* In nsfns.c */
+extern const char *ns_get_string_resource (void *_rdb,
+                                           const char *name,
+                                           const char *class);
+
 #ifdef __OBJC__
 extern int ns_lisp_to_color (Lisp_Object color, NSColor **col);
 extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f);
@@ -1327,4 +1343,5 @@ enum NSWindowTabbingMode
 /* Deprecated in macOS 10.13.  */
 #define NSPasteboardNameGeneral NSGeneralPboard
 #endif
+INLINE_HEADER_END
 #endif	/* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
index 81d36be6cc..58d33161a3 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5195,6 +5195,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
   terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
   terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
+  terminal->get_string_resource_hook = ns_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = ns_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/termchar.h b/src/termchar.h
index 796453d3cc..564f7f1c12 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -42,6 +42,9 @@ struct tty_display_info
 {
   struct tty_display_info *next; /* Chain of all tty devices. */
 
+  struct terminal *terminal;    /* Points back to the generic terminal
+                                   structure.  This is sometimes handy. */
+
   char *name;                   /* The name of the device file or 0 if
                                    stdin/stdout. */
   char *type;                   /* The type of the tty. */
@@ -63,9 +66,6 @@ struct tty_display_info
 
   int reference_count;          /* Number of frames that are on this display. */
 
-  struct terminal *terminal;    /* Points back to the generic terminal
-                                   structure.  This is sometimes handy. */
-
   /* Info on cursor positioning.  */
   struct cm *Wcm;
 
diff --git a/src/termhooks.h b/src/termhooks.h
index a92b981110..f1d9621d9a 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -54,6 +54,7 @@ enum scroll_bar_part {
 
 enum output_method
 {
+  output_nothing,  /* Special value to be used for comparisons.  */
   output_initial,
   output_termcap,
   output_x_window,
@@ -62,6 +63,28 @@ enum output_method
   output_ns
 };
 
+extern enum output_method gui_initial_output_method;
+
+/* Device-type dependent data shared amongst all frames on this terminal.  */
+
+union display_info
+{
+  /* Note that the following members of each display_info type must be
+     at the start in this order:
+     - next
+     - terminal
+  */
+  struct tty_display_info *tty;     /* termchar.h */
+  struct x_display_info *x;         /* xterm.h    */
+  struct w32_display_info *w32;     /* w32term.h  */
+  struct ns_display_info *ns;       /* nsterm.h   */
+};
+
+/* Access the common elements at the beginning of display_info due to
+   a limitation in C.  Any display_info type would do here.  */
+
+#define DISPLAY_INFO(dpyinfo) (dpyinfo).x
+
 /* Input queue declarations and hooks.  */
 
 enum event_kind
@@ -437,13 +460,7 @@ struct terminal
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* Device-type dependent data shared amongst all frames on this terminal.  */
-  union display_info
-  {
-    struct tty_display_info *tty;     /* termchar.h */
-    struct x_display_info *x;         /* xterm.h */
-    struct w32_display_info *w32;     /* w32term.h */
-    struct ns_display_info *ns;       /* nsterm.h */
-  } display_info;
+  union display_info display_info;
 
 \f
   /* Coding-system to be used for encoding terminal output.  This
@@ -645,6 +662,11 @@ struct terminal
      while it runs.  */
   void (*buffer_flipping_unblocked_hook) (struct frame *);
 
+  /* Retrieve the string resource specified by NAME with CLASS from
+     database RDB. */
+  const char * (*get_string_resource_hook) (void *rdb,
+                                            const char *name,
+                                            const char *class);
 \f
   /* Called to delete the device-specific portions of a frame that is
      on this terminal device. */
diff --git a/src/terminal.c b/src/terminal.c
index 0ee0121e35..c874527006 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -642,6 +642,77 @@ delete_initial_terminal (struct terminal *terminal)
   initial_terminal = NULL;
 }
 
+union display_info
+decode_display_info (Lisp_Object object, enum output_method method)
+{
+  union display_info info;
+
+  DISPLAY_INFO (info) = NULL;
+  if (NILP (object))
+    {
+      struct frame *sf = XFRAME (selected_frame);
+
+      if (FRAME_LIVE_P (sf) && (method == output_nothing
+                                || method == sf->output_method))
+        DISPLAY_INFO (info) = FRAME_DISPLAY_INFO (sf);
+      else
+        {
+          switch (method)
+            {
+#ifdef HAVE_X_WINDOWS
+            case output_x_window:
+              info.x = x_display_list;
+              break;
+#endif
+#ifdef HAVE_NTGUI
+            case output_w32:
+              info.w32 = w32_display_list;
+              break;
+#endif
+#ifdef HAVE_NS
+            case output_ns:
+              info.ns = ns_display_list;
+              break;
+#endif
+            default:
+              break;
+            }
+          if (!DISPLAY_INFO (info))
+            error ("Window system not in use or not initialized");
+        }
+    }
+  else if (TERMINALP (object))
+    {
+      struct terminal *t = decode_live_terminal (object);
+
+      if (method != output_nothing
+          && t->type != method)
+        {
+          char type_name[4];
+          switch (method)
+            {
+            case output_x_window:
+              strcpy (type_name, "x");
+              break;
+            case output_w32:
+              strcpy (type_name, "w32");
+              break;
+            case output_ns:
+              strcpy (type_name, "ns");
+              break;
+            default:
+              emacs_abort ();
+            }
+          error ("Terminal %d is not of type `%s'", t->id, type_name);
+        }
+      info = t->display_info;
+    }
+  else
+    DISPLAY_INFO (info) = FRAME_DISPLAY_INFO (decode_window_system_frame (object));
+
+  return info;
+}
+
 void
 syms_of_terminal (void)
 {
diff --git a/src/w32fns.c b/src/w32fns.c
index af82b46305..4873e7866c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -5411,12 +5411,13 @@ my_create_window (struct frame * f)
   MSG msg;
   static int coords[2];
   Lisp_Object left, top;
-  struct w32_display_info *dpyinfo = &one_w32_display_info;
-
-  /* When called with RES_TYPE_NUMBER, x_get_arg will return zero for
-     anything that is not a number and is not Qunbound.  */
-  left = x_get_arg (dpyinfo, Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
-  top = x_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
+  union display_info dpyinfo = { .w32 = &one_w32_display_info };
+  /* When called with RES_TYPE_NUMBER, gui_display_get_arg will return
+     zero for anything that is not a number and is not Qunbound.  */
+  left = gui_display_get_arg (dpyinfo,
+                              Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
+  top = gui_display_get_arg (dpyinfo,
+                             Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
   if (EQ (left, Qunbound))
     coords[0] = CW_USEDEFAULT;
   else
@@ -5528,12 +5529,14 @@ static void
 x_icon (struct frame *f, Lisp_Object parms)
 {
   Lisp_Object icon_x, icon_y;
-  struct w32_display_info *dpyinfo = &one_w32_display_info;
+  union display_info dpyinfo = { .w32 = &one_w32_display_info };
 
   /* Set the position of the icon.  Note that Windows 95 groups all
      icons in the tray.  */
-  icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
-  icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
+  icon_x = gui_display_get_arg (dpyinfo,
+                                parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
+  icon_y = gui_display_get_arg (dpyinfo,
+                                parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
     {
       CHECK_FIXNUM (icon_x);
@@ -5547,7 +5550,9 @@ x_icon (struct frame *f, Lisp_Object parms)
 #if 0 /* TODO */
   /* Start up iconic or window? */
   x_wm_set_window_state
-    (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
+    (f, (EQ (gui_display_get_arg (dpyinfo,
+                                  parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
+             Qicon)
 	 ? IconicState
 	 : NormalState));
 
@@ -5642,14 +5647,16 @@ do_unwind_create_frame (Lisp_Object frame)
 static void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
-  struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-  Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
-				RES_TYPE_STRING);
+  union display_info dpyinfo = { .w32 = FRAME_DISPLAY_INFO (f) };
+  Lisp_Object font_param = gui_display_get_arg (dpyinfo,
+                                                parms, Qfont, NULL, NULL,
+                                                RES_TYPE_STRING);
   Lisp_Object font;
   if (EQ (font_param, Qunbound))
     font_param = Qnil;
   font = !NILP (font_param) ? font_param
-    : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
+    : gui_display_get_arg (dpyinfo,
+                           parms, Qfont, "font", "Font", RES_TYPE_STRING);
 
   if (!STRINGP (font))
     {
@@ -5692,7 +5699,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   long window_prompting = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object display;
-  struct w32_display_info *dpyinfo = NULL;
+  union display_info dpyinfo_u = { .w32 = NULL };
+  struct w32_display_info *dpyinfo;
   Lisp_Object parent, parent_frame;
   struct kboard *kb;
   int x_width = 0, x_height = 0;
@@ -5709,9 +5717,11 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
 
-  display = x_get_arg (dpyinfo, parameters, Qterminal, 0, 0, RES_TYPE_NUMBER);
+  display = gui_display_get_arg (dpyinfo_u,
+                                 parameters, Qterminal, 0, 0, RES_TYPE_NUMBER);
   if (EQ (display, Qunbound))
-    display = x_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
+    display = gui_display_get_arg (dpyinfo_u,
+                                   parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
   dpyinfo = check_x_display_info (display);
@@ -5720,7 +5730,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
-  name = x_get_arg (dpyinfo, parameters, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (dpyinfo_u,
+                              parameters, Qname, "name", "Name",
+                              RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
       && ! NILP (name))
@@ -5730,8 +5742,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
     Vx_resource_name = name;
 
   /* See if parent window is specified.  */
-  parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
-		      RES_TYPE_NUMBER);
+  parent = gui_display_get_arg (dpyinfo_u,
+                                parameters, Qparent_id, NULL, NULL,
+                                RES_TYPE_NUMBER);
   if (EQ (parent, Qunbound))
     parent = Qnil;
   else if (!NILP (parent))
@@ -5741,8 +5754,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   /* No need to protect DISPLAY because that's not used after passing
      it to make_frame_without_minibuffer.  */
   frame = Qnil;
-  tem = x_get_arg (dpyinfo, parameters, Qminibuffer, "minibuffer", "Minibuffer",
-		   RES_TYPE_SYMBOL);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qminibuffer, "minibuffer", "Minibuffer",
+                             RES_TYPE_SYMBOL);
   if (EQ (tem, Qnone) || NILP (tem))
     f = make_frame_without_minibuffer (Qnil, kb, display);
   else if (EQ (tem, Qonly))
@@ -5757,8 +5771,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
   XSETFRAME (frame, f);
 
-  parent_frame = x_get_arg (dpyinfo, parameters, Qparent_frame, NULL, NULL,
-			    RES_TYPE_SYMBOL);
+  parent_frame = gui_display_get_arg (dpyinfo_u,
+                                      parameters, Qparent_frame, NULL, NULL,
+                                      RES_TYPE_SYMBOL);
   /* Apply `parent-frame' parameter only when no `parent-id' was
      specified.  */
   if (!NILP (parent_frame)
@@ -5771,13 +5786,15 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   fset_parent_frame (f, parent_frame);
   store_frame_param (f, Qparent_frame, parent_frame);
 
-  tem = x_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
-		   RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qundecorated, NULL, NULL,
+                             RES_TYPE_BOOLEAN);
   FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
   store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
 
-  tem = x_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
-		   RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qskip_taskbar, NULL, NULL,
+                             RES_TYPE_BOOLEAN);
   FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
   store_frame_param (f, Qskip_taskbar,
 		     (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
@@ -5793,8 +5810,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   FRAME_FONTSET (f) = -1;
 
   fset_icon_name
-    (f, x_get_arg (dpyinfo, parameters, Qicon_name, "iconName", "Title",
-		   RES_TYPE_STRING));
+    (f, gui_display_get_arg (dpyinfo_u,
+                             parameters, Qicon_name, "iconName", "Title",
+                             RES_TYPE_STRING));
   if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
@@ -5861,8 +5879,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parameters, Qinternal_border_width,
-			 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo_u,
+                                   parameters, Qinternal_border_width,
+                                   "internalBorder", "InternalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parameters = Fcons (Fcons (Qinternal_border_width, value),
 			    parameters);
@@ -5926,12 +5946,12 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
      Also process `min-width' and `min-height' parameters right here
      because `frame-windows-min-size' needs them.  */
-  tem = x_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
-		   RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parameters, Qmin_width, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_width, tem);
-  tem = x_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
-		   RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parameters, Qmin_height, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_height, tem);
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
@@ -5983,7 +6003,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
   window_prompting = x_figure_window_size (f, parameters, true, &x_width, &x_height);
 
-  tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
 
   w32_window (f, window_prompting, minibuffer_only);
@@ -6044,7 +6065,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   if (!f->output_data.w32->explicit_parent)
     {
       Lisp_Object visibility
-	= x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+	= gui_display_get_arg (dpyinfo_u,
+                               parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
 
       if (EQ (visibility, Qicon))
 	x_iconify_frame (f);
@@ -6072,8 +6094,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 	  || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
     kset_default_minibuffer_frame (kb, frame);
 
-  /* All remaining specified parameters, which have not been "used"
-     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  /* All remaining specified parameters, which have not been "used" by
+     gui_display_get_arg and friends, now go in the misc. alist of the
+     frame.  */
   for (tem = parameters; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
@@ -6854,12 +6877,14 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
 
   kb = dpyinfo->terminal->kboard;
 
-  /* The calls to x_get_arg remove elements from PARMS, so copy it to
-     avoid destructive changes behind our caller's back.  */
+  /* The calls to gui_display_get_arg remove elements from PARMS, so
+     copy it to avoid destructive changes behind our caller's
+     back.  */
   parms = Fcopy_alist (parms);
 
   /* Get the name of the frame to use for resource lookup.  */
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (U_DISPLAY_INFO_W32 (dpyinfo),
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && !EQ (name, Qunbound)
       && !NILP (name))
@@ -6928,8 +6953,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
diff --git a/src/w32gui.h b/src/w32gui.h
index dbc67993ce..5dcbbd9516 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -42,8 +42,6 @@ typedef struct _XGCValues
 typedef HBITMAP Pixmap;
 typedef HBITMAP Bitmap;
 
-typedef char * XrmDatabase;
-
 typedef XGCValues * GC;
 typedef COLORREF Color;
 typedef HWND Window;
diff --git a/src/w32reg.c b/src/w32reg.c
index aff131dd37..6500dfd279 100644
--- a/src/w32reg.c
+++ b/src/w32reg.c
@@ -21,7 +21,6 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "lisp.h"
-#include "w32term.h"	/* for XrmDatabase, xrdb */
 #include "blockinput.h"
 
 #include <stdio.h>
@@ -73,8 +72,8 @@ w32_get_rdb_resource (const char *rdb, const char *resource)
   return NULL;
 }
 
-static char *
-w32_get_string_resource (const char *name, const char *class, DWORD dwexptype)
+static const char *
+w32_get_string_resource_1 (const char *name, const char *class, DWORD dwexptype)
 {
   LPBYTE lpvalue = NULL;
   HKEY hrootkey = NULL;
@@ -134,18 +133,19 @@ w32_get_string_resource (const char *name, const char *class, DWORD dwexptype)
       /* Check if there are Windows specific defaults defined.  */
       return w32_get_rdb_resource (SYSTEM_DEFAULT_RESOURCES, name);
     }
-  return (char *)lpvalue;
+  return (const char *)lpvalue;
 }
 
 /* Retrieve the string resource specified by NAME with CLASS from
    database RDB. */
 
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+w32_get_string_resource (void *v_rdb, const char *name, const char *class)
 {
+  char *rdb = v_rdb;
   if (rdb)
     {
-      char *resource;
+      const char *resource;
 
       if ((resource = w32_get_rdb_resource (rdb, name)))
         return resource;
@@ -157,5 +157,5 @@ x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
     /* --quick was passed, so this is a no-op.  */
     return NULL;
 
-  return w32_get_string_resource (name, class, REG_SZ);
+  return w32_get_string_resource_1 (name, class, REG_SZ);
 }
diff --git a/src/w32term.c b/src/w32term.c
index bb1f0bad01..2b4957ae00 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7153,6 +7153,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
   terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
   terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
+  terminal->get_string_resource_hook = w32_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/w32term.h b/src/w32term.h
index 4c496e97e4..6cc0cedc14 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -22,6 +22,8 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "frame.h"
 #include "atimer.h"
 
+INLINE_HEADER_BEGIN
+
 /* Stack alignment stuff.  Every CALLBACK and thread function should
    have the ALIGN_STACK attribute if it manipulates Lisp objects,
    because Windows x86 32-bit ABI only guarantees 4-byte stack
@@ -120,7 +122,7 @@ struct w32_display_info
   Cursor horizontal_scroll_bar_cursor;
 
   /* Resource data base */
-  XrmDatabase xrdb;
+  char *xrdb;
 
   /* color palette information.  */
   int has_palette;
@@ -219,6 +221,14 @@ struct w32_display_info
   int cursor_display_counter;
 };
 
+INLINE union display_info
+U_DISPLAY_INFO_w32 (struct w32_display_info *dpyinfo)
+{
+  union display_info info = { .w32 = dpyinfo };
+
+  return info;
+}
+
 /* This is a chain of structures for all the displays currently in use.  */
 extern struct w32_display_info *x_display_list;
 extern struct w32_display_info one_w32_display_info;
@@ -257,6 +267,10 @@ extern int w32_kbd_mods_to_emacs (DWORD mods, WORD key);
 extern void w32con_hide_cursor (void);
 extern void w32con_show_cursor (void);
 
+/* w32reg.c */
+extern const char *w32_get_string_resource (void *v_rdb,
+                                            const char *name,
+                                            const char *class);
 \f
 #define PIX_TYPE COLORREF
 
@@ -872,3 +886,5 @@ extern void w32_init_main_thread (void);
 #ifdef CYGWIN
 extern int w32_message_fd;
 #endif /* CYGWIN */
+
+INLINE_HEADER_END
diff --git a/src/xfaces.c b/src/xfaces.c
index c6723ebe2c..c74fa9e092 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -3484,7 +3484,7 @@ ordinary `x-get-resource' doesn't take a frame argument.  */)
   CHECK_STRING (class);
   f = decode_live_frame (frame);
   block_input ();
-  value = display_x_get_resource (FRAME_DISPLAY_INFO (f),
+  value = display_x_get_resource (U_DISPLAY_INFO_X (FRAME_DISPLAY_INFO (f)),
 				  resource, class, Qnil, Qnil);
   unblock_input ();
   return value;
diff --git a/src/xfns.c b/src/xfns.c
index 13f66f0718..5d92ab9086 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2115,7 +2115,8 @@ x_default_scroll_bar_color_parameter (struct frame *f,
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Lisp_Object tem;
 
-  tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
+  tem = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                             alist, prop, xprop, xclass, RES_TYPE_STRING);
   if (EQ (tem, Qunbound))
     {
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -2126,7 +2127,8 @@ x_default_scroll_bar_color_parameter (struct frame *f,
       AUTO_STRING (background, "foreground");
       AUTO_STRING (verticalScrollBar, "verticalScrollBar");
       tem = (display_x_get_resource
-	     (dpyinfo, foreground_p ? foreground : background,
+	     (U_DISPLAY_INFO_X (dpyinfo),
+              foreground_p ? foreground : background,
 	      empty_unibyte_string,
 	      verticalScrollBar,
 	      empty_unibyte_string));
@@ -3463,8 +3465,9 @@ static void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-  Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
-                                      RES_TYPE_STRING);
+  Lisp_Object font_param = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                                                parms, Qfont, NULL, NULL,
+                                                RES_TYPE_STRING);
   Lisp_Object font = Qnil;
   if (EQ (font_param, Qunbound))
     font_param = Qnil;
@@ -3481,7 +3484,8 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
 
   if (NILP (font))
       font = !NILP (font_param) ? font_param
-      : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
+      : gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                             parms, Qfont, "font", "Font", RES_TYPE_STRING);
 
   if (! FONTP (font) && ! STRINGP (font))
     {
@@ -3581,7 +3585,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   long window_prompting = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object display;
-  struct x_display_info *dpyinfo = NULL;
+  union display_info dpyinfo_u = { .x = NULL};
+  struct x_display_info *dpyinfo;
   Lisp_Object parent, parent_frame;
   struct kboard *kb;
   int x_width = 0, x_height = 0;
@@ -3592,18 +3597,21 @@ This function is an internal primitive--use `make-frame' instead.  */)
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
 
-  display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
+  display = gui_display_get_arg (dpyinfo_u, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
   if (EQ (display, Qunbound))
-    display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
+    display = gui_display_get_arg (dpyinfo_u,
+                                   parms, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
   dpyinfo = check_x_display_info (display);
+  dpyinfo_u.x = dpyinfo;
   kb = dpyinfo->terminal->kboard;
 
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (dpyinfo_u,
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
       && ! NILP (name))
@@ -3613,15 +3621,17 @@ This function is an internal primitive--use `make-frame' instead.  */)
     Vx_resource_name = name;
 
   /* See if parent window is specified.  */
-  parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
+  parent = gui_display_get_arg (dpyinfo_u,
+                                parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
   if (EQ (parent, Qunbound))
     parent = Qnil;
   if (! NILP (parent))
     CHECK_FIXNUM (parent);
 
   frame = Qnil;
-  tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
-		   RES_TYPE_SYMBOL);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qminibuffer, "minibuffer", "Minibuffer",
+                             RES_TYPE_SYMBOL);
   if (EQ (tem, Qnone) || NILP (tem))
     f = make_frame_without_minibuffer (Qnil, kb, display);
   else if (EQ (tem, Qonly))
@@ -3634,8 +3644,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   else
     f = make_frame (true);
 
-  parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
-			    RES_TYPE_SYMBOL);
+  parent_frame = gui_display_get_arg (dpyinfo_u,
+                                      parms, Qparent_frame, NULL, NULL,
+                                      RES_TYPE_SYMBOL);
   /* Accept parent-frame iff parent-id was not specified.  */
   if (!NILP (parent)
       || EQ (parent_frame, Qunbound)
@@ -3648,16 +3659,17 @@ This function is an internal primitive--use `make-frame' instead.  */)
   fset_parent_frame (f, parent_frame);
   store_frame_param (f, Qparent_frame, parent_frame);
 
-  if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
-			       RES_TYPE_BOOLEAN)))
+  if (!NILP (tem = (gui_display_get_arg (dpyinfo_u,
+                                         parms, Qundecorated, NULL, NULL,
+                                         RES_TYPE_BOOLEAN)))
       && !(EQ (tem, Qunbound)))
     undecorated = true;
 
   FRAME_UNDECORATED (f) = undecorated;
   store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
 
-  if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
-			       RES_TYPE_BOOLEAN)))
+  if (!NILP (tem = (gui_display_get_arg (dpyinfo_u, parms, Qoverride_redirect,
+                                         NULL, NULL, RES_TYPE_BOOLEAN)))
       && !(EQ (tem, Qunbound)))
     override_redirect = true;
 
@@ -3682,8 +3694,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.x->black_relief.pixel = -1;
 
   fset_icon_name (f,
-		  x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
-			     RES_TYPE_STRING));
+		  gui_display_get_arg (dpyinfo_u,
+                                       parms, Qicon_name, "iconName", "Title",
+                                       RES_TYPE_STRING));
   if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
@@ -3792,8 +3805,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo_u, parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
@@ -3865,10 +3879,12 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
      Also process `min-width' and `min-height' parameters right here
      because `frame-windows-min-size' needs them.  */
-  tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parms, Qmin_width, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_width, tem);
-  tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_height, tem);
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
@@ -3905,7 +3921,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Compute the size of the X window.  */
   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
 
-  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
 
   x_icon_verify (f, parms);
@@ -4008,7 +4025,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   if (!f->output_data.x->explicit_parent)
     {
       Lisp_Object visibility
-	= x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+	= gui_display_get_arg (dpyinfo_u,
+                               parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
 
       if (EQ (visibility, Qicon))
 	x_iconify_frame (f);
@@ -4056,8 +4074,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
     kset_default_minibuffer_frame (kb, frame);
 
-  /* All remaining specified parameters, which have not been "used"
-     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  /* All remaining specified parameters, which have not been "used" by
+     gui_display_get_arg and friends, now go in the misc. alist of the
+     frame.  */
   for (tem = parms; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
@@ -5535,8 +5554,11 @@ select_visual (struct x_display_info *dpyinfo)
   /* See if a visual is specified.  */
   AUTO_STRING (visualClass, "visualClass");
   AUTO_STRING (VisualClass, "VisualClass");
-  Lisp_Object value = display_x_get_resource (dpyinfo, visualClass,
-					      VisualClass, Qnil, Qnil);
+  Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                              visualClass,
+					      VisualClass,
+                                              Qnil,
+                                              Qnil);
 
   if (STRINGP (value))
     {
@@ -6144,7 +6166,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
   parms = Fcopy_alist (parms);
 
   /* Get the name of the frame to use for resource lookup.  */
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && !EQ (name, Qunbound)
       && !NILP (name))
@@ -6262,8 +6285,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                                   parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
diff --git a/src/xrdb.c b/src/xrdb.c
index 35de446cb7..05d46324e6 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -60,12 +60,12 @@ x_get_customization_string (XrmDatabase db, const char *name,
 {
   char *full_name = alloca (strlen (name) + sizeof "customization" + 3);
   char *full_class = alloca (strlen (class) + sizeof "Customization" + 3);
-  char *result;
+  const char *result;
 
   sprintf (full_name,  "%s.%s", name,  "customization");
   sprintf (full_class, "%s.%s", class, "Customization");
 
-  result = x_get_string_resource (db, full_name, full_class);
+  result = x_get_string_resource (&db, full_name, full_class);
   return result ? xstrdup (result) : NULL;
 }
 
@@ -522,6 +522,7 @@ static int
 x_get_resource (XrmDatabase rdb, const char *name, const char *class,
 		XrmRepresentation expected_type, XrmValue *ret_value)
 {
+  fprintf (stderr, "x_get_resource\n");
   XrmValue value;
   XrmName namelist[100];
   XrmClass classlist[100];
@@ -547,19 +548,20 @@ x_get_resource (XrmDatabase rdb, const char *name, const char *class,
 /* Retrieve the string resource specified by NAME with CLASS from
    database RDB. */
 
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+x_get_string_resource (void *v_rdb, const char *name, const char *class)
 {
+  XrmDatabase *rdb = v_rdb;
   XrmValue value;
 
   if (inhibit_x_resources)
     /* --quick was passed, so this is a no-op.  */
     return NULL;
 
-  if (x_get_resource (rdb, name, class, x_rm_string, &value))
-    return (char *) value.addr;
+  if (x_get_resource (*rdb, name, class, x_rm_string, &value))
+    return (const char *) value.addr;
 
-  return 0;
+  return NULL;
 }
 \f
 /* Stand-alone test facilities.  */
@@ -648,7 +650,7 @@ main (int argc, char **argv)
 	  printf ("Class: ");
 	  gets (query_class);
 
-	  value = x_get_string_resource (xdb, query_name, query_class);
+	  value = x_get_string_resource (&xdb, query_name, query_class);
 
 	  if (value != NULL)
 	    printf ("\t%s(%s):  %s\n\n", query_name, query_class, value);
diff --git a/src/xterm.c b/src/xterm.c
index 5aa3e3ff25..8646d66f81 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -12737,8 +12737,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
 	  AUTO_STRING (privateColormap, "privateColormap");
 	  AUTO_STRING (PrivateColormap, "PrivateColormap");
 	  Lisp_Object value
-	    = display_x_get_resource (dpyinfo, privateColormap,
-				      PrivateColormap, Qnil, Qnil);
+	    = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                      privateColormap,
+				      PrivateColormap,
+                                      Qnil,
+                                      Qnil);
 	  if (STRINGP (value)
 	      && (!strcmp (SSDATA (value), "true")
 		  || !strcmp (SSDATA (value), "on")))
@@ -12955,8 +12958,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   {
     AUTO_STRING (synchronous, "synchronous");
     AUTO_STRING (Synchronous, "Synchronous");
-    Lisp_Object value = display_x_get_resource (dpyinfo, synchronous,
-						Synchronous, Qnil, Qnil);
+    Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                                synchronous,
+						Synchronous,
+                                                Qnil,
+                                                Qnil);
     if (STRINGP (value)
 	&& (!strcmp (SSDATA (value), "true")
 	    || !strcmp (SSDATA (value), "on")))
@@ -12966,8 +12972,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   {
     AUTO_STRING (useXIM, "useXIM");
     AUTO_STRING (UseXIM, "UseXIM");
-    Lisp_Object value = display_x_get_resource (dpyinfo, useXIM, UseXIM,
-						Qnil, Qnil);
+    Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                                useXIM,
+                                                UseXIM,
+						Qnil,
+                                                Qnil);
 #ifdef USE_XIM
     if (STRINGP (value)
 	&& (!strcmp (SSDATA (value), "false")
@@ -13253,6 +13262,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
   terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
+  terminal->get_string_resource_hook = x_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/xterm.h b/src/xterm.h
index c5ad38650c..da95926eda 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1088,6 +1088,8 @@ extern void x_real_pos_and_offsets (struct frame *f,
 XrmDatabase x_load_resources (Display *, const char *, const char *,
 			      const char *);
 
+extern const char * x_get_string_resource (void *rdb, const char *name,
+                                           const char *class);
 /* Defined in xterm.c */
 
 typedef void (*x_special_error_handler)(Display *, XErrorEvent *, char *,
@@ -1136,6 +1138,15 @@ extern void x_cr_draw_frame (cairo_t *, struct frame *);
 extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
 #endif
 
+INLINE union display_info
+U_DISPLAY_INFO_X (struct x_display_info *dpyinfo)
+{
+  union display_info info = { .x = dpyinfo };
+
+  return info;
+}
+
+
 INLINE int
 x_display_pixel_height (struct x_display_info *dpyinfo)
 {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 16:50 [RFC] Using a display_info union instead of a typedef Display_Info Alex Gramiak
@ 2019-04-12 17:06 ` Alex Gramiak
  2019-04-16 18:54   ` Paul Eggert
  2019-04-12 17:55 ` Eli Zaretskii
  1 sibling, 1 reply; 12+ messages in thread
From: Alex Gramiak @ 2019-04-12 17:06 UTC (permalink / raw)
  To: emacs-devel; +Cc: Eli Zaretskii, Stefan Monnier

[-- Attachment #1: Type: text/plain, Size: 215 bytes --]

Sorry, I just realized that I included part of a change that is
currently out of the scope of this topic (changing x_display_list to
w32/ns_display_list on w32/ns). I've attached a (hopefully) correct
patch below.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: union display_info v1.0001 --]
[-- Type: text/x-patch, Size: 56565 bytes --]

From 39fdbf90665811f474913c5ce9c81ee4ff9b3230 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Fri, 12 Apr 2019 00:09:21 -0600
Subject: [PATCH] Generalize x_get_arg to multiple display types

* src/termhooks.c (display_info): Move the union to global scope.
(get_string_resource_hook): New terminal hook.

* src/terminal.c (decode_display_info): New procedure.

* src/dispnew.c (gui_initial_output_method): New global variable used
when the selected frame is not a graphical frame.

* src/frame.c (xrdb_get_resource): Rename to display_x_get_resource
and remove the old definition of that name. Use the display_info union
instead of a typedef.
(x_get_arg): Rename to gui_display_get_arg.

* src/frame.c:
* src/xfns.c:
* src/w32fns.c: Rename x_get_arg to gui_display_get_arg.

* src/xterm.c (x_create_terminal):
* src/w32term.c (w32_create_terminal):
* src/nsterm.c (ns_create_terminal): Set terminal
get_string_resource_hook.

* srx/xterm.c (x_get_string_resource): Change first argument type to
  void*.

* src/w32reg.c (w32_get_string_resource): Rename to
w32_get_string_resource_1.
(x_get_string_resource): Rename to w32_get_string_resource. Change
first argument type to void*.

* src/nsterm.c (x_get_string_resource): Rename to
  ns_get_string_resource. Change first argument type to void*.
---
 src/dispextern.h |  12 +++--
 src/dispnew.c    |   8 ++++
 src/frame.c      |  95 ++++++++++++++++++++++++--------------
 src/frame.h      |   2 +-
 src/nsfns.m      |  12 ++---
 src/nsgui.h      |   3 --
 src/nsterm.h     |  19 +++++++-
 src/nsterm.m     |   1 +
 src/termchar.h   |   6 +--
 src/termhooks.h  |  36 ++++++++++++---
 src/terminal.c   |  71 +++++++++++++++++++++++++++++
 src/w32fns.c     | 116 +++++++++++++++++++++++++++++------------------
 src/w32gui.h     |   2 -
 src/w32reg.c     |  16 +++----
 src/w32term.c    |   1 +
 src/w32term.h    |  18 +++++++-
 src/xfaces.c     |   2 +-
 src/xfns.c       |  91 +++++++++++++++++++++++--------------
 src/xrdb.c       |  18 ++++----
 src/xterm.c      |  22 ++++++---
 src/xterm.h      |  11 +++++
 21 files changed, 398 insertions(+), 164 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 1a53656353..79a97f6d6d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -23,6 +23,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #define DISPEXTERN_H_INCLUDED
 
 #include "character.h"
+#include "termhooks.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -3539,6 +3540,9 @@ extern void insert_glyphs (struct frame *, struct glyph *, int);
 extern void delete_glyphs (struct frame *, int);
 extern void ins_del_lines (struct frame *, int, int);
 
+extern union display_info decode_display_info (Lisp_Object object,
+                                               enum output_method method);
+
 extern struct terminal *init_initial_terminal (void);
 
 
@@ -3586,9 +3590,9 @@ enum resource_types
 };
 
 extern Display_Info *check_x_display_info (Lisp_Object);
-extern Lisp_Object x_get_arg (Display_Info *, Lisp_Object,
-                              Lisp_Object, const char *, const char *class,
-                              enum resource_types);
+extern Lisp_Object gui_display_get_arg (union display_info, Lisp_Object,
+                                        Lisp_Object, const char *,
+                                        const char *, enum resource_types);
 extern Lisp_Object x_frame_get_and_record_arg (struct frame *, Lisp_Object,
                                                Lisp_Object,
 					       const char *, const char *,
@@ -3597,8 +3601,6 @@ extern Lisp_Object x_default_parameter (struct frame *, Lisp_Object,
                                         Lisp_Object, Lisp_Object,
                                         const char *, const char *,
                                         enum resource_types);
-extern char *x_get_string_resource (XrmDatabase, const char *,
-				    const char *);
 
 #ifndef HAVE_NS /* These both used on W32 and X only.  */
 extern bool x_mouse_grabbed (Display_Info *);
diff --git a/src/dispnew.c b/src/dispnew.c
index ccb08ec1b9..ae57e12062 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5985,6 +5985,10 @@ pass nil for VARIABLE.  */)
 			    Initialization
 ***********************************************************************/
 
+/* For the initial terminal, use this output method for
+   device-dependent procedures.  */
+enum output_method gui_initial_output_method;
+
 static void
 init_faces_initial (void)
 {
@@ -6017,6 +6021,7 @@ init_display_interactive (void)
   /* Now is the time to initialize this; it's used by init_sys_modes
      during startup.  */
   Vinitial_window_system = Qnil;
+  gui_initial_output_method = output_nothing;
 
   /* SIGWINCH needs to be handled no matter what display we start
      with.  Otherwise newly opened tty frames will not resize
@@ -6074,6 +6079,7 @@ init_display_interactive (void)
   if (!inhibit_window_system && display_arg)
     {
       Vinitial_window_system = Qx;
+      gui_initial_output_method = output_x_window;
 #ifdef HAVE_X11
       Vwindow_system_version = make_fixnum (11);
 #endif
@@ -6091,6 +6097,7 @@ init_display_interactive (void)
   if (!inhibit_window_system)
     {
       Vinitial_window_system = Qw32;
+      gui_initial_output_method = output_w32;
       Vwindow_system_version = make_fixnum (1);
       return;
     }
@@ -6100,6 +6107,7 @@ init_display_interactive (void)
   if (!inhibit_window_system && !will_dump_p ())
     {
       Vinitial_window_system = Qns;
+      gui_initial_output_method = output_ns;
       Vwindow_system_version = make_fixnum (10);
       return;
     }
diff --git a/src/frame.c b/src/frame.c
index 192ef4244f..371d95c064 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3719,6 +3719,35 @@ static const struct frame_parm_table frame_parms[] =
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+static union display_info
+gui_frame_display_info (struct frame *f)
+{
+  union display_info info;
+
+  switch (f->output_method)
+    {
+#ifdef HAVE_X_WINDOWS
+    case output_x_window:
+      info.x = f->output_data.x->display_info;
+      break;
+#endif
+#ifdef HAVE_NTGUI
+    case output_w32:
+      info.w32 = f->output_data.w32->display_info;
+      break;
+#endif
+#ifdef HAVE_NS
+    case output_ns:
+      info.ns = f->output_data.ns->display_info;
+      break;
+#endif
+    default:
+      error ("Non-graphical window system frame specified");
+    }
+
+  return info;
+}
+
 /* Enumeration type for switch in frame_float.  */
 enum frame_float_type
 {
@@ -4928,8 +4957,10 @@ validate_x_resource_name (void)
 /* Get specified attribute from resource database RDB.
    See Fx_get_resource below for other parameters.  */
 
-static Lisp_Object
-xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
+Lisp_Object
+display_x_get_resource (union display_info dpyinfo, Lisp_Object attribute,
+                        Lisp_Object class, Lisp_Object component,
+                        Lisp_Object subclass)
 {
   CHECK_STRING (attribute);
   CHECK_STRING (class);
@@ -4982,7 +5013,11 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
   *nz++ = '.';
   lispstpcpy (nz, attribute);
 
-  char *value = x_get_string_resource (rdb, name_key, class_key);
+  void *rdb = &DISPLAY_INFO (dpyinfo)->xrdb;
+  const char *value =
+    DISPLAY_INFO(dpyinfo)->terminal->get_string_resource_hook (rdb,
+                                                               name_key,
+                                                               class_key);
   SAFE_FREE();
 
   if (value && *value)
@@ -4991,7 +5026,6 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
     return Qnil;
 }
 
-
 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
        doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
@@ -5007,19 +5041,9 @@ and the class is `Emacs.CLASS.SUBCLASS'.  */)
 {
   check_window_system (NULL);
 
-  return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
-			    attribute, class, component, subclass);
-}
-
-/* Get an X resource, like Fx_get_resource, but for display DPYINFO.  */
-
-Lisp_Object
-display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
-			Lisp_Object class, Lisp_Object component,
-			Lisp_Object subclass)
-{
-  return xrdb_get_resource (dpyinfo->xrdb,
-			    attribute, class, component, subclass);
+  return display_x_get_resource (decode_display_info
+                                 (Qnil, gui_initial_output_method),
+                                 attribute, class, component, subclass);
 }
 
 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
@@ -5045,7 +5069,7 @@ x_get_resource_string (const char *attribute, const char *class)
   esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
-  result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
+  result = x_get_string_resource (&FRAME_DISPLAY_INFO (sf)->xrdb,
 				  name_key, class_key);
   SAFE_FREE ();
   return result;
@@ -5060,12 +5084,14 @@ x_get_resource_string (const char *attribute, const char *class)
    Convert the resource to the type specified by desired_type.
 
    If no default is specified, return Qunbound.  If you call
-   x_get_arg, make sure you deal with Qunbound in a reasonable way,
-   and don't let it get stored in any Lisp-visible variables!  */
+   gui_display_get_arg, make sure you deal with Qunbound in a
+   reasonable way, and don't let it get stored in any Lisp-visible
+   variables!  */
 
 Lisp_Object
-x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
-	   const char *attribute, const char *class, enum resource_types type)
+gui_display_get_arg (union display_info dpyinfo, Lisp_Object alist,
+                     Lisp_Object param, const char *attribute,
+                     const char *class, enum resource_types type)
 {
   Lisp_Object tem;
 
@@ -5091,7 +5117,7 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
      look in the X resources.  */
   if (NILP (tem))
     {
-      if (attribute && dpyinfo)
+      if (attribute && DISPLAY_INFO (dpyinfo))
 	{
 	  AUTO_STRING (at, attribute);
 	  AUTO_STRING (cl, class);
@@ -5166,8 +5192,8 @@ x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
 		 const char *attribute, const char *class,
 		 enum resource_types type)
 {
-  return x_get_arg (FRAME_DISPLAY_INFO (f),
-		    alist, param, attribute, class, type);
+  return gui_display_get_arg (gui_frame_display_info (f),
+                              alist, param, attribute, class, type);
 }
 
 /* Like x_frame_get_arg, but also record the value in f->param_alist.  */
@@ -5180,8 +5206,8 @@ x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
 {
   Lisp_Object value;
 
-  value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
-		     attribute, class, type);
+  value = gui_display_get_arg (gui_frame_display_info (f), alist, param,
+                               attribute, class, type);
   if (! NILP (value) && ! EQ (value, Qunbound))
     store_frame_param (f, param, value);
 
@@ -5385,7 +5411,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
 {
   Lisp_Object height, width, user_size, top, left, user_position;
   long window_prompting = 0;
-  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
+  union display_info dpyinfo = gui_frame_display_info (f);
   int parent_done = -1, outer_done = -1;
 
   /* Default values if we fall through.
@@ -5435,8 +5461,8 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
      override what we specify below.  */
   f->new_width = f->new_height = 0;
 
-  height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
-  width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+  height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+  width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
   if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
     {
       if (!EQ (width, Qunbound))
@@ -5513,16 +5539,17 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
 	    }
 	}
 
-      user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+      user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
       if (!NILP (user_size) && !EQ (user_size, Qunbound))
 	window_prompting |= USSize;
       else
 	window_prompting |= PSize;
     }
 
-  top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
-  left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
-  user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+  top = gui_display_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+  left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+  user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0,
+                                       RES_TYPE_NUMBER);
   if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
     {
       if (EQ (top, Qminus))
diff --git a/src/frame.h b/src/frame.h
index ec8f61465f..499ed1a51d 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1578,7 +1578,7 @@ extern void x_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
 
 extern void validate_x_resource_name (void);
 
-extern Lisp_Object display_x_get_resource (Display_Info *,
+extern Lisp_Object display_x_get_resource (union display_info,
 					   Lisp_Object attribute,
 					   Lisp_Object class,
 					   Lisp_Object component,
diff --git a/src/nsfns.m b/src/nsfns.m
index ee7598a1c7..5968b38e28 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2248,8 +2248,8 @@ Frames are listed from topmost (first) to bottommost (last).  */)
 }
 
 /* Terms implement this instead of x-get-resource directly.  */
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+ns_get_string_resource (void *_rdb, const char *name, const char *class)
 {
   /* remove appname prefix; TODO: allow for !="Emacs" */
   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
@@ -2261,10 +2261,10 @@ Frames are listed from topmost (first) to bottommost (last).  */)
     return NULL;
 
   res = ns_get_defaults_value (toCheck);
-  return (char *) (!res ? NULL
-		   : !c_strncasecmp (res, "YES", 3) ? "true"
-		   : !c_strncasecmp (res, "NO", 2) ? "false"
-		   : res);
+  return (const char *) (!res ? NULL
+                         : !c_strncasecmp (res, "YES", 3) ? "true"
+                         : !c_strncasecmp (res, "NO", 2) ? "false"
+                         : res);
 }
 
 
diff --git a/src/nsgui.h b/src/nsgui.h
index c857d77d9c..c147f4dec4 100644
--- a/src/nsgui.h
+++ b/src/nsgui.h
@@ -117,9 +117,6 @@ typedef void * Color;
 typedef int Window;
 typedef int Display;
 
-/* Xism */
-typedef Lisp_Object XrmDatabase;
-
 
 /* Some sort of attempt to normalize rectangle handling.  Seems a bit
    much for what is accomplished.  */
diff --git a/src/nsterm.h b/src/nsterm.h
index 78ce608554..8b6d6dfd17 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -25,6 +25,9 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "sysselect.h"
 
 #ifdef HAVE_NS
+
+INLINE_HEADER_BEGIN
+
 #ifdef __OBJC__
 
 /* CGFloat on GNUstep may be 4 or 8 byte, but functions expect float* for some
@@ -869,7 +872,7 @@ struct ns_display_info
   Window root_window;
 
   /* Xism */
-  XrmDatabase xrdb;
+  Lisp_Object xrdb;
 
   /* The cursor to use for vertical scroll bars.  */
   Cursor vertical_scroll_bar_cursor;
@@ -909,6 +912,14 @@ struct ns_display_info
 #endif
 };
 
+INLINE union display_info
+U_DISPLAY_INFO_NS (struct ns_display_info *dpyinfo)
+{
+  union display_info info = { .ns = dpyinfo };
+
+  return info;
+}
+
 /* This is a chain of structures for all the NS displays currently in use.  */
 extern struct ns_display_info *x_display_list;
 
@@ -1142,6 +1153,11 @@ ns_defined_color (struct frame *f,
 extern void
 ns_query_color (void *col, XColor *color_def, int setPixel);
 
+/* In nsfns.c */
+extern const char *ns_get_string_resource (void *_rdb,
+                                           const char *name,
+                                           const char *class);
+
 #ifdef __OBJC__
 extern int ns_lisp_to_color (Lisp_Object color, NSColor **col);
 extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f);
@@ -1327,4 +1343,5 @@ enum NSWindowTabbingMode
 /* Deprecated in macOS 10.13.  */
 #define NSPasteboardNameGeneral NSGeneralPboard
 #endif
+INLINE_HEADER_END
 #endif	/* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
index 81d36be6cc..58d33161a3 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5195,6 +5195,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
   terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
   terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
+  terminal->get_string_resource_hook = ns_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = ns_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/termchar.h b/src/termchar.h
index 796453d3cc..564f7f1c12 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -42,6 +42,9 @@ struct tty_display_info
 {
   struct tty_display_info *next; /* Chain of all tty devices. */
 
+  struct terminal *terminal;    /* Points back to the generic terminal
+                                   structure.  This is sometimes handy. */
+
   char *name;                   /* The name of the device file or 0 if
                                    stdin/stdout. */
   char *type;                   /* The type of the tty. */
@@ -63,9 +66,6 @@ struct tty_display_info
 
   int reference_count;          /* Number of frames that are on this display. */
 
-  struct terminal *terminal;    /* Points back to the generic terminal
-                                   structure.  This is sometimes handy. */
-
   /* Info on cursor positioning.  */
   struct cm *Wcm;
 
diff --git a/src/termhooks.h b/src/termhooks.h
index a92b981110..8020b202ff 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -54,6 +54,7 @@ enum scroll_bar_part {
 
 enum output_method
 {
+  output_nothing,  /* Special value to be used for comparisons.  */
   output_initial,
   output_termcap,
   output_x_window,
@@ -62,6 +63,28 @@ enum output_method
   output_ns
 };
 
+extern enum output_method gui_initial_output_method;
+
+/* Device-type dependent data shared amongst all frames on this terminal.  */
+
+union display_info
+{
+  /* Note that the following members of each display_info type must be
+     at the start in this order:
+     - next
+     - terminal
+  */
+  struct tty_display_info *tty;     /* termchar.h */
+  struct x_display_info *x;         /* xterm.h    */
+  struct w32_display_info *w32;     /* w32term.h  */
+  struct ns_display_info *ns;       /* nsterm.h   */
+};
+
+/* Accessor for the common elements at the beginning of display_info
+   due to a limitation in C.  Any display_info type would do here.  */
+
+#define DISPLAY_INFO(dpyinfo) (dpyinfo).x
+
 /* Input queue declarations and hooks.  */
 
 enum event_kind
@@ -437,13 +460,7 @@ struct terminal
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* Device-type dependent data shared amongst all frames on this terminal.  */
-  union display_info
-  {
-    struct tty_display_info *tty;     /* termchar.h */
-    struct x_display_info *x;         /* xterm.h */
-    struct w32_display_info *w32;     /* w32term.h */
-    struct ns_display_info *ns;       /* nsterm.h */
-  } display_info;
+  union display_info display_info;
 
 \f
   /* Coding-system to be used for encoding terminal output.  This
@@ -645,6 +662,11 @@ struct terminal
      while it runs.  */
   void (*buffer_flipping_unblocked_hook) (struct frame *);
 
+  /* Retrieve the string resource specified by NAME with CLASS from
+     database RDB. */
+  const char * (*get_string_resource_hook) (void *rdb,
+                                            const char *name,
+                                            const char *class);
 \f
   /* Called to delete the device-specific portions of a frame that is
      on this terminal device. */
diff --git a/src/terminal.c b/src/terminal.c
index 0ee0121e35..bd92727fc2 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -642,6 +642,77 @@ delete_initial_terminal (struct terminal *terminal)
   initial_terminal = NULL;
 }
 
+union display_info
+decode_display_info (Lisp_Object object, enum output_method method)
+{
+  union display_info info;
+
+  DISPLAY_INFO (info) = NULL;
+  if (NILP (object))
+    {
+      struct frame *sf = XFRAME (selected_frame);
+
+      if (FRAME_LIVE_P (sf) && (method == output_nothing
+                                || method == sf->output_method))
+        DISPLAY_INFO (info) = FRAME_DISPLAY_INFO (sf);
+      else
+        {
+          switch (method)
+            {
+#ifdef HAVE_X_WINDOWS
+            case output_x_window:
+              info.x = x_display_list;
+              break;
+#endif
+#ifdef HAVE_NTGUI
+            case output_w32:
+              info.w32 = x_display_list;
+              break;
+#endif
+#ifdef HAVE_NS
+            case output_ns:
+              info.ns = x_display_list;
+              break;
+#endif
+            default:
+              break;
+            }
+          if (!DISPLAY_INFO (info))
+            error ("Window system not in use or not initialized");
+        }
+    }
+  else if (TERMINALP (object))
+    {
+      struct terminal *t = decode_live_terminal (object);
+
+      if (method != output_nothing
+          && t->type != method)
+        {
+          char type_name[4];
+          switch (method)
+            {
+            case output_x_window:
+              strcpy (type_name, "x");
+              break;
+            case output_w32:
+              strcpy (type_name, "w32");
+              break;
+            case output_ns:
+              strcpy (type_name, "ns");
+              break;
+            default:
+              emacs_abort ();
+            }
+          error ("Terminal %d is not of type `%s'", t->id, type_name);
+        }
+      info = t->display_info;
+    }
+  else
+    DISPLAY_INFO (info) = FRAME_DISPLAY_INFO (decode_window_system_frame (object));
+
+  return info;
+}
+
 void
 syms_of_terminal (void)
 {
diff --git a/src/w32fns.c b/src/w32fns.c
index af82b46305..4873e7866c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -5411,12 +5411,13 @@ my_create_window (struct frame * f)
   MSG msg;
   static int coords[2];
   Lisp_Object left, top;
-  struct w32_display_info *dpyinfo = &one_w32_display_info;
-
-  /* When called with RES_TYPE_NUMBER, x_get_arg will return zero for
-     anything that is not a number and is not Qunbound.  */
-  left = x_get_arg (dpyinfo, Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
-  top = x_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
+  union display_info dpyinfo = { .w32 = &one_w32_display_info };
+  /* When called with RES_TYPE_NUMBER, gui_display_get_arg will return
+     zero for anything that is not a number and is not Qunbound.  */
+  left = gui_display_get_arg (dpyinfo,
+                              Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
+  top = gui_display_get_arg (dpyinfo,
+                             Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
   if (EQ (left, Qunbound))
     coords[0] = CW_USEDEFAULT;
   else
@@ -5528,12 +5529,14 @@ static void
 x_icon (struct frame *f, Lisp_Object parms)
 {
   Lisp_Object icon_x, icon_y;
-  struct w32_display_info *dpyinfo = &one_w32_display_info;
+  union display_info dpyinfo = { .w32 = &one_w32_display_info };
 
   /* Set the position of the icon.  Note that Windows 95 groups all
      icons in the tray.  */
-  icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
-  icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
+  icon_x = gui_display_get_arg (dpyinfo,
+                                parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
+  icon_y = gui_display_get_arg (dpyinfo,
+                                parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
     {
       CHECK_FIXNUM (icon_x);
@@ -5547,7 +5550,9 @@ x_icon (struct frame *f, Lisp_Object parms)
 #if 0 /* TODO */
   /* Start up iconic or window? */
   x_wm_set_window_state
-    (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
+    (f, (EQ (gui_display_get_arg (dpyinfo,
+                                  parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
+             Qicon)
 	 ? IconicState
 	 : NormalState));
 
@@ -5642,14 +5647,16 @@ do_unwind_create_frame (Lisp_Object frame)
 static void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
-  struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-  Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
-				RES_TYPE_STRING);
+  union display_info dpyinfo = { .w32 = FRAME_DISPLAY_INFO (f) };
+  Lisp_Object font_param = gui_display_get_arg (dpyinfo,
+                                                parms, Qfont, NULL, NULL,
+                                                RES_TYPE_STRING);
   Lisp_Object font;
   if (EQ (font_param, Qunbound))
     font_param = Qnil;
   font = !NILP (font_param) ? font_param
-    : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
+    : gui_display_get_arg (dpyinfo,
+                           parms, Qfont, "font", "Font", RES_TYPE_STRING);
 
   if (!STRINGP (font))
     {
@@ -5692,7 +5699,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   long window_prompting = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object display;
-  struct w32_display_info *dpyinfo = NULL;
+  union display_info dpyinfo_u = { .w32 = NULL };
+  struct w32_display_info *dpyinfo;
   Lisp_Object parent, parent_frame;
   struct kboard *kb;
   int x_width = 0, x_height = 0;
@@ -5709,9 +5717,11 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
 
-  display = x_get_arg (dpyinfo, parameters, Qterminal, 0, 0, RES_TYPE_NUMBER);
+  display = gui_display_get_arg (dpyinfo_u,
+                                 parameters, Qterminal, 0, 0, RES_TYPE_NUMBER);
   if (EQ (display, Qunbound))
-    display = x_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
+    display = gui_display_get_arg (dpyinfo_u,
+                                   parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
   dpyinfo = check_x_display_info (display);
@@ -5720,7 +5730,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
-  name = x_get_arg (dpyinfo, parameters, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (dpyinfo_u,
+                              parameters, Qname, "name", "Name",
+                              RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
       && ! NILP (name))
@@ -5730,8 +5742,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
     Vx_resource_name = name;
 
   /* See if parent window is specified.  */
-  parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
-		      RES_TYPE_NUMBER);
+  parent = gui_display_get_arg (dpyinfo_u,
+                                parameters, Qparent_id, NULL, NULL,
+                                RES_TYPE_NUMBER);
   if (EQ (parent, Qunbound))
     parent = Qnil;
   else if (!NILP (parent))
@@ -5741,8 +5754,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   /* No need to protect DISPLAY because that's not used after passing
      it to make_frame_without_minibuffer.  */
   frame = Qnil;
-  tem = x_get_arg (dpyinfo, parameters, Qminibuffer, "minibuffer", "Minibuffer",
-		   RES_TYPE_SYMBOL);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qminibuffer, "minibuffer", "Minibuffer",
+                             RES_TYPE_SYMBOL);
   if (EQ (tem, Qnone) || NILP (tem))
     f = make_frame_without_minibuffer (Qnil, kb, display);
   else if (EQ (tem, Qonly))
@@ -5757,8 +5771,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
   XSETFRAME (frame, f);
 
-  parent_frame = x_get_arg (dpyinfo, parameters, Qparent_frame, NULL, NULL,
-			    RES_TYPE_SYMBOL);
+  parent_frame = gui_display_get_arg (dpyinfo_u,
+                                      parameters, Qparent_frame, NULL, NULL,
+                                      RES_TYPE_SYMBOL);
   /* Apply `parent-frame' parameter only when no `parent-id' was
      specified.  */
   if (!NILP (parent_frame)
@@ -5771,13 +5786,15 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   fset_parent_frame (f, parent_frame);
   store_frame_param (f, Qparent_frame, parent_frame);
 
-  tem = x_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
-		   RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qundecorated, NULL, NULL,
+                             RES_TYPE_BOOLEAN);
   FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
   store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
 
-  tem = x_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
-		   RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qskip_taskbar, NULL, NULL,
+                             RES_TYPE_BOOLEAN);
   FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
   store_frame_param (f, Qskip_taskbar,
 		     (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
@@ -5793,8 +5810,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   FRAME_FONTSET (f) = -1;
 
   fset_icon_name
-    (f, x_get_arg (dpyinfo, parameters, Qicon_name, "iconName", "Title",
-		   RES_TYPE_STRING));
+    (f, gui_display_get_arg (dpyinfo_u,
+                             parameters, Qicon_name, "iconName", "Title",
+                             RES_TYPE_STRING));
   if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
@@ -5861,8 +5879,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parameters, Qinternal_border_width,
-			 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo_u,
+                                   parameters, Qinternal_border_width,
+                                   "internalBorder", "InternalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parameters = Fcons (Fcons (Qinternal_border_width, value),
 			    parameters);
@@ -5926,12 +5946,12 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
      Also process `min-width' and `min-height' parameters right here
      because `frame-windows-min-size' needs them.  */
-  tem = x_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
-		   RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parameters, Qmin_width, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_width, tem);
-  tem = x_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
-		   RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parameters, Qmin_height, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_height, tem);
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
@@ -5983,7 +6003,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 
   window_prompting = x_figure_window_size (f, parameters, true, &x_width, &x_height);
 
-  tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
 
   w32_window (f, window_prompting, minibuffer_only);
@@ -6044,7 +6065,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
   if (!f->output_data.w32->explicit_parent)
     {
       Lisp_Object visibility
-	= x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+	= gui_display_get_arg (dpyinfo_u,
+                               parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
 
       if (EQ (visibility, Qicon))
 	x_iconify_frame (f);
@@ -6072,8 +6094,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
 	  || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
     kset_default_minibuffer_frame (kb, frame);
 
-  /* All remaining specified parameters, which have not been "used"
-     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  /* All remaining specified parameters, which have not been "used" by
+     gui_display_get_arg and friends, now go in the misc. alist of the
+     frame.  */
   for (tem = parameters; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
@@ -6854,12 +6877,14 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
 
   kb = dpyinfo->terminal->kboard;
 
-  /* The calls to x_get_arg remove elements from PARMS, so copy it to
-     avoid destructive changes behind our caller's back.  */
+  /* The calls to gui_display_get_arg remove elements from PARMS, so
+     copy it to avoid destructive changes behind our caller's
+     back.  */
   parms = Fcopy_alist (parms);
 
   /* Get the name of the frame to use for resource lookup.  */
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (U_DISPLAY_INFO_W32 (dpyinfo),
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && !EQ (name, Qunbound)
       && !NILP (name))
@@ -6928,8 +6953,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
diff --git a/src/w32gui.h b/src/w32gui.h
index dbc67993ce..5dcbbd9516 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -42,8 +42,6 @@ typedef struct _XGCValues
 typedef HBITMAP Pixmap;
 typedef HBITMAP Bitmap;
 
-typedef char * XrmDatabase;
-
 typedef XGCValues * GC;
 typedef COLORREF Color;
 typedef HWND Window;
diff --git a/src/w32reg.c b/src/w32reg.c
index aff131dd37..6500dfd279 100644
--- a/src/w32reg.c
+++ b/src/w32reg.c
@@ -21,7 +21,6 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "lisp.h"
-#include "w32term.h"	/* for XrmDatabase, xrdb */
 #include "blockinput.h"
 
 #include <stdio.h>
@@ -73,8 +72,8 @@ w32_get_rdb_resource (const char *rdb, const char *resource)
   return NULL;
 }
 
-static char *
-w32_get_string_resource (const char *name, const char *class, DWORD dwexptype)
+static const char *
+w32_get_string_resource_1 (const char *name, const char *class, DWORD dwexptype)
 {
   LPBYTE lpvalue = NULL;
   HKEY hrootkey = NULL;
@@ -134,18 +133,19 @@ w32_get_string_resource (const char *name, const char *class, DWORD dwexptype)
       /* Check if there are Windows specific defaults defined.  */
       return w32_get_rdb_resource (SYSTEM_DEFAULT_RESOURCES, name);
     }
-  return (char *)lpvalue;
+  return (const char *)lpvalue;
 }
 
 /* Retrieve the string resource specified by NAME with CLASS from
    database RDB. */
 
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+w32_get_string_resource (void *v_rdb, const char *name, const char *class)
 {
+  char *rdb = v_rdb;
   if (rdb)
     {
-      char *resource;
+      const char *resource;
 
       if ((resource = w32_get_rdb_resource (rdb, name)))
         return resource;
@@ -157,5 +157,5 @@ x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
     /* --quick was passed, so this is a no-op.  */
     return NULL;
 
-  return w32_get_string_resource (name, class, REG_SZ);
+  return w32_get_string_resource_1 (name, class, REG_SZ);
 }
diff --git a/src/w32term.c b/src/w32term.c
index bb1f0bad01..2b4957ae00 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7153,6 +7153,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
   terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
   terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
+  terminal->get_string_resource_hook = w32_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/w32term.h b/src/w32term.h
index 4c496e97e4..6cc0cedc14 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -22,6 +22,8 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "frame.h"
 #include "atimer.h"
 
+INLINE_HEADER_BEGIN
+
 /* Stack alignment stuff.  Every CALLBACK and thread function should
    have the ALIGN_STACK attribute if it manipulates Lisp objects,
    because Windows x86 32-bit ABI only guarantees 4-byte stack
@@ -120,7 +122,7 @@ struct w32_display_info
   Cursor horizontal_scroll_bar_cursor;
 
   /* Resource data base */
-  XrmDatabase xrdb;
+  char *xrdb;
 
   /* color palette information.  */
   int has_palette;
@@ -219,6 +221,14 @@ struct w32_display_info
   int cursor_display_counter;
 };
 
+INLINE union display_info
+U_DISPLAY_INFO_w32 (struct w32_display_info *dpyinfo)
+{
+  union display_info info = { .w32 = dpyinfo };
+
+  return info;
+}
+
 /* This is a chain of structures for all the displays currently in use.  */
 extern struct w32_display_info *x_display_list;
 extern struct w32_display_info one_w32_display_info;
@@ -257,6 +267,10 @@ extern int w32_kbd_mods_to_emacs (DWORD mods, WORD key);
 extern void w32con_hide_cursor (void);
 extern void w32con_show_cursor (void);
 
+/* w32reg.c */
+extern const char *w32_get_string_resource (void *v_rdb,
+                                            const char *name,
+                                            const char *class);
 \f
 #define PIX_TYPE COLORREF
 
@@ -872,3 +886,5 @@ extern void w32_init_main_thread (void);
 #ifdef CYGWIN
 extern int w32_message_fd;
 #endif /* CYGWIN */
+
+INLINE_HEADER_END
diff --git a/src/xfaces.c b/src/xfaces.c
index c6723ebe2c..c74fa9e092 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -3484,7 +3484,7 @@ ordinary `x-get-resource' doesn't take a frame argument.  */)
   CHECK_STRING (class);
   f = decode_live_frame (frame);
   block_input ();
-  value = display_x_get_resource (FRAME_DISPLAY_INFO (f),
+  value = display_x_get_resource (U_DISPLAY_INFO_X (FRAME_DISPLAY_INFO (f)),
 				  resource, class, Qnil, Qnil);
   unblock_input ();
   return value;
diff --git a/src/xfns.c b/src/xfns.c
index 13f66f0718..5d92ab9086 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2115,7 +2115,8 @@ x_default_scroll_bar_color_parameter (struct frame *f,
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Lisp_Object tem;
 
-  tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
+  tem = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                             alist, prop, xprop, xclass, RES_TYPE_STRING);
   if (EQ (tem, Qunbound))
     {
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -2126,7 +2127,8 @@ x_default_scroll_bar_color_parameter (struct frame *f,
       AUTO_STRING (background, "foreground");
       AUTO_STRING (verticalScrollBar, "verticalScrollBar");
       tem = (display_x_get_resource
-	     (dpyinfo, foreground_p ? foreground : background,
+	     (U_DISPLAY_INFO_X (dpyinfo),
+              foreground_p ? foreground : background,
 	      empty_unibyte_string,
 	      verticalScrollBar,
 	      empty_unibyte_string));
@@ -3463,8 +3465,9 @@ static void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-  Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
-                                      RES_TYPE_STRING);
+  Lisp_Object font_param = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                                                parms, Qfont, NULL, NULL,
+                                                RES_TYPE_STRING);
   Lisp_Object font = Qnil;
   if (EQ (font_param, Qunbound))
     font_param = Qnil;
@@ -3481,7 +3484,8 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
 
   if (NILP (font))
       font = !NILP (font_param) ? font_param
-      : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
+      : gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                             parms, Qfont, "font", "Font", RES_TYPE_STRING);
 
   if (! FONTP (font) && ! STRINGP (font))
     {
@@ -3581,7 +3585,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   long window_prompting = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object display;
-  struct x_display_info *dpyinfo = NULL;
+  union display_info dpyinfo_u = { .x = NULL};
+  struct x_display_info *dpyinfo;
   Lisp_Object parent, parent_frame;
   struct kboard *kb;
   int x_width = 0, x_height = 0;
@@ -3592,18 +3597,21 @@ This function is an internal primitive--use `make-frame' instead.  */)
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
 
-  display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
+  display = gui_display_get_arg (dpyinfo_u, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
   if (EQ (display, Qunbound))
-    display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
+    display = gui_display_get_arg (dpyinfo_u,
+                                   parms, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
   dpyinfo = check_x_display_info (display);
+  dpyinfo_u.x = dpyinfo;
   kb = dpyinfo->terminal->kboard;
 
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (dpyinfo_u,
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
       && ! NILP (name))
@@ -3613,15 +3621,17 @@ This function is an internal primitive--use `make-frame' instead.  */)
     Vx_resource_name = name;
 
   /* See if parent window is specified.  */
-  parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
+  parent = gui_display_get_arg (dpyinfo_u,
+                                parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
   if (EQ (parent, Qunbound))
     parent = Qnil;
   if (! NILP (parent))
     CHECK_FIXNUM (parent);
 
   frame = Qnil;
-  tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
-		   RES_TYPE_SYMBOL);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qminibuffer, "minibuffer", "Minibuffer",
+                             RES_TYPE_SYMBOL);
   if (EQ (tem, Qnone) || NILP (tem))
     f = make_frame_without_minibuffer (Qnil, kb, display);
   else if (EQ (tem, Qonly))
@@ -3634,8 +3644,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   else
     f = make_frame (true);
 
-  parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
-			    RES_TYPE_SYMBOL);
+  parent_frame = gui_display_get_arg (dpyinfo_u,
+                                      parms, Qparent_frame, NULL, NULL,
+                                      RES_TYPE_SYMBOL);
   /* Accept parent-frame iff parent-id was not specified.  */
   if (!NILP (parent)
       || EQ (parent_frame, Qunbound)
@@ -3648,16 +3659,17 @@ This function is an internal primitive--use `make-frame' instead.  */)
   fset_parent_frame (f, parent_frame);
   store_frame_param (f, Qparent_frame, parent_frame);
 
-  if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
-			       RES_TYPE_BOOLEAN)))
+  if (!NILP (tem = (gui_display_get_arg (dpyinfo_u,
+                                         parms, Qundecorated, NULL, NULL,
+                                         RES_TYPE_BOOLEAN)))
       && !(EQ (tem, Qunbound)))
     undecorated = true;
 
   FRAME_UNDECORATED (f) = undecorated;
   store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
 
-  if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
-			       RES_TYPE_BOOLEAN)))
+  if (!NILP (tem = (gui_display_get_arg (dpyinfo_u, parms, Qoverride_redirect,
+                                         NULL, NULL, RES_TYPE_BOOLEAN)))
       && !(EQ (tem, Qunbound)))
     override_redirect = true;
 
@@ -3682,8 +3694,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.x->black_relief.pixel = -1;
 
   fset_icon_name (f,
-		  x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
-			     RES_TYPE_STRING));
+		  gui_display_get_arg (dpyinfo_u,
+                                       parms, Qicon_name, "iconName", "Title",
+                                       RES_TYPE_STRING));
   if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
@@ -3792,8 +3805,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (dpyinfo_u, parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
@@ -3865,10 +3879,12 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
      Also process `min-width' and `min-height' parameters right here
      because `frame-windows-min-size' needs them.  */
-  tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u, parms, Qmin_width, NULL, NULL,
+                             RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_width, tem);
-  tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
   if (FIXNUMP (tem))
     store_frame_param (f, Qmin_height, tem);
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
@@ -3905,7 +3921,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Compute the size of the X window.  */
   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
 
-  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  tem = gui_display_get_arg (dpyinfo_u,
+                             parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
 
   x_icon_verify (f, parms);
@@ -4008,7 +4025,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   if (!f->output_data.x->explicit_parent)
     {
       Lisp_Object visibility
-	= x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+	= gui_display_get_arg (dpyinfo_u,
+                               parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
 
       if (EQ (visibility, Qicon))
 	x_iconify_frame (f);
@@ -4056,8 +4074,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
     kset_default_minibuffer_frame (kb, frame);
 
-  /* All remaining specified parameters, which have not been "used"
-     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  /* All remaining specified parameters, which have not been "used" by
+     gui_display_get_arg and friends, now go in the misc. alist of the
+     frame.  */
   for (tem = parms; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
@@ -5535,8 +5554,11 @@ select_visual (struct x_display_info *dpyinfo)
   /* See if a visual is specified.  */
   AUTO_STRING (visualClass, "visualClass");
   AUTO_STRING (VisualClass, "VisualClass");
-  Lisp_Object value = display_x_get_resource (dpyinfo, visualClass,
-					      VisualClass, Qnil, Qnil);
+  Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                              visualClass,
+					      VisualClass,
+                                              Qnil,
+                                              Qnil);
 
   if (STRINGP (value))
     {
@@ -6144,7 +6166,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
   parms = Fcopy_alist (parms);
 
   /* Get the name of the frame to use for resource lookup.  */
-  name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                              parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && !EQ (name, Qunbound)
       && !NILP (name))
@@ -6262,8 +6285,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
     {
       Lisp_Object value;
 
-      value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
-			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+      value = gui_display_get_arg (U_DISPLAY_INFO_X (dpyinfo),
+                                   parms, Qinternal_border_width,
+                                   "internalBorder", "internalBorder",
+                                   RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
 	parms = Fcons (Fcons (Qinternal_border_width, value),
 		       parms);
diff --git a/src/xrdb.c b/src/xrdb.c
index 35de446cb7..05d46324e6 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -60,12 +60,12 @@ x_get_customization_string (XrmDatabase db, const char *name,
 {
   char *full_name = alloca (strlen (name) + sizeof "customization" + 3);
   char *full_class = alloca (strlen (class) + sizeof "Customization" + 3);
-  char *result;
+  const char *result;
 
   sprintf (full_name,  "%s.%s", name,  "customization");
   sprintf (full_class, "%s.%s", class, "Customization");
 
-  result = x_get_string_resource (db, full_name, full_class);
+  result = x_get_string_resource (&db, full_name, full_class);
   return result ? xstrdup (result) : NULL;
 }
 
@@ -522,6 +522,7 @@ static int
 x_get_resource (XrmDatabase rdb, const char *name, const char *class,
 		XrmRepresentation expected_type, XrmValue *ret_value)
 {
+  fprintf (stderr, "x_get_resource\n");
   XrmValue value;
   XrmName namelist[100];
   XrmClass classlist[100];
@@ -547,19 +548,20 @@ x_get_resource (XrmDatabase rdb, const char *name, const char *class,
 /* Retrieve the string resource specified by NAME with CLASS from
    database RDB. */
 
-char *
-x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
+const char *
+x_get_string_resource (void *v_rdb, const char *name, const char *class)
 {
+  XrmDatabase *rdb = v_rdb;
   XrmValue value;
 
   if (inhibit_x_resources)
     /* --quick was passed, so this is a no-op.  */
     return NULL;
 
-  if (x_get_resource (rdb, name, class, x_rm_string, &value))
-    return (char *) value.addr;
+  if (x_get_resource (*rdb, name, class, x_rm_string, &value))
+    return (const char *) value.addr;
 
-  return 0;
+  return NULL;
 }
 \f
 /* Stand-alone test facilities.  */
@@ -648,7 +650,7 @@ main (int argc, char **argv)
 	  printf ("Class: ");
 	  gets (query_class);
 
-	  value = x_get_string_resource (xdb, query_name, query_class);
+	  value = x_get_string_resource (&xdb, query_name, query_class);
 
 	  if (value != NULL)
 	    printf ("\t%s(%s):  %s\n\n", query_name, query_class, value);
diff --git a/src/xterm.c b/src/xterm.c
index 5aa3e3ff25..8646d66f81 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -12737,8 +12737,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
 	  AUTO_STRING (privateColormap, "privateColormap");
 	  AUTO_STRING (PrivateColormap, "PrivateColormap");
 	  Lisp_Object value
-	    = display_x_get_resource (dpyinfo, privateColormap,
-				      PrivateColormap, Qnil, Qnil);
+	    = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                      privateColormap,
+				      PrivateColormap,
+                                      Qnil,
+                                      Qnil);
 	  if (STRINGP (value)
 	      && (!strcmp (SSDATA (value), "true")
 		  || !strcmp (SSDATA (value), "on")))
@@ -12955,8 +12958,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   {
     AUTO_STRING (synchronous, "synchronous");
     AUTO_STRING (Synchronous, "Synchronous");
-    Lisp_Object value = display_x_get_resource (dpyinfo, synchronous,
-						Synchronous, Qnil, Qnil);
+    Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                                synchronous,
+						Synchronous,
+                                                Qnil,
+                                                Qnil);
     if (STRINGP (value)
 	&& (!strcmp (SSDATA (value), "true")
 	    || !strcmp (SSDATA (value), "on")))
@@ -12966,8 +12972,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   {
     AUTO_STRING (useXIM, "useXIM");
     AUTO_STRING (UseXIM, "UseXIM");
-    Lisp_Object value = display_x_get_resource (dpyinfo, useXIM, UseXIM,
-						Qnil, Qnil);
+    Lisp_Object value = display_x_get_resource (U_DISPLAY_INFO_X (dpyinfo),
+                                                useXIM,
+                                                UseXIM,
+						Qnil,
+                                                Qnil);
 #ifdef USE_XIM
     if (STRINGP (value)
 	&& (!strcmp (SSDATA (value), "false")
@@ -13253,6 +13262,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
   terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
   terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
+  terminal->get_string_resource_hook = x_get_string_resource;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
   /* Other hooks are NULL by default.  */
diff --git a/src/xterm.h b/src/xterm.h
index c5ad38650c..da95926eda 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1088,6 +1088,8 @@ extern void x_real_pos_and_offsets (struct frame *f,
 XrmDatabase x_load_resources (Display *, const char *, const char *,
 			      const char *);
 
+extern const char * x_get_string_resource (void *rdb, const char *name,
+                                           const char *class);
 /* Defined in xterm.c */
 
 typedef void (*x_special_error_handler)(Display *, XErrorEvent *, char *,
@@ -1136,6 +1138,15 @@ extern void x_cr_draw_frame (cairo_t *, struct frame *);
 extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
 #endif
 
+INLINE union display_info
+U_DISPLAY_INFO_X (struct x_display_info *dpyinfo)
+{
+  union display_info info = { .x = dpyinfo };
+
+  return info;
+}
+
+
 INLINE int
 x_display_pixel_height (struct x_display_info *dpyinfo)
 {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 16:50 [RFC] Using a display_info union instead of a typedef Display_Info Alex Gramiak
  2019-04-12 17:06 ` Alex Gramiak
@ 2019-04-12 17:55 ` Eli Zaretskii
  2019-04-12 18:40   ` Alex Gramiak
  1 sibling, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2019-04-12 17:55 UTC (permalink / raw)
  To: Alex Gramiak; +Cc: monnier, emacs-devel

> From: Alex Gramiak <agrambot@gmail.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Fri, 12 Apr 2019 10:50:09 -0600
> 
> The jist of the attached patch is that generalizes x_get_string_resource
> into a terminal hook, and in the process changes several procedures to
> use union display_info instead of the typedef Display_Info, which is
> display system-dependent. One uses DISPLAY_INFO (dpyinfo) to access the
> common structure of the union, and there are macros
> U_DISPLAY_INFO_<suffix> to convert from a specific display_info to the
> union. There is also a procedure gui_frame_display_info, that grabs a
> window system display_info from a frame.
> 
> I've also included a new procedure decode_display_info, which takes the
> role of the display system-dependent check_x_display_info. I've left out
> the removal of the check_x_display_info since I'm not sure if this patch
> will be accepted. I've also left out NS support until a later stage.
> 
> WDYT?

Looks to me like replacing one set of window-system specific code with
another: still the same #ifdef's and the same window-system specific
code fragments.  Maybe I'm missing something, but it doesn't look to
me like a change for the better.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 17:55 ` Eli Zaretskii
@ 2019-04-12 18:40   ` Alex Gramiak
  2019-04-12 19:23     ` Eli Zaretskii
  0 siblings, 1 reply; 12+ messages in thread
From: Alex Gramiak @ 2019-04-12 18:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2398 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Alex Gramiak <agrambot@gmail.com>
>> Cc: Eli Zaretskii <eliz@gnu.org>, Stefan Monnier <monnier@iro.umontreal.ca>
>> Date: Fri, 12 Apr 2019 10:50:09 -0600
>> 
>> The jist of the attached patch is that generalizes x_get_string_resource
>> into a terminal hook, and in the process changes several procedures to
>> use union display_info instead of the typedef Display_Info, which is
>> display system-dependent. One uses DISPLAY_INFO (dpyinfo) to access the
>> common structure of the union, and there are macros
>> U_DISPLAY_INFO_<suffix> to convert from a specific display_info to the
>> union. There is also a procedure gui_frame_display_info, that grabs a
>> window system display_info from a frame.
>> 
>> I've also included a new procedure decode_display_info, which takes the
>> role of the display system-dependent check_x_display_info. I've left out
>> the removal of the check_x_display_info since I'm not sure if this patch
>> will be accepted. I've also left out NS support until a later stage.
>> 
>> WDYT?
>
> Looks to me like replacing one set of window-system specific code with
> another: still the same #ifdef's and the same window-system specific
> code fragments.  Maybe I'm missing something, but it doesn't look to
> me like a change for the better.

There will always have to be window-system specific code somewhere. The
difference with this patch is that the changed parts of the code will be
able to be used by multiple different window systems. That is to say, I
believe this is a necessary step towards Stefan's goal of using multiple
window systems simultaneously.

Note how before there was the implicit conditional compilation regarding
the definition of check_x_display_info and x_get_arg that allowed the
procedure to be used by _only_ 1 window system, but decode_display_info
and gui_display_get_arg would be able to handle _all_ graphical window
systems that Emacs is built with.

This currently doesn't mean any functional change as that number can
currently only be 1, but it would be nice for that to change. Again, I
believe this is (part of) the way to do so.

To show how it's used, I've included a diff that uses
decode_display_info to simplify all 3 check_x_display_info
implementations into a single conditional. (I could remove that
conditional with another terminal hook, but I'm not sure that's worth
it).


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: decode_display_info usage --]
[-- Type: text/x-patch, Size: 11501 bytes --]

diff --git a/src/dispextern.h b/src/dispextern.h
index 79a97f6d6d..fb556c906d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3589,7 +3589,6 @@ enum resource_types
   RES_TYPE_BOOLEAN_NUMBER
 };
 
-extern Display_Info *check_x_display_info (Lisp_Object);
 extern Lisp_Object gui_display_get_arg (union display_info, Lisp_Object,
                                         Lisp_Object, const char *,
                                         const char *, enum resource_types);
diff --git a/src/nsfns.m b/src/nsfns.m
index 5968b38e28..b5285ce828 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -72,40 +72,17 @@ Updated by Christian Limpach (chris@nice.ch)
    nil stands for the selected frame--or, if that is not a Nextstep frame,
    the first Nextstep display on the list.  */
 
-static struct ns_display_info *
+struct ns_display_info *
 check_ns_display_info (Lisp_Object object)
 {
-  struct ns_display_info *dpyinfo = NULL;
-
-  if (NILP (object))
-    {
-      struct frame *sf = XFRAME (selected_frame);
-
-      if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
-	dpyinfo = FRAME_DISPLAY_INFO (sf);
-      else if (x_display_list != 0)
-	dpyinfo = x_display_list;
-      else
-        error ("Nextstep windows are not in use or not initialized");
-    }
-  else if (TERMINALP (object))
-    {
-      struct terminal *t = decode_live_terminal (object);
-
-      if (t->type != output_ns)
-        error ("Terminal %d is not a Nextstep display", t->id);
-
-      dpyinfo = t->display_info.ns;
-    }
-  else if (STRINGP (object))
-    dpyinfo = ns_display_info_for_name (object);
+  if (STRINGP (object))
+    return ns_display_info_for_name (object);
   else
     {
-      struct frame *f = decode_window_system_frame (object);
-      dpyinfo = FRAME_DISPLAY_INFO (f);
-    }
+      union display_info dpyinfo_u = decode_display_info (object, output_ns);
 
-  return dpyinfo;
+      return dpyinfo_u.ns;
+    }
 }
 
 
@@ -2221,14 +2198,6 @@ Frames are listed from topmost (first) to bottommost (last).  */)
 
    ========================================================================== */
 
-/* called from frame.c */
-struct ns_display_info *
-check_x_display_info (Lisp_Object frame)
-{
-  return check_ns_display_info (frame);
-}
-
-
 void
 x_set_scroll_bar_default_width (struct frame *f)
 {
diff --git a/src/w32fns.c b/src/w32fns.c
index 4873e7866c..c6da1cef73 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -288,44 +288,26 @@ typedef BOOL (WINAPI *IsDebuggerPresent_Proc) (void);
 /* stdin, from w32console.c */
 extern HANDLE keyboard_handle;
 
+
+static struct w32_display_info *w32_display_info_for_name (Lisp_Object);
+
 /* Let the user specify a display with a frame.
    nil stands for the selected frame--or, if that is not a w32 frame,
    the first display on the list.  */
 
-struct w32_display_info *
-check_x_display_info (Lisp_Object object)
+static struct w32_display_info *
+check_w32_display_info (Lisp_Object object)
 {
-  if (NILP (object))
-    {
-      struct frame *sf = XFRAME (selected_frame);
-
-      if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
-	return FRAME_DISPLAY_INFO (sf);
-      else
-	return &one_w32_display_info;
-    }
-  else if (TERMINALP (object))
-    {
-      struct terminal *t = decode_live_terminal (object);
-
-      if (t->type != output_w32)
-	error ("Terminal %d is not a W32 display", t->id);
-
-      return t->display_info.w32;
-    }
-  else if (STRINGP (object))
-    return x_display_info_for_name (object);
+  if (STRINGP (object))
+    return w32_display_info_for_name (object);
   else
     {
-      struct frame *f;
+      union display_info dpyinfo_u = decode_display_info (object, output_w32);
 
-      CHECK_LIVE_FRAME (object);
-      f = XFRAME (object);
-      if (! FRAME_W32_P (f))
-	error ("Non-W32 frame used");
-      return FRAME_DISPLAY_INFO (f);
+      return dpyinfo_u.w32;
     }
 }
+
 \f
 /* Return the Emacs frame-object corresponding to an w32 window.
    It could be the frame's main window or an icon window.  */
@@ -5724,7 +5706,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                                    parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
-  dpyinfo = check_x_display_info (display);
+  dpyinfo = check_w32_display_info (display);
   kb = dpyinfo->terminal->kboard;
 
   if (!dpyinfo->terminal->name)
@@ -6159,7 +6141,7 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
     return Qnil;
@@ -6172,7 +6154,7 @@ DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
     return Qnil;
@@ -6185,7 +6167,7 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   return make_fixnum (x_display_pixel_width (dpyinfo));
 }
@@ -6195,7 +6177,7 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   return make_fixnum (x_display_pixel_height (dpyinfo));
 }
@@ -6205,7 +6187,7 @@ DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   return make_fixnum (dpyinfo->n_planes * dpyinfo->n_cbits);
 }
@@ -6215,7 +6197,7 @@ DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   int cap;
 
   /* Don't use NCOLORS: it returns incorrect results under remote
@@ -6262,7 +6244,7 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   HDC hdc;
   double mm_per_pixel;
 
@@ -6278,7 +6260,7 @@ DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   HDC hdc;
   double mm_per_pixel;
 
@@ -6303,7 +6285,7 @@ DEFUN ("x-display-visual-class", Fx_display_visual_class,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   Lisp_Object result = Qnil;
 
   if (dpyinfo->has_palette)
@@ -6505,7 +6487,7 @@ If omitted or nil, that stands for the selected frame's display.
 Internal use only, use `display-monitor-attributes-list' instead.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   Lisp_Object attributes_list;
 
   block_input ();
@@ -6558,8 +6540,8 @@ x_screen_planes (register struct frame *f)
 /* Return the display structure for the display named NAME.
    Open a new connection if necessary.  */
 
-struct w32_display_info *
-x_display_info_for_name (Lisp_Object name)
+static struct w32_display_info *
+w32_display_info_for_name (Lisp_Object name)
 {
   struct w32_display_info *dpyinfo;
 
@@ -6670,7 +6652,7 @@ DEFUN ("x-close-connection", Fx_close_connection,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
 
   if (dpyinfo->reference_count > 0)
     error ("Display still has frames on it");
@@ -8979,7 +8961,7 @@ return the child frames of that frame in Z (stacking) order.
 Frames are listed from topmost (first) to bottommost (last).  */)
   (Lisp_Object display)
 {
-  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  struct w32_display_info *dpyinfo = check_w32_display_info (display);
   HWND window;
 
   block_input ();
diff --git a/src/w32term.h b/src/w32term.h
index 6cc0cedc14..e4ebb620a0 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -239,8 +239,6 @@ extern int menubar_in_use;
 
 extern struct frame *x_window_to_frame (struct w32_display_info *, HWND);
 
-struct w32_display_info *x_display_info_for_name (Lisp_Object);
-
 /* also defined in xterm.h XXX: factor out to common header */
 
 extern struct w32_display_info *w32_term_init (Lisp_Object,
diff --git a/src/xfns.c b/src/xfns.c
index 5d92ab9086..7e5e5985eb 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -158,37 +158,15 @@ static void set_up_x_back_buffer (struct frame *f);
 struct x_display_info *
 check_x_display_info (Lisp_Object object)
 {
-  struct x_display_info *dpyinfo = NULL;
-
-  if (NILP (object))
-    {
-      struct frame *sf = XFRAME (selected_frame);
-
-      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
-	dpyinfo = FRAME_DISPLAY_INFO (sf);
-      else if (x_display_list != 0)
-	dpyinfo = x_display_list;
-      else
-	error ("X windows are not in use or not initialized");
-    }
-  else if (TERMINALP (object))
-    {
-      struct terminal *t = decode_live_terminal (object);
-
-      if (t->type != output_x_window)
-        error ("Terminal %d is not an X display", t->id);
-
-      dpyinfo = t->display_info.x;
-    }
-  else if (STRINGP (object))
-    dpyinfo = x_display_info_for_name (object);
+  if (STRINGP (object))
+    return x_display_info_for_name (object);
   else
     {
-      struct frame *f = decode_window_system_frame (object);
-      dpyinfo = FRAME_DISPLAY_INFO (f);
-    }
+      union display_info dpyinfo_u = decode_display_info (object,
+                                                          output_x_window);
 
-  return dpyinfo;
+      return dpyinfo_u.x;
+    }
 }
 
 /* Return the screen positions and offsets of frame F.
diff --git a/src/xterm.h b/src/xterm.h
index da95926eda..6548b0ef8c 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -497,6 +497,7 @@ extern bool use_xim;
 extern struct x_display_info *x_display_list;
 
 extern struct x_display_info *x_display_info_for_display (Display *);
+extern struct x_display_info *check_x_display_info (Lisp_Object);
 extern struct frame *x_top_window_to_frame (struct x_display_info *, int);
 extern struct x_display_info *x_term_init (Lisp_Object, char *, char *);
 extern bool x_display_ok (const char *);

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 18:40   ` Alex Gramiak
@ 2019-04-12 19:23     ` Eli Zaretskii
  2019-04-12 19:36       ` Daniel Colascione
  0 siblings, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2019-04-12 19:23 UTC (permalink / raw)
  To: Alex Gramiak; +Cc: monnier, emacs-devel

> From: Alex Gramiak <agrambot@gmail.com>
> Cc: emacs-devel@gnu.org,  monnier@iro.umontreal.ca
> Date: Fri, 12 Apr 2019 12:40:45 -0600
> 
> > Looks to me like replacing one set of window-system specific code with
> > another: still the same #ifdef's and the same window-system specific
> > code fragments.  Maybe I'm missing something, but it doesn't look to
> > me like a change for the better.
> 
> There will always have to be window-system specific code somewhere. The
> difference with this patch is that the changed parts of the code will be
> able to be used by multiple different window systems. That is to say, I
> believe this is a necessary step towards Stefan's goal of using multiple
> window systems simultaneously.
> 
> Note how before there was the implicit conditional compilation regarding
> the definition of check_x_display_info and x_get_arg that allowed the
> procedure to be used by _only_ 1 window system, but decode_display_info
> and gui_display_get_arg would be able to handle _all_ graphical window
> systems that Emacs is built with.
> 
> This currently doesn't mean any functional change as that number can
> currently only be 1, but it would be nice for that to change. Again, I
> believe this is (part of) the way to do so.

We've been through this before: if these changes don't come together
with, or closely followed by, the code to support using several
window-systems in the same session, I'd prefer not to make these
changes at this time.  The advantages you describe are at this point
theoretical, whereas the disadvantage -- making the code less familiar
for veteran Emacs hackers -- is very real.

Let's invest our time and energy in making changes that are useful
today, not in some distant future.

> To show how it's used, I've included a diff that uses
> decode_display_info to simplify all 3 check_x_display_info
> implementations into a single conditional. (I could remove that
> conditional with another terminal hook, but I'm not sure that's worth
> it).

There's a way to attain that without the massive changes you propose:
just make a single function which dispatches by the type of
output_data.  We won't be able to judge which alternative is better
until and unless we have real code which implements this feature.

Thanks.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 19:23     ` Eli Zaretskii
@ 2019-04-12 19:36       ` Daniel Colascione
  2019-04-12 19:44         ` Eli Zaretskii
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Colascione @ 2019-04-12 19:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, Alex Gramiak, emacs-devel

>> From: Alex Gramiak <agrambot@gmail.com>
>> Cc: emacs-devel@gnu.org,  monnier@iro.umontreal.ca
>> Date: Fri, 12 Apr 2019 12:40:45 -0600
>>
>> > Looks to me like replacing one set of window-system specific code with
>> > another: still the same #ifdef's and the same window-system specific
>> > code fragments.  Maybe I'm missing something, but it doesn't look to
>> > me like a change for the better.
>>
>> There will always have to be window-system specific code somewhere. The
>> difference with this patch is that the changed parts of the code will be
>> able to be used by multiple different window systems. That is to say, I
>> believe this is a necessary step towards Stefan's goal of using multiple
>> window systems simultaneously.
>>
>> Note how before there was the implicit conditional compilation regarding
>> the definition of check_x_display_info and x_get_arg that allowed the
>> procedure to be used by _only_ 1 window system, but decode_display_info
>> and gui_display_get_arg would be able to handle _all_ graphical window
>> systems that Emacs is built with.
>>
>> This currently doesn't mean any functional change as that number can
>> currently only be 1, but it would be nice for that to change. Again, I
>> believe this is (part of) the way to do so.
>
> We've been through this before: if these changes don't come together
> with, or closely followed by, the code to support using several
> window-systems in the same session, I'd prefer not to make these
> changes at this time.  The advantages you describe are at this point
> theoretical, whereas the disadvantage -- making the code less familiar
> for veteran Emacs hackers -- is very real.
>
> Let's invest our time and energy in making changes that are useful
> today, not in some distant future.
>
>> To show how it's used, I've included a diff that uses
>> decode_display_info to simplify all 3 check_x_display_info
>> implementations into a single conditional. (I could remove that
>> conditional with another terminal hook, but I'm not sure that's worth
>> it).
>
> There's a way to attain that without the massive changes you propose:
> just make a single function which dispatches by the type of
> output_data.  We won't be able to judge which alternative is better
> until and unless we have real code which implements this feature.

The way Alex proposes to do it is the right one. You're proposing using
typecases everywhere, which ends up being unmaintainable. A set of
well-defined hooks that various implements can fill is a concept that's
used all over the place, from Linux file_operations structures to C++
vtables. The efficiency argument is bogus: processors will do jump target
prediction perfectly well, because everyone uses this indirect call
technique.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 19:36       ` Daniel Colascione
@ 2019-04-12 19:44         ` Eli Zaretskii
  2019-04-12 19:55           ` Daniel Colascione
  0 siblings, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2019-04-12 19:44 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, agrambot, emacs-devel

> Date: Fri, 12 Apr 2019 12:36:22 -0700
> From: "Daniel Colascione" <dancol@dancol.org>
> Cc: "Alex Gramiak" <agrambot@gmail.com>,
>  monnier@iro.umontreal.ca,
>  emacs-devel@gnu.org
> 
> The way Alex proposes to do it is the right one.

I disagree.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 19:44         ` Eli Zaretskii
@ 2019-04-12 19:55           ` Daniel Colascione
  2019-04-12 20:12             ` Eli Zaretskii
  2019-04-14  1:17             ` Richard Stallman
  0 siblings, 2 replies; 12+ messages in thread
From: Daniel Colascione @ 2019-04-12 19:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Daniel Colascione, monnier, agrambot, emacs-devel

>> Date: Fri, 12 Apr 2019 12:36:22 -0700
>> From: "Daniel Colascione" <dancol@dancol.org>
>> Cc: "Alex Gramiak" <agrambot@gmail.com>,
>>  monnier@iro.umontreal.ca,
>>  emacs-devel@gnu.org
>>
>> The way Alex proposes to do it is the right one.
>
> I disagree.

You're wrong.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 19:55           ` Daniel Colascione
@ 2019-04-12 20:12             ` Eli Zaretskii
  2019-04-14  1:17             ` Richard Stallman
  1 sibling, 0 replies; 12+ messages in thread
From: Eli Zaretskii @ 2019-04-12 20:12 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: dancol, monnier, agrambot, emacs-devel

> Date: Fri, 12 Apr 2019 12:55:22 -0700
> From: "Daniel Colascione" <dancol@dancol.org>
> Cc: "Daniel Colascione" <dancol@dancol.org>,
>  agrambot@gmail.com,
>  monnier@iro.umontreal.ca,
>  emacs-devel@gnu.org
> 
> >> Date: Fri, 12 Apr 2019 12:36:22 -0700
> >> From: "Daniel Colascione" <dancol@dancol.org>
> >> Cc: "Alex Gramiak" <agrambot@gmail.com>,
> >>  monnier@iro.umontreal.ca,
> >>  emacs-devel@gnu.org
> >>
> >> The way Alex proposes to do it is the right one.
> >
> > I disagree.
> 
> You're wrong.

You are entitled to your wrong opinions.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 19:55           ` Daniel Colascione
  2019-04-12 20:12             ` Eli Zaretskii
@ 2019-04-14  1:17             ` Richard Stallman
  1 sibling, 0 replies; 12+ messages in thread
From: Richard Stallman @ 2019-04-14  1:17 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: eliz, dancol, monnier, agrambot, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

Saying "You're wrong" as part of something longer is a bit harsh.
Saying "You're wrong" alone, with no reasons, is quite harsh.

I don't have an opinion about this particular question, but would
people please think about being kinder in expressing views?

See https://gnu.org/philosophy/kind-communication.html.

-- 
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-12 17:06 ` Alex Gramiak
@ 2019-04-16 18:54   ` Paul Eggert
  2019-04-17 16:55     ` Eli Zaretskii
  0 siblings, 1 reply; 12+ messages in thread
From: Paul Eggert @ 2019-04-16 18:54 UTC (permalink / raw)
  To: Alex Gramiak; +Cc: emacs-devel

Thanks, this looks like a step in the right direction. I have a few
minor quibbles: function names like U_DISPLAY_INFO_X shouldn't be
lowercase, and more important DISPLAY_INFO/display_info should be a
function and not a macro, and it should return a pointer to new generic
type, 'struct generic_display_info' say, that contains only the leading
elements common to all the structures - and all the structures should be
changed to have a first member of that generic type. See the first
members of 'struct Lisp_Vector' and 'struct Lisp_Char_Table' for an
example of this.

I have my doubts about installing this in master now, as it doesn't have
direct benefit now. Ironically, one of the patches I have in mind (which
should improve overall Emacs performance significantly) involves
reverting a patch installed some years ago that was intended to be a
refactoring to do later work that was never done. So I appreciate Eli's
concern about merging this into master right away.

However, the patch seems to be a good candidate for installing into a
scratch branch that later patches can improve on, and once that branch
has direct benefits we could merge that into master.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Using a display_info union instead of a typedef Display_Info
  2019-04-16 18:54   ` Paul Eggert
@ 2019-04-17 16:55     ` Eli Zaretskii
  0 siblings, 0 replies; 12+ messages in thread
From: Eli Zaretskii @ 2019-04-17 16:55 UTC (permalink / raw)
  To: Paul Eggert; +Cc: agrambot, emacs-devel

> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 16 Apr 2019 11:54:57 -0700
> Cc: emacs-devel@gnu.org
> 
> Thanks, this looks like a step in the right direction. I have a few
> minor quibbles: function names like U_DISPLAY_INFO_X shouldn't be
> lowercase, and more important DISPLAY_INFO/display_info should be a
> function and not a macro, and it should return a pointer to new generic
> type, 'struct generic_display_info' say, that contains only the leading
> elements common to all the structures - and all the structures should be
> changed to have a first member of that generic type. See the first
> members of 'struct Lisp_Vector' and 'struct Lisp_Char_Table' for an
> example of this.

I actually don't see why we need a function.  FRAME_DISPLAY_INFO can
continue being a macro, because all it does is return a pointer to a
struct which is a member of 'struct frame'.  The struct to which
FRAME_DISPLAY_INFO will have to change to support several
window-systems in the same session, but the change can be very simple,
like what we do with 'struct font' which is then extended by the
various font backends, see for example w32font.h.  Then when some code
needs to access window-system specific parts of display_info, it will
cast the pointer returned by FRAME_DISPLAY_INFO to the correct struct,
and use the result.

> I have my doubts about installing this in master now, as it doesn't have
> direct benefit now. Ironically, one of the patches I have in mind (which
> should improve overall Emacs performance significantly) involves
> reverting a patch installed some years ago that was intended to be a
> refactoring to do later work that was never done. So I appreciate Eli's
> concern about merging this into master right away.
> 
> However, the patch seems to be a good candidate for installing into a
> scratch branch that later patches can improve on, and once that branch
> has direct benefits we could merge that into master.

IMO, if we don't want to install such changes on master soon, there's
no reason to ask Alex to work on these changes.  After all, all the
ideas, the discussions, and even the patches Alex proposed are all in
the archives, so if someone will want to work on this in the future,
they can pick up where we leave off.

FWIW, if the changes are cleaned up, and for example don't introduce
dispatch functions with platform-specific #ifdef's, but instead go the
way I described above, I'm okay with considering something like that
for master.  I didn't like the original implementation, but I don't
reject the idea itself.



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-04-17 16:55 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-12 16:50 [RFC] Using a display_info union instead of a typedef Display_Info Alex Gramiak
2019-04-12 17:06 ` Alex Gramiak
2019-04-16 18:54   ` Paul Eggert
2019-04-17 16:55     ` Eli Zaretskii
2019-04-12 17:55 ` Eli Zaretskii
2019-04-12 18:40   ` Alex Gramiak
2019-04-12 19:23     ` Eli Zaretskii
2019-04-12 19:36       ` Daniel Colascione
2019-04-12 19:44         ` Eli Zaretskii
2019-04-12 19:55           ` Daniel Colascione
2019-04-12 20:12             ` Eli Zaretskii
2019-04-14  1:17             ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).