emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk 31bba95 023/100: Use gsettings instead of X resource databa


From: Yuuki Harano
Subject: feature/pgtk 31bba95 023/100: Use gsettings instead of X resource database
Date: Tue, 24 Nov 2020 08:02:29 -0500 (EST)

branch: feature/pgtk
commit 31bba950bc867e43188922a8ef03c2f07c6a784a
Author: Yuuki Harano <masm+github@masm11.me>
Commit: Jeff Walsh <fejfighter@gmail.com>

    Use gsettings instead of X resource database
    
    * src/pgtkfns.c (pgtk_is_lower_char, pgtk_is_upper_char)
    (pgtk_is_numeric_char, parse_resource_key)
    (pgtk_get_defaults_value, pgtk_set_defaults_value)
    (Fpgtk_set_resource, pgtk_get_string_resource): handle gsettings scheme
    
    * m4/gsettings.m4: new file
    
    * etc/org.gnu.emacs.defaults.gschema.xml: new file
    
    * configure.ac (GLIB_DISABLE_DEPRECATION_WARNINGS)
    (gsettingsschemadir):
    
    * Makefile.in (gsettingsschemadir, GLIB_COMPILE_SCHEMAS)
    (install, uninstall, clean):
    
    * .gitignore: add gschema
    
    *.gschema.valid は生成ファイルなので無視。
    
    schema の置き場所を変更。
---
 .gitignore                             |   3 +
 Makefile.in                            |  22 +++-
 configure.ac                           |   4 +
 etc/org.gnu.emacs.defaults.gschema.xml |  48 +++++++
 m4/gsettings.m4                        |  88 +++++++++++++
 src/pgtkfns.c                          | 228 ++++++++++++++++++++++++++++++---
 6 files changed, 372 insertions(+), 21 deletions(-)

diff --git a/.gitignore b/.gitignore
index bf7e934..8ac0f48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -298,3 +298,6 @@ nt/emacs.rc
 nt/emacsclient.rc
 src/gdb.ini
 /var/
