comparison src/specifier.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents 3742ea8250b5 11357f7846bf
children d1247f3cc363
comparison
equal deleted inserted replaced
5117:3742ea8250b5 5118:e0db3c197671
45 Lisp_Object Qremove_locale, Qremove_locale_type; 45 Lisp_Object Qremove_locale, Qremove_locale_type;
46 46
47 Lisp_Object Qconsole_type, Qdevice_class; 47 Lisp_Object Qconsole_type, Qdevice_class;
48 48
49 static Lisp_Object Vuser_defined_tags; 49 static Lisp_Object Vuser_defined_tags;
50 static Lisp_Object Vcharset_tag_lists;
50 51
51 typedef struct specifier_type_entry specifier_type_entry; 52 typedef struct specifier_type_entry specifier_type_entry;
52 struct specifier_type_entry 53 struct specifier_type_entry
53 { 54 {
54 Lisp_Object symbol; 55 Lisp_Object symbol;
244 { 245 {
245 if (! marked_p (rest)) 246 if (! marked_p (rest))
246 { 247 {
247 Lisp_Specifier* sp = XSPECIFIER (rest); 248 Lisp_Specifier* sp = XSPECIFIER (rest);
248 /* A bit of assertion that we're removing both parts of the 249 /* A bit of assertion that we're removing both parts of the
249 magic one altogether */ 250 magic one altogether */
250 assert (!MAGIC_SPECIFIER_P(sp) 251 assert (!MAGIC_SPECIFIER_P(sp)
251 || (BODILY_SPECIFIER_P(sp) && marked_p (sp->fallback)) 252 || (BODILY_SPECIFIER_P(sp) && marked_p (sp->fallback))
252 || (GHOST_SPECIFIER_P(sp) && marked_p (sp->magic_parent))); 253 || (GHOST_SPECIFIER_P(sp) && marked_p (sp->magic_parent)));
253 /* This specifier is garbage. Remove it from the list. */ 254 /* This specifier is garbage. Remove it from the list. */
254 if (NILP (prev)) 255 if (NILP (prev))
293 } 294 }
294 unbind_to (count); 295 unbind_to (count);
295 write_fmt_string (printcharfun, " 0x%x>", sp->header.uid); 296 write_fmt_string (printcharfun, " 0x%x>", sp->header.uid);
296 } 297 }
297 298
299 #ifndef NEW_GC
298 static void 300 static void
299 finalize_specifier (void *header, int for_disksave) 301 finalize_specifier (void *header, int for_disksave)
300 { 302 {
301 Lisp_Specifier *sp = (Lisp_Specifier *) header; 303 Lisp_Specifier *sp = (Lisp_Specifier *) header;
302 /* don't be snafued by the disksave finalization. */ 304 /* don't be snafued by the disksave finalization. */
304 { 306 {
305 xfree (sp->caching, struct specifier_caching *); 307 xfree (sp->caching, struct specifier_caching *);
306 sp->caching = 0; 308 sp->caching = 0;
307 } 309 }
308 } 310 }
311 #endif /* not NEW_GC */
309 312
310 static int 313 static int
311 specifier_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 314 specifier_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
312 { 315 {
313 Lisp_Specifier *s1 = XSPECIFIER (obj1); 316 Lisp_Specifier *s1 = XSPECIFIER (obj1);
380 383
381 static const struct memory_description specifier_caching_description_1[] = { 384 static const struct memory_description specifier_caching_description_1[] = {
382 { XD_END } 385 { XD_END }
383 }; 386 };
384 387
388 #ifdef NEW_GC
389 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("specifier-caching", specifier_caching,
390 0, specifier_caching_description_1,
391 struct specifier_caching);
392 #else /* not NEW_GC */
385 static const struct sized_memory_description specifier_caching_description = { 393 static const struct sized_memory_description specifier_caching_description = {
386 sizeof (struct specifier_caching), 394 sizeof (struct specifier_caching),
387 specifier_caching_description_1 395 specifier_caching_description_1
388 }; 396 };
397 #endif /* not NEW_GC */
389 398
390 static const struct sized_memory_description specifier_extra_description_map[] 399 static const struct sized_memory_description specifier_extra_description_map[]
391 = { 400 = {
392 { offsetof (Lisp_Specifier, methods) }, 401 { offsetof (Lisp_Specifier, methods) },
393 { offsetof (struct specifier_methods, extra_description) }, 402 { offsetof (struct specifier_methods, extra_description) },
401 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, global_specs) }, 410 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, global_specs) },
402 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, device_specs) }, 411 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, device_specs) },
403 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, frame_specs) }, 412 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, frame_specs) },
404 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, window_specs) }, 413 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, window_specs) },
405 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, buffer_specs) }, 414 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, buffer_specs) },
415 #ifdef NEW_GC
416 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, caching) },
417 #else /* not NEW_GC */
406 { XD_BLOCK_PTR, offsetof (Lisp_Specifier, caching), 1, 418 { XD_BLOCK_PTR, offsetof (Lisp_Specifier, caching), 1,
407 { &specifier_caching_description } }, 419 { &specifier_caching_description } },
420 #endif /* not NEW_GC */
408 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, magic_parent) }, 421 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, magic_parent) },
409 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, fallback) }, 422 { XD_LISP_OBJECT, offsetof (Lisp_Specifier, fallback) },
410 { XD_BLOCK_ARRAY, offsetof (Lisp_Specifier, data), 1, 423 { XD_BLOCK_ARRAY, offsetof (Lisp_Specifier, data), 1,
411 { specifier_extra_description_map } }, 424 { specifier_extra_description_map } },
412 { XD_END } 425 { XD_END }
413 }; 426 };
414 427
415 static const struct memory_description specifier_empty_extra_description_1[] = 428 static const struct memory_description specifier_empty_extra_description_1[] =
416 { 429 {
417 { XD_END } 430 { XD_END }
418 }; 431 };
419 432
420 const struct sized_memory_description specifier_empty_extra_description = { 433 const struct sized_memory_description specifier_empty_extra_description = {
421 0, specifier_empty_extra_description_1 434 0, specifier_empty_extra_description_1
422 }; 435 };
423 436
424 DEFINE_SIZABLE_LISP_OBJECT ("specifier", specifier, 437 #ifdef NEW_GC
425 mark_specifier, print_specifier, 438 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("specifier", specifier,
426 finalize_specifier, 439 mark_specifier, print_specifier,
427 specifier_equal, specifier_hash, 440 0, specifier_equal, specifier_hash,
428 specifier_description, 441 specifier_description,
429 sizeof_specifier, 442 sizeof_specifier,
430 Lisp_Specifier); 443 Lisp_Specifier);
444 #else /* not NEW_GC */
445 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("specifier", specifier,
446 mark_specifier, print_specifier,
447 finalize_specifier,
448 specifier_equal, specifier_hash,
449 specifier_description,
450 sizeof_specifier,
451 Lisp_Specifier);
452 #endif /* not NEW_GC */
431 453
432 /************************************************************************/ 454 /************************************************************************/
433 /* Creating specifiers */ 455 /* Creating specifiers */
434 /************************************************************************/ 456 /************************************************************************/
435 457
443 if (EQ (type, Dynarr_at (the_specifier_type_entry_dynarr, i).symbol)) 465 if (EQ (type, Dynarr_at (the_specifier_type_entry_dynarr, i).symbol))
444 return Dynarr_at (the_specifier_type_entry_dynarr, i).meths; 466 return Dynarr_at (the_specifier_type_entry_dynarr, i).meths;
445 } 467 }
446 468
447 maybe_invalid_argument ("Invalid specifier type", 469 maybe_invalid_argument ("Invalid specifier type",
448 type, Qspecifier, errb); 470 type, Qspecifier, errb);
449 471
450 return 0; 472 return 0;
451 } 473 }
452 474
453 static int 475 static int
653 value in that domain). Valid domains are image instances, windows, frames, 675 value in that domain). Valid domains are image instances, windows, frames,
654 and devices. \(nil is not valid.) image instances are pseudo-domains since 676 and devices. \(nil is not valid.) image instances are pseudo-domains since
655 instantiation will actually occur in the window the image instance itself is 677 instantiation will actually occur in the window the image instance itself is
656 instantiated in. 678 instantiated in.
657 */ 679 */
658 (domain)) 680 (domain))
659 { 681 {
660 /* This cannot GC. */ 682 /* This cannot GC. */
661 return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) || 683 return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) ||
662 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) || 684 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) ||
663 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))) || 685 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))) ||
664 /* #### get image instances out of domains! */ 686 /* #### get image instances out of domains! */
665 IMAGE_INSTANCEP (domain)) 687 IMAGE_INSTANCEP (domain))
666 ? Qt : Qnil; 688 ? Qt : Qnil;
667 } 689 }
668 690
669 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, 691 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1,
670 /* 692 1, 0, /*
671 Given a specifier LOCALE-TYPE, return non-nil if it is valid. 693 Given a specifier LOCALE-TYPE, return non-nil if it is valid.
672 Valid locale types are `global', `device', `frame', `window', and `buffer'. 694 Valid locale types are `global', `device', `frame', `window', and `buffer'.
673 \(Note, however, that in functions that accept either a locale or a locale 695 \(Note, however, that in functions that accept either a locale or a locale
674 type, `global' is considered an individual locale.) 696 type, `global' is considered an individual locale.)
675 */ 697 */
676 (locale_type)) 698 (locale_type))
677 { 699 {
678 /* This cannot GC. */ 700 /* This cannot GC. */
679 return (EQ (locale_type, Qglobal) || 701 return (EQ (locale_type, Qglobal) ||
680 EQ (locale_type, Qdevice) || 702 EQ (locale_type, Qdevice) ||
681 EQ (locale_type, Qframe) || 703 EQ (locale_type, Qframe) ||
701 (locale)) 723 (locale))
702 { 724 {
703 /* This cannot GC. */ 725 /* This cannot GC. */
704 if (NILP (Fvalid_specifier_locale_p (locale))) 726 if (NILP (Fvalid_specifier_locale_p (locale)))
705 invalid_argument ("Invalid specifier locale", 727 invalid_argument ("Invalid specifier locale",
706 locale); 728 locale);
707 if (DEVICEP (locale)) return Qdevice; 729 if (DEVICEP (locale)) return Qdevice;
708 if (FRAMEP (locale)) return Qframe; 730 if (FRAMEP (locale)) return Qframe;
709 if (WINDOWP (locale)) return Qwindow; 731 if (WINDOWP (locale)) return Qwindow;
710 if (BUFFERP (locale)) return Qbuffer; 732 if (BUFFERP (locale)) return Qbuffer;
711 assert (EQ (locale, Qglobal)); 733 assert (EQ (locale, Qglobal));
720 return Qglobal; 742 return Qglobal;
721 else if (!NILP (Fvalid_specifier_locale_p (locale))) 743 else if (!NILP (Fvalid_specifier_locale_p (locale)))
722 return locale; 744 return locale;
723 else 745 else
724 invalid_argument ("Invalid specifier locale", 746 invalid_argument ("Invalid specifier locale",
725 locale); 747 locale);
726 748
727 return Qnil; 749 return Qnil;
728 } 750 }
729 751
730 static enum spec_locale_type 752 static enum spec_locale_type
736 if (EQ (locale_type, Qframe)) return LOCALE_FRAME; 758 if (EQ (locale_type, Qframe)) return LOCALE_FRAME;
737 if (EQ (locale_type, Qwindow)) return LOCALE_WINDOW; 759 if (EQ (locale_type, Qwindow)) return LOCALE_WINDOW;
738 if (EQ (locale_type, Qbuffer)) return LOCALE_BUFFER; 760 if (EQ (locale_type, Qbuffer)) return LOCALE_BUFFER;
739 761
740 invalid_argument ("Invalid specifier locale type", 762 invalid_argument ("Invalid specifier locale type",
741 locale_type); 763 locale_type);
742 RETURN_NOT_REACHED (LOCALE_GLOBAL); 764 RETURN_NOT_REACHED (LOCALE_GLOBAL);
743 } 765 }
744 766
745 Lisp_Object 767 Lisp_Object
746 decode_locale_list (Lisp_Object locale) 768 decode_locale_list (Lisp_Object locale)
773 static void 795 static void
774 check_valid_domain (Lisp_Object domain) 796 check_valid_domain (Lisp_Object domain)
775 { 797 {
776 if (NILP (Fvalid_specifier_domain_p (domain))) 798 if (NILP (Fvalid_specifier_domain_p (domain)))
777 invalid_argument ("Invalid specifier domain", 799 invalid_argument ("Invalid specifier domain",
778 domain); 800 domain);
779 } 801 }
780 802
781 Lisp_Object 803 Lisp_Object
782 decode_domain (Lisp_Object domain) 804 decode_domain (Lisp_Object domain)
783 { 805 {
804 } 826 }
805 827
806 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /* 828 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /*
807 Return non-nil if TAG-SET is a valid specifier tag set. 829 Return non-nil if TAG-SET is a valid specifier tag set.
808 830
809 A specifier tag set is an entity that is attached to an instantiator 831 A specifier tag set is an entity that is attached to an instantiator and can
810 and can be used to restrict the scope of that instantiator to a 832 be used to restrict the scope of that instantiator to a particular device
811 particular device class or device type and/or to mark instantiators 833 class, device type, or charset. It can also be used to mark instantiators
812 added by a particular package so that they can be later removed. 834 added by a particular package so that they can be later removed as a group.
813 835
814 A specifier tag set consists of a list of zero of more specifier tags, 836 A specifier tag set consists of a list of zero of more specifier tags,
815 each of which is a symbol that is recognized by XEmacs as a tag. 837 each of which is a symbol that is recognized by XEmacs as a tag.
816 \(The valid device types and device classes are always tags, as are 838 \(The valid device types and device classes are always tags, as are
817 any tags defined by `define-specifier-tag'.) It is called a "tag set" 839 any tags defined by `define-specifier-tag'.) It is called a "tag set"
818 \(as opposed to a list) because the order of the tags or the number of 840 \(as opposed to a list) because the order of the tags or the number of
819 times a particular tag occurs does not matter. 841 times a particular tag occurs does not matter.
820 842
821 Each tag has a predicate associated with it, which specifies whether 843 Each tag has two predicates associated with it, which specify, respectively,
822 that tag applies to a particular device. The tags which are device types 844 whether that tag applies to a particular device and whether it applies to a
823 and classes match devices of that type or class. User-defined tags can 845 particular character set. The predefined tags which are device types and
824 have any predicate, or none (meaning that all devices match). When 846 classes match devices of that type or class. User-defined tags can have any
825 attempting to instantiate a specifier, a particular instantiator is only 847 device predicate, or none (meaning that all devices match). When attempting
826 considered if the device of the domain being instantiated over matches 848 to instantiate a specifier, a particular instantiator is only considered if
827 all tags in the tag set attached to that instantiator. 849 the device of the domain being instantiated over matches all tags in the tag
850 set attached to that instantiator.
851
852 If a charset is to be considered--which is only the case for face
853 instantiators--this consideration may be done twice. The first iteration
854 pays attention to the character set predicates; if no instantiator can be
855 found in that case, the search is repeated ignoring the character set
856 predicates.
828 857
829 Most of the time, a tag set is not specified, and the instantiator 858 Most of the time, a tag set is not specified, and the instantiator
830 gets a null tag set, which matches all devices. 859 gets a null tag set, which matches all devices.
831 */ 860 */
832 (tag_set)) 861 (tag_set))
833 { 862 {
834 Lisp_Object rest; 863 Lisp_Object rest;
835 864
836 for (rest = tag_set; !NILP (rest); rest = XCDR (rest)) 865 for (rest = tag_set; !NILP (rest); rest = XCDR (rest))
837 { 866 {
850 /* The return value of this function must be GCPRO'd. */ 879 /* The return value of this function must be GCPRO'd. */
851 if (!NILP (Fvalid_specifier_tag_p (tag_set))) 880 if (!NILP (Fvalid_specifier_tag_p (tag_set)))
852 return list1 (tag_set); 881 return list1 (tag_set);
853 if (NILP (Fvalid_specifier_tag_set_p (tag_set))) 882 if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
854 invalid_argument ("Invalid specifier tag-set", 883 invalid_argument ("Invalid specifier tag-set",
855 tag_set); 884 tag_set);
856 return tag_set; 885 return tag_set;
857 } 886 }
858 887
859 static Lisp_Object 888 static Lisp_Object
860 canonicalize_tag_set (Lisp_Object tag_set) 889 canonicalize_tag_set (Lisp_Object tag_set)
943 } 972 }
944 973
945 return 1; 974 return 1;
946 } 975 }
947 976
977 static int
978 charset_matches_specifier_tag_set_p (Lisp_Object charset,
979 Lisp_Object tag_set,
980 enum font_specifier_matchspec_stages
981 stage)
982 {
983 Lisp_Object rest;
984 int res = 0;
985
986 assert(stage != impossible);
987
988 LIST_LOOP (rest, tag_set)
989 {
990 Lisp_Object tag = XCAR (rest);
991 Lisp_Object assoc;
992
993 /* In the event that, during the creation of a charset, no specifier
994 tags exist for which CHARSET-PREDICATE has been specified, then
995 that charset's entry in Vcharset_tag_lists will be nil, and this
996 charset shouldn't match. */
997
998 if (NILP (XVECTOR_DATA(Vcharset_tag_lists)[XCHARSET_LEADING_BYTE(charset)
999 - MIN_LEADING_BYTE]))
1000 {
1001 return 0;
1002 }
1003
1004 /* Now, find out what the pre-calculated value is. */
1005 assoc = assq_no_quit(tag,
1006 XVECTOR_DATA(Vcharset_tag_lists)
1007 [XCHARSET_LEADING_BYTE(charset)
1008 - MIN_LEADING_BYTE]);
1009
1010 if (!(NILP(assoc)) && !(NILP(XCDR(assoc))))
1011 {
1012 assert(VECTORP(XCDR(assoc)));
1013
1014 /* In the event that a tag specifies a charset, then the specifier
1015 must match for (this stage and this charset) for all
1016 charset-specifying tags. */
1017 if (NILP(XVECTOR_DATA(XCDR(assoc))[stage]))
1018 {
1019 /* It doesn't match for this tag, even though the tag
1020 specifies a charset. Return 0. */
1021 return 0;
1022 }
1023
1024 /* This tag specifies charset limitations, and this charset and
1025 stage match those charset limitations.
1026
1027 In the event that a later tag specifies charset limitations
1028 that don't match, the return 0 above prevents us giving a
1029 positive match. */
1030 res = 1;
1031 }
1032 }
1033
1034 return res;
1035 }
1036
1037
948 DEFUN ("device-matches-specifier-tag-set-p", 1038 DEFUN ("device-matches-specifier-tag-set-p",
949 Fdevice_matches_specifier_tag_set_p, 2, 2, 0, /* 1039 Fdevice_matches_specifier_tag_set_p, 2, 2, 0, /*
950 Return non-nil if DEVICE matches specifier tag set TAG-SET. 1040 Return non-nil if DEVICE matches specifier tag set TAG-SET.
951 This means that DEVICE matches each tag in the tag set. (Every 1041 This means that DEVICE matches each tag in the tag set. (Every
952 tag recognized by XEmacs has a predicate associated with it that 1042 tag recognized by XEmacs has a predicate associated with it that
960 invalid_argument ("Invalid tag set", tag_set); 1050 invalid_argument ("Invalid tag set", tag_set);
961 1051
962 return device_matches_specifier_tag_set_p (device, tag_set) ? Qt : Qnil; 1052 return device_matches_specifier_tag_set_p (device, tag_set) ? Qt : Qnil;
963 } 1053 }
964 1054
965 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /* 1055 Lisp_Object
1056 define_specifier_tag(Lisp_Object tag, Lisp_Object device_predicate,
1057 Lisp_Object charset_predicate)
1058 {
1059 Lisp_Object assoc = assq_no_quit (tag, Vuser_defined_tags),
1060 concons, devcons, charpres = Qnil;
1061 int recompute_devices = 0, recompute_charsets = 0, i, max_args = -1;
1062
1063 if (NILP (assoc))
1064 {
1065 recompute_devices = recompute_charsets = 1;
1066 Vuser_defined_tags = Fcons (list3 (tag, device_predicate,
1067 charset_predicate),
1068 Vuser_defined_tags);
1069 DEVICE_LOOP_NO_BREAK (devcons, concons)
1070 {
1071 struct device *d = XDEVICE (XCAR (devcons));
1072 /* Initially set the value to t in case of error
1073 in device_predicate */
1074 DEVICE_USER_DEFINED_TAGS (d) =
1075 Fcons (Fcons (tag, Qt), DEVICE_USER_DEFINED_TAGS (d));
1076 }
1077
1078 if (!NILP (charset_predicate))
1079 {
1080 max_args = XINT(Ffunction_max_args(charset_predicate));
1081 if (max_args < 1)
1082 {
1083 invalid_argument
1084 ("Charset predicate must be able to take an argument", tag);
1085 }
1086 }
1087 }
1088 else if (!NILP (device_predicate) && !NILP (XCADR (assoc)))
1089 {
1090 recompute_devices = 1;
1091 XCDR (assoc) = list2(device_predicate, charset_predicate);
1092 }
1093 else if (!NILP (charset_predicate) || !NILP(XCADDR (assoc)))
1094 {
1095 max_args = XINT(Ffunction_max_args(charset_predicate));
1096 if (max_args < 1)
1097 {
1098 invalid_argument
1099 ("Charset predicate must be able to take an argument", tag);
1100 }
1101
1102 /* If there exists a charset_predicate for the tag currently (even if
1103 the new charset_predicate is nil), or if we're adding one, we need
1104 to recompute. This contrasts with the device predicates, where we
1105 don't need to recompute if the old and new device predicates are
1106 both nil. */
1107
1108 recompute_charsets = 1;
1109 XCDR (assoc) = list2(device_predicate, charset_predicate);
1110 }
1111
1112 /* Recompute the tag values for all devices and charsets, if necessary. In
1113 the special case where both the old and new device_predicates are nil,
1114 we know that we don't have to do it for the device. (It's probably
1115 common for people to call (define-specifier-tag) more than once on the
1116 same tag, and the most common case is where DEVICE_PREDICATE is not
1117 specified.) */
1118
1119 if (recompute_devices)
1120 {
1121 DEVICE_LOOP_NO_BREAK (devcons, concons)
1122 {
1123 Lisp_Object device = XCAR (devcons);
1124 assoc = assq_no_quit (tag,
1125 DEVICE_USER_DEFINED_TAGS (XDEVICE (device)));
1126 assert (CONSP (assoc));
1127 if (NILP (device_predicate))
1128 XCDR (assoc) = Qt;
1129 else
1130 XCDR (assoc) = !NILP (call1 (device_predicate, device)) ? Qt
1131 : Qnil;
1132 }
1133 }
1134
1135 if (recompute_charsets)
1136 {
1137 if (NILP(charset_predicate))
1138 {
1139 charpres = Qnil;
1140 }
1141
1142 for (i = 0; i < NUM_LEADING_BYTES; ++i)
1143 {
1144 if (NILP(charset_by_leading_byte(MIN_LEADING_BYTE + i)))
1145 {
1146 continue;
1147 }
1148
1149 assoc = assq_no_quit (tag,
1150 XVECTOR_DATA(Vcharset_tag_lists)[i]);
1151
1152 if (!NILP(charset_predicate))
1153 {
1154 struct gcpro gcpro1;
1155 charpres = make_vector(impossible, Qnil);
1156 GCPRO1 (charpres);
1157
1158 /* If you want to extend the number of stages available, here
1159 in setup_charset_initial_specifier_tags, and in specifier.h
1160 is where you want to go. */
1161
1162 #define DEFINE_SPECIFIER_TAG_FROB(stage) do { \
1163 if (max_args > 1) \
1164 { \
1165 XVECTOR_DATA(charpres)[stage] = \
1166 call2_trapping_problems \
1167 ("Error during specifier tag charset predicate," \
1168 " stage " #stage, charset_predicate, \
1169 charset_by_leading_byte(MIN_LEADING_BYTE + i), \
1170 Q##stage, 0); \
1171 } \
1172 else \
1173 { \
1174 XVECTOR_DATA(charpres)[stage] = \
1175 call1_trapping_problems \
1176 ("Error during specifier tag charset predicate," \
1177 " stage " #stage, charset_predicate, \
1178 charset_by_leading_byte(MIN_LEADING_BYTE + i), \
1179 0); \
1180 } \
1181 \
1182 if (UNBOUNDP(XVECTOR_DATA(charpres)[stage])) \
1183 { \
1184 XVECTOR_DATA(charpres)[stage] = Qnil; \
1185 } \
1186 else if (!NILP(XVECTOR_DATA(charpres)[stage])) \
1187 { \
1188 /* Don't want refs to random other objects. */ \
1189 XVECTOR_DATA(charpres)[stage] = Qt; \
1190 } \
1191 } while (0)
1192
1193 DEFINE_SPECIFIER_TAG_FROB (initial);
1194 DEFINE_SPECIFIER_TAG_FROB (final);
1195
1196 #undef DEFINE_SPECIFIER_TAG_FROB
1197
1198 UNGCPRO;
1199 }
1200
1201 if (!NILP(assoc))
1202 {
1203 assert(CONSP(assoc));
1204 XCDR (assoc) = charpres;
1205 }
1206 else
1207 {
1208 XVECTOR_DATA(Vcharset_tag_lists)[i]
1209 = Fcons(Fcons(tag, charpres),
1210 XVECTOR_DATA (Vcharset_tag_lists)[i]);
1211 }
1212 }
1213 }
1214 return Qt;
1215 }
1216
1217 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 3, 0, /*
966 Define a new specifier tag. 1218 Define a new specifier tag.
967 If PREDICATE is specified, it should be a function of one argument 1219
968 \(a device) that specifies whether the tag matches that particular 1220 If DEVICE-PREDICATE is specified, it should be a function of one argument
969 device. If PREDICATE is omitted, the tag matches all devices. 1221 \(a device) that specifies whether the tag matches that particular device.
970 1222 If DEVICE-PREDICATE is omitted, the tag matches all devices.
971 You can redefine an existing user-defined specifier tag. However, 1223
972 you cannot redefine the built-in specifier tags (the device types 1224 If CHARSET-PREDICATE is supplied, it should be a function taking a single
973 and classes) or the symbols nil, t, `all', or `global'. 1225 Lisp character set argument. A tag's charset predicate is primarily used to
974 */ 1226 determine what font to use for a given \(set of) charset\(s) when that tag
975 (tag, predicate)) 1227 is used in a set-face-font call; a non-nil return value indicates that the
976 { 1228 tag matches the charset.
977 Lisp_Object assoc, devcons, concons; 1229
978 int recompute = 0; 1230 The font matching process also has a concept of stages; the defined stages
1231 are currently `initial' and `final', and there exist specifier tags with
1232 those names that correspond to those stages. On X11, 'initial is used when
1233 the font matching process is looking for fonts that match the desired
1234 registries of the charset--see the `charset-registries' function. If that
1235 match process fails, then the 'final tag becomes relevant; this means that a
1236 more general lookup is desired, and that a font doesn't necessarily have to
1237 match the desired XLFD for the face, just the charset repertoire for this
1238 charset. It also means that the charset registry and encoding used will be
1239 `iso10646-1', and the characters will be converted to display using that
1240 registry.
1241
1242 If a tag set matches no character set; the two-stage match process will
1243 ignore the tag on its first pass, but if no match is found, it will respect
1244 it on the second pass, where character set information is ignored.
1245
1246 You can redefine an existing user-defined specifier tag. However, you
1247 cannot redefine most of the built-in specifier tags \(the device types and
1248 classes, `initial', and `final') or the symbols nil, t, `all', or `global'.
1249 Note that if a device type is not supported in this XEmacs, it will not be
1250 available as a built-in specifier tag; this is probably something we should
1251 change.
1252 */
1253 (tag, device_predicate, charset_predicate))
1254 {
1255 int max_args;
979 1256
980 CHECK_SYMBOL (tag); 1257 CHECK_SYMBOL (tag);
981 if (valid_device_class_p (tag) || 1258 if (valid_device_class_p (tag) ||
982 valid_console_type_p (tag)) 1259 valid_console_type_p (tag) ||
1260 EQ (tag, Qinitial) || EQ (tag, Qfinal))
983 invalid_change ("Cannot redefine built-in specifier tags", tag); 1261 invalid_change ("Cannot redefine built-in specifier tags", tag);
984 /* Try to prevent common instantiators and locales from being 1262 /* Try to prevent common instantiators and locales from being
985 redefined, to reduce ambiguity */ 1263 redefined, to reduce ambiguity */
986 if (NILP (tag) || EQ (tag, Qt) || EQ (tag, Qall) || EQ (tag, Qglobal)) 1264 if (NILP (tag) || EQ (tag, Qt) || EQ (tag, Qall) || EQ (tag, Qglobal))
987 invalid_change ("Cannot define nil, t, `all', or `global'", tag); 1265 invalid_change ("Cannot define nil, t, `all', or `global'", tag);
988 assoc = assq_no_quit (tag, Vuser_defined_tags); 1266
989 if (NILP (assoc)) 1267 if (!NILP (charset_predicate))
990 { 1268 {
991 recompute = 1; 1269 max_args = XINT(Ffunction_max_args(charset_predicate));
992 Vuser_defined_tags = Fcons (Fcons (tag, predicate), Vuser_defined_tags); 1270 if (max_args != 1)
993 DEVICE_LOOP_NO_BREAK (devcons, concons) 1271 {
994 { 1272 /* We only allow the stage argument to be specifed from C. */
995 struct device *d = XDEVICE (XCAR (devcons)); 1273 invalid_change ("Charset predicate must take one argument",
996 /* Initially set the value to t in case of error 1274 tag);
997 in predicate */ 1275 }
998 DEVICE_USER_DEFINED_TAGS (d) = 1276 }
999 Fcons (Fcons (tag, Qt), DEVICE_USER_DEFINED_TAGS (d)); 1277
1000 } 1278 return define_specifier_tag(tag, device_predicate, charset_predicate);
1001 }
1002 else if (!NILP (predicate) && !NILP (XCDR (assoc)))
1003 {
1004 recompute = 1;
1005 XCDR (assoc) = predicate;
1006 }
1007
1008 /* recompute the tag values for all devices. However, in the special
1009 case where both the old and new predicates are nil, we know that
1010 we don't have to do this. (It's probably common for people to
1011 call (define-specifier-tag) more than once on the same tag,
1012 and the most common case is where PREDICATE is not specified.) */
1013
1014 if (recompute)
1015 {
1016 DEVICE_LOOP_NO_BREAK (devcons, concons)
1017 {
1018 Lisp_Object device = XCAR (devcons);
1019 assoc = assq_no_quit (tag,
1020 DEVICE_USER_DEFINED_TAGS (XDEVICE (device)));
1021 assert (CONSP (assoc));
1022 if (NILP (predicate))
1023 XCDR (assoc) = Qt;
1024 else
1025 XCDR (assoc) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
1026 }
1027 }
1028
1029 return Qnil;
1030 } 1279 }
1031 1280
1032 /* Called at device-creation time to initialize the user-defined 1281 /* Called at device-creation time to initialize the user-defined
1033 tag values for the newly-created device. */ 1282 tag values for the newly-created device. */
1034 1283
1035 void 1284 void
1036 setup_device_initial_specifier_tags (struct device *d) 1285 setup_device_initial_specifier_tags (struct device *d)
1037 { 1286 {
1038 Lisp_Object rest, rest2; 1287 Lisp_Object rest, rest2;
1039 Lisp_Object device = wrap_device (d); 1288 Lisp_Object device = wrap_device (d);
1289 Lisp_Object device_predicate;
1290 int list_len;
1040 1291
1041 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags); 1292 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags);
1042 1293
1043 /* Now set up the initial values */ 1294 /* Now set up the initial values */
1044 LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d)) 1295 LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d))
1045 XCDR (XCAR (rest)) = Qt; 1296 XCDR (XCAR (rest)) = Qt;
1046 1297
1047 for (rest = Vuser_defined_tags, rest2 = DEVICE_USER_DEFINED_TAGS (d); 1298 for (rest = Vuser_defined_tags, rest2 = DEVICE_USER_DEFINED_TAGS (d);
1048 !NILP (rest); rest = XCDR (rest), rest2 = XCDR (rest2)) 1299 !NILP (rest); rest = XCDR (rest), rest2 = XCDR (rest2))
1049 { 1300 {
1050 Lisp_Object predicate = XCDR (XCAR (rest)); 1301 GET_LIST_LENGTH(XCAR(rest), list_len);
1051 if (NILP (predicate)) 1302
1052 XCDR (XCAR (rest2)) = Qt; 1303 assert(3 == list_len);
1304
1305 device_predicate = XCADR(XCAR (rest));
1306
1307 if (NILP (device_predicate))
1308 {
1309 XCDR (XCAR (rest2)) = Qt;
1310 }
1053 else 1311 else
1054 XCDR (XCAR (rest2)) = 1312 {
1055 !NILP (call_critical_lisp_code (d, predicate, device)) ? Qt : Qnil; 1313 device_predicate = !NILP (call_critical_lisp_code
1056 } 1314 (d, device_predicate, device))
1057 } 1315 ? Qt : Qnil;
1316 XCDR (XCAR (rest2)) = device_predicate;
1317 }
1318 }
1319 }
1320
1321 void
1322 setup_charset_initial_specifier_tags (Lisp_Object charset)
1323 {
1324 Lisp_Object rest, charset_predicate, tag, new_value;
1325 Lisp_Object charset_tag_list = Qnil;
1326
1327 LIST_LOOP (rest, Vuser_defined_tags)
1328 {
1329 tag = XCAR(XCAR(rest));
1330 charset_predicate = XCADDR(XCAR (rest));
1331
1332 if (NILP(charset_predicate))
1333 {
1334 continue;
1335 }
1336
1337 new_value = make_vector(impossible, Qnil);
1338
1339 #define SETUP_CHARSET_TAGS_FROB(stage) do { \
1340 \
1341 XVECTOR_DATA(new_value)[stage] = call2_trapping_problems \
1342 ("Error during specifier tag charset predicate," \
1343 " stage " #stage, \
1344 charset_predicate, charset, Q##stage, 0); \
1345 \
1346 if (UNBOUNDP(XVECTOR_DATA(new_value)[stage])) \
1347 { \
1348 XVECTOR_DATA(new_value)[stage] = Qnil; \
1349 } \
1350 else if (!NILP(XVECTOR_DATA(new_value)[stage])) \
1351 { \
1352 /* Don't want random other objects hanging around. */ \
1353 XVECTOR_DATA(new_value)[stage] = Qt; \
1354 } \
1355 \
1356 } while (0)
1357
1358 SETUP_CHARSET_TAGS_FROB (initial);
1359 SETUP_CHARSET_TAGS_FROB (final);
1360 /* More later? */
1361
1362 #undef SETUP_CHARSET_TAGS_FROB
1363
1364 charset_tag_list = Fcons(Fcons(tag, new_value), charset_tag_list);
1365 }
1366
1367 XVECTOR_DATA
1368 (Vcharset_tag_lists)[XCHARSET_LEADING_BYTE(charset) - MIN_LEADING_BYTE]
1369 = charset_tag_list;
1370 }
1371
1372 /* VM calls this, in vm-multiple-frames-possible-p, in the event that you're
1373 considering taking it out. */
1058 1374
1059 DEFUN ("device-matching-specifier-tag-list", 1375 DEFUN ("device-matching-specifier-tag-list",
1060 Fdevice_matching_specifier_tag_list, 1376 Fdevice_matching_specifier_tag_list,
1061 0, 1, 0, /* 1377 0, 1, 0, /*
1062 Return a list of all specifier tags matching DEVICE. 1378 Return a list of all specifier tags matching DEVICE.
1102 list = nconc2 (Fcopy_sequence (Vconsole_type_list), list); 1418 list = nconc2 (Fcopy_sequence (Vconsole_type_list), list);
1103 1419
1104 RETURN_UNGCPRO (list); 1420 RETURN_UNGCPRO (list);
1105 } 1421 }
1106 1422
1107 DEFUN ("specifier-tag-predicate", Fspecifier_tag_predicate, 1, 1, 0, /* 1423 DEFUN ("specifier-tag-device-predicate", Fspecifier_tag_device_predicate,
1108 Return the predicate for the given specifier tag. 1424 1, 1, 0, /*
1425 Return the device predicate for the given specifier tag.
1109 */ 1426 */
1110 (tag)) 1427 (tag))
1111 { 1428 {
1112 /* The return value of this function must be GCPRO'd. */ 1429 /* The return value of this function must be GCPRO'd. */
1113 CHECK_SYMBOL (tag); 1430 CHECK_SYMBOL (tag);
1114 1431
1115 if (NILP (Fvalid_specifier_tag_p (tag))) 1432 if (NILP (Fvalid_specifier_tag_p (tag)))
1116 invalid_argument ("Invalid specifier tag", 1433 invalid_argument ("Invalid specifier tag",
1117 tag); 1434 tag);
1118 1435
1119 /* Make up some predicates for the built-in types */ 1436 /* Make up some predicates for the built-in types */
1120 1437
1121 if (valid_console_type_p (tag)) 1438 if (valid_console_type_p (tag))
1122 return list3 (Qlambda, list1 (Qdevice), 1439 return list3 (Qlambda, list1 (Qdevice),
1126 if (valid_device_class_p (tag)) 1443 if (valid_device_class_p (tag))
1127 return list3 (Qlambda, list1 (Qdevice), 1444 return list3 (Qlambda, list1 (Qdevice),
1128 list3 (Qeq, list2 (Qquote, tag), 1445 list3 (Qeq, list2 (Qquote, tag),
1129 list2 (Qdevice_class, Qdevice))); 1446 list2 (Qdevice_class, Qdevice)));
1130 1447
1131 return XCDR (assq_no_quit (tag, Vuser_defined_tags)); 1448 return XCADR (assq_no_quit (tag, Vuser_defined_tags));
1449 }
1450
1451 DEFUN ("specifier-tag-charset-predicate", Fspecifier_tag_charset_predicate,
1452 1, 1, 0, /*
1453 Return the charset predicate for the given specifier tag.
1454 */
1455 (tag))
1456 {
1457 /* The return value of this function must be GCPRO'd. */
1458 CHECK_SYMBOL (tag);
1459
1460 if (NILP (Fvalid_specifier_tag_p (tag)))
1461 invalid_argument ("Invalid specifier tag",
1462 tag);
1463
1464 return XCADDR (assq_no_quit (tag, Vuser_defined_tags));
1132 } 1465 }
1133 1466
1134 /* Return true if A "matches" B. If EXACT_P is 0, A must be a subset of B. 1467 /* Return true if A "matches" B. If EXACT_P is 0, A must be a subset of B.
1135 Otherwise, A must be `equal' to B. The sets must be canonicalized. */ 1468 Otherwise, A must be `equal' to B. The sets must be canonicalized. */
1136 static int 1469 static int
1137 tag_sets_match_p (Lisp_Object a, Lisp_Object b, int exact_p) 1470 tag_sets_match_p (Lisp_Object a, Lisp_Object b, int exact_p)
1138 { 1471 {
1139 if (!exact_p) 1472 if (!exact_p)
1140 { 1473 {
1238 Lisp_Object tag_set; 1571 Lisp_Object tag_set;
1239 1572
1240 if (!CONSP (inst_pair)) 1573 if (!CONSP (inst_pair))
1241 { 1574 {
1242 maybe_sferror ( 1575 maybe_sferror (
1243 "Invalid instantiator pair", inst_pair, 1576 "Invalid instantiator pair", inst_pair,
1244 Qspecifier, errb); 1577 Qspecifier, errb);
1245 return Qnil; 1578 return Qnil;
1246 } 1579 }
1247 if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair)))) 1580 if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair))))
1248 { 1581 {
1249 maybe_invalid_argument ( 1582 maybe_invalid_argument (
1250 "Invalid specifier tag", tag_set, 1583 "Invalid specifier tag", tag_set,
1251 Qspecifier, errb); 1584 Qspecifier, errb);
1252 return Qnil; 1585 return Qnil;
1253 } 1586 }
1254 1587
1255 if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb))) 1588 if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb)))
1256 return Qnil; 1589 return Qnil;
1287 { 1620 {
1288 Lisp_Object locale; 1621 Lisp_Object locale;
1289 if (!CONSP (spec)) 1622 if (!CONSP (spec))
1290 { 1623 {
1291 maybe_sferror ( 1624 maybe_sferror (
1292 "Invalid specification list", spec_list, 1625 "Invalid specification list", spec_list,
1293 Qspecifier, errb); 1626 Qspecifier, errb);
1294 return Qnil; 1627 return Qnil;
1295 } 1628 }
1296 if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec)))) 1629 if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec))))
1297 { 1630 {
1298 maybe_invalid_argument ( 1631 maybe_invalid_argument (
1299 "Invalid specifier locale", locale, 1632 "Invalid specifier locale", locale,
1300 Qspecifier, errb); 1633 Qspecifier, errb);
1301 return Qnil; 1634 return Qnil;
1302 } 1635 }
1303 1636
1304 if (NILP (check_valid_inst_list (XCDR (spec), meths, errb))) 1637 if (NILP (check_valid_inst_list (XCDR (spec), meths, errb)))
1305 return Qnil; 1638 return Qnil;
1384 /* This gets hit so much that the function call overhead had a 1717 /* This gets hit so much that the function call overhead had a
1385 measurable impact (according to Quantify). #### We should figure 1718 measurable impact (according to Quantify). #### We should figure
1386 out the frequency with which this is called with the various types 1719 out the frequency with which this is called with the various types
1387 and reorder the check accordingly. */ 1720 and reorder the check accordingly. */
1388 #define SPECIFIER_GET_SPEC_LIST(specifier, type) \ 1721 #define SPECIFIER_GET_SPEC_LIST(specifier, type) \
1389 (type == LOCALE_GLOBAL ? &(XSPECIFIER (specifier)->global_specs) : \ 1722 (type == LOCALE_GLOBAL ? &(XSPECIFIER (specifier)->global_specs) : \
1390 type == LOCALE_DEVICE ? &(XSPECIFIER (specifier)->device_specs) : \ 1723 type == LOCALE_DEVICE ? &(XSPECIFIER (specifier)->device_specs) : \
1391 type == LOCALE_FRAME ? &(XSPECIFIER (specifier)->frame_specs) : \ 1724 type == LOCALE_FRAME ? &(XSPECIFIER (specifier)->frame_specs) : \
1392 type == LOCALE_WINDOW ? &(XWEAK_LIST_LIST \ 1725 type == LOCALE_WINDOW ? &(XWEAK_LIST_LIST \
1393 (XSPECIFIER (specifier)->window_specs)) : \ 1726 (XSPECIFIER (specifier)->window_specs)) : \
1394 type == LOCALE_BUFFER ? &(XSPECIFIER (specifier)->buffer_specs) : \ 1727 type == LOCALE_BUFFER ? &(XSPECIFIER (specifier)->buffer_specs) : \
1395 0) 1728 0)
1396 1729
1397 static Lisp_Object * 1730 static Lisp_Object *
1398 specifier_get_inst_list (Lisp_Object specifier, Lisp_Object locale, 1731 specifier_get_inst_list (Lisp_Object specifier, Lisp_Object locale,
1399 enum spec_locale_type type) 1732 enum spec_locale_type type)
1400 { 1733 {
1729 specifier, and is an enum that corresponds to the values in 2062 specifier, and is an enum that corresponds to the values in
1730 `add-spec-to-specifier'. The calling routine is responsible for 2063 `add-spec-to-specifier'. The calling routine is responsible for
1731 validating LOCALE and INST-LIST, but the tag-sets in INST-LIST 2064 validating LOCALE and INST-LIST, but the tag-sets in INST-LIST
1732 do not need to be canonicalized. */ 2065 do not need to be canonicalized. */
1733 2066
1734 /* #### I really need to rethink the after-change 2067 /* #### I really need to rethink the after-change
1735 functions to make them easier to use and more efficient. */ 2068 functions to make them easier to use and more efficient. */
1736 2069
1737 static void 2070 static void
1738 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale, 2071 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale,
1739 Lisp_Object inst_list, enum spec_add_meth add_meth) 2072 Lisp_Object inst_list, enum spec_add_meth add_meth)
1740 { 2073 {
1826 } 2159 }
1827 2160
1828 /* map MAPFUN over the locales in SPECIFIER that are given in LOCALE. 2161 /* map MAPFUN over the locales in SPECIFIER that are given in LOCALE.
1829 CLOSURE is passed unchanged to MAPFUN. LOCALE can be one of 2162 CLOSURE is passed unchanged to MAPFUN. LOCALE can be one of
1830 2163
1831 -- nil (same as `all') 2164 -- nil (same as `all')
1832 -- a single locale, locale type, or `all' 2165 -- a single locale, locale type, or `all'
1833 -- a list of locales, locale types, and/or `all' 2166 -- a list of locales, locale types, and/or `all'
1834 2167
1835 MAPFUN is called for each locale and locale type given; for `all', 2168 MAPFUN is called for each locale and locale type given; for `all',
1836 it is called for the locale `global' and for the four possible 2169 it is called for the locale `global' and for the four possible
1837 locale types. In each invocation, either LOCALE will be a locale 2170 locale types. In each invocation, either LOCALE will be a locale
1838 and LOCALE_TYPE will be the locale type of this locale, 2171 and LOCALE_TYPE will be the locale type of this locale,
1839 or LOCALE will be nil and LOCALE_TYPE will be a locale type. 2172 or LOCALE will be nil and LOCALE_TYPE will be a locale type.
1840 If MAPFUN ever returns non-zero, the mapping is halted and the 2173 If MAPFUN ever returns non-zero, the mapping is halted and the
1841 value returned is returned from map_specifier(). Otherwise, the 2174 value returned is returned from map_specifier(). Otherwise, the
1842 mapping proceeds to the end and map_specifier() returns 0. 2175 mapping proceeds to the end and map_specifier() returns 0.
1843 */ 2176 */
1844 2177
1845 static int 2178 static int
1846 map_specifier (Lisp_Object specifier, Lisp_Object locale, 2179 map_specifier (Lisp_Object specifier, Lisp_Object locale,
1847 int (*mapfun) (Lisp_Object specifier, 2180 int (*mapfun) (Lisp_Object specifier,
1848 Lisp_Object locale, 2181 Lisp_Object locale,
1983 ((LOCALE (TAG-SET . INSTANTIATOR) ...) ...) 2316 ((LOCALE (TAG-SET . INSTANTIATOR) ...) ...)
1984 2317
1985 where 2318 where
1986 LOCALE := a window, a buffer, a frame, a device, or `global' 2319 LOCALE := a window, a buffer, a frame, a device, or `global'
1987 TAG-SET := an unordered list of zero or more TAGS, each of which 2320 TAG-SET := an unordered list of zero or more TAGS, each of which
1988 is a symbol 2321 is a symbol
1989 TAG := a device class (see `valid-device-class-p'), a device type 2322 TAG := a device class (see `valid-device-class-p'), a device type
1990 (see `valid-console-type-p'), or a tag defined with 2323 (see `valid-console-type-p'), or a tag defined with
1991 `define-specifier-tag' 2324 `define-specifier-tag'
1992 INSTANTIATOR := format determined by the type of specifier 2325 INSTANTIATOR := format determined by the type of specifier
1993 2326
1994 The pair (TAG-SET . INSTANTIATOR) is called an `inst-pair'. 2327 The pair (TAG-SET . INSTANTIATOR) is called an `inst-pair'.
1995 A list of inst-pairs is called an `inst-list'. 2328 A list of inst-pairs is called an `inst-list'.
1996 The pair (LOCALE . INST-LIST) is called a `specification' or `spec'. 2329 The pair (LOCALE . INST-LIST) is called a `specification' or `spec'.
2118 \(The default value of nil is a subset of all tag sets, so in this case 2451 \(The default value of nil is a subset of all tag sets, so in this case
2119 no instantiators will be screened out.) If EXACT-P is non-nil, however, 2452 no instantiators will be screened out.) If EXACT-P is non-nil, however,
2120 TAG-SET must be equal to an instantiator's tag set for the instantiator 2453 TAG-SET must be equal to an instantiator's tag set for the instantiator
2121 to be returned. 2454 to be returned.
2122 */ 2455 */
2123 (specifier, locale, tag_set, exact_p)) 2456 (specifier, locale, tag_set, exact_p))
2124 { 2457 {
2125 struct specifier_spec_list_closure cl; 2458 struct specifier_spec_list_closure cl;
2126 struct gcpro gcpro1, gcpro2; 2459 struct gcpro gcpro1, gcpro2;
2127 2460
2128 CHECK_SPECIFIER (specifier); 2461 CHECK_SPECIFIER (specifier);
2317 else 2650 else
2318 { 2651 {
2319 CHECK_SPECIFIER (dest); 2652 CHECK_SPECIFIER (dest);
2320 check_modifiable_specifier (dest); 2653 check_modifiable_specifier (dest);
2321 if (XSPECIFIER (dest)->methods != XSPECIFIER (specifier)->methods) 2654 if (XSPECIFIER (dest)->methods != XSPECIFIER (specifier)->methods)
2322 invalid_argument ("Specifiers not of same type", Qunbound); 2655 invalid_argument ("Specifiers not of same type", Qunbound);
2323 } 2656 }
2324 2657
2325 cl.dest = dest; 2658 cl.dest = dest;
2326 GCPRO1 (dest); 2659 GCPRO1 (dest);
2327 map_specifier (specifier, locale, copy_specifier_mapfun, 2660 map_specifier (specifier, locale, copy_specifier_mapfun,
2462 Lisp_Object matchspec, 2795 Lisp_Object matchspec,
2463 Lisp_Object domain, 2796 Lisp_Object domain,
2464 Lisp_Object inst_list, 2797 Lisp_Object inst_list,
2465 Error_Behavior errb, int no_quit, 2798 Error_Behavior errb, int no_quit,
2466 Lisp_Object depth, 2799 Lisp_Object depth,
2467 Lisp_Object *instantiator) 2800 Lisp_Object *instantiator,
2801 int no_fallback)
2468 { 2802 {
2469 /* This function can GC */ 2803 /* This function can GC */
2470 Lisp_Specifier *sp; 2804 Lisp_Specifier *sp;
2471 Lisp_Object device; 2805 Lisp_Object device, charset = Qnil, rest;
2472 Lisp_Object rest; 2806 int count = specpdl_depth (), respected_charsets = 0;
2473 int count = specpdl_depth ();
2474 struct gcpro gcpro1, gcpro2; 2807 struct gcpro gcpro1, gcpro2;
2808 enum font_specifier_matchspec_stages stage = initial;
2809 #ifdef DEBUG_XEMACS
2810 int non_ascii;
2811 #endif
2475 2812
2476 GCPRO2 (specifier, inst_list); 2813 GCPRO2 (specifier, inst_list);
2477 2814
2478 sp = XSPECIFIER (specifier); 2815 sp = XSPECIFIER (specifier);
2479 device = DOMAIN_DEVICE (domain); 2816 device = DOMAIN_DEVICE (domain);
2480 2817
2481 if (no_quit) 2818 if (no_quit)
2482 /* The instantiate method is allowed to call eval. Since it 2819 /* The instantiate method is allowed to call eval. Since it
2483 is quite common for this function to get called from somewhere in 2820 is quite common for this function to get called from somewhere in
2484 redisplay we need to make sure that quits are ignored. Otherwise 2821 redisplay we need to make sure that quits are ignored. Otherwise
2485 Fsignal will abort. */ 2822 Fsignal will abort. */
2486 specbind (Qinhibit_quit, Qt); 2823 specbind (Qinhibit_quit, Qt);
2487 2824
2488 LIST_LOOP (rest, inst_list) 2825 #ifdef MULE
2826 if (CONSP(matchspec) && (CHARSETP(Ffind_charset(XCAR(matchspec)))))
2827 {
2828 charset = Ffind_charset(XCAR(matchspec));
2829
2830 #ifdef DEBUG_XEMACS
2831 /* This is mostly to have somewhere to set debug breakpoints. */
2832 if (!EQ(charset, Vcharset_ascii))
2833 {
2834 non_ascii = 1;
2835 }
2836 #endif /* DEBUG_XEMACS */
2837
2838 if (!NILP(XCDR(matchspec)))
2839 {
2840
2841 #define FROB(new_stage) if (EQ(Q##new_stage, XCDR(matchspec))) \
2842 { \
2843 stage = new_stage; \
2844 }
2845
2846 FROB(initial)
2847 else FROB(final)
2848 else assert(0);
2849 #undef FROB
2850
2851 }
2852 }
2853 #endif /* MULE */
2854
2855 LIST_LOOP(rest, inst_list)
2489 { 2856 {
2490 Lisp_Object tagged_inst = XCAR (rest); 2857 Lisp_Object tagged_inst = XCAR (rest);
2491 Lisp_Object tag_set = XCAR (tagged_inst); 2858 Lisp_Object tag_set = XCAR (tagged_inst);
2492 2859 Lisp_Object val, the_instantiator;
2493 if (device_matches_specifier_tag_set_p (device, tag_set)) 2860
2494 { 2861 if (!device_matches_specifier_tag_set_p (device, tag_set))
2495 Lisp_Object val = XCDR (tagged_inst); 2862 {
2496 Lisp_Object the_instantiator = val; 2863 continue;
2497 2864 }
2498 2865
2499 if (HAS_SPECMETH_P (sp, instantiate)) 2866 val = XCDR (tagged_inst);
2500 val = call_with_suspended_errors 2867 the_instantiator = val;
2501 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate), 2868
2502 Qunbound, Qspecifier, errb, 5, specifier, 2869 if (!NILP(charset) &&
2503 matchspec, domain, val, depth); 2870 !(charset_matches_specifier_tag_set_p (charset, tag_set, stage)))
2504 2871 {
2505 if (!UNBOUNDP (val)) 2872 ++respected_charsets;
2506 { 2873 continue;
2507 unbind_to (count); 2874 }
2508 UNGCPRO; 2875
2509 if (instantiator) 2876 if (HAS_SPECMETH_P (sp, instantiate))
2510 *instantiator = the_instantiator; 2877 val = call_with_suspended_errors
2511 return val; 2878 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate),
2512 } 2879 Qunbound, Qspecifier, errb, 5, specifier,
2880 matchspec, domain, val, depth, no_fallback);
2881
2882 if (!UNBOUNDP (val))
2883 {
2884 unbind_to (count);
2885 UNGCPRO;
2886 if (instantiator)
2887 *instantiator = the_instantiator;
2888 return val;
2889 }
2890 }
2891
2892 /* We've checked all the tag sets, and checking the charset part of the
2893 specifier never returned 0 (preventing the attempted instantiation), so
2894 there's no need to loop for the second time to avoid checking the
2895 charsets. */
2896 if (!respected_charsets)
2897 {
2898 unbind_to (count);
2899 UNGCPRO;
2900 return Qunbound;
2901 }
2902
2903 /* Right, didn't instantiate a specifier last time, perhaps because we
2904 paid attention to the charset-specific aspects of the specifier. Try
2905 again without checking the charset information.
2906
2907 We can't emulate the approach for devices, defaulting to matching all
2908 character sets for a given specifier, because $random font instantiator
2909 cannot usefully show all character sets, and indeed having it try is a
2910 failure on our part. */
2911 LIST_LOOP (rest, inst_list)
2912 {
2913 Lisp_Object tagged_inst = XCAR (rest);
2914 Lisp_Object tag_set = XCAR (tagged_inst);
2915 Lisp_Object val, the_instantiator;
2916
2917 if (!device_matches_specifier_tag_set_p (device, tag_set))
2918 {
2919 continue;
2920 }
2921
2922 val = XCDR (tagged_inst);
2923 the_instantiator = val;
2924
2925 if (HAS_SPECMETH_P (sp, instantiate))
2926 val = call_with_suspended_errors
2927 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate),
2928 Qunbound, Qspecifier, errb, 5, specifier,
2929 matchspec, domain, val, depth, no_fallback);
2930
2931 if (!UNBOUNDP (val))
2932 {
2933 unbind_to (count);
2934 UNGCPRO;
2935 if (instantiator)
2936 *instantiator = the_instantiator;
2937 return val;
2513 } 2938 }
2514 } 2939 }
2515 2940
2516 unbind_to (count); 2941 unbind_to (count);
2517 UNGCPRO; 2942 UNGCPRO;
2518 return Qunbound; 2943 return Qunbound;
2519 } 2944 }
2520 2945
2521 /* Given a SPECIFIER and a DOMAIN, return a specific instance for that 2946 /* Given a SPECIFIER and a DOMAIN, return a specific instance for that
2522 specifier. Try to find one by checking the specifier types from most 2947 specifier. Try to find one by checking the specifier types from most
2523 specific (buffer) to most general (global). If we find an instance, 2948 specific (window) to most general (global). If we find an instance,
2524 return it. Otherwise return Qunbound. */ 2949 return it. Otherwise return Qunbound. */
2525 2950
2526 #define CHECK_INSTANCE_ENTRY(key, matchspec, type) do { \ 2951 #define CHECK_INSTANCE_ENTRY(key, matchspec, type) do { \
2527 Lisp_Object *CIE_inst_list = \ 2952 Lisp_Object *CIE_inst_list = \
2528 specifier_get_inst_list (specifier, key, type); \ 2953 specifier_get_inst_list (specifier, key, type); \
2529 if (CIE_inst_list) \ 2954 if (CIE_inst_list) \
2530 { \ 2955 { \
2531 Lisp_Object CIE_val = \ 2956 Lisp_Object CIE_val = \
2532 specifier_instance_from_inst_list (specifier, matchspec, \ 2957 specifier_instance_from_inst_list (specifier, matchspec, \
2533 domain, *CIE_inst_list, \ 2958 domain, *CIE_inst_list, \
2534 errb, no_quit, depth, \ 2959 errb, no_quit, depth, \
2535 instantiator); \ 2960 instantiator, no_fallback); \
2536 if (!UNBOUNDP (CIE_val)) \ 2961 if (!UNBOUNDP (CIE_val)) \
2537 return CIE_val; \ 2962 return CIE_val; \
2538 } \ 2963 } \
2539 } while (0) 2964 } while (0)
2540 2965
2541 /* We accept any window, frame or device domain and do our checking 2966 /* We accept any window, frame or device domain and do our checking
2542 starting from as specific a locale type as we can determine from the 2967 starting from as specific a locale type as we can determine from the
2543 domain we are passed and going on up through as many other locale types 2968 domain we are passed and going on up through as many other locale types
2544 as we can determine. In practice, when called from redisplay the 2969 as we can determine. In practice, when called from redisplay the
2642 } 3067 }
2643 3068
2644 assert (CONSP (sp->fallback)); 3069 assert (CONSP (sp->fallback));
2645 return specifier_instance_from_inst_list (specifier, matchspec, domain, 3070 return specifier_instance_from_inst_list (specifier, matchspec, domain,
2646 sp->fallback, errb, no_quit, 3071 sp->fallback, errb, no_quit,
2647 depth, instantiator); 3072 depth, instantiator,
3073 no_fallback);
2648 } 3074 }
2649 #undef CHECK_INSTANCE_ENTRY 3075 #undef CHECK_INSTANCE_ENTRY
2650 3076
2651 Lisp_Object 3077 Lisp_Object
2652 specifier_instance (Lisp_Object specifier, Lisp_Object matchspec, 3078 specifier_instance (Lisp_Object specifier, Lisp_Object matchspec,
2812 e.g., a buffer-local display table that only gives values for particular 3238 e.g., a buffer-local display table that only gives values for particular
2813 characters. All other characters are handled as if the buffer-local 3239 characters. All other characters are handled as if the buffer-local
2814 display table is not there. (Chartable specifiers are not yet 3240 display table is not there. (Chartable specifiers are not yet
2815 implemented.) 3241 implemented.)
2816 3242
2817 -- For font specifiers, MATCHSPEC should be a list (CHARSET . SECOND-STAGE-P), 3243 -- For font specifiers, MATCHSPEC should be a cons (CHARSET . STAGE).
2818 and the specification (a font string) must have a registry that matches 3244 The defined stages are currently `initial' and `final'. On X11, 'initial
2819 the charset's registry. (This only makes sense with Mule support.) This 3245 is used when the font matching process is looking for fonts that match
2820 makes it easy to choose a font that can display a particular 3246 the desired registries of the charset--see the `charset-registries'
2821 character. (This is what redisplay does, in fact.) SECOND-STAGE-P means 3247 function. If that match process fails, then the 'final stage comes into
2822 to ignore the font's registry and instead look at the characters in the 3248 play; this means that a more general lookup is desired, and that a font
2823 font to see if the font can support the charset. This currently only makes 3249 doesn't necessarily have to match the desired XLFD for the face, just the
2824 sense under MS Windows. 3250 charset repertoire for this charset. It also means that the charset
3251 registry and encoding used will be `iso10646-1', and the characters will
3252 be converted to display using that registry.
3253
3254 See `define-specifier-tag' for details on how to create a tag that
3255 specifies a given character set and stage combination. You can supply
3256 such a tag to `set-face-font' in order to set a face's font for that
3257 character set and stage combination.
2825 */ 3258 */
2826 (specifier, matchspec, domain, default_, no_fallback)) 3259 (specifier, matchspec, domain, default_, no_fallback))
2827 { 3260 {
2828 return specifier_matching_foo (specifier, matchspec, domain, default_, 3261 return specifier_matching_foo (specifier, matchspec, domain, default_,
2829 no_fallback, 0); 3262 no_fallback, 0);
2868 GCPRO1 (built_up_list); 3301 GCPRO1 (built_up_list);
2869 built_up_list = build_up_processed_list (specifier, domain, inst_list); 3302 built_up_list = build_up_processed_list (specifier, domain, inst_list);
2870 if (!NILP (built_up_list)) 3303 if (!NILP (built_up_list))
2871 val = specifier_instance_from_inst_list (specifier, matchspec, domain, 3304 val = specifier_instance_from_inst_list (specifier, matchspec, domain,
2872 built_up_list, ERROR_ME, 3305 built_up_list, ERROR_ME,
2873 0, Qzero, &instantiator); 3306 0, Qzero, &instantiator, 0);
2874 UNGCPRO; 3307 UNGCPRO;
2875 return UNBOUNDP (val) ? default_ : want_instantiator ? instantiator : val; 3308 return UNBOUNDP (val) ? default_ : want_instantiator ? instantiator : val;
2876 3309
2877 } 3310 }
2878 3311
2889 return specifier_matching_foo_from_inst_list (specifier, Qunbound, 3322 return specifier_matching_foo_from_inst_list (specifier, Qunbound,
2890 domain, inst_list, default_, 3323 domain, inst_list, default_,
2891 0); 3324 0);
2892 } 3325 }
2893 3326
2894 DEFUN ("specifier-instantiator-from-inst-list", Fspecifier_instantiator_from_inst_list, 3327 DEFUN ("specifier-instantiator-from-inst-list",
2895 3, 4, 0, /* 3328 Fspecifier_instantiator_from_inst_list, 3, 4, 0, /*
2896 Attempt to convert an inst-list into an instance; return instantiator. 3329 Attempt to convert an inst-list into an instance; return instantiator.
2897 This is identical to `specifier-instance-from-inst-list' but returns 3330 This is identical to `specifier-instance-from-inst-list' but returns
2898 the instantiator used to generate the instance, rather than the instance 3331 the instantiator used to generate the instance, rather than the instance
2899 itself. 3332 itself.
2900 */ 3333 */
2958 You nearly always need to do something, e.g. set a dirty flag.) 3391 You nearly always need to do something, e.g. set a dirty flag.)
2959 3392
2960 If you create a built-in specifier, you should do the following: 3393 If you create a built-in specifier, you should do the following:
2961 3394
2962 - Make sure the file you create the specifier in has a 3395 - Make sure the file you create the specifier in has a
2963 specifier_vars_of_foo() function. If not, create it, declare it in 3396 specifier_vars_of_foo() function. If not, create it, declare it in
2964 symsinit.h, and make sure it's called in the appropriate place in 3397 symsinit.h, and make sure it's called in the appropriate place in
2965 emacs.c. 3398 emacs.c.
2966 - In specifier_vars_of_foo(), do a DEFVAR_SPECIFIER(), followed by 3399 - In specifier_vars_of_foo(), do a DEFVAR_SPECIFIER(), followed by
2967 initializing the specifier using Fmake_specifier(), followed by 3400 initializing the specifier using Fmake_specifier(), followed by
2968 set_specifier_fallback(), followed (optionally) by 3401 set_specifier_fallback(), followed (optionally) by
2969 set_specifier_caching(). 3402 set_specifier_caching().
2970 - If you used set_specifier_caching(), make sure to create the 3403 - If you used set_specifier_caching(), make sure to create the
2971 appropriate value-changed functions. Also make sure to add the 3404 appropriate value-changed functions. Also make sure to add the
2972 appropriate slots where the values are cached to frameslots.h and 3405 appropriate slots where the values are cached to frameslots.h and
2973 winslots.h. 3406 winslots.h.
2974 3407
2975 Do a grep for menubar_visible_p for an example. 3408 Do a grep for menubar_visible_p for an example.
2976 */ 3409 */
2977 3410
2978 /* #### It would be nice if the specifier caching automatically knew 3411 /* #### It would be nice if the specifier caching automatically knew
2991 { 3424 {
2992 Lisp_Specifier *sp = XSPECIFIER (specifier); 3425 Lisp_Specifier *sp = XSPECIFIER (specifier);
2993 assert (!GHOST_SPECIFIER_P (sp)); 3426 assert (!GHOST_SPECIFIER_P (sp));
2994 3427
2995 if (!sp->caching) 3428 if (!sp->caching)
2996 sp->caching = xnew_and_zero (struct specifier_caching); 3429 #ifdef NEW_GC
3430 sp->caching = alloc_lrecord_type (struct specifier_caching,
3431 &lrecord_specifier_caching);
3432 #else /* not NEW_GC */
3433 sp->caching = xnew_and_zero (struct specifier_caching);
3434 #endif /* not NEW_GC */
2997 sp->caching->offset_into_struct_window = struct_window_offset; 3435 sp->caching->offset_into_struct_window = struct_window_offset;
2998 sp->caching->value_changed_in_window = value_changed_in_window; 3436 sp->caching->value_changed_in_window = value_changed_in_window;
2999 sp->caching->offset_into_struct_frame = struct_frame_offset; 3437 sp->caching->offset_into_struct_frame = struct_frame_offset;
3000 sp->caching->value_changed_in_frame = value_changed_in_frame; 3438 sp->caching->value_changed_in_frame = value_changed_in_frame;
3001 if (struct_window_offset) 3439 if (struct_window_offset)
3291 /* Display table specifier type */ 3729 /* Display table specifier type */
3292 /************************************************************************/ 3730 /************************************************************************/
3293 3731
3294 DEFINE_SPECIFIER_TYPE (display_table); 3732 DEFINE_SPECIFIER_TYPE (display_table);
3295 3733
3296 #define VALID_SINGLE_DISPTABLE_INSTANTIATOR_P(instantiator) \ 3734 #define VALID_SINGLE_DISPTABLE_INSTANTIATOR_P(instantiator) \
3297 (VECTORP (instantiator) \ 3735 (VECTORP (instantiator) \
3298 || (CHAR_TABLEP (instantiator) \ 3736 || (CHAR_TABLEP (instantiator) \
3299 && (XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_CHAR \ 3737 && (XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_CHAR \
3300 || XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_GENERIC)) \ 3738 || XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_GENERIC)) \
3301 || RANGE_TABLEP (instantiator)) 3739 || RANGE_TABLEP (instantiator))
3302 3740
3303 static void 3741 static void
3304 display_table_validate (Lisp_Object instantiator) 3742 display_table_validate (Lisp_Object instantiator)
3319 if (!VALID_SINGLE_DISPTABLE_INSTANTIATOR_P (instantiator)) 3757 if (!VALID_SINGLE_DISPTABLE_INSTANTIATOR_P (instantiator))
3320 { 3758 {
3321 lose: 3759 lose:
3322 dead_wrong_type_argument 3760 dead_wrong_type_argument
3323 (display_table_specifier_methods->predicate_symbol, 3761 (display_table_specifier_methods->predicate_symbol,
3324 instantiator); 3762 instantiator);
3325 } 3763 }
3326 } 3764 }
3327 } 3765 }
3328 3766
3329 DEFUN ("display-table-specifier-p", Fdisplay_table_specifier_p, 1, 1, 0, /* 3767 DEFUN ("display-table-specifier-p", Fdisplay_table_specifier_p, 1, 1, 0, /*
3344 3782
3345 void 3783 void
3346 syms_of_specifier (void) 3784 syms_of_specifier (void)
3347 { 3785 {
3348 INIT_LISP_OBJECT (specifier); 3786 INIT_LISP_OBJECT (specifier);
3787 #ifdef NEW_GC
3788 INIT_LISP_OBJECT (specifier_caching);
3789 #endif /* NEW_GC */
3349 3790
3350 DEFSYMBOL (Qspecifierp); 3791 DEFSYMBOL (Qspecifierp);
3351 3792
3352 DEFSYMBOL (Qconsole_type); 3793 DEFSYMBOL (Qconsole_type);
3353 DEFSYMBOL (Qdevice_class); 3794 DEFSYMBOL (Qdevice_class);
3369 DEFSUBR (Fvalid_specifier_tag_set_p); 3810 DEFSUBR (Fvalid_specifier_tag_set_p);
3370 DEFSUBR (Fcanonicalize_tag_set); 3811 DEFSUBR (Fcanonicalize_tag_set);
3371 DEFSUBR (Fdevice_matches_specifier_tag_set_p); 3812 DEFSUBR (Fdevice_matches_specifier_tag_set_p);
3372 DEFSUBR (Fdefine_specifier_tag); 3813 DEFSUBR (Fdefine_specifier_tag);
3373 DEFSUBR (Fdevice_matching_specifier_tag_list); 3814 DEFSUBR (Fdevice_matching_specifier_tag_list);
3815
3374 DEFSUBR (Fspecifier_tag_list); 3816 DEFSUBR (Fspecifier_tag_list);
3375 DEFSUBR (Fspecifier_tag_predicate); 3817 DEFSUBR (Fspecifier_tag_device_predicate);
3818 DEFSUBR (Fspecifier_tag_charset_predicate);
3376 3819
3377 DEFSUBR (Fcheck_valid_instantiator); 3820 DEFSUBR (Fcheck_valid_instantiator);
3378 DEFSUBR (Fvalid_instantiator_p); 3821 DEFSUBR (Fvalid_instantiator_p);
3379 DEFSUBR (Fcheck_valid_inst_list); 3822 DEFSUBR (Fcheck_valid_inst_list);
3380 DEFSUBR (Fvalid_inst_list_p); 3823 DEFSUBR (Fvalid_inst_list_p);
3471 Vuser_defined_tags = Qnil; 3914 Vuser_defined_tags = Qnil;
3472 staticpro (&Vuser_defined_tags); 3915 staticpro (&Vuser_defined_tags);
3473 3916
3474 Vunlock_ghost_specifiers = Qnil; 3917 Vunlock_ghost_specifiers = Qnil;
3475 staticpro (&Vunlock_ghost_specifiers); 3918 staticpro (&Vunlock_ghost_specifiers);
3476 } 3919
3920 Vcharset_tag_lists = make_vector(NUM_LEADING_BYTES, Qnil);
3921 staticpro (&Vcharset_tag_lists);
3922 }