]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-0.0.39
authorfred <fred>
Tue, 4 Mar 1997 19:42:17 +0000 (19:42 +0000)
committerfred <fred>
Tue, 4 Mar 1997 19:42:17 +0000 (19:42 +0000)
143 files changed:
bin/genheader [new file with mode: 0755]
lib/include/input-file.hh [new file with mode: 0644]
lib/include/source-file.hh [new file with mode: 0644]
lib/input-file.cc [new file with mode: 0644]
lib/source.cc [new file with mode: 0644]
lily/bar-reg.cc [new file with mode: 0644]
lily/bar.cc [new file with mode: 0644]
lily/beam.cc [new file with mode: 0644]
lily/boxes.cc [new file with mode: 0644]
lily/break.cc [new file with mode: 0644]
lily/calcideal.cc [new file with mode: 0644]
lily/clef-item.cc [new file with mode: 0644]
lily/clef-reg.cc [new file with mode: 0644]
lily/colhpos.cc [new file with mode: 0644]
lily/commandrequest.cc [new file with mode: 0644]
lily/complex-staff.cc [new file with mode: 0644]
lily/debug.cc [new file with mode: 0644]
lily/dimen.cc [new file with mode: 0644]
lily/directional-spanner.cc [new file with mode: 0644]
lily/grouping.cc [new file with mode: 0644]
lily/headreg.cc [new file with mode: 0644]
lily/idealspacing.cc [new file with mode: 0644]
lily/identifier.cc [new file with mode: 0644]
lily/include/bar-reg.hh [new file with mode: 0644]
lily/include/bar.hh [new file with mode: 0644]
lily/include/beam.hh [new file with mode: 0644]
lily/include/class-name.hh [new file with mode: 0644]
lily/include/clef-item.hh [new file with mode: 0644]
lily/include/clef-reg.hh [new file with mode: 0644]
lily/include/complex-staff.hh [new file with mode: 0644]
lily/include/complex-walker.hh [new file with mode: 0644]
lily/include/directional-spanner.hh [new file with mode: 0644]
lily/include/grouping.hh [new file with mode: 0644]
lily/include/headreg.hh [new file with mode: 0644]
lily/include/identifier.hh [new file with mode: 0644]
lily/include/identparent.hh [new file with mode: 0644]
lily/include/input-music.hh [new file with mode: 0644]
lily/include/input-score.hh [new file with mode: 0644]
lily/include/input-staff.hh [new file with mode: 0644]
lily/include/item.hh [new file with mode: 0644]
lily/include/key-item.hh [new file with mode: 0644]
lily/include/key-reg.hh [new file with mode: 0644]
lily/include/lexer.hh [new file with mode: 0644]
lily/include/local-key-item.hh [new file with mode: 0644]
lily/include/local-key-reg.hh [new file with mode: 0644]
lily/include/lookup.hh [new file with mode: 0644]
lily/include/lyric-walker.hh [new file with mode: 0644]
lily/include/meter-reg.hh [new file with mode: 0644]
lily/include/meter.hh [new file with mode: 0644]
lily/include/midi-def.hh [new file with mode: 0644]
lily/include/midi-walker.hh [new file with mode: 0644]
lily/include/notehead.hh [new file with mode: 0644]
lily/include/paper-def.hh [new file with mode: 0644]
lily/include/pscore.hh [new file with mode: 0644]
lily/include/pstaff.hh [new file with mode: 0644]
lily/include/register.hh [new file with mode: 0644]
lily/include/registergroup.hh [new file with mode: 0644]
lily/include/request.hh [new file with mode: 0644]
lily/include/rest.hh [new file with mode: 0644]
lily/include/score-walker.hh [new file with mode: 0644]
lily/include/score.hh [new file with mode: 0644]
lily/include/script-def.hh [new file with mode: 0644]
lily/include/script-reg.hh [new file with mode: 0644]
lily/include/script.hh [new file with mode: 0644]
lily/include/slur-reg.hh [new file with mode: 0644]
lily/include/slur.hh [new file with mode: 0644]
lily/include/spanner.hh [new file with mode: 0644]
lily/include/staff-column.hh [new file with mode: 0644]
lily/include/staff-elem-info.hh [new file with mode: 0644]
lily/include/staff-elem.hh [new file with mode: 0644]
lily/include/staff-walker.hh [new file with mode: 0644]
lily/include/staff.hh [new file with mode: 0644]
lily/include/staffsym.hh [new file with mode: 0644]
lily/include/stem-beam-reg.hh [new file with mode: 0644]
lily/include/stem.hh [new file with mode: 0644]
lily/include/symbol.hh [new file with mode: 0644]
lily/include/symtable.hh [new file with mode: 0644]
lily/include/text-def.hh [new file with mode: 0644]
lily/include/text-item.hh [new file with mode: 0644]
lily/include/text-reg.hh [new file with mode: 0644]
lily/include/text-spanner.hh [new file with mode: 0644]
lily/include/voice-element.hh [new file with mode: 0644]
lily/include/voice-group-regs.hh [new file with mode: 0644]
lily/include/voice-regs.hh [new file with mode: 0644]
lily/include/voice.hh [new file with mode: 0644]
lily/include/walk-regs.hh [new file with mode: 0644]
lily/input-music.cc [new file with mode: 0644]
lily/input-score.cc [new file with mode: 0644]
lily/item.cc [new file with mode: 0644]
lily/key-item.cc [new file with mode: 0644]
lily/key-reg.cc [new file with mode: 0644]
lily/key.cc [new file with mode: 0644]
lily/keyword.cc [new file with mode: 0644]
lily/leastsquares.cc [new file with mode: 0644]
lily/lexerinit.cc [new file with mode: 0644]
lily/linespace.cc [new file with mode: 0644]
lily/local-key-item.cc [new file with mode: 0644]
lily/lookup.cc [new file with mode: 0644]
lily/meter-reg.cc [new file with mode: 0644]
lily/meter.cc [new file with mode: 0644]
lily/midi-walker.cc [new file with mode: 0644]
lily/misc.cc [new file with mode: 0644]
lily/molecule.cc [new file with mode: 0644]
lily/mylexer.cc [new file with mode: 0644]
lily/note.cc [new file with mode: 0644]
lily/notehead.cc [new file with mode: 0644]
lily/notename.cc [new file with mode: 0644]
lily/paper-def.cc [new file with mode: 0644]
lily/pcol.cc [new file with mode: 0644]
lily/pscore.cc [new file with mode: 0644]
lily/pstaff.cc [new file with mode: 0644]
lily/qlp.cc [new file with mode: 0644]
lily/qlpsolve.cc [new file with mode: 0644]
lily/register.cc [new file with mode: 0644]
lily/request.cc [new file with mode: 0644]
lily/rest.cc [new file with mode: 0644]
lily/score-column.cc [new file with mode: 0644]
lily/score.cc [new file with mode: 0644]
lily/scoreline.cc [new file with mode: 0644]
lily/scores.cc [new file with mode: 0644]
lily/script-def.cc [new file with mode: 0644]
lily/script-reg.cc [new file with mode: 0644]
lily/script.cc [new file with mode: 0644]
lily/slur.cc [new file with mode: 0644]
lily/spanner.cc [new file with mode: 0644]
lily/staff-elem-info.cc [new file with mode: 0644]
lily/staff-elem.cc [new file with mode: 0644]
lily/staffline.cc [new file with mode: 0644]
lily/staffsym.cc [new file with mode: 0644]
lily/stem.cc [new file with mode: 0644]
lily/symbol.cc [new file with mode: 0644]
lily/symtable.cc [new file with mode: 0644]
lily/template2.cc [new file with mode: 0644]
lily/template3.cc [new file with mode: 0644]
lily/template4.cc [new file with mode: 0644]
lily/template5.cc [new file with mode: 0644]
lily/template6.cc [new file with mode: 0644]
lily/tex-beam.cc [new file with mode: 0644]
lily/tex-slur.cc [new file with mode: 0644]
lily/tex.cc [new file with mode: 0644]
lily/text-def.cc [new file with mode: 0644]
lily/version.cc [new file with mode: 0644]
lily/wordwrap.cc [new file with mode: 0644]