+
+# gsettings schema
+/etc/*.gschema.valid
diff --git a/Makefile.in b/Makefile.in
index fbb1891..984c619 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -216,6 +216,9 @@ icondir=$(datarootdir)/icons
 # The source directory for the icon files.
 iconsrcdir=$(srcdir)/etc/images/icons
 
+# Where to install the gsettings schema file.
+gsettingsschemadir = @gsettingsschemadir@
+
 # ==================== Emacs-specific directories ====================
 
 # These variables hold the values Emacs will actually use.  They are
@@ -300,6 +303,8 @@ LN_S_FILEONLY = @LN_S_FILEONLY@
 # We use gzip to compress installed .el and some .txt files.
 GZIP_PROG = @GZIP_PROG@
 
+GLIB_COMPILE_SCHEMAS = glib-compile-schemas
+
 # ============================= Targets ==============================
 
 # Program name transformation.
@@ -330,7 +335,9 @@ CONFIG_STATUS_FILES_IN = \
 COPYDIR = ${srcdir}/etc ${srcdir}/lisp
 COPYDESTS = "$(DESTDIR)${etcdir}" "$(DESTDIR)${lispdir}"
 
-all: ${SUBDIR} info
+gsettings_SCHEMAS = etc/org.gnu.emacs.defaults.gschema.xml
+
+all: ${SUBDIR} info $(gsettings_SCHEMAS:.xml=.valid)
 
 .PHONY: all ${SUBDIR} blessmail epaths-force epaths-force-w32 etc-emacsver
 
@@ -468,7 +475,7 @@ $(srcdir)/configure: $(srcdir)/configure.ac 
$(srcdir)/m4/*.m4
 ## don't have to duplicate the list of utilities to install in
 ## this Makefile as well.
 
-install: all install-arch-indep install-etcdoc install-arch-dep 
install-$(NTDIR) blessmail
+install: all install-arch-indep install-etcdoc install-arch-dep 
install-$(NTDIR) blessmail install-gsettings-schemas
        @true
 
 ## Ensure that $subdir contains a subdirs.el file.
@@ -760,7 +767,7 @@ install-strip:
 ### create (but not the noninstalled files such as 'make all' would create).
 ###
 ### Don't delete the lisp and etc directories if they're in the source tree.
-uninstall: uninstall-$(NTDIR) uninstall-doc
+uninstall: uninstall-$(NTDIR) uninstall-doc uninstall-gsettings-schemas
        rm -f "$(DESTDIR)$(includedir)/emacs-module.h"
        $(MAKE) -C lib-src uninstall
        -unset CDPATH; \
@@ -857,7 +864,7 @@ clean_dirs = $(mostlyclean_dirs) nextstep
 
 $(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean)))
 
-clean: $(clean_dirs:=_clean)
+clean: $(clean_dirs:=_clean) clean-gsettings-schemas
        $(MAKE) -C admin/charsets $@
        [ ! -d test ] || $(MAKE) -C test $@
        -rm -f ./*.tmp etc/*.tmp*
@@ -1194,3 +1201,10 @@ gitmerge:
        ${GITMERGE_EMACS} -batch --no-site-file --no-site-lisp \
          -l ${srcdir}/admin/gitmerge.el \
          --eval '(setq gitmerge-minimum-missing ${GITMERGE_NMIN})' -f gitmerge
+
+@GSETTINGS_RULES@
+
+install-gsettings-schemas:
+uninstall-gsettings-schemas:
+clean-gsettings-schemas:
+$(gsettings_SCHEMAS:.xml=.valid):
diff --git a/configure.ac b/configure.ac
index ce9d016..6d3652d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2683,6 +2683,9 @@ if test "${opsys}" != "mingw32"; then
         AC_DEFINE([GLIB_DISABLE_DEPRECATION_WARNINGS], [1],
           [Define to 1 to disable Glib deprecation warnings.])
        fi
+       if test "$window_system" = pgtk; then
+         GLIB_GSETTINGS
+       fi
     else
        check_gtk2=yes
        gtk3_pkg_errors="$GTK_PKG_ERRORS "
@@ -5297,6 +5300,7 @@ AC_SUBST(prefix)
 AC_SUBST(exec_prefix)
 AC_SUBST(bindir)
 AC_SUBST(datadir)
+AC_SUBST(gsettingsschemadir)
 AC_SUBST(sharedstatedir)
 AC_SUBST(libexecdir)
 AC_SUBST(mandir)
diff --git a/etc/org.gnu.emacs.defaults.gschema.xml 
b/etc/org.gnu.emacs.defaults.gschema.xml
new file mode 100644
index 0000000..6f2c791
--- /dev/null
+++ b/etc/org.gnu.emacs.defaults.gschema.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<schemalist>
+
+  <schema id="org.gnu.emacs.defaults">
+
+    <key name='alpha'                    type='s'><default>''</default></key>
+    <key name='auto-raise-lower'         type='s'><default>''</default></key>
+    <key name='auto-lower'               type='s'><default>''</default></key>
+    <key name='auto-raise'               type='s'><default>''</default></key>
+    <key name='background'               type='s'><default>''</default></key>
+    <key name='background-mode'          type='s'><default>''</default></key>
+    <key name='bitmap-icon'              type='s'><default>''</default></key>
+    <key name='border-color'             type='s'><default>''</default></key>
+    <key name='border-width'             type='s'><default>''</default></key>
+    <key name='buffer-predicate'         type='s'><default>''</default></key>
+    <key name='cursor-blink'             type='s'><default>''</default></key>
+    <key name='cursor-type'              type='s'><default>''</default></key>
+    <key name='cursor-color'             type='s'><default>''</default></key>
+    <key name='font'                     type='s'><default>''</default></key>
+    <key name='font-backend'             type='s'><default>''</default></key>
+    <key name='foreground'               type='s'><default>''</default></key>
+    <key name='fullscreen'               type='s'><default>''</default></key>
+    <key name='horizontal-scroll-bars'   type='s'><default>''</default></key>
+    <key name='icon-name'                type='s'><default>''</default></key>
+    <key name='inhibit-double-buffering' type='s'><default>''</default></key>
+    <key name='internal-border'          type='s'><default>''</default></key>
+    <key name='internal-border-width'    type='s'><default>''</default></key>
+    <key name='left-fringe'              type='s'><default>''</default></key>
+    <key name='line-spacing'             type='s'><default>''</default></key>
+    <key name='menu-bar'                 type='s'><default>''</default></key>
+    <key name='minibuffer'               type='s'><default>''</default></key>
+    <key name='name'                     type='s'><default>''</default></key>
+    <key name='pointer-color'            type='s'><default>''</default></key>
+    <key name='reverse-video'            type='s'><default>''</default></key>
+    <key name='right-fringe'             type='s'><default>''</default></key>
+    <key name='screen-gamma'             type='s'><default>''</default></key>
+    <key name='scroll-bar'               type='s'><default>''</default></key>
+    <key name='scroll-bar-height'        type='s'><default>''</default></key>
+    <key name='scroll-bar-width'         type='s'><default>''</default></key>
+    <key name='scroll-bars'              type='s'><default>''</default></key>
+    <key name='title'                    type='s'><default>''</default></key>
+    <key name='tool-bar'                 type='s'><default>''</default></key>
+    <key name='vertical-scroll-bars'     type='s'><default>''</default></key>
+    <key name='wait-for-w-m'             type='s'><default>''</default></key>
+
+  </schema>
+
+</schemalist>
diff --git a/m4/gsettings.m4 b/m4/gsettings.m4
new file mode 100644
index 0000000..882e6a8
--- /dev/null
+++ b/m4/gsettings.m4
@@ -0,0 +1,88 @@
+# Increment this whenever this file is changed.
+#serial 2
+
+dnl GLIB_GSETTINGS
+dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether
+dnl the schema should be compiled
+dnl
+
+AC_DEFUN([GLIB_GSETTINGS],
+[
+  dnl We can't use PKG_PREREQ because that needs 0.29.
+  m4_ifndef([PKG_PROG_PKG_CONFIG],
+            [pkg.m4 version 0.28 or later is required])
+
+  m4_pattern_allow([AM_V_GEN])
+  AC_ARG_ENABLE(schemas-compile,
+                AS_HELP_STRING([--disable-schemas-compile],
+                               [Disable regeneration of gschemas.compiled on 
install]),
+                [case ${enableval} in
+                  yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE=""  ;;
+                  no)  GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;;
+                  *) AC_MSG_ERROR([bad value ${enableval} for 
--enable-schemas-compile]) ;;
+                 esac])
+  AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE])
+  PKG_PROG_PKG_CONFIG([0.16])
+  AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas])
+  AS_IF([test x$cross_compiling != xyes],
+        [PKG_CHECK_VAR([GLIB_COMPILE_SCHEMAS], [gio-2.0], 
[glib_compile_schemas])],
+        [AC_PATH_PROG([GLIB_COMPILE_SCHEMAS], [glib-compile-schemas])])
+  AC_SUBST(GLIB_COMPILE_SCHEMAS)
+  if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then
+    ifelse([$2],,[AC_MSG_ERROR([glib-compile-schemas not found.])],[$2])
+  else
+    ifelse([$1],,[:],[$1])
+  fi
+
+  GSETTINGS_RULES='
+.PHONY : uninstall-gsettings-schemas install-gsettings-schemas 
clean-gsettings-schemas
+
+mostlyclean-am: clean-gsettings-schemas
+
+gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE))
+
+%.gschema.valid: %.gschema.xml $(gsettings__enum_file)
+       $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix 
--schema-file=,$(gsettings__enum_file)) --schema-file=$< && mkdir -p [$](@D) && 
touch [$]@
+
+all-am: $(gsettings_SCHEMAS:.xml=.valid)
+uninstall-am: uninstall-gsettings-schemas
+install-data-am: install-gsettings-schemas
+
+.SECONDARY: $(gsettings_SCHEMAS)
+
+install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file)
+       @$(NORMAL_INSTALL)
+       if test -n "$^"; then \
+               test -z "$(gsettingsschemadir)" || $(MKDIR_P) 
"$(DESTDIR)$(gsettingsschemadir)"; \
+               $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \
+               test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || 
$(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \
+       fi
+
+uninstall-gsettings-schemas:
+       @$(NORMAL_UNINSTALL)
+       @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n 
"$(gsettingsschemadir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files 
")"; \
+       cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files
+       test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || 
$(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir)
+
+clean-gsettings-schemas:
+       rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file)
+
+ifdef gsettings_ENUM_NAMESPACE
+$(gsettings__enum_file): $(gsettings_ENUM_FILES)
+       $(AM_V_GEN) glib-mkenums --comments '\''<!-- @comment@ -->'\'' --fhead 
"<schemalist>" --vhead "  <@type@ 
id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod "    <value 
nick='\''@valuenick@'\'' value='\''@valuenum@'\''/>" --vtail "  </@type@>" 
--ftail "</schemalist>" [$]^ > [$]@.tmp && mv [$]@.tmp [$]@
+endif
+'
+  _GSETTINGS_SUBST(GSETTINGS_RULES)
+])
+
+dnl _GSETTINGS_SUBST(VARIABLE)
+dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
+AC_DEFUN([_GSETTINGS_SUBST],
+[
+AC_SUBST([$1])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
+]
+)
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 845c2c6..0418182 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1471,7 +1471,6 @@ Some window managers may refuse to restack windows.  */)
 
       [window orderWindow: flag
                relativeTo: window2];
