to undo property settings.
* lily/parser.yy (property_def): syntax for \once \property ....
* lily/note-spacing.cc (get_spacing): don't get crazy when there
is no (live) stem.
* lily/my-lily-lexer.cc: new keyword \once
* lily/global-translator.cc (apply_finalizations): new function
(add_finalization): new function
Score_engraver*
Engraver::top_engraver () const
{
- /*
- ugh.
- */
- if (dynamic_cast<Score_engraver*>((Engraver*)this))
- return dynamic_cast<Score_engraver*> ((Engraver*)this);
-
- if (daddy_trans_)
- return dynamic_cast<Engraver*> (daddy_trans_)->top_engraver ();
-
- programming_error ("No score engraver!");
- return 0;
+ return dynamic_cast<Score_engraver*> (top_translator());
}
ENTER_DESCRIPTION(Engraver,
Global_translator::one_time_step ()
{
}
+
void
Global_translator::start ()
{
w = sneaky_insert_extra_moment (w);
// printf ("proccing %s\n ", w.string ().to_str0 ());
-
-
-
if (first)
{
first = false;
one_time_step ();
}
}
+
+void
+Global_translator::apply_finalizations ()
+{
+ SCM lst = get_property ("finalizations");
+ set_property ("finalizations" , SCM_EOL);
+ for (SCM s = lst ; gh_pair_p (s); s = gh_cdr (s))
+ {
+ scm_primitive_eval (gh_car (s));
+ }
+}
+
+/*
+ Add a function to execute before stepping to the next time step.
+ */
+void
+Global_translator::add_finalization (SCM x)
+{
+ SCM lst = get_property ("finalizations");
+ lst = scm_cons (x, lst);
+ set_property ("finalizations" ,lst);
+}
+
+
+Global_translator *
+Translator::top_translator()const
+{
+ if (dynamic_cast<Global_translator*>((Translator*)this))
+ return dynamic_cast<Global_translator*> ((Translator*)this);
+
+ if (daddy_trans_)
+ return daddy_trans_->top_translator ();
+
+ programming_error ("No top translator!");
+ return 0;
+}
#include "moment.hh"
#include "pqueue.hh"
-
-class Global_translator : public virtual Translator_group{
+class Global_translator : public virtual Translator_group
+{
PQueue<Moment> extra_mom_pq_;
public:
VIRTUAL_COPY_CONS (Translator);
Moment sneaky_insert_extra_moment (Moment);
void add_moment_to_process (Moment);
void run_iterator_on_me (Music_iterator*);
+
+ void apply_finalizations ();
+ void add_finalization (SCM);
virtual Music_output *get_output ();
virtual void prepare (Moment);
public:
VIRTUAL_COPY_CONS (Music_iterator);
DECLARE_SCHEME_CALLBACK(constructor, ());
- /* construction */
+ DECLARE_SCHEME_CALLBACK(once_finalization, (SCM, SCM ));
+
protected:
+ virtual void do_quit();
virtual void process (Moment);
};
public:
VIRTUAL_COPY_CONS (Music_iterator);
DECLARE_SCHEME_CALLBACK(constructor, ());
- /* construction */
protected:
virtual void process (Moment);
};
public:
VIRTUAL_COPY_CONS (Music_iterator);
DECLARE_SCHEME_CALLBACK(constructor, ());
+ DECLARE_SCHEME_CALLBACK(once_finalization, (SCM, SCM));
protected:
- /* construction */
virtual void process (Moment);
+ virtual void do_quit();
};
class Pop_property_iterator : public Simple_music_iterator
DECLARE_SCHEME_CALLBACK(constructor, ());
VIRTUAL_COPY_CONS (Music_iterator);
protected:
- /* construction */
virtual void process (Moment);
};
SCM properties_scm_;
DECLARE_SMOBS (Translator, dummy);
+
public:
+ Global_translator * top_translator () const;
TRANSLATOR_DECLARATIONS(Translator);
/**
try to fit the request in this engraver
{"lyrics", LYRICS},
{"key", KEY},
{"mark", MARK},
+ {"once", ONCE},
{"pitch", PITCH},
{"time", TIME_T},
{"times", TIMES},
if (!g)
g = Note_column::first_head (it);
+ /*
+ Ugh. If Stem is switched off, we don't know what the
+ first note head will be.
+ */
if (g)
left_head_wid = g->extent(it_col, X_AXIS);
}
*/
*fixed = left_head_wid.empty_b () ? increment : left_head_wid[RIGHT];
*space = (base_space - increment) + *fixed +
- (extents[LEFT][RIGHT] - left_head_wid[RIGHT])/ 2;
+ (extents[LEFT][RIGHT]
+ - (left_head_wid.empty_b () ? 0.0 : left_head_wid[RIGHT]))/ 2;
;
if (*space - *fixed < 2 * ((- extents[RIGHT][LEFT]) >? 0))
Grob *stem = Note_column::get_stem (it);
- if (!stem)
+ if (!stem || !stem->live ())
{
if (d == RIGHT && Separation_item::has_interface (it))
{
%token NAME
%token PITCHNAMES
%token NOTES
+%token ONCE
%token PAPER
%token PARTIAL
%token PENALTY
%type <i> tremolo_type
%type <i> bare_int bare_unsigned
%type <i> script_dir
-
%type <scm> identifier_init
%type <scm> steno_duration optional_notemode_duration multiplied_duration
%type <scm> embedded_scm scalar
%type <music> Music Sequential_music Simultaneous_music
%type <music> relative_music re_rhythmed_music part_combined_music
-%type <music> property_def translator_change
+%type <music> property_def translator_change simple_property_def
%type <scm> Music_list
%type <outputdef> music_output_def_body
%type <request> shorthand_command_req
;
property_def:
+ simple_property_def
+ | ONCE simple_property_def {
+ $$ = $2;
+ SCM e = $2->get_mus_property ("element");
+ unsmob_music (e)->set_mus_property ("once", SCM_BOOL_T);
+ }
+ ;
+
+simple_property_def:
PROPERTY STRING '.' STRING '=' scalar {
Music *t = set_property_music (scm_string_to_symbol ($4), $6);
csm-> set_mus_property ("context-type", $2);
}
- | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
+ | PROPERTY STRING '.' STRING OVERRIDE
+ embedded_scm '=' embedded_scm
+ {
/*
UGH UGH UGH UGH.
*/
$$->set_spot (THIS->here_input ());
csm-> set_mus_property ("context-type", $2);
+
}
| PROPERTY STRING '.' STRING REVERT embedded_scm {
Music *t = new Music (SCM_EOL);
#include "music.hh"
#include "translator-def.hh"
#include "translator-group.hh"
+#include "global-translator.hh"
bool check_grob(Music *mus, SCM sym);
Simple_music_iterator::process (m);
}
+MAKE_SCHEME_CALLBACK(Property_iterator,once_finalization, 2);
+SCM
+Property_iterator::once_finalization(SCM translator, SCM music )
+{
+ Music * m = unsmob_music (music);
+ Translator_group * tg
+ = dynamic_cast<Translator_group*> (unsmob_translator (translator));
+ SCM sym = m->get_mus_property ("symbol");
+
+ tg->unset_property (sym);
+ return SCM_UNSPECIFIED;
+}
+
+void
+Property_iterator::do_quit ()
+{
+ if (to_boolean (get_music ()->get_mus_property ("once")))
+ {
+ SCM trans = report_to()->self_scm();
+ SCM music = get_music()->self_scm();
+
+ Global_translator * tg= report_to()->top_translator ();
+
+ tg->add_finalization (scm_list_n (once_finalization_proc,
+ trans, music, SCM_UNDEFINED));
+ }
+}
+
SCM list_p = 0;
SCM eprop = get_music ()->get_mus_property ("grob-property");
SCM val = get_music ()->get_mus_property ("grob-value");
- if (to_boolean (get_music ()->get_mus_property ("pop-first")))
+ if (to_boolean (get_music ()->get_mus_property ("pop-first"))
+ && !to_boolean (get_music ()->get_mus_property ("once"))
+ )
Translator_def::apply_pushpop_property (report_to (),
sym, eprop, SCM_UNDEFINED);
- Translator_def::apply_pushpop_property (report_to (), sym, eprop, val);
+ translator_def::apply_pushpop_property (report_to (), sym, eprop, val);
+ }
+ simple_music_iterator::process (m);
+}
+
+make_scheme_callback(push_property_iterator,once_finalization, 2);
+scm
+push_property_iterator::once_finalization (scm trans, scm music)
+{
+ music * mus = unsmob_music (music);
+ translator_group *tg
+ = dynamic_cast<translator_group*> (unsmob_translator (trans));
+
+ scm sym = mus->get_mus_property ("symbol");
+ if (check_grob (mus, sym))
+ {
+ scm eprop = mus->get_mus_property ("grob-property");
+
+ translator_def::apply_pushpop_property (tg, sym, eprop, scm_undefined);
+ }
+ return scm_unspecified;
+}
+
+void
+Push_property_iterator::do_quit ()
+{
+ if (to_boolean (get_music ()->get_mus_property ("once")))
+ {
+ SCM trans = report_to()->self_scm();
+ SCM music = get_music ()->self_scm();
+
+ Global_translator * tg= report_to()->top_translator ();
+ tg->add_finalization (scm_list_n (once_finalization_proc,
+ trans, music, SCM_UNDEFINED));
}
- Simple_music_iterator::process (m);
}
void
}
+
IMPLEMENT_CTOR_CALLBACK (Pop_property_iterator);
IMPLEMENT_CTOR_CALLBACK (Push_property_iterator);
IMPLEMENT_CTOR_CALLBACK (Property_iterator);
IMPLEMENT_CTOR_CALLBACK (Property_unset_iterator);
+
Grob_info i2 (musical_column_);
i2.origin_trans_ = this;
-
announce_grob (i1);
announce_grob (i2);
-
-
}
}
}
stop_translation_timestep ();
+
+ apply_finalizations ();
check_removal ();
if (!elem)
programming_error ("Score_engraver: empty elt\n");
else
-
elems_.push (elem);
}
void
Sequential_iterator::do_quit ()
{
- if (iter_) iter_->quit();
+ if (iter_)
+ iter_->quit();
}