diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el index ca607c8db9b..fb82f8b912b 100644 --- a/lisp/calendar/holidays.el +++ b/lisp/calendar/holidays.el @@ -67,7 +67,10 @@ (holiday-fixed 11 11 "Veteran's Day") (holiday-float 11 4 4 "Thanksgiving")) "General holidays. Default value is for the United States. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload @@ -86,7 +89,10 @@ See the documentation for `calendar-holidays' for details." (holiday-chinese 9 9 "Double Ninth Festival") (holiday-chinese-winter-solstice)))) "Oriental holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :version "23.1" ; added more holidays :set #'holidays--set-calendar-holidays :type 'sexp) @@ -96,7 +102,10 @@ See the documentation for `calendar-holidays' for details." ;;;###autoload (defcustom holiday-local-holidays nil "Local holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload @@ -105,7 +114,10 @@ See the documentation for `calendar-holidays' for details." ;;;###autoload (defcustom holiday-other-holidays nil "User defined holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload @@ -121,7 +133,10 @@ See the documentation for `calendar-holidays' for details." (holiday-hebrew-tisha-b-av) (holiday-hebrew-misc)))) "Jewish holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp :version "23.1") ; removed dependency on hebrew-holidays-N @@ -141,7 +156,10 @@ See the documentation for `calendar-holidays' for details." (holiday-fixed 8 15 "Assumption") (holiday-advent 0 "Advent")))) "Christian holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload @@ -161,7 +179,10 @@ See the documentation for `calendar-holidays' for details." (holiday-islamic 10 1 "Id-al-Fitr") (holiday-islamic 12 10 "Id-al-Adha")))) "Islamic holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload @@ -201,7 +222,10 @@ See the documentation for `calendar-holidays' for details." (/ calendar-daylight-savings-ends-time (float 60)) calendar-daylight-time-zone-name)))) "Sun-related holidays. -See the documentation for `calendar-holidays' for details." +See the documentation for `calendar-holidays' for details. + +Do not set this variable with `setq'; instead, use `setopt' +or `customize-option'." :set #'holidays--set-calendar-holidays :type 'sexp) ;;;###autoload diff --git a/src/xfaces.c b/src/xfaces.c index 7626dfeb75c..ca1bee1d17a 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -2426,6 +2426,60 @@ face_inherited_attr (struct window *w, struct frame *f, return attr_val; } +/* Chase the chain of inheritance for FACE on frame F, and return + non-zero if FACE inherits from its CHILD face, directly or + indirectly. FACE is either a symbol or a list of face symbols, which + are two forms of values for the :inherit attribute of a face. CHILD + must be a face symbol. */ +static bool +face_inheritance_cycle (struct frame *f, Lisp_Object face, Lisp_Object child) +{ + Lisp_Object face_attrs[LFACE_VECTOR_SIZE]; + Lisp_Object parent_face; + bool ok, cycle_found = false; + + eassert (SYMBOLP (child)); + if (CONSP (face)) + { + Lisp_Object tail; + for (tail = face; !NILP (tail); tail = XCDR (tail)) + { + ok = get_lface_attributes (NULL, f, XCAR (tail), face_attrs, + false, NULL); + if (!ok) + break; + parent_face = face_attrs[LFACE_INHERIT_INDEX]; + if (EQ (parent_face, child)) + cycle_found = true; + else if (!NILP (parent_face) + && !UNSPECIFIEDP (parent_face) + && !IGNORE_DEFFACE_P (parent_face) + && !RESET_P (parent_face)) + cycle_found = face_inheritance_cycle (f, parent_face, child); + if (cycle_found) + break; + } + } + else + { + eassert (SYMBOLP (face)); + ok = get_lface_attributes (NULL, f, face, face_attrs, false, NULL); + if (ok) + { + parent_face = face_attrs[LFACE_INHERIT_INDEX]; + if (EQ (parent_face, child)) + cycle_found = true; + else if (!NILP (parent_face) + && !UNSPECIFIEDP (parent_face) + && !IGNORE_DEFFACE_P (parent_face) + && !RESET_P (parent_face)) + cycle_found = face_inheritance_cycle (f, parent_face, child); + } + } + + return cycle_found; +} + /* Merge the named face FACE_NAME on frame F, into the vector of face attributes TO. Use NAMED_MERGE_POINTS to detect loops in face inheritance. Return true if FACE_NAME is a valid face name and @@ -3654,7 +3708,9 @@ FRAME 0 means change the face on all frames, and change the default for (tail = value; CONSP (tail); tail = XCDR (tail)) if (!SYMBOLP (XCAR (tail))) break; - if (NILP (tail)) + if (face_inheritance_cycle (f, value, face)) + signal_error ("Face inheritance results in inheritance cycle", value); + else if (NILP (tail)) ASET (lface, LFACE_INHERIT_INDEX, value); else signal_error ("Invalid face inheritance", value);