Mercurial > hg > xemacs-beta
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 } |