X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fscore-element.cc;h=b489d299896b5d7aab16332bd37599443affcf68;hb=5cbe821608ec464ea8f418cba15f012b9b1cad80;hp=654469111fbb5e62258d449581356f2c8e1f4da9;hpb=463b2c0ee322d149eeaa4cf0fb36cd8712d334ce;p=lilypond.git diff --git a/lily/score-element.cc b/lily/score-element.cc index 654469111f..b489d29989 100644 --- a/lily/score-element.cc +++ b/lily/score-element.cc @@ -8,7 +8,10 @@ #include +#include +#include "input-smob.hh" +#include "libc-extension.hh" #include "group-interface.hh" #include "misc.hh" #include "paper-score.hh" @@ -28,6 +31,8 @@ #include "side-position-interface.hh" #include "item.hh" +#include "ly-smobs.icc" + /* TODO: @@ -35,44 +40,65 @@ remove dynamic_cast and put this code into respective subclass. */ -Score_element::Score_element() -{ - dim_cache_[X_AXIS] = new Dimension_cache; - dim_cache_[Y_AXIS] = new Dimension_cache; - dim_cache_[X_AXIS]->elt_l_ = dim_cache_[Y_AXIS]->elt_l_ = this; - // junkme. - used_b_ = false; +#define INFINITY_MSG "Infinity or NaN encountered" + +Score_element::Score_element(SCM basicprops) +{ + /* + fixme: default should be no callback. + */ - dim_cache_[X_AXIS]->set_extent_callback (molecule_extent); - dim_cache_[Y_AXIS]->set_extent_callback (molecule_extent); - used_b_ = false; pscore_l_=0; lookup_l_ =0; status_i_ = 0; - self_scm_ = SCM_EOL; original_l_ = 0; - element_property_alist_ = SCM_EOL; + immutable_property_alist_ = basicprops; + mutable_property_alist_ = SCM_EOL; smobify_self (); + char const*onames[] = {"X-offset-callbacks", "Y-offset-callbacks"}; + char const*enames[] = {"X-extent-callback", "Y-extent-callback"}; + + for (int a = X_AXIS; a <= Y_AXIS; a++){ + SCM l = get_elt_property (onames[a]); + + if (scm_ilength (l) >=0) + { + dim_cache_[a].offset_callbacks_ = l; + dim_cache_[a].offsets_left_ = scm_ilength (l); + } + else + { + programming_error ("[XY]-offset-callbacks must be a list"); + } + + SCM cb = get_elt_property (enames[a]); + + /* + Should change default to be empty? + */ + if (!gh_procedure_p (cb) && !gh_pair_p (cb)) + cb = molecule_extent_proc; + + dim_cache_[a].dimension_ = cb; + } - set_elt_property ("dependencies", SCM_EOL); - set_elt_property ("interfaces", SCM_EOL); + SCM meta = get_elt_property ("meta"); + SCM ifs = scm_assoc (ly_symbol2scm ("interfaces"), meta); + + set_elt_property ("interfaces",gh_cdr (ifs)); } Score_element::Score_element (Score_element const&s) + : dim_cache_ (s.dim_cache_) { - dim_cache_[X_AXIS] = new Dimension_cache (*s.dim_cache_[X_AXIS]); - dim_cache_[Y_AXIS] = new Dimension_cache (*s.dim_cache_[Y_AXIS]); - dim_cache_[X_AXIS]->elt_l_ = dim_cache_[Y_AXIS]->elt_l_ = this; - - self_scm_ = SCM_EOL; - used_b_ = true; original_l_ =(Score_element*) &s; - element_property_alist_ = SCM_EOL; // onstack; - + immutable_property_alist_ = s.immutable_property_alist_; + mutable_property_alist_ = SCM_EOL; + status_i_ = s.status_i_; lookup_l_ = s.lookup_l_; pscore_l_ = s.pscore_l_; @@ -82,71 +108,96 @@ Score_element::Score_element (Score_element const&s) Score_element::~Score_element() { - assert (status_i_ >=0); - status_i_ = -1; - - delete dim_cache_[X_AXIS]; - delete dim_cache_[Y_AXIS]; + /* + do nothing scm-ish and no unprotecting here. + */ } -// should also have one that takes SCM arg. + SCM -Score_element::get_elt_property (String nm) const +Score_element::get_elt_property (const char *nm) const { - SCM sym = ly_symbol2scm (nm.ch_C()); - SCM s = scm_assq(sym, element_property_alist_); + SCM sym = ly_symbol2scm (nm); + return get_elt_property (sym); +} +SCM +Score_element::get_elt_property (SCM sym) const +{ + SCM s = scm_sloppy_assq(sym, mutable_property_alist_); if (s != SCM_BOOL_F) - return gh_cdr (s); - - if (pscore_l_) - { - SCM sym2 = ly_symbol2scm ((name () + ("::" + nm)).ch_C()); - SCM val; - - // should probably check for Type::sym as well. - Paper_def * p= pscore_l_->paper_l_; - if (p->default_properties_.try_retrieve (sym2, &val)) - return val; - else if (p->default_properties_.try_retrieve (sym, &val)) - return val; - } - - return SCM_UNDEFINED; + return gh_cdr (s); + + s = scm_sloppy_assq (sym, immutable_property_alist_); + return (s == SCM_BOOL_F) ? SCM_EOL : gh_cdr (s); } +/* + Remove the value associated with KEY, and return it. The result is + that a next call will yield SCM_UNDEFINED (and not the underlying + `basic' property. +*/ SCM -Score_element::remove_elt_property (String key) +Score_element::remove_elt_property (const char* key) { - SCM s = get_elt_property (key); - SCM sym = ly_symbol2scm (key.ch_C()); - element_property_alist_ = scm_assq_remove_x (element_property_alist_, sym); - return s; + SCM val = get_elt_property (key); + if (val != SCM_EOL) + set_elt_property (key, SCM_EOL); + return val; +} + +void +Score_element::set_elt_property (const char* k, SCM v) +{ + SCM s = ly_symbol2scm (k); + set_elt_property (s, v); } /* - UGH. assoc vs. assq + Puts the k, v in the immutable_property_alist_, which is convenient for + storing variables that are needed during the breaking process. (eg. + Line_of_score::rank : int ) */ void -Score_element::set_elt_property (String k, SCM v) +Score_element::set_immutable_elt_property (const char*k, SCM v) { - SCM s = ly_symbol2scm (k.ch_C( )); - element_property_alist_ = scm_assoc_set_x (element_property_alist_, s, v); + SCM s = ly_symbol2scm (k); + set_immutable_elt_property (s, v); } -Interval -Score_element::molecule_extent (Dimension_cache const *c) +void +Score_element::set_immutable_elt_property (SCM s, SCM v) +{ + immutable_property_alist_ = gh_cons (gh_cons (s,v), mutable_property_alist_); + mutable_property_alist_ = scm_assq_remove_x (mutable_property_alist_, s); +} +void +Score_element::set_elt_property (SCM s, SCM v) { - Score_element *s = dynamic_cast(c->element_l()); - Molecule m = s->do_brew_molecule(); - return m.extent()[c->axis ()]; + mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, s, v); } -Interval -Score_element::preset_extent (Dimension_cache const *c) + +MAKE_SCHEME_CALLBACK(Score_element,molecule_extent,2); +SCM +Score_element::molecule_extent (SCM element_smob, SCM scm_axis) +{ + Score_element *s = unsmob_element (element_smob); + Axis a = (Axis) gh_scm2int (scm_axis); + + Molecule m = s->get_molecule (); + return ly_interval2scm ( m.extent(a)); +} + +MAKE_SCHEME_CALLBACK(Score_element,preset_extent,2); + +SCM +Score_element::preset_extent (SCM element_smob, SCM scm_axis) { - Score_element *s = dynamic_cast(c->element_l()); - SCM ext = s->get_elt_property ((c->axis () == X_AXIS) + Score_element *s = unsmob_element (element_smob); + Axis a = (Axis) gh_scm2int (scm_axis); + + SCM ext = s->get_elt_property ((a == X_AXIS) ? "extent-X" : "extent-Y"); @@ -156,29 +207,13 @@ Score_element::preset_extent (Dimension_cache const *c) Real r = gh_scm2double (gh_cdr (ext)); l *= s->paper_l ()->get_var ("staffspace"); r *= s->paper_l ()->get_var ("staffspace"); - return Interval (l, r); + return ly_interval2scm (Interval (l, r)); } - return Interval (); + return ly_interval2scm ( Interval ()); } -void -Score_element::print() const -{ -#ifndef NPRINT - DEBUG_OUT << classname(this) << "{\n"; - - if (flower_dstream && !flower_dstream->silent_b ("Score_element")) - ly_display_scm (element_property_alist_); - - if (original_l_) - DEBUG_OUT << "Copy "; - do_print(); - - DEBUG_OUT << "}\n"; -#endif -} Paper_def* Score_element::paper_l () const @@ -189,10 +224,13 @@ Score_element::paper_l () const Lookup const * Score_element::lookup_l () const { + /* + URG junkthis, caching is clumsy. + */ if (!lookup_l_) { Score_element * urg = (Score_element*)this; - SCM sz = urg->remove_elt_property ("fontsize"); + SCM sz = urg->remove_elt_property ("font-relative-size"); int i = (gh_number_p (sz)) ? gh_scm2int (sz) : 0; @@ -203,19 +241,7 @@ Score_element::lookup_l () const } void -Score_element::add_processing() -{ - assert (status_i_ >=0); - if (status_i_) - return; - status_i_ ++; - - do_add_processing(); -} - -void -Score_element::calculate_dependencies (int final, int busy, - Score_element_method_pointer funcptr) +Score_element::calculate_dependencies (int final, int busy, SCM funcname) { assert (status_i_ >=0); @@ -233,33 +259,52 @@ Score_element::calculate_dependencies (int final, int busy, for (SCM d= get_elt_property ("dependencies"); gh_pair_p (d); d = gh_cdr (d)) { unsmob_element (gh_car (d)) - ->calculate_dependencies (final, busy, funcptr); + ->calculate_dependencies (final, busy, funcname); } - (this->*funcptr)(); + // ughugh. + String s = ly_symbol2string (funcname); + SCM proc = get_elt_property (s.ch_C()); + if (gh_procedure_p (proc)) + gh_call1 (proc, this->self_scm ()); + status_i_= final; + } -void -Score_element::output_processing () +Molecule +Score_element::get_molecule () const { - if (to_boolean (get_elt_property ("transparent"))) - return; + SCM proc = get_elt_property ("molecule-callback"); - Molecule m (do_brew_molecule ()); - Offset o (relative_coordinate (0, X_AXIS), relative_coordinate (0, Y_AXIS)); + SCM mol = SCM_EOL; + if (gh_procedure_p (proc)) + mol = gh_apply (proc, gh_list (this->self_scm (), SCM_UNDEFINED)); - SCM s = get_elt_property ("extra-offset"); - if (gh_pair_p (s)) + + SCM origin =get_elt_property ("origin"); + if (!unsmob_input (origin)) + origin =ly_symbol2scm ("no-origin"); + + if (gh_pair_p (mol)) { - Real il = paper_l ()->get_var ("interline"); - o[X_AXIS] += il * gh_scm2double (gh_car (s)); - o[Y_AXIS] += il * gh_scm2double (gh_cdr (s)); + // ugr. + mol = gh_cons (gh_list (origin, gh_car (mol), SCM_UNDEFINED), gh_cdr (mol)); } - - line_l ()->output_molecule (m.expr_, o); + + + Molecule m (create_molecule (mol)); + + /* + transparent retains dimensions of element. + */ + if (to_boolean (get_elt_property ("transparent"))) + m = Molecule (m.extent_box (), SCM_EOL); + + return m; } + /* VIRTUAL STUBS @@ -270,47 +315,9 @@ Score_element::do_break_processing() { } -void -Score_element::after_line_breaking () -{ -} - -void -Score_element::before_line_breaking () -{ -} - -void -Score_element::do_space_processing () -{ -} - -void -Score_element::do_add_processing() -{ -} -/* - ugh. - */ -Molecule -Score_element::do_brew_molecule() const -{ - SCM glyph = get_elt_property ("glyph"); - if (gh_string_p (glyph)) - { - return lookup_l ()->afm_find (String (ly_scm2string (glyph))); - - } - else - { - Molecule m ; - m.set_empty (true); - return m; - } -} Line_of_score * @@ -324,8 +331,8 @@ Score_element::add_dependency (Score_element*e) { if (e) { - Group_interface gi (this, "dependencies"); - gi.add_element (e); + Pointer_group_interface ::add_element (this, "dependencies",e); + } else programming_error ("Null dependency added"); @@ -353,25 +360,31 @@ Score_element::handle_broken_smobs (SCM src, SCM criterion) if (i && i->break_status_dir () != d) { Item *br = i->find_prebroken_piece (d); - return (br) ? br->self_scm_ : SCM_UNDEFINED; + return (br) ? br->self_scm () : SCM_UNDEFINED; } } else { - Line_of_score * line = dynamic_cast (unsmob_element ( criterion)); - Line_of_score * dep_line = sc->line_l (); - if (dep_line != line) + Line_of_score * line + = dynamic_cast (unsmob_element (criterion)); + if (sc->line_l () != line) { - Score_element * br = sc->find_broken_piece (line); - return (br) ? br->self_scm_ : SCM_UNDEFINED; + sc = sc->find_broken_piece (line); + } - if (line - && (!dep_line - || !sc->common_refpoint (line, X_AXIS) - || !sc->common_refpoint (line, Y_AXIS))) + + /* now: !sc || (sc && sc->line_l () == line) */ + if (!sc) + return SCM_UNDEFINED; + + /* now: sc && sc->line_l () == line */ + if (!line + || (sc->common_refpoint (line, X_AXIS) + && sc->common_refpoint (line, Y_AXIS))) { - return SCM_UNDEFINED; + return sc->self_scm (); } + return SCM_UNDEFINED; } } else if (gh_pair_p (src)) @@ -419,9 +432,9 @@ Score_element::handle_broken_dependencies() { Score_element * sc = s->broken_into_l_arr_[i]; Line_of_score * l = sc->line_l (); - s->broken_into_l_arr_[i]->element_property_alist_ = - handle_broken_smobs (element_property_alist_, - l ? l->self_scm_ : SCM_UNDEFINED); + sc->mutable_property_alist_ = + handle_broken_smobs (mutable_property_alist_, + l ? l->self_scm () : SCM_UNDEFINED); } } @@ -430,40 +443,52 @@ Score_element::handle_broken_dependencies() if (line && common_refpoint (line, X_AXIS) && common_refpoint (line, Y_AXIS)) { - element_property_alist_ - = handle_broken_smobs (element_property_alist_, - line ? line->self_scm_ : SCM_UNDEFINED); + mutable_property_alist_ + = handle_broken_smobs (mutable_property_alist_, + line ? line->self_scm () : SCM_UNDEFINED); } - else if (!dynamic_cast (this)) + else if (dynamic_cast (this)) + { + mutable_property_alist_ = handle_broken_smobs (mutable_property_alist_, + SCM_UNDEFINED); + } + else { /* This element is `invalid'; it has been removed from all dependencies, so let's junk the element itself. - do not do this for Line_of_score , since that would free - up originals of score-elts (a bad thing.) + do not do this for Line_of_score, since that would remove + references to the originals of score-elts, which get then GC'd + (a bad thing.) */ - - element_property_alist_ = SCM_EOL; - set_extent_callback (0, Y_AXIS); - set_extent_callback (0, X_AXIS); + suicide(); } } +/* + Note that we still want references to this element to be + rearranged, and not silently thrown away, so we keep pointers + like {broken_into_{drul,array}, original} +*/ void -Score_element::handle_prebroken_dependencies() +Score_element::suicide () { -} + mutable_property_alist_ = SCM_EOL; + immutable_property_alist_ = SCM_EOL; + set_extent_callback (SCM_EOL, Y_AXIS); + set_extent_callback (SCM_EOL, X_AXIS); -bool -Score_element::linked_b() const -{ - return used_b_; + for (int a= X_AXIS; a <= Y_AXIS; a++) + { + dim_cache_[a].offset_callbacks_ = SCM_EOL; + dim_cache_[a].offsets_left_ = 0; + } } void -Score_element::do_print () const +Score_element::handle_prebroken_dependencies() { } @@ -476,38 +501,101 @@ Score_element::find_broken_piece (Line_of_score*) const void Score_element::translate_axis (Real y, Axis a) { - dim_cache_[a]->translate (y); + if (isinf (y) || isnan (y)) + programming_error (_(INFINITY_MSG)); + else + { + dim_cache_[a].offset_ += y; + } } Real -Score_element::relative_coordinate (Score_element const*e, Axis a) const +Score_element::relative_coordinate (Score_element const*refp, Axis a) const { - return dim_cache_[a]->relative_coordinate (e ? e->dim_cache_[a] : 0); + if (refp == this) + return 0.0; + + /* + We catch PARENT_L_ == nil case with this, but we crash if we did + not ask for the absolute coordinate (ie. REFP == nil.) + + */ + if (refp == dim_cache_[a].parent_l_) + return get_offset (a); + else + return get_offset (a) + dim_cache_[a].parent_l_->relative_coordinate (refp, a); } -Score_element * -Score_element::common_refpoint (Score_element const* s, Axis a) const +Real +Score_element::get_offset (Axis a) const { - Dimension_cache *dim = dim_cache_[a]->common_refpoint (s->dim_cache_[a]); - return dim ? dim->element_l () : 0; + Score_element *me = (Score_element*) this; + while (dim_cache_[a].offsets_left_) + { + int l = --me->dim_cache_[a].offsets_left_; + SCM cb = scm_list_ref (dim_cache_[a].offset_callbacks_, gh_int2scm (l)); + SCM retval = gh_call2 (cb, self_scm (), gh_int2scm (a)); + + Real r = gh_scm2double (retval); + if (isinf (r) || isnan (r)) + { + programming_error (INFINITY_MSG); + r = 0.0; + } + me->dim_cache_[a].offset_ +=r; + } + return dim_cache_[a].offset_; +} + + +MAKE_SCHEME_CALLBACK(Score_element,point_dimension_callback,2); +SCM +Score_element::point_dimension_callback (SCM , SCM ) +{ + return ly_interval2scm ( Interval (0,0)); } bool Score_element::empty_b (Axis a)const { - return !dim_cache_[a]->extent_callback_l_; + return ! (gh_pair_p (dim_cache_[a].dimension_ ) || + gh_procedure_p (dim_cache_[a].dimension_ )); } +/* + TODO: add + + Score_element *refpoint + + to arguments? + */ Interval -Score_element::extent (Axis a) const +Score_element::extent (Score_element * refp, Axis a) const { - Dimension_cache const * d = dim_cache_[a]; - Interval ext = d->get_dim (); + Real x = relative_coordinate (refp, a); - if (empty_b (a)) + + Dimension_cache * d = (Dimension_cache *)&dim_cache_[a]; + Interval ext ; + if (gh_pair_p (d->dimension_)) + ; + else if (gh_procedure_p (d->dimension_)) + { + /* + FIXME: add doco on types, and should typecheck maybe? + */ + d->dimension_= gh_call2 (d->dimension_, self_scm(), gh_int2scm (a)); + } + else return ext; - SCM extra = get_elt_property (a == X_AXIS ? "extra-extent-X" + if (!gh_pair_p (d->dimension_)) + return ext; + + ext = ly_scm2interval (d->dimension_); + + SCM extra = get_elt_property (a == X_AXIS + ? "extra-extent-X" : "extra-extent-Y"); /* @@ -528,6 +616,8 @@ Score_element::extent (Axis a) const ext.unite (Interval (s * gh_scm2double (gh_car (extra)), s * gh_scm2double (gh_cdr (extra)))); } + + ext.translate (x); return ext; } @@ -536,76 +626,109 @@ Score_element::extent (Axis a) const Score_element* Score_element::parent_l (Axis a) const { - Dimension_cache*d= dim_cache_[a]->parent_l_; - return d ? d->elt_l_ : 0; + return dim_cache_[a].parent_l_; } +Score_element * +Score_element::common_refpoint (Score_element const* s, Axis a) const +{ + /* + I don't like the quadratic aspect of this code, but I see no other + way. The largest chain of parents might be 10 high or so, so + it shouldn't be a real issue. */ + for (Score_element const *c = this; c; c = c->dim_cache_[a].parent_l_) + for (Score_element const * d = s; d; d = d->dim_cache_[a].parent_l_) + if (d == c) + return (Score_element*)d; + + return 0; +} + + Score_element * -Score_element::common_refpoint (Link_array gs, Axis a) const +Score_element::common_refpoint (SCM elist, Axis a) const { - Dimension_cache * common = dim_cache_[a]; - for (int i=0; i < gs.size (); i++) + Score_element * common = (Score_element*) this; + for (; gh_pair_p (elist); elist = gh_cdr (elist)) { - common = common->common_refpoint (gs[i]->dim_cache_[a]); + Score_element * s = unsmob_element (gh_car (elist)); + if (s) + common = common->common_refpoint (s, a); } - return common->element_l (); + return common; } -char const * +String Score_element::name () const { - return classname (this); + SCM meta = get_elt_property ("meta"); + SCM nm = scm_assoc (ly_symbol2scm ("name"), meta); + nm = (gh_pair_p (nm)) ? gh_cdr (nm) : SCM_EOL; + return gh_string_p (nm) ?ly_scm2string (nm) : classname (this); } void -Score_element::add_offset_callback (Offset_cache_callback cb, Axis a) +Score_element::add_offset_callback (SCM cb, Axis a) { - dim_cache_[a]->off_callbacks_.push (cb); + if (!has_offset_callback_b (cb, a)) + { + dim_cache_[a].offset_callbacks_ = gh_cons (cb, dim_cache_[a].offset_callbacks_ ); + dim_cache_[a].offsets_left_ ++; + } } bool -Score_element::has_offset_callback_b (Offset_cache_callback cb, Axis a)const +Score_element::has_extent_callback_b (SCM cb, Axis a)const { - for (int i= dim_cache_[a]->off_callbacks_.size (); i--;) - { - if (dim_cache_[a]->off_callbacks_[i] == cb) - return true; - } - return false; + return scm_equal_p (cb, dim_cache_[a].dimension_); +} + + +bool +Score_element::has_extent_callback_b (Axis a) const +{ + return gh_procedure_p (dim_cache_[a].dimension_); +} + +bool +Score_element::has_offset_callback_b (SCM cb, Axis a)const +{ + return scm_memq (cb, dim_cache_[a].offset_callbacks_) != SCM_BOOL_F; } void -Score_element::set_extent_callback (Dim_cache_callback dc, Axis a) +Score_element::set_extent_callback (SCM dc, Axis a) { - dim_cache_[a]->extent_callback_l_ = dc ; + dim_cache_[a].dimension_ =dc; } - void Score_element::set_parent (Score_element *g, Axis a) { - dim_cache_[a]->parent_l_ = g ? g->dim_cache_[a]: 0; + dim_cache_[a].parent_l_ = g; } -void -Score_element::fixup_refpoint () +MAKE_SCHEME_CALLBACK(Score_element,fixup_refpoint,1); +SCM +Score_element::fixup_refpoint (SCM smob) { + Score_element *me = unsmob_element (smob); for (int a = X_AXIS; a < NO_AXES; a ++) { Axis ax = (Axis)a; - Score_element * parent = parent_l (ax); + Score_element * parent = me->parent_l (ax); if (!parent) continue; - if (parent->line_l () != line_l () && line_l ()) + if (parent->line_l () != me->line_l () && me->line_l ()) { - Score_element * newparent = parent->find_broken_piece (line_l ()); - set_parent (newparent, ax); + Score_element * newparent = parent->find_broken_piece (me->line_l ()); + me->set_parent (newparent, ax); } - if (Item * i = dynamic_cast (this)) + if (Item * i = dynamic_cast (me)) { Item *parenti = dynamic_cast (parent); @@ -615,11 +738,12 @@ Score_element::fixup_refpoint () if (my_dir!= parenti->break_status_dir()) { Item *newparent = parenti->find_prebroken_piece (my_dir); - set_parent (newparent, ax); + me->set_parent (newparent, ax); } } } } + return smob; } @@ -628,21 +752,32 @@ Score_element::fixup_refpoint () SMOB funcs ****************************************************/ -#include "ly-smobs.icc" IMPLEMENT_UNSMOB(Score_element, element); IMPLEMENT_SMOBS(Score_element); +IMPLEMENT_DEFAULT_EQUAL_P(Score_element); SCM Score_element::mark_smob (SCM ses) { - Score_element * s = SMOB_TO_TYPE (Score_element, ses); - if (s->self_scm_ != ses) + Score_element * s = (Score_element*) SCM_CELL_WORD_1(ses); + scm_gc_mark (s->immutable_property_alist_); + scm_gc_mark (s->mutable_property_alist_); + + for (int a =0 ; a < 2; a++) { - programming_error ("SMOB marking gone awry"); - return SCM_EOL; + scm_gc_mark (s->dim_cache_[a].offset_callbacks_); + scm_gc_mark (s->dim_cache_[a].dimension_); } - return s->element_property_alist_; + + if (s->parent_l (Y_AXIS)) + scm_gc_mark (s->parent_l (Y_AXIS)->self_scm ()); + if (s->parent_l (X_AXIS)) + scm_gc_mark (s->parent_l (X_AXIS)->self_scm ()); + + if (s->original_l_) + scm_gc_mark (s->original_l_->self_scm ()); + return s->do_derived_mark (); } int @@ -651,7 +786,7 @@ Score_element::print_smob (SCM s, SCM port, scm_print_state *) Score_element *sc = (Score_element *) gh_cdr (s); scm_puts ("#name (), port); + scm_puts ((char *)sc->name ().ch_C(), port); /* don't try to print properties, that is too much hassle. @@ -660,20 +795,15 @@ Score_element::print_smob (SCM s, SCM port, scm_print_state *) return 1; } -void -Score_element::do_smobify_self () -{ -} - SCM -Score_element::equal_p (SCM a, SCM b) +Score_element::do_derived_mark () { - return gh_cdr(a) == gh_cdr(b) ? SCM_BOOL_T : SCM_BOOL_F; + return SCM_EOL; } SCM -Score_element::ly_set_elt_property (SCM elt, SCM sym, SCM val) +ly_set_elt_property (SCM elt, SCM sym, SCM val) { Score_element * sc = unsmob_element (elt); @@ -681,12 +811,12 @@ Score_element::ly_set_elt_property (SCM elt, SCM sym, SCM val) { error ("Not a symbol"); ly_display_scm (sym); - return SCM_UNDEFINED; + return SCM_UNSPECIFIED; } if (sc) { - sc->element_property_alist_ = scm_assoc_set_x (sc->element_property_alist_, sym, val); + sc->set_elt_property (sym, val); } else { @@ -694,43 +824,74 @@ Score_element::ly_set_elt_property (SCM elt, SCM sym, SCM val) ly_display_scm (elt); } - return SCM_UNDEFINED; + return SCM_UNSPECIFIED; } SCM -Score_element::ly_get_elt_property (SCM elt, SCM sym) +ly_get_elt_property (SCM elt, SCM sym) { Score_element * sc = unsmob_element (elt); if (sc) { - SCM s = scm_assq(sym, sc->element_property_alist_); - - if (s != SCM_BOOL_F) - return gh_cdr (s); - else - return SCM_UNDEFINED; + return sc->get_elt_property (sym); } else { error ("Not a score element"); ly_display_scm (elt); } - return SCM_UNDEFINED; + return SCM_UNSPECIFIED; +} + + +void +Score_element::discretionary_processing() +{ +} + + + +SCM +spanner_get_bound (SCM slur, SCM dir) +{ + return dynamic_cast (unsmob_element (slur))->get_bound (to_dir (dir))->self_scm (); } + +static SCM interfaces_sym; static void init_functions () { - scm_make_gsubr ("ly-get-elt-property", 2, 0, 0, (SCM(*)(...))Score_element::ly_get_elt_property); - scm_make_gsubr ("ly-set-elt-property", 3, 0, 0, (SCM(*)(...))Score_element::ly_set_elt_property); + interfaces_sym = scm_permanent_object (ly_symbol2scm ("interfaces")); + + scm_make_gsubr ("ly-get-elt-property", 2, 0, 0, (Scheme_function_unknown)ly_get_elt_property); + scm_make_gsubr ("ly-set-elt-property", 3, 0, 0, (Scheme_function_unknown)ly_set_elt_property); + scm_make_gsubr ("ly-get-spanner-bound", 2 , 0, 0, (Scheme_function_unknown) spanner_get_bound); } -ADD_SCM_INIT_FUNC(scoreelt, init_functions); +bool +Score_element::has_interface (SCM k) +{ + SCM ifs = get_elt_property (interfaces_sym); + + return scm_memq (k, ifs) != SCM_BOOL_F; +} void -Score_element::do_breakable_col_processing () +Score_element::set_interface (SCM k) { + if (has_interface (k)) + return ; + else + { + set_elt_property (interfaces_sym, + gh_cons (k, get_elt_property (interfaces_sym))); + } } + + +ADD_SCM_INIT_FUNC(scoreelt, init_functions); +IMPLEMENT_TYPE_P(Score_element, "ly-element?");