]> git.donarmstrong.com Git - lilypond.git/blobdiff - scm/music-functions.scm
Fix almost all warnings in flower/ and many in lily/.
[lilypond.git] / scm / music-functions.scm
index 95587b8670bf84ab44daf03b2ccfee66875f9936..250defcdd2f98bdaa09761b16a98eb1d62cd2802 100644 (file)
@@ -1,6 +1,6 @@
 ;;;; This file is part of LilyPond, the GNU music typesetter.
 ;;;;
 ;;;; This file is part of LilyPond, the GNU music typesetter.
 ;;;;
-;;;; Copyright (C) 1998--2010 Jan Nieuwenhuizen <janneke@gnu.org>
+;;;; Copyright (C) 1998--2011 Jan Nieuwenhuizen <janneke@gnu.org>
 ;;;;                 Han-Wen Nienhuys <hanwen@xs4all.nl>
 ;;;;
 ;;;; LilyPond is free software: you can redistribute it and/or modify
 ;;;;                 Han-Wen Nienhuys <hanwen@xs4all.nl>
 ;;;;
 ;;;; LilyPond is free software: you can redistribute it and/or modify
@@ -16,6 +16,9 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 
+; for define-safe-public when byte-compiling using Guile V2
+(use-modules (scm safe-utility-defs))
+
 ;; (use-modules (ice-9 optargs))
 
 ;;; ly:music-property with setter
 ;; (use-modules (ice-9 optargs))
 
 ;;; ly:music-property with setter