-
 #endif
       return Qt;
     }
@@ -1482,22 +1481,211 @@ Some window managers may refuse to restack windows.  
*/)
     }
 }
 
+#ifdef HAVE_GSETTINGS
+
+#define RESOURCE_KEY_MAX_LEN 128
+#define SCHEMA_ID "org.gnu.emacs.defaults"
+#define PATH_FOR_CLASS_TYPE "/org/gnu/emacs/defaults-by-class/"
+#define PATH_PREFIX_FOR_NAME_TYPE "/org/gnu/emacs/defaults-by-name/"
+
+static inline int
+pgtk_is_lower_char (int c)
+{
+  return c >= 'a' && c <= 'z';
+}
+
+static inline int
+pgtk_is_upper_char (int c)
+{
+  return c >= 'A' && c <= 'Z';
+}
+
+static inline int
+pgtk_is_numeric_char (int c)
+{
+  return c >= '0' && c <= '9';
+}
+
+static GSettings *
+parse_resource_key (const char *res_key, char *setting_key)
+{
+  char path[32 + RESOURCE_KEY_MAX_LEN];
+  const char *sp = res_key;
+  char *dp;
+
+  /*
+   * res_key="emacs.cursorBlink"
+   *   -> path="/org/gnu/emacs/defaults-by-name/emacs/"
+   *      setting_key="cursor-blink"
+   *
+   * res_key="Emacs.CursorBlink"
+   *   -> path="/org/gnu/emacs/defaults-by-class/"
+   *      setting_key="cursor-blink"
+   *
+   * Returns GSettings* if setting_key exists in schema, otherwise NULL.
+   */
+
+  /* generate path */
+  if (pgtk_is_upper_char(*sp)) {
+    /* First letter is upper case. It should be "Emacs",
+     * but don't care.
+     */
+    strcpy (path, PATH_FOR_CLASS_TYPE);
+    while (*sp != '\0') {
+      if (*sp == '.')
+       break;
+      sp++;
+    }
+  } else {
+    strcpy (path, PATH_PREFIX_FOR_NAME_TYPE);
+    dp = path + strlen (path);
+    while (*sp != '\0') {
+      int c = *sp;
+      if (c == '.')
+       break;
+      if (pgtk_is_lower_char (c))
+       (void) 0;               /* lower -> NOP */
+      else if (pgtk_is_upper_char (c))
+       c = c - 'A' + 'a';      /* upper -> lower */
+      else if (pgtk_is_numeric_char (c))
+       (void) 0;               /* numeric -> NOP */
+      else
+       return NULL;            /* invalid */
+      *dp++ = c;
+      sp++;
+    }
+    *dp++ = '/';       /* must ends with '/' */
+    *dp = '\0';
+  }
+
+  if (*sp++ != '.')
+    return NULL;
+
+  /* generate setting_key */
+  dp = setting_key;
+  while (*sp != '\0') {
+    int c = *sp;
+    if (pgtk_is_lower_char (c))
+      (void) 0;                        /* lower -> NOP */
+    else if (pgtk_is_upper_char (c)) {
+      c = c - 'A' + 'a';       /* upper -> lower */
+      if (dp != setting_key)
+       *dp++ = '-';            /* store '-' unless first char */
+    } else if (pgtk_is_numeric_char (c))
+      (void) 0;                        /* numeric -> NOP */
+    else
+      return NULL;             /* invalid */
+
+    *dp++ = c;
+    sp++;
+  }
+  *dp = '\0';
+
+  /* check existence of setting_key */
+  GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default ();
+  GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, 
FALSE);
+  if (!g_settings_schema_has_key (scm, setting_key)) {
+    g_settings_schema_unref (scm);
+    return NULL;
+  }
+
+  /* create GSettings, and return it */
+  GSettings *gs = g_settings_new_full (scm, NULL, path);
+
+  g_settings_schema_unref (scm);
+  return gs;
+}
+
+const char *
+pgtk_get_defaults_value (const char *key)
+{
+  char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2];
+
+  if (strlen (key) >= RESOURCE_KEY_MAX_LEN)
+    error ("resource key too long.");
+
+  GSettings *gs = parse_resource_key(key, skey);
+  if (gs == NULL) {
+    return NULL;
+  }
+
+  gchar *str = g_settings_get_string (gs, skey);
+
+  /* There is no timing to free str.
+   * So, copy it here and free it.
+   *
+   * MEMO: Resource values for emacs shouldn't need such a long string value.
+   */
+  static char holder[128];
+  strncpy (holder, str, 128);
+  holder[127] = '\0';
+
+  g_object_unref (gs);
+  g_free (str);
+  return holder[0] != '\0' ? holder : NULL;
+}
+
+static void
+pgtk_set_defaults_value (const char *key, const char *value)
+{
+  char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2];
+
+  if (strlen (key) >= RESOURCE_KEY_MAX_LEN)
+    error ("resource key too long.");
+
+  GSettings *gs = parse_resource_key(key, skey);
+  if (gs == NULL) {
+    error ("unknown resource key.");
+  }
+  if (value != NULL) {
+    g_settings_set_string (gs, skey, value);
+  } else {
+    g_settings_reset (gs, skey);
+  }
+
+  g_object_unref (gs);
+}
+
+#undef RESOURCE_KEY_MAX_LEN
+#undef SCHEMA_ID
+#undef PATH_FOR_CLASS_TYPE
+#undef PATH_PREFIX_FOR_NAME_TYPE
+
+#else /* not HAVE_GSETTINGS */
+
 const char *
 pgtk_get_defaults_value (const char *key)
 {
   return NULL;
 }
 
-DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 3, 3, 0,
-       doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
-If OWNER is nil, Emacs is assumed.
-If VALUE is nil, the default is removed.  */)
-     (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
+static void
+pgtk_set_defaults_value (const char *key, const char *value)
+{
+  error ("gsettings not supported.");
+}
+
+#endif
+
+
+DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 2, 2, 0,
+       doc: /* Set the value of ATTRIBUTE, of class CLASS, as VALUE, into 
defaults database. */)
+     (Lisp_Object attribute, Lisp_Object value)
 {
   check_window_system (NULL);
-  if (NILP (owner))
-    owner = build_string (pgtk_app_name);
-  CHECK_STRING (name);
+
+  CHECK_STRING (attribute);
+  if (!NILP (value))
+    CHECK_STRING (value);
+
+  char *res = SSDATA (Vx_resource_name);
+  char *attr = SSDATA (attribute);
+  if (attr[0] >= 'A' && attr[0] <= 'Z')
+    res = SSDATA (Vx_resource_class);
+
+  char *key = g_strdup_printf("%s.%s", res, attr);
+
+  pgtk_set_defaults_value(key, NILP (value) ? NULL : SSDATA (value));
 
   return Qnil;
 }
@@ -1794,20 +1982,26 @@ pgtk_set_scroll_bar_default_height (struct frame *f)
 const char *
 pgtk_get_string_resource (XrmDatabase 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);
-
   check_window_system (NULL);
 
   if (inhibit_x_resources)
     /* --quick was passed, so this is a no-op.  */
     return NULL;
 
-  res = pgtk_get_defaults_value (toCheck);
-  return (char *) (!res ? NULL
-                  : !c_strncasecmp (res, "YES", 3) ? "true"
-                  : !c_strncasecmp (res, "NO", 2) ? "false"
-                  : res);
+  const char *res = pgtk_get_defaults_value (name);
+  if (res == NULL)
+    res = pgtk_get_defaults_value (class);
+
+  if (res == NULL)
+    return NULL;
+
+  if (c_strncasecmp (res, "YES", 3) == 0)
+    return "true";
+
+  if (c_strncasecmp (res, "NO", 2) == 0)
+    return "false";
+
+  return res;
 }
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]