344 |
CFNumberRef number; |
CFNumberRef number; |
345 |
{ |
{ |
346 |
Lisp_Object result = Qnil; |
Lisp_Object result = Qnil; |
347 |
#if BITS_PER_EMACS_INT > 32 |
#if BITS_PER_EMACS_INT > 32 |
348 |
SInt64 int_val; |
SInt64 int_val; |
349 |
CFNumberType emacs_int_type = kCFNumberSInt64Type; |
CFNumberType emacs_int_type = kCFNumberSInt64Type; |
350 |
#else |
#else |
667 |
if (NILP (component)) |
if (NILP (component)) |
668 |
return Qnil; |
return Qnil; |
669 |
|
|
670 |
result = Fcons (component, result); |
result = Fcons (component, result); |
671 |
while (binding = parse_binding (p)) |
while (binding = parse_binding (p)) |
672 |
{ |
{ |
673 |
if (binding == '*') |
if (binding == '*') |
678 |
else |
else |
679 |
result = Fcons (component, result); |
result = Fcons (component, result); |
680 |
} |
} |
681 |
|
|
682 |
/* The final component should not be '?'. */ |
/* The final component should not be '?'. */ |
683 |
if (EQ (component, SINGLE_COMPONENT)) |
if (EQ (component, SINGLE_COMPONENT)) |
684 |
return Qnil; |
return Qnil; |
766 |
q = buf + total_len; |
q = buf + total_len; |
767 |
for (; CONSP (seq); seq = XCDR (seq)) |
for (; CONSP (seq); seq = XCDR (seq)) |
768 |
{ |
{ |
769 |
len = SBYTES (XCAR (seq)); |
len = SBYTES (XCAR (seq)); |
770 |
q -= len; |
q -= len; |
771 |
memcpy (q, SDATA (XCAR (seq)), len); |
memcpy (q, SDATA (XCAR (seq)), len); |
772 |
} |
} |
812 |
An X Resource Database acts as a collection of resource names and |
An X Resource Database acts as a collection of resource names and |
813 |
associated values. It is implemented as a trie on quarks. Namely, |
associated values. It is implemented as a trie on quarks. Namely, |
814 |
each edge is labeled by either a string, LOOSE_BINDING, or |
each edge is labeled by either a string, LOOSE_BINDING, or |
815 |
SINGLE_COMPONENT. Nodes of the trie are implemented as Lisp hash |
SINGLE_COMPONENT. Each node has a node id, which is a unique |
816 |
tables, and a value associated with a resource name is recorded as |
nonnegative integer, and the root node id is 0. A database is |
817 |
a value for HASHKEY_TERMINAL at the hash table whose path from the |
implemented as a hash table that maps a pair (SRC-NODE-ID . |
818 |
root is the quarks of the resource name. */ |
EDGE-LABEL) to DEST-NODE-ID. It also holds a maximum node id used |
819 |
|
in the table as a value for HASHKEY_MAX_NID. A value associated to |
820 |
|
a node is recorded as a value for the node id. */ |
821 |
|
|
822 |
#define HASHKEY_TERMINAL Qt /* "T"erminal */ |
#define HASHKEY_MAX_NID (make_number (0)) |
823 |
|
|
824 |
static XrmDatabase |
static XrmDatabase |
825 |
xrm_create_database () |
xrm_create_database () |
826 |
{ |
{ |
827 |
return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), |
XrmDatabase database; |
828 |
make_float (DEFAULT_REHASH_SIZE), |
|
829 |
make_float (DEFAULT_REHASH_THRESHOLD), |
database = make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), |
830 |
Qnil, Qnil, Qnil); |
make_float (DEFAULT_REHASH_SIZE), |
831 |
|
make_float (DEFAULT_REHASH_THRESHOLD), |
832 |
|
Qnil, Qnil, Qnil); |
833 |
|
Fputhash (HASHKEY_MAX_NID, make_number (0), database); |
834 |
|
|
835 |
|
return database; |
836 |
} |
} |
837 |
|
|
838 |
static void |
static void |
840 |
XrmDatabase database; |
XrmDatabase database; |
841 |
Lisp_Object quarks, value; |
Lisp_Object quarks, value; |
842 |
{ |
{ |
843 |
struct Lisp_Hash_Table *h; |
struct Lisp_Hash_Table *h = XHASH_TABLE (database); |
844 |
unsigned hash_code; |
unsigned hash_code; |
845 |
int i; |
int max_nid, i; |
846 |
|
Lisp_Object node_id, key; |
847 |
|
|
848 |
|
max_nid = XINT (Fgethash (HASHKEY_MAX_NID, database, Qnil)); |
849 |
|
|
850 |
|
XSETINT (node_id, 0); |
851 |
for (; CONSP (quarks); quarks = XCDR (quarks)) |
for (; CONSP (quarks); quarks = XCDR (quarks)) |
852 |
{ |
{ |
853 |
h = XHASH_TABLE (database); |
key = Fcons (node_id, XCAR (quarks)); |
854 |
i = hash_lookup (h, XCAR (quarks), &hash_code); |
i = hash_lookup (h, key, &hash_code); |
855 |
if (i < 0) |
if (i < 0) |
856 |
{ |
{ |
857 |
database = xrm_create_database (); |
max_nid++; |
858 |
hash_put (h, XCAR (quarks), database, hash_code); |
XSETINT (node_id, max_nid); |
859 |
|
hash_put (h, key, node_id, hash_code); |
860 |
} |
} |
861 |
else |
else |
862 |
database = HASH_VALUE (h, i); |
node_id = HASH_VALUE (h, i); |
863 |
} |
} |
864 |
|
Fputhash (node_id, value, database); |
865 |
|
|
866 |
Fputhash (HASHKEY_TERMINAL, value, database); |
Fputhash (HASHKEY_MAX_NID, make_number (max_nid), database); |
867 |
} |
} |
868 |
|
|
869 |
/* Merge multiple resource entries specified by DATA into a resource |
/* Merge multiple resource entries specified by DATA into a resource |
888 |
} |
} |
889 |
|
|
890 |
static Lisp_Object |
static Lisp_Object |
891 |
xrm_q_get_resource (database, quark_name, quark_class) |
xrm_q_get_resource_1 (database, node_id, quark_name, quark_class) |
892 |
XrmDatabase database; |
XrmDatabase database; |
893 |
Lisp_Object quark_name, quark_class; |
Lisp_Object node_id, quark_name, quark_class; |
894 |
{ |
{ |
895 |
struct Lisp_Hash_Table *h = XHASH_TABLE (database); |
struct Lisp_Hash_Table *h = XHASH_TABLE (database); |
896 |
Lisp_Object keys[3], value; |
Lisp_Object key, labels[3], value; |
897 |
int i, k; |
int i, k; |
898 |
|
|
899 |
if (!CONSP (quark_name)) |
if (!CONSP (quark_name)) |
900 |
return Fgethash (HASHKEY_TERMINAL, database, Qnil); |
return Fgethash (node_id, database, Qnil); |
901 |
|
|
902 |
/* First, try tight bindings */ |
/* First, try tight bindings */ |
903 |
keys[0] = XCAR (quark_name); |
labels[0] = XCAR (quark_name); |
904 |
keys[1] = XCAR (quark_class); |
labels[1] = XCAR (quark_class); |
905 |
keys[2] = SINGLE_COMPONENT; |
labels[2] = SINGLE_COMPONENT; |
906 |
|
|
907 |
for (k = 0; k < sizeof (keys) / sizeof (*keys); k++) |
key = Fcons (node_id, Qnil); |
908 |
|
for (k = 0; k < sizeof (labels) / sizeof (*labels); k++) |
909 |
{ |
{ |
910 |
i = hash_lookup (h, keys[k], NULL); |
XSETCDR (key, labels[k]); |
911 |
|
i = hash_lookup (h, key, NULL); |
912 |
if (i >= 0) |
if (i >= 0) |
913 |
{ |
{ |
914 |
value = xrm_q_get_resource (HASH_VALUE (h, i), |
value = xrm_q_get_resource_1 (database, HASH_VALUE (h, i), |
915 |
XCDR (quark_name), XCDR (quark_class)); |
XCDR (quark_name), XCDR (quark_class)); |
916 |
if (!NILP (value)) |
if (!NILP (value)) |
917 |
return value; |
return value; |
918 |
} |
} |
919 |
} |
} |
920 |
|
|
921 |
/* Then, try loose bindings */ |
/* Then, try loose bindings */ |
922 |
i = hash_lookup (h, LOOSE_BINDING, NULL); |
XSETCDR (key, LOOSE_BINDING); |
923 |
|
i = hash_lookup (h, key, NULL); |
924 |
if (i >= 0) |
if (i >= 0) |
925 |
{ |
{ |
926 |
value = xrm_q_get_resource (HASH_VALUE (h, i), quark_name, quark_class); |
value = xrm_q_get_resource_1 (database, HASH_VALUE (h, i), |
927 |
|
quark_name, quark_class); |
928 |
if (!NILP (value)) |
if (!NILP (value)) |
929 |
return value; |
return value; |
930 |
else |
else |
931 |
return xrm_q_get_resource (database, |
return xrm_q_get_resource_1 (database, node_id, |
932 |
XCDR (quark_name), XCDR (quark_class)); |
XCDR (quark_name), XCDR (quark_class)); |
933 |
} |
} |
934 |
else |
else |
935 |
return Qnil; |
return Qnil; |
936 |
} |
} |
937 |
|
|
938 |
|
static Lisp_Object |
939 |
|
xrm_q_get_resource (database, quark_name, quark_class) |
940 |
|
XrmDatabase database; |
941 |
|
Lisp_Object quark_name, quark_class; |
942 |
|
{ |
943 |
|
return xrm_q_get_resource_1 (database, make_number (0), |
944 |
|
quark_name, quark_class); |
945 |
|
} |
946 |
|
|
947 |
/* Retrieve a resource value for the specified NAME and CLASS from the |
/* Retrieve a resource value for the specified NAME and CLASS from the |
948 |
resource database DATABASE. It corresponds to XrmGetResource. */ |
resource database DATABASE. It corresponds to XrmGetResource. */ |
949 |
|
|
998 |
return result; |
return result; |
999 |
} |
} |
1000 |
else if (type_id == CFBooleanGetTypeID ()) |
else if (type_id == CFBooleanGetTypeID ()) |
1001 |
{ |
return build_string (CFBooleanGetValue (plist) ? "true" : "false"); |
|
static value_true = NULL, value_false = NULL; |
|
|
|
|
|
if (value_true == NULL) |
|
|
{ |
|
|
value_true = build_string ("true"); |
|
|
value_false = build_string ("false"); |
|
|
} |
|
|
return CFBooleanGetValue (plist) ? value_true : value_false; |
|
|
} |
|
1002 |
else if (type_id == CFDataGetTypeID ()) |
else if (type_id == CFDataGetTypeID ()) |
1003 |
return cfdata_to_lisp (plist); |
return cfdata_to_lisp (plist); |
1004 |
else |
else |