@@ -55,8 +58,8 @@
 (define-public (music-map function music)
   "Apply @var{function} to @var{music} and all of the music it contains.
 
 (define-public (music-map function music)
   "Apply @var{function} to @var{music} and all of the music it contains.
 
-First it recurses over the children, then the function is applied to MUSIC.
-"
+First it recurses over the children, then the function is applied to
+@var{music}."
   (let ((es (ly:music-property music 'elements))
        (e (ly:music-property music 'element)))
     (set! (ly:music-property music 'elements)
   (let ((es (ly:music-property music 'elements))
        (e (ly:music-property music 'element)))
     (set! (ly:music-property music 'elements)
@@ -67,7 +70,7 @@ First it recurses over the children, then the function is applied to MUSIC.
     (function music)))
 
 (define-public (music-filter pred? music)
     (function music)))
 
 (define-public (music-filter pred? music)
-  "Filter out music expressions that do not satisfy PRED."
+  "Filter out music expressions that do not satisfy @var{pred?}."
 
   (define (inner-music-filter pred? music)
     "Recursive function."
 
   (define (inner-music-filter pred? music)
     "Recursive function."
@@ -96,7 +99,8 @@ First it recurses over the children, then the function is applied to MUSIC.
       (make-music 'Music)))      ;must return music.
 
 (define-public (display-music music)
       (make-music 'Music)))      ;must return music.
 
 (define-public (display-music music)
-  "Display music, not done with music-map for clarity of presentation."
+  "Display music, not done with @code{music-map} for clarity of
+presentation."
 
   (display music)
   (display ": { ")
 
   (display music)
   (display ": { ")
@@ -147,8 +151,9 @@ For instance,
       `(markup ,@(inner-markup->make-markup markup-expression))))
 
 (define-public (music->make-music obj)
       `(markup ,@(inner-markup->make-markup markup-expression))))
 
 (define-public (music->make-music obj)
-  "Generate a expression that, once evaluated, may return an object equivalent to `obj',
-that is, for a music expression, a (make-music ...) form."
+  "Generate an expression that, once evaluated, may return an object
+equivalent to @var{obj}, that is, for a music expression, a
+@code{(make-music ...)} form."
   (cond (;; markup expression
         (markup? obj)
         (markup-expression->make-markup obj))
   (cond (;; markup expression
         (markup? obj)
         (markup-expression->make-markup obj))
@@ -227,16 +232,17 @@ Returns `obj'.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (shift-one-duration-log music shift dot)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (shift-one-duration-log music shift dot)
-  "  add SHIFT to duration-log of 'duration in music and optionally
-  a dot to any note encountered. This scales the music up by a factor
-  2^shift * (2 - (1/2)^dot)"
+  "Add @var{shift} to @code{duration-log} of @code{'duration} in
+@var{music} and optionally @var{dot} to any note encountered.
+The number of dots in the shifted music may not be less than zero."
   (let ((d (ly:music-property music 'duration)))
     (if (ly:duration? d)
        (let* ((cp (ly:duration-factor d))
   (let ((d (ly:music-property music 'duration)))
     (if (ly:duration? d)
        (let* ((cp (ly:duration-factor d))
-              (nd (ly:make-duration (+ shift (ly:duration-log d))
-                                    (+ dot (ly:duration-dot-count d))
-                                    (car cp)
-                                    (cdr cp))))
+              (nd (ly:make-duration
+                    (+ shift (ly:duration-log d))
+                    (max 0 (+ dot (ly:duration-dot-count d)))
+                   (car cp)
+                   (cdr cp))))
          (set! (ly:music-property music 'duration) nd)))
     music))
 
          (set! (ly:music-property music 'duration) nd)))
     music))
 
@@ -245,7 +251,8 @@ Returns `obj'.
             music))
 
 (define-public (make-repeat name times main alts)
             music))
 
 (define-public (make-repeat name times main alts)
-  "create a repeat music expression, with all properties initialized properly"
+  "Create a repeat music expression, with all properties initialized
+properly."
   (define (first-note-duration music)
     "Finds the duration of the first NoteEvent by searching depth-first
 through MUSIC."
   (define (first-note-duration music)
     "Finds the duration of the first NoteEvent by searching depth-first
 through MUSIC."
@@ -275,7 +282,7 @@ through MUSIC."
        ;; This works for single-note and multi-note tremolos!
        (let* ((children (if (music-is-of-type? main 'sequential-music)
                             ;; \repeat tremolo n { ... }
        ;; This works for single-note and multi-note tremolos!
        (let* ((children (if (music-is-of-type? main 'sequential-music)
                             ;; \repeat tremolo n { ... }
-                            (length (ly:music-property main 'elements))
+                            (length (extract-named-music main 'EventChord))
                             ;; \repeat tremolo n c4
                             1))
               ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
                             ;; \repeat tremolo n c4
                             1))
               ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
@@ -298,11 +305,25 @@ through MUSIC."
          (shift-duration-log r shift dots))
        r)))
 
          (shift-duration-log r shift dots))
        r)))
 
+(define (calc-repeat-slash-count music)
+  "Given the child-list @var{music} in @code{PercentRepeatMusic},
+calculate the number of slashes based on the durations.  Returns @code{0}
+if durations in @var{music} vary, allowing slash beats and double-percent
+beats to be distinguished."
+  (let* ((durs (map (lambda (elt)
+                     (duration-of-note elt))
+                   (extract-named-music music 'EventChord)))
+        (first-dur (car durs)))
+
+    (if (every (lambda (d) (equal? d first-dur)) durs)
+       (max (- (ly:duration-log first-dur) 2) 1)
+       0)))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; clusters.
 
 (define-public (note-to-cluster music)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; clusters.
 
 (define-public (note-to-cluster music)
-  "Replace NoteEvents by ClusterNoteEvents."
+  "Replace @code{NoteEvents} by @code{ClusterNoteEvents}."
   (if (eq? (ly:music-property music 'name) 'NoteEvent)
       (make-music 'ClusterNoteEvent
                  'pitch (ly:music-property music 'pitch)
   (if (eq? (ly:music-property music 'name) 'NoteEvent)
       (make-music 'ClusterNoteEvent
                  'pitch (ly:music-property music 'pitch)
@@ -316,7 +337,7 @@ through MUSIC."
 ;; repeats.
 
 (define-public (unfold-repeats music)
 ;; repeats.
 
 (define-public (unfold-repeats music)
-  "This function replaces all repeats with unfolded repeats."
+  "Replace all repeats with unfolded repeats."
 
   (let ((es (ly:music-property music 'elements))
        (e (ly:music-property music 'element)))
 
   (let ((es (ly:music-property music 'elements))
        (e (ly:music-property music 'element)))
@@ -360,8 +381,8 @@ through MUSIC."
 ;; property setting music objs.
 
 (define-public (make-grob-property-set grob gprop val)
 ;; property setting music objs.
 
 (define-public (make-grob-property-set grob gprop val)
-  "Make a Music expression that sets GPROP to VAL in GROB. Does a pop first,
-i.e.  this is not an override"
+  "Make a @code{Music} expression that sets @var{gprop} to @var{val} in
+@var{grob}.  Does a pop first, i.e., this is not an override."
   (make-music 'OverrideProperty
              'symbol grob
              'grob-property gprop
   (make-music 'OverrideProperty
              'symbol grob
              'grob-property gprop
@@ -369,23 +390,26 @@ i.e.  this is not an override"
              'pop-first #t))
 
 (define-public (make-grob-property-override grob gprop val)
              'pop-first #t))
 
 (define-public (make-grob-property-override grob gprop val)
-  "Make a Music expression that overrides GPROP to VAL in GROB."
+  "Make a @code{Music} expression that overrides @var{gprop} to @var{val}
+in @var{grob}."
   (make-music 'OverrideProperty
              'symbol grob
              'grob-property gprop
              'grob-value val))
 
 (define-public (make-grob-property-revert grob gprop)
   (make-music 'OverrideProperty
              'symbol grob
              'grob-property gprop
              'grob-value val))
 
 (define-public (make-grob-property-revert grob gprop)
-  "Revert the grob property GPROP for GROB."
+  "Revert the grob property @var{gprop} for @var{grob}."
   (make-music 'RevertProperty
              'symbol grob
              'grob-property gprop))
 
 (define direction-polyphonic-grobs
   (make-music 'RevertProperty
              'symbol grob
              'grob-property gprop))
 
 (define direction-polyphonic-grobs
-  '(DotColumn
+  '(AccidentalSuggestion
+    DotColumn
     Dots
     Fingering
     LaissezVibrerTie
     Dots
     Fingering
     LaissezVibrerTie
+    LigatureBracket
     PhrasingSlur
     RepeatTie
     Rest
     PhrasingSlur
     RepeatTie
     Rest
@@ -393,7 +417,9 @@ i.e.  this is not an override"
     Slur
     Stem
     TextScript
     Slur
     Stem
     TextScript
-    Tie))
+    Tie
+    TupletBracket
+    TrillSpanner))
 
 (define-safe-public (make-voice-props-set n)
   (make-sequential-music
 
 (define-safe-public (make-voice-props-set n)
   (make-sequential-music
@@ -405,6 +431,7 @@ i.e.  this is not an override"
      (make-property-set 'graceSettings
                        ;; TODO: take this from voicedGraceSettings or similar.
                        '((Voice Stem font-size -3)
      (make-property-set 'graceSettings
                        ;; TODO: take this from voicedGraceSettings or similar.
                        '((Voice Stem font-size -3)
+                         (Voice Flag font-size -3)
                          (Voice NoteHead font-size -3)
                          (Voice TabNoteHead font-size -4)
                          (Voice Dots font-size -3)
                          (Voice NoteHead font-size -3)
                          (Voice TabNoteHead font-size -4)
                          (Voice Dots font-size -3)
@@ -432,7 +459,7 @@ i.e.  this is not an override"
 
 
 (define-safe-public (context-spec-music m context #:optional id)
 
 
 (define-safe-public (context-spec-music m context #:optional id)
-  "Add \\context CONTEXT = ID to M. "
+  "Add \\context CONTEXT = ID to M."
   (let ((cm (make-music 'ContextSpeccedMusic
                        'element m
                        'context-type context)))
   (let ((cm (make-music 'ContextSpeccedMusic
                        'element m
                        'context-type context)))
@@ -441,7 +468,7 @@ i.e.  this is not an override"
     cm))
 
 (define-public (descend-to-context m context)
     cm))
 
 (define-public (descend-to-context m context)
-  "Like context-spec-music, but only descending. "
+  "Like @code{context-spec-music}, but only descending."
   (let ((cm (context-spec-music m context)))
     (ly:music-set-property! cm 'descend-only #t)
     cm))
   (let ((cm (context-spec-music m context)))
     (ly:music-set-property! cm 'descend-only #t)
     cm))
@@ -491,25 +518,6 @@ i.e.  this is not an override"
   (make-music 'PropertyUnset
              'symbol sym))
 
   (make-music 'PropertyUnset
              'symbol sym))
 
-;;; Need to keep this definition for \time calls from parser
-(define-public (make-time-signature-set num den)
-  "Set properties for time signature NUM/DEN."
-  (make-music 'TimeSignatureMusic
-              'numerator num
-              'denominator den
-              'beat-structure '()))
-
-;;; Used for calls that include beat-grouping setting
-(define-public (set-time-signature num den . rest)
-  "Set properties for time signature @var{num/den}.
-If @var{rest} is present, it is used to set
-@code{beatStructure}."
-  (ly:export
-   (make-music 'TimeSignatureMusic
-              'numerator num
-              'denominator den
-              'beat-structure (if (null? rest) rest (car rest)))))
-
 (define-safe-public (make-articulation name)
   (make-music 'ArticulationEvent
              'articulation-type name))
 (define-safe-public (make-articulation name)
   (make-music 'ArticulationEvent
              'articulation-type name))
@@ -559,14 +567,14 @@ inside of and outside of chord construct."
           (revert-head-style heads)))))
 
  (define-public (set-mus-properties! m alist)
           (revert-head-style heads)))))
 
  (define-public (set-mus-properties! m alist)
-  "Set all of ALIST as properties of M."
+  "Set all of @var{alist} as properties of @var{m}."
   (if (pair? alist)
       (begin
        (set! (ly:music-property m (caar alist)) (cdar alist))
        (set-mus-properties! m (cdr alist)))))
 
 (define-public (music-separator? m)
   (if (pair? alist)
       (begin
        (set! (ly:music-property m (caar alist)) (cdar alist))
        (set-mus-properties! m (cdr alist)))))
 
 (define-public (music-separator? m)
-  "Is M a separator?"
+  "Is @var{m} a separator?"
   (let ((ts (ly:music-property m 'types)))
     (memq 'separator ts)))
 
   (let ((ts (ly:music-property m 'types)))
     (memq 'separator ts)))
 
@@ -574,10 +582,10 @@ inside of and outside of chord construct."
 (define (voicify-list lst number)
   "Make a list of Musics.
 
 (define (voicify-list lst number)
   "Make a list of Musics.
 
-   voicify-list :: [ [Music ] ] -> number -> [Music]
-   LST is a list music-lists.
+voicify-list :: [ [Music ] ] -> number -> [Music]
+LST is a list music-lists.
 
 
-   NUMBER is 0-base, i.e. Voice=1 (upstems) has number 0.
+NUMBER is 0-base, i.e., Voice=1 (upstems) has number 0.
 "
   (if (null? lst)
       '()
 "
   (if (null? lst)
       '()
@@ -596,7 +604,7 @@ inside of and outside of chord construct."
     ch))
 
 (define-public (voicify-music m)
     ch))
 
 (define-public (voicify-music m)
-  "Recursively split chords that are separated with \\ "
+  "Recursively split chords that are separated with @code{\\\\}."
   (if (not (ly:music? m))
       (ly:error (_ "music expected: ~S") m))
   (let ((es (ly:music-property m 'elements))
   (if (not (ly:music? m))
       (ly:error (_ "music expected: ~S") m))
   (let ((es (ly:music-property m 'elements))
@@ -612,7 +620,7 @@ inside of and outside of chord construct."
     m))
 
 (define-public (empty-music)
     m))
 
 (define-public (empty-music)
-  (ly:export (make-music 'Music)))
+  (make-music 'Music))
 
 ;; Make a function that checks score element for being of a specific type.
 (define-public (make-type-checker symbol)
 
 ;; Make a function that checks score element for being of a specific type.
 (define-public (make-type-checker symbol)
@@ -625,37 +633,16 @@ inside of and outside of chord construct."
 
 
 (define-public ((set-output-property grob-name symbol val)  grob grob-c context)
 
 
 (define-public ((set-output-property grob-name symbol val)  grob grob-c context)
-  "Usage:
-
-\\applyoutput #(set-output-property 'Clef 'extra-offset '(0 . 1))
-
-"
+  "Usage example:
+@code{\\applyoutput #(set-output-property 'Clef 'extra-offset '(0 . 1))}"
   (let ((meta (ly:grob-property grob 'meta)))
     (if (equal? (assoc-get 'name meta) grob-name)
        (set! (ly:grob-property grob symbol) val))))
 
 
   (let ((meta (ly:grob-property grob 'meta)))
     (if (equal? (assoc-get 'name meta) grob-name)
        (set! (ly:grob-property grob symbol) val))))
 
 
-;;
-(define-public (smart-bar-check n)
-  "Make         a bar check that checks for a specific bar number.
-"
-  (let ((m (make-music 'ApplyContext)))
-    (define (checker tr)
-      (let* ((bn (ly:context-property tr 'currentBarNumber)))
-       (if (= bn n)
-           #t
-           (ly:error
-            ;; FIXME: uncomprehensable message
-            (_ "Bar check failed.  Expect to be at ~a, instead at ~a")
-            n bn))))
-    (set! (ly:music-property m 'procedure) checker)
-    m))
-
-
 (define-public (skip->rest mus)
 (define-public (skip->rest mus)
-
-  "Replace MUS by RestEvent of the same duration if it is a
-SkipEvent. Useful for extracting parts from crowded scores"
+  "Replace @var{mus} by @code{RestEvent} of the same duration if it is a
+@code{SkipEvent}.  Useful for extracting parts from crowded scores."
 
   (if  (memq (ly:music-property mus 'name) '(SkipEvent SkipMusic))
    (make-music 'RestEvent 'duration (ly:music-property mus 'duration))
 
   (if  (memq (ly:music-property mus 'name) '(SkipEvent SkipMusic))
    (make-music 'RestEvent 'duration (ly:music-property mus 'duration))
@@ -680,12 +667,17 @@ SkipEvent. Useful for extracting parts from crowded scores"
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; warn for bare chords at start.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; warn for bare chords at start.
 
-
 (define-public (ly:music-message music msg)
   (let ((ip (ly:music-property music 'origin)))
     (if (ly:input-location? ip)
 (define-public (ly:music-message music msg)
   (let ((ip (ly:music-property music 'origin)))
     (if (ly:input-location? ip)
-       (ly:input-message ip msg)
-       (ly:warning msg))))
+        (ly:input-message ip msg)
+        (ly:message msg))))
+
+(define-public (ly:music-warning music msg)
+  (let ((ip (ly:music-property music 'origin)))
+    (if (ly:input-location? ip)
+        (ly:input-warning ip msg)
+        (ly:warning msg))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -701,30 +693,30 @@ SkipEvent. Useful for extracting parts from crowded scores"
     nv))
 
 (define (vector-map f v)
     nv))
 
 (define (vector-map f v)
-  "Map F over V. This function returns nothing."
+  "Map F over V.  This function returns nothing."
   (do ((n (vector-length v))
        (i 0 (+ i 1)))
       ((>= i n))
     (f (vector-ref v i))))
 
 (define (vector-reverse-map f v)
   (do ((n (vector-length v))
        (i 0 (+ i 1)))
       ((>= i n))
     (f (vector-ref v i))))
 
 (define (vector-reverse-map f v)
-  "Map F over V, N to 0 order. This function returns nothing."
+  "Map F over V, N to 0 order.  This function returns nothing."
   (do ((i (- (vector-length v) 1) (- i 1)))
       ((< i 0))
     (f (vector-ref v i))))
 
 (define-public (add-grace-property context-name grob sym val)
   (do ((i (- (vector-length v) 1) (- i 1)))
       ((< i 0))
     (f (vector-ref v i))))
 
 (define-public (add-grace-property context-name grob sym val)
-  "Set SYM=VAL for GROB in CONTEXT-NAME. "
+  "Set @var{sym}=@var{val} for @var{grob} in @var{context-name}."
   (define (set-prop context)
     (let* ((where (ly:context-property-where-defined context 'graceSettings))
           (current (ly:context-property where 'graceSettings))
           (new-settings (append current
                                 (list (list context-name grob sym val)))))
       (ly:context-set-property! where 'graceSettings new-settings)))
   (define (set-prop context)
     (let* ((where (ly:context-property-where-defined context 'graceSettings))
           (current (ly:context-property where 'graceSettings))
           (new-settings (append current
                                 (list (list context-name grob sym val)))))
       (ly:context-set-property! where 'graceSettings new-settings)))
-  (ly:export (context-spec-music (make-apply-context set-prop) 'Voice)))
+  (context-spec-music (make-apply-context set-prop) 'Voice))
 
 (define-public (remove-grace-property context-name grob sym)
 
 (define-public (remove-grace-property context-name grob sym)
-  "Remove all SYM for GROB in CONTEXT-NAME. "
+  "Remove all @var{sym} for @var{grob} in @var{context-name}."
   (define (sym-grob-context? property sym grob context-name)
     (and (eq? (car property) context-name)
          (eq? (cadr property) grob)
   (define (sym-grob-context? property sym grob context-name)
     (and (eq? (car property) context-name)
          (eq? (cadr property) grob)
@@ -740,7 +732,7 @@ SkipEvent. Useful for extracting parts from crowded scores"
                  (set! new-settings (delete x new-settings)))
                prop-settings)
       (ly:context-set-property! where 'graceSettings new-settings)))
                  (set! new-settings (delete x new-settings)))
                prop-settings)
       (ly:context-set-property! where 'graceSettings new-settings)))
-  (ly:export (context-spec-music (make-apply-context delete-prop) 'Voice)))
+  (context-spec-music (make-apply-context delete-prop) 'Voice))
 
 
 
 
 
 
@@ -755,33 +747,134 @@ SkipEvent. Useful for extracting parts from crowded scores"
                                                      music
                                                      (ly:music-deep-copy ,stop))))))
 
                                                      music
                                                      (ly:music-deep-copy ,stop))))))
 
-(defmacro-public define-music-function (args signature . body)
+(defmacro-public define-syntax-function (type args signature . body)
   "Helper macro for `ly:make-music-function'.
 Syntax:
   "Helper macro for `ly:make-music-function'.
 Syntax:
-  (define-music-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+  (define-syntax-function (result-type? parser location arg1 arg2 ...) (result-type? arg1-type arg2-type ...)
     ...function body...)
     ...function body...)
-"
-(if (and (pair? body) (pair? (car body)) (eqv? '_i (caar body)))
+
+argX-type can take one of the forms @code{predicate?} for mandatory
+arguments satisfying the predicate, @code{(predicate?)} for optional
+parameters of that type defaulting to @code{#f}, @code{@w{(predicate?
+value)}} for optional parameters with a specified default
+value (evaluated at definition time).  An optional parameter can be
+omitted in a call only when it can't get confused with a following
+parameter of different type.
+
+Predicates with syntactical significance are @code{ly:pitch?},
+@code{ly:duration?}, @code{ly:music?}, @code{markup?}.  Other
+predicates require the parameter to be entered as Scheme expression.
+
+@code{result-type?} can specify a default in the same manner as
+predicates, to be used in case of a type error in arguments or
+result."
+
+  (set! signature (map (lambda (pred)
+                        (if (pair? pred)
+                            `(cons ,(car pred)
+                                   ,(and (pair? (cdr pred)) (cadr pred)))
+                            pred))
+                      (cons type signature)))
+  (if (and (pair? body) (pair? (car body)) (eqv? '_i (caar body)))
       ;; When the music function definition contains a i10n doc string,
       ;; (_i "doc string"), keep the literal string only
       (let ((docstring (cadar body))
            (body (cdr body)))
        `(ly:make-music-function (list ,@signature)
       ;; When the music function definition contains a i10n doc string,
       ;; (_i "doc string"), keep the literal string only
       (let ((docstring (cadar body))
            (body (cdr body)))
        `(ly:make-music-function (list ,@signature)
-                                (lambda (,@args)
+                                (lambda ,args
                                   ,docstring
                                   ,@body)))
       `(ly:make-music-function (list ,@signature)
                                   ,docstring
                                   ,@body)))
       `(ly:make-music-function (list ,@signature)
-                              (lambda (,@args)
+                              (lambda ,args
                                 ,@body))))
 
                                 ,@body))))
 
+(defmacro-public define-music-function rest
+  "Defining macro returning music functions.
+Syntax:
+  (define-music-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+    ...function body...)
+
+argX-type can take one of the forms @code{predicate?} for mandatory
+arguments satisfying the predicate, @code{(predicate?)} for optional
+parameters of that type defaulting to @code{#f}, @code{@w{(predicate?
+value)}} for optional parameters with a specified default
+value (evaluated at definition time).  An optional parameter can be
+omitted in a call only when it can't get confused with a following
+parameter of different type.
+
+Predicates with syntactical significance are @code{ly:pitch?},
+@code{ly:duration?}, @code{ly:music?}, @code{markup?}.  Other
+predicates require the parameter to be entered as Scheme expression.
+
+Must return a music expression.  The @code{origin} is automatically
+set to the @code{location} parameter."
+
+  `(define-syntax-function (ly:music? (make-music 'Music 'void #t)) ,@rest))
+
+
+(defmacro-public define-scheme-function rest
+  "Defining macro returning Scheme functions.
+Syntax:
+  (define-scheme-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+    ...function body...)
+
+argX-type can take one of the forms @code{predicate?} for mandatory
+arguments satisfying the predicate, @code{(predicate?)} for optional
+parameters of that type defaulting to @code{#f}, @code{@w{(predicate?
+value)}} for optional parameters with a specified default
+value (evaluated at definition time).  An optional parameter can be
+omitted in a call only when it can't get confused with a following
+parameter of different type.
+
+Predicates with syntactical significance are @code{ly:pitch?},
+@code{ly:duration?}, @code{ly:music?}, @code{markup?}.  Other
+predicates require the parameter to be entered as Scheme expression.
+
+Can return arbitrary expressions.  If a music expression is returned,
+its @code{origin} is automatically set to the @code{location}
+parameter."
+
+  `(define-syntax-function scheme? ,@rest))
+
+(defmacro-public define-void-function rest
+  "This defines a Scheme function like @code{define-scheme-function} with
+void return value (i.e., what most Guile functions with `unspecified'
+value return).  Use this when defining functions for executing actions
+rather than returning values, to keep Lilypond from trying to interpret
+the return value."
+  `(define-syntax-function (void? *unspecified*) ,@rest *unspecified*))
+
+(defmacro-public define-event-function rest
+  "Defining macro returning event functions.
+Syntax:
+  (define-event-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+    ...function body...)
+
+argX-type can take one of the forms @code{predicate?} for mandatory
+arguments satisfying the predicate, @code{(predicate?)} for optional
+parameters of that type defaulting to @code{#f}, @code{@w{(predicate?
+value)}} for optional parameters with a specified default
+value (evaluated at definition time).  An optional parameter can be
+omitted in a call only when it can't get confused with a following
+parameter of different type.
+
+Predicates with syntactical significance are @code{ly:pitch?},
+@code{ly:duration?}, @code{ly:music?}, @code{markup?}.  Other
+predicates require the parameter to be entered as Scheme expression.
+
+Must return an event expression.  The @code{origin} is automatically
+set to the @code{location} parameter."
+
+  `(define-syntax-function (ly:event? (make-music 'Event 'void #t)) ,@rest))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (cue-substitute quote-music)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (cue-substitute quote-music)
-  "Must happen after quote-substitute."
+  "Must happen after @code{quote-substitute}."
 
   (if (vector? (ly:music-property quote-music 'quoted-events))
       (let* ((dir (ly:music-property quote-music 'quoted-voice-direction))
 
   (if (vector? (ly:music-property quote-music 'quoted-events))
       (let* ((dir (ly:music-property quote-music 'quoted-voice-direction))
+            (clef (ly:music-property quote-music 'quoted-music-clef))
             (main-voice (if (eq? 1 dir) 1 0))
             (cue-voice (if (eq? 1 dir) 0 1))
             (main-music (ly:music-property quote-music 'element))
             (main-voice (if (eq? 1 dir) 1 0))
             (cue-voice (if (eq? 1 dir) 0 1))
             (main-music (ly:music-property quote-music 'element))
@@ -793,14 +886,19 @@ Syntax:
            ;; to have opposite stems.
            (begin
              (set! return-value
            ;; to have opposite stems.
            (begin
              (set! return-value
-
                    ;; cannot context-spec Quote-music, since context
                    ;; for the quotes is determined in the iterator.
                    (make-sequential-music
                     (list
                    ;; cannot context-spec Quote-music, since context
                    ;; for the quotes is determined in the iterator.
                    (make-sequential-music
                     (list
+                     (if (null? clef)
+                         (make-music 'Music)
+                         (make-cue-clef-set clef))
                      (context-spec-music (make-voice-props-set cue-voice) 'CueVoice "cue")
                      quote-music
                      (context-spec-music (make-voice-props-set cue-voice) 'CueVoice "cue")
                      quote-music
-                     (context-spec-music (make-voice-props-revert)  'CueVoice "cue"))))
+                     (context-spec-music (make-voice-props-revert) 'CueVoice "cue")
+                     (if (null? clef)
+                         (make-music 'Music)
+                         (make-cue-clef-unset)))))
              (set! main-music
                    (make-sequential-music
                     (list
              (set! main-music
                    (make-sequential-music
                     (list
@@ -814,9 +912,8 @@ Syntax:
 
 (define-public ((quote-substitute quote-tab) music)
   (let* ((quoted-name (ly:music-property music 'quoted-music-name))
 
 (define-public ((quote-substitute quote-tab) music)
   (let* ((quoted-name (ly:music-property music 'quoted-music-name))
-        (quoted-vector (if (string? quoted-name)
-                           (hash-ref quote-tab quoted-name #f)
-                           #f)))
+        (quoted-vector (and (string? quoted-name)
+                            (hash-ref quote-tab quoted-name #f))))
 
 
     (if (string? quoted-name)
 
 
     (if (string? quoted-name)
@@ -825,7 +922,7 @@ Syntax:
              (set! (ly:music-property music 'quoted-events) quoted-vector)
              (set! (ly:music-property music 'iterator-ctor)
                    ly:quote-iterator::constructor))
              (set! (ly:music-property music 'quoted-events) quoted-vector)
              (set! (ly:music-property music 'iterator-ctor)
                    ly:quote-iterator::constructor))
-           (ly:warning (_ "cannot find quoted music: `~S'") quoted-name)))
+           (ly:music-warning music (ly:format (_ "cannot find quoted music: `~S'") quoted-name))))
     music))
 
 
     music))
 
 
@@ -859,37 +956,26 @@ Syntax:
   music)
 
 (define-public (make-duration-of-length moment)
   music)
 
 (define-public (make-duration-of-length moment)
- "Make duration of the given MOMENT length."
+ "Make duration of the given @code{moment} length."
  (ly:make-duration 0 0
   (ly:moment-main-numerator moment)
   (ly:moment-main-denominator moment)))
 
  (ly:make-duration 0 0
   (ly:moment-main-numerator moment)
   (ly:moment-main-denominator moment)))
 
-(define (skip-this moment)
- "set skipTypesetting, make SkipMusic of the given MOMENT length,
- and then unset skipTypesetting."
+(define (make-skipped moment bool)
+ "Depending on BOOL, set or unset skipTypesetting,
+then make SkipMusic of the given MOMENT length, and
+then revert skipTypesetting."
  (make-sequential-music
   (list
  (make-sequential-music
   (list
-   (context-spec-music (make-property-set 'skipTypesetting #t)
+   (context-spec-music (make-property-set 'skipTypesetting bool)
     'Score)
    (make-music 'SkipMusic 'duration
     (make-duration-of-length moment))
     'Score)
    (make-music 'SkipMusic 'duration
     (make-duration-of-length moment))
-   (context-spec-music (make-property-set 'skipTypesetting #f)
-    'Score))))
-
-(define (unskip-this moment)
- "unset skipTypesetting, make SkipMusic of the given MOMENT length,
- and then set skipTypesetting."
- (make-sequential-music
-  (list
-   (context-spec-music (make-property-set 'skipTypesetting #f)
-    'Score)
-   (make-music 'SkipMusic 'duration
-    (make-duration-of-length moment))
-   (context-spec-music (make-property-set 'skipTypesetting #t)
+   (context-spec-music (make-property-set 'skipTypesetting (not bool))
     'Score))))
 
 (define (skip-as-needed music parser)
     'Score))))
 
 (define (skip-as-needed music parser)
- "Replace MUSIC by
 "Replace MUSIC by
  << {  \\set skipTypesetting = ##f
  LENGTHOF(\\showFirstLength)
  \\set skipTypesetting = ##t
  << {  \\set skipTypesetting = ##f
  LENGTHOF(\\showFirstLength)
  \\set skipTypesetting = ##t
@@ -900,51 +986,54 @@ Syntax:
  When only showFirstLength is set,
  the 'length property of the music is
  overridden to speed up compiling."
  When only showFirstLength is set,
  the 'length property of the music is
  overridden to speed up compiling."
- (let*
-  ((show-last (ly:parser-lookup parser 'showLastLength))
-   (show-first (ly:parser-lookup parser 'showFirstLength)))
-  (cond
-
-   ;; both properties may be set.
-   ((and (ly:music? show-first) (ly:music? show-last))
-    (let*
-     ((orig-length (ly:music-length music))
-      (skip-length (ly:moment-sub orig-length (ly:music-length show-last)))
-      (begin-length (ly:music-length show-first)))
-     (make-simultaneous-music
-      (list
-       (make-sequential-music
-        (list
-         (skip-this skip-length)
-         ;; let's draw a separator between the beginning and the end
-         (context-spec-music (make-property-set 'whichBar "||")
-          'Timing)))
-       (unskip-this begin-length)
-       music))))
-
-   ;; we may only want to print the last length
-   ((ly:music? show-last)
-    (let*
-     ((orig-length (ly:music-length music))
-      (skip-length (ly:moment-sub orig-length (ly:music-length show-last))))
-     (make-simultaneous-music
-      (list
-       (skip-this skip-length)
-       music))))
-
-   ;; we may only want to print the beginning; in this case
-   ;; only the first length will be processed (much faster).
-   ((ly:music? show-first)
-    (let*
-     ((orig-length (ly:music-length music))
-      (begin-length (ly:music-length show-first)))
-     ;; the first length must not exceed the original length.
-     (if (ly:moment<? begin-length orig-length)
-      (set! (ly:music-property music 'length)
-       (ly:music-length show-first)))
-     music))
-
-   (else music))))
+  (let*
+      ((show-last (ly:parser-lookup parser 'showLastLength))
+       (show-first (ly:parser-lookup parser 'showFirstLength))
+       (show-last-length (and (ly:music? show-last)
+                             (ly:music-length show-last)))
+       (show-first-length (and (ly:music? show-first)
+                              (ly:music-length show-first)))
+       (orig-length (ly:music-length music)))
+
+    ;;FIXME: if using either showFirst- or showLastLength,
+    ;; make sure that skipBars is not set.
+
+    (cond
+
+     ;; both properties may be set.
+     ((and show-first-length show-last-length)
+      (let
+          ((skip-length (ly:moment-sub orig-length show-last-length)))
+        (make-simultaneous-music
+         (list
+          (make-sequential-music
+           (list
+            (make-skipped skip-length #t)
+            ;; let's draw a separator between the beginning and the end
+            (context-spec-music (make-property-set 'whichBar "||")
+                                'Timing)))
+          (make-skipped show-first-length #f)
+          music))))
+
+     ;; we may only want to print the last length
+     (show-last-length
+      (let
+          ((skip-length (ly:moment-sub orig-length show-last-length)))
+        (make-simultaneous-music
+         (list
+          (make-skipped skip-length #t)
+          music))))
+
+     ;; we may only want to print the beginning; in this case
+     ;; only the first length will be processed (much faster).
+     (show-first-length
+      ;; the first length must not exceed the original length.
+      (if (ly:moment<? show-first-length orig-length)
+          (set! (ly:music-property music 'length)
+                show-first-length))
+      music)
+
+     (else music))))
 
 
 (define-public toplevel-music-functions
 
 
 (define-public toplevel-music-functions
@@ -992,17 +1081,22 @@ Syntax:
 ;; accidentals
 
 (define (recent-enough? bar-number alteration-def laziness)
 ;; accidentals
 
 (define (recent-enough? bar-number alteration-def laziness)
-  (if (or (number? alteration-def)
-         (equal? laziness #t))
-      #t
+  (or (number? alteration-def)
+      (equal? laziness #t)
       (<= bar-number (+ (cadr alteration-def) laziness))))
 
       (<= bar-number (+ (cadr alteration-def) laziness))))
 
-(define (is-tied? alteration-def)
-  (let* ((def (if (pair? alteration-def)
-                (car alteration-def)
-                alteration-def)))
+(define (accidental-invalid? alteration-def)
+  "Checks an alteration entry for being invalid.
 
 
-    (if (equal? def 'tied) #t #f)))
+Non-key alterations are invalidated when tying into the next bar or
+when there is a clef change, since neither repetition nor cancellation
+can be omitted when the same note occurs again.
+
+Returns @code{#f} or the reason for the invalidation, a symbol."
+  (let* ((def (if (pair? alteration-def)
+                 (car alteration-def)
+                 alteration-def)))
+    (and (symbol? def) def)))
 
 (define (extract-alteration alteration-def)
   (cond ((number? alteration-def)
 
 (define (extract-alteration alteration-def)
   (cond ((number? alteration-def)
@@ -1013,7 +1107,7 @@ Syntax:
 
 (define (check-pitch-against-signature context pitch barnum laziness octaveness)
   "Checks the need for an accidental and a @q{restore} accidental against
 
 (define (check-pitch-against-signature context pitch barnum laziness octaveness)
   "Checks the need for an accidental and a @q{restore} accidental against
-@code{localKeySignature}. The @var{laziness} is the number of measures
+@code{localKeySignature}.  The @var{laziness} is the number of measures
 for which reminder accidentals are used (i.e., if @var{laziness} is zero,
 only cancel accidentals in the same measure; if @var{laziness} is three,
 we cancel accidentals up to three measures after they first appear.
 for which reminder accidentals are used (i.e., if @var{laziness} is zero,
 only cancel accidentals in the same measure; if @var{laziness} is three,
 we cancel accidentals up to three measures after they first appear.
@@ -1035,14 +1129,13 @@ specifies whether accidentals should be canceled in different octaves."
         (previous-alteration #f)
         (from-other-octaves #f)
         (from-same-octave (assoc-get pitch-handle local-key-sig))
         (previous-alteration #f)
         (from-other-octaves #f)
         (from-same-octave (assoc-get pitch-handle local-key-sig))
-        (from-key-sig (assoc-get notename local-key-sig)))
+        (from-key-sig (or (assoc-get notename local-key-sig)
 
     ;; If no key signature match is found from localKeySignature, we may have a custom
     ;; type with octave-specific entries of the form ((octave . pitch) alteration)
     ;; instead of (pitch . alteration).  Since this type cannot coexist with entries in
     ;; localKeySignature, try extracting from keySignature instead.
 
     ;; If no key signature match is found from localKeySignature, we may have a custom
     ;; type with octave-specific entries of the form ((octave . pitch) alteration)
     ;; instead of (pitch . alteration).  Since this type cannot coexist with entries in
     ;; localKeySignature, try extracting from keySignature instead.
-    (if (equal? from-key-sig #f)
-       (set! from-key-sig (assoc-get pitch-handle key-sig)))
+                          (assoc-get pitch-handle key-sig))))
 
     ;; loop through localKeySignature to search for a notename match from other octaves
     (let loop ((l local-key-sig))
 
     ;; loop through localKeySignature to search for a notename match from other octaves
     (let loop ((l local-key-sig))
@@ -1056,22 +1149,22 @@ specifies whether accidentals should be canceled in different octaves."
     ;; find previous alteration-def for comparison with pitch
     (cond
      ;; from same octave?
     ;; find previous alteration-def for comparison with pitch
     (cond
      ;; from same octave?
-     ((and (eq? ignore-octave #f)
-          (not (equal? from-same-octave #f))
+     ((and (not ignore-octave)
+          from-same-octave
           (recent-enough? barnum from-same-octave laziness))
       (set! previous-alteration from-same-octave))
 
      ;; from any octave?
           (recent-enough? barnum from-same-octave laziness))
       (set! previous-alteration from-same-octave))
 
      ;; from any octave?
-     ((and (eq? ignore-octave #t)
-          (not (equal? from-other-octaves #f))
+     ((and ignore-octave
+          from-other-octaves
           (recent-enough? barnum from-other-octaves laziness))
       (set! previous-alteration from-other-octaves))
 
      ;; not recent enough, extract from key signature/local key signature
           (recent-enough? barnum from-other-octaves laziness))
       (set! previous-alteration from-other-octaves))
 
      ;; not recent enough, extract from key signature/local key signature
-     ((not (equal? from-key-sig #f))
+     (from-key-sig
       (set! previous-alteration from-key-sig)))
 
       (set! previous-alteration from-key-sig)))
 
-    (if (is-tied? previous-alteration)
+    (if (accidental-invalid? previous-alteration)
        (set! need-accidental #t)
 
        (let* ((prev-alt (extract-alteration previous-alteration))
        (set! need-accidental #t)
 
        (let* ((prev-alt (extract-alteration previous-alteration))
@@ -1081,29 +1174,33 @@ specifies whether accidentals should be canceled in different octaves."
              (begin
                (set! need-accidental #t)
                (if (and (not (= this-alt 0))
              (begin
                (set! need-accidental #t)
                (if (and (not (= this-alt 0))
-                        (or (< (abs this-alt) (abs prev-alt))
-                            (< (* prev-alt this-alt) 0)))
+                        (and (< (abs this-alt) (abs prev-alt))
+                            (> (* prev-alt this-alt) 0)))
                    (set! need-restore #t))))))
 
     (cons need-restore need-accidental)))
 
 (define-public ((make-accidental-rule octaveness laziness) context pitch barnum measurepos)
                    (set! need-restore #t))))))
 
     (cons need-restore need-accidental)))
 
 (define-public ((make-accidental-rule octaveness laziness) context pitch barnum measurepos)
-  "Creates an accidental rule that makes its decision based on the octave of the note
-  and a laziness value.
-  octaveness is either 'same-octave or 'any-octave and defines whether the rule should
-  respond to accidental changes in other octaves than the current. 'same-octave is the
-  normal way to typeset accidentals - an accidental is made if the alteration is different
-  from the last active pitch in the same octave. 'any-octave looks at the last active pitch
-  in any octave.
-  laziness states over how many bars an accidental should be remembered.
-  0 is default - accidental lasts over 0 bar lines, that is, to the end of current measure.
-  A positive integer means that the accidental lasts over that many bar lines.
-  -1 is 'forget immediately', that is, only look at key signature.
-  #t is forever."
+  "Create an accidental rule that makes its decision based on the octave of
+the note and a laziness value.
+
+@var{octaveness} is either @code{'same-octave} or @code{'any-octave} and
+defines whether the rule should respond to accidental changes in other
+octaves than the current.  @code{'same-octave} is the normal way to typeset
+accidentals -- an accidental is made if the alteration is different from the
+last active pitch in the same octave.  @code{'any-octave} looks at the last
+active pitch in any octave.
+
+@var{laziness} states over how many bars an accidental should be remembered.
+@code{0}@tie{}is the default -- accidental lasts over 0@tie{}bar lines, that
+is, to the end of current measure.  A positive integer means that the
+accidental lasts over that many bar lines.  @w{@code{-1}} is `forget
+immediately', that is, only look at key signature.  @code{#t} is `forever'."
+
   (check-pitch-against-signature context pitch barnum laziness octaveness))
 
 (define (key-entry-notename entry)
   (check-pitch-against-signature context pitch barnum laziness octaveness))
 
 (define (key-entry-notename entry)
-  "Return the pitch of an entry in localKeySignature. The entry is either of the form
+  "Return the pitch of an entry in localKeySignature.  The entry is either of the form
   '(notename . alter) or '((octave . notename) . (alter barnum . measurepos))."
   (if (number? (car entry))
       (car entry)
   '(notename . alter) or '((octave . notename) . (alter barnum . measurepos))."
   (if (number? (car entry))
       (car entry)
@@ -1125,42 +1222,43 @@ specifies whether accidentals should be canceled in different octaves."
   (and (pair? (car entry)) (cdddr entry)))
 
 (define (key-entry-alteration entry)
   (and (pair? (car entry)) (cdddr entry)))
 
 (define (key-entry-alteration entry)
-  "Return the alteration of an entry in localKeySignature."
-  (if (number? (car entry))
-      (cdr entry)
-      (cadr entry)))
+  "Return the alteration of an entry in localKeySignature.
+
+For convenience, returns @code{0} if entry is @code{#f}."
+  (if entry
+      (if (number? (car entry))
+         (cdr entry)
+         (cadr entry))
+      0))
 
 (define-public (find-pitch-entry keysig pitch accept-global accept-local)
 
 (define-public (find-pitch-entry keysig pitch accept-global accept-local)
-  "Return the first entry in keysig that matches the pitch.
-  accept-global states whether key signature entries should be included.
-  accept-local states whether local accidentals should be included.
-  if no matching entry is found, #f is returned."
-  (if (pair? keysig)
-      (let* ((entry (car keysig))
-            (entryoct (key-entry-octave entry))
-            (entrynn (key-entry-notename entry))
-            (oct (ly:pitch-octave pitch))
-            (nn (ly:pitch-notename pitch)))
-       (if (and (equal? nn entrynn)
-                (or (and accept-global (equal? #f entryoct))
-                    (and accept-local (equal? oct entryoct))))
-           entry
-           (find-pitch-entry (cdr keysig) pitch accept-global accept-local)))
-      #f))
+  "Return the first entry in @var{keysig} that matches @var{pitch}.
+@var{accept-global} states whether key signature entries should be included.
+@var{accept-local} states whether local accidentals should be included.
+If no matching entry is found, @var{#f} is returned."
+  (and (pair? keysig)
+       (let* ((entry (car keysig))
+             (entryoct (key-entry-octave entry))
+             (entrynn (key-entry-notename entry))
+             (oct (ly:pitch-octave pitch))
+             (nn (ly:pitch-notename pitch)))
+        (if (and (equal? nn entrynn)
+                 (or (and accept-global (not entryoct))
+                     (and accept-local (equal? oct entryoct))))
+            entry
+            (find-pitch-entry (cdr keysig) pitch accept-global accept-local)))))
 
 (define-public (neo-modern-accidental-rule context pitch barnum measurepos)
 
 (define-public (neo-modern-accidental-rule context pitch barnum measurepos)
-  "an accidental rule that typesets an accidental if it differs from the key signature
-   AND does not directly follow a note on the same staff-line.
-   This rule should not be used alone because it does neither look at bar lines
-   nor different accidentals at the same notename"
+  "An accidental rule that typesets an accidental if it differs from the
+key signature @emph{and} does not directly follow a note on the same
+staff line.  This rule should not be used alone because it does neither
+look at bar lines nor different accidentals at the same note name."
   (let* ((keysig (ly:context-property context 'localKeySignature))
         (entry (find-pitch-entry keysig pitch #t #t)))
   (let* ((keysig (ly:context-property context 'localKeySignature))
         (entry (find-pitch-entry keysig pitch #t #t)))
-    (if (equal? #f entry)
+    (if (not entry)
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #t #f))
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #t #f))
-              (key-acc (if (equal? global-entry #f)
-                           0
-                           (key-entry-alteration global-entry)))
+              (key-acc (key-entry-alteration global-entry))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
@@ -1168,17 +1266,15 @@ specifies whether accidentals should be canceled in different octaves."
                            (and (equal? entrybn barnum) (equal? entrymp measurepos)))))))))
 
 (define-public (teaching-accidental-rule context pitch barnum measurepos)
                            (and (equal? entrybn barnum) (equal? entrymp measurepos)))))))))
 
 (define-public (teaching-accidental-rule context pitch barnum measurepos)
-  "an accidental rule that typesets a cautionary accidental
-  if it is included in the key signature AND does not directly follow
-  a note on the same staff-line."
+  "An accidental rule that typesets a cautionary accidental if it is
+included in the key signature @emph{and} does not directly follow a note
+on the same staff line."
   (let* ((keysig (ly:context-property context 'localKeySignature))
         (entry (find-pitch-entry keysig pitch #t #t)))
   (let* ((keysig (ly:context-property context 'localKeySignature))
         (entry (find-pitch-entry keysig pitch #t #t)))
-    (if (equal? #f entry)
+    (if (not entry)
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #f #f))
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #f #f))
-              (key-acc (if (equal? global-entry #f)
-                           0
-                           (key-entry-alteration global-entry)))
+              (key-acc (key-entry-alteration global-entry))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
@@ -1198,15 +1294,15 @@ specifies whether accidentals should be canceled in different octaves."
    context))
 
 (define-public (set-accidental-style style . rest)
    context))
 
 (define-public (set-accidental-style style . rest)
-  "Set accidental style to STYLE. Optionally takes a context argument,
-e.g. 'Staff or 'Voice. The context defaults to Staff, except for piano styles, which
-use GrandStaff as a context. "
+  "Set accidental style to @var{style}.  Optionally take a context
+argument, e.g. @code{'Staff} or @code{'Voice}.  The context defaults
+to @code{Staff}, except for piano styles, which use @code{GrandStaff}
+as a context."
   (let ((context (if (pair? rest)
                     (car rest) 'Staff))
        (pcontext (if (pair? rest)
                      (car rest) 'GrandStaff)))
   (let ((context (if (pair? rest)
                     (car rest) 'Staff))
        (pcontext (if (pair? rest)
                      (car rest) 'GrandStaff)))
-    (ly:export
-     (cond
+    (cond
       ;; accidentals as they were common in the 18th century.
       ((equal? style 'default)
        (set-accidentals-properties #t
       ;; accidentals as they were common in the 18th century.
       ((equal? style 'default)
        (set-accidentals-properties #t
@@ -1359,12 +1455,42 @@ use GrandStaff as a context. "
                                   context))
       (else
        (ly:warning (_ "unknown accidental style: ~S") style)
                                   context))
       (else
        (ly:warning (_ "unknown accidental style: ~S") style)
-       (make-sequential-music '()))))))
+       (make-sequential-music '())))))
+
+(define-public (invalidate-alterations context)
+  "Invalidate alterations in @var{context}.
+
+Elements of @code{'localKeySignature} corresponding to local
+alterations of the key signature have the form
+@code{'((octave . notename) . (alter barnum . measurepos))}.
+Replace them with a version where @code{alter} is set to @code{'clef}
+to force a repetition of accidentals.
+
+Entries that conform with the current key signature are not invalidated."
+  (let* ((keysig (ly:context-property context 'keySignature)))
+    (set! (ly:context-property context 'localKeySignature)
+         (map-in-order
+          (lambda (entry)
+            (let* ((localalt (key-entry-alteration entry))
+                   (localoct (key-entry-octave entry)))
+              (if (or (accidental-invalid? localalt)
+                      (not localoct)
+                      (= localalt
+                         (key-entry-alteration
+                          (find-pitch-entry
+                           keysig
+                           (ly:make-pitch localoct
+                                          (key-entry-notename entry)
+                                          0)
+                           #t #t))))
+                  entry
+                  (cons (car entry) (cons 'clef (cddr entry))))))
+          (ly:context-property context 'localKeySignature)))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (skip-of-length mus)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (skip-of-length mus)
-  "Create a skip of exactly the same length as MUS."
+  "Create a skip of exactly the same length as @var{mus}."
   (let* ((skip
          (make-music
           'SkipEvent
   (let* ((skip
          (make-music
           'SkipEvent
@@ -1373,7 +1499,7 @@ use GrandStaff as a context. "
     (make-event-chord (list (ly:music-compress skip (ly:music-length mus))))))
 
 (define-public (mmrest-of-length mus)
     (make-event-chord (list (ly:music-compress skip (ly:music-length mus))))))
 
 (define-public (mmrest-of-length mus)
-  "Create a mmrest of exactly the same length as MUS."
+  "Create a multi-measure rest of exactly the same length as @var{mus}."
 
   (let* ((skip
          (make-multi-measure-rest
 
   (let* ((skip
          (make-multi-measure-rest
@@ -1382,20 +1508,25 @@ use GrandStaff as a context. "
     skip))
 
 (define-public (pitch-of-note event-chord)
     skip))
 
 (define-public (pitch-of-note event-chord)
+  (let ((evs (filter (lambda (x)
+                      (music-has-type x 'note-event))
+                    (ly:music-property event-chord 'elements))))
 
 
-  (let*
-      ((evs (filter (lambda (x) (memq 'note-event (ly:music-property x 'types)))
-                   (ly:music-property event-chord 'elements))))
+    (and (pair? evs)
+        (ly:music-property (car evs) 'pitch))))
+
+(define-public (duration-of-note event-chord)
+  (let ((evs (filter (lambda (x)
+                      (music-has-type x 'rhythmic-event))
+                    (ly:music-property event-chord 'elements))))
 
 
-    (if (pair? evs)
-       (ly:music-property (car evs) 'pitch)
-       #f)))
+    (and (pair? evs)
+        (ly:music-property (car evs) 'duration))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (extract-named-music music music-name)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (extract-named-music music music-name)
-"Return a flat list of all music named @code{music-name}
-from @code{music}."
+  "Return a flat list of all music named @var{music-name} from @var{music}."
    (let ((extracted-list
           (if (ly:music? music)
               (if (eq? (ly:music-property music 'name) music-name)
    (let ((extracted-list
           (if (ly:music? music)
               (if (eq? (ly:music-property music 'name) music-name)
@@ -1413,12 +1544,12 @@ from @code{music}."
      (flatten-list extracted-list)))
 
 (define-public (event-chord-notes event-chord)
      (flatten-list extracted-list)))
 
 (define-public (event-chord-notes event-chord)
-"Return a list of all notes from @{event-chord}."
+  "Return a list of all notes from @var{event-chord}."
   (filter
     (lambda (m) (eq? 'NoteEvent (ly:music-property m 'name)))
     (ly:music-property event-chord 'elements)))
 
 (define-public (event-chord-pitches event-chord)
   (filter
     (lambda (m) (eq? 'NoteEvent (ly:music-property m 'name)))
     (ly:music-property event-chord 'elements)))
 
 (define-public (event-chord-pitches event-chord)
-"Return a list of all pitches from @{event-chord}."
+  "Return a list of all pitches from @var{event-chord}."
   (map (lambda (x) (ly:music-property x 'pitch))
        (event-chord-notes event-chord)))
   (map (lambda (x) (ly:music-property x 'pitch))
        (event-chord-notes event-chord)))