diff --git a/bin/genheader b/bin/genheader
new file mode 100755 (executable)
index 0000000..7c36afe
--- /dev/null
@@ -0,0 +1,31 @@
+#!/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;
+
+
+
diff --git a/lib/include/input-file.hh b/lib/include/input-file.hh
new file mode 100644 (file)
index 0000000..a01ea75
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  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
diff --git a/lib/include/source-file.hh b/lib/include/source-file.hh
new file mode 100644 (file)
index 0000000..7f7168e
--- /dev/null
@@ -0,0 +1,40 @@
+//
+//  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 //
diff --git a/lib/input-file.cc b/lib/input-file.cc
new file mode 100644 (file)
index 0000000..a0f1018
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+  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;  
+}
diff --git a/lib/source.cc b/lib/source.cc
new file mode 100644 (file)
index 0000000..8a8c528
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// 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;
+}
diff --git a/lily/bar-reg.cc b/lily/bar-reg.cc
new file mode 100644 (file)
index 0000000..b72eca8
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  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;
+}
diff --git a/lily/bar.cc b/lily/bar.cc
new file mode 100644 (file)
index 0000000..32a7cd5
--- /dev/null
@@ -0,0 +1,28 @@
+#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;
+}
+    
diff --git a/lily/beam.cc b/lily/beam.cc
new file mode 100644 (file)
index 0000000..64f3e3c
--- /dev/null
@@ -0,0 +1,295 @@
+#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()
+{
+
+}
diff --git a/lily/boxes.cc b/lily/boxes.cc
new file mode 100644 (file)
index 0000000..f83f765
--- /dev/null
@@ -0,0 +1,15 @@
+#include "boxes.hh"
+#include "const.hh"
+#include "varray.hh"
+
+
+Box::Box()
+{        
+}
+
+Box::Box(Interval ix, Interval iy)
+{
+    x = ix;
+    y = iy;
+}
+
diff --git a/lily/break.cc b/lily/break.cc
new file mode 100644 (file)
index 0000000..7d21918
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+    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
+}
diff --git a/lily/calcideal.cc b/lily/calcideal.cc
new file mode 100644 (file)
index 0000000..5ead08d
--- /dev/null
@@ -0,0 +1,53 @@
+#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.
+    }
+}
+
+
diff --git a/lily/clef-item.cc b/lily/clef-item.cc
new file mode 100644 (file)
index 0000000..528623e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  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;
+}
+
diff --git a/lily/clef-reg.cc b/lily/clef-reg.cc
new file mode 100644 (file)
index 0000000..2d9dcc1
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+  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");
+    }
+}
diff --git a/lily/colhpos.cc b/lily/colhpos.cc
new file mode 100644 (file)
index 0000000..530e4d4
--- /dev/null
@@ -0,0 +1,35 @@
+#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
+}
diff --git a/lily/commandrequest.cc b/lily/commandrequest.cc
new file mode 100644 (file)
index 0000000..5cf0912
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+  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];
+}
diff --git a/lily/complex-staff.cc b/lily/complex-staff.cc
new file mode 100644 (file)
index 0000000..bb13274
--- /dev/null
@@ -0,0 +1,37 @@
+#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);
+}
diff --git a/lily/debug.cc b/lily/debug.cc
new file mode 100644 (file)
index 0000000..01a35bd
--- /dev/null
@@ -0,0 +1,59 @@
+#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;
+}
+
+
diff --git a/lily/dimen.cc b/lily/dimen.cc
new file mode 100644 (file)
index 0000000..9489ae9
--- /dev/null
@@ -0,0 +1,39 @@
+#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;
+}
diff --git a/lily/directional-spanner.cc b/lily/directional-spanner.cc
new file mode 100644 (file)
index 0000000..7e2bb7c
--- /dev/null
@@ -0,0 +1,6 @@
+#include "directional-spanner.hh"
+
+Directional_spanner::Directional_spanner()
+{
+    dir_i_ = 0;
+}
diff --git a/lily/grouping.cc b/lily/grouping.cc
new file mode 100644 (file)
index 0000000..bc665a1
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+  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);
+}
+
diff --git a/lily/headreg.cc b/lily/headreg.cc
new file mode 100644 (file)
index 0000000..dc5d72d
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+  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;
+}
diff --git a/lily/idealspacing.cc b/lily/idealspacing.cc
new file mode 100644 (file)
index 0000000..3ceaff1
--- /dev/null
@@ -0,0 +1,31 @@
+#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    
+}
diff --git a/lily/identifier.cc b/lily/identifier.cc
new file mode 100644 (file)
index 0000000..59f1ff5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+  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";
+}
diff --git a/lily/include/bar-reg.hh b/lily/include/bar-reg.hh
new file mode 100644 (file)
index 0000000..c73e5d1
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+  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
diff --git a/lily/include/bar.hh b/lily/include/bar.hh
new file mode 100644 (file)
index 0000000..3727358
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+  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
+
diff --git a/lily/include/beam.hh b/lily/include/beam.hh
new file mode 100644 (file)
index 0000000..8eb2f14
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+  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
+
diff --git a/lily/include/class-name.hh b/lily/include/class-name.hh
new file mode 100644 (file)
index 0000000..26da52d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  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
diff --git a/lily/include/clef-item.hh b/lily/include/clef-item.hh
new file mode 100644 (file)
index 0000000..341204f
--- /dev/null
@@ -0,0 +1,31 @@
+
+/*
+  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
+
+
diff --git a/lily/include/clef-reg.hh b/lily/include/clef-reg.hh
new file mode 100644 (file)
index 0000000..cc3a8a9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  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
+
diff --git a/lily/include/complex-staff.hh b/lily/include/complex-staff.hh
new file mode 100644 (file)
index 0000000..0a37e3a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  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
+
diff --git a/lily/include/complex-walker.hh b/lily/include/complex-walker.hh
new file mode 100644 (file)
index 0000000..861cee7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+  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
+
+
diff --git a/lily/include/directional-spanner.hh b/lily/include/directional-spanner.hh
new file mode 100644 (file)
index 0000000..9399b71
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  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
+
diff --git a/lily/include/grouping.hh b/lily/include/grouping.hh
new file mode 100644 (file)
index 0000000..06b4421
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+  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
diff --git a/lily/include/headreg.hh b/lily/include/headreg.hh
new file mode 100644 (file)
index 0000000..eaa2d6f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  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
diff --git a/lily/include/identifier.hh b/lily/include/identifier.hh
new file mode 100644 (file)
index 0000000..1aa7f7d
--- /dev/null
@@ -0,0 +1,42 @@
+
+/*
+  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
+
diff --git a/lily/include/identparent.hh b/lily/include/identparent.hh
new file mode 100644 (file)
index 0000000..3e6d566
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+  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
+
+
+
diff --git a/lily/include/input-music.hh b/lily/include/input-music.hh
new file mode 100644 (file)
index 0000000..1d7a8ca
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+  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
diff --git a/lily/include/input-score.hh b/lily/include/input-score.hh
new file mode 100644 (file)
index 0000000..4286f4b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+  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
diff --git a/lily/include/input-staff.hh b/lily/include/input-staff.hh
new file mode 100644 (file)
index 0000000..3b874a1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  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
+
diff --git a/lily/include/item.hh b/lily/include/item.hh
new file mode 100644 (file)
index 0000000..d1fc8c8
--- /dev/null
@@ -0,0 +1,32 @@
+#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
diff --git a/lily/include/key-item.hh b/lily/include/key-item.hh
new file mode 100644 (file)
index 0000000..e56af8e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+  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
diff --git a/lily/include/key-reg.hh b/lily/include/key-reg.hh
new file mode 100644 (file)
index 0000000..d8a96d0
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  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
diff --git a/lily/include/lexer.hh b/lily/include/lexer.hh
new file mode 100644 (file)
index 0000000..6a9d21a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+  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
diff --git a/lily/include/local-key-item.hh b/lily/include/local-key-item.hh
new file mode 100644 (file)
index 0000000..96bad99
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  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
+
diff --git a/lily/include/local-key-reg.hh b/lily/include/local-key-reg.hh
new file mode 100644 (file)
index 0000000..d0a2867
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  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
diff --git a/lily/include/lookup.hh b/lily/include/lookup.hh
new file mode 100644 (file)
index 0000000..524cdf1
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+  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
diff --git a/lily/include/lyric-walker.hh b/lily/include/lyric-walker.hh
new file mode 100644 (file)
index 0000000..1a80523
--- /dev/null
@@ -0,0 +1,28 @@
+//
+//  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
+
+
diff --git a/lily/include/meter-reg.hh b/lily/include/meter-reg.hh
new file mode 100644 (file)
index 0000000..6ebe18c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+  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
diff --git a/lily/include/meter.hh b/lily/include/meter.hh
new file mode 100644 (file)
index 0000000..928434b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+  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
+
diff --git a/lily/include/midi-def.hh b/lily/include/midi-def.hh
new file mode 100644 (file)
index 0000000..7a559ad
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+  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 //
+
diff --git a/lily/include/midi-walker.hh b/lily/include/midi-walker.hh
new file mode 100644 (file)
index 0000000..e7c2638
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+  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
+
+
diff --git a/lily/include/notehead.hh b/lily/include/notehead.hh
new file mode 100644 (file)
index 0000000..d7a68e7
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+  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
+
diff --git a/lily/include/paper-def.hh b/lily/include/paper-def.hh
new file mode 100644 (file)
index 0000000..ae55725
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  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
+
diff --git a/lily/include/pscore.hh b/lily/include/pscore.hh
new file mode 100644 (file)
index 0000000..b7ad49c
--- /dev/null
@@ -0,0 +1,106 @@
+// 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
diff --git a/lily/include/pstaff.hh b/lily/include/pstaff.hh
new file mode 100644 (file)
index 0000000..50a7f0c
--- /dev/null
@@ -0,0 +1,25 @@
+#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
diff --git a/lily/include/register.hh b/lily/include/register.hh
new file mode 100644 (file)
index 0000000..da80db3
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+  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
+
diff --git a/lily/include/registergroup.hh b/lily/include/registergroup.hh
new file mode 100644 (file)
index 0000000..6d6e76a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  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
+
+
diff --git a/lily/include/request.hh b/lily/include/request.hh
new file mode 100644 (file)
index 0000000..1936d5a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+  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
diff --git a/lily/include/rest.hh b/lily/include/rest.hh
new file mode 100644 (file)
index 0000000..85c7266
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  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 
+
diff --git a/lily/include/score-walker.hh b/lily/include/score-walker.hh
new file mode 100644 (file)
index 0000000..b3d3042
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  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
diff --git a/lily/include/score.hh b/lily/include/score.hh
new file mode 100644 (file)
index 0000000..a865ed0
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+  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
diff --git a/lily/include/script-def.hh b/lily/include/script-def.hh
new file mode 100644 (file)
index 0000000..8b5be32
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  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
+
diff --git a/lily/include/script-reg.hh b/lily/include/script-reg.hh
new file mode 100644 (file)
index 0000000..33592ca
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+  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
diff --git a/lily/include/script.hh b/lily/include/script.hh
new file mode 100644 (file)
index 0000000..df408f0
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+  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
+
diff --git a/lily/include/slur-reg.hh b/lily/include/slur-reg.hh
new file mode 100644 (file)
index 0000000..e357c87
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  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
diff --git a/lily/include/slur.hh b/lily/include/slur.hh
new file mode 100644 (file)
index 0000000..87f1fe8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  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
+
+
diff --git a/lily/include/spanner.hh b/lily/include/spanner.hh
new file mode 100644 (file)
index 0000000..43a3567
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  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
diff --git a/lily/include/staff-column.hh b/lily/include/staff-column.hh
new file mode 100644 (file)
index 0000000..dd6303e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+  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
+
diff --git a/lily/include/staff-elem-info.hh b/lily/include/staff-elem-info.hh
new file mode 100644 (file)
index 0000000..9c6264a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+  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
diff --git a/lily/include/staff-elem.hh b/lily/include/staff-elem.hh
new file mode 100644 (file)
index 0000000..e2fce84
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+  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
+
diff --git a/lily/include/staff-walker.hh b/lily/include/staff-walker.hh
new file mode 100644 (file)
index 0000000..fb0d098
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+  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
+
diff --git a/lily/include/staff.hh b/lily/include/staff.hh
new file mode 100644 (file)
index 0000000..959859b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+  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
diff --git a/lily/include/staffsym.hh b/lily/include/staffsym.hh
new file mode 100644 (file)
index 0000000..bcec2bf
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+  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
diff --git a/lily/include/stem-beam-reg.hh b/lily/include/stem-beam-reg.hh
new file mode 100644 (file)
index 0000000..dddba26
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  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
diff --git a/lily/include/stem.hh b/lily/include/stem.hh
new file mode 100644 (file)
index 0000000..34776ea
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+  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
diff --git a/lily/include/symbol.hh b/lily/include/symbol.hh
new file mode 100644 (file)
index 0000000..c166fa5
--- /dev/null
@@ -0,0 +1,17 @@
+#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
diff --git a/lily/include/symtable.hh b/lily/include/symtable.hh
new file mode 100644 (file)
index 0000000..f96d02c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  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
+
diff --git a/lily/include/text-def.hh b/lily/include/text-def.hh
new file mode 100644 (file)
index 0000000..cc9c3c9
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+  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
+
diff --git a/lily/include/text-item.hh b/lily/include/text-item.hh
new file mode 100644 (file)
index 0000000..ae0b556
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+  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
+
diff --git a/lily/include/text-reg.hh b/lily/include/text-reg.hh
new file mode 100644 (file)
index 0000000..59317e5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  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
diff --git a/lily/include/text-spanner.hh b/lily/include/text-spanner.hh
new file mode 100644 (file)
index 0000000..dbdea97
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  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
+
diff --git a/lily/include/voice-element.hh b/lily/include/voice-element.hh
new file mode 100644 (file)
index 0000000..0c5b6b1
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  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
diff --git a/lily/include/voice-group-regs.hh b/lily/include/voice-group-regs.hh
new file mode 100644 (file)
index 0000000..7c1b4ed
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+  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
diff --git a/lily/include/voice-regs.hh b/lily/include/voice-regs.hh
new file mode 100644 (file)
index 0000000..82070a7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+  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
diff --git a/lily/include/voice.hh b/lily/include/voice.hh
new file mode 100644 (file)
index 0000000..06e6e1d
--- /dev/null
@@ -0,0 +1,35 @@
+#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
diff --git a/lily/include/walk-regs.hh b/lily/include/walk-regs.hh
new file mode 100644 (file)
index 0000000..643ce57
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+  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
diff --git a/lily/input-music.cc b/lily/input-music.cc
new file mode 100644 (file)
index 0000000..f1047e8
--- /dev/null
@@ -0,0 +1,252 @@
+#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;    
+}
+
diff --git a/lily/input-score.cc b/lily/input-score.cc
new file mode 100644 (file)
index 0000000..f39d47a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+  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
+}
diff --git a/lily/item.cc b/lily/item.cc
new file mode 100644 (file)
index 0000000..e653c46
--- /dev/null
@@ -0,0 +1,18 @@
+#include "debug.hh"
+#include "item.hh"
+
+
+
+Item::Item()
+{
+    pcol_l_ = 0;
+}
+
+void
+Item::do_print() const
+{
+#ifndef NPRINT
+    mtor << "(unknown)";
+#endif
+}
+
diff --git a/lily/key-item.cc b/lily/key-item.cc
new file mode 100644 (file)
index 0000000..963b1bc
--- /dev/null
@@ -0,0 +1,70 @@
+#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;
+}
diff --git a/lily/key-reg.cc b/lily/key-reg.cc
new file mode 100644 (file)
index 0000000..84b0e26
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+  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;
+}
diff --git a/lily/key.cc b/lily/key.cc
new file mode 100644 (file)
index 0000000..7e23464
--- /dev/null
@@ -0,0 +1,38 @@
+#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;
+}
+
diff --git a/lily/keyword.cc b/lily/keyword.cc
new file mode 100644 (file)
index 0000000..14903cf
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  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 */
+}
+
diff --git a/lily/leastsquares.cc b/lily/leastsquares.cc
new file mode 100644 (file)
index 0000000..cf9ec47
--- /dev/null
@@ -0,0 +1,35 @@
+#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;
+       
+}
diff --git a/lily/lexerinit.cc b/lily/lexerinit.cc
new file mode 100644 (file)
index 0000000..2eb9ed4
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+  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;      
+}
diff --git a/lily/linespace.cc b/lily/linespace.cc
new file mode 100644 (file)
index 0000000..a7bfa1d
--- /dev/null
@@ -0,0 +1,288 @@
+#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;
+}
diff --git a/lily/local-key-item.cc b/lily/local-key-item.cc
new file mode 100644 (file)
index 0000000..4259821
--- /dev/null
@@ -0,0 +1,93 @@
+#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);
+};
diff --git a/lily/lookup.cc b/lily/lookup.cc
new file mode 100644 (file)
index 0000000..ffd668e
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+  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;
+}
diff --git a/lily/meter-reg.cc b/lily/meter-reg.cc
new file mode 100644 (file)
index 0000000..a27737c
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+  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;
+}
diff --git a/lily/meter.cc b/lily/meter.cc
new file mode 100644 (file)
index 0000000..94f6b6c
--- /dev/null
@@ -0,0 +1,18 @@
+#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));
+}
+
diff --git a/lily/midi-walker.cc b/lily/midi-walker.cc
new file mode 100644 (file)
index 0000000..801ba32
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+  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
+}
diff --git a/lily/misc.cc b/lily/misc.cc
new file mode 100644 (file)
index 0000000..093af7f
--- /dev/null
@@ -0,0 +1,53 @@
+#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;
+}
+
diff --git a/lily/molecule.cc b/lily/molecule.cc
new file mode 100644 (file)
index 0000000..c52fdc7
--- /dev/null
@@ -0,0 +1,146 @@
+#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();
+}
diff --git a/lily/mylexer.cc b/lily/mylexer.cc
new file mode 100644 (file)
index 0000000..7da6ddd
--- /dev/null
@@ -0,0 +1,196 @@
+#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;
+}
diff --git a/lily/note.cc b/lily/note.cc
new file mode 100644 (file)
index 0000000..496d892
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+  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;
+}
diff --git a/lily/notehead.cc b/lily/notehead.cc
new file mode 100644 (file)
index 0000000..722b231
--- /dev/null
@@ -0,0 +1,77 @@
+#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));
+}
+
diff --git a/lily/notename.cc b/lily/notename.cc
new file mode 100644 (file)
index 0000000..e6d6264
--- /dev/null
@@ -0,0 +1,47 @@
+#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);
+}
diff --git a/lily/paper-def.cc b/lily/paper-def.cc
new file mode 100644 (file)
index 0000000..b49a53f
--- /dev/null
@@ -0,0 +1,91 @@
+#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
+}
diff --git a/lily/pcol.cc b/lily/pcol.cc
new file mode 100644 (file)
index 0000000..4f1b65d
--- /dev/null
@@ -0,0 +1,121 @@
+#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();
+}
diff --git a/lily/pscore.cc b/lily/pscore.cc
new file mode 100644 (file)
index 0000000..1f4a8b6
--- /dev/null
@@ -0,0 +1,257 @@
+#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();
+}
diff --git a/lily/pstaff.cc b/lily/pstaff.cc
new file mode 100644 (file)
index 0000000..ce7f7b0
--- /dev/null
@@ -0,0 +1,14 @@
+#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;
+}
diff --git a/lily/qlp.cc b/lily/qlp.cc
new file mode 100644 (file)
index 0000000..e6696ac
--- /dev/null
@@ -0,0 +1,155 @@
+#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
+}
+
diff --git a/lily/qlpsolve.cc b/lily/qlpsolve.cc
new file mode 100644 (file)
index 0000000..5738be2
--- /dev/null
@@ -0,0 +1,265 @@
+#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;
+} 
+
+    
diff --git a/lily/register.cc b/lily/register.cc
new file mode 100644 (file)
index 0000000..126507c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+  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
+{
+}
diff --git a/lily/request.cc b/lily/request.cc
new file mode 100644 (file)
index 0000000..ecfe68c
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+  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_;
+}
diff --git a/lily/rest.cc b/lily/rest.cc
new file mode 100644 (file)
index 0000000..0e4394a
--- /dev/null
@@ -0,0 +1,42 @@
+#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;
+}
+
diff --git a/lily/score-column.cc b/lily/score-column.cc
new file mode 100644 (file)
index 0000000..4387630
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+  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();
+}
diff --git a/lily/score.cc b/lily/score.cc
new file mode 100644 (file)
index 0000000..88e2e2f
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+  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);
+}
diff --git a/lily/scoreline.cc b/lily/scoreline.cc
new file mode 100644 (file)
index 0000000..2f8f0f3
--- /dev/null
@@ -0,0 +1,51 @@
+#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();
+}
+       
diff --git a/lily/scores.cc b/lily/scores.cc
new file mode 100644 (file)
index 0000000..a6df7ea
--- /dev/null
@@ -0,0 +1,48 @@
+#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;
+}
+
diff --git a/lily/script-def.cc b/lily/script-def.cc
new file mode 100644 (file)
index 0000000..53bdd12
--- /dev/null
@@ -0,0 +1,24 @@
+#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);
+}
diff --git a/lily/script-reg.cc b/lily/script-reg.cc
new file mode 100644 (file)
index 0000000..6cfba0f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+  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_;
+}
diff --git a/lily/script.cc b/lily/script.cc
new file mode 100644 (file)
index 0000000..2a31133
--- /dev/null
@@ -0,0 +1,129 @@
+#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;
+}
diff --git a/lily/slur.cc b/lily/slur.cc
new file mode 100644 (file)
index 0000000..ba77a69
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+
+  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;
+}
+
diff --git a/lily/spanner.cc b/lily/spanner.cc
new file mode 100644 (file)
index 0000000..cc57686
--- /dev/null
@@ -0,0 +1,43 @@
+#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);
+}
diff --git a/lily/staff-elem-info.cc b/lily/staff-elem-info.cc
new file mode 100644 (file)
index 0000000..9a6283e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+  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;
+}
diff --git a/lily/staff-elem.cc b/lily/staff-elem.cc
new file mode 100644 (file)
index 0000000..b24172f
--- /dev/null
@@ -0,0 +1,200 @@
+#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);
+}
diff --git a/lily/staffline.cc b/lily/staffline.cc
new file mode 100644 (file)
index 0000000..5d18b21
--- /dev/null
@@ -0,0 +1,110 @@
+#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
+}
diff --git a/lily/staffsym.cc b/lily/staffsym.cc
new file mode 100644 (file)
index 0000000..631a5f3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+  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;
+}
diff --git a/lily/stem.cc b/lily/stem.cc
new file mode 100644 (file)
index 0000000..74ea4b5
--- /dev/null
@@ -0,0 +1,200 @@
+#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;
+}
+
+
diff --git a/lily/symbol.cc b/lily/symbol.cc
new file mode 100644 (file)
index 0000000..becdf1e
--- /dev/null
@@ -0,0 +1,21 @@
+#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() + "))";
+}
diff --git a/lily/symtable.cc b/lily/symtable.cc
new file mode 100644 (file)
index 0000000..d55e9ac
--- /dev/null
@@ -0,0 +1,61 @@
+#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";
+    }
+}
+       
diff --git a/lily/template2.cc b/lily/template2.cc
new file mode 100644 (file)
index 0000000..0f58147
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+  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);
+
+
diff --git a/lily/template3.cc b/lily/template3.cc
new file mode 100644 (file)
index 0000000..7df0ef3
--- /dev/null
@@ -0,0 +1,15 @@
+#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);
diff --git a/lily/template4.cc b/lily/template4.cc
new file mode 100644 (file)
index 0000000..d26e748
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+  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 *);
diff --git a/lily/template5.cc b/lily/template5.cc
new file mode 100644 (file)
index 0000000..a1ab7e8
--- /dev/null
@@ -0,0 +1,9 @@
+#include "proto.hh"
+#include "string.hh"
+#include "moment.hh"
+#include "real.hh"
+
+#include "interval.tcc"
+
+Interval__instantiate(Real);
+Interval__instantiate(Rational);
diff --git a/lily/template6.cc b/lily/template6.cc
new file mode 100644 (file)
index 0000000..0401c8c
--- /dev/null
@@ -0,0 +1,10 @@
+#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);
diff --git a/lily/tex-beam.cc b/lily/tex-beam.cc
new file mode 100644 (file)
index 0000000..c9f3c95
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+
+  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;
+}
+
+
diff --git a/lily/tex-slur.cc b/lily/tex-slur.cc
new file mode 100644 (file)
index 0000000..71cded9
--- /dev/null
@@ -0,0 +1,208 @@
+#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;
+}
+
+
diff --git a/lily/tex.cc b/lily/tex.cc
new file mode 100644 (file)
index 0000000..e8349e6
--- /dev/null
@@ -0,0 +1,44 @@
+#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);
+}
diff --git a/lily/text-def.cc b/lily/text-def.cc
new file mode 100644 (file)
index 0000000..d67622e
--- /dev/null
@@ -0,0 +1,31 @@
+#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';
+}
diff --git a/lily/version.cc b/lily/version.cc
new file mode 100644 (file)
index 0000000..b2a57de
--- /dev/null
@@ -0,0 +1,11 @@
+#include "version.hh"
+#include "fversion.hh"
+
+static char *s = "LilyPond " VERSIONSTR    "/FlowerLib " FVERSIONSTR
+". Compile: "   __DATE__ ", " __TIME__ " (" COMPILER ")\n";
+
+const char *
+get_version()
+{
+   return s;
+}
diff --git a/lily/wordwrap.cc b/lily/wordwrap.cc
new file mode 100644 (file)
index 0000000..f217a63
--- /dev/null
@@ -0,0 +1,78 @@
+#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)
+{
+}