--- /dev/null
+#!/usr/bin/perl -w
+
+die "arg needed\n" if (!($#ARGV+1));
+my $fn = $ARGV[0];
+my $hh_q = ($fn =~ /hh$/ );
+my $MAILADRESS=$ENV{MAILADRESS};
+my @pw=(getpwuid($<));
+my $username=$pw[6];
+my $what="implement ";
+$what = "declare " if ($hh_q);
+my $headstr ="/*
+ $fn -- $what
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 $username <$MAILADRESS>
+*/\n";
+
+my $startdef= $fn;
+$startdef =~ s/[\.-]/_/g;
+$startdef =~ tr/a-z/A-Z/;
+my $terminatestr="\n";
+if ($hh_q) {
+ $headstr .= "\n\n#ifndef $startdef\n#define $startdef\n";
+ $terminatestr .= "#endif // $startdef\n"
+}
+
+print $headstr, $terminatestr;
+
+
+
--- /dev/null
+/*
+ input-file.hh -- declare Input_file
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef INPUT_FILE_HH
+#define INPUT_FILE_HH
+#include <FlexLexer.h>
+#include "proto.hh"
+#include "fproto.hh"
+#include "varray.hh"
+#include "string.hh"
+
+struct Input_file {
+ istream* is;
+ char const* defined_ch_c_l_;
+ Source_file* sourcefile_l_;
+ int line;
+ String name;
+
+ Input_file(String);
+ ~Input_file();
+};
+
+#endif // INPUT_FILE_HH
--- /dev/null
+//
+// source-file.hh -- declare Source_file
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef SOURCE_FILE_HH
+#define SOURCE_FILE_HH
+
+/// class for reading and mapping a file.
+class Source_file
+{
+public:
+ /** Ugh! filename gets changed! The path to the opened file may
+ change, since it might be searched in multiple directories. */
+ Source_file( String& filename_str_r );
+ virtual ~Source_file();
+
+ char const* ch_c_l();
+ virtual String error_str( char const* pos_ch_c_l );
+ istream* istream_l();
+ bool in_b( char const* pos_ch_c_l );
+ off_t length_off();
+ virtual int line_i( char const* pos_ch_c_l );
+ String name_str();
+ String file_line_no_str( char const* ch_c_l );
+
+private:
+ void close();
+ void map();
+ void open();
+ void unmap();
+
+ istream* istream_p_;
+ int fildes_i_;
+ String name_str_;
+ off_t size_off_;
+ caddr_t data_caddr_;
+};
+
+#endif // SOURCE_FILE_HH //
--- /dev/null
+/*
+ input-file.cc -- implement Input_file
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl> Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+#include <iostream.h>
+#include <strstream.h>
+#include "proto.hh"
+#include "plist.hh"
+#include "input-file.hh"
+#include "debug.hh"
+#include "source-file.hh"
+#include "binary-source-file.hh"
+#include "source.hh"
+
+Input_file::Input_file(String s)
+{
+ name = s;
+ line = 1;
+ String pf(s);
+ if ( pf == "" ) {
+ is = &cin;
+ defined_ch_c_l_ = 0;
+ sourcefile_l_ = 0;
+ }
+ else {
+ Source_file* sourcefile_p = 0;
+ // ugh, very dirty, need to go away
+ if ( ( pf.right_str( 3 ).lower_str() == "mid" ) || ( pf.right_str( 4 ).lower_str() == "midi" ) )
+ sourcefile_p = new Binary_source_file( pf );
+ else
+ sourcefile_p = new Source_file( pf );
+ source_l_g->add( sourcefile_p );
+ sourcefile_l_ = sourcefile_p;
+ is = sourcefile_l_->istream_l();
+ defined_ch_c_l_ = sourcefile_l_->ch_c_l();
+ }
+ cout << "[" << pf << flush;
+}
+
+Input_file::~Input_file()
+{
+ cout << "]" << flush;
+}
--- /dev/null
+//
+// source.cc
+//
+
+#include <assert.h>
+
+#include "string.hh"
+#include "proto.hh"
+#include "plist.hh"
+
+#include "source-file.hh"
+#include "source.hh"
+
+Source::Source()
+{
+}
+
+Source::~Source()
+{
+}
+
+void
+Source::add( Source_file* sourcefile_p )
+{
+ sourcefile_p_iplist_.bottom().add( sourcefile_p );
+}
+
+Source_file*
+Source::sourcefile_l( char const* ch_c_l )
+{
+ PCursor<Source_file*> sourcefile_l_pcur( sourcefile_p_iplist_.top() );
+ for ( ; sourcefile_l_pcur.ok(); sourcefile_l_pcur++ )
+ if ( sourcefile_l_pcur->in_b( ch_c_l ) )
+ return *sourcefile_l_pcur;
+ return 0;
+}
--- /dev/null
+/*
+ bar-reg.cc -- implement Bar_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "bar-reg.hh"
+#include "bar.hh"
+#include "commandrequest.hh"
+#include "score-column.hh"
+#include "time-description.hh"
+
+Bar_register::Bar_register()
+{
+ post_move_processing();
+}
+
+bool
+Bar_register::try_request(Request*r_l)
+{
+ Command_req* c_l = r_l->command();
+ if (!c_l|| !c_l->bar())
+ return false;
+
+ assert(!bar_req_l_);
+ bar_req_l_ = c_l->bar();
+
+ return true;
+}
+
+void
+Bar_register::process_requests()
+{
+ if (bar_req_l_ ) {
+ bar_p_ = new Bar(bar_req_l_->type_str_);
+ } else if (!get_staff_info().time_c_l_->whole_in_measure_) {
+ bar_p_ = new Bar("|");
+ }
+
+ if (bar_p_){
+ announce_element(Staff_elem_info(bar_p_, bar_req_l_) );
+ }
+}
+
+void
+Bar_register::split_bar(Bar *& pre, Bar * no, Bar * &post)
+{
+ String s= no->type;
+ if (s == ":|:") {
+ pre = new Bar(":|");
+ post = new Bar("|:");
+ }else if (s=="|:") {
+ post = new Bar(s);
+ } else {
+ pre = new Bar(*no);
+ }
+}
+
+void
+Bar_register::pre_move_processing()
+{
+ if (bar_p_) {
+ Bar * post_p =0;
+ Bar * pre_p =0;
+ split_bar(pre_p, bar_p_, post_p);
+
+ typeset_breakable_item(pre_p, bar_p_, post_p);
+ bar_p_ =0;
+ }
+}
+
+void
+Bar_register::post_move_processing()
+{
+ bar_req_l_ = 0;
+ bar_p_ =0;
+}
--- /dev/null
+#include "bar.hh"
+#include "string.hh"
+#include "molecule.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "debug.hh"
+
+
+
+Bar::Bar( String t)
+{
+ type = t;
+}
+
+void
+Bar::do_print()const
+{
+ mtor << type;
+}
+
+Molecule*
+Bar::brew_molecule_p()const
+{
+ Symbol s = paper()->lookup_p_->bar(type);
+ Molecule*output = new Molecule(Atom(s));
+ return output;
+}
+
--- /dev/null
+#include "varray.hh"
+
+#include "dimen.hh"
+#include "beam.hh"
+#include "misc.hh"
+#include "debug.hh"
+#include "symbol.hh"
+#include "molecule.hh"
+#include "leastsquares.hh"
+#include "pcol.hh"
+#include "stem.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "grouping.hh"
+
+
+
+struct Stem_info {
+ Real x;
+ Real idealy;
+ Real miny;
+ int no_beams;
+
+
+ Stem_info(){}
+ Stem_info(const Stem*);
+};
+
+Stem_info::Stem_info(const Stem*s)
+{
+ x = s->hindex();
+ int dir = s->dir;
+ idealy = max(dir*s->top, dir*s->bot);
+ miny = max(dir*s->minnote, dir*s-> maxnote);
+ assert(miny <= idealy);
+
+}
+
+/* *************** */
+
+Offset
+Beam::center()const
+{
+ assert(status >= POSTCALCED);
+
+ Real w=(paper()->note_width() + width().length())/2.0;
+ return Offset(w, (left_pos + w* slope)*paper()->internote());
+}
+
+
+Beam::Beam()
+{
+ slope = 0;
+ left_pos = 0.0;
+}
+
+void
+Beam::add(Stem*s)
+{
+ stems.bottom().add(s);
+ s->add_dependency(this);
+ s->print_flag = false;
+}
+
+void
+Beam::set_default_dir()
+{
+ int dirs[2];
+ dirs[0]=0; dirs[1] =0;
+ for (iter_top(stems,i); i.ok(); i++) {
+ int d = i->get_default_dir();
+ dirs[(d+1)/2] ++;
+ }
+ dir_i_ = (dirs[0] > dirs[1]) ? -1 : 1;
+ for (iter_top(stems,i); i.ok(); i++) {
+ i->dir = dir_i_;
+ }
+}
+
+/*
+ should use minimum energy formulation (cf linespacing)
+ */
+void
+Beam::solve_slope()
+{
+ Array<Stem_info> sinfo;
+ for (iter_top(stems,i); i.ok(); i++) {
+ i->set_default_extents();
+ Stem_info info(i);
+ sinfo.push(info);
+ }
+ Real leftx = sinfo[0].x;
+ Least_squares l;
+ for (int i=0; i < sinfo.size(); i++) {
+ sinfo[i].x -= leftx;
+ l.input.push(Offset(sinfo[i].x, sinfo[i].idealy));
+ }
+
+ l.minimise(slope, left_pos);
+ Real dy = 0.0;
+ for (int i=0; i < sinfo.size(); i++) {
+ Real y = sinfo[i].x * slope + left_pos;
+ Real my = sinfo[i].miny;
+
+ if (my - y > dy)
+ dy = my -y;
+ }
+ left_pos += dy;
+ left_pos *= dir_i_;
+ slope *= dir_i_;
+
+ // URG
+ Real sl = slope*paper()->internote();
+ paper()->lookup_p_->beam(sl, 20 PT);
+ slope = sl /paper()->internote();
+}
+
+void
+Beam::set_stemlens()
+{
+ iter_top(stems,s);
+ Real x0 = s->hindex();
+ for (; s.ok() ; s++) {
+ Real x = s->hindex()-x0;
+ s->set_stemend(left_pos + slope * x);
+ }
+}
+
+
+void
+Beam::do_post_processing()
+{
+ solve_slope();
+ set_stemlens();
+}
+
+void
+Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
+{
+ def.OK();
+ cur.OK();
+ assert(cur.children.size() == stems.size());
+
+ cur.split(def);
+
+ Array<int> b;
+ {
+ iter_top(stems,s);
+ Array<int> flags;
+ for (; s.ok(); s++) {
+ int f = intlog2(abs(s->flag))-2;
+ assert(f>0);
+ flags.push(f);
+ }
+ int fi =0;
+ b= cur.generate_beams(flags, fi);
+ b.insert(0,0);
+ b.push(0);
+ assert(stems.size() == b.size()/2);
+ }
+
+ iter_top(stems,s);
+ for (int i=0; i < b.size() && s.ok(); i+=2, s++) {
+ s->beams_left = b[i];
+ s->beams_right = b[i+1];
+ }
+}
+
+
+// todo.
+Spanner *
+Beam::do_break_at( PCol *, PCol *) const
+{
+ Beam *beam_p= new Beam(*this);
+
+ return beam_p;
+}
+
+void
+Beam::do_pre_processing()
+{
+ left = (*stems.top()) ->pcol_l_;
+ right = (*stems.bottom())->pcol_l_;
+ assert(stems.size()>1);
+ if (!dir_i_)
+ set_default_dir();
+
+}
+
+
+Interval
+Beam::width() const
+{
+ Beam * me = (Beam*) this; // ugh
+ return Interval( (*me->stems.top()) ->hindex(),
+ (*me->stems.bottom()) ->hindex() );
+}
+
+/*
+ beams to go with one stem.
+ */
+Molecule
+Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
+{
+ assert( !next || next->hindex() > here->hindex() );
+ assert( !prev || prev->hindex() < here->hindex() );
+ Real dy=paper()->internote()*2;
+ Real stemdx = paper()->rule_thickness();
+ Real sl = slope*paper()->internote();
+ paper()->lookup_p_->beam(sl, 20 PT);
+
+ Molecule leftbeams;
+ Molecule rightbeams;
+
+ /* half beams extending to the left. */
+ if (prev) {
+ int lhalfs= lhalfs = here->beams_left - prev->beams_right ;
+ int lwholebeams= here->beams_left <? prev->beams_right ;
+ Real w = (here->hindex() - prev->hindex())/4;
+ Symbol dummy;
+ Atom a(dummy);
+ if (lhalfs) // generates warnings if not
+ a = paper()->lookup_p_->beam(sl, w);
+ a.translate(Offset (-w, -w * sl));
+ for (int j = 0; j < lhalfs; j++) {
+ Atom b(a);
+ b.translate(Offset(0, -dir_i_ * dy * (lwholebeams+j)));
+ leftbeams.add( b );
+ }
+ }
+
+ if (next){
+ int rhalfs = here->beams_right - next->beams_left;
+ int rwholebeams = here->beams_right <? next->beams_left;
+
+ Real w = next->hindex() - here->hindex();
+ Atom a = paper()->lookup_p_->beam(sl, w + stemdx);
+
+ int j = 0;
+ for (; j < rwholebeams; j++) {
+ Atom b(a);
+ b.translate(Offset(0, -dir_i_ * dy * j));
+ rightbeams.add( b );
+ }
+
+ w /= 4;
+ if (rhalfs)
+ a = paper()->lookup_p_->beam(sl, w);
+
+ for (; j < rwholebeams + rhalfs; j++) {
+ Atom b(a);
+ b.translate(Offset(0, -dir_i_ * dy * j));
+ rightbeams.add(b );
+ }
+
+ }
+ leftbeams.add(rightbeams);
+ return leftbeams;
+}
+
+
+Molecule*
+Beam::brew_molecule_p() const return out;
+{
+ Real inter=paper()->internote();
+ out = new Molecule;
+ Real x0 = stems.top()->hindex();
+
+ for (iter_top(stems,i); i.ok(); i++) {
+ PCursor<Stem*> p(i-1);
+ PCursor<Stem*> n(i+1);
+ Stem * prev = p.ok() ? p.ptr() : 0;
+ Stem * next = n.ok() ? n.ptr() : 0;
+
+ Molecule sb = stem_beams(i, next, prev);
+ Real x = i->hindex()-x0;
+ sb.translate(Offset(x, (x * slope + left_pos)* inter));
+ out->add(sb);
+ }
+ out->translate(Offset(x0 - left->hpos,0));
+}
+
+void
+Beam::do_print()const
+{
+#ifndef NPRINT
+ mtor << "slope " <<slope << "left ypos " << left_pos;
+ Spanner::print();
+#endif
+}
+
+Beam::~Beam()
+{
+
+}
--- /dev/null
+#include "boxes.hh"
+#include "const.hh"
+#include "varray.hh"
+
+
+Box::Box()
+{
+}
+
+Box::Box(Interval ix, Interval iy)
+{
+ x = ix;
+ y = iy;
+}
+
--- /dev/null
+/*
+ do calculations for breaking problem
+ */
+#include "break.hh"
+#include "paper-def.hh"
+#include "linespace.hh"
+#include "debug.hh"
+#include "scoreline.hh"
+#include "pscore.hh"
+
+
+/*
+ return all breakable columns
+ */
+Line_of_cols
+Break_algorithm::find_breaks() const
+{
+ Line_of_cols retval;
+ for (iter_top(pscore_.cols,c); c.ok(); c++)
+ if (c->breakable_b())
+ retval.push(c);
+ assert(retval.top() == pscore_.cols.bottom().ptr());
+ return retval;
+}
+
+// construct an appropriate Spacing_problem and solve it.
+Col_hpositions
+Break_algorithm::solve_line(Line_of_cols curline) const
+{
+ Spacing_problem sp;
+
+ sp.add_column(curline[0], true, 0.0);
+ for (int i=1; i< curline.size()-1; i++)
+ sp.add_column(curline[i]);
+ sp.add_column(curline.top(), true, linelength);
+
+ // misschien moeven uit Spacing_problem?
+ for (iter_top(pscore_.suz,i); i.ok(); i++) {
+ sp.add_ideal(i);
+ }
+ Array<Real> the_sol=sp.solve();
+ Col_hpositions col_hpos;
+ col_hpos.cols = curline;
+ col_hpos.energy = the_sol.pop();
+ col_hpos.config = the_sol;
+ col_hpos.OK();
+ return col_hpos;
+}
+
+Break_algorithm::Break_algorithm(PScore&s)
+ :pscore_(s)
+{
+ linelength = s.paper_l_->linewidth;
+}
+
+bool
+Break_algorithm::feasible(Line_of_cols curline) const
+{
+ Real l =0;
+ for (int i=0; i < curline.size(); i++)
+ l +=curline[i]->width().length();
+ return l < linelength;
+}
+
+void
+Break_algorithm::problem_OK() const
+{
+ if (!pscore_.cols.size())
+ error("Score does not have any columns");
+#ifndef NDEBUG
+ iter_top(pscore_.cols,start);
+ PCursor<PCol *> end (pscore_.cols.bottom());
+
+ assert(start->breakable_b());
+ assert(end->breakable_b());
+#endif
+}
--- /dev/null
+#include "idealspacing.hh"
+#include "score.hh"
+#include "pscore.hh"
+#include "paper-def.hh"
+#include "score-column.hh"
+#include "dimen.hh"
+
+
+/**
+ this needs A LOT of rethinking.
+
+ generate springs between columns.
+
+ */
+void
+Score::calc_idealspacing()
+{
+ iter_top(cols_,i);
+
+ for (; i.ok(); i++) {
+ assert(i->used_b());
+ PCursor<Score_column*> j(i+1);
+ if (i->musical_b()) {
+ assert(j.ok());
+ for (int n=0; n < i->durations.size(); n++) {
+ Moment d = i->durations[n];
+ Real dist = paper_p_->duration_to_dist(d);
+ Real strength = i->durations[0]/i->durations[n];
+ assert(strength <= 1.0);
+
+ while (j->when() < d + i->when())
+ j++;
+ Moment delta_desired = j->when() - (d+i->when());
+ dist += paper_p_->duration_to_dist(delta_desired);
+
+ pscore_p_->connect(i->pcol_l_, j->pcol_l_, dist, strength);
+ }
+ } else if (j.ok()) {
+
+ /* attach i to the next column in use. This exists, since
+ the last col is breakable, and therefore in use
+ */
+
+ Moment d = j->when() - i->when();
+ Real dist = (d) ? paper_p_->duration_to_dist(d) : 2 PT; // todo
+
+ pscore_p_->connect(i->pcol_l_, j->pcol_l_, dist, (d) ? 1.0:1.0);
+ }
+ // !j.ok() might hold if we're at the last col.
+ }
+}
+
+
--- /dev/null
+/*
+ clef-item.cc -- implement Clef_item
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "clef-item.hh"
+#include "string.hh"
+#include "molecule.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "clef-reg.hh"
+
+
+
+Clef_item::Clef_item()
+{
+ change = true;
+ read("violin");
+}
+
+void
+Clef_item::read(String t)
+{
+ type = t;
+ if (type == "violin")
+ y_off = 2;
+ if (type == "alto")
+ y_off = 4;
+ if (type == "tenor")
+ y_off = 6;
+ if (type == "bass")
+ y_off = 6;
+}
+void
+Clef_item::read(Clef_register const &k)
+{
+ read(k.clef_type_str_);
+}
+
+Molecule*
+Clef_item::brew_molecule_p()const
+{
+ String t = type;
+ if (change)
+ t += "_change";
+ Symbol s = paper()->lookup_p_->clef(t);
+ Molecule*output = new Molecule(Atom(s));
+ output->translate(Offset(0, paper()->internote() * y_off));
+ return output;
+}
+
--- /dev/null
+/*
+ clef.cc -- implement Clef_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>,
+ Mats Bengtsson <matsb@s3.kth.se>
+*/
+
+#include "clef-reg.hh"
+#include "clef-item.hh"
+#include "debug.hh"
+#include "commandrequest.hh"
+#include "time-description.hh"
+#include "staff-column.hh"
+
+Clef_register::Clef_register()
+{
+ clef_p_ = 0;
+
+ /* ugly hack to prevent segfault (daddy_reg_l_ == 0 at construction) */
+ clef_type_str_ = "";
+}
+
+bool
+Clef_register::set_type(String s)
+{
+ clef_type_str_ = s;
+ if (clef_type_str_ == "violin") {
+ c0_position_i_= -2;
+ } else if (clef_type_str_ == "alto") {
+ c0_position_i_= 4;
+ } else if (clef_type_str_ == "tenor") {
+ c0_position_i_= 6;
+ } else if (clef_type_str_ == "bass") {
+ c0_position_i_= 10;
+ }else
+ return false;
+ *get_staff_info().c0_position_i_ = c0_position_i_;
+
+ return true;
+}
+
+void
+Clef_register::read_req(Clef_change_req*c_l)
+{
+ if (!set_type(c_l->clef_str_))
+ error("unknown clef type ", c_l->defined_ch_c_l_);
+}
+
+bool
+Clef_register::try_request(Request * r_l)
+{
+ Command_req* creq_l= r_l->command();
+ if (!creq_l || !creq_l->clefchange())
+ return false;
+
+ clef_req_l_ = creq_l->clefchange();
+
+ // do it now! Others have to read c0_pos.
+ read_req(creq_l->clefchange());
+ return true;
+}
+
+void
+Clef_register::process_requests()
+{
+ const Time_description *time_l = get_staff_info().time_c_l_;
+ if (!clef_req_l_ && (!time_l->whole_in_measure_|| !time_l->when_)) {
+ clef_p_ = new Clef_item;
+ clef_p_->change = false;
+ } else if (clef_req_l_) {
+ clef_p_ = new Clef_item;
+ clef_p_->change = true;
+ }
+ if (clef_p_) {
+ clef_p_->read(*this);
+ announce_element(Staff_elem_info(clef_p_,
+ clef_req_l_));
+ }
+}
+
+void
+Clef_register::pre_move_processing()
+{
+ if (!clef_p_)
+ return;
+ if (clef_p_->change) {
+ Clef_item* post_p = new Clef_item(*clef_p_);
+ post_p->change = false;
+ typeset_breakable_item(new Clef_item(*clef_p_),
+ clef_p_, post_p);
+ } else {
+ typeset_breakable_item(0, 0, clef_p_);
+ }
+ clef_p_ = 0;
+}
+
+void
+Clef_register::post_move_processing()
+{
+ clef_req_l_ = 0;
+ /* not in ctor, since the reg might not be linked in.*/
+ if (clef_type_str_ == "") {
+ set_type("violin");
+ }
+}
--- /dev/null
+#include "colhpos.hh"
+#include "real.hh"
+#include "debug.hh"
+#include "const.hh"
+#include "vector.hh"
+
+Col_hpositions::Col_hpositions()
+{
+ energy = INFTY;
+}
+
+void
+Col_hpositions::add( PCol*c)
+{
+ cols.push(c);
+}
+
+void
+Col_hpositions::print() const
+{
+#ifndef NPRINT
+ mtor << "energy : " << energy << '\n';
+ mtor << "line of " << config.size() << " cols\n";
+ Vector v(config);
+ mtor << v;
+#endif
+}
+
+void
+Col_hpositions::OK()const
+{
+#ifndef NDEBUG
+ assert(config.size() == cols.size());
+#endif
+}
--- /dev/null
+/*
+ commandrequest.cc -- implement Nonmusical reqs
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "commandrequest.hh"
+#include "debug.hh"
+#include "musicalrequest.hh"
+
+
+void
+Cadenza_req::do_print()const
+{
+ mtor << on_b_;
+}
+
+Cadenza_req::Cadenza_req(bool b)
+{
+ on_b_ =b;
+}
+/* *************** */
+
+
+int
+Bar_req::compare(const Bar_req &c1)const
+{
+ return type_str_ == c1.type_str_;
+}
+
+void
+Bar_req::do_print() const
+{
+ mtor << type_str_;
+}
+
+Bar_req::Bar_req(String s)
+{
+ type_str_ = s;
+}
+
+Partial_measure_req::Partial_measure_req(Moment m)
+{
+ duration_ =m;
+}
+/* *************** */
+Meter_change_req::Meter_change_req()
+{
+ beats_i_ = 0;
+ one_beat_i_ =0;
+}
+void
+Meter_change_req::set(int b,int o)
+{
+ beats_i_=b;
+ one_beat_i_=o;
+}
+
+void
+Timing_req::do_print()const{}
+
+void
+Command_req::do_print()const{}
+/* *************** */
+void
+Barcheck_req::do_print() const{}
+
+/* *************** */
+void
+Clef_change_req::do_print() const
+{
+ mtor << clef_str_ ;
+}
+
+Clef_change_req::Clef_change_req(String s)
+{
+ clef_str_ = s;
+}
+/* *************** */
+void
+Group_feature_req::do_print() const
+{
+ mtor << "stemdir " << stemdir_i_;
+}
+
+Group_feature_req::Group_feature_req()
+{
+ stemdir_i_ = 0;
+}
+
+void
+Group_change_req::do_print()const
+{
+ mtor << "id : " << newgroup_str_;
+}
+/* *************** */
+void
+Terminate_voice_req::do_print()const
+{
+}
+
+/* *************** */
+void
+Partial_measure_req::do_print() const
+{
+ mtor << duration_;
+}
+
+void
+Meter_change_req::do_print() const
+{
+ mtor << beats_i_ << "*" << one_beat_i_;
+}
+
+/* *************** */
+
+void
+Measure_grouping_req::do_print() const
+{
+ for (int i=0; i < elt_length_arr_.size(); i++) {
+ mtor << beat_i_arr_[i] <<"*" << elt_length_arr_[i]<<" ";
+ }
+}
+/* *************** */
+void
+Key_change_req::do_print() const
+{
+ for (int i=0; i < melodic_p_arr_.size(); i++) {
+ melodic_p_arr_[i]->print();
+ }
+}
+
+Key_change_req::Key_change_req()
+{
+}
+Key_change_req::Key_change_req(Key_change_req const&c)
+{
+ for (int i=0; i < c.melodic_p_arr_.size(); i++) {
+ melodic_p_arr_.push( c.melodic_p_arr_[i]->clone()->melodic() );
+ }
+}
+
+Key_change_req::~Key_change_req()
+{
+ for (int i=0; i < melodic_p_arr_.size(); i++)
+ delete melodic_p_arr_[i];
+}
--- /dev/null
+#include "complex-staff.hh"
+#include "complex-walker.hh"
+#include "score.hh"
+#include "pscore.hh"
+#include "staffsym.hh"
+#include "score-column.hh"
+
+const NO_LINES = 5;
+
+/** Aside from putting fields right, this generates the staff symbol.
+ */
+void
+Complex_staff::set_output(PScore* pscore_l )
+{
+ pstaff_l_ = new PStaff(pscore_l);
+ pscore_l_ = pscore_l;
+ pscore_l_->add(pstaff_l_);
+
+ Staff_symbol *span_p = new Staff_symbol(NO_LINES);
+
+ Score_column* col_last
+ =score_l_->find_col(score_l_->last(), false);
+ Score_column* col_first=
+ score_l_->find_col(0, false);
+
+ span_p->set_extent(col_first->pcol_l_->postbreak_p_,
+ col_last->pcol_l_->prebreak_p_);
+
+ pscore_l_->typeset_spanner(span_p, pstaff_l_);
+}
+
+
+Staff_walker *
+Complex_staff::get_walker_p()
+{
+ return new Complex_walker(this);
+}
--- /dev/null
+#include <fstream.h>
+#include <signal.h>
+#include <std/new.h>
+#include <stdlib.h>
+#include "debug.hh"
+#include "dstream.hh"
+#include "vector.hh"
+
+Dstream *monitor=0;
+ostream * nulldev =0;
+
+struct _Dinit {
+ _Dinit() {
+ nulldev = new ofstream("/dev/null");
+ monitor = new Dstream(&cout,".dstreamrc");
+ }
+ ~_Dinit() {
+ delete nulldev;
+ delete monitor;
+ }
+} dinit;
+
+
+
+/*
+ want to do a stacktrace .
+ */
+void
+mynewhandler()
+{
+ assert(false);
+}
+
+void
+float_handler(int)
+{
+ cerr << "Floating point exception .. \n"<< flush;
+ assert(false);
+}
+
+void
+debug_init()
+{
+#ifndef NDEBUG
+ set_new_handler(&mynewhandler);
+#endif
+ set_matrix_debug(*monitor);
+ signal(SIGFPE, float_handler);
+}
+
+bool check_debug=false;
+
+void
+set_debug(bool b)
+{
+ check_debug =b;
+}
+
+
--- /dev/null
+#include <ctype.h>
+#include "dimen.hh"
+#include "debug.hh"
+#include "string.hh"
+
+Real
+parse_dimen(String dim)
+{
+ int i=dim.length_i()-1;
+ const char *s = dim;
+ while (i > 0 && (isspace(s[i]) || isalpha(s[i])) ){
+ i--;
+ }
+ String unit(s + i+1);
+ return convert_dimen(dim.value_f(), unit);
+}
+
+
+Real
+convert_dimen(Real quant, String unit)
+{
+ if (unit == "cm")
+ return quant * CM_TO_PT;
+ if (unit == "pt")
+ return quant;
+ if (unit == "mm")
+ return quant*CM_TO_PT/10;
+ if (unit == "in")
+ return quant * INCH_TO_PT;
+ error ("unknown length unit: `" + unit+"'");
+}
+
+String
+print_dimen(Real r)
+{
+ String s(r);
+ s += "pt ";
+ return s;
+}
--- /dev/null
+#include "directional-spanner.hh"
+
+Directional_spanner::Directional_spanner()
+{
+ dir_i_ = 0;
+}
--- /dev/null
+/*
+ grouping.cc -- implement Rhythmic_grouping
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "debug.hh"
+#include "grouping.hh"
+#include "interval.hh"
+
+void
+Rhythmic_grouping::init()
+{
+ interval_ = 0;
+ children.set_size(0);
+}
+
+void
+Rhythmic_grouping::OK()const
+{
+#ifndef NDEBUG
+ assert(bool(children.size()) != bool(interval_));
+
+ for (int i= 0; i < children.size(); i++) {
+ children[i]->OK();
+ if (i>0)
+ assert(children[i-1]->interval().right ==
+ children[i]->interval().left);
+ }
+#endif
+}
+
+Moment
+Rhythmic_grouping::length() const
+{
+ return interval().length();
+}
+
+MInterval
+Rhythmic_grouping::interval()const
+{
+ if (interval_)
+ return *interval_;
+ else
+ return
+ MInterval(children[0]->interval().left,
+ children.top()->interval().right);
+}
+
+void
+Rhythmic_grouping::split(Rhythmic_grouping r)
+{
+ if (interval_)
+ return ;
+
+ r.intersect(interval());
+ split(r.intervals());
+
+ for (int i= 0; i < children.size(); i++) {
+ if (!children[i]->interval_) {
+ Rhythmic_grouping here(r);
+ children[i]->split(here);
+ }
+ }
+}
+
+
+Array<MInterval>
+Rhythmic_grouping::intervals()
+{
+ Array<MInterval> r;
+ if (interval_ || children.size() == 1) {
+ MInterval i(interval());
+ MInterval r1(i), r2(i);
+ r1.right = r2.left = i.center();
+ r.push(r1); r.push(r2);
+ } else {
+ for (int i=0; i < children.size(); i++)
+ r.push(children[i]->interval());
+ }
+ return r;
+}
+
+void
+Rhythmic_grouping::intersect(MInterval t)
+{
+ if (interval_) {
+ interval_->intersect(t);
+ return;
+ }
+
+ for (int i=0; i < children.size(); i++) {
+ MInterval inter = intersection(t, children[i]->interval());
+ if (inter.empty() || inter.length() <= Rational( 0 )) {
+ delete children[i];
+ children[i] =0;
+ } else {
+ children[i]->intersect(t);
+ }
+ }
+ for (int i=0; i < children.size(); ) {
+ if (!children[i])
+ children.del(i);
+ else
+ i++;
+ }
+
+}
+
+/**
+ Put our children in branches of #this#.
+ The min and max time intervals coincide with elements of #splitpoints#
+
+ I really should be documenting what is happening here, but I find
+ that difficult, since I don't really understand what's going on here.
+
+ */
+void
+Rhythmic_grouping::split(Array<MInterval> splitpoints)
+{
+ //check on splitpoints..
+ int j = 0, i = 0, starti = 0, startj = 0;
+
+ Array<Rhythmic_grouping*> ch;
+ while (1) {
+ if ( i >= children.size() || j >= splitpoints.size())
+ break;
+
+ assert(
+ children[starti]->interval().left== splitpoints[startj].left);
+ if (children[i]->interval().right < splitpoints[j].right) {
+ i ++;
+ } else if (children[i]->interval().right > splitpoints[j].right ) {
+ j ++;
+ } else {
+
+ if (i == starti) {
+ ch.push(children[i]);
+ } else {
+ Rhythmic_grouping *newchild=new Rhythmic_grouping(
+ children.subvec(starti, i+1));
+
+ ch.push(newchild);
+ }
+ i ++;
+ j++;
+ starti = i;
+ startj = j;
+
+
+ }
+ }
+ if (ch.size() != 1)
+ children = ch;
+ }
+
+
+Rhythmic_grouping::Rhythmic_grouping(MInterval t, int n)
+{
+ init();
+ if (n == 1 || !n) {
+ interval_ = new MInterval(t);
+ return;
+ }
+ Moment dt = t.length()/Rational(n);
+ MInterval basic = MInterval(t.left, t.left+dt);
+ for (int i= 0; i < n; i++)
+ children.push(new Rhythmic_grouping( dt*Rational(i) + basic ));
+}
+
+
+Rhythmic_grouping::Rhythmic_grouping(Array<Rhythmic_grouping*> r)
+ :children(r)
+{
+ interval_ =0;
+}
+
+Rhythmic_grouping::~Rhythmic_grouping()
+{
+ junk();
+}
+
+void
+Rhythmic_grouping::copy(Rhythmic_grouping const&s)
+{
+ interval_ = (s.interval_)? new MInterval(*s.interval_) : 0;
+ for (int i=0; i < s.children.size(); i++)
+ children.push(new Rhythmic_grouping(*s.children[i]));
+}
+
+void
+Rhythmic_grouping::operator=(Rhythmic_grouping const &s)
+{
+ junk();
+ copy(s);
+}
+
+Rhythmic_grouping::Rhythmic_grouping(Rhythmic_grouping const&s)
+{
+ init();
+ copy(s);
+}
+
+void
+Rhythmic_grouping::junk()
+{
+ delete interval_;
+ for (int i=0; i < children.size(); i++)
+ delete children[i];
+ init();
+}
+
+void
+Rhythmic_grouping::print()const
+{
+#ifndef NPRINT
+ mtor << "{ \n";
+ if (interval_)
+ mtor<<" Interval "<< interval_->str();
+ for (int i=0; i < children.size(); i++) {
+ children[i]->print();
+ }
+ mtor << "}\n";
+#endif
+}
+
+bool
+Rhythmic_grouping::child_fit_query(Moment start)
+{
+ if (children.size())
+ return ( children.top()->interval().right== start);
+
+ return true;
+}
+
+void
+Rhythmic_grouping::add_child(Moment start, Moment len)
+{
+ Moment stop = start+len;
+
+ assert(child_fit_query(start));
+ children.push(new Rhythmic_grouping(MInterval(start, stop)));
+}
+
+Rhythmic_grouping::Rhythmic_grouping()
+{
+ interval_ =0;
+}
+
+int
+min_elt(Array<int> v)
+{
+ int i = 1000; // ugh
+ for (int j = 0 ; j < v.size(); j++)
+ i = i <? v[j];
+ return i;
+}
+
+Array<int>
+Rhythmic_grouping::generate_beams(Array<int> flags, int &flagidx)
+{
+ assert (!interval_) ;
+
+ Array< Array<int> > children_beams;
+ for (int i=0; i < children.size(); i++) {
+ Array<int> child_beams;
+ if (children[i]->interval_) {
+ int f = flags[flagidx++];
+ child_beams.push(f);
+ } else {
+ child_beams = children[i]->
+ generate_beams(flags, flagidx);
+ }
+ children_beams.push(child_beams);
+ }
+ Array<int> beams;
+ int lastm, m, nextm;
+ for (int i=0; i < children_beams.size(); i++) {
+ bool add_left = (i >0);
+ bool add_right = (i < children_beams.size() -1);
+
+ if (!i)
+ m = min_elt(children_beams[i]);
+ if (add_right)
+ nextm = min_elt(children_beams[i+1]);
+
+ if (children_beams[i].size() == 1) {
+ if (add_right)
+ beams.push(m);
+ if (add_left)
+ beams.push(m);
+ } else {
+ if (add_left)
+ beams.push(lastm <? m);
+ beams.concat(children_beams[i]);
+ if (add_right)
+ beams.push(m <? nextm);
+ }
+ lastm = m;
+ m = nextm;
+ }
+ assert(!(beams.size()%2));
+ return beams;
+}
+
+void
+Rhythmic_grouping::translate(Moment m)
+{
+ if (interval_)
+ *interval_ += m;
+ else
+ for (int i=0; i < children.size(); i++)
+ children[i]->translate(m);
+}
+
+void
+Rhythmic_grouping::extend(MInterval m)const
+{
+ assert(m.left >= interval().left);
+ while (m.right >interval().right ) {
+ Array<Rhythmic_grouping*> a(children);
+ for (int i=0; i < a.size(); i++) {
+ a[i] =new Rhythmic_grouping(*children[i]);
+ a[i]->translate(children.top()->interval().right);
+ }
+ ((Rhythmic_grouping*)this)->children.concat(a);
+ }
+ assert(m.right <= interval().right);
+ OK();
+}
+
+Rhythmic_grouping
+parse_grouping(Array<int> beat_i_arr, Array<Moment> elt_length_arr)
+{
+ Moment here =0;
+ assert(beat_i_arr.size() == elt_length_arr.size());
+
+ Array<Rhythmic_grouping*> children;
+ for (int i=0; i < beat_i_arr.size(); i++) {
+ Moment last = here;
+ here += elt_length_arr[i] * Moment(beat_i_arr[i]);
+ children.push(
+ new Rhythmic_grouping(MInterval(last, here),
+ beat_i_arr[i] ));
+ }
+ return Rhythmic_grouping(children);
+}
+
--- /dev/null
+/*
+ headreg.cc -- part of LilyPond
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include "rest.hh"
+#include "notehead.hh"
+#include "headreg.hh"
+#include "paper-def.hh"
+#include "complex-walker.hh"
+#include "musicalrequest.hh"
+
+Notehead_register::Notehead_register()
+{
+ note_p_ = 0;
+ set_feature(Features::dir(0));
+ post_move_processing();
+}
+
+bool
+Notehead_register::try_request(Request *req_l)
+{
+ if (req_l->note() || req_l->rest())
+ note_req_l_=req_l->rhythmic();
+ else
+ return false;
+
+ return true;
+}
+void
+Notehead_register::set_feature(Features d)
+{
+ if(d.direction_i_ || d.initialiser_b_)
+ dir_i_ = d.direction_i_;
+}
+
+void
+Notehead_register::process_requests()
+{
+ if (!note_req_l_)
+ return;
+
+
+ if (note_req_l_->note()) {
+ Notehead*n_p = new Notehead(8); // ugh
+ note_p_ = n_p;
+ n_p->set_rhythmic(note_req_l_->rhythmic());
+ n_p->position = note_req_l_->note()->height() +
+ *get_staff_info().c0_position_i_;
+ } else {
+ note_p_ = new Rest ( note_req_l_->rhythmic()->balltype,
+ note_req_l_->rhythmic()->dots);
+ if (note_req_l_->rhythmic()->balltype <= 2)
+ note_p_->translate(
+ Offset(0,
+ 6 * paper()->internote()));
+ }
+ Staff_elem_info itinf(note_p_,note_req_l_);
+ announce_element(itinf);
+}
+
+void
+Notehead_register::pre_move_processing()
+{
+ if (note_p_) {
+ if (dir_i_ && note_p_->name() == Rest::static_name())
+ note_p_->translate(Offset(0, 4*dir_i_ * paper()->internote()));
+ typeset_element(note_p_);
+ note_p_ = 0;
+ }
+}
+void
+Notehead_register::post_move_processing()
+{
+ note_req_l_ = 0;
+}
--- /dev/null
+#include "idealspacing.hh"
+#include "pcol.hh"
+#include "pscore.hh"
+#include "pstaff.hh"
+#include "debug.hh"
+
+void
+Idealspacing::print() const
+{
+#ifndef NPRINT
+ mtor << "idealspacing {" ;
+ mtor << "distance "<<space<< " strength " << hooke ;
+ mtor << "left " << left->rank() << " right " << right->rank() << "}\n";
+#endif
+}
+
+Idealspacing::Idealspacing(const PCol * l,const PCol * r)
+{
+ space = 0.0;
+ hooke = 0.0;
+ left = l;
+ right = r;
+}
+
+void
+Idealspacing::OK() const
+{
+#ifndef NDEBUG
+ assert(hooke >= 0 && left && right);
+#endif
+}
--- /dev/null
+/*
+ identifier.cc -- implement identifier and derived classes
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include <assert.h>
+
+#include "identifier.hh"
+#include "lexer.hh"
+#include "debug.hh"
+
+void
+Identifier::error(String expect)
+{
+ String e("Wrong identifier type: ");
+ e += String(classname()) + "(expected " + expect + ")";
+ ::error(e);
+}
+
+void
+Identifier::print()const
+{
+ mtor << "identifier \'" << name << "\'=";
+ do_print();
+}
+
+/* ugh. */
+#define DEFAULT_PRINT(Class, Content_type, accessor) \
+void \
+Class::do_print() const { \
+ ((Class*)this)->accessor(false)->print(); \
+} \
+class Class
+
+DEFAULT_PRINT(Script_id, Script_def, script);
+DEFAULT_PRINT(Lookup_id, Lookup, lookup);
+DEFAULT_PRINT(Symtables_id, Symtables, symtables);
+DEFAULT_PRINT(Staff_id, Input_staff, staff);
+DEFAULT_PRINT(M_chord_id, Music_general_chord, mchord);
+DEFAULT_PRINT(M_voice_id, Music_voice, mvoice);
+
+void
+Real_id::do_print() const
+{
+ Identifier::print();
+ mtor << *((Real_id*)this)->real(false)<< "\n";
+}
+
+void
+Notetab_id::do_print() const
+{
+ mtor << "unknown" << "\n";
+}
--- /dev/null
+/*
+ bar-reg.hh -- declare Bar_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef BARREG_HH
+#define BARREG_HH
+#include "register.hh"
+
+/**
+ generate bars. Either user ("|:"), or default (new measure)
+ */
+class Bar_register : public Request_register {
+ void split_bar(Bar *& pre, Bar * no, Bar * &post);
+public:
+ Bar_req * bar_req_l_;
+ Bar * bar_p_;
+
+ virtual bool try_request(Request *req_l);
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ Bar_register();
+ NAME_MEMBERS(Bar_register);
+};
+
+#endif // BARREG_HH
--- /dev/null
+/*
+ bar.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef BAR_HH
+#define BAR_HH
+#include "item.hh"
+
+struct Bar: Item {
+ String type;
+
+ Bar(String type);
+NAME_MEMBERS(Bar);
+ void do_print() const;
+ Molecule*brew_molecule_p()const;
+};
+#endif // BAR_HH
+
--- /dev/null
+/*
+ beam.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef BEAM_HH
+#define BEAM_HH
+#include "proto.hh"
+#include "directional-spanner.hh"
+#include "plist.hh"
+
+/** a beam connects multiple stems Beam adjusts the stems its owns to
+ make sure that they reach the beam and that point in the correct
+ direction */
+struct Beam: public Directional_spanner {
+ PointerList<Stem*> stems;
+ /// the slope of the beam in posns / point (dimension)
+ Real slope;
+
+ /// position of leftmost end of beam
+ Real left_pos;
+
+
+ /* *************** */
+NAME_MEMBERS(Beam);
+
+ virtual Interval width()const;
+ Offset center() const;
+ Spanner *do_break_at(PCol *, PCol *) const;
+ Beam();
+ void add(Stem*);
+
+
+ void set_default_dir();
+ void do_pre_processing();
+ void do_post_processing();
+
+ void do_print() const;
+ void set_grouping(Rhythmic_grouping def, Rhythmic_grouping current);
+ void set_stemlens();
+ ~Beam();
+
+private:
+ Molecule stem_beams(Stem *here, Stem *next, Stem *prev)const;
+ void solve_slope();
+ Molecule*brew_molecule_p()const;
+};
+
+#endif // BEAM_HH
+
--- /dev/null
+/*
+ class-name.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef CLASS_NAME_HH
+#define CLASS_NAME_HH
+
+/// a macro to declare the classes name as a static and virtual function.
+#define NAME_MEMBERS(c) \
+static const char *static_name(){ return #c; }\
+virtual const char *name() const{ return c::static_name(); } \
+int a_stupid_nonexistent_function_to_allow_the_semicolon_come_out()
+
+#endif // CLASS-NAME_HH
--- /dev/null
+
+/*
+ clef-item.hh -- declare Clef_item
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef CLEFITEM_HH
+#define CLEFITEM_HH
+#include "item.hh"
+
+
+struct Clef_item : Item {
+ String type;
+ int y_off;
+
+ /// is this a change clef (smaller size)?
+ bool change;
+
+
+ /* *************** */
+NAME_MEMBERS(Clef_item);
+ Clef_item();
+ void read(Clef_register const&);
+ void read(String);
+ Molecule* brew_molecule_p()const;
+};
+
+#endif // CLEFITEM_HH
+
+
--- /dev/null
+/*
+ clef.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef CLEF_HH
+#define CLEF_HH
+
+#include "scalar.hh"
+#include "varray.hh"
+#include "register.hh"
+
+/// where is c-0 in the staff?
+class Clef_register : public Request_register {
+ Clef_item *clef_p_;
+ Clef_change_req * clef_req_l_;
+
+public:
+ int c0_position_i_;
+ String clef_type_str_;
+
+ /* ************** */
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ virtual bool try_request(Request*);
+ Clef_register();
+ NAME_MEMBERS(Clef_register);
+ void read_req(Clef_change_req*);
+ bool set_type(String);
+};
+#endif // CLEF_HH
+
--- /dev/null
+/*
+ complex-staff.hh -- declare Complex_staff
+
+ (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef COMPLEXSTAF_HH
+#define COMPLEXSTAF_HH
+
+
+#include "key.hh"
+#include "staff.hh"
+#include "staff-walker.hh"
+
+///
+struct Complex_staff : Staff {
+
+ /* *************** */
+
+ virtual void set_output(PScore *);
+ virtual Staff_walker *get_walker_p();
+};
+
+#endif // COMPLEXSTAF_HH
+
--- /dev/null
+/*
+ complex-walker.hh -- declare Complex_walker
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef COMPLEXWALKER_HH
+#define COMPLEXWALKER_HH
+
+#include "proto.hh"
+#include "staff-walker.hh"
+#include "staff-elem-info.hh"
+
+/**
+ A staff walker which uses registers to decide what to print
+ */
+class Complex_walker: public Staff_walker {
+ bool try_command_request(Command_req *req_l);
+ void do_announces();
+ void try_request(Request*req);
+
+
+
+public:
+ int c0_position_i_;
+ Walker_registers *walk_regs_p_;
+
+ /* *************** */
+
+ void regs_process_requests();
+ void typeset_element(Staff_elem *elem_p);
+ void announce_element(Staff_elem_info);
+ virtual void process_requests();
+ virtual void do_post_move();
+ virtual void do_pre_move();
+
+ Complex_walker(Complex_staff*);
+ ~Complex_walker();
+
+ Complex_staff *staff();
+private:
+};
+
+
+#endif // COMPLEXWALKER_HH
+
+
--- /dev/null
+/*
+ directional-spanner.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef DIRECTIONALSPANNER_HH
+#define DIRECTIONALSPANNER_HH
+
+#include "spanner.hh"
+
+/// a spanner which can be pointing "up" or "down"
+struct Directional_spanner : Spanner{
+
+ /// -1 below heads, +1 above heads.
+ int dir_i_;
+
+ /// offset of "center" relative to left-column/0-pos of staff
+ virtual Offset center() const=0;
+ virtual void set_default_dir()=0;
+ Directional_spanner();
+
+};
+
+#endif // DIRECTIONALSPANNER_HH
+
--- /dev/null
+/*
+ grouping.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef GROUPING_HH
+#define GROUPING_HH
+
+#include "moment.hh"
+#include "interval.hh"
+#include "varray.hh"
+
+typedef Interval_t<Moment> MInterval;
+
+/** data structure which represents rhythmic units this is a tree. It groupes notes according to rules
+ */
+struct Rhythmic_grouping {
+ Array<Rhythmic_grouping*> children;
+ MInterval *interval_;
+
+ /* *************** */
+
+ Array<MInterval> intervals();
+ MInterval interval()const;
+ Moment length() const;
+ void intersect(MInterval);
+
+ void operator=(Rhythmic_grouping const&);
+ Rhythmic_grouping(Rhythmic_grouping const&);
+ Rhythmic_grouping(MInterval, int n=1);
+ Rhythmic_grouping();
+ Rhythmic_grouping(Array<Rhythmic_grouping*>);
+ ~Rhythmic_grouping();
+
+ void add_child(Moment start, Moment len);
+ bool child_fit_query(Moment start);
+ void split(Rhythmic_grouping r);
+ void split(Array<MInterval>);
+ void split(int n);
+
+ void print() const;
+ void OK() const;
+
+ Array<int> generate_beams(Array<int>, int&);
+
+ /** multiply self to span #i#.
+ In implementation, this isn't really const, but conceptually it is.
+ */
+ void extend(MInterval i) const;
+ void translate(Moment);
+private:
+ void init();
+ void junk();
+ void copy(Rhythmic_grouping const&);
+};
+
+
+Rhythmic_grouping parse_grouping(Array<int> beat_i_arr, Array<Moment> elt_length_arr);
+
+
+#endif
--- /dev/null
+/*
+ headreg.hh -- part of LilyPond
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef HEADREG_HH
+#define HEADREG_HH
+#include "register.hh"
+
+struct Notehead_register : Request_register {
+ Item* note_p_;
+ Rhythmic_req * note_req_l_;
+ int dir_i_;
+
+ /* *************** */
+ Notehead_register();
+ virtual bool try_request(Request *req_l) ;
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ void set_feature(Features);
+ NAME_MEMBERS(Notehead_register);
+};
+
+
+#endif // HEADREG_HH
--- /dev/null
+
+/*
+ identifier.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef IDENTIFIER_HH
+#define IDENTIFIER_HH
+#include "identparent.hh"
+#include "symtable.hh"
+#include "input-staff.hh"
+#include "input-music.hh"
+#include "notename.hh"
+#include "lookup.hh"
+#include "script-def.hh"
+
+#define make_id_class(Idclass, Class, accessor) \
+struct Idclass : Identifier {\
+ virtual const char *classname() { return #Class; }\
+ Idclass(String s, Class*st):Identifier(s) { data = st; }\
+ virtual Class* accessor(bool copy) {\
+ if (copy)\
+ return new Class(* (Class*) data);\
+ else\
+ return (Class*) data;\
+ }\
+ ~Idclass() { delete accessor(false); }\
+ virtual void do_print()const; \
+}\
+
+make_id_class(Real_id, Real, real);
+make_id_class(Script_id, Script_def, script);
+make_id_class(Lookup_id, Lookup, lookup);
+make_id_class(Symtables_id, Symtables, symtables);
+make_id_class(Staff_id, Input_staff, staff);
+make_id_class(M_chord_id, Music_general_chord, mchord);
+make_id_class(M_voice_id, Music_voice, mvoice);
+make_id_class(Notetab_id, Notename_tab, notename_tab);
+
+#endif // IDENTIFIER_HH
+
--- /dev/null
+/*
+ identparent.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef IDENTPARENT_HH
+#define IDENTPARENT_HH
+
+#include "proto.hh"
+#include "string.hh"
+
+/* boolean argument to accesor is copy_b..*/
+#define IDACCESSOR( Input_staff, staff)\
+ virtual Input_staff * staff(bool) { error(#Input_staff); return 0; }
+
+struct Identifier {
+ void *data;
+ String name;
+
+ Identifier(String n) : name(n) { }
+ virtual ~Identifier() {}
+
+ void print()const;
+ virtual const char*classname() { return "new Identifier"; }
+ void error(String);
+ IDACCESSOR(Input_staff, staff)
+ IDACCESSOR(Input_music, music)
+ IDACCESSOR(Music_voice, mvoice)
+ IDACCESSOR(Script_def, script)
+ IDACCESSOR(Symtables, symtables)
+ IDACCESSOR(Music_general_chord, mchord)
+ IDACCESSOR(Lookup,lookup)
+ IDACCESSOR(Real,real)
+ IDACCESSOR(Notename_tab, notename_tab)
+protected:
+ virtual void do_print()const=0;
+private:
+ Identifier(Identifier const&){}
+
+};
+#endif // IDENTPARENT_HH
+
+
+
--- /dev/null
+/*
+ input-music.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef INPUTMUSIC_HH
+#define INPUTMUSIC_HH
+
+#include "plist.hh"
+#include "proto.hh"
+#include "voice.hh"
+#include "moment.hh"
+
+struct Voice_list : public PointerList<Voice*> {
+ void translate_time(Moment dt);
+};
+
+/**
+
+ A set voices.
+ Input_music is anything that can simply be regarded as/converted to
+ a set of voices "cooperating" or independant. It has some basic
+ characteristics that real music has too:
+
+ - it is rhythmic (it has a length, and can be translated horizontally)
+ - a pitch (it can be transposed)
+
+ */
+struct Input_music {
+ virtual Voice_list convert()const=0;
+ void check_plet(Voice_element* velt_l);
+ virtual Moment length()const=0;
+ virtual void translate_time(Moment dt)=0;
+ virtual ~Input_music(){}
+ virtual void print() const =0;
+ virtual void set_default_group(String)=0;
+ virtual bool find_plet_start_bo(char c, Moment& moment_r) = 0;
+ virtual void set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i) = 0;
+ // virtual void transpose(...) const =0;
+
+
+ virtual Input_music *clone() const = 0;
+ virtual Simple_music *simple() { return 0; }
+};
+
+/// Simple music consists of one voice
+struct Simple_music : Input_music {
+ Voice voice_;
+
+ /* *** */
+ virtual Simple_music*simple() { return this; }
+ void add(Voice_element*);
+ virtual void set_default_group(String g) { voice_.set_default_group(g); }
+ virtual Moment length()const;
+ virtual Voice_list convert()const;
+ virtual void translate_time(Moment dt);
+ virtual void print() const;
+ virtual bool find_plet_start_bo(char c, Moment& moment_r);
+ virtual void set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i);
+ virtual Input_music *clone() const {
+ return new Simple_music(*this);
+ }
+
+};
+
+/// Complex_music consists of multiple voices
+struct Complex_music : Input_music {
+ IPointerList<Input_music*> elts;
+ /* *************** */
+ virtual void set_default_group(String g);
+ void add(Input_music*);
+ Complex_music();
+ Complex_music(Complex_music const &);
+ virtual void print() const ;
+ void concatenate(Complex_music*);
+ virtual bool find_plet_start_bo(char c, Moment& moment_r);
+ virtual void set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i);
+
+};
+
+
+/**
+ A voice like list of music.
+
+ different music forms which start after each other ( concatenated,
+ stacked "horizontally )
+
+ */
+
+struct Music_voice : Complex_music {
+
+
+ /* *************** */
+ Moment length()const;
+ virtual void translate_time(Moment dt);
+ virtual Voice_list convert()const;
+ void add_elt(Voice_element*);
+ virtual Input_music *clone() const {
+ return new Music_voice(*this);
+ }
+ virtual void print() const ;
+};
+
+/**
+ Multiple musicstuff stacked on top of each other
+ chord like :
+
+ - different music forms which start at the same time ( stacked "vertically" )
+
+ */
+struct Music_general_chord : Complex_music {
+
+
+ /* *************** */
+
+ virtual Moment length()const;
+ virtual Voice_list convert()const;
+ virtual void translate_time(Moment dt);
+ void add_elt(Voice_element*);
+ virtual Input_music *clone() const {
+ return new Music_general_chord(*this);
+ }
+
+ virtual void print() const ;
+};
+
+struct Multi_voice_chord : Music_general_chord {
+ void set_default_group(String);
+ virtual Input_music *clone() const {
+ return new Multi_voice_chord(*this);
+ }
+};
+struct Voice_group_chord : Music_general_chord {
+
+ virtual Input_music *clone() const {
+ return new Voice_group_chord(*this);
+ }
+};
+#endif // INPUTMUSIC_HH
--- /dev/null
+/*
+ input-score.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef INPUTSCORE_HH
+#define INPUTSCORE_HH
+
+#include "varray.hh"
+#include "proto.hh"
+#include "plist.hh"
+#include "string.hh"
+
+
+/// the total music def of one movement
+struct Input_score {
+ /// defined where?
+ const char* defined_ch_c_l_;
+ int errorlevel_i_;
+
+ /// paper_, staffs_ and commands_ form the problem definition.
+ Paper_def *paper_p_;
+ Midi_def* midi_p_;
+ IPointerList<Input_staff*> staffs_;
+
+ Input_music * score_wide_music_p_;
+
+ /* *************************************************************** */
+ Input_score();
+ Input_score(Input_score const&);
+
+ void add(Input_staff*);
+ ~Input_score();
+ /// construction
+ void set(Paper_def*);
+ void set(Midi_def* midi_p);
+ void print() const;
+ Score*parse();
+ void set(Input_music*);
+};
+
+#endif
--- /dev/null
+/*
+ input-staff.hh -- declare Input_staff
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef INPUTSTAFF_HH
+#define INPUTSTAFF_HH
+
+#include "string.hh"
+#include "plist.hh"
+#include "varray.hh"
+#include "proto.hh"
+
+struct Input_staff {
+
+ const char * defined_ch_c_l_;
+ String type;
+
+ IPointerList<Input_music*> music_;
+ Input_music * score_wide_music_p_;
+
+ /* *************** */
+ ~Input_staff();
+ void add(Input_music*m);
+ Input_staff(Input_staff const&);
+ Input_staff(String);
+ void set_score_wide(Input_music*m);
+ Staff* parse(Score*, Input_music *score_wide);
+ void print() const;
+};
+
+
+#endif // INPUTSTAFF_HH
+
--- /dev/null
+#ifndef ITEM_HH
+#define ITEM_HH
+
+#include "glob.hh"
+#include "boxes.hh"
+#include "string.hh"
+#include "staff-elem.hh"
+
+/**
+ a horizontally fixed size element of the score
+
+ Item is the datastructure for printables whose width is known
+ before the spacing is calculated
+
+ NB. This doesn't mean an Item has to initialize the output field before
+ spacing calculation.
+
+*/
+struct Item : Staff_elem {
+ /// indirection to the column it is in
+ PCol * pcol_l_;
+
+ /* *************** */
+ virtual Item *item() { return this; }
+ Item();
+ void do_print()const;
+
+ NAME_MEMBERS(Item);
+};
+
+
+#endif
--- /dev/null
+/*
+ key-item.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef KEYITEM_HH
+#define KEYITEM_HH
+
+#include "item.hh"
+#include "varray.hh"
+
+
+/// An item which places accidentals at the start of the line
+struct Key_item : Item {
+ Array<int> pitch;
+ Array<int> acc;
+ int c_position;
+
+
+ /* *************** */
+NAME_MEMBERS(Key_item);
+ Key_item(int cposition);
+ void add(int pitch, int acc);
+ void read(const Key_register&);
+ void set_c_position(int);
+ void preprocess();
+ Molecule* brew_molecule_p()const;
+};
+
+#endif // KEYITEM_HH
--- /dev/null
+/*
+ key-reg.hh -- declare Key_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef KEYREG_HH
+#define KEYREG_HH
+
+#include "register.hh"
+#include "key.hh"
+
+struct Key_register : Request_register {
+ Key key_;
+ Key_change_req * keyreq_l_;
+ Key_item * kit_p_;
+ Array<int> accidental_idx_arr_;
+ bool default_key_b_;
+
+ virtual bool try_request(Request *req_l);
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ virtual void acknowledge_element(Staff_elem_info);
+ Key_register();
+ NAME_MEMBERS(Key_register);
+private:
+
+ void read_req(Key_change_req * r);
+};
+
+#endif // KEYREG_HH
--- /dev/null
+/*
+ lexer.hh -- declare My_flex_lexer
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef LEXER_HH
+#define LEXER_HH
+#include <FlexLexer.h>
+#include "proto.hh"
+#include "fproto.hh"
+#include "varray.hh"
+#include "string.hh"
+
+int yylex();
+void yyerror(const char *s);
+bool busy_parsing();
+void kill_lexer();
+void set_lexer();
+
+/// lexer with provisions for include files.
+struct My_flex_lexer : yyFlexLexer {
+
+ Array<Input_file*> include_stack;
+ Assoc<String, Identifier*> *the_id_tab;
+ Keyword_table * keytable;
+ Notename_tab * defaulttab;
+ int errorlevel_i_;
+ /* *************** */
+ int ret_notename(int *p, String text, int octave_mod);
+ char const* here_ch_c_l();
+ void set(Notename_tab *n);
+ int lookup_keyword(String);
+ void lookup_notename(int &large, int &small, String s);
+ void LexerError(const char *);
+ String spot() const;
+ Identifier*lookup_identifier(String s);
+ My_flex_lexer();
+ void add_identifier(Identifier*i);
+ ~My_flex_lexer();
+ void new_input(String s);
+ bool close_input();
+ int yylex();
+ void print_declarations() const;
+};
+
+extern My_flex_lexer *lexer;
+
+#endif
--- /dev/null
+/*
+ local-key-item.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef LOCALKEYITEM_HH
+#define LOCALKEYITEM_HH
+#include "item.hh"
+#include "varray.hh"
+
+struct Local_acc {
+ int name , acc, octave;
+ static int compare(Local_acc&, Local_acc&);
+};
+
+struct Local_key_item : Item {
+NAME_MEMBERS(Local_key_item);
+ Array<Local_acc> accs;
+ Array<Item*> support_items_;
+ int c0_position;
+
+ /* *************** */
+
+ Local_key_item(int c0position);
+ void add(Item*);
+ void add(int oct, int pitch, int acc);
+ void add(Melodic_req*);
+ void do_pre_processing();
+ Molecule* brew_molecule_p()const;
+};
+#endif // LOCALKEYITEM_HH
+
--- /dev/null
+/*
+ local-key-reg.hh -- declare Local_key_register
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef LOCALKEYREG_HH
+#define LOCALKEYREG_HH
+#include "register.hh"
+#include "key.hh"
+
+struct Local_key_register : Request_register {
+ Local_key local_key_;
+ Local_key_item* key_item_p_;
+ const Key *key_c_l_;
+ /* *************** */
+ virtual void process_requests();
+ virtual void acknowledge_element(Staff_elem_info);
+ virtual void pre_move_processing();
+ Local_key_register();
+ NAME_MEMBERS(Local_key_register);
+};
+
+#endif // LOCALKEYREG_HH
--- /dev/null
+/*
+ lilypond, (c) 1996,97 Han-Wen Nienhuys
+*/
+#ifndef LOOKUPSYMS_HH
+#define LOOKUPSYMS_HH
+
+#include "symbol.hh"
+#include "fproto.hh"
+#include "scalar.hh"
+
+/// intuitive interface to symbol table
+struct Lookup {
+ Symtables *symtables_;
+ String texsetting;
+ /* *************** */
+ void add(String, Symtable*);
+ void print()const;
+ Real internote();
+
+ Symbol linestaff(int n, Real w);
+ Symbol fill(Box b);
+ Symbol beam_element(int,int,Real=0);
+
+ /// round slope to closest TeXslope
+ Symbol beam(Real&,Real);
+
+ /**
+ pos == 3 : 3 lines above staff (extending below note)
+
+ pos == -3: below staff
+ */
+ Symbol streepjes(int pos);
+
+ Symbol meter(Array<Scalar>);
+ Symbol stem(Real y1_pos, Real y2_pos);
+ Symbol rule_symbol(Real height, Real width);
+ Symbol accidental(int);
+ Symbol ball(int);
+ Symbol flag(int);
+ Symbol rest(int);
+ Symbol clef(String);
+ Symbol bar(String);
+ Symbol dots(int);
+ Symbol slur(int dy, Real &dx, int dir);
+ Symbol half_slur(int dy, Real &dx, int dir, int xpart);
+ Symbol half_slur_middlepart(Real &dx, int dir);
+ Symbol big_slur(int dy, Real &dx, int dir);
+ Symbol text(String style, String text, int align = 1);
+ Symbol script(String idx);
+ Symbol hairpin(Real & width, bool decresc);
+
+ Lookup();
+ Lookup(Lookup const &);
+ ~Lookup();
+};
+
+#endif
--- /dev/null
+//
+// lyricwalker.hh -- declare Lyric_walker
+//
+// (c) 1996,97 Han-Wen Nienhuys, Jan Nieuwenhuizen <jan@digicash.com>
+//
+
+#ifndef LYRICWALKER_HH
+#define LYRICWALKER_HH
+
+#include "proto.hh"
+#include "grouping.hh"
+#include "staff-walker.hh"
+
+/// a simple walker which collects words, and then print them, first on top
+struct Lyric_walker: Staff_walker {
+ Array<Lyric_item*> litem_l_array_;
+
+ /* *************** */
+ virtual void process_requests();
+
+ Lyric_walker(Lyric_staff* lstaff_l);
+ Lyric_staff* lstaff_l();
+};
+
+
+#endif // LYRICWALKER_HH
+
+
--- /dev/null
+/*
+ meter-reg.hh -- declare Meter_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef METERREG_HH
+#define METERREG_HH
+#include "register.hh"
+
+/**
+ generate meters.
+ */
+class Meter_register : public Request_register {
+public:
+ Meter_change_req * meter_req_l_;
+ Meter * meter_p_;
+
+ virtual bool try_request(Request *req_l);
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ Meter_register();
+ NAME_MEMBERS(Meter_register);
+};
+#endif // METERREG_HH
--- /dev/null
+/*
+ meter.hh -- declare Meter
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef METER_HH
+#define METER_HH
+#include "item.hh"
+#include "varray.hh"
+#include "scalar.hh"
+
+struct Meter: Item {
+ Array<Scalar> args;
+ /* *************** */
+NAME_MEMBERS(Meter);
+
+ Meter(Array<Scalar> args) ;
+ Molecule*brew_molecule_p() const;
+};
+#endif // METER_HH
+
--- /dev/null
+/*
+ midi-def.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+
+#ifndef MIDIDEF_HH
+#define MIDIDEF_HH
+#include "proto.hh"
+#include "real.hh"
+#include "string.hh"
+#include "moment.hh"
+
+
+/**
+ */
+struct Midi_def {
+ /// output file name
+ String outfile_str_;
+
+ /// duration of whole note
+ Real whole_seconds_f_;
+
+ Midi_def();
+ Midi_def(Midi_def const& midi_c_r);
+ ~Midi_def();
+
+ Real duration_to_seconds_f(Moment);
+ int get_tempo_i( Moment moment );
+ void set_tempo( Moment moment, int count_per_minute_i );
+ void print() const;
+};
+
+#endif // MIDIDEF_HH //
+
--- /dev/null
+/*
+ midi-walker.hh -- declare Midi_walker
+
+ (c) 1996,97 Han-Wen Nienhuys, Jan Nieuwenhuizen <jan@digicash.com>
+ */
+
+#ifndef MIDIWALKER_HH
+#define MIDIWALKER_HH
+
+#include "proto.hh"
+#include "grouping.hh"
+#include "staff-walker.hh"
+#include "pcursor.hh"
+#include "pqueue.hh"
+
+
+/**
+ a simple walker which collects midi stuff, and then outputs.
+
+ Should derive from Staff_walker
+ */
+class Midi_walker : public PCursor<Staff_column*> {
+ Midi_track *track_l_;
+ PQueue<Melodic_req*, Moment> stop_notes;
+ Moment last_moment_;
+
+ /* *************** */
+ void do_stop_notes(Moment);
+
+ void output_event(Midi_item&, Moment);
+public:
+
+ Midi_walker(Staff*, Midi_track*);
+ void process_requests();
+ ~Midi_walker();
+};
+
+
+#endif // MIDIWALKER_HH
+
+
--- /dev/null
+/*
+ notehead.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef NOTEHEAD_HH
+#define NOTEHEAD_HH
+#include "item.hh"
+
+/**
+ ball at the end of the stem
+takes care of:
+
+ * help lines
+ * proper placing of dots
+
+ */
+
+struct Notehead : Item {
+ NAME_MEMBERS(Notehead);
+
+ int position;
+ /// -1 = lowest, 0 = inside, 1 = top
+ int extremal;
+ /// needed for the help-lines
+ int staff_size;
+ int dots;
+ int balltype;
+ int x_dir;
+
+ /* *************** */
+
+ void set_rhythmic(Rhythmic_req *);
+
+ /**
+ position of top line (5 linestaff: 8)
+ */
+ Notehead(int staff_size);
+ void do_print()const;
+ static int compare(Notehead * const &a, Notehead *const &b) ;
+ Molecule* brew_molecule_p()const;
+};
+#endif // NOTEHEAD_HH
+
--- /dev/null
+/*
+ paper-def.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef Paper_def_HH
+#define Paper_def_HH
+#include "proto.hh"
+#include "real.hh"
+#include "string.hh"
+#include "moment.hh"
+
+
+/** symbols, dimensions and constants
+
+ This struct takes care of all kinds of symbols, dimensions and
+ constants. Most of them are related to the point-size of the fonts,
+ so therefore, the lookup table for symbols is also in here.
+
+ see TODO
+ */
+struct Paper_def {
+ Lookup *lookup_p_;
+ String outfile;
+
+ Real linewidth;
+
+ /// how much space does a whole note take (ideally?)
+ Real whole_width;
+
+ /// ideal = geometric_ ^ log2(duration)
+ Real geometric_;
+
+ /* *************** */
+ void reinit();
+ Paper_def(Lookup*);
+ void set(Lookup*);
+ ~Paper_def();
+ Paper_def(Paper_def const&);
+ Real interline()const;
+ Real internote()const;
+ Real rule_thickness()const;
+ Real standard_height()const;
+ Real note_width() const;
+ void print() const;
+ Real duration_to_dist(Moment);
+};
+
+#endif // Paper_def_HH
+
--- /dev/null
+// the breaking problem for a score.
+
+#ifndef PSCORE_HH
+#define PSCORE_HH
+
+#include "colhpos.hh"
+#include "varray.hh"
+#include "pcol.hh"
+#include "pstaff.hh"
+
+
+/** all stuff which goes onto paper. notes, signs, symbols in a score can be grouped in two ways:
+ horizontally (staffwise), and vertically (columns). #PScore#
+ contains the items, the columns and the staffs.
+ */
+
+struct PScore {
+ Paper_def *paper_l_;
+
+ /// the columns, ordered left to right
+ IPointerList<PCol *> cols;
+
+ /// the idealspacings, no particular order
+ IPointerList<Idealspacing*> suz;
+
+ /// the staffs ordered top to bottom
+ IPointerList<PStaff*> staffs;
+
+ /// all symbols in score. No particular order.
+ IPointerList<Item*> its;
+
+ /// if broken, the different lines
+ IPointerList<Line_of_score*> lines;
+
+ /// crescs etc; no particular order
+ IPointerList<Spanner *> spanners;
+
+ /// broken spanners
+ IPointerList<Spanner*> broken_spans;
+
+ /* *************** */
+ /* CONSTRUCTION */
+
+ PScore(Paper_def*);
+ /// add a line to the broken stuff. Positions given in #config#
+ void set_breaking(Array<Col_hpositions>);
+
+ void add(PStaff *);
+
+
+ /** add an item.
+ add the item in specified containers. If breakstatus is set
+ properly, add it to the {pre,post}break of the pcol.
+ */
+ void typeset_item(Item *item_p, PCol *pcol_l,PStaff*pstaf_l,int breakstatus=1);
+
+ /// add a Spanner
+ void typeset_spanner(Spanner*, PStaff*);
+
+ /// add to bottom of pcols
+ void add(PCol*);
+ void add_broken(Spanner*);
+
+ /* INSPECTION */
+ Array<Item*> select_items(PStaff*, PCol*);
+
+ /**
+ @return argument as a cursor of the list
+ */
+ PCursor<PCol *> find_col(const PCol *)const;
+
+ /* MAIN ROUTINES */
+ void process();
+
+ /// last deed of this struct
+ void output(Tex_stream &ts);
+
+ /* UTILITY ROUTINES */
+
+ /// get the spacing between c1 and c2, create one if necessary.
+ Idealspacing* get_spacing(PCol *c1, PCol *c2);
+
+ /// connect c1 and c2
+ void do_connect(PCol *c1, PCol *c2, Real distance_f, Real strength_f);
+
+ /// connect c1 and c2 and any children of c1 and c2
+ void connect(PCol* c1, PCol *c2, Real distance_f,Real strength_f= 1.0);
+
+ /* STANDARD ROUTINES */
+ void OK()const;
+ void print() const;
+private:
+ /// before calc_breaking
+ void preprocess();
+
+ /// calculate where the lines are to be broken, and use results
+ void calc_breaking();
+
+ /// after calc_breaking
+ void postprocess();
+
+ /// delete unused columns
+ void clean_cols();
+};
+
+#endif
--- /dev/null
+#ifndef PSTAFF_HH
+#define PSTAFF_HH
+
+#include "proto.hh"
+#include "plist.hh"
+#include "item.hh"
+#include "symbol.hh"
+
+/// items grouped horizontally
+struct PStaff {
+ PScore * pscore_l_;
+
+
+ PointerList<const Spanner*> spans;
+ PointerList<Item*> its;
+
+ /* *************** */
+ void add(Item*i);
+ PStaff(PScore*);
+
+private:
+ PStaff(PStaff const&);
+};
+
+#endif
--- /dev/null
+/*
+ register.hh -- part of LilyPond
+
+ (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef REGISTER_HH
+#define REGISTER_HH
+
+#include "proto.hh"
+#include "varray.hh"
+#include "request.hh"
+#include "staff-elem-info.hh"
+
+/**
+ a struct which processes requests, and creates the #Staff_elem#s.
+ It may use derived classes. Hungarian postfix: register
+ */
+class Request_register {
+ friend class Register_group_register;
+ /**
+ You cannot copy a Request_register
+ */
+ Request_register(const Request_register&){}
+protected:
+
+ /// utility
+ virtual Paper_def * paper() const;
+
+ /**
+ try to fit the request in this register
+
+ @return
+ false: not noted, not taken.
+
+ true: request swallowed. Don't try to put the request elsewhere.
+
+
+ Default: always return false
+ */
+ virtual bool try_request(Request *req_l);
+
+ /// make items/spanners with the requests you got
+ virtual void process_requests(){}
+
+ /** typeset any items/spanners. Default: do nothing
+ */
+ virtual void pre_move_processing(){}
+ /** reset any appropriate data. Default: do nothing
+ */
+ virtual void post_move_processing(){}
+
+ /**
+ Is this request eligible to be processed? Default: return false.
+ */
+ virtual bool acceptable_request_b(Request*) const;
+
+ /**
+ typeset a "command" item. Default: pass on to daddy.
+ If the column is not breakable, #pre_p# and #post_p# are junked
+ */
+ virtual void typeset_breakable_item(Item * pre_p ,
+ Item * nobreak_p, Item * post_p);
+ /**
+ Invoke walker method to typeset element. Default: pass on to daddy.
+ */
+ virtual void typeset_element(Staff_elem*elem_p);
+
+ /**
+ take note of item/spanner
+ put item in spanner. Adjust local key; etc.
+
+ Default: ignore the info
+ */
+ virtual void acknowledge_element(Staff_elem_info) {}
+ /**
+ Announce element. Default: pass on to daddy. Utility
+ */
+ virtual void announce_element(Staff_elem_info);
+ /**
+ Set features of the register(s). Default: ignore features.
+ */
+ virtual void set_feature(Features){}
+ /**
+ Does this equal or contain a certain register?
+ */
+ virtual bool contains_b(Request_register*reg_l);
+ /**
+ Get information on the staff. Default: ask daddy.
+ */
+ virtual Staff_info get_staff_info();
+
+ virtual void do_print()const;
+public:
+ /** Every Request_register (except for the 'top' which is directly
+ inside the Staff_walker, is a element of a group. */
+ Register_group_register * daddy_reg_l_;
+
+ Request_register();
+ virtual ~Request_register(){}
+ NAME_MEMBERS(Request_register);
+ void print() const;
+};
+
+
+#endif // REGISTER_HH
+
--- /dev/null
+/*
+ registergroup.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef REGISTERGROUP_HH
+#define REGISTERGROUP_HH
+
+
+#include "plist.hh"
+#include "staff-elem-info.hh"
+#include "register.hh"
+
+/**
+ Group a number of registers. Usually delegates everything to its contents.
+ Postfix: group
+ */
+class Register_group_register : public Request_register {
+protected:
+ IPointerList<Request_register*> reg_list_;
+ virtual void do_print()const;
+public:
+
+ /**
+ Junk #reg_l#.
+
+ Pre:
+ #reg_l# is in #reg_list_#
+ */
+ virtual void terminate_register(Request_register * reg_l);
+
+ /**
+ Remove #reg_l# from the list, and return it.
+ */
+ Request_register * get_register_p(Request_register*reg_l);
+ virtual void set_feature(Features i);
+ virtual bool acceptable_request_b(Request*);
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ virtual void acknowledge_element(Staff_elem_info info);
+ virtual bool try_request(Request*);
+ virtual void process_requests();
+ virtual ~Register_group_register();
+ virtual void add(Request_register* reg_p);
+ virtual bool contains_b(Request_register*);
+};
+
+#endif // REGISTERGROUP_HH
+
+
--- /dev/null
+/*
+ request.hh -- declare Request baseclasses.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef REQUEST_HH
+#define REQUEST_HH
+// LilyPond's second egg of columbus!
+
+#include "glob.hh"
+#include "string.hh"
+#include "moment.hh"
+#include "class-name.hh"
+
+/**
+ a voice element wants something printed.
+ Hungarian postfix: req
+ @see lilygut manpage
+ */
+class Request {
+public:
+ Voice_element*elt_l_;
+ char const* defined_ch_c_l_;
+
+ /* *************** */
+ Voice * voice_l();
+ Request();
+ Request(Request const&);
+ virtual ~Request(){}
+
+ NAME_MEMBERS(Request);
+ virtual Request* clone() const { return new Request(*this); }
+ void print()const ;
+
+ virtual Moment duration() const { return 0; }
+
+ /* accessors for children
+ maybe checkout RTTI
+ */
+ virtual Barcheck_req *barcheck() { return 0; }
+ virtual Note_req *note() { return 0;}
+ virtual Script_req *script() { return 0;}
+ virtual Stem_req *stem() { return 0;}
+ virtual Text_req*text() { return 0; }
+ virtual Rest_req *rest() { return 0; }
+ virtual Span_req *span() { return 0; }
+ virtual Beam_req *beam() { return 0 ; }
+ virtual Plet_req* plet() { return 0; }
+ virtual Slur_req *slur() { return 0 ; }
+ virtual Rhythmic_req*rhythmic() { return 0; }
+ virtual Lyric_req* lreq_l() { return 0; }
+ virtual Melodic_req *melodic() { return 0; }
+ virtual Terminate_voice_req *terminate() {return 0;}
+ virtual Group_change_req * groupchange() { return 0;}
+ virtual Group_feature_req * groupfeature() { return 0; }
+ virtual Spacing_req * spacing() { return 0; }
+ virtual Blank_req * blank() { return 0; }
+ virtual Musical_req *musical() { return 0; }
+ virtual Command_req * command() { return 0; }
+protected:
+ virtual void do_print()const ;
+};
+
+#define REQUESTMETHODS(T,accessor) \
+virtual T * accessor() { return this;}\
+NAME_MEMBERS(T);\
+virtual Request *clone() const { return new T(*this); } \
+virtual void do_print() const
+
+#endif
--- /dev/null
+/*
+ rest.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef REST_HH
+#define REST_HH
+#include "item.hh"
+
+struct Rest : Item {
+
+ int dots;
+ int balltype;
+
+ /* *************** */
+
+
+ Rest(int dur,int dots);
+ void do_print()const;
+NAME_MEMBERS(Rest);
+ Molecule* brew_molecule_p()const;
+};
+#endif
+
--- /dev/null
+/*
+ score-walker.hh -- declare Score_walker
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef SCOREWALKER_HH
+#define SCOREWALKER_HH
+#include "pcursor.hh"
+#include "proto.hh"
+#include "varray.hh"
+
+
+/**
+ walk through the score_columns, and while doing so, walk all staffs in a score.
+ */
+class Score_walker : public PCursor<Score_column *>
+{
+ Score* score_l_;
+ /// walkers for the individual staves.
+ Array<Staff_walker *> walker_p_arr_;
+ Array<Staff_walker *> disallow_break_walk_l_arr;
+ int disallow_break_count_;
+ void reinit();
+public:
+ void allow_break(Staff_walker*w);
+ Score_walker(Score*);
+ ~Score_walker();
+ Moment when();
+ void operator++(int);
+ /// process staff walkers.
+ void process();
+};
+#endif // SCOREWALKER_HH
--- /dev/null
+/*
+ score.hh -- declare Score
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef SCORE_HH
+#define SCORE_HH
+
+#include "varray.hh"
+#include "proto.hh"
+#include "plist.hh"
+#include "moment.hh"
+#include "assoc.hh"
+#include "string.hh"
+
+/// the total music def of one movement
+struct Score {
+ /// paper_, staffs_ and commands_ form the problem definition.
+ Paper_def *paper_p_;
+ Midi_def *midi_p_;
+ IPointerList<Staff*> staffs_;
+
+ /// "runtime" fields for setting up spacing
+ IPointerList<Score_column*> cols_;
+ PScore *pscore_p_;
+
+ const char *defined_ch_c_l_;
+ int errorlevel_i_;
+
+ /* *************************************************************** */
+
+ /// construction
+ Score();
+ ~Score();
+ void add(Staff*);
+
+ /// do everything except outputting to file
+ void process();
+
+ /// output to file
+ void output(String fn);
+
+
+ ///
+ void set(Midi_def* midi_p);
+ ///
+ void set(Paper_def* midi_p);
+
+ // standard
+ void OK() const;
+ void print() const;
+
+ /// find a column.
+ PCursor<Score_column *> find_col(Moment,bool);
+
+ /// when does the last *musical* element finish?
+ Moment last() const;
+
+private:
+ void paper_output();
+ void setup_music();
+ void process_music();
+ /// do midi stuff
+ void midi();
+
+ /// do paper stuff
+ void paper();
+
+ // utils:
+ PCursor<Score_column*> create_cols(Moment);
+
+ Score(Score const&){}
+
+ /**
+ make the pcol_l_ fields of each Score_column point to the correct PCol,
+ remove any unnecessary Score_column's
+ */
+ void do_cols();
+
+ /// remove unused cols
+ void clean_cols();
+
+ /// add #Idealspacings# to #pscore_#
+ void calc_idealspacing();
+};
+#endif
--- /dev/null
+/*
+ script-def.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef SCRIPTDEF_HH
+#define SCRIPTDEF_HH
+#include "string.hh"
+struct Script_def{
+ int stemdir;
+ int staffdir;
+
+ bool invertsym;
+ String symidx;
+
+ /* *************** */
+ int compare(Script_def const &);
+ void print() const;
+ Script_def(String, int, int ,bool);
+};
+
+
+#endif // SCRIPTDEF_HH
+
--- /dev/null
+/*
+ script-reg.hh -- part of LilyPond
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef SCRIPTREG_HH
+#define SCRIPTREG_HH
+
+#include "register.hh"
+
+
+struct Script_register : Request_register {
+ Script * script_p_;
+ Script_req * script_req_l_;
+ int dir_i_;
+ /* *************** */
+ void set_feature(Features dir_i_);
+ Script_register();
+ virtual bool try_request(Request*);
+ virtual void process_requests();
+ virtual void acknowledge_element(Staff_elem_info);
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ NAME_MEMBERS(Script_register);
+};
+
+#endif // SCRIPTREG_HH
--- /dev/null
+/*
+ script.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef SCRIPT_HH
+#define SCRIPT_HH
+
+#include "script-def.hh"
+#include "item.hh"
+
+struct Script : Item {
+ int dir;
+ int symdir;
+ int pos;
+ int staffsize;
+ Script_def *specs_l_;
+ Stem *stem_l_;
+ Array<Item *> support;
+
+ /* *************** */
+ NAME_MEMBERS(Script);
+ Molecule *brew_molecule_p()const;
+ virtual void do_post_processing();
+ virtual void do_pre_processing();
+ Script(Script_req*, int staffsize);
+ void set_support(Item*);
+ void set_stem(Stem*);
+ Interval support_height()const;
+ virtual Interval width() const;
+private:
+ void set_symdir();
+ void set_default_dir();
+ void set_default_index();
+ Symbol symbol()const;
+};
+
+
+#endif // SCRIPT_HH
+
--- /dev/null
+/*
+ slur-reg.hh -- declare Slur_register
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef SLURREG_HH
+#define SLURREG_HH
+
+#include "register.hh"
+
+struct Slur_register : Request_register {
+ Array<Slur_req*> requests_arr_;
+ Array<Slur_req*> new_slur_req_l_arr_;
+ Array<Slur *> slur_l_stack_;
+ Array<Slur*> end_slur_l_arr_;
+
+ int dir_i_;
+
+ /* *************** */
+ ~Slur_register();
+ Slur_register();
+ virtual bool try_request(Request*);
+ virtual void process_requests();
+ virtual void acknowledge_element(Staff_elem_info);
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ virtual void set_feature(Features);
+ NAME_MEMBERS(Slur_register);
+};
+
+#endif // SLURREG_HH
--- /dev/null
+/*
+ slur.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef SLUR_HH
+#define SLUR_HH
+
+#include "directional-spanner.hh"
+#include "fproto.hh"
+#include "varray.hh"
+
+struct Slur : Directional_spanner {
+
+ Array<Notehead*> encompass;
+
+ bool open_left, open_right;
+
+ /* *************** */
+ Offset center() const;
+ Slur();
+ void do_post_processing();
+ void do_pre_processing();
+ void add(Notehead*);
+ void set_default_dir();
+
+ Spanner* do_break_at( PCol*, PCol*) const;
+ void process();
+private:
+ Molecule*brew_molecule_p()const;
+ NAME_MEMBERS(Slur);
+};
+
+#endif // SLUR_HH
+
+
--- /dev/null
+/*
+ spanner.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef SPANNER_HH
+#define SPANNER_HH
+
+#include "proto.hh"
+#include "staff-elem.hh"
+
+
+/** a symbol which is attached between two columns. A spanner is a symbol which spans across several columns, so its
+ final appearance can only be calculated after the breaking problem
+ is solved.
+
+ Examples
+
+ - (de)crescendo
+ - slur
+ - beam
+ - bracket
+
+
+ Spanner should know about the items which it should consider:
+ e.g. slurs should be steep enough to "enclose" all those items. This
+ is absolutely necessary for beams, since they have to adjust the
+ length of stems of notes they encompass.
+
+ */
+struct Spanner:Staff_elem {
+ PCol *left, *right;
+
+
+ /* *************** */
+
+ Spanner();
+ virtual Interval width()const;
+ void do_print()const;
+
+ Spanner *broken_at(PCol *c1, PCol *c2) const;
+ virtual Spanner* spanner() { return this; }
+protected:
+
+ /**
+ clone a piece of this spanner.
+ PRE
+ c1 >= start, c2 <= stop
+ */
+ virtual Spanner *do_break_at( PCol *c1, PCol *c2) const=0;
+ NAME_MEMBERS(Spanner);
+};
+#endif
--- /dev/null
+/*
+ staff-column.hh -- declare Staff_column
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef STAFFCOLUMN_HH
+#define STAFFCOLUMN_HH
+#include "proto.hh"
+#include "varray.hh"
+#include "moment.hh"
+
+/// store simultaneous requests
+class Staff_column {
+
+ Staff_column(Staff_column const&);
+
+public:
+ Array<Request*> creationreq_l_arr_;
+ Array<Request*> musicalreq_l_arr_;
+ Array<Request*> commandreq_l_arr_;
+ Staff * staff_l_;
+
+ /// fields to collect timing data vertically.
+ Array<Timing_req*> timing_req_l_arr_;
+ Score_column *musical_column_l_, *command_column_l_;
+
+ /* *************** */
+
+ Staff_column();
+
+ Moment when() const;
+ void set_cols(Score_column *c1, Score_column *c2);
+ void add(Voice_element*ve);
+ void OK() const;
+ ~Staff_column();
+ void typeset_breakable_items(Array<Item *> &pre_p_arr,
+ Array<Item *> &nobreak_p_arr,
+ Array<Item *> &post_p_arr);
+ void typeset_musical_item(Item *i);
+protected:
+ void setup_one_request(Request*);
+};
+
+
+
+#endif // STAFFCOLUMN_HH
+
--- /dev/null
+/*
+ staff-elem-info.hh -- declare Staff_elem_info
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef STAFFELEMINFO_HH
+#define STAFFELEMINFO_HH
+
+#include "proto.hh"
+#include "varray.hh"
+/// data container.
+struct Staff_elem_info {
+ Staff_elem * elem_p_;
+ Request*req_l_;
+ const Voice * voice_l_;
+ Array<Request_register*> origin_reg_l_arr_;
+
+
+ /* *** */
+ Staff_elem_info(Staff_elem*, Request*);
+ Staff_elem_info();
+};
+
+struct Staff_info {
+ int *c0_position_i_;
+ Staff_walker *walk_l_;
+ const Time_description *time_c_l_;
+ const Rhythmic_grouping *rhythmic_c_l_;
+};
+
+
+struct Features {
+ bool initialiser_b_;
+ int direction_i_;
+
+ Features();
+ static Features dir(int);
+};
+#endif // STAFFELEMINFO_HH
--- /dev/null
+/*
+ staff-elem.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef STAFFELEM_HH
+#define STAFFELEM_HH
+#include "varray.hh"
+#include "proto.hh"
+#include "offset.hh"
+#include "molecule.hh"
+#include "class-name.hh"
+
+
+/** Both Spanner and Item are Staff_elem's. Most Staff_elem's depend
+ on other Staff_elem's, eg, Beam needs to know and set direction of
+ Stem. So the Beam has to be calculated *before* Stem. This is
+ accomplished with the dependencies field of struct Staff_elem.
+
+ */
+struct Staff_elem {
+ enum Status {
+ ORPHAN, // not yet added to pstaff
+ VIRGIN, // added to pstaff
+ PRECALCING,
+ PRECALCED, // calcs before spacing done
+ POSTCALCING,
+ POSTCALCED, // after spacing calcs done
+ OUTPUT, // molecule has been output
+ } status;
+
+ /// the pstaff it is in
+ PStaff *pstaff_l_;
+
+ /* *************** */
+ Staff_elem(Staff_elem const&);
+ String TeXstring () const ;
+ virtual void print() const;
+ virtual Interval width() const;
+ virtual Interval height() const;
+ Paper_def *paper() const;
+ virtual ~Staff_elem();
+ Staff_elem();
+ NAME_MEMBERS(Staff_elem);
+ void translate(Offset);
+ void add_processing();
+ void pre_processing();
+ void post_processing();
+ void molecule_processing();
+
+ virtual Spanner* spanner() { return 0; }
+ virtual Item * item() { return 0; }
+ void add_dependency(Staff_elem* );
+ void substitute_dependency(Staff_elem* old, Staff_elem * newdep);
+
+protected:
+
+ /// do printing of derived info.
+ virtual void do_print() const=0;
+ /// generate the molecule
+ virtual Molecule* brew_molecule_p()const=0;
+ ///executed directly after the item is added to the PScore
+ virtual void do_add_processing();
+ /// do calculations before determining horizontal spacing
+ virtual void do_pre_processing();
+
+ /// do calculations after determining horizontal spacing
+ virtual void do_post_processing();
+
+ Array<Staff_elem*> dependants;
+
+private:
+ /// member: the symbols
+ Molecule *output; // should scrap, and use temp var?
+
+
+ /**
+ This is needed, because #output# may still be
+ NULL.
+ */
+ Offset offset_;
+ Array<Staff_elem*> dependencies;
+};
+
+
+#endif // STAFFELEM_HH
+
--- /dev/null
+/*
+ staff-walker.hh -- declare Staff_walker
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef STAFFWALKER_HH
+#define STAFFWALKER_HH
+
+#include "proto.hh"
+#include "time-description.hh"
+#include "pcursor.hh"
+
+/**
+ manage run-time info when walking staffcolumns such as: key,
+ meter, pending beams & slurs
+ */
+struct Staff_walker : public PCursor<Staff_column*> {
+ Staff * staff_l_;
+ PScore * pscore_l_;
+ Score_walker *score_walk_l_;
+ Time_description time_;
+ Rhythmic_grouping *default_grouping;
+
+ /* *************** */
+
+ Moment when() const;
+ virtual ~Staff_walker();
+ Staff_walker(Staff*, PScore*);
+ void process() ;
+
+ void operator++(int);
+ void allow_break();
+
+protected:
+ /// every time before ++ is called
+ virtual void do_pre_move(){}
+ /// every time after ++ is called
+ virtual void do_post_move(){}
+ virtual void process_requests()=0;
+private:
+ void process_timing_reqs();
+ Staff_walker(Staff_walker const&);
+};
+
+#endif // STAFFWALKER_HH
+
--- /dev/null
+/*
+ staff.hh -- declare Staff
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef STAFF_HH
+#define STAFF_HH
+
+#include "plist.hh"
+#include "proto.hh"
+#include "moment.hh"
+
+/// base class for a collection of voices.
+class Staff {
+ Staff(const Staff&src);
+
+ /// synchronous horizontal stuff
+ IPointerList<Voice*> voice_list_;
+ Staff_column *get_col(Moment, PCursor<Staff_column*> * last= 0);
+
+public:
+
+ /// runtime field
+ IPointerList<Staff_column*> cols_;
+
+ Score *score_l_;
+ PScore *pscore_l_;
+ PStaff *pstaff_l_;
+
+ /* *************************************************************** */
+
+ void add(const PointerList<Voice*> &s);
+
+ void add_voice(Voice *v);
+ Paper_def*paper()const;
+
+ void setup_staffcols();
+
+ void OK() const;
+ void print() const;
+
+ /// when does the last *musical* element finish?
+ Moment last() const;
+
+// /// extract midi info
+// Midi_track* midi_track_p();
+
+ /// remove unused cols
+ void clean_cols() ;
+ Staff();
+
+ virtual void set_output(PScore * destination)=0;
+ virtual Staff_walker *get_walker_p()=0;
+ virtual ~Staff() { }
+protected:
+
+};
+#endif
--- /dev/null
+/*
+ staffsym.hh -- declare Staff_symbol
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef STAFFSYM_HH
+#define STAFFSYM_HH
+#include "spanner.hh"
+/**
+ This spanner draws the lines of a pstaff.
+ The bottom line is position 0.
+ */
+class Staff_symbol : public Spanner
+{
+public:
+ /// this many lines.
+ int no_lines_i_;
+
+ NAME_MEMBERS(Staff_symbol);
+ Staff_symbol(int lines);
+ virtual Molecule* brew_molecule_p() const;
+ void set_extent(PCol* p1, PCol* p2);
+ virtual void do_print()const;
+ virtual Spanner *do_break_at( PCol *c1, PCol *c2) const;
+};
+#endif // STAFFSYM_HH
--- /dev/null
+/*
+ stem-beam-reg.hh -- part of LilyPond
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef STEMBEAMREG_HH
+#define STEMBEAMREG_HH
+#include "register.hh"
+
+struct Stem_beam_register : Request_register {
+ Stem * stem_p_;
+ Beam * beam_p_;
+ Beam_req * beam_req_l_;
+ Stem_req * stem_req_l_;
+ Beam_req * start_req_l_;
+ bool end_beam_b_;
+ Rhythmic_grouping *current_grouping;
+ int default_dir_i_;
+
+ /* *************** */
+ Stem_beam_register();
+ ~Stem_beam_register();
+ virtual void set_feature(Features dir_i_);
+ virtual bool try_request(Request*);
+ virtual void process_requests();
+ virtual void acknowledge_element(Staff_elem_info);
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ NAME_MEMBERS(Stem_beam_register);
+};
+#endif // STEMBEAMREG_HH
--- /dev/null
+/*
+ stem.hh -- declare Stem
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef STEM_HH
+#define STEM_HH
+#include "item.hh"
+#include "varray.hh"
+#include "moment.hh"
+
+
+/**the rule attached to the ball.
+ takes care of:
+
+ \begin{itemize}
+ \item the rule
+ \item the flag
+ \item up/down position.
+ \end{itemize}
+ */
+
+struct Stem : Item {
+ /// heads that the stem encompasses (positions)
+ int minnote, maxnote;
+
+ /// false if in beam
+ bool print_flag;
+
+ int beams_left;
+ int beams_right;
+
+ /// needed for determining direction/length
+ int staff_center;
+
+
+ /**extent of the stem (positions).
+ fractional, since Beam has to adapt them.
+ */
+
+ Real bot, top;
+ Real stemlen;
+
+ /// flagtype? 4 none, 8 8th flag, 0 = beam.
+ int flag;
+
+
+ /**
+ geen gedonder, jij gaat onder.
+ -1 stem points down, +1: stem points up
+ */
+
+ int dir;
+ Real stem_xoffset;
+
+ Array<Notehead*> heads;
+
+ /* *************** */
+ Stem(int center); //, Moment duration);
+
+ /// ensure that this Stem also encompasses the Notehead #n#
+ void add(Notehead*n);
+
+ NAME_MEMBERS(Stem);
+
+ Real hindex()const;
+ void do_print() const;
+ void set_stemend(Real);
+ int get_default_dir();
+ void set_default_dir();
+ void set_default_stemlen();
+ void set_default_extents();
+ void set_noteheads();
+ void do_pre_processing();
+
+ Interval width() const;
+
+ Molecule* brew_molecule_p() const;
+};
+#endif
--- /dev/null
+#ifndef SYMBOL_HH
+#define SYMBOL_HH
+
+#include "string.hh"
+#include "boxes.hh"
+#include "proto.hh"
+
+struct Symbol {
+ String tex;
+ Box dim;
+
+ Symbol (String, Box);
+ Symbol();
+ String str()const; // for printing.
+};
+
+#endif
--- /dev/null
+/*
+ lilypond, (c) 1996,97 Han-Wen Nienhuys
+*/
+#ifndef SYMTABLE_HH
+#define SYMTABLE_HH
+#include "assoc.hh"
+#include "string.hh"
+#include "symbol.hh"
+
+struct Symtable : public Assoc<String, Symbol> {
+ Symbol lookup(String)const;
+ void print()const;
+};
+
+
+struct Symtables : private Assoc<String, Symtable*> {
+
+ Symtable* operator()(String s);
+ ~Symtables();
+ Symtables();
+ Symtables(Symtables const&);
+ Assoc<String, Symtable*>::add;
+ void print()const;
+};
+
+
+#endif
+
--- /dev/null
+/*
+ text-def.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef TEXTDEF_HH
+#define TEXTDEF_HH
+
+#include "string.hh"
+#include "proto.hh"
+
+struct Text_def {
+ int align_i_;
+ String text_str_;
+ String style_str_;
+ char const* defined_ch_c_l_;
+
+
+ /* ****************/
+ virtual ~Text_def() {};
+ bool compare(const Text_def&);
+ Text_def();
+ virtual void print() const;
+ virtual Atom create_atom(Paper_def*) const;
+};
+
+#endif // TEXTDEF_HH
+
--- /dev/null
+/*
+ text.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef TEXT_ITEM_HH
+#define TEXT_ITEM_HH
+
+#include "text-def.hh"
+#include "item.hh"
+
+struct Text_item : Item {
+ int pos_i_;
+ int staffsize_i_;
+ int dir_i_;
+ Text_def* tdef_l_;
+
+ /* ***************/
+ NAME_MEMBERS(Text_item);
+ virtual void set_default_index();
+ Molecule* brew_molecule_p() const;
+ void do_pre_processing();
+
+ Text_item(Text_req*,int);
+};
+
+
+#endif // TEXT_HH
+
--- /dev/null
+/*
+ text-reg.hh -- part of LilyPond
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef TEXTREG_HH
+#define TEXTREG_HH
+#include "register.hh"
+
+struct Text_register : Request_register{
+ Text_item * text_p_;
+ Text_req * text_req_l_;
+ int dir_i_;
+ /* *************** */
+ virtual void set_feature(Features );
+ Text_register();
+ virtual bool try_request(Request*);
+ virtual void process_requests();
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ NAME_MEMBERS(Text_register);
+};
+
+#endif // TEXTREG_HH
--- /dev/null
+/*
+ textspanner.hh -- part of LilyPond
+
+ (c) 1996,97 Han-Wen Nienhuys
+*/
+
+#ifndef TEXTSPANNER_HH
+#define TEXTSPANNER_HH
+
+#include "string.hh"
+#include "directional-spanner.hh"
+#include "text-def.hh"
+
+/** a spanner which puts texts on top of other spanners. Use for
+ triplets, eentweetjes, ottava, etc. */
+struct Text_spanner : Spanner {
+ Text_def spec;
+ Offset text_off_;
+ Directional_spanner*support;
+
+ /* *************** */
+
+ NAME_MEMBERS(Text_spanner);
+ virtual void do_pre_processing();
+ virtual void do_post_processing();
+ virtual Interval height() const ;
+ virtual Molecule* brew_molecule_p()const;
+ virtual void do_print() const;
+ virtual Spanner* do_break_at(PCol*,PCol*)const;
+ Text_spanner();
+ void set_support(Directional_spanner*);
+};
+#endif // TEXTSPANNER_HH
+
--- /dev/null
+/*
+ voice-element.hh -- declare Voice_element
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef VOICE_ELEMENT_HH
+#define VOICE_ELEMENT_HH
+
+#include "proto.hh"
+#include "plist.hh"
+#include "moment.hh"
+
+/** one horizontal bit. Voice_element is nothing but a container for
+ *the requests, */
+struct Voice_element {
+ Moment duration;
+ char const* defined_ch_c_l_;
+ const Voice *voice_l_;
+ IPointerList<Request*> reqs;
+
+ /* *************** */
+
+ Voice_element();
+ Voice_element(Voice_element const & src );
+
+ void add(Request*);
+ bool find_plet_start_bo(char c, Moment& moment_r);
+ void print ()const;
+ void set_default_group(String id);
+ void set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i);
+};
+
+#endif // VOICE-ELEMENT_HH
--- /dev/null
+/*
+ voice-group-regs.hh -- declare Voice_group_registers
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef VOICEGROUPREGS_HH
+#define VOICEGROUPREGS_HH
+
+#include "registergroup.hh"
+
+struct Voice_group_registers : Register_group_register {
+ String group_id_str_;
+ Array<Voice_registers*> voice_regs_l_;
+
+ /* *************** */
+
+ NAME_MEMBERS(Voice_group_registers);
+ static bool static_acceptable_request_b(Request*);
+ virtual void terminate_register(Request_register*);
+ virtual void do_print() const;
+ virtual void add(Request_register*);
+ Voice_group_registers(String id);
+ virtual bool try_request(Request*);
+};
+#endif // VOICEGROUPREGS_HH
--- /dev/null
+/*
+ voice-regs.hh -- declare Voice_registers
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef VOICEREGS_HH
+#define VOICEREGS_HH
+
+#include "registergroup.hh"
+
+class Voice_registers : public Register_group_register {
+
+
+public:
+ Voice *voice_l_;
+ /* *************** */
+
+ NAME_MEMBERS(Voice_registers);
+ virtual bool acceptable_request_b(Request*);
+ virtual void acknowledge_element(Staff_elem_info info);
+ virtual bool try_request(Request*);
+ Voice_registers(Voice*);
+ virtual void do_print() const;
+};
+
+
+#endif // VOICEREGS_HH
--- /dev/null
+#ifndef VOICE_HH
+#define VOICE_HH
+
+#include "proto.hh"
+#include "plist.hh"
+#include "moment.hh"
+
+/** class for horizontal stuff.
+
+ Voice is a ordered row of Voice_elements. It is strictly
+ horizontal: you cannot have two rhythmic elements running parallel
+ in a Voice. For proper processing, each Voice should have
+ Group_change_req as a first element.
+
+ */
+
+struct Voice {
+ IPointerList<Voice_element *> elts;
+ Moment start;
+
+ /* *************** */
+ Voice();
+ Voice(Voice const&);
+
+ Moment when(const Voice_element*)const;
+ Moment last() const;
+
+ void add(Voice_element*);
+ bool find_plet_start_bo(char c, Moment& moment_r);
+ void print() const;
+ void set_default_group(String id);
+ void set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i);
+};
+
+#endif
--- /dev/null
+/*
+ walkregs.hh -- declare Walker_registers
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef WALKREGS_HH
+#define WALKREGS_HH
+
+
+#include "registergroup.hh"
+
+/**
+ Top level registers: the interface to Complex_walker.
+
+ [sigh. Sometimes I wish C++ could do better late binding.]
+ */
+struct Walker_registers : Register_group_register {
+ Array<Item*> prebreak_item_p_arr_;
+ Array<Item*> nobreak_item_p_arr_;
+ Array<Item*> postbreak_item_p_arr_;
+ Array<Staff_elem_info> announce_info_arr_;
+ Array<Voice_group_registers*> group_l_arr_;
+ Complex_walker * walk_l_;
+
+ /* *************** */
+ void change_group(Group_change_req * greq_l,
+ Voice_registers *voice_regs_l,
+ Voice_group_registers * old_group);
+ Voice_group_registers * get_group(String id);
+ void typeset_musical_item(Staff_elem * elem_p);
+ Walker_registers(Complex_walker*);
+ void do_announces();
+ void terminate_register(Request_register * reg);
+ virtual bool try_request(Request * r);
+ virtual Staff_info get_staff_info();
+
+ virtual void announce_element(Staff_elem_info);
+ virtual void acknowledge_element(Staff_elem_info);
+ virtual void typeset_breakable_item(Item * pre_p , Item * nobreak_p, Item * post_p);
+ virtual void typeset_element(Staff_elem*elem_p);
+ virtual void pre_move_processing();
+ virtual void post_move_processing();
+ virtual Paper_def * paper() const;
+};
+
+#endif // WALKREGS_HH
--- /dev/null
+#include "debug.hh"
+#include "input-music.hh"
+#include "voice.hh"
+#include "musicalrequest.hh"
+#include "voice-element.hh"
+
+void
+Input_music::check_plet(Voice_element* velt_l)
+{
+ for (iter_top(velt_l->reqs,i); i.ok(); i++)
+ if ( i->plet() ) {
+ Moment start_moment = 0;
+ if ( !find_plet_start_bo( i->plet()->type_c_, start_moment ) ) {
+ error( "begin of plet not found", i->defined_ch_c_l_ );
+ break;
+ }
+ Moment moment = 0;
+ set_plet_backwards( moment, start_moment, i->plet()->dur_i_, i->plet()->type_i_ );
+ i.del();
+ break;
+ }
+}
+
+void
+Simple_music::add(Voice_element*v)
+{
+ voice_.add(v);
+}
+
+Moment
+Simple_music::length()const
+{
+ return voice_.last();
+}
+void
+Simple_music::translate_time(Moment t)
+{
+ voice_.start += t;
+}
+
+Voice_list
+Simple_music::convert()const
+{
+ Voice_list l;
+ l.bottom().add(new Voice(voice_));
+ return l;
+}
+
+
+void
+Simple_music::print() const
+{
+ mtor << "Simple_music {";
+ voice_.print();
+ mtor << "}\n";
+}
+bool
+Simple_music::find_plet_start_bo(char c, Moment& moment_r)
+{
+ return voice_.find_plet_start_bo(c, moment_r);
+}
+void
+Simple_music::set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i)
+{
+ voice_.set_plet_backwards(now_moment_r, until_moment, num_i, den_i);
+}
+
+/* *************** */
+
+void
+Complex_music::add(Input_music*v)
+{
+ elts.bottom().add(v);
+}
+
+void
+Complex_music::print() const
+{
+ for (iter_top(elts,i); i.ok(); i++)
+ i->print();
+}
+
+void
+Complex_music::concatenate(Complex_music*h)
+{
+ for (iter_top(h->elts,i); i.ok(); i++)
+ add(i->clone());
+}
+
+Complex_music::Complex_music()
+{
+}
+
+Complex_music::Complex_music(Complex_music const&s)
+{
+ for (iter_top(s.elts,i); i.ok(); i++)
+ add(i->clone());
+}
+void
+Complex_music::set_default_group(String g)
+{
+ for (iter_top(elts,i); i.ok(); i++)
+ i->set_default_group(g);
+}
+bool
+Complex_music::find_plet_start_bo(char c, Moment& moment_r)
+{
+ for (iter_bot(elts,i); i.ok(); i--) {
+ if ( i->find_plet_start_bo(c, moment_r) )
+ return true;
+ }
+ return false;
+}
+void
+Complex_music::set_plet_backwards(Moment& now_moment_r, Moment until_moment, int num_i, int den_i)
+{
+ for (iter_bot(elts,i); i.ok(); i--) {
+ i->set_plet_backwards(now_moment_r, until_moment, num_i, den_i);
+ }
+}
+/* *************************************************************** */
+
+void
+Music_voice::print() const
+{
+ mtor << "Music_voice {";
+ Complex_music::print();
+ mtor << "}\n";
+}
+
+void
+Music_voice::add_elt(Voice_element*v)
+{
+ PCursor<Input_music*> c(elts.bottom());
+ if (!c.ok() || !c->simple()) {
+ Simple_music*vs = new Simple_music;
+
+ c.add(vs);
+ }
+
+ c = elts.bottom();
+ Simple_music *s = c->simple();
+ s->add(v);
+
+ check_plet(v);
+}
+
+Moment
+Music_voice::length()const
+{
+ Moment l = 0;
+
+ for (iter_top(elts,i); i.ok(); i++)
+ l += i->length();
+ return l;
+}
+
+
+Voice_list
+Music_voice::convert()const
+{
+ Voice_list l;
+ Moment here = 0;
+
+ for (iter_top(elts,i); i.ok(); i++) {
+ Moment len = i->length();
+ Voice_list k(i->convert());
+ k.translate_time(here);
+ l.concatenate(k);
+ here +=len;
+ }
+ return l;
+}
+
+void
+Music_voice::translate_time(Moment t)
+{
+ elts.bottom()->translate_time(t);
+}
+
+
+
+/* *************** */
+
+void
+Music_general_chord::add_elt(Voice_element*v)
+{
+ Simple_music*vs = new Simple_music;
+ vs->add(v);
+ elts.bottom().add(vs);
+
+ check_plet(v);
+}
+
+void
+Music_general_chord::print() const
+{
+ mtor << "Music_general_chord {";
+ Complex_music::print();
+ mtor << "}\n";
+}
+
+void
+Music_general_chord::translate_time(Moment t)
+{
+ for (iter_top(elts,i); i.ok(); i++)
+ i->translate_time(t);
+}
+
+Moment
+Music_general_chord::length()const
+{
+ Moment l =0;
+
+ for (iter_top(elts,i); i.ok(); i++)
+ l = l >? i->length();
+ return l;
+}
+
+Voice_list
+Music_general_chord::convert()const
+{
+ Voice_list l;
+ for (iter_top(elts,i); i.ok(); i++) {
+ Voice_list k(i->convert());
+ l.concatenate(k);
+ }
+ return l;
+}
+
+/* *************** */
+
+void
+Multi_voice_chord::set_default_group(String g)
+{
+ int j=0;
+ for (iter_top(elts, i); i.ok(); i++) {
+ i->set_default_group(g + String(j));
+ j++;
+ }
+}
+
+
+/* *************** */
+
+void
+Voice_list::translate_time(Moment x)
+{
+ for (iter_top(*this,i); i.ok(); i++)
+ i->start += x;
+}
+
--- /dev/null
+/*
+ input-score.cc -- implement Input_score
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "debug.hh"
+#include "input-score.hh"
+#include "input-staff.hh"
+#include "input-music.hh"
+#include "score.hh"
+#include "paper-def.hh"
+#include "midi-def.hh"
+#include "staff.hh"
+
+
+void
+Input_score::add(Input_staff*s)
+{
+ staffs_.bottom().add(s);
+}
+
+void
+Input_score::set(Paper_def*p)
+{
+ delete paper_p_;
+ paper_p_ = p;
+}
+
+void
+Input_score::set(Midi_def* midi_p)
+{
+ delete midi_p_;
+ midi_p_ = midi_p;
+}
+
+Input_score::Input_score(Input_score const&s)
+{
+ paper_p_ = (s.paper_p_)? new Paper_def(*s.paper_p_) :0;
+ midi_p_ = (s.midi_p_)? new Midi_def(*s.midi_p_) : 0;
+ defined_ch_c_l_ = s.defined_ch_c_l_;
+ errorlevel_i_ = s.errorlevel_i_;
+ score_wide_music_p_ = (s.score_wide_music_p_) ?
+ s.score_wide_music_p_->clone():0;
+}
+
+Score*
+Input_score::parse()
+{
+ Score *s_p = new Score;
+ s_p->defined_ch_c_l_= defined_ch_c_l_;
+ s_p->errorlevel_i_ = errorlevel_i_;
+ if (midi_p_)
+ s_p->set(new Midi_def(*midi_p_));
+ if (paper_p_)
+ s_p->set( new Paper_def(*paper_p_));
+
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ Staff* staf_p=i->parse(s_p, score_wide_music_p_);
+ s_p->add(staf_p);
+ }
+
+ return s_p;
+}
+
+void
+Input_score::set(Input_music *m_p)
+{
+ delete score_wide_music_p_;
+ score_wide_music_p_ =m_p;
+}
+
+
+Input_score::~Input_score()
+{
+ delete paper_p_;
+ delete score_wide_music_p_;
+ delete midi_p_;
+}
+
+Input_score::Input_score()
+{
+ score_wide_music_p_ =0;
+ defined_ch_c_l_=0;
+ paper_p_= 0;
+ midi_p_ = 0;
+ errorlevel_i_ = 0;
+}
+
+void
+Input_score::print()const
+{
+#ifndef NPRINT
+ mtor << "Input_score {\n";
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->print();
+ }
+ mtor << "}\n";
+#endif
+}
--- /dev/null
+#include "debug.hh"
+#include "item.hh"
+
+
+
+Item::Item()
+{
+ pcol_l_ = 0;
+}
+
+void
+Item::do_print() const
+{
+#ifndef NPRINT
+ mtor << "(unknown)";
+#endif
+}
+
--- /dev/null
+#include "key-item.hh"
+#include "key.hh"
+#include "debug.hh"
+#include "molecule.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+//#include "clef-reg.hh"
+#include "key-reg.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(int c)
+{
+ set_c_position(c);
+}
+
+void
+Key_item::read(const Key_register& key_reg_r)
+{
+ const Array<int> &idx_arr =key_reg_r.accidental_idx_arr_;
+ for (int i = 0 ; i< idx_arr.size(); i++) {
+ int note = idx_arr[i];
+ int acc = key_reg_r.key_.acc(note);
+
+ add(note, acc);
+ }
+}
+
+void
+Key_item::set_c_position(int c0)
+{
+ int octaves =(abs(c0) / 7) +1 ;
+ c_position=(c0 + 7*octaves)%7;
+}
+
+
+void
+Key_item::add(int p, int a)
+{
+ if ((a<0 && p>FLAT_TOP_PITCH) ||
+ (a>0 && p>SHARP_TOP_PITCH)) {
+ p -= 7; /* Typeset below c_position */
+ }
+ pitch.push(p);
+ acc.push(a);
+}
+
+
+Molecule*
+Key_item::brew_molecule_p()const
+{
+ Molecule*output = new Molecule;
+ Real inter = paper()->internote();
+
+ for (int i =0; i < pitch.size(); i++) {
+ Symbol s= paper()->lookup_p_->accidental(acc[i]);
+ Atom a(s);
+ a.translate(Offset(0,(c_position + pitch[i]) * inter));
+ Molecule m(a);
+ output->add_right(m);
+ }
+ Molecule m(paper()->lookup_p_->fill(Box(
+ Interval(0, paper()->note_width()),
+ Interval(0,0))));
+ output->add_right(m);
+ return output;
+}
--- /dev/null
+/*
+ key-reg.cc -- implement Key_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+
+ todo: key undo
+
+ */
+#include "time-description.hh"
+#include "key-reg.hh"
+#include "key-item.hh"
+#include "commandrequest.hh"
+#include "staff-column.hh"
+#include "local-key-reg.hh"
+#include "musicalrequest.hh"
+
+Key_register::Key_register()
+{
+ post_move_processing();
+}
+
+bool
+Key_register::try_request(Request * req_l)
+{
+ Command_req* creq_l= req_l->command();
+ if (!creq_l|| !creq_l->keychange())
+ return false;
+
+ assert(!keyreq_l_); // todo
+ keyreq_l_ = creq_l->keychange();
+ read_req(keyreq_l_);
+ return true;
+}
+
+void
+Key_register::acknowledge_element(Staff_elem_info info)
+{
+ Command_req * r_l = info.req_l_->command() ;
+ if (r_l && r_l->clefchange() && !kit_p_) {
+ int c0_i= *get_staff_info().c0_position_i_;
+ kit_p_ = new Key_item(c0_i);
+ kit_p_->read(*this);
+ announce_element(Staff_elem_info(kit_p_, keyreq_l_));
+ }
+}
+
+void
+Key_register::process_requests()
+{
+ const Time_description *time_l = get_staff_info().time_c_l_;
+
+ if (!keyreq_l_ &&
+ (!time_l->whole_in_measure_|| !time_l->when_)) {
+ default_key_b_ = true;
+ }
+
+ if ( default_key_b_ || keyreq_l_) {
+ int c0_i= *get_staff_info().c0_position_i_;
+ kit_p_ = new Key_item(c0_i);
+ kit_p_->read(*this);
+ announce_element(Staff_elem_info(kit_p_, keyreq_l_));
+ }
+}
+
+void
+Key_register::pre_move_processing()
+{
+ if (kit_p_) {
+ if (default_key_b_)
+ typeset_breakable_item(0,0,kit_p_);
+ else
+ typeset_breakable_item(
+ new Key_item(*kit_p_), kit_p_, new Key_item(*kit_p_));
+ kit_p_ = 0;
+ }
+}
+
+
+
+void
+Key_register::read_req(Key_change_req * r)
+{
+ accidental_idx_arr_.set_size(0);
+ for (int i = 0; i < r->melodic_p_arr_.size(); i ++) {
+ int n_i=r->melodic_p_arr_[i]->notename_i_;
+ key_.set(n_i, r->melodic_p_arr_[i]->accidental_i_);
+ accidental_idx_arr_.push(n_i);
+ }
+}
+
+void
+Key_register::post_move_processing()
+{
+ keyreq_l_ = 0;
+ default_key_b_ = false;
+ kit_p_ = 0;
+}
--- /dev/null
+#include "key.hh"
+
+const int OCTAVES=14; // ugh..
+const int ZEROOCTAVE=7;
+
+Key::Key()
+{
+ accidental_i_arr_.set_size(7);
+ for (int i= 0; i < 7 ; i++)
+ accidental_i_arr_[i] = 0;
+}
+
+Local_key::Local_key()
+{
+ octaves.set_size(OCTAVES);
+}
+
+Key&
+Local_key::oct(int i)
+{
+ return octaves[i+ZEROOCTAVE];
+}
+
+void
+Key::set(int i, int a)
+{
+ assert(a > -3 && a < 3);
+ accidental_i_arr_[i]=a;
+}
+
+
+void
+Local_key::reset(Key k)
+{
+ for (int i= 0; i < OCTAVES ; i++)
+ octaves[i] = k;
+}
+
--- /dev/null
+/*
+ keyword.cc -- keywords and identifiers
+ */
+
+#include <stdlib.h>
+
+#include "glob.hh"
+#include "lexer.hh"
+//#include "mudobs.hh"
+//#include "gram.hh"
+
+/* for the keyword table */
+struct Keyword_ent
+{
+ const char *name;
+ int tokcode;
+};
+
+struct Keyword_table
+{
+ Keyword_ent *table;
+ int maxkey;
+ Keyword_table(Keyword_ent *);
+ int lookup(const char *s) const;
+};
+
+
+/* for qsort */
+int
+ tabcmp(const void * p1, const void * p2)
+{
+ return strcmp(((const Keyword_ent *) p1)->name,
+ ((const Keyword_ent *) p2)->name);
+}
+
+Keyword_table::Keyword_table(Keyword_ent *tab)
+{
+ table = tab;
+
+ /* count keywords */
+ for (maxkey = 0; table[maxkey].name; maxkey++);
+
+ /* sort them */
+ qsort(table, maxkey, sizeof(Keyword_ent), tabcmp);
+}
+
+/*
+ lookup with binsearch, return tokencode.
+*/
+int
+Keyword_table::lookup(const char *s)const
+{
+ int lo,
+ hi,
+ cmp,
+ result;
+ lo = 0;
+ hi = maxkey;
+
+ /* binary search */
+ do
+ {
+ cmp = (lo + hi) / 2;
+
+ result = strcmp(s, table[cmp].name);
+
+ if (result < 0)
+ hi = cmp;
+ else
+ lo = cmp;
+ }
+ while (hi - lo > 1);
+ if (!strcmp(s, table[lo].name))
+ {
+ return table[lo].tokcode;
+ } else
+ return -1; /* not found */
+}
+
--- /dev/null
+#include "leastsquares.hh"
+void
+Least_squares::OK() const
+{
+ assert( input.size() > 1 );
+ Real dx = 0.0;
+ for (int i=1; i < input.size(); i++)
+ dx += abs (input[i-1].x - input[i].x);
+
+ assert(dx);
+}
+void
+Least_squares::minimise(Real &coef, Real &offset)
+{
+ OK();
+ Real sx = 0.0;
+ Real sy = 0.0;
+ Real sqx =0.0;
+ Real sxy = 0.0;
+
+ for (int i=0; i < input.size();i++) {
+ Real x=input[i].x;
+ Real y = input[i].y;
+ sx += x;
+ sy += y;
+ sqx += sqr(x);
+ sxy += x*y;
+ }
+ int N = input.size();
+
+
+ coef = (N * sxy - sx*sy )/(N*sqx - sqr(sx));
+ offset = (sy - coef * sx)/N;
+
+}
--- /dev/null
+/*
+ lexerinit.cc -- implement some stuff
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include <iostream.h>
+#include <strstream.h>
+#include "proto.hh"
+#include "plist.hh"
+#include "lexer.hh"
+#include "debug.hh"
+#include "main.hh"
+#include "source-file.hh"
+#include "source.hh"
+
+My_flex_lexer *lexer=0;
+
+int
+yylex() {
+ return lexer->yylex();
+}
+
+bool
+busy_parsing()
+{
+ return lexer;
+}
--- /dev/null
+#include <math.h>
+#include "linespace.hh"
+#include "pcol.hh"
+#include "debug.hh"
+#include "qlp.hh"
+#include "unionfind.hh"
+#include "idealspacing.hh"
+
+const Real COLFUDGE=1e-3;
+
+
+bool
+Spacing_problem::contains(const PCol *w)
+{
+ for (int i=0; i< cols.size(); i++)
+ if (cols[i].pcol_ == w)
+ return true;
+ return false;
+}
+
+int
+Spacing_problem::col_id(const PCol *w)const
+{
+ for (int i=0; i< cols.size(); i++)
+ if (cols[i].pcol_ == w)
+ return i;
+ assert(false);
+ return -1;
+}
+
+void
+Spacing_problem::OK() const
+{
+#ifndef NDEBUG
+ Union_find connected(cols.size());
+ Array<int> fixed;
+ for (int i=0; i < ideals.size(); i++) {
+ assert(ideals[i]->hooke > 0);
+ int l = col_id(ideals[i]->left);
+ int r = col_id(ideals[i]->right);
+ connected.connect(l,r);
+ }
+ for (int i = 0; i < cols.size(); i++)
+ if (cols[i].fixed())
+ fixed.push(i);
+ for (int i = 0; i < cols.size(); i++) {
+ bool c=false;
+ for (int j =0; j<fixed.size(); j++)
+ c |= connected.equiv(fixed[j],i);
+ if (!c)
+ WARN << "You have unconnected columns. \n"
+ "Check if bars and music fit each other\n"
+ "(crashing :-)\n";
+ assert(c);
+ }
+#endif
+}
+
+bool
+Spacing_problem::check_constraints(Vector v) const
+{
+ int dim=v.dim();
+ for (int i=0; i < dim; i++) {
+
+ if (cols[i].fixed()&&
+ abs(cols[i].fixed_position() - v(i)) > COLFUDGE)
+ return false;
+
+ if (!i)
+ continue;
+
+ Real mindist=cols[i-1].minright()
+ +cols[i].minleft();
+
+ // ugh... compares
+ Real dif =v(i) - v(i-1)- mindist;
+ bool b = (dif > - COLFUDGE);
+
+
+ if (!b)
+ return false;
+
+ }
+ return true;
+}
+
+bool
+Spacing_problem::check_feasible() const
+{
+ Vector sol(try_initial_solution());
+ return check_constraints(sol);
+}
+
+// generate a solution which obeys the min distances and fixed positions
+Vector
+Spacing_problem::try_initial_solution() const
+{
+ int dim=cols.size();
+ Vector initsol(dim);
+ for (int i=0; i < dim; i++) {
+ if (cols[i].fixed()) {
+ initsol(i)=cols[i].fixed_position();
+ } else {
+ Real mindist=cols[i-1].minright()
+ +cols[i].minleft();
+ assert(mindist >= 0.0);
+ initsol(i)=initsol(i-1)+mindist;
+
+ //nog niet
+ //if (i>0)
+ // assert(initsol(i) > initsol(i-1));
+ }
+ }
+
+ return initsol;
+}
+Vector
+Spacing_problem::find_initial_solution() const
+{
+ Vector v(try_initial_solution());
+ assert(check_constraints(v));
+ return v;
+}
+
+// generate the matrices
+void
+Spacing_problem::make_matrices(Matrix &quad, Vector &lin, Real &c) const
+{
+ quad.fill(0);
+ lin.fill(0);
+ c = 0;
+ for (int j=0; j < ideals.size(); j++){
+ Idealspacing const*i=ideals[j];
+ int l = col_id(i->left);
+ int r = col_id(i->right);
+
+ quad(r,r) += i->hooke;
+ quad(r,l) -= i->hooke;
+ quad(l,r) -= i->hooke;
+ quad(l,l) += i->hooke;
+
+ lin(r) -= i->space*i->hooke;
+ lin(l) += i->space*i->hooke;
+
+ c += sqr(i->space);
+ }
+}
+
+// put the constraints into the LP problem
+void
+Spacing_problem::make_constraints(Mixed_qp& lp) const
+{
+ int dim=cols.size();
+ for (int j=0; j < dim; j++) {
+ Colinfo *c=&(cols[j]);
+ if (c->fixed()) {
+ lp.add_fixed_var(j,c->fixed_position());
+ }
+ if (j > 0){
+ Vector c1(dim);
+
+ c1(j)=1.0 ;
+ c1(j-1)=-1.0 ;
+ lp.add_inequality_cons(c1, cols[j-1].minright() +
+ cols[j].minleft());
+ }
+ }
+}
+
+Array<Real>
+Spacing_problem::solve() const
+{
+ print();
+ OK();
+ assert(check_feasible());
+
+ /* optimalisatiefunctie */
+ Mixed_qp lp(cols.size());
+ make_matrices(lp.quad,lp.lin, lp.const_term);
+ make_constraints(lp);
+ Vector start=find_initial_solution();
+ Vector sol(lp.solve(start));
+ if (!check_constraints(sol)) {
+ WARN << "solution doesn't satisfy constraints.\n" ;
+ }
+
+
+ Array<Real> posns(sol);
+ posns.push(lp.eval(sol));
+ return posns;
+}
+
+/*
+ add one column to the problem.
+*/
+void
+Spacing_problem::add_column(const PCol *col, bool fixed, Real fixpos)
+{
+ Colinfo c(col,(fixed)? &fixpos : 0);
+ cols.push(c);
+}
+
+void
+Spacing_problem::add_ideal(const Idealspacing *i)
+{
+ const PCol *l =i->left;
+ const PCol *r= i->right;
+
+ if (!contains(l) || !contains(r)) {
+ return;
+ }
+ ideals.push(i);
+}
+
+void
+Spacing_problem::print_ideal(const Idealspacing*id)const
+{
+#ifndef NPRINT
+ int l = col_id(id->left);
+ int r = col_id(id->right);
+
+ mtor << "between " << l <<","<<r<<":" ;
+ id->print();
+#endif
+}
+
+void
+Spacing_problem::print() const
+{
+#ifndef NPRINT
+ for (int i=0; i < cols.size(); i++) {
+ mtor << "col " << i<<' ';
+ cols[i].print();
+ }
+ for (int i=0; i < ideals.size(); i++) {
+ print_ideal(ideals[i]);
+ }
+#endif
+
+}
+
+/* **************** */
+
+void
+Colinfo::print() const
+{
+#ifndef NPRINT
+ mtor << "column { ";
+ if (fixed())
+ mtor << "fixed at " << fixed_position()<<", ";
+ assert(pcol_);
+ mtor << "[" << minleft() << ", " << minright() << "]";
+ mtor <<"}\n";
+#endif
+}
+
+Colinfo::Colinfo(Colinfo const&c)
+{
+ fixpos = (c.fixpos)?new Real(*c.fixpos):0;
+ pcol_ = c.pcol_;
+ width = c.width;
+}
+
+Colinfo::Colinfo(const PCol*col_p, const Real*fixed_r_p )
+{
+ fixpos = (fixed_r_p)? new Real(*fixed_r_p) : 0;
+ pcol_ = col_p;
+ width = pcol_->width();
+}
+
+Colinfo::~Colinfo()
+{
+ delete fixpos;
+}
+
+Colinfo::Colinfo()
+{
+ pcol_=0;
+ fixpos = 0;
+}
+void
+Colinfo::operator=(Colinfo const&c )
+{
+ delete fixpos;
+ fixpos = (c.fixpos)?new Real(*c.fixpos):0;
+ pcol_ = c.pcol_;
+ width = c.width;
+}
--- /dev/null
+#include "local-key-item.hh"
+#include "molecule.hh"
+#include "scalar.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "musicalrequest.hh"
+#include "notehead.hh"
+#include "misc.hh"
+
+
+
+Local_key_item::Local_key_item(int i)
+{
+ c0_position = i;
+}
+
+void
+Local_key_item::add(Item*head_l)
+{
+ support_items_.push(head_l);
+ add_dependency(head_l);
+}
+
+void
+Local_key_item::add(Melodic_req*m_l)
+{
+ add(m_l->octave_i_, m_l->notename_i_, m_l->accidental_i_);
+}
+void
+Local_key_item::add (int o, int p , int a)
+{
+ Local_acc l;
+ l.octave = o;
+ l.name = p;
+ l.acc = a;
+ accs.push(l);
+}
+
+void
+Local_key_item::do_pre_processing()
+{
+ accs.sort(Local_acc::compare);
+}
+
+Molecule*
+Local_key_item::brew_molecule_p()const
+{
+ Molecule* output = new Molecule;
+ Molecule*octmol = 0;
+ int lastoct = -100;
+ for (int i = 0; i < accs.size(); i++) {
+ // do one octave
+ if (accs[i].octave != lastoct) {
+ if (octmol){
+ Real dy =lastoct*7*paper()->internote();
+ octmol->translate(Offset(0, dy));
+ output->add(*octmol);
+ delete octmol;
+ }
+ octmol= new Molecule;
+ }
+ lastoct = accs[i].octave;
+ Symbol s =paper()->lookup_p_->accidental(accs[i].acc);
+ Atom a(s);
+ Real dy = (accs[i].name + c0_position) * paper()->internote();
+ a.translate(Offset(0,dy));
+
+ octmol->add_right(a);
+ }
+
+ if (octmol){
+ Real dy =lastoct*7*paper()->internote();
+ octmol->translate(Offset(0, dy));
+ output->add(*octmol);
+ delete octmol;
+ }
+
+ Interval head_width=itemlist_width(support_items_);
+ output->translate(Offset(-output->extent().x.right + head_width.left ,0));
+
+ return output;
+}
+
+int
+Local_acc::compare(Local_acc&a, Local_acc&b)
+{
+ if (a.octave - b.octave)
+ return a.octave - b.octave;
+ if (a.name - b.name)
+ return a.name - b.name;
+
+ assert(false);
+};
--- /dev/null
+/*
+ lookup.cc -- implement simple Lookup methods.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "lookup.hh"
+#include "debug.hh"
+#include "symtable.hh"
+#include "dimen.hh"
+#include "tex.hh"
+#include "scalar.hh"
+
+Lookup::Lookup()
+{
+ texsetting = "\\unknowntexsetting";
+ symtables_ = new Symtables;
+}
+
+Lookup::Lookup(Lookup const &s)
+{
+ texsetting = s.texsetting;
+ symtables_ = new Symtables(*s.symtables_);
+}
+Lookup::~Lookup()
+{
+ delete symtables_;
+}
+
+void
+Lookup::add(String s, Symtable*p)
+{
+ symtables_->add(s, p);
+}
+
+void
+Lookup::print()const
+{
+ mtor << "Lookup: " << texsetting << " {\n";
+ symtables_->print();
+ mtor << "}\n";
+}
+
+Symbol
+Lookup::text(String style, String text, int dir)
+{
+ Array<String> a;
+
+ a.push(text);
+ Symbol tsym = (*symtables_)("style")->lookup(style);
+ a[0] = substitute_args(tsym.tex,a);
+
+ Symbol s = (*symtables_)("align")->lookup(dir);
+ s.tex = substitute_args(s.tex,a);
+ s.dim.y = tsym.dim.y;
+ return s;
+}
+
+
+Real
+Lookup::internote()
+{
+ return ball(4).dim.y.length()/2;
+}
+
+Symbol
+Lookup::ball(int j)
+{
+ if (j > 4)
+ j = 4;
+
+ Symtable * st = (*symtables_)("balls");
+ return st->lookup(String(j));
+}
+
+Symbol
+Lookup::rest(int j)
+{
+ return (*symtables_)("rests")->lookup(String(j));
+}
+
+Symbol
+Lookup::fill(Box b)
+{
+ Symbol s( (*symtables_)("param")->lookup("fill"));
+ s.dim = b;
+ return s;
+}
+
+Symbol
+Lookup::accidental(int j)
+{
+ return (*symtables_)("accidentals")->lookup(String(j));
+}
+
+
+Symbol
+Lookup::bar(String s)
+{
+ return (*symtables_)("bars")->lookup(s);
+}
+
+Symbol
+Lookup::script(String s)
+{
+ return (*symtables_)("scripts")->lookup(s);
+}
+
+Symbol
+Lookup::clef(String s)
+{
+ return (*symtables_)("clefs")->lookup(s);
+}
+
+Symbol
+Lookup::dots(int j)
+{
+ if (j>3)
+ error("max 3 dots"); // todo
+ return (*symtables_)("dots")->lookup(j);
+}
+
+Symbol
+Lookup::flag(int j)
+{
+ return (*symtables_)("flags")->lookup(j);
+}
+
+Symbol
+Lookup::streepjes(int i)
+{
+ assert(i);
+
+ int arg;
+ String idx;
+
+ if (i < 0) {
+ idx = "botlines";
+ arg = -i;
+ } else {
+ arg = i;
+ idx = "toplines";
+ }
+ Symbol ret = (*symtables_)("streepjes")->lookup(idx);
+
+ Array<String> a;
+ a.push(arg);
+ ret.tex = substitute_args(ret.tex, a);
+
+ return ret;
+}
+
+Symbol
+Lookup::hairpin(Real &wid, bool decresc)
+{
+ int idx = int(rint(wid / 6 PT));
+ if(!idx) idx ++;
+ wid = idx*6 PT;
+ String idxstr = (decresc)? "decrescendosym" : "crescendosym";
+ Symbol ret=(*symtables_)("param")->lookup(idxstr);
+
+ Array<String> a;
+ a.push(idx);
+ ret.tex = substitute_args(ret.tex, a);
+ ret.dim.x = Interval(0,wid);
+ return ret;
+}
+
+Symbol
+Lookup::linestaff(int lines, Real wid)
+{
+ Symbol s;
+ s.dim.x = Interval(0,wid);
+ Real dy = (lines >0) ? (lines-1)*internote()*2 : 0;
+ s.dim.y = Interval(0,dy);
+
+ Array<String> a;
+ a.push(lines);
+ a.push(print_dimen(wid));
+
+ s.tex = (*symtables_)("param")->lookup("linestaf").tex;
+ s.tex = substitute_args(s.tex, a);
+
+ return s;
+}
+
+
+Symbol
+Lookup::meter(Array<Scalar> a)
+{
+ Symbol s;
+ s.dim.x = Interval( 0 PT, 10 PT);
+ s.dim.y = Interval(0, 20 PT); // todo
+ String src = (*symtables_)("param")->lookup("meter").tex;
+ s.tex = substitute_args(src,a);
+ return s;
+}
+
+
+Symbol
+Lookup::stem(Real y1,Real y2)
+{
+ if (y1 > y2) {
+ Real t = y1;
+ y1 = y2;
+ y2 = t;
+ }
+ Symbol s;
+
+ s.dim.x = Interval(0,0);
+ s.dim.y = Interval(y1,y2);
+
+ Array<String> a;
+ a.push(print_dimen(y1));
+ a.push(print_dimen(y2));
+
+ String src = (*symtables_)("param")->lookup("stem").tex;
+ s.tex = substitute_args(src,a);
+ return s;
+}
--- /dev/null
+/*
+ meter-reg.cc -- implement Meter_register
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "meter-reg.hh"
+#include "meter.hh"
+#include "commandrequest.hh"
+
+Meter_register::Meter_register()
+
+{
+ post_move_processing();
+}
+
+bool
+Meter_register::try_request(Request*r_l)
+{
+ Command_req* creq_l= r_l->command();
+ if (!creq_l || !creq_l->meterchange())
+ return false;
+
+ assert(!meter_req_l_);
+ meter_req_l_ = r_l->command()->meterchange();
+
+ return true;
+}
+
+void
+Meter_register::process_requests()
+{
+ if (meter_req_l_ ) {
+ Array<Scalar> args;
+ args.push(meter_req_l_->beats_i_);
+ args.push(meter_req_l_->one_beat_i_);
+
+ meter_p_ = new Meter(args);
+ }
+
+ if (meter_p_)
+ announce_element(Staff_elem_info(meter_p_, meter_req_l_) );
+}
+
+void
+Meter_register::pre_move_processing()
+{
+ if (meter_p_) {
+ Meter * post_p =new Meter(*meter_p_);
+ Meter * pre_p =new Meter(*meter_p_);
+
+ typeset_breakable_item(pre_p, meter_p_, post_p);
+ meter_p_ =0;
+ }
+}
+
+void
+Meter_register::post_move_processing()
+{
+ meter_req_l_ = 0;
+ meter_p_ =0;
+}
--- /dev/null
+#include "scalar.hh"
+#include "molecule.hh"
+#include "meter.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+
+Meter::Meter(Array<Scalar>a)
+ :args(a)
+{
+}
+
+Molecule*
+Meter::brew_molecule_p()const
+{
+ Symbol s = paper()->lookup_p_->meter(args);
+ return new Molecule(Atom(s));
+}
+
--- /dev/null
+/*
+ midi-walker.cc -- implement Midi_walker
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>, Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+#include "musicalrequest.hh"
+#include "pscore.hh"
+#include "staff.hh"
+#include "midi-walker.hh"
+#include "midi-item.hh"
+#include "midi-stream.hh"
+#include "debug.hh"
+#include "staff-column.hh"
+
+Midi_walker::Midi_walker(Staff *st_l, Midi_track* track_l)
+ : PCursor<Staff_column*>(st_l->cols_)
+{
+ track_l_ = track_l;
+ last_moment_= 0;
+}
+
+/**
+ output notestop events for all notes which end before #max_moment#
+ */
+void
+Midi_walker::do_stop_notes(Moment max_moment)
+{
+ while (stop_notes.size() && stop_notes.front_idx() <= max_moment) {
+ Moment stop_moment = stop_notes.front_idx();
+ Melodic_req * req_l = stop_notes.get();
+
+ Midi_note note(req_l, track_l_->number_i_, false);
+ output_event(note, stop_moment);
+ }
+}
+/** advance the track to #now#, output the item, and adjust current
+ "moment". */
+void
+Midi_walker::output_event(Midi_item &i, Moment now)
+{
+ Moment delta_t = now - last_moment_ ;
+ last_moment_ += delta_t;
+ track_l_->add(delta_t, &i );
+}
+
+void
+Midi_walker::process_requests()
+{
+ do_stop_notes(ptr()->when());
+ for ( int i = 0; i < ptr()->musicalreq_l_arr_.size(); i++ ) {
+
+ Rhythmic_req *n = ptr()->musicalreq_l_arr_[i]->rhythmic();
+ if ( !n)
+ continue;
+ Note_req * note_l = n->note();
+ if (!note_l)
+ continue;
+
+ Midi_note note(note_l, track_l_->number_i_, true);
+ stop_notes.enter(note_l, n->duration() + ptr()->when() );
+ output_event(note, ptr()->when());
+ }
+}
+
+Midi_walker::~Midi_walker()
+{
+ do_stop_notes( last_moment_ + Moment(10,1)); // ugh
+}
--- /dev/null
+#include <math.h>
+
+#include "item.hh"
+#include "misc.hh"
+#include "glob.hh"
+#include "moment.hh"
+
+
+// depreciated, see struct Duration*
+Moment
+wholes(int dur, int dots)
+{
+ if (!dur)
+ return 0;
+
+ Moment f = Rational(1)/Moment(dur);
+ Moment delta = f;
+
+ while (dots--) {
+ delta /= 2.0;
+ f += delta;
+ }
+ return f;
+}
+int
+intlog2(int d) {
+ int i=0;
+ while (!(d&1)) {
+ d/= 2;
+ i++;
+ }
+ assert(!(d/2));
+ return i;
+}
+
+double
+log_2(double x) {
+ return log(x) /log(2.0);
+}
+
+Interval
+itemlist_width(const Array<Item*> &its)
+{
+ Interval iv ;
+ iv.set_empty();
+
+ for (int j =0; j < its.size(); j++){
+ iv.unite (its[j]->width());
+
+ }
+ return iv;
+}
+
--- /dev/null
+#include "varray.hh"
+#include "interval.hh"
+#include "dimen.hh"
+#include "string.hh"
+#include "molecule.hh"
+#include "symbol.hh"
+#include "debug.hh"
+#include "tex.hh"
+
+void
+Atom::print() const
+{
+ mtor << "texstring: " <<sym.tex<<"\n";
+}
+
+Box
+Atom::extent() const
+{
+ Box b( sym.dim);
+ b.translate(off);
+ return b;
+}
+
+Atom::Atom(Symbol s)
+{
+ sym=s;
+}
+
+
+String
+Atom::TeXstring() const
+{
+ // whugh.. Hard coded...
+ String s("\\placebox{%}{%}{%}");
+ Array<String> a;
+ a.push(print_dimen(off.y));
+ a.push(print_dimen(off.x));
+ a.push(sym.tex);
+ return substitute_args(s, a);
+}
+
+/* *************** */
+
+String
+Molecule::TeXstring() const
+{
+ String s;
+ for(iter_top(ats,c); c.ok(); c++)
+ s+=c->TeXstring();
+ return s;
+}
+
+Box
+Molecule::extent() const
+{
+ Box b;
+ for(iter_top(ats,c); c.ok(); c++)
+ b.unite(c->extent());
+ return b;
+}
+
+void
+Molecule::translate(Offset o)
+{
+ for (iter_top(ats,c); c.ok(); c++)
+ c->translate(o);
+}
+
+void
+Molecule::add(const Molecule &m)
+{
+ for (iter_top(m.ats,c); c.ok(); c++) {
+ add(**c);
+ }
+}
+
+void
+Molecule::add_right(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real xof=extent().x.right - m.extent().x.left;
+ Molecule toadd(m);
+ toadd.translate(Offset(xof, 0.0));
+ add(toadd);
+}
+
+void
+Molecule::add_left(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real xof=extent().x.left - m.extent().x.right;
+ Molecule toadd(m);
+ toadd.translate(Offset(xof, 0.0));
+ add(toadd);
+}
+
+
+void
+Molecule::add_top(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real yof=extent().y.right - m.extent().y.left;
+ Molecule toadd(m);
+ toadd.translate(Offset(0,yof));
+ add(toadd);
+}
+
+void
+Molecule::add_bottom(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real yof=extent().y.left- m.extent().y.right;
+ Molecule toadd(m);
+ toadd.translate(Offset(0,yof));
+ add(toadd);
+}
+
+void
+Molecule::operator = (const Molecule&)
+{
+ assert(false);
+}
+
+Molecule::Molecule(const Molecule&s)
+{
+ add(s);
+}
+
+void
+Molecule::print() const
+{
+ for (iter_top(ats,c); c.ok(); c++)
+ c->print();
+}
--- /dev/null
+#include <strstream.h>
+
+#include "interval.hh"
+#include "identparent.hh"
+#include "assoc-iter.hh"
+#include "lexer.hh"
+#include "input-file.hh"
+#include "parser.hh"
+#include "keyword.hh"
+#include "assoc.hh"
+#include "lexer.hh"
+#include "debug.hh"
+#include "notename.hh"
+#include "source-file.hh"
+#include "parseconstruct.hh"
+
+static Keyword_ent the_key_tab[]={
+ "bar", BAR,
+ "cadenza", CADENZA,
+ "clef", CLEF,
+ "cm", CM_T,
+ "command", COMMAND,
+ "commands", COMMANDS,
+ "duration", DURATIONCOMMAND,
+ "geometric", GEOMETRIC,
+ "goto", GOTO,
+ "in", IN_T,
+ "key", KEY,
+ "meter", METER,
+ "midi", MIDI,
+ "mm", MM_T,
+ "multivoice", MULTIVOICE,
+ "octave", OCTAVECOMMAND,
+ "output", OUTPUT,
+ "partial", PARTIAL,
+ "paper", PAPER,
+ "plet", PLET,
+ "pt", PT_T,
+ "score", SCORE,
+ "script", SCRIPT,
+ "skip", SKIP,
+ "staff", STAFF,
+ "start", START_T,
+ "stem", STEM,
+ "table", TABLE,
+ "symboltables", SYMBOLTABLES,
+ "notenames", NOTENAMES,
+ "tempo", TEMPO,
+ "texid", TEXID,
+ "textstyle", TEXTSTYLE,
+ "unitspace", UNITSPACE,
+ "voice", VOICE,
+ "voices", VOICES,
+ "width", WIDTH,
+ "music", MUSIC,
+ "grouping", GROUPING,
+ 0,0
+};
+
+int
+My_flex_lexer::ret_notename(int *p, String text, int octave_mod)
+{
+ text = text.lower_str();
+ char const* ch_c_l = here_ch_c_l();
+ if ( ch_c_l ) {
+ ch_c_l--;
+ while ( ( *ch_c_l == ' ' )
+ || ( *ch_c_l == '\t' ) || ( *ch_c_l == '\n' ) )
+ ch_c_l--;
+ ch_c_l++;
+ }
+
+ lookup_notename(p[0], p[1], text);
+ p[2] = octave_mod;
+ mtor << "notename: "<< text <<eol;
+ if (p[0] < 0) {
+
+ errorlevel_i_ |= 1;
+ error( String( "notename does not exist: " ) + YYText(), ch_c_l );
+ p[0] = p[1] = 0;
+ }
+ return NOTENAME;
+}
+
+My_flex_lexer::My_flex_lexer()
+{
+ keytable = new Keyword_table(the_key_tab);
+ the_id_tab = new Assoc<String, Identifier*>;
+ defaulttab = 0;
+ errorlevel_i_ = 0;
+}
+
+int
+My_flex_lexer::lookup_keyword(String s)
+{
+ return keytable->lookup(s);
+}
+
+Identifier*
+My_flex_lexer::lookup_identifier(String s)
+{
+ if (!the_id_tab->elt_query(s))
+ return 0;
+
+ return (*the_id_tab)[s];
+}
+
+char const*
+My_flex_lexer::here_ch_c_l()
+{
+ return include_stack.top()->sourcefile_l_->ch_c_l() + yyin->tellg();
+}
+
+void
+My_flex_lexer::add_identifier(Identifier*i)
+{
+ delete lookup_identifier(i->name);
+ (*the_id_tab)[i->name] = i;
+}
+
+My_flex_lexer::~My_flex_lexer()
+{
+ delete keytable;
+ delete defaulttab;
+ for (Assoc_iter<String,Identifier*> ai(*the_id_tab); ai.ok(); ai++) {
+ mtor << "deleting: " << ai.key()<<'\n';
+ delete ai.val();
+ }
+ delete the_id_tab;
+}
+void
+My_flex_lexer::print_declarations()const
+{
+ for (Assoc_iter<String,Identifier*> ai(*the_id_tab); ai.ok(); ai++) {
+ ai.val()->print();
+ }
+}
+
+String
+My_flex_lexer::spot()const
+{
+ return include_stack.top()->name + ": " + String( lineno() );
+}
+
+void
+My_flex_lexer::LexerError(const char *s)
+{
+ if (lexer->include_stack.empty()) {
+ *mlog << "error at EOF" << s << '\n';
+ } else {
+ char const* ch_c_l = here_ch_c_l();
+ if ( ch_c_l ) {
+ ch_c_l--;
+ while ( ( *ch_c_l == ' ' ) || ( *ch_c_l == '\t' ) || ( *ch_c_l == '\n' ) )
+ ch_c_l--;
+ ch_c_l++;
+ }
+ errorlevel_i_ |= 1;
+ error( s, ch_c_l );
+ }
+}
+
+// set the new input to s, remember old file.
+void
+My_flex_lexer::new_input(String s)
+{
+ if (!include_stack.empty()) {
+ include_stack.top()->line = lineno();
+ // should this be saved at all?
+ include_stack.top()->defined_ch_c_l_ = defined_ch_c_l;
+ }
+
+ Input_file *newin = new Input_file(s);
+ include_stack.push(newin);
+ switch_streams(newin->is);
+
+ yylineno = 1;
+}
+
+// pop the inputstack.
+bool
+My_flex_lexer::close_input()
+{
+ Input_file *old = include_stack.pop();
+ bool ok = true;
+ if (include_stack.empty()) {
+ ok = false;
+ } else {
+ Input_file *i = include_stack.top();
+ switch_streams(i->is);
+ yylineno = i->line;
+ defined_ch_c_l = i->defined_ch_c_l_;
+ }
+ delete old;
+ return ok;
+}
--- /dev/null
+/*
+ could use cleanup
+ */
+#include <ctype.h>
+#include "lexer.hh"
+#include "string.hh"
+#include "real.hh"
+#include "debug.hh"
+#include "musicalrequest.hh"
+#include "commandrequest.hh"
+#include "voice.hh"
+#include "notename.hh"
+#include "identparent.hh"
+#include "varray.hh"
+#include "text-def.hh"
+#include "parseconstruct.hh"
+#include "input-music.hh"
+#include "voice-element.hh"
+
+int default_duration = 4, default_dots=0, default_octave=0;
+int default_plet_type = 1, default_plet_dur = 1;
+String textstyle="roman"; // in lexer?
+
+bool last_duration_mode = false;
+
+void
+set_duration_mode(String s)
+{
+ s = s.upper_str();
+ last_duration_mode = (s== "LAST");
+}
+
+void
+last_duration(int n)
+{
+ if (last_duration_mode)
+ default_duration = n;
+}
+
+/* triplet is '2/3' */
+void
+set_plet(int num,int den)
+{
+ assert(num >0&& den>0);
+ default_plet_dur = num;
+ default_plet_type = den;
+}
+
+Text_def*
+get_text(String s) return t;
+{
+ t= new Text_def;
+ t->text_str_= s;
+ t->style_str_ = textstyle;
+ t->defined_ch_c_l_ = defined_ch_c_l;
+ return t;
+}
+
+void
+set_text_style(String s)
+{
+ textstyle = s;
+}
+
+void
+parse_octave (const char *a, int &j, int &oct)
+{
+ while (1)
+ {
+ if (a[j] == '\'')
+ oct ++;
+ else if (a[j] == '`')
+ oct --;
+ else
+ break;
+ j++;
+ }
+}
+
+void
+parse_pitch( const char *a, Melodic_req* mel_l)
+{
+ int j=0;
+
+ // octave
+ mel_l->octave_i_ = default_octave;
+ parse_octave(a,j,mel_l->octave_i_);
+
+ // accidental
+ mel_l->forceacc_b_ = false;
+
+ if (a[j] == '!'){
+ mel_l->forceacc_b_ = true;
+ j++;
+ }
+}
+
+Voice_element *
+get_note_element(String pitch, int * notename, int * duration )
+{
+ Voice_element*v = new Voice_element;
+ v->defined_ch_c_l_ = defined_ch_c_l;
+
+
+ int dur = duration[0];
+ int dots = duration[1];
+
+ if (dur >= 2) {
+ Stem_req * stem_req_p = new Stem_req(dur,dots);
+ stem_req_p->plet_factor = Moment(default_plet_dur, default_plet_type);
+ stem_req_p->defined_ch_c_l_ = defined_ch_c_l;
+ v->add(stem_req_p);
+ }
+
+ if ( !defined_ch_c_l )
+ defined_ch_c_l = lexer->here_ch_c_l();
+
+ Note_req * rq = new Note_req;
+ rq->notename_i_ =notename[0];
+ rq->accidental_i_ = notename[1];
+ parse_pitch(pitch, rq);
+ rq->octave_i_ += notename[2];
+
+ rq->balltype = dur;
+ rq->dots = dots;
+ rq->plet_factor = Moment(default_plet_dur, default_plet_type);
+ rq->defined_ch_c_l_ = defined_ch_c_l;
+
+ v->add(rq);
+
+ return v;
+}
+
+Voice_element*
+get_word_element(Text_def* tdef_p, int* duration)
+{
+ Voice_element* velt_p = new Voice_element;
+ velt_p->defined_ch_c_l_ = defined_ch_c_l;
+
+ int dur = duration[0];
+ int dots=duration[1];
+
+ tdef_p->defined_ch_c_l_ = defined_ch_c_l;
+
+ Lyric_req* lreq_p = new Lyric_req(tdef_p);
+
+ lreq_p->balltype = dur;
+ lreq_p->dots = dots;
+ lreq_p->plet_factor = Moment(default_plet_dur, default_plet_type);
+ lreq_p->print();
+ lreq_p->defined_ch_c_l_ = defined_ch_c_l;
+
+ velt_p->add(lreq_p);
+
+ return velt_p;
+}
+
+Voice_element *
+get_rest_element(String, int * duration )
+{
+ Voice_element* velt_p = new Voice_element;
+ velt_p->defined_ch_c_l_ = defined_ch_c_l;
+
+ Rest_req * rest_req_p = new Rest_req;
+ rest_req_p->plet_factor = Moment(default_plet_dur, default_plet_type);
+ rest_req_p->balltype = duration[0];
+ rest_req_p->dots = duration[1];
+ rest_req_p->print();
+ rest_req_p->defined_ch_c_l_ = defined_ch_c_l;
+
+ velt_p->add(rest_req_p);
+
+ return velt_p;
+}
+
+void
+get_default_duration(int *p)
+{
+ *p++ = default_duration;
+ *p = default_dots;
+}
+
+void
+set_default_duration(int *p)
+{
+ default_duration = *p++;
+ default_dots = *p++;
+}
+
+
+void
+set_default_octave(String d)
+{
+ int i=0;
+ default_octave=0;
+ parse_octave(d, i, default_octave);
+}
+
+Request*
+get_plet_request( char c, int dur_i, int type_i )
+{
+ Plet_req* plet_req_p = new Plet_req;
+ plet_req_p->dur_i_ = dur_i;
+ plet_req_p->type_i_ = type_i;
+ plet_req_p->type_c_ = c;
+ return plet_req_p;
+}
+
+Request*
+get_request(char c)
+{
+ Request* req_p=0;
+ switch (c) {
+ case '|':
+ req_p = new Barcheck_req;
+ break;
+
+ case '[':
+ case ']':
+ {
+ Beam_req*b = new Beam_req;
+ if (default_plet_type != 1)
+ b->nplet = default_plet_type;
+ req_p = b;
+ }
+ break;
+
+
+ case ')':
+ case '(':
+ req_p = new Slur_req;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ switch (c) {
+ case '(':
+ case '[':
+ req_p->span()->spantype = Span_req::START;
+ break;
+ case ')':
+ case ']':
+ req_p->span()->spantype = Span_req::STOP;
+ break;
+
+ default:
+ break;
+ }
+
+ req_p->defined_ch_c_l_ = req_defined_ch_c_l;
+ return req_p;
+}
+
+void
+add_requests(Voice_element *v, Array<Request*> &req)
+{
+ for (int i = 0; i < req.size(); i++) {
+ v->add(req[i]);
+ }
+ req.set_size(0);
+}
+
+Script_def*
+get_scriptdef(char c)
+{
+ String s;
+ switch (c) {
+ case '^' : s = "marcato";
+ break;
+ case '+' : s = "stopped";
+ break;
+ case '-' : s = "tenuto";
+ break;
+ case '|': s = "staccatissimo";
+ break;
+ case 'o' : s = "";
+ break;
+ case '>' : s = "accent";
+ break;
+ case 'v' : s = "";
+ break;
+ case '.' : s = "staccato";
+ break;
+ }
+ return lexer->lookup_identifier(s)->script(1);
+}
+
+Request*
+get_script_req(int d , Script_def*def)
+{
+ Script_req* script_req_p = new Script_req(d, def);
+ return script_req_p;
+}
+
+Request*
+get_text_req(int d , Text_def*def)
+{
+ Text_req* text_req_p = new Text_req(d, def);
+ return text_req_p;
+}
+
+Request*
+get_stemdir_req(int d)
+{
+ Group_feature_req * gfreq_p = new Group_feature_req;
+ gfreq_p->stemdir_i_ =d;
+ return gfreq_p;
+}
+
+Request*
+get_grouping_req(Array<int> i_arr)
+{
+ Measure_grouping_req * mr_p = new Measure_grouping_req;
+ for (int i=0; i <i_arr.size(); ) {
+ mr_p->beat_i_arr_.push(i_arr[i++]);
+ mr_p->elt_length_arr_.push(Moment(1, i_arr[i++]));
+ }
+ return mr_p;
+}
--- /dev/null
+#include "misc.hh"
+#include "notehead.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "musicalrequest.hh"
+
+
+
+Notehead::Notehead(int ss)
+{
+ x_dir = 0;
+ staff_size=ss;
+ position = 0;
+ balltype = 0;
+ dots = 0;
+ extremal = 0;
+}
+
+void
+Notehead::set_rhythmic(Rhythmic_req*r_req_l)
+{
+ balltype = r_req_l->balltype;
+ dots = r_req_l->dots;
+}
+
+void
+Notehead::do_print()const
+{
+#ifndef NPRINT
+ mtor << "balltype "<< balltype << ", position = "<< position
+ << "dots " << dots;
+#endif
+}
+
+
+int
+Notehead::compare(Notehead *const &a, Notehead * const &b)
+{
+ return a->position - b->position;
+}
+
+Molecule*
+Notehead::brew_molecule_p() const return out;
+{
+ Paper_def *p = paper();
+
+ Real dy = p->internote();
+ Symbol s = p->lookup_p_->ball(balltype);
+
+ out = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d = p->lookup_p_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ if (!(position %2))
+ dm.translate(Offset(0,dy));
+ out->add_right(dm);
+ }
+ out->translate(Offset(x_dir * p->note_width(),0));
+ bool streepjes = (position<-1)||(position > staff_size+1);
+ if (streepjes) {
+ int dir = sign(position);
+ int s =(position<-1) ? -((-position)/2): (position-staff_size)/2;
+ Symbol str = p->lookup_p_->streepjes(s);
+ Molecule sm;
+ sm.add(Atom(str));
+ if (position % 2)
+ sm.translate(Offset(0,-dy* dir));
+ out->add(sm);
+ }
+
+ out->translate(Offset(0,dy*position));
+}
+
--- /dev/null
+#include "glob.hh"
+#include "string.hh"
+#include "notename.hh"
+#include "lexer.hh"
+#include "identifier.hh"
+
+
+
+void
+Notename_tab::lookup(int &large, int &small, String s)
+{
+ large = -1;
+ small = 0;
+
+ for (int i =0; i < 7*5; i++)
+ if (s == notetab[i])
+ {
+ large = i /5;
+ small = i %5 - 2;
+ return;
+ }
+}
+
+
+void
+Notename_tab::set(int l, int s, String n)
+{
+ assert(l < 8 && s <= 2 && s >= -2 && l >=0);
+ notetab[l * 5 + s +2] = n;
+}
+/* *************** */
+void
+My_flex_lexer::set(Notename_tab *n)
+{
+ delete defaulttab;
+ defaulttab = n;
+}
+
+void
+My_flex_lexer::lookup_notename(int &large, int &small, String s)
+{
+ if (!defaulttab)
+ set(lookup_identifier("default_table")->
+ notename_tab(true));
+
+ defaulttab->lookup(large, small, s);
+}
--- /dev/null
+#include <math.h>
+#include "misc.hh"
+#include "paper-def.hh"
+#include "debug.hh"
+#include "lookup.hh"
+#include "dimen.hh"
+
+
+
+// golden ratio
+const Real PHI = (1+sqrt(5))/2;
+
+// see Roelofs, p. 57
+Real
+Paper_def::duration_to_dist(Moment d)
+{
+ if (!d)
+ return 0;
+
+ return whole_width * pow(geometric_, log_2(d));
+}
+
+Real
+Paper_def::rule_thickness()const
+{
+ return 0.4 PT;
+}
+
+Paper_def::Paper_def(Lookup *l)
+{
+ lookup_p_ = l;
+ linewidth = 15 *CM_TO_PT; // in cm for now
+ whole_width = 8 * note_width();
+ geometric_ = sqrt(2);
+ outfile = "lelie.out";
+}
+
+Paper_def::~Paper_def()
+{
+ delete lookup_p_;
+}
+Paper_def::Paper_def(Paper_def const&s)
+{
+ lookup_p_ = new Lookup(*s.lookup_p_);
+ geometric_ = s.geometric_;
+ whole_width = s.whole_width;
+ outfile = s.outfile;
+ linewidth = s.linewidth;
+}
+
+void
+Paper_def::set(Lookup*l)
+{
+ assert(l != lookup_p_);
+ delete lookup_p_;
+ lookup_p_ = l;
+}
+
+Real
+Paper_def::interline() const
+{
+ return lookup_p_->ball(4).dim.y.length();
+}
+
+Real
+Paper_def::internote() const
+{
+ return lookup_p_->internote();
+}
+Real
+Paper_def::note_width()const
+{
+ return lookup_p_->ball(4).dim.x.length( );
+}
+Real
+Paper_def::standard_height() const
+{
+ return 20 PT;
+}
+
+void
+Paper_def::print() const
+{
+#ifndef NPRINT
+ mtor << "Paper {width: " << print_dimen(linewidth);
+ mtor << "whole: " << print_dimen(whole_width);
+ mtor << "out: " <<outfile;
+ lookup_p_->print();
+ mtor << "}\n";
+#endif
+}
--- /dev/null
+#include "pcol.hh"
+#include "pscore.hh"
+#include "pstaff.hh"
+#include "debug.hh"
+
+Interval
+PCol::width() const
+{
+ Interval w;
+
+ for (iter_top(its,i); i.ok(); i++)
+ w.unite(i->width());
+ if (w.empty())
+ w.unite(Interval(0,0));
+ return w;
+}
+
+int
+PCol::rank() const
+{
+ if(!pscore_l_)
+ return -1;
+ PCursor<PCol*> me=pscore_l_->find_col( (PCol*)this);
+ if (!me.ok())
+ return -1;
+ PCursor<PCol*> bot(pscore_l_->cols.top());
+ return me - bot;
+}
+
+void
+PCol::print() const
+{
+#ifndef NPRINT
+ mtor << "PCol {";
+
+ if (rank() >= 0)
+ mtor << "rank: " << rank() << '\n';
+
+ mtor << "# symbols: " << its.size() ;
+ if (breakable_b()){
+ mtor << "\npre,post: ";
+ prebreak_p_->print();
+ postbreak_p_->print();
+ } else if (daddy_l_) {
+ mtor<<'\n' << ((this == daddy_l_->prebreak_p_) ?
+ "prebreak" : "postbreak");
+ mtor << '\n';
+ }
+ mtor << "extent: " << width().str() << "\n";
+ mtor << "}\n";
+#endif
+}
+
+int
+PCol::compare(const PCol &c1, const PCol &c2)
+{
+ PScore*ps_l = c1.pscore_l_;
+ PCursor<PCol*> ac(ps_l->find_col(&c1));
+ PCursor<PCol*> bc(ps_l->find_col(&c2));
+ assert(ac.ok() && bc.ok());
+ return ac - bc;
+}
+
+void
+PCol::OK() const
+{
+#ifndef NDEBUG
+ if (prebreak_p_ || postbreak_p_ ) {
+ assert(prebreak_p_&&postbreak_p_);
+ assert(prebreak_p_->daddy_l_ == this);
+ assert(postbreak_p_->daddy_l_ == this);
+ }
+#endif
+}
+
+void
+PCol::set_breakable()
+{
+ if (breakable_b())
+ return;
+
+ prebreak_p_ = new PCol(this);
+ postbreak_p_ = new PCol(this);
+ prebreak_p_->pscore_l_ = pscore_l_;
+ postbreak_p_->pscore_l_ = pscore_l_;
+}
+
+bool
+PCol::breakable_b() const
+{
+ return prebreak_p_||postbreak_p_;
+}
+
+PCol::PCol(PCol *parent)
+{
+ daddy_l_ = parent;
+ prebreak_p_=0;
+ postbreak_p_=0;
+ line_l_=0;
+ hpos = -1.0;
+ pscore_l_ = 0;
+}
+
+PCol::~PCol()
+{
+ delete prebreak_p_;
+ delete postbreak_p_;
+}
+
+void
+PCol::add( Item *i)
+{
+ its.bottom().add(i);
+ i->pcol_l_ = this;
+}
+
+bool
+PCol::used_b()const
+{
+ return breakable_b() || its.size();
+}
--- /dev/null
+#include "idealspacing.hh"
+#include "debug.hh"
+#include "lookup.hh"
+#include "spanner.hh"
+#include "paper-def.hh"
+#include "molecule.hh"
+#include "dimen.hh"
+#include "scoreline.hh"
+#include "pscore.hh"
+#include "tex-stream.hh"
+#include "item.hh"
+#include "break.hh"
+
+Idealspacing*
+PScore::get_spacing(PCol*l, PCol*r)
+{
+ assert(l!=r);
+
+ Idealspacing*i_p =new Idealspacing(l,r);
+ suz.bottom().add(i_p);
+
+ return i_p;
+}
+
+
+void
+PScore::clean_cols()
+{
+ for (iter_top(cols,c); c.ok(); )
+ if (!c->used_b()) {
+ delete c.remove_p();
+ } else
+ c++;
+}
+
+
+void
+PScore::add(PStaff *s)
+{
+ assert(s->pscore_l_ == this);
+ staffs.bottom().add(s);
+}
+
+
+void
+PScore::do_connect(PCol *c1, PCol *c2, Real d, Real h)
+{
+ if (!c1 || !c2 )
+ return;
+ Idealspacing*s_l=get_spacing(c1,c2);
+
+
+ s_l->hooke = h;
+ s_l->space =d;
+}
+
+void
+PScore::connect(PCol* c1, PCol *c2, Real d, Real h)
+{
+ do_connect(c1,c2,d,h);
+ do_connect(c1->postbreak_p_, c2,d,h);
+ do_connect(c1, c2->prebreak_p_,d,h);
+ do_connect(c1->postbreak_p_, c2->prebreak_p_,d,h);
+}
+
+void
+PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat)
+{
+ assert(c && i && s);
+
+ if (breakstat == 0) {
+ typeset_item(i, c->prebreak_p_, s);
+ return;
+ }
+
+ if (breakstat == 2) {
+ typeset_item(i, c->postbreak_p_, s);
+ return;
+ }
+
+
+ its.bottom().add(i);
+ s->add(i);
+ c->add(i);
+
+ /* first do this, because i->width() may follow the 0-pointer */
+ i->add_processing();
+}
+
+void
+PScore::typeset_spanner(Spanner*span_p, PStaff*ps)
+{
+ span_p->pstaff_l_ = ps;
+ spanners.bottom().add(span_p);
+ ps->spans.bottom().add(span_p);
+
+ // do not init start/stop fields. These are for broken spans only.
+ span_p->add_processing();
+}
+
+
+void
+PScore::add(PCol *p)
+{
+ p->pscore_l_ = this;
+ if (p->breakable_b()){
+ p->prebreak_p_->pscore_l_ = this;
+ p->postbreak_p_->pscore_l_ = this;
+ }
+ cols.bottom().add(p);
+}
+
+PScore::PScore( Paper_def*p)
+{
+ paper_l_ = p;
+}
+
+void
+PScore::output(Tex_stream &ts)
+{
+ int l=1;
+
+ ts << "\n "<< paper_l_->lookup_p_->texsetting << "%(Tex id)\n";
+ for (iter_top(lines,lic); lic.ok(); lic++) {
+ ts << "% line of score no. " << l++ <<"\n";
+ ts << lic->TeXstring();
+ if ((lic+1).ok())
+ ts << "\\interscoreline\n";
+ }
+}
+
+
+Array<Item*>
+PScore::select_items(PStaff*ps, PCol*pc)
+{
+ Array<Item*> ret;
+ assert(ps && pc);
+ for (iter_top(pc->its,i); i.ok(); i++){
+ if (i->pstaff_l_ == ps)
+ ret.push((Item*)(const Item*)i);
+ }
+ return ret;
+}
+
+void
+PScore::OK()const
+{
+#ifdef NDEBUG
+ for (iter_top(cols,cc); cc.ok(); cc++)
+ cc->OK();
+ for (iter_top(suz,i); i.ok(); i++)
+ i->OK();
+#endif
+}
+
+void
+PScore::print() const
+{
+#ifndef NPRINT
+ mtor << "PScore { ";
+ paper_l_->print();
+ mtor << "\ncolumns: ";
+ for (iter_top(cols,cc); cc.ok(); cc++)
+ cc->print();
+
+ mtor << "\nideals: ";
+ for (iter_top(suz,i); i.ok(); i++)
+ i->print();
+ mtor << "}\n";
+#endif
+}
+
+void
+PScore::preprocess()
+{
+ for (iter_top(spanners,i); i.ok(); i++) {
+ i->pre_processing();
+ }
+ for (iter_top(its,i); i.ok(); i++){
+ i->pre_processing();
+ }
+}
+
+void
+PScore::postprocess()
+{
+ for (iter_top(broken_spans,i); i.ok(); i++) { // could chase spans as well.
+ i->post_processing();
+ }
+ for (iter_top(its,i); i.ok(); i++){
+ i->post_processing();
+ }
+
+ for (iter_top(broken_spans,i); i.ok(); i++) {
+ i->molecule_processing();
+ }
+ for (iter_top(its,i); i.ok(); i++){
+ i->molecule_processing();
+ }
+
+ for (iter_top(lines,i); i.ok(); i++)
+ i->process();
+
+}
+
+PCursor<PCol *>
+PScore::find_col(const PCol *c)const
+{
+ const PCol*what = c;
+ if (what->daddy_l_ )
+ what = what->daddy_l_;
+
+ return cols.find((PCol*)what);
+}
+
+void
+PScore::add_broken(Spanner*s)
+{
+ assert(s->left->line_l_ == s->right->line_l_);
+ broken_spans.bottom().add(s);
+ s->left->starters.bottom().add (s);
+ s->right->stoppers.bottom().add (s);
+}
+
+void
+PScore::set_breaking(Array<Col_hpositions> breaking)
+{
+ for (int j=0; j < breaking.size(); j++) {
+ Array<PCol*> &curline(breaking[j].cols);
+ Array<Real> &config(breaking[j].config);
+
+ Line_of_score *s_p = new Line_of_score(curline,this);
+ lines.bottom().add(s_p);
+ for (int i=0; i < curline.size(); i++){
+ curline[i]->hpos = config[i];
+ }
+ }
+}
+
+void
+PScore::calc_breaking()
+{
+ Word_wrap w(*this);
+ set_breaking(w.solve());
+}
+
+void
+PScore::process()
+{
+ clean_cols();
+ *mlog << "Preprocessing ... " <<flush;
+ preprocess();
+ *mlog << "\nCalculating column positions ... " <<flush;
+ calc_breaking();
+ *mlog << "\nPostprocessing ..." << endl;
+ postprocess();
+}
--- /dev/null
+#include "pstaff.hh"
+#include "molecule.hh"
+
+PStaff::PStaff(PScore*ps)
+{
+ pscore_l_=ps;
+}
+
+void
+PStaff::add(Item *i)
+{
+ its.bottom().add(i);
+ i->pstaff_l_ = this;
+}
--- /dev/null
+#include "debug.hh"
+#include "const.hh"
+#include "qlp.hh"
+#include "choleski.hh"
+
+void
+Mixed_qp::add_equality_cons(Vector , double )
+{
+ assert(false);
+}
+
+void
+Mixed_qp::add_fixed_var(int i, Real r)
+{
+ eq_cons.push(i);
+ eq_consrhs.push(r);
+}
+
+void
+Ineq_constrained_qp::add_inequality_cons(Vector c, double r)
+{
+ cons.push(c);
+ consrhs.push(r);
+}
+
+Ineq_constrained_qp::Ineq_constrained_qp(int novars):
+ quad(novars),
+ lin(novars),
+ const_term (0.0)
+{
+}
+
+void
+Ineq_constrained_qp::OK() const
+{
+#ifndef NDEBUG
+ assert(cons.size() == consrhs.size());
+ Matrix Qdif= quad - quad.transposed();
+ assert(Qdif.norm()/quad.norm() < EPS);
+#endif
+}
+
+
+Real
+Ineq_constrained_qp::eval (Vector v)
+{
+ return v * quad * v + lin * v + const_term;
+}
+
+/**
+ eliminate appropriate variables, until we have a Ineq_constrained_qp
+ then solve that.
+
+ PRE
+ cons should be ascending
+ */
+Vector
+Mixed_qp::solve(Vector start) const
+{
+ print();
+ Ineq_constrained_qp pure(*this);
+
+ for (int i= eq_cons.size()-1; i>=0; i--) {
+ pure.eliminate_var(eq_cons[i], eq_consrhs[i]);
+ start.del(eq_cons[i]);
+ }
+ Vector sol = pure.solve(start);
+ for (int i= 0; i < eq_cons.size(); i++) {
+ sol.insert( eq_consrhs[i],eq_cons[i]);
+ }
+ return sol;
+}
+
+/*
+ assume x(idx) == value, and adjust constraints, lin and quad accordingly
+
+ TODO: add const_term
+ */
+void
+Ineq_constrained_qp::eliminate_var(int idx, Real value)
+{
+ Vector row(quad.row(idx));
+ row*= value;
+
+ quad.delete_row(idx);
+
+ quad.delete_column(idx);
+
+ lin.del(idx);
+ row.del(idx);
+ lin +=row ;
+
+ for (int i=0; i < cons.size(); i++) {
+ consrhs[i] -= cons[i](idx) *value;
+ cons[i].del(idx);
+ }
+}
+
+
+
+void
+Ineq_constrained_qp::assert_solution(Vector sol) const
+{
+ Array<int> binding;
+ for (int i=0; i < cons.size(); i++) {
+ Real R=cons[i] * sol- consrhs[i];
+ assert(R> -EPS);
+ if (R < EPS)
+ binding.push(i);
+ }
+ // KKT check...
+ // todo
+}
+
+void
+Ineq_constrained_qp::print() const
+{
+#ifndef NPRINT
+ mtor << "Quad " << quad;
+ mtor << "lin " << lin <<"\n"
+ << "const " << const_term<<"\n";
+ for (int i=0; i < cons.size(); i++) {
+ mtor << "constraint["<<i<<"]: " << cons[i] << " >= " << consrhs[i];
+ mtor << "\n";
+ }
+#endif
+}
+
+/* *************** */
+
+Mixed_qp::Mixed_qp(int n)
+ : Ineq_constrained_qp(n)
+{
+}
+
+void
+Mixed_qp::OK() const
+{
+#ifndef NDEBUG
+ Ineq_constrained_qp::OK();
+ assert(eq_consrhs.size() == eq_cons.size());
+#endif
+}
+
+void
+Mixed_qp::print() const
+{
+#ifndef NPRINT
+ Ineq_constrained_qp::print();
+ for (int i=0; i < eq_cons.size(); i++) {
+ mtor << "eq cons "<<i<<": x["<<eq_cons[i]<<"] == " << eq_consrhs[i]<<"\n";
+ }
+#endif
+}
+
--- /dev/null
+#include "qlpsolve.hh"
+#include "const.hh"
+#include "debug.hh"
+#include "choleski.hh"
+
+const Real TOL=1e-2; // roughly 1/10 mm
+
+String
+Active_constraints::status() const
+{
+ String s("Active|Inactive [");
+ for (int i=0; i< active.size(); i++) {
+ s += String(active[i]) + " ";
+ }
+
+ s+="| ";
+ for (int i=0; i< inactive.size(); i++) {
+ s += String(inactive[i]) + " ";
+ }
+ s+="]";
+
+ return s;
+}
+
+void
+Active_constraints::OK()
+{
+ #ifndef NDEBUG
+ H.OK();
+ A.OK();
+ assert(active.size() +inactive.size() == opt->cons.size());
+ assert(H.dim() == opt->dim());
+ assert(active.size() == A.rows());
+ Array<int> allcons;
+
+ for (int i=0; i < opt->cons.size(); i++)
+ allcons.push(0);
+ for (int i=0; i < active.size(); i++) {
+ int j = active[i];
+ allcons[j]++;
+ }
+ for (int i=0; i < inactive.size(); i++) {
+ int j = inactive[i];
+ allcons[j]++;
+ }
+ for (int i=0; i < allcons.size(); i++)
+ assert(allcons[i] == 1);
+#endif
+}
+
+Vector
+Active_constraints::get_lagrange(Vector gradient)
+{
+ Vector l(A*gradient);
+
+ return l;
+}
+
+void
+Active_constraints::add(int k)
+{
+ // add indices
+ int cidx=inactive[k];
+ active.push(cidx);
+
+ inactive.swap(k,inactive.size()-1);
+ inactive.pop();
+
+ Vector a( opt->cons[cidx] );
+ // update of matrices
+ Vector Ha = H*a;
+ Real aHa = a*Ha;
+ Vector addrow(Ha.dim());
+ if (abs(aHa) > EPS) {
+ /*
+ a != 0, so if Ha = O(EPS), then
+ Ha * aH / aHa = O(EPS^2/EPS)
+
+ if H*a == 0, the constraints are dependent.
+ */
+ H -= Matrix(Ha/aHa , Ha);
+
+
+ /*
+ sorry, don't know how to justify this. ..
+ */
+ addrow=Ha;
+ addrow/= aHa;
+ A -= Matrix(A*a, addrow);
+ A.insert_row(addrow,A.rows());
+ }else
+ WARN << "degenerate constraints";
+}
+
+void
+Active_constraints::drop(int k)
+{
+ int q=active.size()-1;
+
+ // drop indices
+ inactive.push(active[k]);
+ active.swap(k,q);
+ A.swap_rows(k,q);
+ active.pop();
+
+ Vector a(A.row(q));
+ if (a.norm() > EPS) {
+ /*
+
+ */
+ Real q = a*opt->quad*a;
+ H += Matrix(a,a/q);
+ A -= A*opt->quad*Matrix(a,a/q);
+ }else
+ WARN << "degenerate constraints";
+ #ifndef NDEBUG
+ Vector rem_row(A.row(q));
+ assert(rem_row.norm() < EPS);
+ #endif
+
+ A.delete_row(q);
+}
+
+
+Active_constraints::Active_constraints(Ineq_constrained_qp const *op)
+ : A(0,op->dim()),
+ H(op->dim()),
+ opt(op)
+{
+ for (int i=0; i < op->cons.size(); i++)
+ inactive.push(i);
+ Choleski_decomposition chol(op->quad);
+ H=chol.inverse();
+}
+
+/** Find the optimum which is in the planes generated by the active
+ constraints.
+ */
+Vector
+Active_constraints::find_active_optimum(Vector g)
+{
+ return H*g;
+}
+
+/* *************************************************************** */
+
+int
+min_elt_index(Vector v)
+{
+ Real m=INFTY; int idx=-1;
+ for (int i = 0; i < v.dim(); i++){
+ if (v(i) < m) {
+ idx = i;
+ m = v(i);
+ }
+ assert(v(i) <= INFTY);
+ }
+ return idx;
+}
+
+
+/**the numerical solving. Mordecai Avriel, Nonlinear Programming: analysis and methods (1976)
+ Prentice Hall.
+
+ Section 13.3
+
+ This is a "projected gradient" algorithm. Starting from a point x
+ the next point is found in a direction determined by projecting
+ the gradient onto the active constraints. (well, not really the
+ gradient. The optimal solution obeying the active constraints is
+ tried. This is why H = Q^-1 in initialisation) )
+
+
+ */
+Vector
+Ineq_constrained_qp::solve(Vector start) const
+{
+ Active_constraints act(this);
+
+
+ act.OK();
+
+
+ Vector x(start);
+ Vector gradient=quad*x+lin;
+// Real fvalue = x*quad*x/2 + lin*x + const_term;
+// it's no use.
+
+ Vector last_gradient(gradient);
+ int iterations=0;
+
+ while (iterations++ < MAXITER) {
+ Vector direction= - act.find_active_optimum(gradient);
+
+ mtor << "gradient "<< gradient<< "\ndirection " << direction<<"\n";
+
+ if (direction.norm() > EPS) {
+ mtor << act.status() << '\n';
+
+ Real minalf = INFTY;
+
+ Inactive_iter minidx(act);
+
+
+ /*
+ we know the optimum on this "hyperplane". Check if we
+ bump into the edges of the simplex
+ */
+
+ for (Inactive_iter ia(act); ia.ok(); ia++) {
+
+ if (ia.vec() * direction >= 0)
+ continue;
+ Real alfa= - (ia.vec()*x - ia.rhs())/
+ (ia.vec()*direction);
+
+ if (minalf > alfa) {
+ minidx = ia;
+ minalf = alfa;
+ }
+ }
+ Real unbounded_alfa = 1.0;
+ Real optimal_step = min(minalf, unbounded_alfa);
+
+ Vector deltax=direction * optimal_step;
+ x += deltax;
+ gradient += optimal_step * (quad * deltax);
+
+ mtor << "step = " << optimal_step<< " (|dx| = " <<
+ deltax.norm() << ")\n";
+
+ if (minalf < unbounded_alfa) {
+ /* bumped into an edge. try again, in smaller space. */
+ act.add(minidx.idx());
+ mtor << "adding cons "<< minidx.idx()<<'\n';
+ continue;
+ }
+ /*ASSERT: we are at optimal solution for this "plane"*/
+
+
+ }
+
+ Vector lagrange_mult=act.get_lagrange(gradient);
+ int m= min_elt_index(lagrange_mult);
+
+ if (m>=0 && lagrange_mult(m) > 0) {
+ break; // optimal sol.
+ } else if (m<0) {
+ assert(gradient.norm() < EPS) ;
+
+ break;
+ }
+
+ mtor << "dropping cons " << m<<'\n';
+ act.drop(m);
+ }
+ if (iterations >= MAXITER)
+ WARN<<"didn't converge!\n";
+
+ mtor << ": found " << x<<" in " << iterations <<" iterations\n";
+ assert_solution(x);
+ return x;
+}
+
+
--- /dev/null
+/*
+ register.cc -- implement Request_register
+
+ Sourcefile of LilyPond musictypesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "voice.hh"
+#include "musicalrequest.hh"
+#include "register.hh"
+#include "notehead.hh"
+#include "complex-walker.hh"
+#include "local-key-item.hh"
+#include "complex-staff.hh"
+#include "registergroup.hh"
+#include "debug.hh"
+
+
+bool
+Request_register::try_request(Request*)
+{
+ return false;
+}
+
+Request_register::Request_register()
+{
+ daddy_reg_l_ = 0;
+}
+
+void
+Request_register::announce_element(Staff_elem_info i)
+{
+ i.origin_reg_l_arr_.push(this);
+ daddy_reg_l_->announce_element(i);
+}
+
+void
+Request_register::typeset_element(Staff_elem*p)
+{
+ daddy_reg_l_->typeset_element(p);
+}
+
+Paper_def*
+Request_register::paper()const
+{
+ return daddy_reg_l_->paper();
+}
+
+void
+Request_register::typeset_breakable_item(Item * pre_p , Item * nobreak_p,
+ Item * post_p)
+{
+ daddy_reg_l_->typeset_breakable_item(pre_p, nobreak_p, post_p);
+}
+
+bool
+Request_register::acceptable_request_b(Request*)const
+{
+ return false;
+}
+
+bool
+Request_register::contains_b(Request_register *reg_l)
+{
+ return this == reg_l;
+}
+
+Staff_info
+Request_register::get_staff_info() return inf;
+{
+ inf = daddy_reg_l_->get_staff_info();
+}
+
+void
+Request_register::print() const
+{
+#ifndef NPRINT
+ mtor << name() << " {";
+ do_print();
+ mtor << "}\n";
+#endif
+}
+
+void
+Request_register::do_print()const
+{
+}
--- /dev/null
+/*
+ request.cc -- implement all musical requests.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "musicalrequest.hh"
+#include "misc.hh"
+#include "debug.hh"
+#include "script-def.hh"
+#include "text-def.hh"
+#include "voice.hh"
+#include "voice-element.hh"
+
+void
+Stem_req::do_print() const
+{
+ Rhythmic_req::do_print();
+ mtor << "dir : " << dir_i_;
+}
+
+Stem_req::Stem_req(int s, int d)
+ : Rhythmic_req(s,d)
+{
+ dir_i_ = 0;
+}
+
+/* ************** */
+void Musical_req::do_print()const{}
+void Request::do_print() const{}
+
+/* *************** */
+
+void
+Request::print() const
+{
+ mtor << name() << " {";
+ do_print();
+ mtor << "}\n";
+}
+
+
+
+void
+Span_req::do_print() const
+{
+#ifndef NPRINT
+ mtor << spantype ;
+#endif
+}
+
+Request::Request()
+{
+ elt_l_ = 0;
+ defined_ch_c_l_ = 0;
+}
+Request::Request(Request const&src)
+{
+ elt_l_ = 0;
+ defined_ch_c_l_ = src.defined_ch_c_l_;
+}
+/* *************** */
+Spacing_req::Spacing_req()
+{
+ next = 0;
+ distance = 0;
+ strength = 0;
+}
+void
+Spacing_req::do_print()const
+{
+ mtor << "next " << next << "dist " << distance << "strength\n";
+}
+
+void
+Blank_req::do_print()const
+{
+ Spacing_req::do_print();
+}
+/* *************** */
+Melodic_req::Melodic_req()
+{
+ notename_i_ = 0;
+ octave_i_ = 0;
+ accidental_i_ = 0;
+ forceacc_b_ = false;
+}
+
+void
+Melodic_req::do_print() const
+{
+ mtor << "notename: " << notename_i_ << " acc: " <<accidental_i_<<" oct: "<< octave_i_;
+}
+
+int
+Melodic_req::height() const
+{
+ return notename_i_ + octave_i_*7;
+}
+
+/*
+ should be settable from input to allow "viola"-mode
+ */
+static Byte pitch_byte_a[ 7 ] = { 0, 2, 4, 5, 7, 9, 11 };
+
+int
+Melodic_req::pitch() const
+{
+ return pitch_byte_a[ notename_i_ % 7 ] + accidental_i_ + octave_i_ * 12;
+}
+
+Plet_req::Plet_req()
+{
+ type_c_ = ']';
+ dur_i_ = 1;
+ type_i_ = 1;
+}
+
+void
+Plet_req::do_print() const
+{
+ mtor << "plet: " << type_c_ << ": " << dur_i_ << "/" << type_i_;
+}
+
+/* *************** */
+int
+Rhythmic_req::compare(const Rhythmic_req &r1, const Rhythmic_req &r2)
+{
+ return sign(r1.duration() - r2.duration());
+}
+Rhythmic_req::Rhythmic_req(int b, int d)
+{
+ plet_factor = 1;
+ balltype = b;
+ dots = d;
+}
+
+Rhythmic_req::Rhythmic_req()
+{
+ plet_factor = 1;
+ balltype = 1;
+ dots = 0;
+}
+
+void
+Rhythmic_req::do_print() const
+{
+ mtor << "ball: " << balltype ;
+ int d =dots;
+ while (d--)
+ mtor << '.';
+
+ mtor<<", plet factor"<<plet_factor<<"\n";
+}
+
+
+Moment
+Rhythmic_req::duration() const {
+ return wholes(balltype,dots)*plet_factor;
+}
+/* *************** */
+
+Lyric_req::Lyric_req(Text_def* def_p)
+ :Text_req(0, def_p)
+{
+ def_p->align_i_ = 0; // centre
+ dir_i_ = -1; // lyrics below (invisible) staff
+}
+
+void
+Lyric_req::do_print() const
+{
+ Rhythmic_req::do_print();
+ Text_req::do_print();
+}
+/* *************** */
+void
+Note_req::do_print() const
+{
+ Melodic_req::do_print();
+ Rhythmic_req::do_print();
+}
+/* *************** */
+void
+Rest_req::do_print() const
+{
+ Rhythmic_req::do_print();
+}
+
+/* *************** */
+Beam_req::Beam_req()
+{
+ nplet = 0;
+}
+
+void Beam_req::do_print()const{}
+/* *************** */
+void Slur_req::do_print()const{}
+/* *************** */
+int
+Span_req:: compare(const Span_req &r1, const Span_req &r2)
+{
+ return r1.spantype - r2.spantype;
+}
+
+Span_req::Span_req()
+{
+ spantype = NOSPAN;
+}
+
+/* *************** */
+Script_req::Script_req(int d , Script_def*def)
+{
+ dir_i_ = d;
+ scriptdef_p_ = def;
+}
+
+int
+Script_req::compare(const Script_req &d1, const Script_req &d2)
+{
+ return d1.dir_i_ == d2.dir_i_ &&
+ d1.scriptdef_p_->compare(*d2.scriptdef_p_);
+}
+
+Script_req::Script_req(Script_req const &s)
+ : Request( s )
+{
+ dir_i_ = s.dir_i_;
+ scriptdef_p_ = new Script_def(*s.scriptdef_p_);
+}
+
+void
+Script_req::do_print() const
+{
+ mtor << " dir " << dir_i_ ;
+ scriptdef_p_->print();
+}
+
+
+Script_req::~Script_req()
+{
+ delete scriptdef_p_;
+}
+/* *************** */
+int
+Text_req:: compare(const Text_req &r1, const Text_req &r2)
+{
+ bool b1 = (r1.dir_i_ == r2.dir_i_);
+ bool b2 = (r1.tdef_p_ ->compare(*r2.tdef_p_));
+ return b1 && b2;
+}
+Text_req::~Text_req()
+{
+ delete tdef_p_;
+ tdef_p_ = 0;
+}
+
+Text_req::Text_req(Text_req const& src)
+{
+ tdef_p_ = new Text_def(*src.tdef_p_);
+ dir_i_ = src.dir_i_;
+}
+
+Text_req::Text_req(int dir_i, Text_def* tdef_p)
+{
+ dir_i_ = dir_i;
+ tdef_p_ = tdef_p;
+}
+
+void
+Text_req::do_print() const
+{
+ mtor << " dir " << dir_i_ ;
+ tdef_p_->print();
+}
+
+/* *************** */
+
+Moment
+Skip_req::duration() const
+{
+ return duration_;
+}
+
+void
+Skip_req::do_print() const
+{
+ mtor << "duration: " << duration();
+}
+
+Voice *
+Request::voice_l()
+{
+ if (!elt_l_)
+ return 0;
+ else
+ return (Voice*)elt_l_->voice_l_;
+}
--- /dev/null
+#include "rest.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+
+
+Rest::Rest(int t, int d)
+{
+ balltype = t;
+ dots = d;
+}
+
+
+void
+Rest::do_print()const
+{
+#ifndef NPRINT
+ mtor << "Rest "<<balltype<< "dots " << dots;
+ Item::print();
+#endif
+}
+
+Molecule*
+Rest::brew_molecule_p()const
+{
+ Paper_def *p =paper();
+
+ Symbol s;
+ s = p->lookup_p_->rest(balltype);
+
+ Molecule *m = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d =p->lookup_p_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ m->add_right(dm);
+ }
+ return m;
+}
+
--- /dev/null
+/*
+ score-column.cc -- implement Score_column
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "debug.hh"
+#include "pcol.hh"
+#include "score-column.hh"
+
+int
+Score_column::compare(Score_column & c1, Score_column &c2)
+{
+ return sign(c1.when_ - c2.when_);
+}
+
+void
+Score_column::set_breakable()
+{
+ pcol_l_->set_breakable();
+}
+
+Score_column::Score_column(Moment w)
+{
+ when_ = w;
+ pcol_l_ = new PCol(0);
+ musical_b_ = false;
+}
+
+bool
+Score_column::used_b() {
+ return pcol_l_->used_b();
+}
+
+void
+Score_column::print() const
+{
+#ifndef NPRINT
+ mtor << "Score_column { mus "<< musical_b_ <<" at " << when_<<'\n';
+ mtor << "durations: [";
+ for (int i=0; i < durations.size(); i++)
+ mtor << durations[i] << " ";
+ mtor << "]\n";
+ pcol_l_->print();
+ mtor << "}\n";
+#endif
+}
+
+int
+Moment_compare(Moment &a , Moment& b)
+{
+ return sign(a-b);
+}
+
+void
+Score_column::preprocess()
+{
+ durations.sort(Moment_compare);
+}
+void
+Score_column::add_duration(Moment d)
+{
+ assert(d);
+ for (int i = 0; i< durations.size(); i++) {
+ if (d == durations[i])
+ return ;
+ }
+ durations.push(d);
+}
+
+bool
+Score_column::breakable_b()
+{
+ return pcol_l_->breakable_b();
+}
--- /dev/null
+/*
+ score.cc -- implement Score
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include "tex-stream.hh"
+#include "score.hh"
+#include "score-column.hh"
+#include "pscore.hh"
+#include "staff.hh"
+#include "debug.hh"
+#include "paper-def.hh"
+#include "main.hh"
+#include "source.hh"
+#include "source-file.hh"
+#include "score-walker.hh"
+#include "midi-output.hh"
+#include "midi-def.hh"
+
+extern String default_out_fn;
+
+void
+Score::setup_music()
+{
+ *mlog << "\nSetting up music ..." << flush;
+ if (last() == Moment(0)) {
+ errorlevel_i_ |= 1;
+ error("Need to have music in a score.", defined_ch_c_l_);
+ }
+
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->setup_staffcols();
+ i->OK();
+ }
+}
+
+void
+Score::process_music()
+{
+ *mlog << "Processing music ..." << flush;
+ for (Score_walker w(this); w.ok(); w++) {
+ w.process();
+ }
+}
+
+void
+Score::process()
+{
+ setup_music();
+
+ paper();
+ midi();
+}
+
+void
+Score::paper()
+{
+ if (!paper_p_)
+ return;
+
+ pscore_p_ = new PScore(paper_p_);
+
+ find_col(0, false)->set_breakable(); // ugh
+ find_col(last(), false)->set_breakable();
+ do_cols();
+
+ for (iter_top(staffs_,i); i.ok(); i++)
+ i->set_output(pscore_p_);
+
+
+ process_music();
+ clean_cols(); // can't move clean_cols() farther up.
+ print();
+ calc_idealspacing();
+
+ // debugging
+ OK();
+ *mlog << endl;
+ pscore_p_->process();
+
+ // output
+ paper_output();
+
+}
+
+/**
+ Remove empty cols, preprocess other columns.
+ */
+void
+Score::clean_cols()
+{
+ for (iter_top(staffs_,i); i.ok(); i++)
+ i->clean_cols();
+
+ for (iter_top(cols_,c); c.ok(); ) {
+ if (!c->pcol_l_->used_b()) {
+ delete c.remove_p();
+ } else {
+ c->preprocess();
+ c++;
+ }
+ }
+}
+
+/**
+ Create columns at time #w#.
+ this sux. We should have Score_column create the appropriate PCol.
+ Unfortunately, PCols don't know about their position.
+
+ @return cursor pointing to the nonmusical (first) column
+ */
+PCursor<Score_column*>
+Score::create_cols(Moment w)
+{
+ Score_column* c1 = new Score_column(w);
+ Score_column* c2 = new Score_column(w);
+
+ c1->musical_b_ = false;
+ c2->musical_b_ = true;
+
+ iter_top(cols_,i);
+
+ for (; i.ok(); i++) {
+ assert(i->when() != w);
+ if (i->when() > w)
+ break;
+ }
+
+ if (!i.ok()) {
+ cols_.bottom().add(c1);
+ cols_.bottom().add(c2);
+ i = cols_.bottom();
+ i --;
+ } else {
+ i.insert(c1);
+ i.insert(c2);
+ i -= 2;
+ }
+ return i;
+}
+
+PCursor<Score_column*>
+Score::find_col(Moment w, bool mus)
+{
+ iter_top( cols_,i);
+
+ for (; i.ok(); i++) {
+ if (i->when() == w && i->musical_b_ == mus)
+ return i;
+ if (i->when() > w)
+ break;
+ }
+ i = create_cols(w);
+ if (mus)
+ i++;
+ return i;
+}
+
+void
+Score::do_cols()
+{
+ iter_top(cols_,i);
+ for (; i.ok(); i++) {
+ pscore_p_->add(i->pcol_l_);
+ }
+}
+
+Moment
+Score::last() const
+{
+ Moment l = 0;
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ l = l>? i->last();
+ }
+ return l;
+}
+
+void
+Score::set(Paper_def *pap_p)
+{
+ delete paper_p_;
+ paper_p_ = pap_p;
+}
+
+void
+Score::set(Midi_def* midi_p)
+{
+ delete midi_p_;
+ midi_p_ = midi_p;
+}
+
+void
+Score::OK() const
+{
+#ifndef NDEBUG
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->OK();
+ assert(i->score_l_ == this);
+ }
+ staffs_.OK();
+ cols_.OK();
+ for (iter_top(cols_,cc); cc.ok() && (cc+1).ok(); cc++) {
+ assert(cc->when() <= (cc+1)->when());
+ }
+#endif
+}
+
+
+void
+Score::print() const
+{
+#ifndef NPRINT
+ mtor << "score {\n";
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->print();
+ }
+ for (iter_top(cols_,i); i.ok(); i++) {
+ i->print();
+ }
+ if (pscore_p_)
+ pscore_p_->print();
+ if (midi_p_)
+ midi_p_->print();
+
+ mtor << "}\n";
+#endif
+}
+
+Score::Score()
+{
+ pscore_p_=0;
+ paper_p_ = 0;
+ midi_p_ = 0;
+ errorlevel_i_ = 0;
+ defined_ch_c_l_ = 0;
+}
+
+Score::~Score()
+{
+ delete pscore_p_;
+ delete paper_p_;
+ delete midi_p_;
+}
+
+void
+Score::paper_output()
+{
+ OK();
+ if (paper_p_->outfile=="")
+ paper_p_->outfile = default_out_fn + ".out";
+
+ if ( errorlevel_i_ ) {
+ *mlog << "lilypond: warning: no output to: " << paper_p_->outfile
+ << " (errorlevel=" << errorlevel_i_ << ")" << endl;
+ return;
+ }
+
+ *mlog << "TeX output to " << paper_p_->outfile << " ...\n";
+
+ Tex_stream the_output(paper_p_->outfile);
+
+ the_output << "% outputting Score, defined at: " <<
+ source_l_g->
+ sourcefile_l (defined_ch_c_l_)->file_line_no_str(defined_ch_c_l_) << "\n";
+ pscore_p_->output(the_output);
+}
+
+void
+Score::midi()
+{
+ if (!midi_p_)
+ return;
+
+ if (midi_p_->outfile_str_ == "")
+ midi_p_->outfile_str_ = default_out_fn + ".midi";
+
+ *mlog << "midi output to " << midi_p_->outfile_str_ << " ...\n";
+ Midi_output(this, midi_p_);
+}
+
+void
+Score::add(Staff*s)
+{
+ s->score_l_ = this;
+ staffs_.bottom().add(s);
+}
--- /dev/null
+#include "scoreline.hh"
+#include "staffline.hh"
+#include "dimen.hh"
+#include "spanner.hh"
+#include "symbol.hh"
+#include "paper-def.hh"
+#include "pcol.hh"
+#include "pscore.hh"
+
+
+String
+Line_of_score::TeXstring() const
+{
+ String s("\\vbox{%<- line of score\n");
+ for (iter_top(staffs,sc); sc.ok(); sc++){
+ s += sc->TeXstring();
+ if ((sc+1).ok())
+ s+= "\\interstaffline\n";
+ }
+ s += "}";
+ return s;
+}
+
+
+Line_of_score::Line_of_score(Array<PCol *> sv,
+ PScore *ps)
+{
+ pscore_l_ = ps;
+ for (int i=0; i< sv.size(); i++) {
+ PCol *p=(PCol *) sv[i];
+ cols.bottom().add(p);
+ p->line_l_=this;
+ }
+
+ for (iter_top(pscore_l_->staffs,sc); sc.ok(); sc++)
+ staffs.bottom().add(new Line_of_staff(this, sc));
+}
+/* construct a line with the named columns. Make the line field
+ in each column point to this
+
+ #sv# isn't really const!!
+ */
+
+
+void
+Line_of_score::process()
+{
+ for (iter_top(staffs,i); i.ok(); i++)
+ i->process();
+}
+
--- /dev/null
+#include "main.hh"
+#include "input-score.hh"
+#include "score.hh"
+#include "string.hh"
+#include "paper-def.hh"
+#include "debug.hh"
+
+static Array<Input_score*> score_array_global;
+String default_out_fn = "lelie";
+
+void
+do_scores()
+{
+ for (int i=0; i < score_array_global.size(); i++) {
+ Input_score* &is_p = score_array_global[i];
+ if (is_p->errorlevel_i_) {
+ warning("Score contains errors. Will not process it. ",
+ is_p->defined_ch_c_l_);
+ delete is_p;
+ continue;
+ }
+
+ if (only_midi) {
+ delete is_p->paper_p_;
+ is_p->paper_p_ = 0;
+ }
+
+ Score * s_p = is_p->parse();
+ delete is_p;
+ s_p->print ();
+ s_p->process();
+ delete s_p;
+ }
+ score_array_global.set_size(0);
+}
+
+void
+add_score(Input_score * s)
+{
+ score_array_global.push(s);
+}
+
+void
+set_default_output(String s)
+{
+ default_out_fn = s;
+}
+
--- /dev/null
+#include "debug.hh"
+#include "script-def.hh"
+
+Script_def::Script_def(String idx, int stem, int staff ,bool invert)
+{
+ symidx = idx ;
+ stemdir =stem;
+ staffdir = staff;
+ invertsym = invert;
+}
+void
+Script_def::print() const
+{
+ mtor << "Script_def{ idx: " << symidx
+ << " direction, stem: " << stemdir << " staff : " << staffdir << "}\n";
+}
+int
+Script_def::compare(Script_def const & c)
+{
+ return !(symidx == c.symidx &&
+ stemdir == c.stemdir&&
+ staffdir == c.staffdir&&
+ invertsym == c.invertsym);
+}
--- /dev/null
+/*
+ script-reg.cc -- implement Script_register
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "script-reg.hh"
+#include "script.hh"
+#include "musicalrequest.hh"
+#include "complex-walker.hh"
+#include "stem.hh"
+
+Script_register::Script_register()
+{
+ script_p_ = 0;
+ post_move_processing();
+}
+
+bool
+Script_register::try_request(Request *r_l)
+{
+ if (!r_l->script())
+ return false ;
+
+ if (script_req_l_
+ && Script_req::compare(*script_req_l_, *r_l->script()))
+
+ return false;
+
+ script_req_l_ = r_l->script();
+
+ return true;
+}
+
+void
+Script_register::process_requests()
+{
+ if (script_req_l_) {
+ script_p_ = new Script(script_req_l_, 10);
+ announce_element(
+ Staff_elem_info(script_p_, script_req_l_));
+ }
+}
+
+void
+Script_register::acknowledge_element(Staff_elem_info info)
+{
+ if (!script_p_)
+ return;
+ if (info.elem_p_->name() == Stem::static_name())
+ script_p_->set_stem((Stem*)info.elem_p_);
+ else if (info.req_l_->rhythmic())
+ script_p_->set_support(info.elem_p_->item());
+}
+
+void
+Script_register::pre_move_processing()
+{
+ if (script_p_){
+ script_p_->dir = dir_i_;
+ typeset_element(script_p_);
+ script_p_ = 0;
+ }
+}
+void
+Script_register::post_move_processing()
+{
+ script_req_l_ = 0;
+}
+
+void
+Script_register::set_feature(Features i)
+{
+ if (i.direction_i_|| i.initialiser_b_)
+ dir_i_ = i.direction_i_;
+}
--- /dev/null
+#include "musicalrequest.hh"
+#include "paper-def.hh"
+#include "script.hh"
+#include "stem.hh"
+#include "molecule.hh"
+#include "lookup.hh"
+
+
+
+void
+Script::set_stem(Stem*st_l)
+{
+ stem_l_ = st_l;
+ add_dependency(st_l);
+}
+
+void
+Script::set_support(Item*i)
+{
+ support.push(i);
+ add_dependency(i);
+}
+
+Script::Script(Script_req* rq, int staflen)
+{
+ staffsize =staflen;
+ specs_l_ = rq->scriptdef_p_;
+ stem_l_ = 0;
+ pos = 0;
+ symdir=1;
+ dir =rq->dir_i_;
+}
+
+void
+Script::set_symdir()
+{
+ if (specs_l_->invertsym)
+ symdir = (dir < 0) ? -1:1;
+}
+
+void
+Script::set_default_dir()
+{
+ if (specs_l_->stemdir) {
+ if (!stem_l_)
+ dir = 1;
+ else
+ dir = stem_l_->dir * specs_l_->stemdir;
+ }
+}
+
+Interval
+Script::support_height() const return r;
+{
+ for (int i=0; i < support.size(); i++)
+ r.unite(support[i]->height());
+}
+
+void
+Script::set_default_index()
+{
+ Real inter_f= paper()->internote();
+ Interval dy = symbol().dim.y;
+
+ int d = specs_l_->staffdir;
+ Real y ;
+ if (!d) {
+ Interval v= support_height();
+ y = v[dir] -dy[-dir] + 2*dir*inter_f;
+ } else {
+ y = (d > 0) ? staffsize + 2: -2; // ug
+ y *=inter_f;
+ Interval v= support_height();
+
+ if (d > 0) {
+ y = y >? v.max();
+ } else if (d < 0) {
+ y = y <? v.min();
+ }
+ }
+
+ if (stem_l_) {
+ Interval v= stem_l_->height();
+
+ if (d > 0 || (!d && dir > 0)) {
+ y = y >? v.max();
+ }else if (d < 0 || (!d && dir < 0)) {
+ y = y <? v.min();
+ }
+ }
+
+ pos = int(rint(Real(y)/inter_f));
+}
+
+Interval
+Script::width() const
+{
+ return symbol().dim.x;
+}
+
+Symbol
+Script::symbol()const
+{
+ String preidx_str = (symdir < 0) ?"-" :"";
+ return paper()->lookup_p_->script(preidx_str + specs_l_->symidx);
+}
+
+void
+Script::do_pre_processing()
+{
+ set_default_dir();
+ set_symdir();
+}
+
+void
+Script::do_post_processing()
+{
+ set_default_index();
+}
+
+Molecule*
+Script::brew_molecule_p() const
+{
+ Real dy = paper()->internote();
+
+ Molecule*out = new Molecule(Atom(symbol()));
+ out->translate(Offset(0,dy * pos));
+ return out;
+}
--- /dev/null
+/*
+
+ TODO:
+ think about crossing stems.
+ */
+#include "slur.hh"
+#include "scalar.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "notehead.hh"
+#include "pcol.hh"
+#include "molecule.hh"
+#include "debug.hh"
+#include "boxes.hh"
+
+
+
+Slur::Slur()
+{
+ open_right=open_left=false;
+}
+
+Offset
+Slur::center() const
+{
+ int pos1 = encompass.top()->position;
+ int pos2 = encompass[0]->position;
+
+ int dy = pos1-pos2;
+
+ Real w = width().length();
+
+ return Offset(w/2,dy * paper()->internote());
+}
+
+void
+Slur::add(Notehead*n)
+{
+ encompass.push(n);
+ add_dependency(n);
+}
+
+void
+Slur::set_default_dir()
+{
+ int sumpos=0;
+ for (int i=0; i < encompass.size(); i ++) {
+ sumpos += encompass[i]->position;
+ }
+
+ /* should consult stems */
+ Real meanpos = sumpos/Real(encompass.size());
+ if (meanpos < 5) // todo
+ dir_i_ = -1;
+ else
+ dir_i_ = 1;
+}
+
+void
+Slur::do_pre_processing()
+{
+ right = encompass.top()->pcol_l_;
+ left = encompass[0]->pcol_l_;
+}
+
+Spanner*
+Slur::do_break_at(PCol*l, PCol*r) const
+{
+ assert(l->line_l_ == r->line_l_);
+ Slur*ret = new Slur(*this);
+
+ ret->encompass.set_size(0);
+ for (int i =0; i < encompass.size(); i++) {
+ if (encompass[i]->pcol_l_->line_l_==l->line_l_)
+ ret->encompass.push(encompass[i]);
+ }
+ if (right != r)
+ ret->open_right = true;
+ if (left != l)
+ ret->open_left = true;
+
+
+ return ret;
+}
+
+void
+Slur::do_post_processing()
+{
+ if (!dir_i_)
+ set_default_dir();
+}
+
+Molecule*
+Slur::brew_molecule_p() const
+{
+ Molecule*output = new Molecule;
+
+ int minp=1000, maxp=-1000; // todo
+ for (int i=0; i<encompass.size(); i++) {
+ minp = encompass[i]->position <? minp;
+ maxp = encompass[i]->position >? maxp;
+ }
+ assert(encompass.size()>0); // todo
+
+ Notehead *lnote_p =encompass[0];
+ Notehead *rnote_p =encompass.top();
+ int lpos_i = lnote_p->position;
+ int rpos_i = rnote_p->position;
+ Offset left_off(lnote_p->x_dir, lpos_i + 2*dir_i_);
+ Offset right_off(lnote_p->x_dir, rpos_i + 2*dir_i_);
+ if (!lnote_p->extremal)
+ left_off += Offset(0.5, -dir_i_);
+ if (!rnote_p->extremal)
+ right_off+= Offset(-0.5, -dir_i_);
+
+ int dy = int(right_off.y - left_off.y);
+
+ Real nw_f = paper()->note_width();
+ Real nh_f = paper()->internote();
+ Real w = width().length();
+
+ w+= (right_off.x - left_off.x) * nw_f ;
+ Real round_w = w; // slur lookup rounds the slurwidth .
+
+ Symbol sl = paper()->lookup_p_->slur(dy , round_w, dir_i_);
+
+ Real error = w-round_w;
+
+ Atom a(sl);
+ a.translate(Offset((left_off.x + 0.5 )*nw_f + error/2,
+ left_off.y * nh_f));
+ output->add(a);
+ return output;
+}
+
--- /dev/null
+#include "debug.hh"
+#include "spanner.hh"
+#include "pcol.hh"
+
+
+
+void
+Spanner::do_print()const
+{
+ mtor << " (unknown) ";
+}
+
+Spanner*
+Spanner::broken_at(PCol*c1, PCol *c2)const
+{
+ Spanner *span_p = do_break_at(c1,c2);
+
+ for (int i=0; i < dependants.size(); i++) {
+ dependants[i]->substitute_dependency((Staff_elem*)this, span_p);
+ }
+
+ span_p->left = c1;
+ span_p->right = c2;
+
+ return span_p;
+}
+
+Spanner::Spanner()
+{
+ left = right = 0;
+}
+
+
+Interval
+Spanner::width()const
+{
+ Real r = right->hpos;
+ Real l = left->hpos;
+ assert(*left < *right);
+ assert(r>=l);
+
+ return Interval(0, r-l);
+}
--- /dev/null
+/*
+ staff-elem-info.cc -- implement Staff_elem_info
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "staff-elem-info.hh"
+#include "request.hh"
+
+Staff_elem_info::Staff_elem_info(Staff_elem*s_l, Request*r_l)
+{
+ elem_p_ = s_l;
+ voice_l_ = (r_l)?r_l->voice_l():0;
+ req_l_ = r_l;
+}
+
+Staff_elem_info::Staff_elem_info()
+{
+ elem_p_ = 0;
+ voice_l_ = 0;
+
+ req_l_ = 0;
+}
+
+Features::Features()
+{
+ direction_i_ = 0;
+ initialiser_b_ = false;
+}
+
+Features
+Features::dir(int d) return f;
+{
+ f.initialiser_b_ = true;
+ f.direction_i_ = d;
+}
--- /dev/null
+#include "pscore.hh"
+#include "symbol.hh"
+#include "pstaff.hh"
+#include "molecule.hh"
+#include "staff-elem.hh"
+#include "debug.hh"
+
+String
+Staff_elem::TeXstring() const
+{
+ Molecule m(*output);
+ m.translate(offset_); // ugh?
+ return m.TeXstring();
+}
+
+Staff_elem::Staff_elem(Staff_elem const&s)
+ : dependants(s.dependants),
+ dependencies(s.dependencies)
+{
+ status = s.status;
+ assert(!s.output);
+ output = 0;
+ pstaff_l_ = s.pstaff_l_;
+ offset_ = Offset(0,0);
+}
+/**
+ TODO:
+ If deleted, then remove dependants depency!
+ */
+Staff_elem::~Staff_elem()
+{
+ delete output;
+}
+
+void
+Staff_elem::translate(Offset O)
+{
+ offset_ += O;
+}
+Interval
+Staff_elem::width() const
+{
+ Interval r;
+
+ if (!output){
+ Molecule*m = brew_molecule_p();
+ r = m->extent().x;
+ delete m;
+ } else
+ r = output->extent().x;
+
+ if (!r.empty()) // float exception on DEC Alpha
+ r+=offset_.x;
+
+ return r;
+}
+Interval
+Staff_elem::height() const
+{
+ Interval r;
+
+ if (!output){
+ Molecule*m = brew_molecule_p();
+ r = m->extent().y;
+ delete m;
+ } else
+ r = output->extent().y;
+
+ if (!r.empty())
+ r+=offset_.y;
+
+
+ return r;
+}
+
+void
+Staff_elem::print()const
+{
+#ifndef NPRINT
+ mtor << name() << "{\n";
+ do_print();
+ if (output)
+ output->print();
+
+ mtor << "}\n";
+#endif
+}
+
+
+
+Staff_elem::Staff_elem()
+{
+ pstaff_l_=0;
+ offset_ = Offset(0,0);
+ output = 0;
+ status = ORPHAN;
+}
+
+
+Paper_def*
+Staff_elem::paper() const
+{
+ assert(pstaff_l_);
+ return pstaff_l_->pscore_l_->paper_l_;
+}
+
+void
+Staff_elem::add_processing()
+{
+ if (status >= VIRGIN)
+ return;
+ status = VIRGIN;
+ do_add_processing();
+}
+
+void
+Staff_elem::pre_processing()
+{
+ if (status >= PRECALCED )
+ return;
+ assert(status != PRECALCING); // cyclic dependency
+ status = PRECALCING;
+
+ for (int i=0; i < dependencies.size(); i++)
+ if (dependencies[i])
+ dependencies[i]->pre_processing();
+
+
+ do_pre_processing();
+ status = PRECALCED;
+}
+void
+Staff_elem::post_processing()
+{
+ if (status >= POSTCALCED)
+ return;
+ assert(status != POSTCALCING);// cyclic dependency
+ status=POSTCALCING;
+
+ for (int i=0; i < dependencies.size(); i++)
+ if (dependencies[i])
+ dependencies[i]->post_processing();
+ do_post_processing();
+ status=POSTCALCED;
+}
+
+void
+Staff_elem::molecule_processing()
+{
+ if (status >= OUTPUT)
+ return;
+ status = OUTPUT; // do it only once.
+ for (int i=0; i < dependencies.size(); i++)
+ if (dependencies[i])
+ dependencies[i]->molecule_processing();
+
+ output= brew_molecule_p();
+}
+
+void
+Staff_elem::do_post_processing()
+{
+}
+
+void
+Staff_elem::do_pre_processing()
+{
+}
+
+void
+Staff_elem::do_add_processing()
+{
+}
+
+void
+Staff_elem::substitute_dependency(Staff_elem * old, Staff_elem * newdep)
+{
+ bool hebbes_b=false;
+ for (int i=0; i < dependencies.size(); i++) {
+ if (dependencies[i] == old){
+ dependencies[i] = newdep;
+ hebbes_b = true;
+ } else if (dependencies[i] == newdep) {
+ hebbes_b = true;
+ }
+ }
+ if (!hebbes_b)
+ dependencies.push(newdep);
+}
+
+void
+Staff_elem::add_dependency(Staff_elem * p)
+{
+ for (int i=0; i < dependencies.size(); i ++)
+ if (dependencies[i] == p)
+ return;
+
+ dependencies.push(p);
+ p->dependants.push(p);
+}
--- /dev/null
+#include "staffline.hh"
+#include "scoreline.hh"
+#include "dimen.hh"
+#include "spanner.hh"
+#include "symbol.hh"
+#include "paper-def.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+#include "pscore.hh"
+
+static String
+make_vbox(Interval i)
+{
+ Real r = (i.empty()) ? 0.0 : i.length();
+ String s("\\vbox to ");
+ s += print_dimen(r);
+ s += "{\\vskip "+print_dimen(i.right)+" ";
+ return s;
+}
+
+
+String
+Line_of_staff::TeXstring() const
+{
+ String s("%line_of_staff\n");
+
+ s+=make_vbox(height());
+ // the staff itself: eg lines, accolades
+ s += "\\hbox{";
+ {
+ iter_top(line_of_score_l_->cols,cc);
+ Real lastpos=cc->hpos;
+
+ // all items in the current line & staff.
+ for (; cc.ok(); cc++) {
+ Real delta=cc->hpos - lastpos;
+ lastpos = cc->hpos;
+
+ // moveover
+ if (delta)
+ s +=String( "\\kern ") + print_dimen(delta);
+
+ // now output the items.
+ for (iter_top(cc->its,i); i.ok(); i++) {
+ if (i->pstaff_l_ == pstaff_l_)
+ s += i->TeXstring();
+ }
+ // spanners.
+ for (iter_top(cc->starters,i); i.ok(); i++)
+ if (i->pstaff_l_ == pstaff_l_)
+ s += i->TeXstring();
+ }
+ }
+ s+="\\hss}\\vss}";
+ return s;
+}
+
+Line_of_staff::Line_of_staff(Line_of_score * sc, PStaff*st)
+{
+ line_of_score_l_=sc;
+ pstaff_l_=st;
+
+ PCol *linestart = sc->cols.top();
+ PCol *linestop = sc->cols.bottom();
+
+ for (iter_top(pstaff_l_->spans,i); i.ok(); i++) {
+ PCol *brokenstart = &max(*linestart, *i->left);
+ PCol *brokenstop = &min(*linestop, *i->right);
+ if ( *brokenstart < *brokenstop) {
+ Spanner*span_p =i->broken_at(brokenstart,brokenstop);
+ line_of_score_l_->pscore_l_-> // higghl
+ add_broken(span_p);
+ }
+ }
+}
+
+
+Interval
+Line_of_staff::height() const
+{
+ Interval y(0,0);
+
+ iter_top(line_of_score_l_->cols,cc);
+
+ // all items in the current line & staff.
+ for (; cc.ok(); cc++) {
+ for (iter_top(cc->its,i); i.ok(); i++) {
+ if (i->pstaff_l_ == pstaff_l_)
+ y.unite(i->height());
+
+ }
+ // spanners.
+ for (iter_top(cc->starters,i); i.ok(); i++)
+ if (i->pstaff_l_ == pstaff_l_) {
+ y.unite(i->height());
+ }
+ }
+
+ return y;
+}
+
+void
+Line_of_staff::process()
+{
+#if 0
+ if (!pstaff_l_->stafsym_p_)
+ pstaff_l_->brew_molecule_p(line_of_score_l_->pscore_l_->
+ paper_l_->linewidth);
+#endif
+}
--- /dev/null
+/*
+ staffsym.cc -- implement Staff_symbol
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include "staffsym.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "debug.hh"
+
+
+
+Staff_symbol::Staff_symbol(int l)
+{
+ no_lines_i_ = l;
+}
+
+void
+Staff_symbol::do_print()const
+{
+ mtor << "lines: " << no_lines_i_;
+}
+
+Molecule*
+Staff_symbol::brew_molecule_p() const
+{
+ Atom a = paper()->lookup_p_->linestaff(no_lines_i_, width().length());
+ return new Molecule(a);
+}
+
+Spanner*
+Staff_symbol::do_break_at(PCol*p1, PCol*p2)const
+{
+ Staff_symbol *span_p=new Staff_symbol(*this);
+ return span_p;
+}
+
+void
+Staff_symbol::set_extent(PCol*p1, PCol*p2)
+{
+ assert(p1&&p2);
+ left = p1;
+ right = p2;
+}
--- /dev/null
+#include "stem.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper-def.hh"
+#include "notehead.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+#include "misc.hh"
+
+const int STEMLEN=7;
+
+
+Stem::Stem(int c) //, Moment len)
+{
+ beams_left = 0;
+ beams_right = 0;
+ minnote = 1000; // invalid values
+ maxnote = -1000;
+ bot = top = 0;
+ flag = 4;
+ dir =0;
+ staff_center=c;
+ stemlen=0;
+ print_flag=true;
+ stem_xoffset=0;
+}
+
+void
+Stem::do_print() const
+{
+#ifndef NPRINT
+ mtor << "flag "<< flag << " print_flag " << print_flag
+ << "min,max [" << minnote << ", " << maxnote << "]";
+#endif
+}
+void
+Stem::set_stemend(Real se)
+{
+
+ // todo: margins
+ if (! ((dir > 0 && se >= maxnote) || (se <= minnote && dir <0)) )
+ warning("Weird stem size; check for narrow beams",0);
+
+ top = (dir < 0) ? maxnote : se;
+ bot = (dir < 0) ? se : minnote;
+ flag = dir*abs(flag);
+}
+
+void
+Stem::add(Notehead *n)
+{
+ assert(status < PRECALCED);
+
+ if (n->balltype == 1)
+ return;
+ int p = n->position;
+ if (p < minnote)
+ minnote = p;
+ if (p > maxnote)
+ maxnote = p;
+ heads.push(n);
+ n->add_dependency(this);
+}
+
+
+int
+Stem::get_default_dir()
+{
+ if (dir)
+ return dir;
+ Real mean = (minnote+maxnote)/2;
+ return (mean > staff_center) ? -1: 1;
+}
+
+void
+Stem::set_default_dir()
+{
+ dir = get_default_dir();
+}
+
+void
+Stem::set_default_stemlen()
+{
+ if (!dir)
+ set_default_dir();
+
+ int stafftop = 2*staff_center;
+ stemlen = STEMLEN + (maxnote - minnote);
+
+ // uhh... how about non 5-line staffs?
+ if (maxnote < -2 && dir == 1){
+ int t = staff_center - staff_center/2;
+ stemlen = t - minnote +2;
+ } else if (minnote > stafftop + 2 && dir == -1) {
+ int t = staff_center + staff_center/2;
+ stemlen = maxnote -t +2;
+ }
+
+ assert(stemlen);
+}
+
+
+void
+Stem::set_default_extents()
+{
+ if (minnote > maxnote) {
+ warning("Empty stem. Ugh!", 0);
+ minnote = -10;
+ maxnote = 20;
+ }
+
+ if (!stemlen)
+ set_default_stemlen();
+
+ set_stemend((dir< 0) ? maxnote-stemlen: minnote +stemlen);
+ if (dir > 0){
+ stem_xoffset = paper()->note_width()-paper()->rule_thickness();
+ } else
+ stem_xoffset = 0;
+}
+
+void
+Stem::set_noteheads()
+{
+ if(!heads.size())
+ return;
+ heads.sort(Notehead::compare);
+ heads[0]->extremal = -1;
+ heads.top()->extremal = 1;
+ int parity=1;
+ int lastpos = heads[0]->position;
+ for (int i=1; i < heads.size(); i ++) {
+ int dy =abs(lastpos- heads[i]->position);
+
+ if (dy <= 1) {
+ if (parity)
+ heads[i]->x_dir = (stem_xoffset>0) ? 1:-1;
+ parity = !parity;
+ } else
+ parity = 0;
+ lastpos = heads[i]->position;
+ }
+}
+
+void
+Stem::do_pre_processing()
+{
+ if (bot == top)
+ set_default_extents();
+ set_noteheads();
+}
+
+
+Interval
+Stem::width()const
+{
+ if (!print_flag || abs(flag) <= 4)
+ return Interval(0,0); // TODO!
+ Paper_def*p= paper();
+ Interval r(p->lookup_p_->flag(flag).dim.x);
+ r+= stem_xoffset;
+ return r;
+}
+
+Molecule*
+Stem::brew_molecule_p()const return out;
+{
+ assert(bot!=top);
+
+
+ Paper_def *p =paper();
+
+ Real dy = p->internote();
+ Symbol ss =p->lookup_p_->stem(bot*dy,top*dy);
+
+
+ out = new Molecule(Atom(ss));
+
+ if (print_flag&&abs(flag) > 4){
+ Symbol fl = p->lookup_p_->flag(flag);
+ Molecule m(fl);
+ if (flag < -4){
+ out->add_bottom(m);
+ } else if (flag > 4) {
+ out->add_top(m);
+ } else
+ assert(false);
+ }
+
+ out->translate(Offset(stem_xoffset,0));
+}
+
+Real
+Stem::hindex()const
+{
+ return pcol_l_->hpos + stem_xoffset; // hmm. + offset_.x;
+}
+
+
--- /dev/null
+#include "symbol.hh"
+#include "varray.hh"
+
+
+Symbol::Symbol()
+ : dim(Interval(0,0),Interval(0,0))
+{
+ tex = "\\unknown";
+}
+Symbol::Symbol(String s, Box b)
+ : dim(b)
+{
+ tex = s;
+}
+
+
+String
+Symbol::str()const return s;
+{
+ s = "symbol(\'"+tex+"\', (" + dim.x.str() + ", " + dim.y.str() + "))";
+}
--- /dev/null
+#include "misc.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "real.hh"
+#include "symbol.hh"
+#include "assoc.hh"
+#include "assoc-iter.hh"
+#include "symtable.hh"
+
+Symtables::Symtables()
+{
+}
+
+Symtables::Symtables(Symtables const &s)
+{
+ for (Assoc_iter<String, Symtable*> i(s); i.ok(); i++) {
+ add(i.key(), new Symtable(*i.val()));
+ }
+}
+
+Symtables::~Symtables()
+{
+ for (Assoc_iter<String, Symtable*> i(*this); i.ok(); i++) {
+ delete i.val();
+ }
+}
+
+Symbol
+Symtable::lookup(String s) const
+{
+ if (elt_query(s))
+ return (*this)[s];
+ else {
+ error( "Unknown symbol `" +s+"'\n");
+ }
+ Symbol sy; // unreachable
+ return sy;
+}
+
+Symtable*
+Symtables::operator()(String s)
+{
+ return Assoc<String, Symtable*>::operator[](s);
+}
+void
+Symtables::print() const
+{
+ for (Assoc_iter<String, Symtable*> i(*this); i.ok(); i++) {
+ mtor << "table \'" << i.key() << "\' {\n";
+ i.val()->print();
+ mtor << "}\n";
+ }
+}
+void
+Symtable::print() const
+{
+ for (Assoc_iter<String, Symbol> i(*this); i.ok(); i++) {
+ mtor << "\'" << i.key() << "\'->" << i.val().str() << "\n";
+ }
+}
+
--- /dev/null
+/*
+ template2.cc -- instantiate some list templates.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "symbol.hh"
+#include "voice.hh"
+#include "voice-element.hh"
+#include "musicalrequest.hh"
+#include "staff.hh"
+#include "score-column.hh"
+#include "staff-column.hh"
+#include "spanner.hh"
+#include "plist.tcc"
+#include "pcursor.tcc"
+
+IPL_instantiate(Request);
+IPL_instantiate(Score_column);
+IPL_instantiate(Staff_column);
+IPL_instantiate(Staff);
+IPL_instantiate(Voice_element);
+IPL_instantiate(Voice);
+
+
--- /dev/null
+#include "request.hh"
+#include "input-score.hh"
+#include "input-staff.hh"
+#include "input-music.hh"
+#include "molecule.hh"
+#include "source-file.hh"
+#include "voice-element.hh"
+#include "plist.tcc"
+#include "pcursor.tcc"
+
+IPL_instantiate(Atom);
+IPL_instantiate(Atom);
+IPL_instantiate(Input_staff);
+IPL_instantiate(Input_music);
+IPL_instantiate(Source_file);
--- /dev/null
+/*
+ template4.cc -- instantiate PointerList baseclass.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "proto.hh"
+#include "list.tcc"
+#include "cursor.tcc"
+
+L_instantiate(void *);
--- /dev/null
+#include "proto.hh"
+#include "string.hh"
+#include "moment.hh"
+#include "real.hh"
+
+#include "interval.tcc"
+
+Interval__instantiate(Real);
+Interval__instantiate(Rational);
--- /dev/null
+#include "proto.hh"
+#include "plist.tcc"
+#include "register.hh"
+#include "voice-group-regs.hh"
+#include "voice-regs.hh"
+
+
+IPL_instantiate(Voice_registers);
+IPL_instantiate(Voice_group_registers);
+IPL_instantiate(Request_register);
--- /dev/null
+/*
+
+ Code to generate beams for TeX
+
+ */
+
+#include <math.h>
+#include "symbol.hh"
+#include "molecule.hh"
+#include "tex.hh"
+#include "symtable.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "lookup.hh"
+
+Symbol
+Lookup::beam_element(int sidx, int widx, Real slope)
+{
+ Symbol bs=(*symtables_)("beamslopes")->lookup("slope");
+
+ Array<String> args;
+ args.push(sidx);
+ args.push(widx);
+ bs.tex = substitute_args(bs.tex,args);
+ int w = 2 << widx;
+ Real width = w PT;
+ bs.dim.x = Interval(0,width);
+ bs.dim.y = Interval(0,width*slope);
+ return bs;
+}
+
+// ugh.. hard wired tex-code.
+static int
+slope_index(Real &s)
+{
+ if (abs(s) > 0.5) {
+ WARN << "beam steeper than 0.5 (" << s << ")\n";
+ s = sign(s) * 0.5;
+ }
+
+ int i = int(rint(s * 20.0));
+
+ s = i/20.0;
+ if (s>0)
+ return 6*i +122;
+ else
+ return -6 * i+ 186;
+}
+
+Symbol
+Lookup::rule_symbol(Real height, Real width)
+{
+ Symbol bs=(*symtables_)("beamslopes")->lookup("horizontal");
+ Array<String> args;
+ args.push(print_dimen(height));
+ args.push(print_dimen(width));
+ bs.tex = substitute_args(bs.tex,args);
+ bs.dim.x = Interval(0,width);
+ bs.dim.y = Interval(0,height);
+ return bs;
+}
+
+Symbol
+Lookup::beam(Real &slope, Real width)
+{
+ int sidx = slope_index(slope);
+ if (!slope)
+ return rule_symbol(2 PT, width);
+ if (width < 2 PT) {
+ WARN<<"Beam too narrow. (" << print_dimen(width) <<")\n";
+ width = 2 PT;
+ }
+ Real elemwidth = 64 PT;
+ int widx = 5;
+
+ Molecule m;
+
+ while (elemwidth > width) {
+ widx --;
+ elemwidth /= 2.0;
+ }
+ Real overlap = elemwidth/4;
+ Real last_x = width - elemwidth;
+ Real x = overlap;
+ Atom elem(beam_element(sidx, widx, slope));
+ Atom a(elem);
+ m.add(a);
+ while (x < last_x) {
+ a=elem;
+ a.translate(Offset(x-overlap, (x-overlap)*slope));
+ m.add(a);
+ x += elemwidth - overlap;
+ }
+ a=elem;
+ a.translate(Offset(last_x, (last_x) * slope));
+ m.add(a);
+
+ Symbol ret;
+ ret.tex = m.TeXstring();
+ ret.dim.y = Interval(0,width*slope);
+ ret.dim.x = Interval(0,width);
+
+ return ret;
+}
+
+
--- /dev/null
+#include <math.h>
+#include "misc.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "dimen.hh"
+#include "debug.hh"
+
+static
+char direction_char(int y_sign)
+{
+ char c='#';
+ switch(y_sign){
+ case -1:
+ c = 'd';
+ break;
+ case 0:
+ c = 'h';
+ break;
+ case 1:
+ c = 'u';
+ break;
+ default:
+ assert(false);
+ }
+ return c;
+}
+
+Symbol
+Lookup::half_slur_middlepart(Real &dx, int dir)
+{
+ if (dx >= 400 PT) {// todo
+ WARN<<"halfslur too large" <<print_dimen(dx)<< "shrinking (ugh)\n";
+ dx = 400 PT;
+ }
+ int widx = int(floor(dx / 4.0));
+ dx = widx * 4.0;
+ if (widx) widx --;
+ else {
+ WARN << "slur too narrow\n";
+ }
+
+ Symbol s;
+
+ s.dim.y = Interval(min(0,0), max(0,0)); // todo
+ s.dim.x = Interval(0,dx);
+
+ String f = String("\\hslurchar");
+ f += direction_char(0);
+
+ int idx = widx;
+ if (dir < 0)
+ idx += 128;
+
+
+ f+=String( "{" ) + String( idx ) + "}";
+ s.tex = f;
+ Atom a(s);
+ a.translate(Offset(dx/2,0));
+ s.tex = a.TeXstring();
+
+ return s;
+}
+Symbol
+Lookup::half_slur(int dy, Real &dx, int dir, int xpart)
+{
+ Real orig_dx = dx;
+ if (!xpart)
+ return half_slur_middlepart(dx, dir);
+
+ int widx;
+
+ if (dx >= 96 PT) {
+ WARN << "Slur half too wide." << print_dimen(orig_dx) << " shrinking (ugh)\n";
+ dx = 96 PT;
+ }
+
+ widx = int(rint(dx/12.0));
+ dx = widx*12.0;
+ if (widx)
+ widx --;
+ else {
+ WARN << "slur too narrow " << print_dimen(orig_dx)<<"\n";
+ }
+
+ Symbol s;
+ s.dim.x = Interval(0,dx);
+ s.dim.y = Interval(min(0,dy), max(0,dy));
+
+
+ String f = String("\\hslurchar");
+
+ f+= direction_char(dir);
+
+ int hidx = dy;
+ if (hidx <0)
+ hidx = -hidx;
+ hidx --;
+ int idx =-1;
+
+
+ idx = widx * 16 + hidx;
+ if (xpart < 0)
+ idx += 128;
+
+ f+=String( "{" ) + String( idx ) + "}";
+
+
+ s.tex = f;
+
+ return s;
+}
+
+Symbol
+Lookup::slur (int dy , Real &dx, int dir)
+{
+ assert(dx >=0 && abs(dir) <= 1);
+ int y_sign = sign(dy);
+
+ bool large = dy > 16;
+
+ if (y_sign) {
+ large |= dx>= 4*16 PT;
+ } else
+ large |= dx>= 4*54 PT;
+
+ if (large) {
+ return big_slur(dy, dx, dir);
+ }
+ Real orig_dx = dx;
+ int widx = int(floor(dx/4.0)); // slurs better too small..
+ dx = 4.0 * widx;
+ if (widx)
+ widx --;
+ else {
+ WARN << "slur too narrow: " << print_dimen(orig_dx) << "\n";
+ }
+
+ int hidx = dy;
+ if (hidx <0)
+ hidx = -hidx;
+ hidx --;
+ if (hidx > 16) {
+ WARN<<"slur to steep: " << dy << " shrinking (ugh)\n";
+ }
+
+ Symbol s;
+ s.dim.x = Interval(0,dx);
+ s.dim.y = Interval(min(0,dy), max(0,dy));
+
+ String f = String("\\slurchar") + String( direction_char(y_sign) );
+
+ int idx=-1;
+ if (y_sign) {
+ idx = hidx * 16 + widx;
+ if (dir < 0)
+ idx += 128;
+ } else {
+ if (dx >= 4*54 PT) {
+ WARN << "slur too wide: " << print_dimen(dx) <<
+ " shrinking (ugh)\n";
+ dx = 4*54 PT;
+ }
+ idx = widx;
+ if (dir < 0)
+ idx += 54;
+ }
+
+ f+=String( "{" ) + String( idx ) + "}";
+ s.tex = f;
+
+ Atom a(s);
+ a.translate(Offset(dx/2,0));
+ s.dim = a.extent();
+ s.tex = a.TeXstring();
+ return s;
+}
+
+Symbol
+Lookup::big_slur(int dy , Real &dx, int dir)
+{
+ assert(dx >= 24 PT);
+ Real slur_extra =abs(dy) /2.0 + 2;
+ int l_dy = int(Real (dy)/2 + slur_extra*dir);
+ int r_dy = dy - l_dy;
+
+ Real left_wid = dx/4.0;
+ Real right_wid = left_wid;
+
+ Atom l = half_slur(l_dy, left_wid, dir, -1);
+ Atom r = half_slur(r_dy, right_wid, dir, 1);
+ Real mid_wid = dx - left_wid - right_wid;
+
+ Atom m = half_slur(0, mid_wid, dir, 0);
+
+ Molecule mol;
+ mol.add(l);
+ Atom a(m);
+ a.translate(Offset(0,slur_extra * internote()));
+ mol.add_right(m);
+ mol.add_right(r);
+ mol.translate(Offset(0, l_dy * internote()));
+ Symbol s;
+ s.tex = mol.TeXstring();
+ s.dim = mol.extent();
+ return s;
+}
+
+
--- /dev/null
+#include "dimen.hh"
+#include "tex.hh"
+#include "symbol.hh"
+#include "const.hh"
+#include "varray.hh"
+
+String
+vstrut(Real h)
+{
+ return String("\\vrule height ") + print_dimen(h) + "depth 0pt width 0pt";
+}
+
+
+static void
+substitute_arg(String& r, String arg)
+{
+ int p = r.index_i('%');
+ if (p < 0)
+ return ;
+
+ r = r.left_str(p) + arg + r.right_str(r.length_i() - p -1);
+}
+
+
+String
+substitute_args(String source, Array<String> args)
+{
+ String retval (source);
+ for (int i = 0 ; i < args.size(); i++)
+ substitute_arg(retval, args[i]);
+ while (retval.index_i('%') >= 0)
+ substitute_arg(retval, "");
+ return retval;
+}
+
+String
+substitute_args(String source, Array<Scalar> args)
+{
+ Array<String> sv;
+ for (int i = 0 ; i < args.size(); i++)
+ sv.push(args[i]);
+
+ return substitute_args(source, sv);
+}
--- /dev/null
+#include "debug.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "molecule.hh"
+#include "text-def.hh"
+
+Text_def::Text_def()
+{
+ align_i_ = 1; // right
+ style_str_ = "roman";
+ defined_ch_c_l_ = 0;
+}
+bool
+Text_def::compare(const Text_def&def)
+{
+ return align_i_ == def.align_i_ && text_str_ == def.text_str_
+ && style_str_ == def.style_str_;
+}
+
+Atom
+Text_def::create_atom(Paper_def*p) const
+{
+ return p->lookup_p_->text(style_str_, text_str_, -align_i_);
+}
+
+void
+Text_def::print() const
+{
+ mtor << "Text `" << text_str_ << "\', style " <<
+ style_str_ << "align " << align_i_ << '\n';
+}
--- /dev/null
+#include "version.hh"
+#include "fversion.hh"
+
+static char *s = "LilyPond " VERSIONSTR "/FlowerLib " FVERSIONSTR
+". Compile: " __DATE__ ", " __TIME__ " (" COMPILER ")\n";
+
+const char *
+get_version()
+{
+ return s;
+}
--- /dev/null
+#include "break.hh"
+#include "pscore.hh"
+#include "debug.hh"
+
+/** el stupido. This should be done more accurately:
+
+ It would be nice to have a Dynamic Programming type of algorithm
+ similar to TeX's
+
+ */
+Array<Col_hpositions>
+Word_wrap::solve()
+{
+ problem_OK();
+ iter_top(pscore_.cols,curcol);
+ Array<Col_hpositions> breaking;
+ Line_of_cols breakpoints(find_breaks());
+ assert(breakpoints.size()>=2);
+
+ int break_idx_i=0;
+ while ( break_idx_i < breakpoints.size() -1) {
+ Col_hpositions minimum;
+ Col_hpositions current;
+
+ // do another line
+ PCol *post = breakpoints[break_idx_i]->postbreak_p_;
+ current.add( post);
+ curcol++; // skip the breakable.
+ break_idx_i++;
+
+ while (break_idx_i < breakpoints.size()) {
+
+ // add another measure.
+ while (breakpoints[break_idx_i] != curcol.ptr()){
+ current.add(curcol);
+ curcol++;
+ }
+ current.add(breakpoints[break_idx_i]->prebreak_p_ );
+
+ // try to solve
+ if (!feasible(current.cols)) {
+ if (!minimum.cols.size())
+ error("sorry, this measure is too long, breakpoint: "
+ + String(break_idx_i) );
+ current.energy = INFTY; // make sure we go back
+ } else {
+ current = solve_line(current.cols);
+ current.print();
+ }
+
+ // update minimum, or backup.
+ if (current.energy < minimum.energy) {
+ minimum = current;
+ } else { // we're one col too far.
+ break_idx_i--;
+ while (curcol.ptr() != breakpoints[break_idx_i])
+ curcol --;
+ break; // do the next line.
+ }
+
+
+ // add nobreak version of breakable column
+ current.cols.top()=breakpoints[break_idx_i];
+ curcol ++;
+ break_idx_i++;
+ }
+
+ *mlog << "[" <<break_idx_i<<"]"<<flush;
+ breaking.push(minimum);
+ }
+
+ return breaking;
+}
+
+Word_wrap::Word_wrap(PScore&ps)
+ : Break_algorithm(ps)
+{
+}