From b95222d4f362ff37c54f9130a7d94b368942dfac Mon Sep 17 00:00:00 2001
From: Han-Wen Nienhuys <hanwen@xs4all.nl>
Date: Fri, 15 Mar 2002 15:44:50 +0100
Subject: [PATCH] release: 1.5.41

---
 AUTHORS.txt                        |   4 +-
 ChangeLog                          |  42 ++++
 Documentation/regression-test.tely |   2 +
 Documentation/topdocs/AUTHORS.texi |   2 +-
 Documentation/user/refman.itely    |  30 ++-
 VERSION                            |   4 +-
 input/regression/pedal.ly          |  39 ++++
 input/test/pedal.ly                |  23 --
 lily/include/new-beam.hh           |   0
 lily/include/text-spanner.hh       |   2 +
 lily/new-beam.cc                   |   0
 lily/piano-pedal-engraver.cc       | 345 ++++++++++++++++++++++++-----
 lily/text-spanner.cc               | 117 +++++++++-
 lilypond-font-lock.el              |   2 +-
 ly/engraver-init.ly                |   5 +-
 make/out/lilypond.lsm              |   6 +-
 make/out/lilypond.mandrake.spec    |   2 +-
 make/out/lilypond.redhat.spec      |   4 +-
 make/out/lilypond.suse.spec        |   4 +-
 mf/feta-bolletjes.mf               |   4 +-
 mf/feta-eindelijk.mf               |  33 ++-
 mf/feta-generic.mf                 |   2 +-
 mf/feta-schrift.mf                 |  14 +-
 mf/feta-toevallig.mf               |  27 ++-
 scm/grob-description.scm           |  69 ++++--
 scm/grob-property-description.scm  |   4 +
 scm/interface-description.scm      |  13 +-
 scm/ps.scm                         |   4 +-
 28 files changed, 650 insertions(+), 153 deletions(-)
 create mode 100644 input/regression/pedal.ly
 delete mode 100644 input/test/pedal.ly
 delete mode 100644 lily/include/new-beam.hh
 delete mode 100644 lily/new-beam.cc

diff --git a/AUTHORS.txt b/AUTHORS.txt
index 12a58e4a6a..13884f19c6 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -27,8 +27,8 @@ list is alphabetically ordered.
 
    * Bjoern Jacke <bjoern.jacke@gmx.de>     German glossary stuff.
 
-   * Chris Jackson <chris@fluffhouse.org.uk>,     Emacs mode
-     indentation, directed arpeggios.
+   * Chris Jackson <chris@fluffhouse.org.uk>,     Piano pedals, Emacs
+     mode indentation, directed arpeggios.
 
    * Neil Jerram <nj104@cus.cam.ac.uk>.      parts of
      Documentation/Vocab*
diff --git a/ChangeLog b/ChangeLog
index ea09fe446f..5154a27c0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2002-03-15  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
+
+	* VERSION: 1.5.41 released
+	
+	* mf/feta-schrift.mf: make Tr. smaller, smoother and closer.  Use
+	optima serifs on top of t, bottom of r.
+
+	* mf/feta-bolletjes.mf: make ledger line rounder. 
+
+	* mf/feta-toevallig.mf: some smallish fixes for flat sign.
+
+	* mf/feta-eindelijk.mf: make 8th rest a little darker, some more
+	parametrization.
+
+2002-03-15 Chris Jackson <chris@fluffhouse.org.uk>
+ 
+       * lily/piano-pedal-engraver.cc: Rewritten to support bracketed as
+       well as text pedal indications and a combination of both.  All
+       pedal indications are horizontally aligned on a line spanner.
+ 
+       * lily/text-spanner.cc: Edge-width property added to use in
+       bracketed piano pedals. Function setup_sustain_pedal added to set
+       the dimensions of the brackets. 
+ 
+       * scm/grob-description.scm: New *PedalLineSpanner grobs added, and 
+       some of the *Pedal properties tweaked. 
+ 
+       * scm/grob-property-description.scm: New pedal-type (*Pedal) and
+       edge-width (TextSpanner) properties.
+ 
+       * ly/engraver-init.ly: Default strings added for SostenutoPedal. 
+ 
+       * lilypond-font-lock.el: sostenuto, unaCorda and treCorde added to
+       fontified identifiers list.
+ 
+       * input/test/pedal.ly: New pedal features added. 
+ 
+       * Documentation/user/refman.itely: New pedal features documented.
+       
+
 2002-03-15  Jan Nieuwenhuizen  <janneke@gnu.org>
 
 	* lily/include/new-beam.hh: Previously new-beam.hh
@@ -11,6 +51,8 @@
 	
 2002-03-14  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
 
+	* VERSION: 1.5.40
+
 	* mf/feta-eindelijk.mf: new 8th rest.
 
 	* mf/feta-toevallig.mf: small fixes for the sharp symbol. Don't
diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely
index 18a0520914..d35558ed0d 100644
--- a/Documentation/regression-test.tely
+++ b/Documentation/regression-test.tely
@@ -85,6 +85,8 @@ Accidentals are currently in a development stage.
 
 @lilypondfile[printfilename]{dynamics-unbound-hairpin.ly}
 
+@lilypondfile[printfilename]{pedal.ly}
+
 @section Chord names
 
 @lilypondfile[printfilename]{chord-names.ly}
diff --git a/Documentation/topdocs/AUTHORS.texi b/Documentation/topdocs/AUTHORS.texi
index c465d4a230..f7d94f655c 100644
--- a/Documentation/topdocs/AUTHORS.texi
+++ b/Documentation/topdocs/AUTHORS.texi
@@ -38,7 +38,7 @@ list is alphabetically ordered.
 @item @email{bjoern.jacke@@gmx.de, Bjoern Jacke}
     German glossary stuff.
 @item @email{chris@@fluffhouse.org.uk, Chris Jackson},
-    Emacs mode indentation, directed arpeggios.
+    Piano pedals, Emacs mode indentation, directed arpeggios.
 @item @email{nj104@@cus.cam.ac.uk, Neil Jerram}. 
     parts of Documentation/Vocab*
 @item @email{heikki.junes@@hut.fi, Heikki Junes}. 
diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely
index a1440e0e83..13eb20e0a4 100644
--- a/Documentation/user/refman.itely
+++ b/Documentation/user/refman.itely
@@ -1946,15 +1946,33 @@ c''4 \spanrequest \stop "Sustain"
 @end lilypond
 
 The symbols that are printed can be modified by setting
-@code{pedal@var{X}Strings}, where @var{X} is one of the pedal
-types. Refer to the generated documentation of @rgrob{PianoPedal} for
-more information.
+@code{pedal@var{X}Strings}, where @var{X} is one of the pedal types:
+Sustain, Sostenuto or UnaCorda.  Refer to the generated documentation of
+@rgrob{PianoPedal} for more information.
 
-@refbugs
+Pedals can also be indicated by a sequence of brackets, by setting the 
+@code{pedal-type} property of SustainPedal grobs: 
+
+@lilypond[fragment,verbatim]
+\property Staff.SustainPedal \override #'pedal-type = #'bracket
+c''4 \sustainDown d''4 e''4 a'4 \sustainUp \sustainDown f'4 g'4 a'4 \sustainUp
+@end lilypond
+
+A third style of pedal notation is a mixture of text and brackets,
+obtained by setting @code{pedal-type} to @code{mixed}:
 
