Mercurial > hg > xemacs-beta
comparison src/specifier.c @ 272:c5d627a313b1 r21-0b34
Import from CVS: tag r21-0b34
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:28:48 +0200 |
parents | 3d6bfa290dbd |
children | 6330739388db |
comparison
equal
deleted
inserted
replaced
271:c7b7086b0a39 | 272:c5d627a313b1 |
---|---|
47 | 47 |
48 Lisp_Object Qconsole_type, Qdevice_class; | 48 Lisp_Object Qconsole_type, Qdevice_class; |
49 | 49 |
50 Lisp_Object Vuser_defined_tags; | 50 Lisp_Object Vuser_defined_tags; |
51 | 51 |
52 MAC_DEFINE (struct Lisp_Specifier *, MTspecmeth_or_given) | |
53 MAC_DEFINE (struct Lisp_Specifier *, MTspecifier_data) | |
54 | |
55 typedef struct specifier_type_entry specifier_type_entry; | 52 typedef struct specifier_type_entry specifier_type_entry; |
56 struct specifier_type_entry | 53 struct specifier_type_entry |
57 { | 54 { |
58 Lisp_Object symbol; | 55 Lisp_Object symbol; |
59 struct specifier_methods *meths; | 56 struct specifier_methods *meths; |
78 | 75 |
79 #### Look into this for 19.14. */ | 76 #### Look into this for 19.14. */ |
80 Lisp_Object_dynarr current_specifiers; | 77 Lisp_Object_dynarr current_specifiers; |
81 | 78 |
82 static void recompute_cached_specifier_everywhere (Lisp_Object specifier); | 79 static void recompute_cached_specifier_everywhere (Lisp_Object specifier); |
80 | |
81 EXFUN (Fspecifier_specs, 4); | |
82 EXFUN (Fremove_specifier, 4); | |
83 | 83 |
84 | 84 |
85 /************************************************************************/ | 85 /************************************************************************/ |
86 /* Specifier object methods */ | 86 /* Specifier object methods */ |
87 /************************************************************************/ | 87 /************************************************************************/ |
88 | |
89 static Lisp_Object mark_specifier (Lisp_Object, void (*) (Lisp_Object)); | |
90 static void print_specifier (Lisp_Object, Lisp_Object, int); | |
91 static int specifier_equal (Lisp_Object, Lisp_Object, int depth); | |
92 static unsigned long specifier_hash (Lisp_Object obj, int depth); | |
93 static unsigned int sizeof_specifier (CONST void *header); | |
94 static void finalize_specifier (void *header, int for_disksave); | |
95 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier, | |
96 mark_specifier, print_specifier, | |
97 finalize_specifier, | |
98 specifier_equal, specifier_hash, | |
99 sizeof_specifier, | |
100 struct Lisp_Specifier); | |
101 | 88 |
102 /* Remove dead objects from the specified assoc list. */ | 89 /* Remove dead objects from the specified assoc list. */ |
103 | 90 |
104 static Lisp_Object | 91 static Lisp_Object |
105 cleanup_assoc_list (Lisp_Object list) | 92 cleanup_assoc_list (Lisp_Object list) |
297 /* This function can be called from within redisplay. | 284 /* This function can be called from within redisplay. |
298 internal_equal can trigger a quit. That leads to Bad Things. */ | 285 internal_equal can trigger a quit. That leads to Bad Things. */ |
299 Vinhibit_quit = Qt; | 286 Vinhibit_quit = Qt; |
300 | 287 |
301 depth++; | 288 depth++; |
302 if (s1->methods != s2->methods || | 289 retval = |
303 !internal_equal (s1->global_specs, s2->global_specs, depth) || | 290 (s1->methods == s2->methods && |
304 !internal_equal (s1->device_specs, s2->device_specs, depth) || | 291 internal_equal (s1->global_specs, s2->global_specs, depth) && |
305 !internal_equal (s1->frame_specs, s2->frame_specs, depth) || | 292 internal_equal (s1->device_specs, s2->device_specs, depth) && |
306 !internal_equal (s1->window_specs, s2->window_specs, depth) || | 293 internal_equal (s1->frame_specs, s2->frame_specs, depth) && |
307 !internal_equal (s1->buffer_specs, s2->buffer_specs, depth) || | 294 internal_equal (s1->window_specs, s2->window_specs, depth) && |
308 !SPECMETH_OR_GIVEN (s1, equal, (o1, o2, depth - 1), 1)) | 295 internal_equal (s1->buffer_specs, s2->buffer_specs, depth)); |
309 retval = 0; | 296 |
310 else | 297 if (retval && HAS_SPECMETH_P (s1, equal)) |
311 retval = 1; | 298 retval = SPECMETH (s1, equal, (o1, o2, depth - 1)); |
312 | 299 |
313 Vinhibit_quit = old_inhibit_quit; | 300 Vinhibit_quit = old_inhibit_quit; |
314 return retval; | 301 return retval; |
315 } | 302 } |
316 | 303 |
320 struct Lisp_Specifier *s = XSPECIFIER (obj); | 307 struct Lisp_Specifier *s = XSPECIFIER (obj); |
321 | 308 |
322 /* specifier hashing is a bit problematic because there are so | 309 /* specifier hashing is a bit problematic because there are so |
323 many places where data can be stored. We pick what are perhaps | 310 many places where data can be stored. We pick what are perhaps |
324 the most likely places where interesting stuff will be. */ | 311 the most likely places where interesting stuff will be. */ |
325 return HASH5 (SPECMETH_OR_GIVEN (s, hash, (obj, depth), 0), | 312 return HASH5 ((HAS_SPECMETH_P (s, hash) ? |
313 SPECMETH (s, hash, (obj, depth)) : 0), | |
326 (unsigned long) s->methods, | 314 (unsigned long) s->methods, |
327 internal_hash (s->global_specs, depth + 1), | 315 internal_hash (s->global_specs, depth + 1), |
328 internal_hash (s->frame_specs, depth + 1), | 316 internal_hash (s->frame_specs, depth + 1), |
329 internal_hash (s->buffer_specs, depth + 1)); | 317 internal_hash (s->buffer_specs, depth + 1)); |
330 } | 318 } |
331 | 319 |
332 static unsigned int | 320 static size_t |
333 sizeof_specifier (CONST void *header) | 321 sizeof_specifier (CONST void *header) |
334 { | 322 { |
335 CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header; | 323 CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header; |
336 return sizeof (*p) + p->methods->extra_data_size - 1; | 324 return sizeof (*p) + p->methods->extra_data_size - 1; |
337 } | 325 } |
338 | 326 |
327 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier, | |
328 mark_specifier, print_specifier, | |
329 finalize_specifier, | |
330 specifier_equal, specifier_hash, | |
331 sizeof_specifier, | |
332 struct Lisp_Specifier); | |
339 | 333 |
340 /************************************************************************/ | 334 /************************************************************************/ |
341 /* Creating specifiers */ | 335 /* Creating specifiers */ |
342 /************************************************************************/ | 336 /************************************************************************/ |
343 | 337 |
359 } | 353 } |
360 | 354 |
361 static int | 355 static int |
362 valid_specifier_type_p (Lisp_Object type) | 356 valid_specifier_type_p (Lisp_Object type) |
363 { | 357 { |
364 if (decode_specifier_type (type, ERROR_ME_NOT)) | 358 return decode_specifier_type (type, ERROR_ME_NOT) != 0; |
365 return 1; | |
366 return 0; | |
367 } | 359 } |
368 | 360 |
369 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /* | 361 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /* |
370 Given a SPECIFIER-TYPE, return non-nil if it is valid. | 362 Given a SPECIFIER-TYPE, return non-nil if it is valid. |
371 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image, | 363 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image, |
372 'face-boolean, and 'toolbar. | 364 'face-boolean, and 'toolbar. |
373 */ | 365 */ |
374 (specifier_type)) | 366 (specifier_type)) |
375 { | 367 { |
376 if (valid_specifier_type_p (specifier_type)) | 368 return valid_specifier_type_p (specifier_type) ? Qt : Qnil; |
377 return Qt; | |
378 else | |
379 return Qnil; | |
380 } | 369 } |
381 | 370 |
382 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /* | 371 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /* |
383 Return a list of valid specifier types. | 372 Return a list of valid specifier types. |
384 */ | 373 */ |
400 } | 389 } |
401 | 390 |
402 static Lisp_Object | 391 static Lisp_Object |
403 make_specifier (struct specifier_methods *spec_meths) | 392 make_specifier (struct specifier_methods *spec_meths) |
404 { | 393 { |
405 Lisp_Object specifier = Qnil; | 394 Lisp_Object specifier; |
406 struct gcpro gcpro1; | 395 struct gcpro gcpro1; |
407 struct Lisp_Specifier *sp = (struct Lisp_Specifier *) | 396 struct Lisp_Specifier *sp = (struct Lisp_Specifier *) |
408 alloc_lcrecord (sizeof (struct Lisp_Specifier) + | 397 alloc_lcrecord (sizeof (struct Lisp_Specifier) + |
409 spec_meths->extra_data_size - 1, lrecord_specifier); | 398 spec_meths->extra_data_size - 1, lrecord_specifier); |
410 | 399 |
426 UNGCPRO; | 415 UNGCPRO; |
427 return specifier; | 416 return specifier; |
428 } | 417 } |
429 | 418 |
430 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /* | 419 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /* |
431 Create a new specifier. | 420 Return a new specifier object of type TYPE. |
432 | 421 |
433 A specifier is an object that can be used to keep track of a property | 422 A specifier is an object that can be used to keep track of a property |
434 whose value can be per-buffer, per-window, per-frame, or per-device, | 423 whose value can be per-buffer, per-window, per-frame, or per-device, |
435 and can further be restricted to a particular console-type or device-class. | 424 and can further be restricted to a particular console-type or device-class. |
436 Specifiers are used, for example, for the various built-in properties of a | 425 Specifiers are used, for example, for the various built-in properties of a |
458 | 447 |
459 return make_specifier (meths); | 448 return make_specifier (meths); |
460 } | 449 } |
461 | 450 |
462 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /* | 451 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /* |
463 Return non-nil if OBJECT is a specifier. | 452 Return t if OBJECT is a specifier. |
464 | 453 |
465 A specifier is an object that can be used to keep track of a property | 454 A specifier is an object that can be used to keep track of a property |
466 whose value can be per-buffer, per-window, per-frame, or per-device, | 455 whose value can be per-buffer, per-window, per-frame, or per-device, |
467 and can further be restricted to a particular console-type or device-class. | 456 and can further be restricted to a particular console-type or device-class. |
468 See `make-specifier'. | 457 See `make-specifier'. |
469 */ | 458 */ |
470 (object)) | 459 (object)) |
471 { | 460 { |
472 if (!SPECIFIERP (object)) | 461 return SPECIFIERP (object) ? Qt : Qnil; |
473 return Qnil; | |
474 return Qt; | |
475 } | 462 } |
476 | 463 |
477 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /* | 464 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /* |
478 Return the type of SPECIFIER. | 465 Return the type of SPECIFIER. |
479 */ | 466 */ |
487 /************************************************************************/ | 474 /************************************************************************/ |
488 /* Locales and domains */ | 475 /* Locales and domains */ |
489 /************************************************************************/ | 476 /************************************************************************/ |
490 | 477 |
491 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /* | 478 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /* |
492 Return non-nil if LOCALE is a valid specifier locale. | 479 Return t if LOCALE is a valid specifier locale. |
493 Valid locales are a device, a frame, a window, a buffer, and 'global. | 480 Valid locales are devices, frames, windows, buffers, and 'global. |
494 (nil is not valid.) | 481 \(nil is not valid.) |
495 */ | 482 */ |
496 (locale)) | 483 (locale)) |
497 { | 484 { |
498 /* This cannot GC. */ | 485 /* This cannot GC. */ |
499 if ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) || | 486 return ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) || |
500 (FRAMEP (locale) && FRAME_LIVE_P (XFRAME (locale))) || | 487 (FRAMEP (locale) && FRAME_LIVE_P (XFRAME (locale))) || |
501 (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) || | 488 (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) || |
502 /* dead windows are allowed because they may become live | 489 /* dead windows are allowed because they may become live |
503 windows again when a window configuration is restored */ | 490 windows again when a window configuration is restored */ |
504 WINDOWP (locale) || | 491 WINDOWP (locale) || |
505 EQ (locale, Qglobal)) | 492 EQ (locale, Qglobal)) |
506 return Qt; | 493 ? Qt : Qnil; |
507 else | |
508 return Qnil; | |
509 } | 494 } |
510 | 495 |
511 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /* | 496 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /* |
512 Return non-nil if DOMAIN is a valid specifier domain. | 497 Return t if DOMAIN is a valid specifier domain. |
513 A domain is used to instance a specifier (i.e. determine the specifier's | 498 A domain is used to instance a specifier (i.e. determine the specifier's |
514 value in that domain). Valid domains are a window, frame, or device. | 499 value in that domain). Valid domains are windows, frames, and devices. |
515 (nil is not valid.) | 500 \(nil is not valid.) |
516 */ | 501 */ |
517 (domain)) | 502 (domain)) |
518 { | 503 { |
519 /* This cannot GC. */ | 504 /* This cannot GC. */ |
520 if ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) || | 505 return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) || |
521 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) || | 506 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) || |
522 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain)))) | 507 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain)))) |
523 return Qt; | 508 ? Qt : Qnil; |
524 else | |
525 return Qnil; | |
526 } | 509 } |
527 | 510 |
528 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /* | 511 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /* |
529 Given a specifier LOCALE-TYPE, return non-nil if it is valid. | 512 Given a specifier LOCALE-TYPE, return non-nil if it is valid. |
530 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer. | 513 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer. |
531 (Note, however, that in functions that accept either a locale or a locale | 514 \(Note, however, that in functions that accept either a locale or a locale |
532 type, 'global is considered an individual locale.) | 515 type, 'global is considered an individual locale.) |
533 */ | 516 */ |
534 (locale_type)) | 517 (locale_type)) |
535 { | 518 { |
536 /* This cannot GC. */ | 519 /* This cannot GC. */ |
537 if (EQ (locale_type, Qglobal) || | 520 return (EQ (locale_type, Qglobal) || |
538 EQ (locale_type, Qdevice) || | 521 EQ (locale_type, Qdevice) || |
539 EQ (locale_type, Qframe) || | 522 EQ (locale_type, Qframe) || |
540 EQ (locale_type, Qwindow) || | 523 EQ (locale_type, Qwindow) || |
541 EQ (locale_type, Qbuffer)) | 524 EQ (locale_type, Qbuffer)) ? Qt : Qnil; |
542 return Qt; | |
543 else | |
544 return Qnil; | |
545 } | 525 } |
546 | 526 |
547 static void | 527 static void |
548 check_valid_locale_or_locale_type (Lisp_Object locale) | 528 check_valid_locale_or_locale_type (Lisp_Object locale) |
549 { | 529 { |
553 !NILP (Fvalid_specifier_locale_type_p (locale))) | 533 !NILP (Fvalid_specifier_locale_type_p (locale))) |
554 return; | 534 return; |
555 signal_simple_error ("Invalid specifier locale or locale type", locale); | 535 signal_simple_error ("Invalid specifier locale or locale type", locale); |
556 } | 536 } |
557 | 537 |
558 DEFUN ("specifier-locale-type-from-locale", Fspecifier_locale_type_from_locale, 1, 1, 0, /* | 538 DEFUN ("specifier-locale-type-from-locale", |
539 Fspecifier_locale_type_from_locale, 1, 1, 0, /* | |
559 Given a specifier LOCALE, return its type. | 540 Given a specifier LOCALE, return its type. |
560 */ | 541 */ |
561 (locale)) | 542 (locale)) |
562 { | 543 { |
563 /* This cannot GC. */ | 544 /* This cannot GC. */ |
564 if (NILP (Fvalid_specifier_locale_p (locale))) | 545 if (NILP (Fvalid_specifier_locale_p (locale))) |
565 signal_simple_error ("Invalid specifier locale", locale); | 546 signal_simple_error ("Invalid specifier locale", locale); |
566 if (DEVICEP (locale)) | 547 if (DEVICEP (locale)) return Qdevice; |
567 return Qdevice; | 548 if (FRAMEP (locale)) return Qframe; |
568 if (FRAMEP (locale)) | 549 if (WINDOWP (locale)) return Qwindow; |
569 return Qframe; | 550 if (BUFFERP (locale)) return Qbuffer; |
570 if (WINDOWP (locale)) | |
571 return Qwindow; | |
572 if (BUFFERP (locale)) | |
573 return Qbuffer; | |
574 assert (EQ (locale, Qglobal)); | 551 assert (EQ (locale, Qglobal)); |
575 return Qglobal; | 552 return Qglobal; |
576 } | 553 } |
577 | 554 |
578 Lisp_Object | 555 static Lisp_Object |
579 decode_locale (Lisp_Object locale) | 556 decode_locale (Lisp_Object locale) |
580 { | 557 { |
581 /* This cannot GC. */ | 558 /* This cannot GC. */ |
582 if (NILP (locale)) | 559 if (NILP (locale)) |
583 return Qglobal; | 560 return Qglobal; |
632 { | 609 { |
633 if (NILP (Fvalid_specifier_domain_p (domain))) | 610 if (NILP (Fvalid_specifier_domain_p (domain))) |
634 signal_simple_error ("Invalid specifier domain", domain); | 611 signal_simple_error ("Invalid specifier domain", domain); |
635 } | 612 } |
636 | 613 |
637 Lisp_Object | 614 static Lisp_Object |
638 decode_domain (Lisp_Object domain) | 615 decode_domain (Lisp_Object domain) |
639 { | 616 { |
640 if (NILP (domain)) | 617 if (NILP (domain)) |
641 return Fselected_window (Qnil); | 618 return Fselected_window (Qnil); |
642 check_valid_domain (domain); | 619 check_valid_domain (domain); |
652 Return non-nil if TAG is a valid specifier tag. | 629 Return non-nil if TAG is a valid specifier tag. |
653 See also `valid-specifier-tag-set-p'. | 630 See also `valid-specifier-tag-set-p'. |
654 */ | 631 */ |
655 (tag)) | 632 (tag)) |
656 { | 633 { |
657 if (valid_console_type_p (tag) || | 634 return (valid_console_type_p (tag) || |
658 valid_device_class_p (tag) || | 635 valid_device_class_p (tag) || |
659 !NILP (assq_no_quit (tag, Vuser_defined_tags))) | 636 !NILP (assq_no_quit (tag, Vuser_defined_tags))) ? Qt : Qnil; |
660 return Qt; | |
661 return Qnil; | |
662 } | 637 } |
663 | 638 |
664 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /* | 639 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /* |
665 Return non-nil if TAG-SET is a valid specifier tag set. | 640 Return non-nil if TAG-SET is a valid specifier tag set. |
666 | 641 |
669 particular device class or device type and/or to mark instantiators | 644 particular device class or device type and/or to mark instantiators |
670 added by a particular package so that they can be later removed. | 645 added by a particular package so that they can be later removed. |
671 | 646 |
672 A specifier tag set consists of a list of zero of more specifier tags, | 647 A specifier tag set consists of a list of zero of more specifier tags, |
673 each of which is a symbol that is recognized by XEmacs as a tag. | 648 each of which is a symbol that is recognized by XEmacs as a tag. |
674 (The valid device types and device classes are always tags, as are | 649 \(The valid device types and device classes are always tags, as are |
675 any tags defined by `define-specifier-tag'.) It is called a "tag set" | 650 any tags defined by `define-specifier-tag'.) It is called a "tag set" |
676 (as opposed to a list) because the order of the tags or the number of | 651 \(as opposed to a list) because the order of the tags or the number of |
677 times a particular tag occurs does not matter. | 652 times a particular tag occurs does not matter. |
678 | 653 |
679 Each tag has a predicate associated with it, which specifies whether | 654 Each tag has a predicate associated with it, which specifies whether |
680 that tag applies to a particular device. The tags which are device types | 655 that tag applies to a particular device. The tags which are device types |
681 and classes match devices of that type or class. User-defined tags can | 656 and classes match devices of that type or class. User-defined tags can |
819 } | 794 } |
820 | 795 |
821 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /* | 796 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /* |
822 Define a new specifier tag. | 797 Define a new specifier tag. |
823 If PREDICATE is specified, it should be a function of one argument | 798 If PREDICATE is specified, it should be a function of one argument |
824 (a device) that specifies whether the tag matches that particular | 799 \(a device) that specifies whether the tag matches that particular |
825 device. If PREDICATE is omitted, the tag matches all devices. | 800 device. If PREDICATE is omitted, the tag matches all devices. |
826 | 801 |
827 You can redefine an existing user-defined specifier tag. However, | 802 You can redefine an existing user-defined specifier tag. However, |
828 you cannot redefine the built-in specifier tags (the device types | 803 you cannot redefine the built-in specifier tags (the device types |
829 and classes) or the symbols nil, t, 'all, or 'global. | 804 and classes) or the symbols nil, t, 'all, or 'global. |
891 | 866 |
892 void | 867 void |
893 setup_device_initial_specifier_tags (struct device *d) | 868 setup_device_initial_specifier_tags (struct device *d) |
894 { | 869 { |
895 Lisp_Object rest, rest2; | 870 Lisp_Object rest, rest2; |
896 Lisp_Object device = Qnil; | 871 Lisp_Object device; |
897 | 872 |
898 XSETDEVICE (device, d); | 873 XSETDEVICE (device, d); |
899 | 874 |
900 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags); | 875 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags); |
901 | 876 |
912 else | 887 else |
913 XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil; | 888 XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil; |
914 } | 889 } |
915 } | 890 } |
916 | 891 |
917 DEFUN ("device-matching-specifier-tag-list", Fdevice_matching_specifier_tag_list, 0, 1, 0, /* | 892 DEFUN ("device-matching-specifier-tag-list", |
893 Fdevice_matching_specifier_tag_list, 0, 1, 0, /* | |
918 Return a list of all specifier tags matching DEVICE. | 894 Return a list of all specifier tags matching DEVICE. |
919 DEVICE defaults to the selected device if omitted. | 895 DEVICE defaults to the selected device if omitted. |
920 */ | 896 */ |
921 (device)) | 897 (device)) |
922 { | 898 { |
932 list = Fcons (XCAR (XCAR (rest)), list); | 908 list = Fcons (XCAR (XCAR (rest)), list); |
933 } | 909 } |
934 | 910 |
935 list = Fnreverse (list); | 911 list = Fnreverse (list); |
936 list = Fcons (DEVICE_CLASS (d), list); | 912 list = Fcons (DEVICE_CLASS (d), list); |
937 list = Fcons (DEVICE_TYPE (d), list); | 913 list = Fcons (DEVICE_TYPE (d), list); |
938 | 914 |
939 RETURN_UNGCPRO (list); | 915 RETURN_UNGCPRO (list); |
940 } | 916 } |
941 | 917 |
942 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /* | 918 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /* |
1090 { | 1066 { |
1091 Lisp_Object rest; | 1067 Lisp_Object rest; |
1092 | 1068 |
1093 LIST_LOOP (rest, inst_list) | 1069 LIST_LOOP (rest, inst_list) |
1094 { | 1070 { |
1095 if (!CONSP (rest) || !CONSP (XCAR (rest))) | 1071 Lisp_Object inst_pair, tag_set; |
1072 | |
1073 if (!CONSP (rest)) | |
1096 { | 1074 { |
1097 maybe_signal_simple_error ("Invalid instantiator list", inst_list, | 1075 maybe_signal_simple_error ("Invalid instantiator list", inst_list, |
1098 Qspecifier, errb); | 1076 Qspecifier, errb); |
1099 return Qnil; | 1077 return Qnil; |
1100 } | 1078 } |
1101 if (NILP (Fvalid_specifier_tag_set_p (XCAR (XCAR (rest))))) | 1079 if (!CONSP (inst_pair = XCAR (rest))) |
1102 { | 1080 { |
1103 maybe_signal_simple_error ("Invalid specifier tag", | 1081 maybe_signal_simple_error ("Invalid instantiator pair", inst_pair, |
1104 XCAR (XCAR (rest)), Qspecifier, errb); | 1082 Qspecifier, errb); |
1105 return Qnil; | 1083 return Qnil; |
1106 } | 1084 } |
1107 | 1085 if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair)))) |
1108 if (NILP (check_valid_instantiator (XCDR (XCAR (rest)), meths, | 1086 { |
1109 errb))) | 1087 maybe_signal_simple_error ("Invalid specifier tag", tag_set, |
1088 Qspecifier, errb); | |
1089 return Qnil; | |
1090 } | |
1091 | |
1092 if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb))) | |
1110 return Qnil; | 1093 return Qnil; |
1111 } | 1094 } |
1112 | 1095 |
1113 return Qt; | 1096 return Qt; |
1114 } | 1097 } |
1139 { | 1122 { |
1140 Lisp_Object rest; | 1123 Lisp_Object rest; |
1141 | 1124 |
1142 LIST_LOOP (rest, spec_list) | 1125 LIST_LOOP (rest, spec_list) |
1143 { | 1126 { |
1144 if (!CONSP (rest) || !CONSP (XCAR (rest))) | 1127 Lisp_Object spec, locale; |
1128 if (!CONSP (rest) || !CONSP (spec = XCAR (rest))) | |
1145 { | 1129 { |
1146 maybe_signal_simple_error ("Invalid specification list", spec_list, | 1130 maybe_signal_simple_error ("Invalid specification list", spec_list, |
1147 Qspecifier, errb); | 1131 Qspecifier, errb); |
1148 return Qnil; | 1132 return Qnil; |
1149 } | 1133 } |
1150 if (NILP (Fvalid_specifier_locale_p (XCAR (XCAR (rest))))) | 1134 if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec)))) |
1151 { | 1135 { |
1152 maybe_signal_simple_error ("Invalid specifier locale", | 1136 maybe_signal_simple_error ("Invalid specifier locale", locale, |
1153 XCAR (XCAR (rest)), | |
1154 Qspecifier, errb); | 1137 Qspecifier, errb); |
1155 return Qnil; | 1138 return Qnil; |
1156 } | 1139 } |
1157 | 1140 |
1158 if (NILP (check_valid_inst_list (XCDR (XCAR (rest)), meths, errb))) | 1141 if (NILP (check_valid_inst_list (XCDR (spec), meths, errb))) |
1159 return Qnil; | 1142 return Qnil; |
1160 } | 1143 } |
1161 | 1144 |
1162 return Qt; | 1145 return Qt; |
1163 } | 1146 } |
1457 static enum spec_add_meth | 1440 static enum spec_add_meth |
1458 handle_multiple_add_insts (Lisp_Object *inst_list, | 1441 handle_multiple_add_insts (Lisp_Object *inst_list, |
1459 Lisp_Object new_list, | 1442 Lisp_Object new_list, |
1460 enum spec_add_meth add_meth) | 1443 enum spec_add_meth add_meth) |
1461 { | 1444 { |
1462 if (add_meth == SPEC_REMOVE_TAG_SET_PREPEND || | 1445 switch (add_meth) |
1463 add_meth == SPEC_REMOVE_TAG_SET_APPEND) | 1446 { |
1464 { | 1447 case SPEC_REMOVE_TAG_SET_APPEND: |
1465 Lisp_Object rest; | 1448 add_meth = SPEC_APPEND; |
1466 | 1449 goto remove_tag_set; |
1467 LIST_LOOP (rest, new_list) | 1450 case SPEC_REMOVE_TAG_SET_PREPEND: |
1468 { | 1451 add_meth = SPEC_PREPEND; |
1469 Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest))); | 1452 remove_tag_set: |
1470 struct gcpro gcpro1; | 1453 { |
1471 | 1454 Lisp_Object rest; |
1472 GCPRO1 (canontag); | 1455 |
1473 /* pull out all elements from the existing list with the | 1456 LIST_LOOP (rest, new_list) |
1474 same tag as any tags in NEW_LIST. */ | 1457 { |
1475 *inst_list = remassoc_no_quit (canontag, *inst_list); | 1458 Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest))); |
1476 UNGCPRO; | 1459 struct gcpro gcpro1; |
1477 } | 1460 |
1478 if (add_meth == SPEC_REMOVE_TAG_SET_PREPEND) | 1461 GCPRO1 (canontag); |
1479 return SPEC_PREPEND; | 1462 /* pull out all elements from the existing list with the |
1480 else | 1463 same tag as any tags in NEW_LIST. */ |
1481 return SPEC_APPEND; | 1464 *inst_list = remassoc_no_quit (canontag, *inst_list); |
1482 } | 1465 UNGCPRO; |
1483 else if (add_meth == SPEC_REMOVE_LOCALE) | 1466 } |
1484 { | 1467 } |
1468 return add_meth; | |
1469 case SPEC_REMOVE_LOCALE: | |
1485 *inst_list = Qnil; | 1470 *inst_list = Qnil; |
1486 return SPEC_PREPEND; | 1471 return SPEC_PREPEND; |
1487 } | 1472 case SPEC_APPEND: |
1488 if (add_meth == SPEC_APPEND) | 1473 return add_meth; |
1489 return add_meth; | 1474 default: |
1490 | 1475 return SPEC_PREPEND; |
1491 return SPEC_PREPEND; | 1476 } |
1492 } | 1477 } |
1493 | 1478 |
1494 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER, | 1479 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER, |
1495 copy, canonicalize, and call the going_to_add methods as necessary | 1480 copy, canonicalize, and call the going_to_add methods as necessary |
1496 to produce a new list that is the one that really will be added | 1481 to produce a new list that is the one that really will be added |
1500 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale, | 1485 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale, |
1501 Lisp_Object inst_list) | 1486 Lisp_Object inst_list) |
1502 { | 1487 { |
1503 /* The return value of this function must be GCPRO'd. */ | 1488 /* The return value of this function must be GCPRO'd. */ |
1504 Lisp_Object rest, list_to_build_up = Qnil; | 1489 Lisp_Object rest, list_to_build_up = Qnil; |
1490 struct Lisp_Specifier *sp = XSPECIFIER (specifier); | |
1505 struct gcpro gcpro1; | 1491 struct gcpro gcpro1; |
1506 | 1492 |
1507 GCPRO1 (list_to_build_up); | 1493 GCPRO1 (list_to_build_up); |
1508 LIST_LOOP (rest, inst_list) | 1494 LIST_LOOP (rest, inst_list) |
1509 { | 1495 { |
1512 Lisp_Object sub_inst_list = Qnil; | 1498 Lisp_Object sub_inst_list = Qnil; |
1513 struct gcpro ngcpro1, ngcpro2; | 1499 struct gcpro ngcpro1, ngcpro2; |
1514 | 1500 |
1515 NGCPRO2 (instantiator, sub_inst_list); | 1501 NGCPRO2 (instantiator, sub_inst_list); |
1516 /* call the will-add method; it may GC */ | 1502 /* call the will-add method; it may GC */ |
1517 sub_inst_list = SPECMETH_OR_GIVEN (XSPECIFIER (specifier), going_to_add, | 1503 sub_inst_list = HAS_SPECMETH_P (sp, going_to_add) ? |
1518 (specifier, locale, tag_set, | 1504 SPECMETH (sp, going_to_add, |
1519 instantiator), Qt); | 1505 (specifier, locale, tag_set, instantiator)) : |
1506 Qt; | |
1520 if (EQ (sub_inst_list, Qt)) | 1507 if (EQ (sub_inst_list, Qt)) |
1521 /* no change here. */ | 1508 /* no change here. */ |
1522 sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set), | 1509 sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set), |
1523 instantiator)); | 1510 instantiator)); |
1524 else | 1511 else |
1549 static void | 1536 static void |
1550 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale, | 1537 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale, |
1551 Lisp_Object inst_list, enum spec_add_meth add_meth) | 1538 Lisp_Object inst_list, enum spec_add_meth add_meth) |
1552 { | 1539 { |
1553 struct Lisp_Specifier *sp = XSPECIFIER (specifier); | 1540 struct Lisp_Specifier *sp = XSPECIFIER (specifier); |
1554 enum spec_locale_type type; | 1541 enum spec_locale_type type = locale_type_from_locale (locale); |
1555 Lisp_Object *orig_inst_list; | 1542 Lisp_Object *orig_inst_list, tem; |
1556 Lisp_Object list_to_build_up = Qnil; | 1543 Lisp_Object list_to_build_up = Qnil; |
1557 struct gcpro gcpro1; | 1544 struct gcpro gcpro1; |
1558 | |
1559 type = locale_type_from_locale (locale); | |
1560 | 1545 |
1561 GCPRO1 (list_to_build_up); | 1546 GCPRO1 (list_to_build_up); |
1562 list_to_build_up = build_up_processed_list (specifier, locale, inst_list); | 1547 list_to_build_up = build_up_processed_list (specifier, locale, inst_list); |
1563 /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL. These are the | 1548 /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL. These are the |
1564 add-meth types that affect locales other than this one. */ | 1549 add-meth types that affect locales other than this one. */ |
1566 specifier_remove_locale_type (specifier, type, Qnil, 0); | 1551 specifier_remove_locale_type (specifier, type, Qnil, 0); |
1567 else if (add_meth == SPEC_REMOVE_ALL) | 1552 else if (add_meth == SPEC_REMOVE_ALL) |
1568 { | 1553 { |
1569 specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0); | 1554 specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0); |
1570 specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0); | 1555 specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0); |
1571 specifier_remove_locale_type (specifier, LOCALE_FRAME, Qnil, 0); | 1556 specifier_remove_locale_type (specifier, LOCALE_FRAME, Qnil, 0); |
1572 specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0); | 1557 specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0); |
1573 specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0); | 1558 specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0); |
1574 } | 1559 } |
1575 | 1560 |
1576 orig_inst_list = specifier_get_inst_list (specifier, locale, type); | 1561 orig_inst_list = specifier_get_inst_list (specifier, locale, type); |
1578 orig_inst_list = specifier_new_spec (specifier, locale, type); | 1563 orig_inst_list = specifier_new_spec (specifier, locale, type); |
1579 add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up, | 1564 add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up, |
1580 add_meth); | 1565 add_meth); |
1581 | 1566 |
1582 if (add_meth == SPEC_PREPEND) | 1567 if (add_meth == SPEC_PREPEND) |
1583 { | 1568 tem = nconc2 (list_to_build_up, *orig_inst_list); |
1584 *orig_inst_list = nconc2 (list_to_build_up, *orig_inst_list); | |
1585 } | |
1586 else if (add_meth == SPEC_APPEND) | 1569 else if (add_meth == SPEC_APPEND) |
1587 { | 1570 tem = nconc2 (*orig_inst_list, list_to_build_up); |
1588 *orig_inst_list = nconc2 (*orig_inst_list, list_to_build_up); | |
1589 } | |
1590 else | 1571 else |
1591 abort (); | 1572 abort (); |
1573 | |
1574 *orig_inst_list = tem; | |
1592 | 1575 |
1593 UNGCPRO; | 1576 UNGCPRO; |
1594 | 1577 |
1595 /* call the after-change method */ | 1578 /* call the after-change method */ |
1596 MAYBE_SPECMETH (sp, after_change, (specifier, locale)); | 1579 MAYBE_SPECMETH (sp, after_change, (specifier, locale)); |
1823 add_meth = decode_how_to_add_specification (how_to_add); | 1806 add_meth = decode_how_to_add_specification (how_to_add); |
1824 | 1807 |
1825 LIST_LOOP (rest, spec_list) | 1808 LIST_LOOP (rest, spec_list) |
1826 { | 1809 { |
1827 /* Placating the GCC god. */ | 1810 /* Placating the GCC god. */ |
1828 Lisp_Object crock1 = specifier; | 1811 Lisp_Object specification = XCAR (rest); |
1829 Lisp_Object crock2 = XCAR (XCAR (rest)); | 1812 Lisp_Object locale = XCAR (specification); |
1830 Lisp_Object crock3 = XCDR (XCAR (rest)); | 1813 Lisp_Object inst_list = XCDR (specification); |
1831 | 1814 |
1832 specifier_add_spec (crock1, crock2, crock3, add_meth); | 1815 specifier_add_spec (specifier, locale, inst_list, add_meth); |
1833 } | 1816 } |
1834 recompute_cached_specifier_everywhere (specifier); | 1817 recompute_cached_specifier_everywhere (specifier); |
1835 return Qnil; | 1818 return Qnil; |
1836 } | 1819 } |
1837 | 1820 |
1907 result is as if `specifier-spec-list' were called on each element of the | 1890 result is as if `specifier-spec-list' were called on each element of the |
1908 list and the results concatenated together. | 1891 list and the results concatenated together. |
1909 | 1892 |
1910 Only instantiators where TAG-SET (a list of zero or more tags) is a | 1893 Only instantiators where TAG-SET (a list of zero or more tags) is a |
1911 subset of (or possibly equal to) the instantiator's tag set are returned. | 1894 subset of (or possibly equal to) the instantiator's tag set are returned. |
1912 (The default value of nil is a subset of all tag sets, so in this case | 1895 \(The default value of nil is a subset of all tag sets, so in this case |
1913 no instantiators will be screened out.) If EXACT-P is non-nil, however, | 1896 no instantiators will be screened out.) If EXACT-P is non-nil, however, |
1914 TAG-SET must be equal to an instantiator's tag set for the instantiator | 1897 TAG-SET must be equal to an instantiator's tag set for the instantiator |
1915 to be returned. | 1898 to be returned. |
1916 */ | 1899 */ |
1917 (specifier, locale, tag_set, exact_p)) | 1900 (specifier, locale, tag_set, exact_p)) |
2272 | 2255 |
2273 if (HAS_SPECMETH_P (sp, instantiate)) | 2256 if (HAS_SPECMETH_P (sp, instantiate)) |
2274 val = call_with_suspended_errors | 2257 val = call_with_suspended_errors |
2275 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate), | 2258 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate), |
2276 Qunbound, Qspecifier, errb, 5, specifier, | 2259 Qunbound, Qspecifier, errb, 5, specifier, |
2277 matchspec, domain, XCDR (tagged_inst), depth); | 2260 matchspec, domain, val, depth); |
2278 | 2261 |
2279 if (!UNBOUNDP (val)) | 2262 if (!UNBOUNDP (val)) |
2280 { | 2263 { |
2281 unbind_to (count, Qnil); | 2264 unbind_to (count, Qnil); |
2282 UNGCPRO; | 2265 UNGCPRO; |
2547 | 2530 |
2548 DEFUN ("specifier-matching-instance-from-inst-list", | 2531 DEFUN ("specifier-matching-instance-from-inst-list", |
2549 Fspecifier_matching_instance_from_inst_list, 4, 5, 0, /* | 2532 Fspecifier_matching_instance_from_inst_list, 4, 5, 0, /* |
2550 Attempt to convert a particular inst-list into an instance. | 2533 Attempt to convert a particular inst-list into an instance. |
2551 This attempts to instantiate INST-LIST in the given DOMAIN | 2534 This attempts to instantiate INST-LIST in the given DOMAIN |
2552 (as if INST-LIST existed in a specification in SPECIFIER), | 2535 \(as if INST-LIST existed in a specification in SPECIFIER), |
2553 matching the specifications against MATCHSPEC. | 2536 matching the specifications against MATCHSPEC. |
2554 | 2537 |
2555 This function is analogous to `specifier-instance-from-inst-list' | 2538 This function is analogous to `specifier-instance-from-inst-list' |
2556 but allows for specification-matching as in `specifier-matching-instance'. | 2539 but allows for specification-matching as in `specifier-matching-instance'. |
2557 See that function for a description of exactly how the matching process | 2540 See that function for a description of exactly how the matching process |
2614 | 2597 |
2615 static void | 2598 static void |
2616 recompute_one_cached_specifier_in_window (Lisp_Object specifier, | 2599 recompute_one_cached_specifier_in_window (Lisp_Object specifier, |
2617 struct window *w) | 2600 struct window *w) |
2618 { | 2601 { |
2619 Lisp_Object window = Qnil; | 2602 Lisp_Object window; |
2620 Lisp_Object newval, *location; | 2603 Lisp_Object newval, *location; |
2621 | 2604 |
2622 XSETWINDOW (window, w); | 2605 XSETWINDOW (window, w); |
2623 | 2606 |
2624 newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN, | 2607 newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN, |
2640 | 2623 |
2641 static void | 2624 static void |
2642 recompute_one_cached_specifier_in_frame (Lisp_Object specifier, | 2625 recompute_one_cached_specifier_in_frame (Lisp_Object specifier, |
2643 struct frame *f) | 2626 struct frame *f) |
2644 { | 2627 { |
2645 Lisp_Object frame = Qnil; | 2628 Lisp_Object frame; |
2646 Lisp_Object newval, *location; | 2629 Lisp_Object newval, *location; |
2647 | 2630 |
2648 XSETFRAME (frame, f); | 2631 XSETFRAME (frame, f); |
2649 | 2632 |
2650 newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN, | 2633 newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN, |