1 /* Specifier implementation
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995, 1996 Ben Wing.
4 Copyright (C) 1995 Sun Microsystems, Inc.
6 This file is part of XEmacs.
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* Synched up with: Not in FSF. */
25 /* Design by Ben Wing;
26 Original version by Chuck Thompson;
27 rewritten by Ben Wing;
28 Magic specifiers by Kirill Katsnelson;
38 #include "specifier.h"
40 #include "glyphs.h" /* for DISP_TABLE_SIZE definition */
42 Lisp_Object Qspecifierp;
43 Lisp_Object Qprepend, Qappend, Qremove_tag_set_prepend, Qremove_tag_set_append;
44 Lisp_Object Qremove_locale, Qremove_locale_type, Qremove_all;
45 Lisp_Object Qfallback;
47 /* Qinteger, Qboolean, Qgeneric defined in general.c. */
50 Lisp_Object Qconsole_type, Qdevice_class;
52 static Lisp_Object Vuser_defined_tags;
54 typedef struct specifier_type_entry specifier_type_entry;
55 struct specifier_type_entry
58 struct specifier_methods *meths;
63 Dynarr_declare (specifier_type_entry);
64 } specifier_type_entry_dynarr;
66 specifier_type_entry_dynarr *the_specifier_type_entry_dynarr;
68 static Lisp_Object Vspecifier_type_list;
70 static Lisp_Object Vcached_specifiers;
71 /* Do NOT mark through this, or specifiers will never be GC'd. */
72 static Lisp_Object Vall_specifiers;
74 static Lisp_Object Vunlock_ghost_specifiers;
76 /* #### The purpose of this is to check for inheritance loops
77 in specifiers that can inherit from other specifiers, but it's
80 #### Look into this for 19.14. */
81 /* static Lisp_Object_dynarr current_specifiers; */
83 static void recompute_cached_specifier_everywhere (Lisp_Object specifier);
85 EXFUN (Fspecifier_specs, 4);
86 EXFUN (Fremove_specifier, 4);
89 /************************************************************************/
90 /* Specifier object methods */
91 /************************************************************************/
93 /* Remove dead objects from the specified assoc list. */
96 cleanup_assoc_list (Lisp_Object list)
98 Lisp_Object loop, prev, retval;
100 loop = retval = list;
105 Lisp_Object entry = XCAR (loop);
106 Lisp_Object key = XCAR (entry);
108 /* remember, dead windows can become alive again. */
109 if (!WINDOWP (key) && object_dead_p (key))
113 /* Removing the head. */
114 retval = XCDR (retval);
118 Fsetcdr (prev, XCDR (loop));
130 /* Remove dead objects from the various lists so that they
131 don't keep getting marked as long as this specifier exists and
132 therefore wasting memory. */
135 cleanup_specifiers (void)
139 for (rest = Vall_specifiers;
141 rest = XSPECIFIER (rest)->next_specifier)
143 struct Lisp_Specifier *sp = XSPECIFIER (rest);
144 /* This effectively changes the specifier specs.
145 However, there's no need to call
146 recompute_cached_specifier_everywhere() or the
147 after-change methods because the only specs we
148 are removing are for dead objects, and they can
149 never have any effect on the specifier values:
150 specifiers can only be instantiated over live
151 objects, and you can't derive a dead object
153 sp->device_specs = cleanup_assoc_list (sp->device_specs);
154 sp->frame_specs = cleanup_assoc_list (sp->frame_specs);
155 sp->buffer_specs = cleanup_assoc_list (sp->buffer_specs);
156 /* windows are handled specially because dead windows
157 can be resurrected */
162 kill_specifier_buffer_locals (Lisp_Object buffer)
166 for (rest = Vall_specifiers;
168 rest = XSPECIFIER (rest)->next_specifier)
170 struct Lisp_Specifier *sp = XSPECIFIER (rest);
172 /* Make sure we're actually going to be changing something.
173 Fremove_specifier() always calls
174 recompute_cached_specifier_everywhere() (#### but should
175 be smarter about this). */
176 if (!NILP (assq_no_quit (buffer, sp->buffer_specs)))
177 Fremove_specifier (rest, buffer, Qnil, Qnil);
182 mark_specifier (Lisp_Object obj, void (*markobj) (Lisp_Object))
184 struct Lisp_Specifier *specifier = XSPECIFIER (obj);
186 ((markobj) (specifier->global_specs));
187 ((markobj) (specifier->device_specs));
188 ((markobj) (specifier->frame_specs));
189 ((markobj) (specifier->window_specs));
190 ((markobj) (specifier->buffer_specs));
191 ((markobj) (specifier->magic_parent));
192 ((markobj) (specifier->fallback));
193 if (!GHOST_SPECIFIER_P (XSPECIFIER (obj)))
194 MAYBE_SPECMETH (specifier, mark, (obj, markobj));
198 /* The idea here is that the specifier specs point to locales
199 (windows, buffers, frames, and devices), and we want to make sure
200 that the specs disappear automatically when the associated locale
201 is no longer in use. For all but windows, "no longer in use"
202 corresponds exactly to when the object is deleted (non-deleted
203 objects are always held permanently in special lists, and deleted
204 objects are never on these lists and never reusable). To handle
205 this, we just have cleanup_specifiers() called periodically
206 (at the beginning of garbage collection); it removes all dead
209 For windows, however, it's trickier because dead objects can be
210 converted to live ones again if the dead object is in a window
211 configuration. Therefore, for windows, "no longer in use"
212 corresponds to when the window object is garbage-collected.
213 We now use weak lists for this purpose.
218 prune_specifiers (int (*obj_marked_p) (Lisp_Object))
220 Lisp_Object rest, prev = Qnil;
222 for (rest = Vall_specifiers;
224 rest = XSPECIFIER (rest)->next_specifier)
226 if (! ((*obj_marked_p) (rest)))
228 struct Lisp_Specifier* sp = XSPECIFIER (rest);
229 /* A bit of assertion that we're removing both parts of the
230 magic one altogether */
231 assert (!GC_MAGIC_SPECIFIER_P(sp)
232 || (GC_BODILY_SPECIFIER_P(sp) && (*obj_marked_p)(sp->fallback))
233 || (GC_GHOST_SPECIFIER_P(sp) && (*obj_marked_p)(sp->magic_parent)));
234 /* This specifier is garbage. Remove it from the list. */
236 Vall_specifiers = sp->next_specifier;
238 XSPECIFIER (prev)->next_specifier = sp->next_specifier;
246 print_specifier (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
248 struct Lisp_Specifier *sp = XSPECIFIER (obj);
250 int count = specpdl_depth ();
251 Lisp_Object the_specs;
254 error ("printing unreadable object #<%s-specifier 0x%x>",
255 sp->methods->name, sp->header.uid);
257 sprintf (buf, "#<%s-specifier global=", sp->methods->name);
258 write_c_string (buf, printcharfun);
259 specbind (Qprint_string_length, make_int (100));
260 specbind (Qprint_length, make_int (5));
261 the_specs = Fspecifier_specs (obj, Qglobal, Qnil, Qnil);
262 if (NILP (the_specs))
263 /* there are no global specs */
264 write_c_string ("<unspecified>", printcharfun);
266 print_internal (the_specs, printcharfun, 1);
267 if (!NILP (sp->fallback))
269 write_c_string (" fallback=", printcharfun);
270 print_internal (sp->fallback, printcharfun, escapeflag);
272 unbind_to (count, Qnil);
273 sprintf (buf, " 0x%x>", sp->header.uid);
274 write_c_string (buf, printcharfun);
278 finalize_specifier (void *header, int for_disksave)
280 struct Lisp_Specifier *sp = (struct Lisp_Specifier *) header;
281 /* don't be snafued by the disksave finalization. */
282 if (!for_disksave && !GC_GHOST_SPECIFIER_P(sp) && sp->caching)
290 specifier_equal (Lisp_Object o1, Lisp_Object o2, int depth)
292 struct Lisp_Specifier *s1 = XSPECIFIER (o1);
293 struct Lisp_Specifier *s2 = XSPECIFIER (o2);
295 Lisp_Object old_inhibit_quit = Vinhibit_quit;
297 /* This function can be called from within redisplay.
298 internal_equal can trigger a quit. That leads to Bad Things. */
303 (s1->methods == s2->methods &&
304 internal_equal (s1->global_specs, s2->global_specs, depth) &&
305 internal_equal (s1->device_specs, s2->device_specs, depth) &&
306 internal_equal (s1->frame_specs, s2->frame_specs, depth) &&
307 internal_equal (s1->window_specs, s2->window_specs, depth) &&
308 internal_equal (s1->buffer_specs, s2->buffer_specs, depth) &&
309 internal_equal (s1->fallback, s2->fallback, depth));
311 if (retval && HAS_SPECMETH_P (s1, equal))
312 retval = SPECMETH (s1, equal, (o1, o2, depth - 1));
314 Vinhibit_quit = old_inhibit_quit;
319 specifier_hash (Lisp_Object obj, int depth)
321 struct Lisp_Specifier *s = XSPECIFIER (obj);
323 /* specifier hashing is a bit problematic because there are so
324 many places where data can be stored. We pick what are perhaps
325 the most likely places where interesting stuff will be. */
326 return HASH5 ((HAS_SPECMETH_P (s, hash) ?
327 SPECMETH (s, hash, (obj, depth)) : 0),
328 (unsigned long) s->methods,
329 internal_hash (s->global_specs, depth + 1),
330 internal_hash (s->frame_specs, depth + 1),
331 internal_hash (s->buffer_specs, depth + 1));
335 sizeof_specifier (CONST void *header)
337 if (GHOST_SPECIFIER_P ((struct Lisp_Specifier *) header))
338 return sizeof (struct Lisp_Specifier);
341 CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header;
342 return sizeof (*p) + p->methods->extra_data_size - 1;
346 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier,
347 mark_specifier, print_specifier,
349 specifier_equal, specifier_hash,
351 struct Lisp_Specifier);
353 /************************************************************************/
354 /* Creating specifiers */
355 /************************************************************************/
357 static struct specifier_methods *
358 decode_specifier_type (Lisp_Object type, Error_behavior errb)
362 for (i = 0; i < Dynarr_length (the_specifier_type_entry_dynarr); i++)
364 if (EQ (type, Dynarr_at (the_specifier_type_entry_dynarr, i).symbol))
365 return Dynarr_at (the_specifier_type_entry_dynarr, i).meths;
368 maybe_signal_simple_error ("Invalid specifier type", type,
375 valid_specifier_type_p (Lisp_Object type)
377 return decode_specifier_type (type, ERROR_ME_NOT) != 0;
380 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /*
381 Given a SPECIFIER-TYPE, return non-nil if it is valid.
382 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image,
383 'face-boolean, and 'toolbar.
387 return valid_specifier_type_p (specifier_type) ? Qt : Qnil;
390 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /*
391 Return a list of valid specifier types.
395 return Fcopy_sequence (Vspecifier_type_list);
399 add_entry_to_specifier_type_list (Lisp_Object symbol,
400 struct specifier_methods *meths)
402 struct specifier_type_entry entry;
404 entry.symbol = symbol;
406 Dynarr_add (the_specifier_type_entry_dynarr, entry);
407 Vspecifier_type_list = Fcons (symbol, Vspecifier_type_list);
411 make_specifier_internal (struct specifier_methods *spec_meths,
412 size_t data_size, int call_create_meth)
414 Lisp_Object specifier;
415 struct Lisp_Specifier *sp = (struct Lisp_Specifier *)
416 alloc_lcrecord (sizeof (struct Lisp_Specifier) +
417 data_size - 1, lrecord_specifier);
419 sp->methods = spec_meths;
420 sp->global_specs = Qnil;
421 sp->device_specs = Qnil;
422 sp->frame_specs = Qnil;
423 sp->window_specs = make_weak_list (WEAK_LIST_KEY_ASSOC);
424 sp->buffer_specs = Qnil;
426 sp->magic_parent = Qnil;
428 sp->next_specifier = Vall_specifiers;
430 XSETSPECIFIER (specifier, sp);
431 Vall_specifiers = specifier;
433 if (call_create_meth)
437 MAYBE_SPECMETH (XSPECIFIER (specifier), create, (specifier));
444 make_specifier (struct specifier_methods *meths)
446 return make_specifier_internal (meths, meths->extra_data_size, 1);
450 make_magic_specifier (Lisp_Object type)
452 /* This function can GC */
453 struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
454 Lisp_Object bodily, ghost;
457 bodily = make_specifier (meths);
459 ghost = make_specifier_internal (meths, 0, 0);
462 /* Connect guys together */
463 XSPECIFIER(bodily)->magic_parent = Qt;
464 XSPECIFIER(bodily)->fallback = ghost;
465 XSPECIFIER(ghost)->magic_parent = bodily;
470 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /*
471 Return a new specifier object of type TYPE.
473 A specifier is an object that can be used to keep track of a property
474 whose value can be per-buffer, per-window, per-frame, or per-device,
475 and can further be restricted to a particular console-type or device-class.
476 Specifiers are used, for example, for the various built-in properties of a
477 face; this allows a face to have different values in different frames,
478 buffers, etc. For more information, see `specifier-instance',
479 `specifier-specs', and `add-spec-to-specifier'; or, for a detailed
480 description of specifiers, including how they are instantiated over a
481 particular domain (i.e. how their value in that domain is determined),
482 see the chapter on specifiers in the XEmacs Lisp Reference Manual.
484 TYPE specifies the particular type of specifier, and should be one of
485 the symbols 'generic, 'integer, 'boolean, 'color, 'font, 'image,
486 'face-boolean, or 'toolbar.
488 For more information on particular types of specifiers, see the functions
489 `generic-specifier-p', `integer-specifier-p', `boolean-specifier-p',
490 `color-specifier-p', `font-specifier-p', `image-specifier-p',
491 `face-boolean-specifier-p', and `toolbar-specifier-p'.
495 /* This function can GC */
496 struct specifier_methods *meths = decode_specifier_type (type,
499 return make_specifier (meths);
502 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /*
503 Return t if OBJECT is a specifier.
505 A specifier is an object that can be used to keep track of a property
506 whose value can be per-buffer, per-window, per-frame, or per-device,
507 and can further be restricted to a particular console-type or device-class.
508 See `make-specifier'.
512 return SPECIFIERP (object) ? Qt : Qnil;
515 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /*
516 Return the type of SPECIFIER.
520 CHECK_SPECIFIER (specifier);
521 return intern (XSPECIFIER (specifier)->methods->name);
525 /************************************************************************/
526 /* Locales and domains */
527 /************************************************************************/
529 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /*
530 Return t if LOCALE is a valid specifier locale.
531 Valid locales are devices, frames, windows, buffers, and 'global.
536 /* This cannot GC. */
537 return ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) ||
538 (FRAMEP (locale) && FRAME_LIVE_P (XFRAME (locale))) ||
539 (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) ||
540 /* dead windows are allowed because they may become live
541 windows again when a window configuration is restored */
543 EQ (locale, Qglobal))
547 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /*
548 Return t if DOMAIN is a valid specifier domain.
549 A domain is used to instance a specifier (i.e. determine the specifier's
550 value in that domain). Valid domains are windows, frames, and devices.
555 /* This cannot GC. */
556 return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) ||
557 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) ||
558 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))))
562 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /*
563 Given a specifier LOCALE-TYPE, return non-nil if it is valid.
564 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer.
565 \(Note, however, that in functions that accept either a locale or a locale
566 type, 'global is considered an individual locale.)
570 /* This cannot GC. */
571 return (EQ (locale_type, Qglobal) ||
572 EQ (locale_type, Qdevice) ||
573 EQ (locale_type, Qframe) ||
574 EQ (locale_type, Qwindow) ||
575 EQ (locale_type, Qbuffer)) ? Qt : Qnil;
579 check_valid_locale_or_locale_type (Lisp_Object locale)
581 /* This cannot GC. */
582 if (EQ (locale, Qall) ||
583 !NILP (Fvalid_specifier_locale_p (locale)) ||
584 !NILP (Fvalid_specifier_locale_type_p (locale)))
586 signal_simple_error ("Invalid specifier locale or locale type", locale);
589 DEFUN ("specifier-locale-type-from-locale", Fspecifier_locale_type_from_locale,
591 Given a specifier LOCALE, return its type.
595 /* This cannot GC. */
596 if (NILP (Fvalid_specifier_locale_p (locale)))
597 signal_simple_error ("Invalid specifier locale", locale);
598 if (DEVICEP (locale)) return Qdevice;
599 if (FRAMEP (locale)) return Qframe;
600 if (WINDOWP (locale)) return Qwindow;
601 if (BUFFERP (locale)) return Qbuffer;
602 assert (EQ (locale, Qglobal));
607 decode_locale (Lisp_Object locale)
609 /* This cannot GC. */
612 else if (!NILP (Fvalid_specifier_locale_p (locale)))
615 signal_simple_error ("Invalid specifier locale", locale);
620 static enum spec_locale_type
621 decode_locale_type (Lisp_Object locale_type)
623 /* This cannot GC. */
624 if (EQ (locale_type, Qglobal)) return LOCALE_GLOBAL;
625 if (EQ (locale_type, Qdevice)) return LOCALE_DEVICE;
626 if (EQ (locale_type, Qframe)) return LOCALE_FRAME;
627 if (EQ (locale_type, Qwindow)) return LOCALE_WINDOW;
628 if (EQ (locale_type, Qbuffer)) return LOCALE_BUFFER;
630 signal_simple_error ("Invalid specifier locale type", locale_type);
631 return LOCALE_GLOBAL; /* not reached */
635 decode_locale_list (Lisp_Object locale)
637 /* This cannot GC. */
638 /* The return value of this function must be GCPRO'd. */
640 locale = list1 (Qall);
645 locale = list1 (locale);
646 EXTERNAL_LIST_LOOP (rest, locale)
647 check_valid_locale_or_locale_type (XCAR (rest));
652 static enum spec_locale_type
653 locale_type_from_locale (Lisp_Object locale)
655 return decode_locale_type (Fspecifier_locale_type_from_locale (locale));
659 check_valid_domain (Lisp_Object domain)
661 if (NILP (Fvalid_specifier_domain_p (domain)))
662 signal_simple_error ("Invalid specifier domain", domain);
666 decode_domain (Lisp_Object domain)
669 return Fselected_window (Qnil);
670 check_valid_domain (domain);
675 /************************************************************************/
677 /************************************************************************/
679 DEFUN ("valid-specifier-tag-p", Fvalid_specifier_tag_p, 1, 1, 0, /*
680 Return non-nil if TAG is a valid specifier tag.
681 See also `valid-specifier-tag-set-p'.
685 return (valid_console_type_p (tag) ||
686 valid_device_class_p (tag) ||
687 !NILP (assq_no_quit (tag, Vuser_defined_tags))) ? Qt : Qnil;
690 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /*
691 Return non-nil if TAG-SET is a valid specifier tag set.
693 A specifier tag set is an entity that is attached to an instantiator
694 and can be used to restrict the scope of that instantiator to a
695 particular device class or device type and/or to mark instantiators
696 added by a particular package so that they can be later removed.
698 A specifier tag set consists of a list of zero of more specifier tags,
699 each of which is a symbol that is recognized by XEmacs as a tag.
700 \(The valid device types and device classes are always tags, as are
701 any tags defined by `define-specifier-tag'.) It is called a "tag set"
702 \(as opposed to a list) because the order of the tags or the number of
703 times a particular tag occurs does not matter.
705 Each tag has a predicate associated with it, which specifies whether
706 that tag applies to a particular device. The tags which are device types
707 and classes match devices of that type or class. User-defined tags can
708 have any predicate, or none (meaning that all devices match). When
709 attempting to instance a specifier, a particular instantiator is only
710 considered if the device of the domain being instanced over matches
711 all tags in the tag set attached to that instantiator.
713 Most of the time, a tag set is not specified, and the instantiator
714 gets a null tag set, which matches all devices.
720 for (rest = tag_set; !NILP (rest); rest = XCDR (rest))
724 if (NILP (Fvalid_specifier_tag_p (XCAR (rest))))
732 decode_specifier_tag_set (Lisp_Object tag_set)
734 /* The return value of this function must be GCPRO'd. */
735 if (!NILP (Fvalid_specifier_tag_p (tag_set)))
736 return list1 (tag_set);
737 if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
738 signal_simple_error ("Invalid specifier tag-set", tag_set);
743 canonicalize_tag_set (Lisp_Object tag_set)
745 int len = XINT (Flength (tag_set));
746 Lisp_Object *tags, rest;
749 /* We assume in this function that the tag_set has already been
750 validated, so there are no surprises. */
752 if (len == 0 || len == 1)
753 /* most common case */
756 tags = alloca_array (Lisp_Object, len);
759 LIST_LOOP (rest, tag_set)
760 tags[i++] = XCAR (rest);
762 /* Sort the list of tags. We use a bubble sort here (copied from
763 extent_fragment_update()) -- reduces the function call overhead,
764 and is the fastest sort for small numbers of items. */
766 for (i = 1; i < len; i++)
770 strcmp ((char *) string_data (XSYMBOL (tags[j])->name),
771 (char *) string_data (XSYMBOL (tags[j+1])->name)) > 0)
773 Lisp_Object tmp = tags[j];
780 /* Now eliminate duplicates. */
782 for (i = 1, j = 1; i < len; i++)
784 /* j holds the destination, i the source. */
785 if (!EQ (tags[i], tags[i-1]))
789 return Flist (j, tags);
792 DEFUN ("canonicalize-tag-set", Fcanonicalize_tag_set, 1, 1, 0, /*
793 Canonicalize the given tag set.
794 Two canonicalized tag sets can be compared with `equal' to see if they
795 represent the same tag set. (Specifically, canonicalizing involves
796 sorting by symbol name and removing duplicates.)
800 if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
801 signal_simple_error ("Invalid tag set", tag_set);
802 return canonicalize_tag_set (tag_set);
806 device_matches_specifier_tag_set_p (Lisp_Object device, Lisp_Object tag_set)
808 Lisp_Object devtype, devclass, rest;
809 struct device *d = XDEVICE (device);
811 devtype = DEVICE_TYPE (d);
812 devclass = DEVICE_CLASS (d);
814 LIST_LOOP (rest, tag_set)
816 Lisp_Object tag = XCAR (rest);
819 if (EQ (tag, devtype) || EQ (tag, devclass))
821 assoc = assq_no_quit (tag, DEVICE_USER_DEFINED_TAGS (d));
822 /* other built-in tags (device types/classes) are not in
823 the user-defined-tags list. */
824 if (NILP (assoc) || NILP (XCDR (assoc)))
831 DEFUN ("device-matches-specifier-tag-set-p", Fdevice_matches_specifier_tag_set_p, 2, 2, 0, /*
832 Return non-nil if DEVICE matches specifier tag set TAG-SET.
833 This means that DEVICE matches each tag in the tag set. (Every
834 tag recognized by XEmacs has a predicate associated with it that
835 specifies which devices match it.)
839 CHECK_LIVE_DEVICE (device);
841 if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
842 signal_simple_error ("Invalid tag set", tag_set);
844 return device_matches_specifier_tag_set_p (device, tag_set) ? Qt : Qnil;
847 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /*
848 Define a new specifier tag.
849 If PREDICATE is specified, it should be a function of one argument
850 \(a device) that specifies whether the tag matches that particular
851 device. If PREDICATE is omitted, the tag matches all devices.
853 You can redefine an existing user-defined specifier tag. However,
854 you cannot redefine the built-in specifier tags (the device types
855 and classes) or the symbols nil, t, 'all, or 'global.
859 Lisp_Object assoc, devcons, concons;
863 if (valid_device_class_p (tag) ||
864 valid_console_type_p (tag))
865 signal_simple_error ("Cannot redefine built-in specifier tags", tag);
866 /* Try to prevent common instantiators and locales from being
867 redefined, to reduce ambiguity */
868 if (NILP (tag) || EQ (tag, Qt) || EQ (tag, Qall) || EQ (tag, Qglobal))
869 signal_simple_error ("Cannot define nil, t, 'all, or 'global",
871 assoc = assq_no_quit (tag, Vuser_defined_tags);
875 Vuser_defined_tags = Fcons (Fcons (tag, predicate), Vuser_defined_tags);
876 DEVICE_LOOP_NO_BREAK (devcons, concons)
878 struct device *d = XDEVICE (XCAR (devcons));
879 /* Initially set the value to t in case of error
881 DEVICE_USER_DEFINED_TAGS (d) =
882 Fcons (Fcons (tag, Qt), DEVICE_USER_DEFINED_TAGS (d));
885 else if (!NILP (predicate) && !NILP (XCDR (assoc)))
888 XCDR (assoc) = predicate;
891 /* recompute the tag values for all devices. However, in the special
892 case where both the old and new predicates are nil, we know that
893 we don't have to do this. (It's probably common for people to
894 call (define-specifier-tag) more than once on the same tag,
895 and the most common case is where PREDICATE is not specified.) */
899 DEVICE_LOOP_NO_BREAK (devcons, concons)
901 Lisp_Object device = XCAR (devcons);
902 assoc = assq_no_quit (tag,
903 DEVICE_USER_DEFINED_TAGS (XDEVICE (device)));
904 assert (CONSP (assoc));
905 if (NILP (predicate))
908 XCDR (assoc) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
915 /* Called at device-creation time to initialize the user-defined
916 tag values for the newly-created device. */
919 setup_device_initial_specifier_tags (struct device *d)
921 Lisp_Object rest, rest2;
924 XSETDEVICE (device, d);
926 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags);
928 /* Now set up the initial values */
929 LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d))
930 XCDR (XCAR (rest)) = Qt;
932 for (rest = Vuser_defined_tags, rest2 = DEVICE_USER_DEFINED_TAGS (d);
933 !NILP (rest); rest = XCDR (rest), rest2 = XCDR (rest2))
935 Lisp_Object predicate = XCDR (XCAR (rest));
936 if (NILP (predicate))
937 XCDR (XCAR (rest2)) = Qt;
939 XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
943 DEFUN ("device-matching-specifier-tag-list", Fdevice_matching_specifier_tag_list,
945 Return a list of all specifier tags matching DEVICE.
946 DEVICE defaults to the selected device if omitted.
950 struct device *d = decode_device (device);
951 Lisp_Object rest, list = Qnil;
956 LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d))
958 if (!NILP (XCDR (XCAR (rest))))
959 list = Fcons (XCAR (XCAR (rest)), list);
962 list = Fnreverse (list);
963 list = Fcons (DEVICE_CLASS (d), list);
964 list = Fcons (DEVICE_TYPE (d), list);
966 RETURN_UNGCPRO (list);
969 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /*
970 Return a list of all currently-defined specifier tags.
971 This includes the built-in ones (the device types and classes).
975 Lisp_Object list = Qnil, rest;
980 LIST_LOOP (rest, Vuser_defined_tags)
981 list = Fcons (XCAR (XCAR (rest)), list);
983 list = Fnreverse (list);
984 list = nconc2 (Fcopy_sequence (Vdevice_class_list), list);
985 list = nconc2 (Fcopy_sequence (Vconsole_type_list), list);
987 RETURN_UNGCPRO (list);
990 DEFUN ("specifier-tag-predicate", Fspecifier_tag_predicate, 1, 1, 0, /*
991 Return the predicate for the given specifier tag.
995 /* The return value of this function must be GCPRO'd. */
998 if (NILP (Fvalid_specifier_tag_p (tag)))
999 signal_simple_error ("Invalid specifier tag", tag);
1001 /* Make up some predicates for the built-in types */
1003 if (valid_console_type_p (tag))
1004 return list3 (Qlambda, list1 (Qdevice),
1005 list3 (Qeq, list2 (Qquote, tag),
1006 list2 (Qconsole_type, Qdevice)));
1008 if (valid_device_class_p (tag))
1009 return list3 (Qlambda, list1 (Qdevice),
1010 list3 (Qeq, list2 (Qquote, tag),
1011 list2 (Qdevice_class, Qdevice)));
1013 return XCDR (assq_no_quit (tag, Vuser_defined_tags));
1016 /* Return true if A "matches" B. If EXACT_P is 0, A must be a subset of B.
1017 Otherwise, A must be `equal' to B. The sets must be canonicalized. */
1019 tag_sets_match_p (Lisp_Object a, Lisp_Object b, int exact_p)
1023 while (!NILP (a) && !NILP (b))
1025 if (EQ (XCAR (a), XCAR (b)))
1034 while (!NILP (a) && !NILP (b))
1036 if (!EQ (XCAR (a), XCAR (b)))
1042 return NILP (a) && NILP (b);
1047 /************************************************************************/
1048 /* Spec-lists and inst-lists */
1049 /************************************************************************/
1052 call_validate_method (Lisp_Object boxed_method, Lisp_Object instantiator)
1054 ((void (*)(Lisp_Object)) get_opaque_ptr (boxed_method)) (instantiator);
1059 check_valid_instantiator (Lisp_Object instantiator,
1060 struct specifier_methods *meths,
1061 Error_behavior errb)
1063 if (meths->validate_method)
1067 if (ERRB_EQ (errb, ERROR_ME))
1069 (meths->validate_method) (instantiator);
1074 Lisp_Object opaque = make_opaque_ptr ((void *)
1075 meths->validate_method);
1076 struct gcpro gcpro1;
1079 retval = call_with_suspended_errors
1080 ((lisp_fn_t) call_validate_method,
1081 Qnil, Qspecifier, errb, 2, opaque, instantiator);
1083 free_opaque_ptr (opaque);
1092 DEFUN ("check-valid-instantiator", Fcheck_valid_instantiator, 2, 2, 0, /*
1093 Signal an error if INSTANTIATOR is invalid for SPECIFIER-TYPE.
1095 (instantiator, specifier_type))
1097 struct specifier_methods *meths = decode_specifier_type (specifier_type,
1100 return check_valid_instantiator (instantiator, meths, ERROR_ME);
1103 DEFUN ("valid-instantiator-p", Fvalid_instantiator_p, 2, 2, 0, /*
1104 Return non-nil if INSTANTIATOR is valid for SPECIFIER-TYPE.
1106 (instantiator, specifier_type))
1108 struct specifier_methods *meths = decode_specifier_type (specifier_type,
1111 return check_valid_instantiator (instantiator, meths, ERROR_ME_NOT);
1115 check_valid_inst_list (Lisp_Object inst_list, struct specifier_methods *meths,
1116 Error_behavior errb)
1120 LIST_LOOP (rest, inst_list)
1122 Lisp_Object inst_pair, tag_set;
1126 maybe_signal_simple_error ("Invalid instantiator list", inst_list,
1130 if (!CONSP (inst_pair = XCAR (rest)))
1132 maybe_signal_simple_error ("Invalid instantiator pair", inst_pair,
1136 if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair))))
1138 maybe_signal_simple_error ("Invalid specifier tag", tag_set,
1143 if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb)))
1150 DEFUN ("check-valid-inst-list", Fcheck_valid_inst_list, 2, 2, 0, /*
1151 Signal an error if INST-LIST is invalid for specifier type TYPE.
1155 struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1157 return check_valid_inst_list (inst_list, meths, ERROR_ME);
1160 DEFUN ("valid-inst-list-p", Fvalid_inst_list_p, 2, 2, 0, /*
1161 Return non-nil if INST-LIST is valid for specifier type TYPE.
1165 struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1167 return check_valid_inst_list (inst_list, meths, ERROR_ME_NOT);
1171 check_valid_spec_list (Lisp_Object spec_list, struct specifier_methods *meths,
1172 Error_behavior errb)
1176 LIST_LOOP (rest, spec_list)
1178 Lisp_Object spec, locale;
1179 if (!CONSP (rest) || !CONSP (spec = XCAR (rest)))
1181 maybe_signal_simple_error ("Invalid specification list", spec_list,
1185 if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec))))
1187 maybe_signal_simple_error ("Invalid specifier locale", locale,
1192 if (NILP (check_valid_inst_list (XCDR (spec), meths, errb)))
1199 DEFUN ("check-valid-spec-list", Fcheck_valid_spec_list, 2, 2, 0, /*
1200 Signal an error if SPEC-LIST is invalid for specifier type TYPE.
1204 struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1206 return check_valid_spec_list (spec_list, meths, ERROR_ME);
1209 DEFUN ("valid-spec-list-p", Fvalid_spec_list_p, 2, 2, 0, /*
1210 Return non-nil if SPEC-LIST is valid for specifier type TYPE.
1214 struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1216 return check_valid_spec_list (spec_list, meths, ERROR_ME_NOT);
1220 decode_how_to_add_specification (Lisp_Object how_to_add)
1222 if (NILP (how_to_add) || EQ (Qremove_tag_set_prepend, how_to_add))
1223 return SPEC_REMOVE_TAG_SET_PREPEND;
1224 if (EQ (Qremove_tag_set_append, how_to_add))
1225 return SPEC_REMOVE_TAG_SET_APPEND;
1226 if (EQ (Qappend, how_to_add))
1228 if (EQ (Qprepend, how_to_add))
1229 return SPEC_PREPEND;
1230 if (EQ (Qremove_locale, how_to_add))
1231 return SPEC_REMOVE_LOCALE;
1232 if (EQ (Qremove_locale_type, how_to_add))
1233 return SPEC_REMOVE_LOCALE_TYPE;
1234 if (EQ (Qremove_all, how_to_add))
1235 return SPEC_REMOVE_ALL;
1237 signal_simple_error ("Invalid `how-to-add' flag", how_to_add);
1239 return SPEC_PREPEND; /* not reached */
1242 /* Given a specifier object SPEC, return bodily specifier if SPEC is a
1243 ghost specifier, otherwise return the object itself
1246 bodily_specifier (Lisp_Object spec)
1248 return (GHOST_SPECIFIER_P (XSPECIFIER (spec))
1249 ? XSPECIFIER(spec)->magic_parent : spec);
1252 /* Signal error if (specifier SPEC is read-only.
1253 Read only are ghost specifiers unless Vunlock_ghost_specifiers is
1254 non-nil. All other specifiers are read-write.
1257 check_modifiable_specifier (Lisp_Object spec)
1259 if (NILP (Vunlock_ghost_specifiers)
1260 && GHOST_SPECIFIER_P (XSPECIFIER (spec)))
1261 signal_simple_error ("Attempt to modify read-only specifier",
1265 /* Helper function which unwind protects the value of
1266 Vunlock_ghost_specifiers, then sets it to non-nil value */
1268 restore_unlock_value (Lisp_Object val)
1270 Vunlock_ghost_specifiers = val;
1275 unlock_ghost_specifiers_protected (void)
1277 int depth = specpdl_depth ();
1278 record_unwind_protect (restore_unlock_value,
1279 Vunlock_ghost_specifiers);
1280 Vunlock_ghost_specifiers = Qt;
1284 /* This gets hit so much that the function call overhead had a
1285 measurable impact (according to Quantify). #### We should figure
1286 out the frequency with which this is called with the various types
1287 and reorder the check accordingly. */
1288 #define SPECIFIER_GET_SPEC_LIST(specifier, type) \
1289 (type == LOCALE_GLOBAL ? &(XSPECIFIER (specifier)->global_specs) : \
1290 type == LOCALE_DEVICE ? &(XSPECIFIER (specifier)->device_specs) : \
1291 type == LOCALE_FRAME ? &(XSPECIFIER (specifier)->frame_specs) : \
1292 type == LOCALE_WINDOW ? &(XWEAK_LIST_LIST \
1293 (XSPECIFIER (specifier)->window_specs)) : \
1294 type == LOCALE_BUFFER ? &(XSPECIFIER (specifier)->buffer_specs) : \
1297 static Lisp_Object *
1298 specifier_get_inst_list (Lisp_Object specifier, Lisp_Object locale,
1299 enum spec_locale_type type)
1301 Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1302 Lisp_Object specification;
1304 if (type == LOCALE_GLOBAL)
1306 /* Calling assq_no_quit when it is just going to return nil anyhow
1307 is extremely expensive. So sayeth Quantify. */
1308 if (!CONSP (*spec_list))
1310 specification = assq_no_quit (locale, *spec_list);
1311 if (NILP (specification))
1313 return &XCDR (specification);
1316 /* For the given INST_LIST, return a new INST_LIST containing all elements
1317 where TAG-SET matches the element's tag set. EXACT_P indicates whether
1318 the match must be exact (as opposed to a subset). SHORT_P indicates
1319 that the short form (for `specifier-specs') should be returned if
1320 possible. If COPY_TREE_P, `copy-tree' is used to ensure that no
1321 elements of the new list are shared with the initial list.
1325 specifier_process_inst_list (Lisp_Object inst_list,
1326 Lisp_Object tag_set, int exact_p,
1327 int short_p, int copy_tree_p)
1329 Lisp_Object retval = Qnil;
1331 struct gcpro gcpro1;
1334 LIST_LOOP (rest, inst_list)
1336 Lisp_Object tagged_inst = XCAR (rest);
1337 Lisp_Object tagged_inst_tag = XCAR (tagged_inst);
1338 if (tag_sets_match_p (tag_set, tagged_inst_tag, exact_p))
1340 if (short_p && NILP (tagged_inst_tag))
1341 retval = Fcons (copy_tree_p ?
1342 Fcopy_tree (XCDR (tagged_inst), Qt) :
1346 retval = Fcons (copy_tree_p ? Fcopy_tree (tagged_inst, Qt) :
1347 tagged_inst, retval);
1350 retval = Fnreverse (retval);
1352 /* If there is a single instantiator and the short form is
1353 requested, return just the instantiator (rather than a one-element
1354 list of it) unless it is nil (so that it can be distinguished from
1355 no instantiators at all). */
1356 if (short_p && CONSP (retval) && !NILP (XCAR (retval)) &&
1357 NILP (XCDR (retval)))
1358 return XCAR (retval);
1364 specifier_get_external_inst_list (Lisp_Object specifier, Lisp_Object locale,
1365 enum spec_locale_type type,
1366 Lisp_Object tag_set, int exact_p,
1367 int short_p, int copy_tree_p)
1369 Lisp_Object *inst_list = specifier_get_inst_list (specifier, locale,
1371 if (!inst_list || NILP (*inst_list))
1373 /* nil for *inst_list should only occur in 'global */
1374 assert (!inst_list || EQ (locale, Qglobal));
1378 return specifier_process_inst_list (*inst_list, tag_set, exact_p,
1379 short_p, copy_tree_p);
1383 specifier_get_external_spec_list (Lisp_Object specifier,
1384 enum spec_locale_type type,
1385 Lisp_Object tag_set, int exact_p)
1387 Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1388 Lisp_Object retval = Qnil;
1390 struct gcpro gcpro1;
1392 assert (type != LOCALE_GLOBAL);
1393 /* We're about to let stuff go external; make sure there aren't
1395 *spec_list = cleanup_assoc_list (*spec_list);
1398 LIST_LOOP (rest, *spec_list)
1400 Lisp_Object spec = XCAR (rest);
1401 Lisp_Object inst_list =
1402 specifier_process_inst_list (XCDR (spec), tag_set, exact_p, 0, 1);
1403 if (!NILP (inst_list))
1404 retval = Fcons (Fcons (XCAR (spec), inst_list), retval);
1406 RETURN_UNGCPRO (Fnreverse (retval));
1409 static Lisp_Object *
1410 specifier_new_spec (Lisp_Object specifier, Lisp_Object locale,
1411 enum spec_locale_type type)
1413 Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1414 Lisp_Object new_spec = Fcons (locale, Qnil);
1415 assert (type != LOCALE_GLOBAL);
1416 *spec_list = Fcons (new_spec, *spec_list);
1417 return &XCDR (new_spec);
1420 /* For the given INST_LIST, return a new list comprised of elements
1421 where TAG_SET does not match the element's tag set. This operation
1425 specifier_process_remove_inst_list (Lisp_Object inst_list,
1426 Lisp_Object tag_set, int exact_p,
1429 Lisp_Object prev = Qnil, rest;
1433 LIST_LOOP (rest, inst_list)
1435 if (tag_sets_match_p (tag_set, XCAR (XCAR (rest)), exact_p))
1437 /* time to remove. */
1440 inst_list = XCDR (rest);
1442 XCDR (prev) = XCDR (rest);
1452 specifier_remove_spec (Lisp_Object specifier, Lisp_Object locale,
1453 enum spec_locale_type type,
1454 Lisp_Object tag_set, int exact_p)
1456 Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1460 if (type == LOCALE_GLOBAL)
1461 *spec_list = specifier_process_remove_inst_list (*spec_list, tag_set,
1462 exact_p, &was_removed);
1465 assoc = assq_no_quit (locale, *spec_list);
1467 /* this locale is not found. */
1469 XCDR (assoc) = specifier_process_remove_inst_list (XCDR (assoc),
1472 if (NILP (XCDR (assoc)))
1473 /* no inst-pairs left; remove this locale entirely. */
1474 *spec_list = remassq_no_quit (locale, *spec_list);
1478 MAYBE_SPECMETH (XSPECIFIER (specifier), after_change,
1479 (bodily_specifier (specifier), locale));
1483 specifier_remove_locale_type (Lisp_Object specifier,
1484 enum spec_locale_type type,
1485 Lisp_Object tag_set, int exact_p)
1487 Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1488 Lisp_Object prev = Qnil, rest;
1490 assert (type != LOCALE_GLOBAL);
1491 LIST_LOOP (rest, *spec_list)
1494 int remove_spec = 0;
1495 Lisp_Object spec = XCAR (rest);
1497 /* There may be dead objects floating around */
1498 /* remember, dead windows can become alive again. */
1499 if (!WINDOWP (XCAR (spec)) && object_dead_p (XCAR (spec)))
1506 XCDR (spec) = specifier_process_remove_inst_list (XCDR (spec),
1509 if (NILP (XCDR (spec)))
1516 *spec_list = XCDR (rest);
1518 XCDR (prev) = XCDR (rest);
1524 MAYBE_SPECMETH (XSPECIFIER (specifier), after_change,
1525 (bodily_specifier (specifier), XCAR (spec)));
1529 /* NEW_LIST is going to be added to INST_LIST, with add method ADD_METH.
1530 Frob INST_LIST according to ADD_METH. No need to call an after-change
1531 function; the calling function will do this. Return either SPEC_PREPEND
1532 or SPEC_APPEND, indicating whether to prepend or append the NEW_LIST. */
1534 static enum spec_add_meth
1535 handle_multiple_add_insts (Lisp_Object *inst_list,
1536 Lisp_Object new_list,
1537 enum spec_add_meth add_meth)
1541 case SPEC_REMOVE_TAG_SET_APPEND:
1542 add_meth = SPEC_APPEND;
1543 goto remove_tag_set;
1544 case SPEC_REMOVE_TAG_SET_PREPEND:
1545 add_meth = SPEC_PREPEND;
1550 LIST_LOOP (rest, new_list)
1552 Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest)));
1553 struct gcpro gcpro1;
1556 /* pull out all elements from the existing list with the
1557 same tag as any tags in NEW_LIST. */
1558 *inst_list = remassoc_no_quit (canontag, *inst_list);
1563 case SPEC_REMOVE_LOCALE:
1565 return SPEC_PREPEND;
1569 return SPEC_PREPEND;
1573 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER,
1574 copy, canonicalize, and call the going_to_add methods as necessary
1575 to produce a new list that is the one that really will be added
1576 to the specifier. */
1579 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale,
1580 Lisp_Object inst_list)
1582 /* The return value of this function must be GCPRO'd. */
1583 Lisp_Object rest, list_to_build_up = Qnil;
1584 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1585 struct gcpro gcpro1;
1587 GCPRO1 (list_to_build_up);
1588 LIST_LOOP (rest, inst_list)
1590 Lisp_Object tag_set = XCAR (XCAR (rest));
1591 Lisp_Object instantiator = Fcopy_tree (XCDR (XCAR (rest)), Qt);
1592 Lisp_Object sub_inst_list = Qnil;
1593 struct gcpro ngcpro1, ngcpro2;
1595 NGCPRO2 (instantiator, sub_inst_list);
1596 /* call the will-add method; it may GC */
1597 sub_inst_list = HAS_SPECMETH_P (sp, going_to_add) ?
1598 SPECMETH (sp, going_to_add,
1599 (bodily_specifier (specifier), locale,
1600 tag_set, instantiator)) :
1602 if (EQ (sub_inst_list, Qt))
1603 /* no change here. */
1604 sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set),
1608 /* now canonicalize all the tag sets in the new objects */
1610 LIST_LOOP (rest2, sub_inst_list)
1611 XCAR (XCAR (rest2)) = canonicalize_tag_set (XCAR (XCAR (rest2)));
1614 list_to_build_up = nconc2 (sub_inst_list, list_to_build_up);
1618 RETURN_UNGCPRO (Fnreverse (list_to_build_up));
1621 /* Add a specification (locale and instantiator list) to a specifier.
1622 ADD_METH specifies what to do with existing specifications in the
1623 specifier, and is an enum that corresponds to the values in
1624 `add-spec-to-specifier'. The calling routine is responsible for
1625 validating LOCALE and INST-LIST, but the tag-sets in INST-LIST
1626 do not need to be canonicalized. */
1628 /* #### I really need to rethink the after-change
1629 functions to make them easier to use and more efficient. */
1632 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale,
1633 Lisp_Object inst_list, enum spec_add_meth add_meth)
1635 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1636 enum spec_locale_type type = locale_type_from_locale (locale);
1637 Lisp_Object *orig_inst_list, tem;
1638 Lisp_Object list_to_build_up = Qnil;
1639 struct gcpro gcpro1;
1641 GCPRO1 (list_to_build_up);
1642 list_to_build_up = build_up_processed_list (specifier, locale, inst_list);
1643 /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL. These are the
1644 add-meth types that affect locales other than this one. */
1645 if (add_meth == SPEC_REMOVE_LOCALE_TYPE)
1646 specifier_remove_locale_type (specifier, type, Qnil, 0);
1647 else if (add_meth == SPEC_REMOVE_ALL)
1649 specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0);
1650 specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0);
1651 specifier_remove_locale_type (specifier, LOCALE_FRAME, Qnil, 0);
1652 specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0);
1653 specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0);
1656 orig_inst_list = specifier_get_inst_list (specifier, locale, type);
1657 if (!orig_inst_list)
1658 orig_inst_list = specifier_new_spec (specifier, locale, type);
1659 add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up,
1662 if (add_meth == SPEC_PREPEND)
1663 tem = nconc2 (list_to_build_up, *orig_inst_list);
1664 else if (add_meth == SPEC_APPEND)
1665 tem = nconc2 (*orig_inst_list, list_to_build_up);
1669 *orig_inst_list = tem;
1673 /* call the after-change method */
1674 MAYBE_SPECMETH (sp, after_change,
1675 (bodily_specifier (specifier), locale));
1679 specifier_copy_spec (Lisp_Object specifier, Lisp_Object dest,
1680 Lisp_Object locale, enum spec_locale_type type,
1681 Lisp_Object tag_set, int exact_p,
1682 enum spec_add_meth add_meth)
1684 Lisp_Object inst_list =
1685 specifier_get_external_inst_list (specifier, locale, type, tag_set,
1687 specifier_add_spec (dest, locale, inst_list, add_meth);
1691 specifier_copy_locale_type (Lisp_Object specifier, Lisp_Object dest,
1692 enum spec_locale_type type,
1693 Lisp_Object tag_set, int exact_p,
1694 enum spec_add_meth add_meth)
1696 Lisp_Object *src_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1699 /* This algorithm is O(n^2) in running time.
1700 It's certainly possible to implement an O(n log n) algorithm,
1701 but I doubt there's any need to. */
1703 LIST_LOOP (rest, *src_list)
1705 Lisp_Object spec = XCAR (rest);
1706 /* There may be dead objects floating around */
1707 /* remember, dead windows can become alive again. */
1708 if (WINDOWP (XCAR (spec)) || !object_dead_p (XCAR (spec)))
1711 specifier_process_inst_list (XCDR (spec), tag_set, exact_p, 0, 0),
1716 /* map MAPFUN over the locales in SPECIFIER that are given in LOCALE.
1717 CLOSURE is passed unchanged to MAPFUN. LOCALE can be one of
1719 -- nil (same as 'all)
1720 -- a single locale, locale type, or 'all
1721 -- a list of locales, locale types, and/or 'all
1723 MAPFUN is called for each locale and locale type given; for 'all,
1724 it is called for the locale 'global and for the four possible
1725 locale types. In each invocation, either LOCALE will be a locale
1726 and LOCALE_TYPE will be the locale type of this locale,
1727 or LOCALE will be nil and LOCALE_TYPE will be a locale type.
1728 If MAPFUN ever returns non-zero, the mapping is halted and the
1729 value returned is returned from map_specifier(). Otherwise, the
1730 mapping proceeds to the end and map_specifier() returns 0.
1734 map_specifier (Lisp_Object specifier, Lisp_Object locale,
1735 int (*mapfun) (Lisp_Object specifier,
1737 enum spec_locale_type locale_type,
1738 Lisp_Object tag_set,
1741 Lisp_Object tag_set, Lisp_Object exact_p,
1746 struct gcpro gcpro1, gcpro2;
1748 GCPRO2 (tag_set, locale);
1749 locale = decode_locale_list (locale);
1750 tag_set = decode_specifier_tag_set (tag_set);
1751 tag_set = canonicalize_tag_set (tag_set);
1753 LIST_LOOP (rest, locale)
1755 Lisp_Object theloc = XCAR (rest);
1756 if (!NILP (Fvalid_specifier_locale_p (theloc)))
1758 retval = (*mapfun) (specifier, theloc,
1759 locale_type_from_locale (theloc),
1760 tag_set, !NILP (exact_p), closure);
1764 else if (!NILP (Fvalid_specifier_locale_type_p (theloc)))
1766 retval = (*mapfun) (specifier, Qnil,
1767 decode_locale_type (theloc), tag_set,
1768 !NILP (exact_p), closure);
1774 assert (EQ (theloc, Qall));
1775 retval = (*mapfun) (specifier, Qnil, LOCALE_BUFFER, tag_set,
1776 !NILP (exact_p), closure);
1779 retval = (*mapfun) (specifier, Qnil, LOCALE_WINDOW, tag_set,
1780 !NILP (exact_p), closure);
1783 retval = (*mapfun) (specifier, Qnil, LOCALE_FRAME, tag_set,
1784 !NILP (exact_p), closure);
1787 retval = (*mapfun) (specifier, Qnil, LOCALE_DEVICE, tag_set,
1788 !NILP (exact_p), closure);
1791 retval = (*mapfun) (specifier, Qglobal, LOCALE_GLOBAL, tag_set,
1792 !NILP (exact_p), closure);
1802 DEFUN ("add-spec-to-specifier", Fadd_spec_to_specifier, 2, 5, 0, /*
1803 Add a specification to SPECIFIER.
1804 The specification maps from LOCALE (which should be a window, buffer,
1805 frame, device, or 'global, and defaults to 'global) to INSTANTIATOR,
1806 whose allowed values depend on the type of the specifier. Optional
1807 argument TAG-SET limits the instantiator to apply only to the specified
1808 tag set, which should be a list of tags all of which must match the
1809 device being instantiated over (tags are a device type, a device class,
1810 or tags defined with `define-specifier-tag'). Specifying a single
1811 symbol for TAG-SET is equivalent to specifying a one-element list
1812 containing that symbol. Optional argument HOW-TO-ADD specifies what to
1813 do if there are already specifications in the specifier.
1816 'prepend Put at the beginning of the current list of
1817 instantiators for LOCALE.
1818 'append Add to the end of the current list of
1819 instantiators for LOCALE.
1820 'remove-tag-set-prepend (this is the default)
1821 Remove any existing instantiators whose tag set is
1822 the same as TAG-SET; then put the new instantiator
1823 at the beginning of the current list. ("Same tag
1824 set" means that they contain the same elements.
1825 The order may be different.)
1826 'remove-tag-set-append
1827 Remove any existing instantiators whose tag set is
1828 the same as TAG-SET; then put the new instantiator
1829 at the end of the current list.
1830 'remove-locale Remove all previous instantiators for this locale
1831 before adding the new spec.
1832 'remove-locale-type Remove all specifications for all locales of the
1833 same type as LOCALE (this includes LOCALE itself)
1834 before adding the new spec.
1835 'remove-all Remove all specifications from the specifier
1836 before adding the new spec.
1838 You can retrieve the specifications for a particular locale or locale type
1839 with the function `specifier-spec-list' or `specifier-specs'.
1841 (specifier, instantiator, locale, tag_set, how_to_add))
1843 enum spec_add_meth add_meth;
1844 Lisp_Object inst_list;
1845 struct gcpro gcpro1;
1847 CHECK_SPECIFIER (specifier);
1848 check_modifiable_specifier (specifier);
1850 locale = decode_locale (locale);
1851 check_valid_instantiator (instantiator,
1852 decode_specifier_type
1853 (Fspecifier_type (specifier), ERROR_ME),
1855 /* tag_set might be newly-created material, but it's part of inst_list
1856 so is properly GC-protected. */
1857 tag_set = decode_specifier_tag_set (tag_set);
1858 add_meth = decode_how_to_add_specification (how_to_add);
1860 inst_list = list1 (Fcons (tag_set, instantiator));
1862 specifier_add_spec (specifier, locale, inst_list, add_meth);
1863 recompute_cached_specifier_everywhere (specifier);
1864 RETURN_UNGCPRO (Qnil);
1867 DEFUN ("add-spec-list-to-specifier", Fadd_spec_list_to_specifier, 2, 3, 0, /*
1868 Add a spec-list (a list of specifications) to SPECIFIER.
1869 The format of a spec-list is
1871 ((LOCALE (TAG-SET . INSTANTIATOR) ...) ...)
1874 LOCALE := a window, a buffer, a frame, a device, or 'global
1875 TAG-SET := an unordered list of zero or more TAGS, each of which
1877 TAG := a device class (see `valid-device-class-p'), a device type
1878 (see `valid-console-type-p'), or a tag defined with
1879 `define-specifier-tag'
1880 INSTANTIATOR := format determined by the type of specifier
1882 The pair (TAG-SET . INSTANTIATOR) is called an `inst-pair'.
1883 A list of inst-pairs is called an `inst-list'.
1884 The pair (LOCALE . INST-LIST) is called a `specification' or `spec'.
1885 A spec-list, then, can be viewed as a list of specifications.
1887 HOW-TO-ADD specifies how to combine the new specifications with
1888 the existing ones, and has the same semantics as for
1889 `add-spec-to-specifier'.
1891 In many circumstances, the higher-level function `set-specifier' is
1892 more convenient and should be used instead.
1894 (specifier, spec_list, how_to_add))
1896 enum spec_add_meth add_meth;
1899 CHECK_SPECIFIER (specifier);
1900 check_modifiable_specifier (specifier);
1902 check_valid_spec_list (spec_list,
1903 decode_specifier_type
1904 (Fspecifier_type (specifier), ERROR_ME),
1906 add_meth = decode_how_to_add_specification (how_to_add);
1908 LIST_LOOP (rest, spec_list)
1910 /* Placating the GCC god. */
1911 Lisp_Object specification = XCAR (rest);
1912 Lisp_Object locale = XCAR (specification);
1913 Lisp_Object inst_list = XCDR (specification);
1915 specifier_add_spec (specifier, locale, inst_list, add_meth);
1917 recompute_cached_specifier_everywhere (specifier);
1922 add_spec_to_ghost_specifier (Lisp_Object specifier, Lisp_Object instantiator,
1923 Lisp_Object locale, Lisp_Object tag_set,
1924 Lisp_Object how_to_add)
1926 int depth = unlock_ghost_specifiers_protected ();
1927 Fadd_spec_to_specifier (XSPECIFIER(specifier)->fallback,
1928 instantiator, locale, tag_set, how_to_add);
1929 unbind_to (depth, Qnil);
1932 struct specifier_spec_list_closure
1934 Lisp_Object head, tail;
1938 specifier_spec_list_mapfun (Lisp_Object specifier,
1940 enum spec_locale_type locale_type,
1941 Lisp_Object tag_set,
1945 struct specifier_spec_list_closure *cl =
1946 (struct specifier_spec_list_closure *) closure;
1947 Lisp_Object partial;
1950 partial = specifier_get_external_spec_list (specifier,
1955 partial = specifier_get_external_inst_list (specifier, locale,
1956 locale_type, tag_set,
1958 if (!NILP (partial))
1959 partial = list1 (Fcons (locale, partial));
1964 /* tack on the new list */
1965 if (NILP (cl->tail))
1966 cl->head = cl->tail = partial;
1968 XCDR (cl->tail) = partial;
1969 /* find the new tail */
1970 while (CONSP (XCDR (cl->tail)))
1971 cl->tail = XCDR (cl->tail);
1975 /* For the given SPECIFIER create and return a list of all specs
1976 contained within it, subject to LOCALE. If LOCALE is a locale, only
1977 specs in that locale will be returned. If LOCALE is a locale type,
1978 all specs in all locales of that type will be returned. If LOCALE is
1979 nil, all specs will be returned. This always copies lists and never
1980 returns the actual lists, because we do not want someone manipulating
1981 the actual objects. This may cause a slight loss of potential
1982 functionality but if we were to allow it then a user could manage to
1983 violate our assertion that the specs contained in the actual
1984 specifier lists are all valid. */
1986 DEFUN ("specifier-spec-list", Fspecifier_spec_list, 1, 4, 0, /*
1987 Return the spec-list of specifications for SPECIFIER in LOCALE.
1989 If LOCALE is a particular locale (a buffer, window, frame, device,
1990 or 'global), a spec-list consisting of the specification for that
1991 locale will be returned.
1993 If LOCALE is a locale type (i.e. 'buffer, 'window, 'frame, or 'device),
1994 a spec-list of the specifications for all locales of that type will be
1997 If LOCALE is nil or 'all, a spec-list of all specifications in SPECIFIER
2000 LOCALE can also be a list of locales, locale types, and/or 'all; the
2001 result is as if `specifier-spec-list' were called on each element of the
2002 list and the results concatenated together.
2004 Only instantiators where TAG-SET (a list of zero or more tags) is a
2005 subset of (or possibly equal to) the instantiator's tag set are returned.
2006 \(The default value of nil is a subset of all tag sets, so in this case
2007 no instantiators will be screened out.) If EXACT-P is non-nil, however,
2008 TAG-SET must be equal to an instantiator's tag set for the instantiator
2011 (specifier, locale, tag_set, exact_p))
2013 struct specifier_spec_list_closure cl;
2014 struct gcpro gcpro1, gcpro2;
2016 CHECK_SPECIFIER (specifier);
2017 cl.head = cl.tail = Qnil;
2018 GCPRO2 (cl.head, cl.tail);
2019 map_specifier (specifier, locale, specifier_spec_list_mapfun,
2020 tag_set, exact_p, &cl);
2026 DEFUN ("specifier-specs", Fspecifier_specs, 1, 4, 0, /*
2027 Return the specification(s) for SPECIFIER in LOCALE.
2029 If LOCALE is a single locale or is a list of one element containing a
2030 single locale, then a "short form" of the instantiators for that locale
2031 will be returned. Otherwise, this function is identical to
2032 `specifier-spec-list'.
2034 The "short form" is designed for readability and not for ease of use
2035 in Lisp programs, and is as follows:
2037 1. If there is only one instantiator, then an inst-pair (i.e. cons of
2038 tag and instantiator) will be returned; otherwise a list of
2039 inst-pairs will be returned.
2040 2. For each inst-pair returned, if the instantiator's tag is 'any,
2041 the tag will be removed and the instantiator itself will be returned
2042 instead of the inst-pair.
2043 3. If there is only one instantiator, its value is nil, and its tag is
2044 'any, a one-element list containing nil will be returned rather
2045 than just nil, to distinguish this case from there being no
2046 instantiators at all.
2048 (specifier, locale, tag_set, exact_p))
2050 if (!NILP (Fvalid_specifier_locale_p (locale)) ||
2051 (CONSP (locale) && !NILP (Fvalid_specifier_locale_p (XCAR (locale))) &&
2052 NILP (XCDR (locale))))
2054 struct gcpro gcpro1;
2056 CHECK_SPECIFIER (specifier);
2058 locale = XCAR (locale);
2060 tag_set = decode_specifier_tag_set (tag_set);
2061 tag_set = canonicalize_tag_set (tag_set);
2063 (specifier_get_external_inst_list (specifier, locale,
2064 locale_type_from_locale (locale),
2065 tag_set, !NILP (exact_p), 1, 1));
2068 return Fspecifier_spec_list (specifier, locale, tag_set, exact_p);
2072 remove_specifier_mapfun (Lisp_Object specifier,
2074 enum spec_locale_type locale_type,
2075 Lisp_Object tag_set,
2077 void *ignored_closure)
2080 specifier_remove_locale_type (specifier, locale_type, tag_set, exact_p);
2082 specifier_remove_spec (specifier, locale, locale_type, tag_set, exact_p);
2086 DEFUN ("remove-specifier", Fremove_specifier, 1, 4, 0, /*
2087 Remove specification(s) for SPECIFIER.
2089 If LOCALE is a particular locale (a window, buffer, frame, device,
2090 or 'global), the specification for that locale will be removed.
2092 If instead, LOCALE is a locale type (i.e. 'window, 'buffer, 'frame,
2093 or 'device), the specifications for all locales of that type will be
2096 If LOCALE is nil or 'all, all specifications will be removed.
2098 LOCALE can also be a list of locales, locale types, and/or 'all; this
2099 is equivalent to calling `remove-specifier' for each of the elements
2102 Only instantiators where TAG-SET (a list of zero or more tags) is a
2103 subset of (or possibly equal to) the instantiator's tag set are removed.
2104 The default value of nil is a subset of all tag sets, so in this case
2105 no instantiators will be screened out. If EXACT-P is non-nil, however,
2106 TAG-SET must be equal to an instantiator's tag set for the instantiator
2109 (specifier, locale, tag_set, exact_p))
2111 CHECK_SPECIFIER (specifier);
2112 check_modifiable_specifier (specifier);
2114 map_specifier (specifier, locale, remove_specifier_mapfun,
2115 tag_set, exact_p, 0);
2116 recompute_cached_specifier_everywhere (specifier);
2121 remove_ghost_specifier (Lisp_Object specifier, Lisp_Object locale,
2122 Lisp_Object tag_set, Lisp_Object exact_p)
2124 int depth = unlock_ghost_specifiers_protected ();
2125 Fremove_specifier (XSPECIFIER(specifier)->fallback,
2126 locale, tag_set, exact_p);
2127 unbind_to (depth, Qnil);
2130 struct copy_specifier_closure
2133 enum spec_add_meth add_meth;
2134 int add_meth_is_nil;
2138 copy_specifier_mapfun (Lisp_Object specifier,
2140 enum spec_locale_type locale_type,
2141 Lisp_Object tag_set,
2145 struct copy_specifier_closure *cl =
2146 (struct copy_specifier_closure *) closure;
2149 specifier_copy_locale_type (specifier, cl->dest, locale_type,
2151 cl->add_meth_is_nil ?
2152 SPEC_REMOVE_LOCALE_TYPE :
2155 specifier_copy_spec (specifier, cl->dest, locale, locale_type,
2157 cl->add_meth_is_nil ? SPEC_REMOVE_LOCALE :
2162 DEFUN ("copy-specifier", Fcopy_specifier, 1, 6, 0, /*
2163 Copy SPECIFIER to DEST, or create a new one if DEST is nil.
2165 If DEST is nil or omitted, a new specifier will be created and the
2166 specifications copied into it. Otherwise, the specifications will be
2167 copied into the existing specifier in DEST.
2169 If LOCALE is nil or 'all, all specifications will be copied. If LOCALE
2170 is a particular locale, the specification for that particular locale will
2171 be copied. If LOCALE is a locale type, the specifications for all locales
2172 of that type will be copied. LOCALE can also be a list of locales,
2173 locale types, and/or 'all; this is equivalent to calling `copy-specifier'
2174 for each of the elements of the list. See `specifier-spec-list' for more
2175 information about LOCALE.
2177 Only instantiators where TAG-SET (a list of zero or more tags) is a
2178 subset of (or possibly equal to) the instantiator's tag set are copied.
2179 The default value of nil is a subset of all tag sets, so in this case
2180 no instantiators will be screened out. If EXACT-P is non-nil, however,
2181 TAG-SET must be equal to an instantiator's tag set for the instantiator
2184 Optional argument HOW-TO-ADD specifies what to do with existing
2185 specifications in DEST. If nil, then whichever locales or locale types
2186 are copied will first be completely erased in DEST. Otherwise, it is
2187 the same as in `add-spec-to-specifier'.
2189 (specifier, dest, locale, tag_set, exact_p, how_to_add))
2191 struct gcpro gcpro1;
2192 struct copy_specifier_closure cl;
2194 CHECK_SPECIFIER (specifier);
2195 if (NILP (how_to_add))
2196 cl.add_meth_is_nil = 1;
2198 cl.add_meth_is_nil = 0;
2199 cl.add_meth = decode_how_to_add_specification (how_to_add);
2202 /* #### What about copying the extra data? */
2203 dest = make_specifier (XSPECIFIER (specifier)->methods);
2207 CHECK_SPECIFIER (dest);
2208 check_modifiable_specifier (dest);
2209 if (XSPECIFIER (dest)->methods != XSPECIFIER (specifier)->methods)
2210 error ("Specifiers not of same type");
2215 map_specifier (specifier, locale, copy_specifier_mapfun,
2216 tag_set, exact_p, &cl);
2218 recompute_cached_specifier_everywhere (dest);
2223 /************************************************************************/
2225 /************************************************************************/
2228 call_validate_matchspec_method (Lisp_Object boxed_method,
2229 Lisp_Object matchspec)
2231 ((void (*)(Lisp_Object)) get_opaque_ptr (boxed_method)) (matchspec);
2236 check_valid_specifier_matchspec (Lisp_Object matchspec,
2237 struct specifier_methods *meths,
2238 Error_behavior errb)
2240 if (meths->validate_matchspec_method)
2244 if (ERRB_EQ (errb, ERROR_ME))
2246 (meths->validate_matchspec_method) (matchspec);
2251 Lisp_Object opaque =
2252 make_opaque_ptr ((void *) meths->validate_matchspec_method);
2253 struct gcpro gcpro1;
2256 retval = call_with_suspended_errors
2257 ((lisp_fn_t) call_validate_matchspec_method,
2258 Qnil, Qspecifier, errb, 2, opaque, matchspec);
2260 free_opaque_ptr (opaque);
2268 maybe_signal_simple_error
2269 ("Matchspecs not allowed for this specifier type",
2270 intern (meths->name), Qspecifier, errb);
2275 DEFUN ("check-valid-specifier-matchspec", Fcheck_valid_specifier_matchspec, 2, 2, 0, /*
2276 Signal an error if MATCHSPEC is invalid for SPECIFIER-TYPE.
2277 See `specifier-matching-instance' for a description of matchspecs.
2279 (matchspec, specifier_type))
2281 struct specifier_methods *meths = decode_specifier_type (specifier_type,
2284 return check_valid_specifier_matchspec (matchspec, meths, ERROR_ME);
2287 DEFUN ("valid-specifier-matchspec-p", Fvalid_specifier_matchspec_p, 2, 2, 0, /*
2288 Return non-nil if MATCHSPEC is valid for SPECIFIER-TYPE.
2289 See `specifier-matching-instance' for a description of matchspecs.
2291 (matchspec, specifier_type))
2293 struct specifier_methods *meths = decode_specifier_type (specifier_type,
2296 return check_valid_specifier_matchspec (matchspec, meths, ERROR_ME_NOT);
2299 /* This function is purposely not callable from Lisp. If a Lisp
2300 caller wants to set a fallback, they should just set the
2304 set_specifier_fallback (Lisp_Object specifier, Lisp_Object fallback)
2306 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2307 assert (SPECIFIERP (fallback) ||
2308 !NILP (Fvalid_inst_list_p (fallback, Fspecifier_type (specifier))));
2309 if (SPECIFIERP (fallback))
2310 assert (EQ (Fspecifier_type (specifier), Fspecifier_type (fallback)));
2311 if (BODILY_SPECIFIER_P (sp))
2312 GHOST_SPECIFIER(sp)->fallback = fallback;
2314 sp->fallback = fallback;
2315 /* call the after-change method */
2316 MAYBE_SPECMETH (sp, after_change,
2317 (bodily_specifier (specifier), Qfallback));
2318 recompute_cached_specifier_everywhere (specifier);
2321 DEFUN ("specifier-fallback", Fspecifier_fallback, 1, 1, 0, /*
2322 Return the fallback value for SPECIFIER.
2323 Fallback values are provided by the C code for certain built-in
2324 specifiers to make sure that instancing won't fail even if all
2325 specs are removed from the specifier, or to implement simple
2326 inheritance behavior (e.g. this method is used to ensure that
2327 faces other than 'default inherit their attributes from 'default).
2328 By design, you cannot change the fallback value, and specifiers
2329 created with `make-specifier' will never have a fallback (although
2330 a similar, Lisp-accessible capability may be provided in the future
2331 to allow for inheritance).
2333 The fallback value will be an inst-list that is instanced like
2334 any other inst-list, a specifier of the same type as SPECIFIER
2335 \(results in inheritance), or nil for no fallback.
2337 When you instance a specifier, you can explicitly request that the
2338 fallback not be consulted. (The C code does this, for example, when
2339 merging faces.) See `specifier-instance'.
2343 CHECK_SPECIFIER (specifier);
2344 return Fcopy_tree (XSPECIFIER (specifier)->fallback, Qt);
2348 specifier_instance_from_inst_list (Lisp_Object specifier,
2349 Lisp_Object matchspec,
2351 Lisp_Object inst_list,
2352 Error_behavior errb, int no_quit,
2355 /* This function can GC */
2356 struct Lisp_Specifier *sp;
2359 int count = specpdl_depth ();
2360 struct gcpro gcpro1, gcpro2;
2362 GCPRO2 (specifier, inst_list);
2364 sp = XSPECIFIER (specifier);
2365 device = DFW_DEVICE (domain);
2368 /* The instantiate method is allowed to call eval. Since it
2369 is quite common for this function to get called from somewhere in
2370 redisplay we need to make sure that quits are ignored. Otherwise
2371 Fsignal will abort. */
2372 specbind (Qinhibit_quit, Qt);
2374 LIST_LOOP (rest, inst_list)
2376 Lisp_Object tagged_inst = XCAR (rest);
2377 Lisp_Object tag_set = XCAR (tagged_inst);
2379 if (device_matches_specifier_tag_set_p (device, tag_set))
2381 Lisp_Object val = XCDR (tagged_inst);
2383 if (HAS_SPECMETH_P (sp, instantiate))
2384 val = call_with_suspended_errors
2385 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate),
2386 Qunbound, Qspecifier, errb, 5, specifier,
2387 matchspec, domain, val, depth);
2389 if (!UNBOUNDP (val))
2391 unbind_to (count, Qnil);
2398 unbind_to (count, Qnil);
2403 /* Given a SPECIFIER and a DOMAIN, return a specific instance for that
2404 specifier. Try to find one by checking the specifier types from most
2405 specific (buffer) to most general (global). If we find an instance,
2406 return it. Otherwise return Qunbound. */
2408 #define CHECK_INSTANCE_ENTRY(key, matchspec, type) \
2410 Lisp_Object *__inst_list = \
2411 specifier_get_inst_list (specifier, key, type); \
2414 Lisp_Object __val__ = \
2415 specifier_instance_from_inst_list (specifier, matchspec, \
2416 domain, *__inst_list, \
2417 errb, no_quit, depth); \
2418 if (!UNBOUNDP (__val__)) \
2423 /* We accept any window, frame or device domain and do our checking
2424 starting from as specific a locale type as we can determine from the
2425 domain we are passed and going on up through as many other locale types
2426 as we can determine. In practice, when called from redisplay the
2427 arg will usually be a window and occasionally a frame. If
2428 triggered by a user call, who knows what it will usually be. */
2430 specifier_instance (Lisp_Object specifier, Lisp_Object matchspec,
2431 Lisp_Object domain, Error_behavior errb, int no_quit,
2432 int no_fallback, Lisp_Object depth)
2434 Lisp_Object buffer = Qnil;
2435 Lisp_Object window = Qnil;
2436 Lisp_Object frame = Qnil;
2437 Lisp_Object device = Qnil;
2438 Lisp_Object tag = Qnil;
2440 struct Lisp_Specifier *sp;
2442 sp = XSPECIFIER (specifier);
2444 /* Attempt to determine buffer, window, frame, and device from the
2446 if (WINDOWP (domain))
2448 else if (FRAMEP (domain))
2450 else if (DEVICEP (domain))
2453 /* #### dmoore - dammit, this should just signal an error or something
2455 #### No. Errors are handled in Lisp primitives implementation.
2456 Invalid domain is a design error here - kkm. */
2459 if (NILP (buffer) && !NILP (window))
2460 buffer = XWINDOW (window)->buffer;
2461 if (NILP (frame) && !NILP (window))
2462 frame = XWINDOW (window)->frame;
2464 /* frame had better exist; if device is undeterminable, something
2465 really went wrong. */
2466 device = XFRAME (frame)->device;
2468 /* device had better be determined by now; abort if not. */
2469 d = XDEVICE (device);
2470 tag = DEVICE_CLASS (d);
2472 depth = make_int (1 + XINT (depth));
2473 if (XINT (depth) > 20)
2475 maybe_error (Qspecifier, errb, "Apparent loop in specifier inheritance");
2476 /* The specification is fucked; at least try the fallback
2477 (which better not be fucked, because it's not changeable
2484 /* First see if we can generate one from the window specifiers. */
2486 CHECK_INSTANCE_ENTRY (window, matchspec, LOCALE_WINDOW);
2488 /* Next see if we can generate one from the buffer specifiers. */
2490 CHECK_INSTANCE_ENTRY (buffer, matchspec, LOCALE_BUFFER);
2492 /* Next see if we can generate one from the frame specifiers. */
2494 CHECK_INSTANCE_ENTRY (frame, matchspec, LOCALE_FRAME);
2496 /* If we still haven't succeeded try with the device specifiers. */
2497 CHECK_INSTANCE_ENTRY (device, matchspec, LOCALE_DEVICE);
2499 /* Last and least try the global specifiers. */
2500 CHECK_INSTANCE_ENTRY (Qglobal, matchspec, LOCALE_GLOBAL);
2503 /* We're out of specifiers and we still haven't generated an
2504 instance. At least try the fallback ... If this fails,
2505 then we just return Qunbound. */
2507 if (no_fallback || NILP (sp->fallback))
2508 /* I said, I don't want the fallbacks. */
2511 if (SPECIFIERP (sp->fallback))
2513 /* If you introduced loops in the default specifier chain,
2514 then you're fucked, so you better not do this. */
2515 specifier = sp->fallback;
2516 sp = XSPECIFIER (specifier);
2520 assert (CONSP (sp->fallback));
2521 return specifier_instance_from_inst_list (specifier, matchspec, domain,
2522 sp->fallback, errb, no_quit,
2525 #undef CHECK_INSTANCE_ENTRY
2528 specifier_instance_no_quit (Lisp_Object specifier, Lisp_Object matchspec,
2529 Lisp_Object domain, Error_behavior errb,
2530 int no_fallback, Lisp_Object depth)
2532 return specifier_instance (specifier, matchspec, domain, errb,
2533 1, no_fallback, depth);
2536 DEFUN ("specifier-instance", Fspecifier_instance, 1, 4, 0, /*
2537 Instantiate SPECIFIER (return its value) in DOMAIN.
2538 If no instance can be generated for this domain, return DEFAULT.
2540 DOMAIN should be a window, frame, or device. Other values that are legal
2541 as a locale (e.g. a buffer) are not valid as a domain because they do not
2542 provide enough information to identify a particular device (see
2543 `valid-specifier-domain-p'). DOMAIN defaults to the selected window
2546 "Instantiating" a specifier in a particular domain means determining
2547 the specifier's "value" in that domain. This is accomplished by
2548 searching through the specifications in the specifier that correspond
2549 to all locales that can be derived from the given domain, from specific
2550 to general. In most cases, the domain is an Emacs window. In that case
2551 specifications are searched for as follows:
2553 1. A specification whose locale is the window itself;
2554 2. A specification whose locale is the window's buffer;
2555 3. A specification whose locale is the window's frame;
2556 4. A specification whose locale is the window's frame's device;
2557 5. A specification whose locale is 'global.
2559 If all of those fail, then the C-code-provided fallback value for
2560 this specifier is consulted (see `specifier-fallback'). If it is
2561 an inst-list, then this function attempts to instantiate that list
2562 just as when a specification is located in the first five steps above.
2563 If the fallback is a specifier, `specifier-instance' is called
2564 recursively on this specifier and the return value used. Note,
2565 however, that if the optional argument NO-FALLBACK is non-nil,
2566 the fallback value will not be consulted.
2568 Note that there may be more than one specification matching a particular
2569 locale; all such specifications are considered before looking for any
2570 specifications for more general locales. Any particular specification
2571 that is found may be rejected because its tag set does not match the
2572 device being instantiated over, or because the specification is not
2573 valid for the device of the given domain (e.g. the font or color name
2574 does not exist for this particular X server).
2576 The returned value is dependent on the type of specifier. For example,
2577 for a font specifier (as returned by the `face-font' function), the returned
2578 value will be a font-instance object. For glyphs, the returned value
2579 will be a string, pixmap, or subwindow.
2581 See also `specifier-matching-instance'.
2583 (specifier, domain, default_, no_fallback))
2585 Lisp_Object instance;
2587 CHECK_SPECIFIER (specifier);
2588 domain = decode_domain (domain);
2590 instance = specifier_instance (specifier, Qunbound, domain, ERROR_ME, 0,
2591 !NILP (no_fallback), Qzero);
2592 return UNBOUNDP (instance) ? default_ : instance;
2595 DEFUN ("specifier-matching-instance", Fspecifier_matching_instance, 2, 5, 0, /*
2596 Return an instance for SPECIFIER in DOMAIN that matches MATCHSPEC.
2597 If no instance can be generated for this domain, return DEFAULT.
2599 This function is identical to `specifier-instance' except that a
2600 specification will only be considered if it matches MATCHSPEC.
2601 The definition of "match", and allowed values for MATCHSPEC, are
2602 dependent on the particular type of specifier. Here are some examples:
2604 -- For chartable (e.g. display table) specifiers, MATCHSPEC should be a
2605 character, and the specification (a chartable) must give a value for
2606 that character in order to be considered. This allows you to specify,
2607 e.g., a buffer-local display table that only gives values for particular
2608 characters. All other characters are handled as if the buffer-local
2609 display table is not there. (Chartable specifiers are not yet
2612 -- For font specifiers, MATCHSPEC should be a charset, and the specification
2613 (a font string) must have a registry that matches the charset's registry.
2614 (This only makes sense with Mule support.) This makes it easy to choose a
2615 font that can display a particular character. (This is what redisplay
2618 (specifier, matchspec, domain, default_, no_fallback))
2620 Lisp_Object instance;
2622 CHECK_SPECIFIER (specifier);
2623 check_valid_specifier_matchspec (matchspec, XSPECIFIER (specifier)->methods,
2625 domain = decode_domain (domain);
2627 instance = specifier_instance (specifier, matchspec, domain, ERROR_ME,
2628 0, !NILP (no_fallback), Qzero);
2629 return UNBOUNDP (instance) ? default_ : instance;
2632 DEFUN ("specifier-instance-from-inst-list", Fspecifier_instance_from_inst_list,
2634 Attempt to convert a particular inst-list into an instance.
2635 This attempts to instantiate INST-LIST in the given DOMAIN,
2636 as if INST-LIST existed in a specification in SPECIFIER. If
2637 the instantiation fails, DEFAULT is returned. In most circumstances,
2638 you should not use this function; use `specifier-instance' instead.
2640 (specifier, domain, inst_list, default_))
2642 Lisp_Object val = Qunbound;
2643 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2644 struct gcpro gcpro1;
2645 Lisp_Object built_up_list = Qnil;
2647 CHECK_SPECIFIER (specifier);
2648 check_valid_domain (domain);
2649 check_valid_inst_list (inst_list, sp->methods, ERROR_ME);
2650 GCPRO1 (built_up_list);
2651 built_up_list = build_up_processed_list (specifier, domain, inst_list);
2652 if (!NILP (built_up_list))
2653 val = specifier_instance_from_inst_list (specifier, Qunbound, domain,
2654 built_up_list, ERROR_ME,
2657 return UNBOUNDP (val) ? default_ : val;
2660 DEFUN ("specifier-matching-instance-from-inst-list", Fspecifier_matching_instance_from_inst_list,
2662 Attempt to convert a particular inst-list into an instance.
2663 This attempts to instantiate INST-LIST in the given DOMAIN
2664 \(as if INST-LIST existed in a specification in SPECIFIER),
2665 matching the specifications against MATCHSPEC.
2667 This function is analogous to `specifier-instance-from-inst-list'
2668 but allows for specification-matching as in `specifier-matching-instance'.
2669 See that function for a description of exactly how the matching process
2672 (specifier, matchspec, domain, inst_list, default_))
2674 Lisp_Object val = Qunbound;
2675 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2676 struct gcpro gcpro1;
2677 Lisp_Object built_up_list = Qnil;
2679 CHECK_SPECIFIER (specifier);
2680 check_valid_specifier_matchspec (matchspec, XSPECIFIER (specifier)->methods,
2682 check_valid_domain (domain);
2683 check_valid_inst_list (inst_list, sp->methods, ERROR_ME);
2684 GCPRO1 (built_up_list);
2685 built_up_list = build_up_processed_list (specifier, domain, inst_list);
2686 if (!NILP (built_up_list))
2687 val = specifier_instance_from_inst_list (specifier, matchspec, domain,
2688 built_up_list, ERROR_ME,
2691 return UNBOUNDP (val) ? default_ : val;
2695 /************************************************************************/
2696 /* Caching in the struct window or frame */
2697 /************************************************************************/
2699 /* Either STRUCT_WINDOW_OFFSET or STRUCT_FRAME_OFFSET can be 0 to indicate
2700 no caching in that sort of object. */
2702 /* #### It would be nice if the specifier caching automatically knew
2703 about specifier fallbacks, so we didn't have to do it ourselves. */
2706 set_specifier_caching (Lisp_Object specifier, int struct_window_offset,
2707 void (*value_changed_in_window)
2708 (Lisp_Object specifier, struct window *w,
2709 Lisp_Object oldval),
2710 int struct_frame_offset,
2711 void (*value_changed_in_frame)
2712 (Lisp_Object specifier, struct frame *f,
2713 Lisp_Object oldval))
2715 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2716 assert (!GHOST_SPECIFIER_P (sp));
2719 sp->caching = xnew_and_zero (struct specifier_caching);
2720 sp->caching->offset_into_struct_window = struct_window_offset;
2721 sp->caching->value_changed_in_window = value_changed_in_window;
2722 sp->caching->offset_into_struct_frame = struct_frame_offset;
2723 sp->caching->value_changed_in_frame = value_changed_in_frame;
2724 Vcached_specifiers = Fcons (specifier, Vcached_specifiers);
2725 if (BODILY_SPECIFIER_P (sp))
2726 GHOST_SPECIFIER(sp)->caching = sp->caching;
2727 recompute_cached_specifier_everywhere (specifier);
2731 recompute_one_cached_specifier_in_window (Lisp_Object specifier,
2735 Lisp_Object newval, *location;
2737 assert (!GHOST_SPECIFIER_P (XSPECIFIER (specifier)));
2739 XSETWINDOW (window, w);
2741 newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN,
2743 /* If newval ended up Qunbound, then the calling functions
2744 better be able to deal. If not, set a default so this
2745 never happens or correct it in the value_changed_in_window
2747 location = (Lisp_Object *)
2748 ((char *) w + XSPECIFIER (specifier)->caching->offset_into_struct_window);
2749 if (!EQ (newval, *location))
2751 Lisp_Object oldval = *location;
2753 (XSPECIFIER (specifier)->caching->value_changed_in_window)
2754 (specifier, w, oldval);
2759 recompute_one_cached_specifier_in_frame (Lisp_Object specifier,
2763 Lisp_Object newval, *location;
2765 assert (!GHOST_SPECIFIER_P (XSPECIFIER (specifier)));
2767 XSETFRAME (frame, f);
2769 newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN,
2771 /* If newval ended up Qunbound, then the calling functions
2772 better be able to deal. If not, set a default so this
2773 never happens or correct it in the value_changed_in_frame
2775 location = (Lisp_Object *)
2776 ((char *) f + XSPECIFIER (specifier)->caching->offset_into_struct_frame);
2777 if (!EQ (newval, *location))
2779 Lisp_Object oldval = *location;
2781 (XSPECIFIER (specifier)->caching->value_changed_in_frame)
2782 (specifier, f, oldval);
2787 recompute_all_cached_specifiers_in_window (struct window *w)
2791 LIST_LOOP (rest, Vcached_specifiers)
2793 Lisp_Object specifier = XCAR (rest);
2794 if (XSPECIFIER (specifier)->caching->offset_into_struct_window)
2795 recompute_one_cached_specifier_in_window (specifier, w);
2800 recompute_all_cached_specifiers_in_frame (struct frame *f)
2804 LIST_LOOP (rest, Vcached_specifiers)
2806 Lisp_Object specifier = XCAR (rest);
2807 if (XSPECIFIER (specifier)->caching->offset_into_struct_frame)
2808 recompute_one_cached_specifier_in_frame (specifier, f);
2813 recompute_cached_specifier_everywhere_mapfun (struct window *w,
2816 Lisp_Object specifier = Qnil;
2818 VOID_TO_LISP (specifier, closure);
2819 recompute_one_cached_specifier_in_window (specifier, w);
2824 recompute_cached_specifier_everywhere (Lisp_Object specifier)
2826 Lisp_Object frmcons, devcons, concons;
2828 specifier = bodily_specifier (specifier);
2830 if (!XSPECIFIER (specifier)->caching)
2833 if (XSPECIFIER (specifier)->caching->offset_into_struct_window)
2835 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
2836 map_windows (XFRAME (XCAR (frmcons)),
2837 recompute_cached_specifier_everywhere_mapfun,
2838 LISP_TO_VOID (specifier));
2841 if (XSPECIFIER (specifier)->caching->offset_into_struct_frame)
2843 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
2844 recompute_one_cached_specifier_in_frame (specifier,
2845 XFRAME (XCAR (frmcons)));
2849 DEFUN ("set-specifier-dirty-flag", Fset_specifier_dirty_flag, 1, 1, 0, /*
2850 Force recomputation of any caches associated with SPECIFIER.
2851 Note that this automatically happens whenever you change a specification
2852 in SPECIFIER; you do not have to call this function then.
2853 One example of where this function is useful is when you have a
2854 toolbar button whose `active-p' field is an expression to be
2855 evaluated. Calling `set-specifier-dirty-flag' on the
2856 toolbar specifier will force the `active-p' fields to be
2861 CHECK_SPECIFIER (specifier);
2862 recompute_cached_specifier_everywhere (specifier);
2867 /************************************************************************/
2868 /* Generic specifier type */
2869 /************************************************************************/
2871 DEFINE_SPECIFIER_TYPE (generic);
2875 /* This is the string that used to be in `generic-specifier-p'.
2876 The idea is good, but it doesn't quite work in the form it's
2877 in. (One major problem is that validating an instantiator
2878 is supposed to require only that the specifier type is passed,
2879 while with this approach the actual specifier is needed.)
2881 What really needs to be done is to write a function
2882 `make-specifier-type' that creates new specifier types.
2883 #### I'll look into this for 19.14.
2886 "A generic specifier is a generalized kind of specifier with user-defined\n"
2887 "semantics. The instantiator can be any kind of Lisp object, and the\n"
2888 "instance computed from it is likewise any kind of Lisp object. The\n"
2889 "SPECIFIER-DATA should be an alist of methods governing how the specifier\n"
2890 "works. All methods are optional, and reasonable default methods will be\n"
2891 "provided. Currently there are two defined methods: 'instantiate and\n"
2894 "'instantiate specifies how to do the instantiation; if omitted, the\n"
2895 "instantiator itself is simply returned as the instance. The method\n"
2896 "should be a function that accepts three parameters (a specifier, the\n"
2897 "instantiator that matched the domain being instantiated over, and that\n"
2898 "domain), and should return a one-element list containing the instance,\n"
2899 "or nil if no instance exists. Note that the domain passed to this function\n"
2900 "is the domain being instantiated over, which may not be the same as the\n"
2901 "locale contained in the specification corresponding to the instantiator\n"
2902 "(for example, the domain being instantiated over could be a window, but\n"
2903 "the locale corresponding to the passed instantiator could be the window's\n"
2904 "buffer or frame).\n"
2906 "'validate specifies whether a given instantiator is valid; if omitted,\n"
2907 "all instantiators are considered valid. It should be a function of\n"
2908 "two arguments: an instantiator and a flag CAN-SIGNAL-ERROR. If this\n"
2909 "flag is false, the function must simply return t or nil indicating\n"
2910 "whether the instantiator is valid. If this flag is true, the function\n"
2911 "is free to signal an error if it encounters an invalid instantiator\n"
2912 "(this can be useful for issuing a specific error about exactly why the\n"
2913 "instantiator is valid). It can also return nil to indicate an invalid\n"
2914 "instantiator; in this case, a general error will be signalled."
2918 DEFUN ("generic-specifier-p", Fgeneric_specifier_p, 1, 1, 0, /*
2919 Return non-nil if OBJECT is a generic specifier.
2921 A generic specifier allows any kind of Lisp object as an instantiator,
2922 and returns back the Lisp object unchanged when it is instantiated.
2926 return GENERIC_SPECIFIERP (object) ? Qt : Qnil;
2930 /************************************************************************/
2931 /* Integer specifier type */
2932 /************************************************************************/
2934 DEFINE_SPECIFIER_TYPE (integer);
2937 integer_validate (Lisp_Object instantiator)
2939 CHECK_INT (instantiator);
2942 DEFUN ("integer-specifier-p", Finteger_specifier_p, 1, 1, 0, /*
2943 Return non-nil if OBJECT is an integer specifier.
2947 return INTEGER_SPECIFIERP (object) ? Qt : Qnil;
2950 /************************************************************************/
2951 /* Non-negative-integer specifier type */
2952 /************************************************************************/
2954 DEFINE_SPECIFIER_TYPE (natnum);
2957 natnum_validate (Lisp_Object instantiator)
2959 CHECK_NATNUM (instantiator);
2962 DEFUN ("natnum-specifier-p", Fnatnum_specifier_p, 1, 1, 0, /*
2963 Return non-nil if OBJECT is a natnum (non-negative-integer) specifier.
2967 return NATNUM_SPECIFIERP (object) ? Qt : Qnil;
2970 /************************************************************************/
2971 /* Boolean specifier type */
2972 /************************************************************************/
2974 DEFINE_SPECIFIER_TYPE (boolean);
2977 boolean_validate (Lisp_Object instantiator)
2979 if (!EQ (instantiator, Qt) && !EQ (instantiator, Qnil))
2980 signal_simple_error ("Must be t or nil", instantiator);
2983 DEFUN ("boolean-specifier-p", Fboolean_specifier_p, 1, 1, 0, /*
2984 Return non-nil if OBJECT is a boolean specifier.
2988 return BOOLEAN_SPECIFIERP (object) ? Qt : Qnil;
2991 /************************************************************************/
2992 /* Display table specifier type */
2993 /************************************************************************/
2995 DEFINE_SPECIFIER_TYPE (display_table);
2998 display_table_validate (Lisp_Object instantiator)
3000 if (!NILP(instantiator) &&
3001 (!VECTORP (instantiator) ||
3002 XVECTOR_LENGTH (instantiator) != DISP_TABLE_SIZE))
3003 dead_wrong_type_argument (display_table_specifier_methods->predicate_symbol,
3007 DEFUN ("display-table-specifier-p", Fdisplay_table_specifier_p, 1, 1, 0, /*
3008 Return non-nil if OBJECT is a display-table specifier.
3012 return DISPLAYTABLE_SPECIFIERP (object) ? Qt : Qnil;
3016 /************************************************************************/
3017 /* Initialization */
3018 /************************************************************************/
3021 syms_of_specifier (void)
3023 defsymbol (&Qspecifierp, "specifierp");
3025 defsymbol (&Qconsole_type, "console-type");
3026 defsymbol (&Qdevice_class, "device-class");
3028 /* Qinteger, Qboolean, Qgeneric defined in general.c */
3029 defsymbol (&Qnatnum, "natnum");
3031 DEFSUBR (Fvalid_specifier_type_p);
3032 DEFSUBR (Fspecifier_type_list);
3033 DEFSUBR (Fmake_specifier);
3034 DEFSUBR (Fspecifierp);
3035 DEFSUBR (Fspecifier_type);
3037 DEFSUBR (Fvalid_specifier_locale_p);
3038 DEFSUBR (Fvalid_specifier_domain_p);
3039 DEFSUBR (Fvalid_specifier_locale_type_p);
3040 DEFSUBR (Fspecifier_locale_type_from_locale);
3042 DEFSUBR (Fvalid_specifier_tag_p);
3043 DEFSUBR (Fvalid_specifier_tag_set_p);
3044 DEFSUBR (Fcanonicalize_tag_set);
3045 DEFSUBR (Fdevice_matches_specifier_tag_set_p);
3046 DEFSUBR (Fdefine_specifier_tag);
3047 DEFSUBR (Fdevice_matching_specifier_tag_list);
3048 DEFSUBR (Fspecifier_tag_list);
3049 DEFSUBR (Fspecifier_tag_predicate);
3051 DEFSUBR (Fcheck_valid_instantiator);
3052 DEFSUBR (Fvalid_instantiator_p);
3053 DEFSUBR (Fcheck_valid_inst_list);
3054 DEFSUBR (Fvalid_inst_list_p);
3055 DEFSUBR (Fcheck_valid_spec_list);
3056 DEFSUBR (Fvalid_spec_list_p);
3057 DEFSUBR (Fadd_spec_to_specifier);
3058 DEFSUBR (Fadd_spec_list_to_specifier);
3059 DEFSUBR (Fspecifier_spec_list);
3060 DEFSUBR (Fspecifier_specs);
3061 DEFSUBR (Fremove_specifier);
3062 DEFSUBR (Fcopy_specifier);
3064 DEFSUBR (Fcheck_valid_specifier_matchspec);
3065 DEFSUBR (Fvalid_specifier_matchspec_p);
3066 DEFSUBR (Fspecifier_fallback);
3067 DEFSUBR (Fspecifier_instance);
3068 DEFSUBR (Fspecifier_matching_instance);
3069 DEFSUBR (Fspecifier_instance_from_inst_list);
3070 DEFSUBR (Fspecifier_matching_instance_from_inst_list);
3071 DEFSUBR (Fset_specifier_dirty_flag);
3073 DEFSUBR (Fgeneric_specifier_p);
3074 DEFSUBR (Finteger_specifier_p);
3075 DEFSUBR (Fnatnum_specifier_p);
3076 DEFSUBR (Fboolean_specifier_p);
3077 DEFSUBR (Fdisplay_table_specifier_p);
3079 /* Symbols pertaining to specifier creation. Specifiers are created
3080 in the syms_of() functions. */
3082 /* locales are defined in general.c. */
3084 defsymbol (&Qprepend, "prepend");
3085 defsymbol (&Qappend, "append");
3086 defsymbol (&Qremove_tag_set_prepend, "remove-tag-set-prepend");
3087 defsymbol (&Qremove_tag_set_append, "remove-tag-set-append");
3088 defsymbol (&Qremove_locale, "remove-locale");
3089 defsymbol (&Qremove_locale_type, "remove-locale-type");
3090 defsymbol (&Qremove_all, "remove-all");
3092 defsymbol (&Qfallback, "fallback");
3096 specifier_type_create (void)
3098 the_specifier_type_entry_dynarr = Dynarr_new (specifier_type_entry);
3100 Vspecifier_type_list = Qnil;
3101 staticpro (&Vspecifier_type_list);
3103 INITIALIZE_SPECIFIER_TYPE (generic, "generic", "generic-specifier-p");
3105 INITIALIZE_SPECIFIER_TYPE (integer, "integer", "integer-specifier-p");
3107 SPECIFIER_HAS_METHOD (integer, validate);
3109 INITIALIZE_SPECIFIER_TYPE (natnum, "natnum", "natnum-specifier-p");
3111 SPECIFIER_HAS_METHOD (natnum, validate);
3113 INITIALIZE_SPECIFIER_TYPE (boolean, "boolean", "boolean-specifier-p");
3115 SPECIFIER_HAS_METHOD (boolean, validate);
3117 INITIALIZE_SPECIFIER_TYPE (display_table, "display-table", "display-table-p");
3119 SPECIFIER_HAS_METHOD (display_table, validate);
3123 vars_of_specifier (void)
3125 Vcached_specifiers = Qnil;
3126 staticpro (&Vcached_specifiers);
3128 /* Do NOT mark through this, or specifiers will never be GC'd.
3129 This is the same deal as for weak hashtables. */
3130 Vall_specifiers = Qnil;
3132 Vuser_defined_tags = Qnil;
3133 staticpro (&Vuser_defined_tags);
3135 Vunlock_ghost_specifiers = Qnil;
3136 staticpro (&Vunlock_ghost_specifiers);