+@lilypond[fragment,verbatim]
+\property Staff.SustainPedal \override #'pedal-type = #'mixed
+c''4 \sustainDown d''4 e''4 c'4 \sustainUp \sustainDown f'4 g'4 a'4 \sustainUp
+@end lilypond
+
+The default '*Ped' style for sustain and damper pedals corresponds to
+@code{\pedal-type = #'text}. However @code{mixed} is the default style
+for a sostenuto pedal:
 
-Currently, brackets are not supported, only text markings (i.e. `*Ped'
-style).
+@lilypond[fragment,verbatim]
+c''4 \sostenutoDown d''4 e''4 c'4 f'4 g'4 a'4 \sostenutoUp
+@end lilypond
 
 
 @c .   {Arpeggio}
diff --git a/VERSION b/VERSION
index be46e1e7bc..fc9b623800 100644
--- a/VERSION
+++ b/VERSION
@@ -1,8 +1,8 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=5
-PATCH_LEVEL=40
-MY_PATCH_LEVEL=jcn1
+PATCH_LEVEL=41
+MY_PATCH_LEVEL=
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
 # released version.
diff --git a/input/regression/pedal.ly b/input/regression/pedal.ly
new file mode 100644
index 0000000000..119f26a50d
--- /dev/null
+++ b/input/regression/pedal.ly
@@ -0,0 +1,39 @@
+\version "1.5.38"
+\header{
+texidoc = "Piano pedal symbols merge stop and start.  The strings are configurable. 
+Text style, bracket style, and a mixture of both are supported.  "
+}
+
+
+
+
+\score{
+\context Staff \notes\relative c'{
+
+c4 d e f g
+\sustainDown b c
+c, [d16  c  c c] [e e \sustainUp \sustainDown e e ] f4 \sustainUp 
+g\sustainDown  b \sustainUp c 
+\property Staff.pedalSustainStrings = #'("-" "-P" "P")
+\property Staff.SustainPedal \override #'padding = #-2
+c, \sustainDown d e \sustainUp \sustainDown f
+ \sustainUp g b c
+
+\property Staff.SustainPedal \override #'pedal-type = #'bracket
+
+c4 d e \sustainDown b c c, \sustainUp \sustainDown [d8 c] [e8 e \sustainUp \sustainDown] f4 d
+\sustainUp g \sustainDown b b, \sustainUp c'
+
+\property Staff.UnaCordaPedal \override #'pedal-type = #'mixed
+
+c4 d \unaCorda e f g
+ b \treCorde c
+
+
+}
+\paper{
+}
+\midi{
+\tempo 4 = 60
+}
+}
diff --git a/input/test/pedal.ly b/input/test/pedal.ly
deleted file mode 100644
index 3b21563bbc..0000000000
--- a/input/test/pedal.ly
+++ /dev/null
@@ -1,23 +0,0 @@
-\version "1.3.146"
-\header{
-texidoc = "Piano pedal symbols merge stop and start.  The strings are configurable. "
-}
-
-
-
-
-\score{
-\context Staff \notes\relative c'{
-c4\sustainDown d e f\sustainUp g\sustainDown b c
-c, [d16 \sustainUp \sustainDown c  c c] [e e \sustainUp \sustainDown e e ] f4 \sustainUp g\sustainDown b c
-\property Staff.pedalSustainStrings = #'("-" "-P" "P")
-\property Staff.SustainPedal \override #'padding = #2
-c, \sustainUp\sustainDown d e f
- \sustainUp g\sustainDown b c
-}
-\paper{
-}
-\midi{
-\tempo 4 = 60
-}
-}
diff --git a/lily/include/new-beam.hh b/lily/include/new-beam.hh
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/lily/include/text-spanner.hh b/lily/include/text-spanner.hh
index 97b43e4187..e7e85fcd23 100644
--- a/lily/include/text-spanner.hh
+++ b/lily/include/text-spanner.hh
@@ -17,6 +17,8 @@ class Text_spanner
 public:
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
   static bool has_interface (Grob*);
+private:
+  static void setup_pedal_bracket(Spanner *s);
 };
 
 #endif /* TEXT_SPANNER_HH */
diff --git a/lily/new-beam.cc b/lily/new-beam.cc
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/lily/piano-pedal-engraver.cc b/lily/piano-pedal-engraver.cc
index 36fcd1a732..2570e28075 100644
--- a/lily/piano-pedal-engraver.cc
+++ b/lily/piano-pedal-engraver.cc
@@ -4,6 +4,10 @@
   source file of the GNU LilyPond music typesetter
   
   (c) 2000--2002 Jan Nieuwenhuizen <janneke@gnu.org>
+  
+  Chris Jackson <chris@fluffhouse.org.uk> - extended to support
+  bracketed pedals.
+  TODO: support for __| |__ or __| Ped  instead of  ___/\__ for pedal up-down
  */
 
 #include "engraver.hh"
@@ -11,11 +15,13 @@
 #include "grob.hh"
 #include "item.hh"
 #include "lily-guile.hh"
-#include "rhythmic-head.hh"
-#include "stem.hh"
 #include "side-position-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "item.hh"
+#include "axis-group-interface.hh"
+#include "translator-group.hh"
+#include "directional-element-interface.hh"
+#include "note-column.hh"
 
 class Piano_pedal_engraver : public Engraver
 {
@@ -24,6 +30,7 @@ public:
   ~Piano_pedal_engraver ();
 protected:
   virtual void initialize ();
+  virtual void finalize ();
   virtual bool try_music (Music*);
   virtual void stop_translation_timestep ();
   virtual void start_translation_timestep ();
@@ -37,10 +44,21 @@ private:
     Span_req* start_req_l_;
     Drul_array<Span_req*> req_l_drul_;
     Item* item_p_;
+    Spanner* bracket_p_;     // A single portion of a pedal bracket
+    Spanner* finished_bracket_p_;
+    Spanner* line_spanner_;  // This grob contains all the pedals of the same type on the same staff
+    Spanner* finished_line_spanner_;
+    Span_req* current_bracket_req_;
   };
 
 
   Pedal_info *info_list_;
+
+  Spanner *previous_p_ [4]; // Record a stack of the current pedal spanners, so if more than one pedal
+  int nspanners_i;          // occurs simultaneously then extra space can be added between them.
+  void create_text_grobs (Pedal_info *p, SCM pedaltype);
+  void create_bracket_grobs (Pedal_info *p, SCM pedaltype);
+  void typeset_all();
 };
 
 
@@ -55,6 +73,10 @@ Piano_pedal_engraver::initialize ()
   info_list_ = new Pedal_info[4];
   Pedal_info *p = info_list_;
 
+  nspanners_i = 0;
+  for (int i = 0; i < 3; ++i)
+    previous_p_[i] = 0; 
+
 
   char * names [] = { "Sostenuto", "Sustain", "UnaCorda", 0  };
   char **np = names ;
@@ -62,6 +84,11 @@ Piano_pedal_engraver::initialize ()
     {
       p->name_ = *np;
       p->item_p_ = 0;
+      p->bracket_p_ = 0;
+      p->finished_bracket_p_ = 0;
+      p->line_spanner_ = 0;
+      p->finished_line_spanner_ = 0;
+      p->current_bracket_req_ = 0;
       p->req_l_drul_[START] = 0;
       p->req_l_drul_[STOP] = 0;
       p->start_req_l_ = 0;
@@ -85,20 +112,24 @@ Piano_pedal_engraver::acknowledge_grob (Grob_info info)
 {
   for (Pedal_info*p = info_list_; p && p->name_; p ++)
     {
-      if (p->item_p_)
+      Grob *g  = (Grob *) p->item_p_;
+      int i = 0; 
+      while ( i < 2 )
 	{
-	  if (Rhythmic_head::has_interface (info.grob_l_))
-	    {
-	      Side_position_interface::add_support (p->item_p_, info.grob_l_);
-
-	      if (Side_position_interface::get_axis (p->item_p_) == X_AXIS
-		  && !p->item_p_->get_parent (Y_AXIS))
-		p->item_p_->set_parent (info.grob_l_, Y_AXIS);
-	    }
-	  if (Stem::has_interface (info.grob_l_))
+	  if (g && p->line_spanner_) 
 	    {
-	      Side_position_interface::add_support (p->item_p_,info.grob_l_);
+	      if (Note_column::has_interface (info.grob_l_))
+		{
+		  Side_position_interface::add_support (p->line_spanner_, info.grob_l_);
+		  add_bound_item (p->line_spanner_,dynamic_cast<Item*> (info.grob_l_));
+		  
+		  if (Side_position_interface::get_axis (g) == X_AXIS
+		      && !g->get_parent (Y_AXIS))
+		    g->set_parent (info.grob_l_, Y_AXIS);
+		}
 	    }
+	  g = (Grob *) p->bracket_p_;
+	  ++i;
 	}
     }
 }
@@ -110,6 +141,15 @@ Piano_pedal_engraver::try_music (Music *m)
     {
       for (Pedal_info*p = info_list_; p->name_; p ++)
 	{
+	  if (ly_scm2string (s->get_mus_property ("span-type")) == "abort")
+	    {
+	      p->req_l_drul_[START] = 0;
+	      p->req_l_drul_[STOP] = 0;
+	      
+	      if (p->bracket_p_)
+		p->bracket_p_->suicide (); /* as in dynamic-engraver.cc */
+	      p->bracket_p_ = 0;
+	    }  
 	  if (scm_equal_p (s->get_mus_property ("span-type"),
 			   ly_str02scm (p->name_))==SCM_BOOL_T)
 	    {
@@ -126,78 +166,241 @@ Piano_pedal_engraver::create_grobs ()
 {
   for (Pedal_info*p = info_list_; p && p->name_; p ++)
     {
-      if (p->item_p_ || ! (p->req_l_drul_[STOP] || p->req_l_drul_[START]))
-	continue;
-      
-      SCM s = SCM_EOL;
-      SCM strings = get_property (("pedal" + String (p->name_) + "Strings").ch_C ());
-      if (scm_ilength (strings) < 3)
-	continue;
-      
-      if (p->req_l_drul_[STOP] && p->req_l_drul_[START])
+      if (p->req_l_drul_[STOP] || p->req_l_drul_[START])
 	{
-	  if (!p->start_req_l_)
-	    {
-	      p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'",  p->name_));
-	    }
-	  else
+	  if (!p->line_spanner_)
 	    {
-	      s = ly_cadr (strings);
+	      p->line_spanner_ = new Spanner (get_property ( ( String (p->name_) + "PedalLineSpanner").ch_C() ));
+	      Side_position_interface::set_axis (p->line_spanner_, Y_AXIS);
+	      Axis_group_interface::set_interface (p->line_spanner_);
+	      Axis_group_interface::set_axes (p->line_spanner_, Y_AXIS, Y_AXIS);
+	      Music * rq = (p->req_l_drul_[START]  ?  p->req_l_drul_[START]  :  p->req_l_drul_[STOP]);
+	      announce_grob (p->line_spanner_, rq->self_scm ());
 	    }
-	  p->start_req_l_ = p->req_l_drul_[START];
+      
+	  // Choose the appropriate grobs to add to the line spanner
+	  // These can be text items or text-spanners
+	  
+	  SCM type = ly_cdr (scm_assoc (ly_symbol2scm("pedal-type"), 
+					get_property( ( String (p->name_) + "Pedal").ch_C () )));
+	  if (type == ly_symbol2scm("text") ||      // Ped.     *Ped.  *
+	      type == ly_symbol2scm("mixed")   )    // Ped. _____/\____|
+	    if (! p->item_p_)
+	      create_text_grobs(p, type);
+
+	  if (type == ly_symbol2scm("bracket") ||   // |_________/\____|
+	      type == ly_symbol2scm("mixed")   )
+	    create_bracket_grobs(p, type);
 	}
-      else if (p->req_l_drul_[STOP])
+      
+    }
+}
+
+
+void
+Piano_pedal_engraver::create_text_grobs (Pedal_info *p, SCM pedaltype)
+{
+  SCM b;
+  SCM s = SCM_EOL;
+  SCM strings = get_property (("pedal" + String (p->name_) + "Strings").ch_C ());
+
+  if (! (scm_ilength (strings) < 3))
+    {
+      if (p->req_l_drul_[STOP] && p->req_l_drul_[START]) 
 	{
-	  if (!p->start_req_l_)
+	  if (pedaltype == ly_symbol2scm("text")) 
 	    {
-	      p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
+	      if (!p->start_req_l_)
+		{
+		  p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'",  p->name_));
+		}
+	      else
+		{
+		  s = ly_cadr (strings);
+		}
+	      p->start_req_l_ = p->req_l_drul_[START];
 	    }
-	  else
+	}
+      
+      else if (p->req_l_drul_[STOP])
+	{ 
+	  if (pedaltype == ly_symbol2scm("text"))
 	    {
-	      s = ly_caddr (strings);
+	      if (!p->start_req_l_)
+		{
+		  p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
+		}
+	      else
+		{
+		  s = ly_caddr (strings);
+		  nspanners_i --;
+		}
+	      p->start_req_l_ = 0;
 	    }
-	  p->start_req_l_ = 0;
 	}
-      else if (p->req_l_drul_[START])
+      
+      else if ( p->req_l_drul_[START] )
 	{
 	  p->start_req_l_ = p->req_l_drul_[START];
 	  s = ly_car (strings);
+	  if (pedaltype == ly_symbol2scm("text")) {
+	    nspanners_i ++;
+	    previous_p_[nspanners_i] = p->line_spanner_;
+	    if  (nspanners_i > 1)
+	      // add extra space below the previous already-occuring pedal
+	      Side_position_interface::add_support(p->line_spanner_, previous_p_[nspanners_i - 1]);
+	  }
 	}
-
+      
       if (gh_string_p (s))
 	{
 	  String propname = String (p->name_) + "Pedal";
-	  p->item_p_ = new Item (get_property (propname.ch_C ()));
+	  b = get_property (propname.ch_C ());
+	  p->item_p_ = new Item (b);
 	  p->item_p_->set_grob_property ("text", s);
+	  Axis_group_interface::add_element (p->line_spanner_, p->item_p_);
+	  
+	  announce_grob (p->item_p_,
+			 (p->req_l_drul_[START]
+			 ? p->req_l_drul_[START]
+			 : p->req_l_drul_[STOP])->self_scm() );
+	  
+	}
+      if (pedaltype == ly_symbol2scm("text")) 
+	{
+	  p->req_l_drul_[START] = 0;
+	  p->req_l_drul_[STOP] = 0;
+	}
+    }
+}
 
+void
+Piano_pedal_engraver::create_bracket_grobs (Pedal_info *p, SCM pedaltype)
+{
 
-	  Music * c =  p->req_l_drul_[START]
-	    ? p->req_l_drul_[START]
-	    : p->req_l_drul_[STOP];
-	  announce_grob (p->item_p_, c ?  c->self_scm() : SCM_EOL);
-			
+  if (p->req_l_drul_[STOP])
+    {
+      if (!p->start_req_l_)
+	{
+	  p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
+	}
+      else if (!p->req_l_drul_[START])
+	nspanners_i -- ;
+
+      assert (!p->finished_bracket_p_ && p->bracket_p_);
+
+      p->bracket_p_->set_bound (RIGHT, unsmob_grob(get_property ("currentMusicalColumn")));
+
+      // Set a property so that the molecule-creating function will know whether the right edge should be angled ___/
+      p->bracket_p_->set_grob_property("angle-right", gh_bool2scm((bool) p->req_l_drul_[START]) );
+      add_bound_item (p->line_spanner_, p->bracket_p_->get_bound (RIGHT));	  
+
+      p->finished_bracket_p_ = p->bracket_p_;
+      p->bracket_p_ = 0;
+      p->current_bracket_req_ = 0;
+      p->start_req_l_ = p->req_l_drul_[START];
+    }
+
+  if (p->req_l_drul_[START])
+    {
+      p->start_req_l_ = p->req_l_drul_[START];
+      p->current_bracket_req_ = p->req_l_drul_[START];
+
+      p->bracket_p_  = new Spanner (get_property ("PianoPedalBracket"));
+      p->bracket_p_->set_interface (ly_symbol2scm ("piano-pedal-interface"));
+
+      // Set a property so that the molecule-creating function will know whether the left edge should be angled \___
+      p->bracket_p_->set_grob_property("angle-left", gh_bool2scm((bool) p->req_l_drul_[STOP]) );
+
+      // Set this property for 'mixed style' pedals,    Ped._______/\ ,  
+      // so the molecule function will shorten the ____ line by the length of the Ped. text. 
+      p->bracket_p_->set_grob_property("text-start", 
+				       pedaltype == ly_symbol2scm("mixed") ? 
+				       gh_bool2scm((bool) ! p->req_l_drul_[STOP]) :
+				       gh_bool2scm(false));
+      if (p->item_p_)
+	p->bracket_p_->set_parent (p->item_p_, Y_AXIS);
+      
+      Side_position_interface::set_axis (p->bracket_p_, Y_AXIS);
+      Side_position_interface::set_direction (p->bracket_p_, UP);
+      p->bracket_p_->set_bound (LEFT, unsmob_grob (get_property ("currentMusicalColumn")));
+      Axis_group_interface::add_element (p->line_spanner_, p->bracket_p_);	      
+
+      add_bound_item (p->line_spanner_, p->bracket_p_->get_bound (LEFT));
+      announce_grob (p->bracket_p_, p->req_l_drul_[START]->self_scm());
+
+      if (!p->req_l_drul_[STOP]) {
+
+	nspanners_i ++;
+	previous_p_[nspanners_i] = p->line_spanner_;	
+
+	if (nspanners_i > 1) 
+	  // position new pedal spanner below the current one
+	  Side_position_interface::add_support(p->line_spanner_, previous_p_[nspanners_i - 1]);      
+	
+      }
+    }
+
+  p->req_l_drul_[START] = 0;
+  p->req_l_drul_[STOP] = 0;
+}
+
+void
+Piano_pedal_engraver::finalize ()
+{  
+  for (Pedal_info*p = info_list_; p && p->name_; p ++)
+    {
+      if (p->line_spanner_
+	  && p->line_spanner_->immutable_property_alist_ == SCM_EOL)
+	p->line_spanner_ = 0;
+      if (p->line_spanner_)
+	{
+	  p->finished_line_spanner_ = p->line_spanner_;
+	  typeset_all ();
+	}
+      if (p->bracket_p_
+	  && p->bracket_p_->immutable_property_alist_ == SCM_EOL)
+	p->bracket_p_ = 0;
+      if (p->bracket_p_)
+	{
+	  p->current_bracket_req_->origin ()->warning (_ ("unterminated pedal bracket"));
+	  p->bracket_p_->suicide ();
+	  p->bracket_p_ = 0;
 	}
-      p->req_l_drul_[START] = 0;
-      p->req_l_drul_[STOP] = 0;
     }
 }
 
+  
 void
 Piano_pedal_engraver::stop_translation_timestep ()
 {
+  for (Pedal_info*p = info_list_; p && p->name_; p ++)
+    {
+      p->finished_line_spanner_ = p->line_spanner_;
+    }
+  typeset_all ();
+}
+
+
+void
+Piano_pedal_engraver::typeset_all ()
+{
+
+
   Item * sustain = 0;
   for (Pedal_info*p = info_list_; p->name_; p ++)
     {
+      if (p->finished_line_spanner_
+	  && p->finished_line_spanner_->immutable_property_alist_ == SCM_EOL)
+	p->finished_line_spanner_ = 0;
+      if (p->finished_bracket_p_
+	  && p->finished_bracket_p_->immutable_property_alist_ == SCM_EOL)
+	p->finished_bracket_p_ = 0;
       if (p->name_ == String ("Sustain"))
 	sustain = p->item_p_;
-    }
 
-  for (Pedal_info*p = info_list_; p->name_; p ++)
-    {
       if (p->item_p_)
 	{
-	  Side_position_interface::add_staff_support (p->item_p_);
-	  
 	  /*
 	    Hmm.
 	  */
@@ -209,8 +412,42 @@ Piano_pedal_engraver::stop_translation_timestep ()
 		}
 	    }
 	  typeset_grob (p->item_p_);
+	  p->item_p_ = 0;
+	}
+      
+      if (p->finished_bracket_p_)
+	{
+	  if (!p->finished_bracket_p_->get_bound (RIGHT))
+	    {
+	      p->finished_bracket_p_->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")));
+
+	      if (p->finished_line_spanner_)
+		add_bound_item (p->finished_line_spanner_,
+				p->finished_bracket_p_->get_bound (RIGHT));
+	    }
+	  typeset_grob (p->finished_bracket_p_);
+	  p->finished_bracket_p_ =0;
+	}
+
+      if (p->finished_line_spanner_)
+	{
+	  Side_position_interface::add_staff_support (p->finished_line_spanner_);
+	  Grob * l = p->finished_line_spanner_->get_bound (LEFT );
+	  Grob * r = p->finished_line_spanner_->get_bound (RIGHT);      
+	  if (!r && l)
+	    p->finished_line_spanner_->set_bound (RIGHT, l);
+	  else if (!l && r)
+	    p->finished_line_spanner_->set_bound (LEFT, r);
+	  else if (!r && !l)
+	    {
+	      Grob * cc = unsmob_grob (get_property ("currentMusicalColumn"));
+	      Item * ci = dynamic_cast<Item*>(cc);
+	      p->finished_line_spanner_->set_bound (RIGHT, ci);
+	      p->finished_line_spanner_->set_bound (LEFT, ci);	  
+	    }
+	  typeset_grob (p->finished_line_spanner_);
+	  p->finished_line_spanner_ = 0;
 	}
-      p->item_p_ = 0;
     }
 }
 
@@ -224,8 +461,8 @@ Piano_pedal_engraver::start_translation_timestep ()
     }
 }
 ENTER_DESCRIPTION(Piano_pedal_engraver,
-/* descr */       "Engrave piano pedal symbols.",
-/* creats*/       "SostenutoPedal SustainPedal UnaCordaPedal",
-/* acks  */       "rhythmic-head-interface stem-interface",
+/* descr */       "Engrave piano pedal symbols and brackets.",
+/* creats*/       "SostenutoPedal SustainPedal UnaCordaPedal SostenutoPedalLineSpanner SustainPedalLineSpanner UnaCordaPedalLineSpanner",
+/* acks  */       "note-column-interface",
 /* reads */       "pedalSostenutoStrings pedalSustainStrings pedalUnaCordaStrings",
 /* write */       "");
diff --git a/lily/text-spanner.cc b/lily/text-spanner.cc
index 0511e632b5..d86f4c99c3 100644
--- a/lily/text-spanner.cc
+++ b/lily/text-spanner.cc
@@ -35,6 +35,10 @@ Text_spanner::brew_molecule (SCM smob)
   Grob *me= unsmob_grob (smob);
   Spanner *spanner = dynamic_cast<Spanner*> (me);
 
+  if (spanner->has_interface (ly_symbol2scm ("piano-pedal-interface")) ) 
+    {
+      setup_pedal_bracket(spanner);
+    }
 
 
   /* Ugh, must be same as Hairpin::brew_molecule.  */
@@ -129,17 +133,21 @@ Text_spanner::brew_molecule (SCM smob)
   
   Drul_array<Molecule> edge_line;
   s = me->get_grob_property ("edge-height");
+  SCM ew = me->get_grob_property ("edge-width");
   if (gh_pair_p (s))
     {
       Direction d = LEFT;
       int dir = to_dir (me->get_grob_property ("direction"));
       do
 	{
+	  Real dx = ( gh_pair_p (ew)  ? 
+		      gh_scm2double (index_cell (ew, d)) * - dir  :  
+		      0 );
 	  Real dy = gh_scm2double (index_cell (s, d)) * - dir;
 	  if (dy)
 	    {
-	      SCM list = Line_spanner::line_atom (me, 0, dy);
-	      Box b (Interval (0, thick),
+	      SCM list = Line_spanner::line_atom (me, dx, dy);
+	      Box b (Interval (-thick, 0),
 		     dy > 0
 		     ? Interval (0, dy)
 		     : Interval (dy, 0));
@@ -161,9 +169,112 @@ Text_spanner::brew_molecule (SCM smob)
     m.add_at_edge (X_AXIS, RIGHT, edge_line[RIGHT], 0);
   if (!edge[RIGHT].empty_b ())
     m.add_at_edge (X_AXIS, RIGHT, edge[RIGHT], 0);
-  m.translate_axis (broken_left + extra_off[LEFT], X_AXIS);
+  m.translate_axis (broken_left + extra_off[LEFT] + shorten[LEFT], X_AXIS);
 
   return m.smobbed_copy ();
 }
 
 
+
+/* 
+   Piano pedal brackets are a special case of a text spanner.
+   Pedal up-down (restart) indicated by the angled right and left edges 
+   of consecutive pedals touching exactly to form an __/\__
+   Chris Jackson <chris@fluffhouse.org.uk>
+
+   TODO: Pedal line extending to the end of the note
+*/
+
+void 
+Text_spanner::setup_pedal_bracket(Spanner *s)
+{
+
+  Real thick = s->paper_l ()->get_var ("stafflinethickness");  
+  Real ss = Staff_symbol_referencer::staff_space (s);
+
+  Drul_array<bool> a, broken;
+  Drul_array<Real> height, width, shorten, r;
+
+  // Pedal has an angled left edge \__  or an angled right edge __/ 
+  a[LEFT] = a[RIGHT] = false;
+  SCM al = s->get_grob_property ("angle-left");
+  SCM ar = s->get_grob_property ("angle-right");
+  if (gh_boolean_p (al) )  
+    a[LEFT]   = to_boolean (al);
+  if (gh_boolean_p (ar) )  
+    a[RIGHT]  = to_boolean (ar);
+  
+  height[LEFT] = ( to_boolean (s->get_grob_property ("text-start")) ?
+		   0 :
+		   ss );
+  height[RIGHT] = ss;
+  
+  Direction d = LEFT;
+  Interval e;
+  Real padding = 0;
+  SCM pa = (s->get_grob_property ("if-text-padding"));
+  if (gh_number_p (pa) )
+    padding = gh_scm2double (pa);
+  do {
+    Item *b = s->get_bound (d);
+
+    e = b->extent (b, X_AXIS);
+    if (!e.empty_b ())
+      r[d] = d * (e[-d] + padding);
+
+    broken[d] = b->break_status_dir () != CENTER;
+    width[d]  = (a[d]  ? ss*d/2 :  0);
+    if (broken[d])
+      height[d] =  0;
+  }
+  while (flip (&d) != LEFT);
+  
+  shorten[RIGHT] =  shorten[LEFT]  =  0;
+  Real extra_short = 0;
+  // For 'Mixed' style pedals, i.e.  a bracket preceded by text:  Ped._____|
+  // need to shorten by the extent of the text grob
+  if ( to_boolean (s->get_grob_property ("text-start")) )
+    {
+      Grob * textbit = s->get_parent(Y_AXIS);
+      extra_short = padding;
+      if (textbit->has_interface(ly_symbol2scm("piano-pedal-interface")))
+	// for pretty Ped. scripts. 
+	{
+	  e = textbit->extent(textbit, Y_AXIS);
+	  extra_short += e.length();
+	}
+      if (textbit->has_interface(ly_symbol2scm("text-interface"))) 
+	// for plain text, e.g., Sost. Ped.
+	{
+	  SCM text  =  textbit->get_grob_property("text"); 
+	  if (gh_string_p (text)) {
+	    SCM properties = Font_interface::font_alist_chain (s);
+	    Molecule mol = Text_item::text2molecule (s, text, properties);
+	    extra_short += mol.extent(X_AXIS).length() / 2;
+	  }
+	}
+      shorten[RIGHT] -= thick;
+    }
+
+  // Shorten a \____ on the left so that it will touch an adjoining ___/ 
+  shorten[LEFT] += abs(width[LEFT]) * 2   +  extra_short ;
+  
+  if (broken[LEFT]) {
+    shorten[LEFT] -= s->get_broken_left_end_align () ;
+    shorten[RIGHT] -= r[RIGHT];
+  }
+  else 
+    // Shorten bracket on the right so it ends just before the spanned note.
+    shorten[RIGHT]  +=  thick  -  (r[LEFT]  +  r[RIGHT]);
+
+  // Hmm. TODO: This should be set in grob-description.scm, but side-positioning
+  // of consecutive brackets only seems to work if direction is +1 within the engraver. 
+  s->set_grob_property ("direction", gh_int2scm(-1)); 
+
+  s->set_grob_property ("edge-height", gh_cons ( gh_double2scm ( height[LEFT] ) , 
+						 gh_double2scm ( height[RIGHT]) ) );
+  s->set_grob_property ("edge-width",  gh_cons ( gh_double2scm ( width[LEFT]  ), 
+						 gh_double2scm ( width[RIGHT] ) ));
+  s->set_grob_property ("shorten", gh_cons ( gh_double2scm ( shorten[LEFT] ), 
+					     gh_double2scm ( shorten[RIGHT] ) ));
+}
diff --git a/lilypond-font-lock.el b/lilypond-font-lock.el
index dbaf18ca96..4a09294c56 100644
--- a/lilypond-font-lock.el
+++ b/lilypond-font-lock.el
@@ -70,7 +70,7 @@
 
 ;; in principle, have one or more uppercase letters
 "\\(\\(BarNumbering\\|Choir\\|Grand\\|HaraKiri\\|OrchestralPart\\|Piano\\|Rhythmic\\)Staff\\|\\(Cue\\|Lyrics\\)?Voice\\|\\(Orchestral\\)?Score\\|ChordNames\\|Grace\\|Lyrics\\|StaffGroup\\|Thread\\)Context" ; *Context
-"\\(script\\|dots\\|dynamic\\|slur\\|stem\\|sustain\\|tie\\|tuplet\\)\\(Both\\|Down\\|Up\\)" ; *(Both/Down/Up)
+"\\(script\\|dots\\|dynamic\\|slur\\|stem\\|sustain\\|sostenuto\\|unaCorda\\|treCorde\\|tie\\|tuplet\\)\\(Both\\|Down\\|Up\\)" ; *(Both/Down/Up)
 "\\(slur\\|tie\\)\\(Dotted\\|Solid\\)" ; *(Dotted/Solid)
 "\\(autoBeam\\|cadenza\\|impro\\|turn\\)\\(Off\\|On\\)" ; *(On/Off)
 "\\(empty\\|fat\\)Text" ; *Text
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 1552a36896..2db5d63839 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -379,7 +379,10 @@ ScoreContext = \translator {
 
 	pedalSustainStrings = #'("Ped." "*Ped." "*")
 	pedalUnaCordaStrings = #'("una corda" "" "tre corde")
-	pedalSostenutoStrings = #'()  % FIXME
+
+	%% these are in ordinary italic font, including the *, but they are unlikely to be used, 
+	%% as the default pedal-style for SostenutoPedal is 'mixed': i.e.  Sost. Ped_____________________ 
+	pedalSostenutoStrings = #'("Sost. Ped." "*Sost. Ped." "*") 
 
 	tupletNumberFormatFunction = #denominator-tuplet-formatter
 	
diff --git a/make/out/lilypond.lsm b/make/out/lilypond.lsm
index b8506cce0e..e4ab0ee2cc 100644
--- a/make/out/lilypond.lsm
+++ b/make/out/lilypond.lsm
@@ -1,6 +1,6 @@
 Begin3
 Title: LilyPond
-Version: 1.5.40
+Version: 1.5.41
 Entered-date: 15MRT02
 Description: @BLURB@
 Keywords: music notation typesetting midi fonts engraving
@@ -8,8 +8,8 @@ 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.5.40.tar.gz 
+	1000k lilypond-1.5.41.tar.gz 
 Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/
-	1000k lilypond-1.5.40.tar.gz 
+	1000k lilypond-1.5.41.tar.gz 
 Copying-policy: GPL
 End
diff --git a/make/out/lilypond.mandrake.spec b/make/out/lilypond.mandrake.spec
index 63f1a68167..227a2264fd 100644
--- a/make/out/lilypond.mandrake.spec
+++ b/make/out/lilypond.mandrake.spec
@@ -1,5 +1,5 @@
 %define name lilypond
-%define version 1.5.40
+%define version 1.5.41
 %define release 1mdk
 
 Name: %{name}
diff --git a/make/out/lilypond.redhat.spec b/make/out/lilypond.redhat.spec
index a2ce3b5389..7a5c645ac8 100644
--- a/make/out/lilypond.redhat.spec
+++ b/make/out/lilypond.redhat.spec
@@ -3,11 +3,11 @@
 %define info yes
 
 Name: lilypond
-Version: 1.5.40
+Version: 1.5.41
 Release: 1
 License: GPL
 Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.40.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.41.tar.gz
 Summary: Create and print music notation 
 URL: http://www.lilypond.org/
 BuildRoot: /tmp/lilypond-install
diff --git a/make/out/lilypond.suse.spec b/make/out/lilypond.suse.spec
index b8b6aa97ea..0ff09a6c34 100644
--- a/make/out/lilypond.suse.spec
+++ b/make/out/lilypond.suse.spec
@@ -14,11 +14,11 @@
 
 Distribution: SuSE Linux 7.0 (i386)
 Name: lilypond
-Version: 1.5.40
+Version: 1.5.41
 Release: 2
 Copyright:    GPL
 Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.40.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.41.tar.gz
 # music notation software for.. ?
 Summary: A program for printing sheet music.
 URL: http://www.lilypond.org/
diff --git a/mf/feta-bolletjes.mf b/mf/feta-bolletjes.mf
index b44922c89b..60c6564867 100644
--- a/mf/feta-bolletjes.mf
+++ b/mf/feta-bolletjes.mf
@@ -443,7 +443,9 @@ fet_endchar;
 fet_beginchar("Ledger ending", "ledgerending", "ledgerending")
 set_char_box (5/2 ledgerlinethickness#, 5/2 ledgerlinethickness#,
   		ledgerlinethickness#/2,ledgerlinethickness#/2);
-	draw_rounded_block((-b,-d),(w,h),1.3 blot_diameter);
+
+
+	draw_rounded_block((-b,-d),(w,h), 0.8 ledgerlinethickness);
 fet_endchar;
 
 
diff --git a/mf/feta-eindelijk.mf b/mf/feta-eindelijk.mf
index 7b15b6ae65..96e88698f1 100644
--- a/mf/feta-eindelijk.mf
+++ b/mf/feta-eindelijk.mf
@@ -184,20 +184,25 @@ enddef;
 % todo: document rest.
 %
 
+def normalize (expr p) =
+	(p / length (p))
+enddef ;
 
 def draw_eighth_rest =
 	save width, bulb_diam, thin, thick;
-	save ycenter, crook_thick;
-	save crook_dir;
+	save ycenter, crook_thick, crook_thin;
+	save crook_dir, lower_brush;
 	pair crook_dir;
 
 
 	width# := 1.0 staff_space#;
 	bulb_diam# := 0.6 staff_space#;
-	thin# := 1.0 stafflinethickness#;
-	thick# :=  2.0 stafflinethickness#;
-	crook_thick# := 1.6 stafflinethickness#;
+	thin# := 1.1 stafflinethickness#;
+	thick# :=  2.2 stafflinethickness#;
+	crook_thick# := 1.8 stafflinethickness#;
+	crook_thin := 1.3 stafflinethickness;
 
+	lower_brush = 1.0 stafflinethickness;
 	ycenter := 0.5 staff_space;
 
 	define_pixels (width, bulb_diam, thin, thick, crook_thick);
@@ -208,30 +213,34 @@ def draw_eighth_rest =
 	penpos2 (thin, 0);
 
 	y1 = ycenter + - 1.5 staff_space ;
-	y2 = y5 -  2.0 stafflinethickness;
+%	y9 = y5 -  lower_brush;
+	y2 = y5 -  0.7 stafflinethickness;
+       
 	x2r = width;
 
 	y3 - y2l = 0.25 staff_space;
 	x2r - x1 = 0.5 staff_space;
 
 	x3 = x1l ;
-	y3 := ycenter +floor (- bulb_diam/2);
+
 
 	x4 = 1.02 bulb_diam ;
-	y4 = ycenter - stafflinethickness;
+	y4 = ycenter - 2 stafflinethickness + crook_thin;
 
 	x5 = 0.5 bulb_diam;
 	y5 = ycenter +bulb_diam/2;
 	
-	crook_dir = (z2l - z4) / length(z2l - z4);
+	z9 = z2 + 0.46 stafflinethickness * dir (angle(z2 - z1)- 10);
+
+	z7 = (bulb_diam/2,ycenter) + 0.26 staff_space * dir ( 35);
+	z8 = (0, ycenter);
 
 	z6 = whatever [z1l, z2l];
 	z6 = whatever [z2l, z4] + crook_thick * (crook_dir rotated -90);
+	crook_dir = normalize(z2l - z4);
 
-	z7 = (bulb_diam/2,ycenter) + 0.26 staff_space * dir ( 35);
-	z8 = (0, ycenter);
+	y3 := ycenter +floor (- bulb_diam/2);
 
-	z9 = z2 + 0.46 stafflinethickness * dir (angle(z2 - z1)- 10);
 
 	penlabels (1, 2);
 	labels(3, 4, 5, 6, 7, 8, 9);
diff --git a/mf/feta-generic.mf b/mf/feta-generic.mf
index 2602e03142..2466feba47 100644
--- a/mf/feta-generic.mf
+++ b/mf/feta-generic.mf
@@ -43,7 +43,7 @@ else:
 	input feta-banier;
 	input feta-eindelijk;
 %	input feta-klef;
-	input feta-toevallig;
+%	input feta-toevallig;
 %	input feta-schrift;
 %	input feta-haak;
 %	input feta-timesig;
diff --git a/mf/feta-schrift.mf b/mf/feta-schrift.mf
index bb9df75307..557096892d 100644
--- a/mf/feta-schrift.mf
+++ b/mf/feta-schrift.mf
@@ -409,8 +409,8 @@ fet_beginchar("Trill (`tr')","trill","trill")
 
 	ascender_extra# = 1/2 ex#;
 	ascender# = ascender_extra# + ex#;
-	ex# = 1.5 staff_space#;
-	kerning# = .75 ex#;
+	ex# = 1.4 staff_space#;
+	kerning# = .60 ex#;
 	start_nib_angle = 20;
 	bulb_size = 0.47;
 	define_pixels(ex, ascender_extra, ascender, kerning);
@@ -447,7 +447,7 @@ fet_beginchar("Trill (`tr')","trill","trill")
 	path t_p, krul_p, r_p;
 
 
-	t_p := z1l -- z2l{down} .. tension (1 + .5 slant)
+	t_p := simple_serif (z1r, z1l, -30) -- z2l {down} .. tension (1 + .5 slant)
 		.. z3l{right} 
 		
 		.. z4l{up} -- z4r{down} 
@@ -461,7 +461,7 @@ fet_beginchar("Trill (`tr')","trill","trill")
 	z5 = (t_fatness/2, 2/3 ex);
 	
 	lft x6 = - uitschieter;
-	y6 =  y5 - 1/20 ex;
+	y6 =  y5 ; % - 1/20 ex;
 
 	z7 = z5 + whatever*dir krul_ang;
 	up_angle = krul_ang;
@@ -480,14 +480,14 @@ fet_beginchar("Trill (`tr')","trill","trill")
 	penpos9(r_fatness, 0);
 
 	x10 = x9;
-	y10 = 0;
+	y10 =  -0.3 stafflinethickness;
 	penpos10(r_fatness, 0);
 
 	krul_p := z4{up} .. tension 1.1  .. z5 
-		.. tension 1 and .75 .. {down}z6
+		.. tension 1 and .75 .. z6
 		.. tension .85 and 1.1 .. z5 --- z7;
 	draw krul_p;
-	r_p := z7l{z7-z5} .. z8l{right} .. z9l{down} --- z10l -- z10r
+	r_p := z7l{z7-z5} .. z9l{down} --- simple_serif (z10l, z10r, -30)
 		--- z9r{up} 
 		..  z8r{left} ..  z7r{z5-z7} -- cycle;
 	fill r_p;
diff --git a/mf/feta-toevallig.mf b/mf/feta-toevallig.mf
index 4d0150d02a..2369621e49 100644
--- a/mf/feta-toevallig.mf
+++ b/mf/feta-toevallig.mf
@@ -163,15 +163,25 @@ fet_beginchar( "Natural", "0", "natural")
 %
 
 % TODO: remove crook_fatness
+% TODO: document, simplify!
+%
 def draw_meta_flat(expr xcenter, w, crook_fatness) =
 	clearxy;
 	save crook_thinness;
-	save top_stem_thick, bottom_stem_thick, hair;
+	save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
 	save center;
 	pair center;
 	center = (xcenter, 0);
 
-	crook_thinness = 1.25 stafflinethickness;
+%
+%  TODO: parameterize  this
+%
+	if w >= 0.75 staff_space:
+		smaller_hole = 0.2 stafflinethickness;
+	else:
+		smaller_hole = 0.0 stafflinethickness;
+	fi
+	crook_thinness = 1.1 stafflinethickness;
 	top_stem_thick = 2 stafflinethickness;
 	bottom_stem_thick = 1.2 stafflinethickness;
 
@@ -188,8 +198,10 @@ def draw_meta_flat(expr xcenter, w, crook_fatness) =
 	y3l = (staff_space - stafflinethickness)/2 + ypart center;
 	z3l = whatever [z2r,z1r];
 
-	z3r = .26 [z2r, z1r];
+	z3r = .26 [z2r, z1r] + (smaller_hole, 0);
+	z10 = whatever [z2r, z1r] + (smaller_hole , 0);
 
+	
 
 	z4 = (3/8 staff_space, staff_space/2) + center;
 	penpos4(whatever, 53);
@@ -207,26 +219,23 @@ def draw_meta_flat(expr xcenter, w, crook_fatness) =
 	save ne_angle;
 	ne_angle = angle(z9 - z8);
 
-	z7 = 8/33 [z8,z9];
+	z7 = 8/33 [z8,z9] + (1.0 smaller_hole, 0);
 	z6l = 18/33 [z8,z9] + .5 crook_thinness *dir(ne_angle -90);
   
 	penpos7(crook_thinness, ne_angle + 90);
 
 	z6r = .3 (z9-z8) + z7r;
 
-%	penpos7(crook_thinness, angle(dir(z8-center) -180);
-
 	penpos8(whatever, ne_angle + 90);
 	x8r =  xpart center - bottom_stem_thick/2;
 	penlabels(range 0 thru 10);
 
 	y10 = -1/5 staff_space;
-	z10 = whatever [z2r, z1r];
 
 	unfill z3r .. z4r{right} .. tension .9 
 		.. z6r ---
-		z7r{left}
-		.. z10  -- cycle;
+		z7r{left} 
+		.. z10{z3r-z10}  -- cycle;
 	fill z8r{down}
 		.. tension 0.8 ..z8l{(z9-z8)}
 		.. z7l
diff --git a/scm/grob-description.scm b/scm/grob-description.scm
index 405e280dbc..fcb3f3b90f 100644
--- a/scm/grob-description.scm
+++ b/scm/grob-description.scm
@@ -557,6 +557,20 @@
 	(meta . ,(grob-description multi-measure-rest-interface  font-interface percent-repeat-interface))
 	))
 
+    (PianoPedalBracket   ;; an example of a text spanner
+     . (
+	(molecule-callback . ,Text_spanner::brew_molecule)
+	(font-family . roman)
+	(type . line)
+	(if-text-padding . 1.0)
+	(width-correct . 0)
+	(outer . #t)
+	(angle-left  . #f)
+	(angle-right . #f)
+	(text-start  . #f)
+	(meta . ,(grob-description text-spanner-interface piano-pedal-interface font-interface))
+	))
+
     (RepeatSlash
      . (
 	(molecule-callback . , Percent_repeat_item_interface::beat_slash)
@@ -700,17 +714,27 @@
     (SostenutoPedal
      . (
 	(molecule-callback . ,Text_item::brew_molecule)
-	(direction . -1)
+	(direction . 1)
 	(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
-	(Y-offset-callbacks .
-			    (,Side_position_interface::aligned_side
-			     ,Side_position_interface::centered_on_parent))
+	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
 	(no-spacing-rods . #t)
+	(padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
+	(pedal-type . mixed)
+	(font-family . roman)
 	(font-shape . italic)
 	(self-alignment-X . 0)
 	(meta . ,(grob-description text-interface  font-interface))
 	))
 
+    (SostenutoPedalLineSpanner 
+     . (
+	(axes . ( 1))
+	(padding . 1.2)
+	(minimum-space . 1.0)
+	(direction . -1)
+	(meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
+	))
+	
     (Stem
      . (
 	(before-line-breaking-callback . ,Stem::before_line_breaking)
@@ -763,13 +787,21 @@
 	(no-spacing-rods . #t)
 	(molecule-callback . ,Sustain_pedal::brew_molecule)
 	(self-alignment-X . 0)
-	(direction . -1)
+	(direction . 1)
+	(padding . 0.0)  ;; padding relative to SustainPedalLineSpanner
+	(pedal-type . text)
 	(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
-	(Y-offset-callbacks .
-			    (,Side_position_interface::aligned_side
-			     ,Side_position_interface::centered_on_parent))
+	(Y-offset-callbacks . (,Side_position_interface::aligned_side ))
+	(meta . ,(grob-description piano-pedal-interface side-position-interface font-interface))
+	))
 
-	(meta . ,(grob-description sustain-pedal-interface side-position-interface font-interface))
+    (SustainPedalLineSpanner 
+     . (
+	(axes . ( 1))
+	(padding . 1.2)
+	(minimum-space . 1.0)
+	(direction . -1)
+	(meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
 	))
 
     (SystemStartBrace
@@ -822,7 +854,7 @@
      . (
 	(molecule-callback . ,Text_spanner::brew_molecule)
 	(font-family . roman)
-	(type . "line")
+	(type . line)
 
 	;; urg, only for (de)cresc. text spanners
 	(if-text-padding . 1.0)
@@ -886,14 +918,23 @@
 	(font-shape . italic)
 	(no-spacing-rods . #t)
 	(self-alignment-X . 0)
-	(direction . -1)
+	(direction . 1)
+	(pedal-type . text)
+	(padding . 0.0)  ;; padding relative to UnaCordaPedalLineSpanner
 	(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
-	(Y-offset-callbacks .
-			    (,Side_position_interface::aligned_side
-			     ,Side_position_interface::centered_on_parent))
+	(Y-offset-callbacks . (,Side_position_interface::aligned_side ))
 	(meta . ,(grob-description text-interface font-interface))
 	))
 
+    (UnaCordaPedalLineSpanner 
+     . (
+	(axes . ( 1))
+	(padding . 1.2)
+	(minimum-space . 1.0)
+	(direction . -1)
+	(meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
+	))
+
     (VoltaBracket
      . (
 	(molecule-callback . ,Volta_spanner::brew_molecule)
diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm
index a171dc3db2..b8580bad21 100644
--- a/scm/grob-property-description.scm
+++ b/scm/grob-property-description.scm
@@ -143,6 +143,7 @@ mean centre distance weighted per note
 (grob-property-description 'duration-log integer? "2-log of the notehead duration, i.e. 0=whole note, 1 = half note, etc.")
 (grob-property-description 'dy number? "set by beam: vertical travel height")
 (grob-property-description 'edge-height pair? "a cons that specifies the heights of the vertical egdes '(LEFT-height . RIGHT-height).")
+(grob-property-description 'edge-width pair? "a cons that specifies the widths of the slanted edges '(LEFT-width . RIGHT-width).")
 (grob-property-description 'edge-text pair? "a cons that specifies the texts to be set at the edges '(LEFT-text . RIGHT-text).")
 (grob-property-description 'elements list? "list of grobs, type depending on the Grob where this is set in.")
 (grob-property-description 'expand-limit integer? "maximum number of measures expanded in church rests.")
@@ -272,6 +273,7 @@ more than this (in staffspace).")
 (grob-property-description 'padding number? "add this much extra space between objects that are next to each other.")
 (grob-property-description 'parallel-beam boolean? "internal: true if there is a beam just as wide as the bracket .")
 (grob-property-description 'paren-cautionaries boolean? "Whether to add parenthesis around cautionary accidentals.")
+(grob-property-description 'pedal-type symbol? "Style of piano pedal: text, bracket or mixed")
 (grob-property-description 'penalty number? "Penalty for breaking at
 this column. 10000 or more means forbid linebreak, -10000 or less
 means force linebreak.  Other values influence linebreaking decisions
@@ -293,6 +295,8 @@ reference point.
 
 TODO: revise typing.")
 (grob-property-description 'self-alignment-Y number? "like self-alignment-X but for Y axis.")
+(grob-property-description 'shorten number? "the amount of space that a stem should be shortened (DOCME!)")
+
 (grob-property-description 'shortest-playing-duration moment? "duration of the shortest playing in that column.")
 (grob-property-description 'shortest-starter-duration moment? "duration of the shortest notes that starts exactly in this column.")
 (grob-property-description 'side-relative-direction dir? "if set: get the direction from a different object, and multiply by this.")
diff --git a/scm/interface-description.scm b/scm/interface-description.scm
index 4deb27f649..dd05c80db0 100644
--- a/scm/interface-description.scm
+++ b/scm/interface-description.scm
@@ -587,6 +587,12 @@ dir-list shortest-playing-duration shortest-starter-duration
 contains-grace extra-space stretch-distance ))
 
 
+  (lily-interface
+   'piano-pedal-interface
+   ""
+   '(pedal-type
+    ))
+
 
   (lily-interface
    'porrectus-interface
@@ -727,12 +733,6 @@ since these usually are in a different X_group
      ))
 
 
-  (lily-interface
-   'sustain-pedal-interface
-   ""
-   '(
-    ))
-
   (lily-interface
    'system-start-delimiter-interface
    "#'style can be bar-line, bracket or brace"
@@ -749,6 +749,7 @@ since these usually are in a different X_group
     dash-length 
     line-thickness 
     edge-height 
+    edge-width
     edge-text 
     type 
 ))
diff --git a/scm/ps.scm b/scm/ps.scm
index 3359c7f042..496bc521e6 100644
--- a/scm/ps.scm
+++ b/scm/ps.scm
@@ -129,11 +129,11 @@
 
 (define (dashed-line thick on off dx dy)
   (string-append 
-   (ly-number->string dx)
+   (ly-number->string (* dx (/ 72 72.27)))
    " "
    (ly-number->string dy)
    " "
-   (ly-number->string thick) 
+   (ly-number->string (* thick (/ 72 72.27))) 
    " [ "
    (ly-number->string on)
    " "
-- 
2.39.5