aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuuki Harano2019-07-18 01:07:36 +0900
committerJeff Walsh2020-11-22 14:46:55 +1100
commit31bba950bc867e43188922a8ef03c2f07c6a784a (patch)
treece3034c5493812f3dc5a719b6bafa9d309b808e7 /src
parent519a4ac39f7cd9e2339b203463704db48752bc5b (diff)
downloademacs-31bba950bc867e43188922a8ef03c2f07c6a784a.tar.gz
emacs-31bba950bc867e43188922a8ef03c2f07c6a784a.zip
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 の置き場所を変更。
Diffstat (limited to 'src')
-rw-r--r--src/pgtkfns.c228
1 files changed, 211 insertions, 17 deletions
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 845c2c6f331..04181825b1a 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1471,7 +1471,6 @@ Some window managers may refuse to restack windows. */)
1471 1471
1472 [window orderWindow: flag 1472 [window orderWindow: flag
1473 relativeTo: window2]; 1473 relativeTo: window2];
1474
1475#endif 1474#endif
1476 return Qt; 1475 return Qt;
1477 } 1476 }
@@ -1482,22 +1481,211 @@ Some window managers may refuse to restack windows. */)
1482 } 1481 }
1483} 1482}
1484 1483
1484#ifdef HAVE_GSETTINGS
1485
1486#define RESOURCE_KEY_MAX_LEN 128
1487#define SCHEMA_ID "org.gnu.emacs.defaults"
1488#define PATH_FOR_CLASS_TYPE "/org/gnu/emacs/defaults-by-class/"
1489#define PATH_PREFIX_FOR_NAME_TYPE "/org/gnu/emacs/defaults-by-name/"
1490
1491static inline int
1492pgtk_is_lower_char (int c)
1493{
1494 return c >= 'a' && c <= 'z';
1495}
1496
1497static inline int
1498pgtk_is_upper_char (int c)
1499{
1500 return c >= 'A' && c <= 'Z';
1501}
1502
1503static inline int
1504pgtk_is_numeric_char (int c)
1505{
1506 return c >= '0' && c <= '9';
1507}
1508
1509static GSettings *
1510parse_resource_key (const char *res_key, char *setting_key)
1511{
1512 char path[32 + RESOURCE_KEY_MAX_LEN];
1513 const char *sp = res_key;
1514 char *dp;
1515
1516 /*
1517 * res_key="emacs.cursorBlink"
1518 * -> path="/org/gnu/emacs/defaults-by-name/emacs/"
1519 * setting_key="cursor-blink"
1520 *
1521 * res_key="Emacs.CursorBlink"
1522 * -> path="/org/gnu/emacs/defaults-by-class/"
1523 * setting_key="cursor-blink"
1524 *
1525 * Returns GSettings* if setting_key exists in schema, otherwise NULL.
1526 */
1527
1528 /* generate path */
1529 if (pgtk_is_upper_char(*sp)) {
1530 /* First letter is upper case. It should be "Emacs",
1531 * but don't care.
1532 */
1533 strcpy (path, PATH_FOR_CLASS_TYPE);
1534 while (*sp != '\0') {
1535 if (*sp == '.')
1536 break;
1537 sp++;
1538 }
1539 } else {
1540 strcpy (path, PATH_PREFIX_FOR_NAME_TYPE);
1541 dp = path + strlen (path);
1542 while (*sp != '\0') {
1543 int c = *sp;
1544 if (c == '.')
1545 break;
1546 if (pgtk_is_lower_char (c))
1547 (void) 0; /* lower -> NOP */
1548 else if (pgtk_is_upper_char (c))
1549 c = c - 'A' + 'a'; /* upper -> lower */
1550 else if (pgtk_is_numeric_char (c))
1551 (void) 0; /* numeric -> NOP */
1552 else
1553 return NULL; /* invalid */
1554 *dp++ = c;
1555 sp++;
1556 }
1557 *dp++ = '/'; /* must ends with '/' */
1558 *dp = '\0';
1559 }
1560
1561 if (*sp++ != '.')
1562 return NULL;
1563
1564 /* generate setting_key */
1565 dp = setting_key;
1566 while (*sp != '\0') {
1567 int c = *sp;
1568 if (pgtk_is_lower_char (c))
1569 (void) 0; /* lower -> NOP */
1570 else if (pgtk_is_upper_char (c)) {
1571 c = c - 'A' + 'a'; /* upper -> lower */
1572 if (dp != setting_key)
1573 *dp++ = '-'; /* store '-' unless first char */
1574 } else if (pgtk_is_numeric_char (c))
1575 (void) 0; /* numeric -> NOP */
1576 else
1577 return NULL; /* invalid */
1578
1579 *dp++ = c;
1580 sp++;
1581 }
1582 *dp = '\0';
1583
1584 /* check existence of setting_key */
1585 GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default ();
1586 GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, FALSE);
1587 if (!g_settings_schema_has_key (scm, setting_key)) {
1588 g_settings_schema_unref (scm);
1589 return NULL;
1590 }
1591
1592 /* create GSettings, and return it */
1593 GSettings *gs = g_settings_new_full (scm, NULL, path);
1594
1595 g_settings_schema_unref (scm);
1596 return gs;
1597}
1598
1599const char *
1600pgtk_get_defaults_value (const char *key)
1601{
1602 char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2];
1603
1604 if (strlen (key) >= RESOURCE_KEY_MAX_LEN)
1605 error ("resource key too long.");
1606
1607 GSettings *gs = parse_resource_key(key, skey);
1608 if (gs == NULL) {
1609 return NULL;
1610 }
1611
1612 gchar *str = g_settings_get_string (gs, skey);
1613
1614 /* There is no timing to free str.
1615 * So, copy it here and free it.
1616 *
1617 * MEMO: Resource values for emacs shouldn't need such a long string value.
1618 */
1619 static char holder[128];
1620 strncpy (holder, str, 128);
1621 holder[127] = '\0';
1622
1623 g_object_unref (gs);
1624 g_free (str);
1625 return holder[0] != '\0' ? holder : NULL;
1626}
1627
1628static void
1629pgtk_set_defaults_value (const char *key, const char *value)
1630{
1631 char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2];
1632
1633 if (strlen (key) >= RESOURCE_KEY_MAX_LEN)
1634 error ("resource key too long.");
1635
1636 GSettings *gs = parse_resource_key(key, skey);
1637 if (gs == NULL) {
1638 error ("unknown resource key.");
1639 }
1640 if (value != NULL) {
1641 g_settings_set_string (gs, skey, value);
1642 } else {
1643 g_settings_reset (gs, skey);
1644 }
1645
1646 g_object_unref (gs);
1647}
1648
1649#undef RESOURCE_KEY_MAX_LEN
1650#undef SCHEMA_ID
1651#undef PATH_FOR_CLASS_TYPE
1652#undef PATH_PREFIX_FOR_NAME_TYPE
1653
1654#else /* not HAVE_GSETTINGS */
1655
1485const char * 1656const char *
1486pgtk_get_defaults_value (const char *key) 1657pgtk_get_defaults_value (const char *key)
1487{ 1658{
1488 return NULL; 1659 return NULL;
1489} 1660}
1490 1661
1491DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 3, 3, 0, 1662static void
1492 doc: /* Set property NAME of OWNER to VALUE, from the defaults database. 1663pgtk_set_defaults_value (const char *key, const char *value)
1493If OWNER is nil, Emacs is assumed. 1664{
1494If VALUE is nil, the default is removed. */) 1665 error ("gsettings not supported.");
1495 (Lisp_Object owner, Lisp_Object name, Lisp_Object value) 1666}
1667
1668#endif
1669
1670
1671DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 2, 2, 0,
1672 doc: /* Set the value of ATTRIBUTE, of class CLASS, as VALUE, into defaults database. */)
1673 (Lisp_Object attribute, Lisp_Object value)
1496{ 1674{
1497 check_window_system (NULL); 1675 check_window_system (NULL);
1498 if (NILP (owner)) 1676
1499 owner = build_string (pgtk_app_name); 1677 CHECK_STRING (attribute);
1500 CHECK_STRING (name); 1678 if (!NILP (value))
1679 CHECK_STRING (value);
1680
1681 char *res = SSDATA (Vx_resource_name);
1682 char *attr = SSDATA (attribute);
1683 if (attr[0] >= 'A' && attr[0] <= 'Z')
1684 res = SSDATA (Vx_resource_class);
1685
1686 char *key = g_strdup_printf("%s.%s", res, attr);
1687
1688 pgtk_set_defaults_value(key, NILP (value) ? NULL : SSDATA (value));
1501 1689
1502 return Qnil; 1690 return Qnil;
1503} 1691}
@@ -1794,20 +1982,26 @@ pgtk_set_scroll_bar_default_height (struct frame *f)
1794const char * 1982const char *
1795pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class) 1983pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
1796{ 1984{
1797 /* remove appname prefix; TODO: allow for !="Emacs" */
1798 const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
1799
1800 check_window_system (NULL); 1985 check_window_system (NULL);
1801 1986
1802 if (inhibit_x_resources) 1987 if (inhibit_x_resources)
1803 /* --quick was passed, so this is a no-op. */ 1988 /* --quick was passed, so this is a no-op. */
1804 return NULL; 1989 return NULL;
1805 1990
1806 res = pgtk_get_defaults_value (toCheck); 1991 const char *res = pgtk_get_defaults_value (name);
1807 return (char *) (!res ? NULL 1992 if (res == NULL)
1808 : !c_strncasecmp (res, "YES", 3) ? "true" 1993 res = pgtk_get_defaults_value (class);
1809 : !c_strncasecmp (res, "NO", 2) ? "false" 1994
1810 : res); 1995 if (res == NULL)
1996 return NULL;
1997
1998 if (c_strncasecmp (res, "YES", 3) == 0)
1999 return "true";
2000
2001 if (c_strncasecmp (res, "NO", 2) == 0)
2002 return "false";
2003
2004 return res;
1811} 2005}
1812 2006
1813 2007