nt/emacsclient.rc
src/gdb.ini
/var/
+
+# gsettings schema
+/etc/*.gschema.valid
# 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
# 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.
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
## 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.
### 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; \
$(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*
${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):
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 "
AC_SUBST(exec_prefix)
AC_SUBST(bindir)
AC_SUBST(datadir)
+AC_SUBST(gsettingsschemadir)
AC_SUBST(sharedstatedir)
AC_SUBST(libexecdir)
AC_SUBST(mandir)
--- /dev/null
+<?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>
--- /dev/null
+# 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])])
+]
+)
[window orderWindow: flag
relativeTo: window2];
-
#endif
return Qt;
}
}
}
+#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;
}
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;
}