-1.3.58.jcn2
+1.3.58.hwn1
+===========
+
+* Rewrote key sig support. Now key signature can also be controlled
+by setting keySignature and localKeySignature properties, eg.
+
+ \property keySignature = #'((2 . -1) ( 4 . -1) (6 . -1))
+
+sets a key signature of `es ges bes' (an unusual key signature).
+
+Keys are internally represented as transpositions of the c-major
+scale. Printing the key signature for a scale is done by filtering out
+all non-natural accidentals.
+
+* Removed support for \keysignature, and \key something \minor; Newkey
+is now obsolete.
+
+1.3.58.jcn3
===========
* Fixed pedal items (hw)
* Replaced one scm_assoc () u-turn slipped through jcn1
-1.3.58.jcn1
-===========
+* various GUILE 1.3.5 compile fixes
* Added `Ped' as a compound symbol font and removed silly scheme kerning.
PACKAGE_NAME=LilyPond
MAJOR_VERSION=1
MINOR_VERSION=3
-PATCH_LEVEL=58
-MY_PATCH_LEVEL=jcn2
+PATCH_LEVEL=59
+MY_PATCH_LEVEL=
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
ac_help="$ac_help
with-lang=LANG use LANG as language to emit messages"
ac_help="$ac_help
- enable-tex-tfmdir=DIR set the tex-directory where cmr10.tfm lives (default: use kpsewhich)"
+ enable-tfm-path=PATH set path of tex directories where tfm files live, esp.: cmr10.tfm (default: use kpsewhich)"
# Initialize some variables set by options.
# The variables have the same names as the options, with
- # Check whether --enable-tex-tfmdir or --disable-tex-tfmdir was given.
-if test "${enable_tex_tfmdir+set}" = set; then
- enableval="$enable_tex_tfmdir"
- TFMDIR=$enableval
+ # Check whether --enable-tfm-path or --disable-tfm-path was given.
+if test "${enable_tfm_path+set}" = set; then
+ enableval="$enable_tfm_path"
+ tfm_path=$enableval
else
- TFMDIR=auto
+ tfm_path=auto
fi
done
test -n "$KPSEWHICH" || KPSEWHICH="no"
- echo $ac_n "checking for TeX TFM directory""... $ac_c" 1>&6
-echo "configure:2654: checking for TeX TFM directory" >&5
- if test "x$TFMDIR" = xauto ; then
- if test "x$TEX_TFMDIR" = "x" ; then
- if test "x$KPSEWHICH" != "xno" ; then
- CMR10=`kpsewhich tfm cmr10.tfm`
- TEX_TFMDIR=`dirname $CMR10`
- else
-
- echo "configure: warning: Please set TEX_TFMDIR (to where cmr10.tfm lives):
- TEX_TFMDIR=/usr/local/TeX/lib/tex/fonts ./configure" 1>&2
+ echo $ac_n "checking for tfm path""... $ac_c" 1>&6
+echo "configure:2654: checking for tfm path" >&5
+
+ TFM_FONTS="cmr msam"
+
+ if test "x$tfm_path" = xauto ; then
+ if test "x$KPSEWHICH" != "xno" ; then
+ for i in $TFM_FONTS; do
+ dir=`$KPSEWHICH tfm ${i}10.tfm`
+ TFM_PATH="$TFM_PATH `dirname $dir`"
+ done
+ else
+
+ echo "configure: warning: Please specify where cmr10.tfm lives:
+ ./configure --enable-tfm-path=/usr/local/TeX/lib/tex/fonts" 1>&2
warn_b=yes
- fi
fi
+ else
+ TFM_PATH=$tfm_path
fi
- echo "$ac_t""$TEX_TFMDIR" 1>&6
+
+ TFM_PATH=`echo $TFM_PATH | tr ':' ' '`
+ echo "$ac_t""$TFM_PATH" 1>&6
## First, let's just see if we can find Guile at all.
echo $ac_n "checking "for guile-config"""... $ac_c" 1>&6
-echo "configure:2675: checking "for guile-config"" >&5
+echo "configure:2682: checking "for guile-config"" >&5
for guile_config in guile-config $target-guile-config $build-guile-config; do
echo "$ac_t"""$guile_config"" 1>&6
if ! $guile_config --version > /dev/null 2>&1 ; then
echo "configure: warning: "cannot execute $guile_config"" 1>&2
echo $ac_n "checking "if we are cross compiling"""... $ac_c" 1>&6
-echo "configure:2681: checking "if we are cross compiling"" >&5
+echo "configure:2688: checking "if we are cross compiling"" >&5
guile_config=error
else
break
exit 1
fi
echo $ac_n "checking "Guile version"""... $ac_c" 1>&6
-echo "configure:2692: checking "Guile version"" >&5
+echo "configure:2699: checking "Guile version"" >&5
need_guile_version="1.3.4"
guile_version=`expr "\`$guile_config --version 2>&1\`" : ".*\($need_guile_version\).*"`
echo "$ac_t"""$guile_version"" 1>&6
## The GUILE_FLAGS macro.
echo $ac_n "checking for Guile""... $ac_c" 1>&6
-echo "configure:2705: checking for Guile" >&5
- if $guile_config link > /dev/null ; then
- :
- else
+echo "configure:2712: checking for Guile" >&5
+ if ! $guile_config link > /dev/null ; then
echo "$ac_t"""cannot execute $guile_config"" 1>&6
{ echo "configure: error: "cannot find guile-config; is Guile installed?"" 1>&2; exit 1; }
exit 1
# Extract the first word of "guile", so it can be a program name with args.
set dummy guile; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2722: checking for $ac_word" >&5
+echo "configure:2727: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GUILE'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:2760: checking for 8-bit clean memcmp" >&5
+echo "configure:2765: checking for 8-bit clean memcmp" >&5
if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_func_memcmp_clean=no
else
cat > conftest.$ac_ext <<EOF
-#line 2768 "configure"
+#line 2773 "configure"
#include "confdefs.h"
#ifdef __cplusplus
extern "C" void exit(int);
}
EOF
-if { (eval echo configure:2781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2786: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memcmp_clean=yes
else
test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:2799: checking for vprintf" >&5
+echo "configure:2804: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2804 "configure"
+#line 2809 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
; return 0; }
EOF
-if { (eval echo configure:2830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:2854: checking for _doprnt" >&5
+echo "configure:2859: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2859 "configure"
+#line 2864 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
; return 0; }
EOF
-if { (eval echo configure:2885: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2890: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
for ac_func in memmem snprintf vsnprintf gettext isinf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2912: checking for $ac_func" >&5
+echo "configure:2917: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2917 "configure"
+#line 2922 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:2943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2982: checking for $ac_word" >&5
+echo "configure:2987: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3015: checking for $ac_word" >&5
+echo "configure:3020: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
s%@MFPLAIN_MP@%$MFPLAIN_MP%g
s%@INIMETAPOST_FLAGS@%$INIMETAPOST_FLAGS%g
s%@KPSEWHICH@%$KPSEWHICH%g
-s%@TEX_TFMDIR@%$TEX_TFMDIR%g
+s%@TFM_PATH@%$TFM_PATH%g
s%@GUILE_CFLAGS@%$GUILE_CFLAGS%g
s%@GUILE_LDFLAGS@%$GUILE_LDFLAGS%g
s%@GUILE@%$GUILE%g
\notes \relative c''
{
\property Staff. createKeyOnClefChange = ##t
- \key bes; c2 \key c \minor; c2
+ \key bes; c2
+% \key c ; % \minor;
+ \key es ; % \minor;
+ c2
\break
- \key bes \major; c2 \clef alto; c2 \key d; c1
+ \key bes ; % \major;
+ c2 \clef alto; c2 \key d; \clef treble; c2
+ \property Staff. keySignature = #'((2 . -1) (6 . -1) (4 . -1))
+ e2
}
}
[cis8 d e f] [e! a b cis'] |
es e f e a a' a a' |
\clef "bass"; }
- [es16 c' b a] [g f es d] [c d es d] [c Bes As G] |
+ [es16 c' b a] [g f es d] [c d es d] [c bes, as, g,] |
\clef "violin";
\keysignature c;
}
-Audio_key::Audio_key (Key_def const& k)
+Audio_key::Audio_key () // Key_def const& k)
{
- key_ = k;
+ //fixme.
}
Audio_dynamic::Audio_dynamic (Real volume)
SCM one (get_property ("beatLength"));
Moment end_mom;
- if (SMOB_IS_TYPE_B(Moment, one))
- end_mom = *SMOB_TO_TYPE (Moment, one);
+ if (unsmob_moment (one))
+ end_mom = *unsmob_moment (one);
/*
second guess: property generic time exception
*/
SCM begin = get_property (time_str + "beamAutoBegin");
- if (SMOB_IS_TYPE_B(Moment, begin))
- begin_mom = * SMOB_TO_TYPE(Moment, begin);
+ if (unsmob_moment (begin))
+ begin_mom = * unsmob_moment (begin);
SCM end = get_property (time_str + "beamAutoEnd");
- if (SMOB_IS_TYPE_B (Moment, end))
- end_mom = * SMOB_TO_TYPE(Moment,end);
+ if (unsmob_moment (end))
+ end_mom = * unsmob_moment (end);
/*
third guess: property time exception, specific for duration type
if (type_str.length_i ())
{
SCM end_mult = get_property ( time_str + "beamAutoEnd" + type_str);
- if (SMOB_IS_TYPE_B (Moment, end_mult))
- end_mom = * SMOB_TO_TYPE (Moment,end_mult);
+ if (unsmob_moment (end_mult))
+ end_mom = * unsmob_moment (end_mult);
SCM begin_mult = get_property (time_str + "beamAutoBegin" + type_str);
- if (SMOB_IS_TYPE_B (Moment, begin_mult))
- begin_mom = * SMOB_TO_TYPE (Moment,begin_mult);
+ if (unsmob_moment (begin_mult))
+ begin_mom = * unsmob_moment (begin_mult);
}
/*
fourth guess [user override]: property plain generic
*/
begin = get_property ("beamAutoBegin");
- if (SMOB_IS_TYPE_B(Moment, begin))
- begin_mom = * SMOB_TO_TYPE(Moment, begin);
+ if (unsmob_moment (begin))
+ begin_mom = * unsmob_moment (begin);
end = get_property ("beamAutoEnd");
- if (SMOB_IS_TYPE_B (Moment, end))
- end_mom = * SMOB_TO_TYPE (Moment,end);
+ if (unsmob_moment (end))
+ end_mom = * unsmob_moment (end);
/*
fifth guess [user override]: property plain, specific for duration type
if (type_str.length_i ())
{
SCM end_mult = get_property (String ("beamAutoEnd") + type_str);
- if (SMOB_IS_TYPE_B (Moment, end_mult))
- end_mom = * SMOB_TO_TYPE (Moment,end_mult);
+ if (unsmob_moment (end_mult))
+ end_mom = * unsmob_moment (end_mult);
SCM begin_mult = get_property (String ("beamAutoBegin") + type_str);
- if (SMOB_IS_TYPE_B (Moment, begin_mult))
- begin_mom = * SMOB_TO_TYPE (Moment,begin_mult);
+ if (unsmob_moment (begin_mult))
+ begin_mom = * unsmob_moment (begin_mult);
}
Rational r;
}
SCM symbol = gh_car (extra_space);
- Real spc = gh_scm2double (SCM_CADR(extra_space));
+ Real spc = gh_scm2double (gh_cadr(extra_space));
spc *= interline;
dists.push(spc);
Key_change_req::Key_change_req (Key_change_req const&s)
: Request (s)
{
- key_ = s.key_ ? new Key_def (*s.key_) : 0;
+ key_ = s.key_ ? new Newkey_def (*s.key_) : 0;
}
Key_change_req::~Key_change_req ()
#ifndef AUDIO_ITEM_HH
#define AUDIO_ITEM_HH
- #include <typeinfo>
+#include <typeinfo>
#include "lily-proto.hh"
#include "string.hh"
#include "audio-element.hh"
-#include "key-def.hh"
+
#include "musical-pitch.hh"
#include "moment.hh"
#include "drul-array.hh"
class Audio_key : public Audio_item
{
public:
- Audio_key (Key_def const& key);
-
- Key_def key_;
+ Audio_key (); //Newkey_def const& key);
+ // FIXME
};
class Audio_instrument : public Audio_item
#include "array.hh"
#include "duration.hh"
#include "musical-pitch.hh"
-#include "key-def.hh"
+#include "newkey-def.hh"
#include "protected-scm.hh"
class Break_req : public Request {
Routines for sharps and flats are separated,
so that caller may identify non-conventional keys.
*/
+/*
+ UGH!
+ */
class Key_change_req : public Request
{
public:
Key_change_req ();
~Key_change_req();
Key_change_req(Key_change_req const &);
- Key_def *key_;
+ Newkey_def *key_;
protected:
VIRTUAL_COPY_CONS(Music);
for (SCM s = elt->get_elt_pointer (name); gh_pair_p (s); s = gh_cdr (s))
{
SCM e = gh_car (s);
- assert (SMOB_IS_TYPE_B(Score_element,e));
- Score_element* se = SMOB_TO_TYPE(Score_element, e);
- arr.push (dynamic_cast<T*> (se));
+ arr.push (dynamic_cast<T*> (unsmob_element (e)));
}
arr.reverse ();
-/*
- key-def.hh -- declare Key_def
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2000 Jan Nieuwenhuizen <janneke@gnu.org>
-
- */
-#ifndef KEY_DEF_HH
-#define KEY_DEF_HH
-
-#include "array.hh"
-#include "musical-pitch.hh"
-
-/**
- Universal key definition (Should rename class Key to 'Accidentals'?)
-
- FIXME: merge key.hh and key-def.hh classes.
-
- FIXME: use Scheme data structs for this.
- */
-class Key_def
-{
-public:
- Key_def ();
-
- Array<Musical_pitch> pitch_arr_;
- int modality_i_;
- bool ordinary_key_b_;
-
- /// squash the octaves to 1
- void squash_octaves ();
-
- /// return number accidentals in key; ordinary key only
- int ordinary_accidentals_i () const;
-
- /// return number of flats in key
- int flats_i () const;
-
- /// return number of sharps in key
- int sharps_i () const;
-
- /// modality == 3
- bool minor_b () const;
-
- void transpose (Musical_pitch d);
-};
-
-#endif /* KEY_DEF_HH */
+#error
#ifndef KEYGRAV_HH
#define KEYGRAV_HH
-
-#include "engraver.hh"
-
-#include "musical-pitch.hh"
-#include "protected-scm.hh"
-#include "newkey.hh"
-
-
-/**
- Make the key signature.
- */
-class Key_engraver : public Engraver {
- void create_key(bool);
- void read_req (Key_change_req const * r);
-
-public:
- Key_engraver();
-
- VIRTUAL_COPY_CONS(Translator);
-
- /*
- TODO: move these into properties.
- */
- Newkey key_;
- Key_change_req * keyreq_l_;
- Key_item * item_p_;
-
- Protected_scm old_accs_;
- Protected_scm new_accs_;
-
- bool key_changed_b() const;
-
-protected:
- virtual bool do_try_music (Music *req_l);
- virtual void do_process_music();
- virtual void do_pre_move_processing();
- virtual void do_post_move_processing();
- virtual void acknowledge_element (Score_element_info);
-};
-
+#error
#endif // KEYGRAV_HH
~Key_performer();
protected:
- void do_print() const;
virtual bool do_try_music (Music* req_l);
virtual void do_process_music ();
virtual void do_pre_move_processing ();
#ifndef SCM_PACK
#define SCM_PACK(x) ((SCM) x)
-#endif
+#endif
+#ifndef SCM_UNPACK
+#define SCM_UNPACK(x) ( x)
+#endif
/*
conversion functions follow the GUILE naming convention, i.e.
+++ /dev/null
-/*
- local-key-engraver.hh -- declare Local_key_engraver
-
- (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-
-
-#ifndef LOCALKEYGRAV_HH
-#define LOCALKEYGRAV_HH
-
-#endif // LOCALKEYGRAV_HH
--- /dev/null
+/*
+ newkey-def.hh -- declare Newkey_def
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#ifndef NEWKEY_DEF_HH
+#define NEWKEY_DEF_HH
+
+#include "protected-scm.hh"
+#include "musical-pitch.hh"
+
+class Newkey_def
+{
+
+public:
+ Protected_scm pitch_alist_;
+
+ Newkey_def();
+
+ /// return number of flats in key
+ int flats_i () const;
+
+ /// return number of sharps in key
+ int sharps_i () const;
+ int accs_i (int) const;
+
+ void transpose (Musical_pitch d);
+};
+
+#endif /* NEWKEY_DEF_HH */
+
+
+++ /dev/null
-/*
- newkey.hh -- declare Newkey
-
- source file of the GNU LilyPond music typesetter
-
- (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
- */
-
-#ifndef NEWKEY_HH
-#define NEWKEY_HH
-
-#include "protected-scm.hh"
-
-class Newkey
-{
- /*
- alist mapping
- (octave . notename) -> accidental and notename -> accidental
- */
- Protected_scm key_alist_;
-public:
- void set (int name, int acc);
- void set (int oct, int name, int acc);
- void clear ();
- void set_scm (SCM k, SCM v);
- Newkey();
- int get (int oct, int name);
- int get (int name);
-};
-#endif /* NEWKEY_HH */
-
SCM self_scm_;
+#ifndef SCM_CELL_TYPE
+#define SCM_CELL_TYPE(X) SCM_CAR(X)
+#endif
+
+#ifndef SCM_CELL_WORD_1
+#define SCM_CELL_WORD_1(X) SCM_CDR(X)
+#endif
+
/**
Check if S is of the specified C++ class.
*/
-#define SMOB_IS_TYPE_B(TYPE, S) (SCM_NIMP((S)) && SCM_CAR((S)) == TYPE::smob_tag_)
+#define SMOB_IS_TYPE_B(TYPE, S) (SCM_NIMP(S) && SCM_CELL_TYPE(S) == TYPE::smob_tag_)
/// Cast S. No checks are done.
-#define SMOB_TO_TYPE(TYPE, S) ((TYPE*) SCM_CDR((S)))
+#define SMOB_TO_TYPE(TYPE, S) ((TYPE*) SCM_CELL_WORD_1(S))
#endif /* SMOBS_HH */
+++ /dev/null
-/*
- key-def.cc -- implement Key_def
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2000 Jan Nieuwenhuizen <janneke@gnu.org>
-
- */
-
-#include "key-def.hh"
-#include "debug.hh"
-
-Key_def::Key_def ()
-{
- modality_i_ = 0;
- ordinary_key_b_ = false;
-}
-
-int
-Key_def::ordinary_accidentals_i () const
-{
- if (!ordinary_key_b_)
- {
- programming_error ("Accidentals requested for non-conventional key");
- return 0;
- }
-
- int p;
- if (pitch_arr_.size () < 1)
- {
- warning (_ ("No key name, assuming `C'"));
- p = 0;
- }
- else
- {
- p = pitch_arr_[0].semitone_pitch ();
- p += modality_i_;
- }
- /* Solve the equation 7*accidentals_i mod 12 = p, -6 <= accidentals_i <= 5 */
- int accidentals_i = (7*p) % 12;
- accidentals_i = (accidentals_i + 18) % 12 -6;
-
- /* Correct from flats to sharps or vice versa */
- if (accidentals_i * pitch_arr_[0].accidental_i_ < 0)
- accidentals_i += 12 * sign (pitch_arr_[0].accidental_i_);
- return accidentals_i;
-}
-
-int
-Key_def::flats_i () const
-{
- if (ordinary_key_b_)
- return 0 >? -ordinary_accidentals_i ();
- int flats_i = 0;
- for (int i = 0; i < pitch_arr_.size (); i++)
- {
- if (pitch_arr_[i].accidental_i_ < 0)
- flats_i -= pitch_arr_[i].accidental_i_;
- }
- return flats_i;
-}
-
-bool
-Key_def::minor_b () const
-{
- return modality_i_ == 3;
-}
-
-int
-Key_def::sharps_i () const
-{
- if (ordinary_key_b_)
- return 0 >? ordinary_accidentals_i ();
- int sharps_i = 0;
- for (int i = 0; i < pitch_arr_.size (); i++)
- {
- if (pitch_arr_[i].accidental_i_ > 0)
- sharps_i += pitch_arr_[i].accidental_i_;
- }
- return sharps_i;
-}
-
-void
-Key_def::transpose (Musical_pitch d)
-{
- if (ordinary_key_b_ )
- {
- if (pitch_arr_.size () > 0)
- pitch_arr_[0].transpose (d);
- else
- {
- warning (_ ("Don't know how handle empty keys")); // TODO
- }
- }
- else
- {
- Array<Musical_pitch> old_pitch_arr_;
- for (int i = 0; i < pitch_arr_.size (); i++)
- {
- old_pitch_arr_.push (pitch_arr_[i]);
- }
- // set accidentals for \key d (as in Key_engraver::read_req)
- // (later called "new accidentals")
- int p = d.semitone_pitch ();
- /* Solve the equation 7*accidentals_i mod 12 = p, -6 <= accidentals_i <= 5 */
- int accidentals_i = (7*p) % 12;
- accidentals_i = (accidentals_i + 18) % 12 -6;
-
- /* Correct from flats to sharps or vice versa */
- if (accidentals_i * d.accidental_i_ < 0)
- accidentals_i += 12 * sign (d.accidental_i_);
-
- pitch_arr_.clear ();
- if (accidentals_i < 0)
- {
- int accidental = 6 ; // First accidental: bes
- for ( ; accidentals_i < 0 ; accidentals_i++ )
- {
- Musical_pitch m;
- m.accidental_i_ = -1;
- m.notename_i_ = accidental;
- pitch_arr_.push (m);
-
- accidental = (accidental + 3) % 7 ;
- }
- }
- else
- {
- int accidental = 3 ; // First accidental: fis
- for ( ; accidentals_i > 0 ; accidentals_i-- )
- {
- Musical_pitch m;
- m.accidental_i_ = 1;
- m.notename_i_ = accidental;
- pitch_arr_.push (m);
-
- accidental = (accidental + 4) % 7 ;
- }
- }
- // Check if transposed old accidentals and the new ones coincide
- accidentals_i = pitch_arr_.size ();
- int acc_found;
- Musical_pitch mm;
- for (int i=0; i < old_pitch_arr_.size (); i++)
- {
- acc_found = 0;
- mm = old_pitch_arr_[i];
- mm.transpose (d);
- for (int j=0; ( (j < accidentals_i) && (acc_found == 0)); j++)
- {
- if (pitch_arr_[j].notename_i_ == mm.notename_i_)
- {
- if (mm.accidental_i_ == 0)
- {
- // remove new accidental
- pitch_arr_.del (j);
- accidentals_i--;
- acc_found = 1;
- }
- else
- {
- // change new accidental
- pitch_arr_[j].accidental_i_ = mm.accidental_i_;
- acc_found = 1;
- }
- }
- }
- if (acc_found == 0)
- {
- // add transposed old accidental
- pitch_arr_.push (mm);
- }
- }
- }
-}
-
-void
-Key_def::squash_octaves ()
-{
- for (int i=0; i < pitch_arr_.size (); i++)
- {
- pitch_arr_[i].octave_i_ = 0;
- }
-}
(c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
-#include "key-engraver.hh"
+
#include "key-item.hh"
#include "command-request.hh"
-#include "local-key-engraver.hh"
#include "musical-request.hh"
#include "local-key-item.hh"
#include "bar.hh"
#include "timing-translator.hh"
#include "staff-symbol-referencer.hh"
-
-/*
- this is a large mess. Please clean this to use Basic properties and
- Scheme data structs.
+#include "translator-group.hh"
+#include "engraver.hh"
+#include "musical-pitch.hh"
+#include "protected-scm.hh"
+#include "clef-item.hh"
+
+/**
+ Make the key signature.
*/
+class Key_engraver : public Engraver {
+ void create_key(bool);
+ void read_req (Key_change_req const * r);
+
+public:
+ Key_engraver();
+
+ VIRTUAL_COPY_CONS(Translator);
+
+ Key_change_req * keyreq_l_;
+ Key_item * item_p_;
+ Protected_scm old_accs_;
+
+protected:
+ virtual void do_creation_processing();
+ virtual bool do_try_music (Music *req_l);
+ virtual void do_process_music();
+ virtual void do_pre_move_processing();
+ virtual void do_post_move_processing();
+ virtual void acknowledge_element (Score_element_info);
+};
+
Key_engraver::Key_engraver ()
{
+ keyreq_l_ = 0;
item_p_ = 0;
- do_post_move_processing ();
-}
-
-bool
-Key_engraver::key_changed_b () const
-{
- return keyreq_l_ ;
}
void
// todo: put this in basic props.
item_p_->set_elt_property ("old-accidentals", old_accs_);
- item_p_->set_elt_property ("new-accidentals", new_accs_);
+ item_p_->set_elt_property ("new-accidentals", get_property ("keySignature"));
Staff_symbol_referencer_interface st (item_p_);
st.set_interface ();
void
Key_engraver::acknowledge_element (Score_element_info info)
{
- if (dynamic_cast <Clef_change_req *> (info.req_l_))
+ if (dynamic_cast <Clef_item *> (info.elem_l_))
{
SCM c = get_property ("createKeyOnClefChange");
if (to_boolean (c))
{
create_key (false);
-
}
}
else if (dynamic_cast<Bar *> (info.elem_l_)
- && gh_pair_p (new_accs_))
+ && gh_pair_p (get_property ("keySignature")))
{
create_key (true);
}
void
Key_engraver::do_process_music ()
{
- if (keyreq_l_)
+ if (keyreq_l_ || old_accs_ != get_property ("keySignature"))
{
create_key (false);
}
}
}
-
-/*
- TODO. Use properties; and this is too hairy.
- */
void
Key_engraver::read_req (Key_change_req const * r)
{
if (!r->key_)
return;
-
- key_.clear ();
- SCM prop = get_property ("keyOctaviation");
- bool multi = to_boolean (prop);
-
- SCM n = SCM_EOL;
-
- if (r->key_->ordinary_key_b_)
- {
- int no_of_acc = r->key_->ordinary_accidentals_i ();
- // Hmm, can't these be handled/constructed by Key_change_req?
- if (no_of_acc < 0)
- {
- int accidental = 6 ; // First accidental: bes
- for ( ; no_of_acc < 0 ; no_of_acc++ )
- {
- Musical_pitch m;
- m.accidental_i_ = -1;
- m.notename_i_ = accidental;
- if (multi)
- key_.set (m.octave_i_, m.notename_i_, m.accidental_i_);
- else
- key_.set (m.notename_i_, m.accidental_i_);
-
- SCM pair = gh_cons (gh_int2scm (m.notename_i_),
- gh_int2scm (m.accidental_i_));
- n = gh_cons (pair, n) ;
- accidental = (accidental + 3) % 7 ;
- }
- }
- else
- {
- int accidental = 3 ; // First accidental: fis
- for ( ; no_of_acc > 0 ; no_of_acc-- )
- {
- Musical_pitch m;
- m.accidental_i_ = 1;
- m.notename_i_ = accidental;
- if (multi)
- key_.set (m.octave_i_, m.notename_i_, m.accidental_i_);
- else
- key_.set (m.notename_i_, m.accidental_i_);
-
- SCM pair = gh_cons (gh_int2scm (m.notename_i_),
- gh_int2scm (m.accidental_i_));
- n = gh_cons (pair, n);
-
- accidental = (accidental + 4) % 7 ;
- }
- }
- }
- else // Special key
+ SCM n = scm_list_copy (r->key_->pitch_alist_);
+ SCM accs = SCM_EOL;
+ for (SCM s = get_property ("keyAccidentalOrder");
+ gh_pair_p (s); s = gh_cdr (s))
{
- for (int i = 0; i < r->key_->pitch_arr_.size (); i ++)
+ if (gh_pair_p (scm_member (gh_car (s), n)))
{
- Musical_pitch m_l =r->key_->pitch_arr_[i];
- if (multi)
- key_.set (m_l.octave_i_, m_l.notename_i_, m_l.accidental_i_);
- else
- key_.set (m_l.notename_i_, m_l.accidental_i_);
-
- SCM pair = gh_cons (gh_int2scm (m_l.notename_i_),
- gh_int2scm (m_l.accidental_i_));
- n = gh_cons (pair, n);
+ accs = gh_cons (gh_car (s), accs);
+ n = scm_delete_x (gh_car (s), n);
}
}
+ for (SCM s = n ; gh_pair_p (s); s = gh_cdr (s))
+ if (gh_scm2int (gh_cdar (s)))
+ accs = gh_cons (gh_car (s), accs);
- old_accs_ = new_accs_;
- new_accs_ = n;
-
+ old_accs_ = get_property ("keySignature");
+ daddy_trans_l_->set_property ("keySignature", accs);
}
void
Key_engraver::do_post_move_processing ()
{
keyreq_l_ = 0;
+ old_accs_ = get_property ("keySignature");
+}
+
+void
+Key_engraver::do_creation_processing ()
+{
+ daddy_trans_l_->set_property ("keySignature", SCM_EOL);
old_accs_ = SCM_EOL;
}
+
ADD_THIS_TRANSLATOR (Key_engraver);
#include "lookup.hh"
#include "staff-symbol-referencer.hh"
-const int FLAT_TOP_PITCH=2; /* fes,ges,as and bes typeset in lower octave */
-const int SHARP_TOP_PITCH=4; /* ais and bis typeset in lower octave */
-
Key_item::Key_item (SCM s)
: Item (s)
{
}
+/*
+ FIXME: too much hardcoding here.
+ */
+const int FLAT_TOP_PITCH=2; /* fes,ges,as and bes typeset in lower octave */
+const int SHARP_TOP_PITCH=4; /* ais and bis typeset in lower octave */
+
/*
FIXME: key-item should just get a list of (position, acc), and leave
#include "audio-item.hh"
-
-
ADD_THIS_TRANSLATOR (Key_performer);
Key_performer::Key_performer ()
{
}
-void
-Key_performer::do_print () const
-{
-#ifndef NPRINT
- if (key_req_l_)
- key_req_l_->print ();
-#endif
-}
-
void
Key_performer::do_process_music ()
{
if (key_req_l_ && key_req_l_->key_)
{
- audio_p_ = new Audio_key (*key_req_l_->key_);
+ audio_p_ = new Audio_key (); // *key_req_l_->key_);
Audio_element_info info (audio_p_, key_req_l_);
announce_element (info);
key_req_l_ = 0;
#include "musical-request.hh"
#include "command-request.hh"
-#include "local-key-engraver.hh"
#include "local-key-item.hh"
-#include "key-engraver.hh"
#include "debug.hh"
#include "key-item.hh"
#include "tie.hh"
virtual void process_acknowledged ();
virtual void do_removal_processing ();
public:
-
- Newkey local_key_;
+
+ SCM last_accs_;
Key_engraver *key_grav_l_;
Array<Note_req* > mel_l_arr_;
Array<Item*> support_l_arr_;
Local_key_engraver();
bool self_grace_b_;
Grace_align_item * grace_align_l_;
- Timing_translator * time_trans_l_ ;
};
key_grav_l_ = 0;
key_item_p_ =0;
grace_align_l_ =0;
- time_trans_l_ = 0;
+ last_accs_ = SCM_EOL;
}
+
void
Local_key_engraver::do_creation_processing ()
{
- /*
- UGHGUHGUH.
-
- Breaks if Key_engraver is removed from under us.
- */
- Translator * result =
- daddy_grav_l()->get_simple_translator ("Key_engraver");
-
- key_grav_l_ = dynamic_cast<Key_engraver *> (result);
-
- if (!key_grav_l_)
- {
- warning (_ ("out of tune:"));
- warning (_f ("can't find: `%s'", "Key_engraver"));
- }
- else
- {
- local_key_ = key_grav_l_->key_;
- }
-
- /*
- TODO
- (if we are grace) get key info from parent Local_key_engraver
- */
-
- Translator * tr = daddy_grav_l()->get_simple_translator ("Timing_engraver"); // ugh
- time_trans_l_ = dynamic_cast<Timing_translator*> (tr);
+ last_accs_ = get_property ("keySignature");
}
void
Local_key_engraver::process_acknowledged ()
{
+ SCM localsig = get_property ("localKeySignature");
+
if (!key_item_p_ && mel_l_arr_.size())
{
SCM f = get_property ("forgetAccidentals");
Item * support_l = support_l_arr_[i];
Note_req * note_l = mel_l_arr_[i];
+ int n = note_l->pitch_.notename_i_;
+ int o = note_l->pitch_.octave_i_;
+ int a = note_l->pitch_.accidental_i_;
+
/* see if there's a tie that "changes" the accidental */
/* works because if there's a tie, the note to the left
is of the same pitch as the actual note */
- int prev_acc =local_key_.get (note_l->pitch_.octave_i_,
- note_l->pitch_.notename_i_);
- bool different = prev_acc != note_l->pitch_.accidental_i_;
+ SCM prev = scm_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), localsig);
+ if (prev == SCM_BOOL_F)
+ prev = scm_assoc (gh_int2scm (n), localsig);
+ int prev_acc = (prev == SCM_BOOL_F) ? 0 : gh_scm2int (gh_cdr (prev));
+ bool different = prev_acc != a;
bool tie_changes = tied_l_arr_.find_l (support_l) && different;
if (!forget
- && (note_l->forceacc_b_
- || !different)
+ && (note_l->forceacc_b_ || different)
&& !tie_changes)
{
if (!key_item_p_)
}
- bool extra_natural
- = sign (prev_acc) * (prev_acc - note_l->pitch_.accidental_i_) == 1 ;
+ bool extra_natural =
+ sign (prev_acc) * (prev_acc - a) == 1
+ && abs(prev_acc) == 2;
key_item_p_->add_pitch (note_l->pitch_,
note_l->cautionary_b_,
if (!forget)
{
- local_key_.set (note_l->pitch_.octave_i_, note_l->pitch_.notename_i_,
- note_l->pitch_.accidental_i_);
+ localsig = scm_assoc_set_x (localsig, gh_cons (gh_int2scm (o),
+ gh_int2scm (n)),
+ gh_int2scm (a));
+
#if 0
+ /*
+ TESTME!
+ */
if (!tied_l_arr_.find_l (support_l))
{
local_key_.clear_internal_forceacc (note_l->pitch_);
void
Local_key_engraver::do_removal_processing ()
{
- // TODO: signal accidentals to Local_key_engraver the
+ // TODO: if grace ? signal accidentals to Local_key_engraver the
}
void
SCM smp = get_property ("measurePosition");
Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
+ SCM sig = get_property ("keySignature");
if (!mp)
{
- if (!to_boolean (get_property ("noResetKey")) && key_grav_l_)
- local_key_= key_grav_l_->key_;
+ if (!to_boolean (get_property ("noResetKey")))
+ daddy_trans_l_->set_property ("localKeySignature", sig);
}
- else if (key_grav_l_ && key_grav_l_->key_changed_b ())
+ else if (last_accs_ != sig)
{
- local_key_ = key_grav_l_->key_;
+ daddy_trans_l_->set_property ("localKeySignature", sig);
}
}
String
Midi_key::str () const
{
- int sharps_i = audio_l_->key_.sharps_i ();
- int flats_i = audio_l_->key_.flats_i ();
+ // fxime.
+ int sharps_i = 0; //audio_l_->key_.sharps_i ();
+ int flats_i = 0; //audio_l_->key_.flats_i ();
// midi cannot handle non-conventional keys
if (flats_i && sharps_i)
String str = "ff5902";
str += String_convert::i2hex_str (accidentals_i, 2, '0');
- str += String_convert::i2hex_str ((int)audio_l_->key_.minor_b (), 2, '0');
+
+ // (int)audio_l_->key_.minor_b ()
+ str += String_convert::i2hex_str (0, 2, '0');
return String_convert::hex2bin_str (str);
}
{"in", IN_T},
{"lyrics", LYRICS},
{"key", KEY},
- {"keysignature", KEYSIGNATURE},
{"mark", MARK},
{"musicalpitch", MUSICAL_PITCH},
{"time", TIME_T},
{"relative", RELATIVE},
{"remove", REMOVE},
{"repeat", REPEAT},
- {"repetitions", REPETITIONS},
{"addlyrics", ADDLYRICS},
{"score", SCORE},
{"script", SCRIPT},
--- /dev/null
+/*
+ newkey-def.cc -- implement Newkey_def
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#include "newkey-def.hh"
+#include "misc.hh"
+
+
+Newkey_def::Newkey_def()
+{
+ pitch_alist_ = SCM_EOL;
+}
+
+void
+Newkey_def::transpose (Musical_pitch p)
+{
+ SCM newlist = SCM_EOL;
+ for (SCM s = pitch_alist_; gh_pair_p (s); s = gh_cdr (s))
+ {
+ SCM k = gh_caar (s);
+
+ if (gh_pair_p (k))
+ {
+ Musical_pitch orig (gh_list (gh_car (k), gh_cdr (k), gh_cdr (s), SCM_UNDEFINED));
+
+ orig.transpose (p);
+
+ SCM key = gh_cons (gh_int2scm (orig.octave_i_),
+ gh_int2scm (orig.notename_i_));
+
+ newlist = gh_cons (gh_cons (key, gh_int2scm (orig.accidental_i_)),
+ newlist);
+ }
+ else if (gh_number_p (k))
+ {
+ Musical_pitch orig (gh_list (gh_int2scm (0), k, gh_cdar (s), SCM_UNDEFINED));
+ orig.transpose (p);
+
+ SCM key =gh_int2scm (orig.notename_i_);
+ newlist = gh_cons (gh_cons (key, gh_int2scm (orig.accidental_i_)),
+ newlist);
+ }
+ }
+
+ pitch_alist_ = newlist;
+}
+++ /dev/null
-#include "newkey.hh"
-
-Newkey::Newkey ()
-{
- clear();
-}
-
-void
-Newkey::clear()
-{
- key_alist_ = SCM_EOL;
-}
-
-void
-Newkey::set (int n, int a)
-{
- set_scm (gh_int2scm (n), gh_int2scm (a));
-}
-
-void
-Newkey::set (int o, int n, int a)
-{
- set_scm (gh_cons (gh_int2scm (o),gh_int2scm(n)), gh_int2scm (a));
-}
-
-void
-Newkey::set_scm (SCM k, SCM v)
-{
- key_alist_
- = scm_assoc_set_x (key_alist_, k, v);
-}
-
-int
-Newkey::get (int o, int n)
-{
- SCM r = scm_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), key_alist_);
- return r == SCM_BOOL_F ? get (n) : gh_cdr (r);
-}
-
-int
-Newkey::get (int n)
-{
- SCM r = scm_assoc (gh_int2scm (n), key_alist_);
- return r == SCM_BOOL_F ? 0: gh_cdr (r);
-}
%token IN_T
%token INVALID
%token KEY
-%token KEYSIGNATURE
%token LYRICS
%token MARK
%token MEASURES
%token RELATIVE
%token REMOVE
%token REPEAT
-%token REPETITIONS
%token ADDLYRICS
%token SCM_T
%token SCORE
%type <i> tremolo_type
%type <i> int unsigned
%type <i> script_dir
-%type <i> optional_modality
+
%type <id> identifier_init
%type <duration> steno_duration optional_notemode_duration
%type <duration> entered_notemode_duration explicit_duration
%type <pitch> steno_musical_pitch musical_pitch absolute_musical_pitch
%type <pitch> steno_tonic_pitch
-%type <pitch_arr> pitch_list chord_additions chord_subtractions chord_notes chord_step
+%type <pitch_arr> chord_additions chord_subtractions chord_notes chord_step
%type <music> chord
%type <pitch> chord_note chord_inversion chord_bass
%type <midi> midi_block midi_body
key_p->key_ = 0;
$$ = key_p;
}
-/* UGH. optional. */
-
- | KEY NOTENAME_PITCH optional_modality {
- Key_change_req *key_p= new Key_change_req;
- Key_def d;
- d.pitch_arr_.push (*$2);
- d.ordinary_key_b_ = true;
- d.modality_i_ = $3;
-
- key_p->key_ = new Key_def (d);
- $$ = key_p;
- delete $2;
- }
- | KEYSIGNATURE pitch_list {
+/*
+TODO: Support for minor/major keys; make `major-scale' settable.
+*/
+ | KEY NOTENAME_PITCH {
Key_change_req *key_p= new Key_change_req;
- Key_def d;
- d.pitch_arr_ = *$2;
- d.ordinary_key_b_ = false;
-
- key_p->key_ = new Key_def(d);
- $$ = key_p;
- delete $2;
+ key_p->key_ = new Newkey_def;
+
+ key_p->key_->pitch_alist_ = scm_eval (ly_symbol2scm ("major-scale"));
+ key_p->key_->transpose (* $2);
+ $$ = key_p;
}
;
}
;
-optional_modality:
- /* empty */ {
- $$ = 0;
- }
- | int {
- $$ = $1;
- }
- ;
-
sup_quotes:
'\'' {
$$ = 1;
/*
UTILITIES
*/
+
+/*
+ FIXME: use scm.
+*/
+/*
pitch_list: {
$$ = new Array<Musical_pitch>;
}
delete $2;
}
;
-
+*/
int_list:
/**/ {
stop_moments_.push (m);
SCM s = get_property ("tupletSpannerDuration");
- if (SMOB_IS_TYPE_B(Moment, s))
- m = m <? (now_mom () + *SMOB_TO_TYPE(Moment,s));
+ if (unsmob_moment(s))
+ m = m <? (now_mom () + *unsmob_moment (s));
span_stop_moments_.push (m);
}
Moment tsd;
SCM s = get_property ("tupletSpannerDuration");
- if (SMOB_IS_TYPE_B(Moment, s))
- tsd = *SMOB_TO_TYPE(Moment,s);
+ if (unsmob_moment (s))
+ tsd = *unsmob_moment (s);
for (int i= started_span_p_arr_.size (); i--; )
{
defaultBarType = #"|"
systemStartDelimiterGlyph = #'bar-line
+ %
+ % what order to print accs. We could compute this,
+ % but computing is more work than putting it here.
+ %
+ % Flats come first, then sharps.
+ keyAccidentalOrder = #'(
+ (6 . -1) (2 . -1) (5 . -1 ) (1 . -1) (4 . -1) (0 . -1) (3 . -1)
+ (3 . 1) (0 . 1) (4 . 1) (1 . 1) (5 . 1) (2 . 1) (6 . 1)
+ )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% default settings, mainly for breakable items
% in alphabetical order
+ % TODO: uniform naming.;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basicBarlineProperties = #`(
(break-align-symbol . Staff_bar)
Begin3
Title: LilyPond
-Version: 1.3.58
-Entered-date: 08JUN00
+Version: 1.3.59
+Entered-date: 12JUN00
Description:
Keywords: music notation typesetting midi fonts engraving
Author: hanwen@cs.uu.nl (Han-Wen Nienhuys)
janneke@gnu.org (Jan Nieuwenhuizen)
Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys)
Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert
- 1000k lilypond-1.3.58.tar.gz
+ 1000k lilypond-1.3.59.tar.gz
Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/
- 1000k lilypond-1.3.58.tar.gz
+ 1000k lilypond-1.3.59.tar.gz
Copying-policy: GPL
End
Name: lilypond
-Version: 1.3.58
+Version: 1.3.59
Release: 1
Copyright: GPL
Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.58.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.59.tar.gz
Summary: A program for printing sheet music.
URL: http://www.cs.uu.nl/~hanwen/lilypond
# Icon: lilypond-icon.gif
)
)
+
+(define major-scale
+ '(
+ (0 . 0)
+ (1 . 0)
+ (2 . 0)
+ (3 . 0)
+ (4 . 0)
+ (5 . 0)
+ (6 . 0)
+ )
+ )