summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile8
-rw-r--r--src/bar.cc18
-rw-r--r--src/beam.cc179
-rw-r--r--src/boxes.cc31
-rw-r--r--src/break.cc135
-rw-r--r--src/calcideal.cc65
-rw-r--r--src/command.cc39
-rw-r--r--src/debug.cc27
-rw-r--r--src/dimen.cc40
-rw-r--r--src/getcommands.cc58
-rw-r--r--src/identifier.cc26
-rw-r--r--src/item.cc73
-rw-r--r--src/keyword.cc79
-rw-r--r--src/leastsquares.cc25
-rw-r--r--src/lexer.l229
-rw-r--r--src/linespace.cc264
-rw-r--r--src/linestaff.cc20
-rw-r--r--src/lookup.cc160
-rw-r--r--src/main.cc79
-rw-r--r--src/melodicstaff.cc59
-rw-r--r--src/meter.cc20
-rw-r--r--src/misc.cc14
-rw-r--r--src/molecule.cc144
-rw-r--r--src/note.cc206
-rw-r--r--src/notehead.cc65
-rw-r--r--src/notename.cc30
-rw-r--r--src/paper.cc82
-rw-r--r--src/parser.y292
-rw-r--r--src/pcol.cc118
-rw-r--r--src/pscore.cc205
-rw-r--r--src/pstaff.cc14
-rw-r--r--src/qlp.cc147
-rw-r--r--src/qlpsolve.cc255
-rw-r--r--src/request.cc101
-rw-r--r--src/rest.cc47
-rw-r--r--src/rhythmstaff.cc62
-rw-r--r--src/sccol.cc28
-rw-r--r--src/scommands.cc266
-rw-r--r--src/score.cc224
-rw-r--r--src/scoreline.cc43
-rw-r--r--src/scores.cc34
-rw-r--r--src/simpleprint.cc55
-rw-r--r--src/simplestaff.cc66
-rw-r--r--src/simplewalker.cc106
-rw-r--r--src/spanner.cc54
-rw-r--r--src/staff.cc172
-rw-r--r--src/staffline.cc107
-rw-r--r--src/stcol.cc30
-rw-r--r--src/stem.cc156
-rw-r--r--src/swalker.cc32
-rw-r--r--src/symbol.cc32
-rw-r--r--src/symtable.cc60
-rw-r--r--src/table.cc67
-rw-r--r--src/template1.cc25
-rw-r--r--src/template2.cc19
-rw-r--r--src/template3.cc12
-rw-r--r--src/tex.cc32
-rw-r--r--src/texbeam.cc99
-rw-r--r--src/tstream.cc75
-rw-r--r--src/version.cc9
-rw-r--r--src/voice.cc78
-rw-r--r--src/warn.cc18
62 files changed, 5315 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000000..65374e807e
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,8 @@
+default:
+ $(MAKE) -C ..
+
+dist:
+ ln Makefile $(mycc) $(othersrc) $(DDIR)/src
+
+TAGS: $(mycc)
+ etags -CT $(mycc)
diff --git a/src/bar.cc b/src/bar.cc
new file mode 100644
index 0000000000..bb66f2b777
--- /dev/null
+++ b/src/bar.cc
@@ -0,0 +1,18 @@
+#include "bar.hh"
+#include "string.hh"
+#include "molecule.hh"
+#include "paper.hh"
+#include "lookup.hh"
+
+
+Bar::Bar( String t)
+{
+ type = t;
+}
+void
+Bar::preprocess()
+{
+ Symbol s = paper()->lookup_->bar(type);
+ output = new Molecule(Atom(s));
+}
+
diff --git a/src/beam.cc b/src/beam.cc
new file mode 100644
index 0000000000..49214c91f2
--- /dev/null
+++ b/src/beam.cc
@@ -0,0 +1,179 @@
+#include "beam.hh"
+#include "debug.hh"
+#include "symbol.hh"
+#include "molecule.hh"
+#include "leastsquares.hh"
+#include "pcol.hh"
+#include "stem.hh"
+#include "paper.hh"
+#include "lookup.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->hpos();
+ int dir = s->dir;
+ idealy = MAX(dir*s->top, dir*s->bot);
+ miny = MAX(dir*s->minnote, dir*s-> maxnote);
+ assert(miny <= idealy);
+ no_beams = s->flag;
+}
+
+/****************/
+
+Beam::Beam()
+{
+ slope = 0;
+ left_pos = 0.0;
+ dir =0;
+}
+
+void
+Beam::add(Stem*s)
+{
+ stems.bottom().add(s);
+ s->print_flag = false;
+}
+
+void
+Beam::set_default_dir()
+{
+ int dirs[2];
+ dirs[0]=0; dirs[1] =0;
+ for (PCursor<Stem*> sc(stems); sc.ok(); sc++) {
+ sc->set_default_dir();
+ dirs[(sc->dir+1)/2] ++;
+ }
+ dir = (dirs[0] > dirs[1]) ? -1 : 1;
+ for (PCursor<Stem*> sc(stems); sc.ok(); sc++) {
+ sc->dir = dir;
+ }
+}
+
+void
+Beam::solve_slope()
+{
+ svec<Stem_info> sinfo;
+ for (PCursor<Stem* >sc(stems); sc.ok(); sc++) {
+ sc->set_default_extents();
+ Stem_info i(sc);
+ sinfo.add(i);
+ }
+ Real leftx = sinfo[0].x;
+ Least_squares l;
+ for (int i=0; i < sinfo.sz(); i++) {
+ sinfo[i].x -= leftx;
+ l.input.add(Offset(sinfo[i].x, sinfo[i].idealy));
+ }
+
+ l.minimise(slope, left_pos);
+ Real dy = 0.0;
+ for (int i=0; i < sinfo.sz(); 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;
+ slope *= dir;
+
+ {Real inter =paper()->interline()/2;
+ Real unitslope = slope*inter;
+
+ // set beamslope, for setting stems correctly
+ // ignoring return.
+ Symbol sy = paper()->lookup_->beam(unitslope, width().length());
+ slope =unitslope / inter;
+ }
+}
+
+void
+Beam::set_stemlens()
+{
+ PCursor<Stem*> s(stems);
+ Real x0 = s->hpos();
+ for (; s.ok() ; s++) {
+ Real x = s->hpos()-x0;
+ s->set_stemend(left_pos + slope * x);
+ }
+}
+
+void
+Beam::calculate()
+{
+ assert(stems.size()>1);
+ if (!dir)
+ set_default_dir();
+
+ solve_slope();
+ set_stemlens();
+}
+
+void
+Beam::process()
+{
+ calculate();
+ brew_molecule();
+}
+
+
+// todo.
+Spanner *
+Beam::broken_at(const PCol *, const PCol *) const
+{
+ return new Beam(*this);
+}
+
+void
+Beam::preprocess()
+{
+ left = (*stems.top()) ->pcol_;
+ right = (*stems.bottom())->pcol_;
+}
+
+Interval
+Beam::height() const
+{
+ return output->extent().y;
+}
+
+Interval
+Beam::width() const
+{
+ Beam * me = (Beam*) this; // ugh
+ return Interval( (*me->stems.top()) ->hpos(),
+ (*me->stems.bottom()) ->hpos() );
+}
+
+void
+Beam::brew_molecule()
+{
+ Real inter=paper()->interline()/2;
+ Real sl = slope*inter;
+ Real w = width().length() + paper()->rule_thickness();
+ Symbol s = paper()->lookup_->beam(sl,w);
+
+ Atom a(s);
+
+ Real dx = width().min -left->hpos;
+ a.translate(Offset(dx,left_pos*inter));
+ output = new Molecule(a);
+}
+
+void
+Beam::print()const
+{
+ mtor << "Beam, slope " <<slope << "left ypos " << left_pos<<'\n';
+}
+
diff --git a/src/boxes.cc b/src/boxes.cc
new file mode 100644
index 0000000000..ebfc08abfe
--- /dev/null
+++ b/src/boxes.cc
@@ -0,0 +1,31 @@
+#include "boxes.hh"
+#include "const.hh"
+
+void
+Interval::set_empty() {
+ min = INFTY;
+ max = -INFTY;
+}
+Real
+Interval::length() const {
+ return max-min;
+}
+Box::Box(svec<Real> s)
+{
+ assert(s.sz() == 4);
+ x.min = s[0];
+ x.max = s[1];
+ y.min = s[2];
+ y.max = s[3];
+}
+
+Box::Box()
+{
+}
+
+Box::Box(Interval ix, Interval iy)
+{
+ x = ix;
+ y = iy;
+}
+
diff --git a/src/break.cc b/src/break.cc
new file mode 100644
index 0000000000..de9a704984
--- /dev/null
+++ b/src/break.cc
@@ -0,0 +1,135 @@
+/*
+ do calculations for breaking problem
+
+ */
+#include "paper.hh"
+#include "linespace.hh"
+#include "debug.hh"
+#include "scoreline.hh"
+#include "pscore.hh"
+
+// construct an appropriate Spacing_problem and solve it.
+svec<Real>
+PScore::solve_line(svec<const PCol *> curline) const
+{
+ Spacing_problem sp;
+
+ sp.add_column(curline[0], true, 0.0);
+ for (int i=1; i< curline.sz()-1; i++)
+ sp.add_column(curline[i]);
+ sp.add_column(curline.last(), true, paper_->linewidth);
+
+ // misschien moeven uit Spacing_problem?
+ for (PCursor<Idealspacing *> i(suz); i.ok(); i++) {
+ sp.add_ideal(i);
+ }
+ svec<Real> the_sol=sp.solve();
+ return the_sol;
+}
+
+bool
+PScore::feasible(svec<const PCol *> curline) const
+{
+ Real l =0;
+ for (int i=0; i < curline.sz(); i++)
+ l +=curline[i]->width().length();
+ return l < paper_->linewidth;
+}
+
+void
+PScore::problem_OK() const
+{
+ if (!cols.size())
+ error("PScore::problem_OK(): Score does not have any columns");
+ PCursor<PCol *> start(cols);
+ PCursor<PCol *> end (((PScore*)this)->cols.bottom());
+
+ assert(start->breakable());
+ assert(end->breakable());
+}
+
+struct Col_configuration {
+ svec<const PCol*> line;
+ svec<Real> config;
+ Real energy;
+
+ Col_configuration() {
+ energy = INFTY;
+ }
+ void add(const PCol*c) { line.add(c);}
+ void setsol(svec<Real> sol) {
+ config = sol;
+ energy = config.last();
+ config.pop();
+ }
+ void print() const {
+#ifndef NPRINT
+ mtor << "energy : " << energy << '\n';
+ mtor << "line of " << config.sz() << " cols\n";
+#endif
+ }
+};
+
+/// wordwrap type algorithm
+/* el stupido. This should be done more accurately:
+
+ It would be nice to have a Dynamic Programming type of algorithm
+ similar to TeX's
+
+ */
+
+void
+PScore::calc_breaking()
+{
+ OK();
+ problem_OK();
+ PCursor<PCol *> curcol(cols);
+
+ svec<const PCol *> breakpoints(find_breaks());
+ assert(breakpoints.sz()>=2);
+ for (int i=0 ; i < breakpoints.sz() -1; ) {
+ Col_configuration minimum;
+ Col_configuration current;
+
+ // do another line
+ PCol *post = breakpoints[i]->postbreak;
+ current.add( post);
+ curcol++; // skip the breakable.
+ i++;
+
+ while (i < breakpoints.sz()) {
+
+ // add another measure.
+ while(breakpoints[i] !=curcol){
+
+ current.add(curcol);
+ curcol++;
+ }
+ current.add(breakpoints[i]->prebreak );
+ if (!feasible(current.line)) {
+ if (!minimum.line.sz())
+ error("sorry, this measure is too long");
+ break;
+ }
+ current.setsol(solve_line(current.line));
+ current.print();
+
+ if (current.energy < minimum.energy) {
+ minimum = current;
+ } else { // we're one col too far.
+ i--;
+ while (curcol != breakpoints[i])
+ curcol --;
+
+ break;
+ }
+
+ current.line.last()=breakpoints[i];
+ curcol ++;
+ i++;
+ }
+ mtor << "Adding line, next breakpoint " << i << '\n';
+ add_line(minimum.line, minimum.config);
+ }
+}
+
diff --git a/src/calcideal.cc b/src/calcideal.cc
new file mode 100644
index 0000000000..8099e0e4c7
--- /dev/null
+++ b/src/calcideal.cc
@@ -0,0 +1,65 @@
+#include "tstream.hh"
+#include "score.hh"
+#include "pscore.hh"
+#include "staff.hh"
+#include "paper.hh"
+#include "sccol.hh"
+#include "debug.hh"
+
+
+void
+Score::do_connect(PCol *c1, PCol *c2, Real d)
+{
+ Idealspacing*sp=pscore_->get_spacing(c1,c2);
+
+ if (!sp->hooke){
+ sp->hooke = 1.0;
+ sp->space =d;
+ }
+}
+
+void
+Score::connect_nonmus(PCol* c1, PCol *c2, Real d)
+{
+ if (c2->used && c1->used) {
+ do_connect(c1,c2,d);
+
+ // alert! this is broken!
+ if (c1->breakable()) {
+ do_connect(c1->postbreak, c2,d);
+ }
+ if (c2->breakable()) {
+ do_connect(c1, c2->prebreak,d);
+ }
+ if (c1->breakable() &&c2->breakable()) {
+ do_connect(c1->postbreak, c2->prebreak,d);
+ }
+ }
+}
+/* this needs A LOT of rethinking.
+
+ generate springs between columns.
+ */
+void
+Score::calc_idealspacing()
+{
+ PCursor<Score_column*> sc(cols_);
+
+ for (; sc.ok(); sc++) {
+ if (sc->musical)
+ for (int i=0; i < sc->durations.sz(); i++) {
+ Real d = sc->durations[i];
+ Real dist = paper_->duration_to_dist(d);
+ PCol * c2 = find_col(sc->when + d,true)->pcol;
+ connect_nonmus(sc->pcol, c2, dist);
+ c2 = find_col(sc->when + d,false)->pcol;
+ connect_nonmus(sc->pcol, c2, dist);
+ }
+ else if (sc->used()) { // ignore empty columns
+ PCol * c2 = find_col(sc->when,true)->pcol;
+ connect_nonmus(sc->pcol,c2,0.0);
+ }
+ }
+}
+
+
diff --git a/src/command.cc b/src/command.cc
new file mode 100644
index 0000000000..23edf1ec36
--- /dev/null
+++ b/src/command.cc
@@ -0,0 +1,39 @@
+#include "string.hh"
+#include "debug.hh"
+#include "command.hh"
+
+bool
+Command::isbreak()const
+{
+ return (code >= BREAK_PRE && code <= BREAK_END);
+}
+
+Command::Command()
+{
+ code = NOP;
+ when = -1;
+ priority=0;
+}
+
+
+
+Command::Command(Real w)
+{
+ code = NOP;
+ when = w;
+ priority=0;
+}
+
+void
+Command::print() const
+{
+#ifndef NPRINT
+ mtor << "command at " << when << ", code " << code << " prio " << priority;
+ if (args.sz()) {
+ mtor<< " args: ";
+ for (int i = 0; i<args.sz(); i++)
+ mtor << "`"<<args[i] <<"',";
+ }
+ mtor << "\n";
+#endif
+}
diff --git a/src/debug.cc b/src/debug.cc
new file mode 100644
index 0000000000..d55c901945
--- /dev/null
+++ b/src/debug.cc
@@ -0,0 +1,27 @@
+#include <fstream.h>
+#include <std/new.h>
+#include "debug.hh"
+#include "dstream.hh"
+#include "vector.hh"
+
+Dstream monitor(&cout,".dstreamrc");
+ostream * nulldev = new ofstream("/dev/null");
+
+
+/*
+ want to do a stacktrace .
+ */
+void
+mynewhandler()
+{
+ cerr << "Out of free store memory. Aborting.. "<< flush;
+ assert(false);
+}
+
+
+void
+debug_init()
+{
+ set_new_handler(&mynewhandler);
+ set_matrix_debug(monitor);
+}
diff --git a/src/dimen.cc b/src/dimen.cc
new file mode 100644
index 0000000000..eb53756b45
--- /dev/null
+++ b/src/dimen.cc
@@ -0,0 +1,40 @@
+#include <ctype.h>
+#include "dimen.hh"
+#include "debug.hh"
+#include "string.hh"
+
+Real
+parse_dimen(String dim)
+{
+ int i=dim.len()-1;
+ const char *s = dim;
+ while (i > 0 && (isspace(s[i]) || isalpha(s[i])) ){
+ i--;
+ }
+ String unit(s + i+1);
+ return convert_dimen(dim.fvalue(), unit);
+}
+
+const Real CM_TO_PT=72/2.54;
+
+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 * 72;
+ error ("unknown length unit: `" + unit+"'");
+}
+
+String
+print_dimen(Real r)
+{
+ String s(r);
+ s += "pt ";
+ return s;
+}
diff --git a/src/getcommands.cc b/src/getcommands.cc
new file mode 100644
index 0000000000..1f9362c59c
--- /dev/null
+++ b/src/getcommands.cc
@@ -0,0 +1,58 @@
+#include "string.hh"
+#include "parseconstruct.hh"
+#include "command.hh"
+
+Command*
+get_bar_command(Real w)
+{
+ Command*c = new Command;
+ c->when = w;
+ c->code = TYPESET;
+ c->args.add( "BAR");
+ c->args.add( "|");
+ c->priority = 100;
+ return c;
+}
+
+Command *
+get_meter_command(Real w, int n, int m)
+{
+ Command*c = new Command;
+
+ c->when = w;
+ c->code = TYPESET;
+ c->args.add( "METER");
+ c->args.add( n );
+ c->args.add( m );
+ c->priority = 50; // less than bar
+ return c;
+}
+
+Command *
+get_meterchange_command(int n, int m)
+{
+ Command*c = new Command;
+
+ c->code = INTERPRET;
+ c->args.add( "METER");
+ c->args.add( n );
+ c->args.add( m );
+ c->priority = 0; // more than bar
+ return c;
+}
+
+
+Command *
+get_skip_command(int n, Real m)
+{
+ Command*c = new Command;
+
+ c->code = INTERPRET;
+ c->args.add( "SKIP");
+ c->args.add( n );
+ c->args.add( m );
+ c->priority = 0; // more than bar
+ return c;
+}
+
+
diff --git a/src/identifier.cc b/src/identifier.cc
new file mode 100644
index 0000000000..024fe06486
--- /dev/null
+++ b/src/identifier.cc
@@ -0,0 +1,26 @@
+#include <assert.h>
+#include "identifier.hh"
+#include "staff.hh"
+#include "lexer.hh"
+
+
+Identifier::Identifier(String n)
+ :name (n)
+{
+ data = 0;
+}
+
+
+Identifier::~Identifier()
+{
+}
+
+Staff_id::~Staff_id()
+{
+ delete staff();
+}
+
+Voice_id::~Voice_id()
+{
+ delete voice();
+}
diff --git a/src/item.cc b/src/item.cc
new file mode 100644
index 0000000000..914c924a99
--- /dev/null
+++ b/src/item.cc
@@ -0,0 +1,73 @@
+#include "pstaff.hh"
+#include "pscore.hh"
+#include "symbol.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+
+void
+Item::translate(Offset O)
+{
+ offset_ += O;
+}
+
+void
+Item::postprocess()
+{
+ // default: do nothing
+}
+
+
+void
+Item::preprocess()
+{
+ // default: do nothing
+}
+
+String
+Item::TeXstring() const
+{
+ Item * me = (Item*) this;
+ output->translate(offset_); // ugh?
+ me ->offset_ = Offset(0,0); // URRGGH!
+ return output->TeXstring();
+}
+
+Interval
+Item::width() const
+{
+ Interval i =output->extent().x ;
+ return i+=offset_.x;
+}
+
+Interval
+Item::height() const
+{
+ Interval i =output->extent().y;
+ return i+=offset_.y;
+}
+
+Item::~Item()
+{
+ delete output;
+}
+
+Item::Item()
+{
+ pcol_ = 0;
+ output = 0;
+ pstaff_ = 0;
+}
+void
+Item::print() const
+{
+ assert(output);
+ output->print();
+}
+
+Paperdef*
+Item::paper() const
+{
+ assert(pstaff_);
+ return pstaff_->pscore_->paper_;
+}
+
diff --git a/src/keyword.cc b/src/keyword.cc
new file mode 100644
index 0000000000..14903cfb61
--- /dev/null
+++ b/src/keyword.cc
@@ -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/src/leastsquares.cc b/src/leastsquares.cc
new file mode 100644
index 0000000000..1e1c91cee3
--- /dev/null
+++ b/src/leastsquares.cc
@@ -0,0 +1,25 @@
+#include "leastsquares.hh"
+
+void
+Least_squares::minimise(Real &coef, Real &offset)
+{
+ Real sx = 0.0;
+ Real sy = 0.0;
+ Real sqx =0.0;
+ Real sxy = 0.0;
+
+ for (int i=0; i < input.sz();i++) {
+ Real x=input[i].x;
+ Real y = input[i].y;
+ sx += x;
+ sy += y;
+ sqx += sqr(x);
+ sxy += x*y;
+ }
+ int N = input.sz();
+
+
+ coef = (N * sxy - sx*sy )/(N*sqx - sqr(sx));
+ offset = (sy - coef * sx)/N;
+
+}
diff --git a/src/lexer.l b/src/lexer.l
new file mode 100644
index 0000000000..1e3443e56e
--- /dev/null
+++ b/src/lexer.l
@@ -0,0 +1,229 @@
+%{ // -*-Fundamental-*-
+
+#include <fstream.h>
+#include <stdio.h>
+#include "glob.hh"
+#include "string.hh"
+
+#include "lexer.hh"
+#include "keyword.hh"
+#include "vray.hh"
+#include "parser.hh"
+#include "debug.hh"
+
+sstack<istream *> include_stack;
+static int last_print;
+const int DOTPRINT=50; // every 50 lines dots
+%}
+
+%option c++
+%option noyywrap
+%option nodefault
+%option yylineno
+%option debug
+%x notes
+%x incl
+%x quote
+
+
+NOTECOMMAND \\{WORD}
+OPTSIGN !?
+NOTENAMEI A|B|C|D|E|F|G|As|Bes|Ces|Des|Es|Fes|Ges|Ais|Bis|Cis|Dis|Eis|Fis|Gis
+NOTENAMEII a|b|c|d|e|f|g|as|bes|ces|des|es|fes|ges|ais|bis|cis|dis|eis|fis|gis
+NOTENAMEIII Ases|Beses|Ceses|Deses|Eses|Feses|Geses|Aisis|Bisis|Cisis|Disis|Eisis|Fisis|Gisis
+NOTENAMEIIII ases|beses|ceses|deses|eses|feses|geses|aisis|bisis|cisis|disis|eisis|fisis|gisis
+RESTNAME r|s
+NOTENAME {NOTENAMEI}|{NOTENAMEII}|{NOTENAMEIII}|{NOTENAMEIIII}
+PITCH ['`]*{OPTSIGN}{NOTENAME}
+DURNAME 1|2|4|8|16|32
+DURATION {DURNAME}\.*
+FULLNOTE {PITCH}{DURATION}?
+WORD [a-zA-Z][a-zA-Z0-9_]+
+REAL [0-9]+(\.[0-9]*)?
+
+%%
+
+\$ {
+ BEGIN(notes); return '$';
+}
+
+<notes>{NOTECOMMAND} {
+ String c = YYText() +1;
+ int l = lookup_keyword(c);
+ if (l == -1) {
+ String e("unknown NOTECOMMAND: \\");
+ e += c;
+ yyerror(e);
+ }
+ return l;
+}
+
+<notes>{RESTNAME} {
+ const char *s = YYText();
+ yylval.string = new String (s);
+ mtor << "rest:"<< yylval.string;
+ return RESTNAME;
+}
+<notes>{PITCH} {
+ const char *s = YYText();
+ yylval.string = new String (s);
+ mtor << "pitch:"<< *yylval.string;
+ return PITCH;
+}
+<notes>{DURATION} {
+ yylval.string = new String (YYText());
+ return DURATION;
+}
+<notes>\| {
+}
+<notes>[:space:]+ {
+}
+<notes>[ \t\n]+ {
+}
+<notes>%.* {
+
+}
+<notes>\$ {
+ BEGIN(INITIAL); return '$';
+}
+<notes>[\[){] { /* parens () are NO mistake */
+ yylval.c = YYText()[0];
+ return OPEN_REQUEST_PARENS;
+}
+<notes>[\]()}] { /* parens () are NO mistake */
+ yylval.c = YYText()[0];
+ return CLOSE_REQUEST_PARENS;
+}
+
+<notes>. {
+ String s("lexer error: illegal character found: " + String(YYText()));
+ yyerror(s);
+}
+
+\" {
+ BEGIN(quote);
+}
+<quote>[^\"]* {
+ yylval.string = new String (YYText());
+}
+<quote>\" {
+ BEGIN(INITIAL);
+ return STRING;
+}
+
+<<EOF>> {
+ if(!close_input())
+ yyterminate();
+}
+{WORD} {
+ int l = lookup_keyword(YYText());
+ if (l != -1)
+ return l;
+ Identifier * id = lookup_identifier(YYText());
+ if (id) {
+ yylval.id = id;
+ return IDENTIFIER;
+ }
+ String *sp = new String( YYText());
+ mtor << "new id: " << *sp;
+ yylval.string=sp;
+ return NEWIDENTIFIER;
+}
+
+{REAL} {
+ Real r;
+ int cnv=sscanf (YYText(), "%lf", &r);
+ assert(cnv == 1);
+ mtor << "token (REAL)" << r;
+ yylval.real = r;
+ return REAL;
+}
+
+[\{\}\[\]\(\)] {
+
+ mtor << "parens\n";
+ return YYText()[0];
+}
+[:=] {
+ char c = YYText()[0];
+ mtor << "misc char" <<c<<"\n";
+ return c;
+}
+[ \t\n]+ {
+
+}
+
+%.* {
+ //ignore
+}
+. {
+ error("lexer error: illegal character '"+String(YYText()[0])+
+ "' encountered");
+ return YYText()[0];
+}
+
+%%
+
+yyFlexLexer *lexer=0;
+
+// set the new input to s, remember old file.
+void
+new_input(String s)
+{
+ istream *newin ;
+
+ if (s=="")
+ newin = &cin;
+ else
+ newin = new ifstream( s ); //
+
+ if ( ! *newin)
+ error("cant open " + s);
+ cout << "["<<s<<flush;
+
+ include_stack.push(newin);
+
+ if (!lexer) {
+ lexer = new yyFlexLexer;
+ lexer->set_debug( !monitor.silence("Lexer"));
+ }
+
+ lexer->switch_streams(newin);
+}
+
+
+// pop the inputstack.
+bool
+close_input()
+{
+
+ istream *closing= include_stack.pop();
+ if (closing != &cin)
+ delete closing;
+
+ cout << "]" << flush;
+
+ if (include_stack.empty()) {
+ return false ;
+ } else
+ lexer->switch_streams(include_stack.top());
+ return true;
+}
+
+int
+yylex() {
+ return lexer->yylex();
+}
+
+void
+yyerror(const char *s)
+{
+ *mlog << "error in line " << lexer->lineno() << ": " << s << '\n';
+ exit(1);
+}
+
+void
+kill_lexer()
+{
+ delete lexer;
+}
diff --git a/src/linespace.cc b/src/linespace.cc
new file mode 100644
index 0000000000..6b16c9afab
--- /dev/null
+++ b/src/linespace.cc
@@ -0,0 +1,264 @@
+#include <math.h>
+#include "linespace.hh"
+#include "debug.hh"
+#include "qlp.hh"
+#include "unionfind.hh"
+
+const Real COLFUDGE=1e-3;
+//#define COLFUDGE 1e-3
+bool
+Spacing_problem::contains(const PCol *w)
+{
+ for (int i=0; i< cols.sz(); 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.sz(); i++)
+ if (cols[i].pcol_ == w)
+ return i;
+ assert(false);
+}
+
+void
+Spacing_problem::OK() const
+{
+#ifndef NDEBUG
+ Union_find connected(cols.sz());
+ svec<int> fixed;
+ for (int i=0; i < ideals.sz(); 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.sz(); i++)
+ if (cols[i].fixed)
+ fixed.add(i);
+ for (int i = 0; i < cols.sz(); i++) {
+ bool c=false;
+ for (int j =0; j<fixed.sz(); j++)
+ c |= connected.equiv(j,i);
+ assert(c);
+ }
+#endif
+}
+
+bool
+Spacing_problem::check_constraints(Vector v) const
+{
+ int dim=v.dim();
+ // mtor << "checking solution " << v << '\n';
+ for (int i=0; i < dim; i++) {
+
+ if (cols[i].fixed&& ABS(cols[i].fixpos - 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 1
+ if (!b)
+ return false;
+
+#else
+ mtor << "dif= "<<dif<<" fudge= " << COLFUDGE<< " dif >fudge= "<<
+ b << "\n";
+
+ /* fucks up for unknown reasons */
+ if (dif < -COLFUDGE)
+ return false;
+#endif
+
+ }
+ 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.sz();
+ Vector initsol(dim);
+ for (int i=0; i < dim; i++) {
+ if (cols[i].fixed) {
+ initsol(i)=cols[i].fixpos;
+ } 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);
+ for (int j=0; j < ideals.sz(); 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.sz();
+ for (int j=0; j < dim; j++) {
+ Colinfo *c=&(cols[j]);
+ if (c->fixed) {
+ lp.add_fixed_var(j,c->fixpos);
+ }
+ 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());
+ }
+ }
+}
+
+svec<Real>
+Spacing_problem::solve() const
+{
+ print();
+ OK();
+ assert(check_feasible());
+
+
+ /* optimalisatiefunctie */
+ Mixed_qp lp(cols.sz());
+ 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" ;
+ }
+
+
+ svec<Real> posns(sol);
+ posns.add(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;
+ c.fixed=fixed;
+ c.fixpos=fixpos;
+ assert(col);
+ c.pcol_=col;
+ cols.add(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.add(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<<":" ;
+#endif
+}
+
+void
+Spacing_problem::print() const
+{
+#ifndef NPRINT
+ for (int i=0; i < cols.sz(); i++) {
+ mtor << "col " << i<<' ';
+ cols[i].print();
+ }
+ for (int i=0; i < ideals.sz(); i++) {
+ print_ideal(ideals[i]);
+ }
+#endif
+
+}
+
+void
+Colinfo::print() const
+{
+#ifndef NPRINT
+ mtor << "column { ";
+ if (fixed)
+ mtor << "fixed at " << fixpos<<", ";
+ assert(pcol_);
+ mtor << "[" << minleft() << ", " << minright() << "]";
+ mtor <<"}\n";
+#endif
+}
+
+Colinfo::Colinfo()
+{
+ fixed=false;
+ pcol_=0;
+}
diff --git a/src/linestaff.cc b/src/linestaff.cc
new file mode 100644
index 0000000000..a52954e6f4
--- /dev/null
+++ b/src/linestaff.cc
@@ -0,0 +1,20 @@
+#include "linestaff.hh"
+#include "symbol.hh"
+#include "lookup.hh"
+#include "dimen.hh"
+#include "paper.hh"
+#include "pscore.hh"
+
+Linestaff::Linestaff(int l, PScore *s)
+ : PStaff(s)
+{
+ nolines = l;
+ stafsym = s->paper_->lookup_->linestaff(l);
+}
+
+Symbol
+Linestaff::get_stafsym(Real width)const
+{
+ String w(print_dimen(width));
+ return stafsym->eval(w);
+}
diff --git a/src/lookup.cc b/src/lookup.cc
new file mode 100644
index 0000000000..d0ce3cb743
--- /dev/null
+++ b/src/lookup.cc
@@ -0,0 +1,160 @@
+#include "lookup.hh"
+#include "debug.hh"
+#include "symtable.hh"
+#include "dimen.hh"
+#include "tex.hh"
+
+void
+Lookup::parse(Text_db&t)
+{
+ symtables_->read(t) ;
+}
+
+Lookup::Lookup()
+{
+ symtables_ = new Symtables;
+}
+
+Lookup::~Lookup()
+{
+ delete symtables_;
+}
+
+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::bar(String s)
+{
+ return (*symtables_)("bars")->lookup(s);
+}
+ Symbol
+Lookup::dots(int j)
+{
+ if (j>3)
+ error("max 3 dots");
+ 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);
+
+ svec<String> a;
+ a.add(arg);
+ ret.tex = substitute_args(ret.tex, a);
+
+ return ret;
+}
+
+/****************************************************************/
+// bare bones.
+
+struct Linestaf_symbol : Parametric_symbol {
+ int lines;
+ Linestaf_symbol(int n, Symtables*s): Parametric_symbol(s) { lines = n;}
+ Symbol eval(svec<String>)const;
+};
+
+
+Symbol
+Linestaf_symbol::eval(svec<String> w)const
+{
+ Real wid = w[0].fvalue();
+
+ Symbol s;
+ s.dim.x = Interval(0,wid);
+ Real dy=(lines-1)*convert_dimen(5,"pt"); // TODO!
+ s.dim.y = Interval(0,dy);
+ svec<String> a;
+ a.add(lines);
+ a.add(w[0]);
+ s.tex = (*symtables_)("param")->lookup("linestaf").tex;
+ s.tex = substitute_args(s.tex, a);
+ return s;
+}
+
+/****************************************************************/
+
+
+struct Meter_sym:Parametric_symbol {
+
+ Meter_sym(Symtables*s) : Parametric_symbol(s){ }
+ Symbol eval(svec<String> a) const{
+ Symbol s;
+ s.dim.x = Interval( convert_dimen(-5,"pt"),
+ convert_dimen(5,"pt"));
+ s.dim.y = Interval(0, convert_dimen(10,"pt") ); // todo
+ String src = (*symtables_)("param")->lookup("meter").tex;
+ s.tex = substitute_args(src,a);
+ return s;
+ }
+};
+/****************************************************************/
+
+struct Stem_sym:Parametric_symbol {
+
+ Stem_sym(Symtables*s) : Parametric_symbol(s) { }
+ Symbol eval(svec<String> a) const {
+ Real y1 = a[0].fvalue();
+ Real y2 = a[1].fvalue();
+ assert(y1 <= y2);
+ Symbol s;
+ s.dim.x = Interval(0,0);
+ s.dim.y = Interval(y1,y2);
+
+ String src = (*symtables_)("param")->lookup("stem").tex;
+ s.tex = substitute_args(src,a);
+ return s;
+ }
+};
+
+Parametric_symbol *
+Lookup::meter(String )
+{
+ return new Meter_sym(symtables_);
+}
+
+Parametric_symbol *
+Lookup::linestaff(int n)
+{
+ return new Linestaf_symbol(n,symtables_);
+}
+
+Parametric_symbol*
+Lookup::stem()
+{
+ return new Stem_sym(symtables_);
+}
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 0000000000..c45de7a683
--- /dev/null
+++ b/src/main.cc
@@ -0,0 +1,79 @@
+#include <iostream.h>
+#include <assert.h>
+#include "lgetopt.hh"
+#include "misc.hh"
+#include "string.hh"
+#include "main.hh"
+
+extern void parse_file(String s);
+
+long_option_init theopts[] = {
+ 1, "output", 'o',
+ 0, "warranty", 'w',
+ 0, "help", 'h',
+ 0,0,0
+};
+
+void
+help()
+{
+ cout <<
+ "--help, -h This help\n"
+ "--warranty, -w show warranty & copyright\n"
+ "--output, -o set default output\n";
+}
+void notice()
+{
+ cout <<
+ "LilyPond, a music typesetter.\n"
+ "Copyright (C) 1996 by\n"
+ " Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>\n"
+ "\n"
+ " This program is free software; you can redistribute it and/or\n"
+ "modify it under the terms of the GNU General Public License version 2\n"
+ "as published by the Free Software Foundation.\n"
+ "\n"
+ " This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ "General Public License for more details.\n"
+ "\n"
+ " You should have received a copy (refer to the file COPYING) of the\n"
+ "GNU General Public License along with this program; if not, write to\n"
+ "the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n"
+ "USA.\n";
+}
+
+int
+main (int argc, char **argv)
+{
+ Getopt_long oparser(argc, argv,theopts);
+ debug_init();
+ cout << get_version();
+
+ while (long_option_init * opt = oparser()) {
+ switch ( opt->shortname){
+ case 'o':
+ set_default_output(oparser.optarg);
+ break;
+ case 'w':
+ notice();
+ exit(0);
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+ char *arg = oparser.get_next_arg();
+
+ if (!arg) arg = "";
+ parse_file(arg);
+
+ do_scores();
+ exit (0);
+}
diff --git a/src/melodicstaff.cc b/src/melodicstaff.cc
new file mode 100644
index 0000000000..17916d2f22
--- /dev/null
+++ b/src/melodicstaff.cc
@@ -0,0 +1,59 @@
+#include "melodicstaff.hh"
+#include "stem.hh"
+#include "rest.hh"
+#include "notehead.hh"
+#include "paper.hh"
+#include "molecule.hh"
+#include "linestaff.hh"
+#include "rhythmstaff.hh"
+#include "sccol.hh"
+
+const int NO_LINES=5;
+const int BOTTOM_POSITION=2; // e is on bottom line of 5-staff...
+
+void
+Melodic_staff::set_output(PScore*ps)
+{
+ theline = new Linestaff(NO_LINES,ps);
+ Simple_staff::set_output(ps);
+}
+
+
+Notehead*
+Melodic_staff::get_notehead(Note_req *rq)
+{
+ int b = rq->rhythmic()->balltype;
+ int d = rq->rhythmic()->dots;
+
+ Notehead *n =new Notehead((NO_LINES-1)*2);
+ n->balltype =b;
+ n->dots = d;
+ n->position = rq->note()->height() - BOTTOM_POSITION;
+ return n;
+}
+
+
+Stem *
+Melodic_staff::get_stem(Stem_req*rq)
+{
+ Stem * s = new Stem(NO_LINES-1);
+ s->flag = rq->stem_number;
+ return s;
+}
+
+/*
+ creation
+ */
+Staff *
+get_new_melodicstaff()
+{
+ return new Melodic_staff;
+}
+
+
+
+Melodic_staff*
+Melodic_staff::clone()const
+{
+ return new Melodic_staff(*this);
+}
diff --git a/src/meter.cc b/src/meter.cc
new file mode 100644
index 0000000000..0afa8ea1a1
--- /dev/null
+++ b/src/meter.cc
@@ -0,0 +1,20 @@
+#include "string.hh"
+#include "molecule.hh"
+#include "meter.hh"
+#include "paper.hh"
+#include "lookup.hh"
+
+
+Meter::Meter(svec<String> a)
+ :args(a)
+{
+}
+void
+Meter::preprocess()
+{
+ Parametric_symbol *p = paper()->lookup_->meter("general");
+ Symbol s = p->eval(args);
+ delete p;
+ output = new Molecule(Atom(s));
+}
+
diff --git a/src/misc.cc b/src/misc.cc
new file mode 100644
index 0000000000..54746fd836
--- /dev/null
+++ b/src/misc.cc
@@ -0,0 +1,14 @@
+#include "misc.hh"
+#include "glob.hh"
+
+#include <math.h>
+
+int intlog2(int d) {
+ int i=0;
+ while (!(d&1)) {
+ d/= 2; i++;
+ }
+ assert(!(d/2));
+ return i;
+}
+
diff --git a/src/molecule.cc b/src/molecule.cc
new file mode 100644
index 0000000000..e8c4d2adec
--- /dev/null
+++ b/src/molecule.cc
@@ -0,0 +1,144 @@
+#include "glob.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{%}{%}{%}");
+ svec<String> a;
+ a.add(print_dimen(off.y));
+ a.add(print_dimen(off.x));
+ a.add(sym.tex);
+ return substitute_args(s, a);
+}
+
+
+String
+Molecule::TeXstring() const
+{
+ String s;
+ for(PCursor<Atom*> c(ats); c.ok(); c++)
+ s+=c->TeXstring();
+ return s;
+}
+
+Box
+Molecule::extent() const
+{
+ Box b;
+ for(PCursor<Atom*> c(ats); c.ok(); c++)
+ b.unite(c->extent());
+ return b;
+}
+
+void
+Molecule::translate(Offset o)
+{
+ for (PCursor<Atom*> c(ats); c.ok(); c++)
+ c->translate(o);
+}
+
+void
+Molecule::add(const Molecule &m)
+{
+ for (PCursor<Atom*> c(m.ats); c.ok(); c++) {
+ add(**c);
+ }
+}
+
+void
+Molecule::add_right(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real xof=extent().x.max - m.extent().x.min;
+ 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.min - m.extent().x.max;
+ 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.max - m.extent().y.min;
+ Molecule toadd(m);
+ toadd.translate(Offset(0,yof));
+ add(toadd);
+}
+
+void
+Molecule::add_bot(const Molecule &m)
+{
+ if (!ats.size()) {
+ add(m);
+ return;
+ }
+ Real yof=extent().y.min- m.extent().y.max;
+ 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 (PCursor<Atom*> c(ats); c.ok(); c++)
+ c->print();
+}
diff --git a/src/note.cc b/src/note.cc
new file mode 100644
index 0000000000..0041bb7238
--- /dev/null
+++ b/src/note.cc
@@ -0,0 +1,206 @@
+#include <ctype.h>
+
+#include "string.hh"
+#include "real.hh"
+#include "debug.hh"
+#include "request.hh"
+#include "voice.hh"
+#include "notename.hh"
+#include "vray.hh"
+
+int default_duration = 4, default_dots=0, default_octave=0;
+
+void
+parse_duration(const char *a, int &j, int &intdur, int &dots)
+{
+ String durstr;
+ while (isdigit(a[j]))
+ {
+ durstr += a[j++];
+ }
+
+ dots=default_dots;
+
+ while (a[j] == '.')
+ {
+ j++;
+ dots++;
+ }
+
+ intdur = (durstr.len()) ?
+ durstr.value():default_duration;
+
+ mtor << "dur " << intdur << "dots " << dots<<eol;
+}
+
+
+
+void
+parse_pitch( const char *a, int &j, int &oct, bool & overide_acc,
+ int & large, int & small)
+{
+ // octave
+ oct =default_octave;
+
+ while (1)
+ {
+ if (a[j] == '\'')
+ oct ++;
+ else if (a[j] == '`')
+ oct --;
+ else
+ break;
+ j++;
+
+ }
+
+ mtor << "oct " << oct;
+
+ // accidental
+ overide_acc = false;
+
+ if (a[j] == '!')
+ {
+ overide_acc = true;
+ j++;
+ }
+
+
+ // notename.
+ String nm;
+ while (isalpha(a[j]))
+ {
+ nm += a[j++];
+ }
+ if (isupper(nm[0]))
+ {
+ oct--;
+ nm.lower();
+ }
+
+
+ lookup_notename(large,small,nm);
+ mtor << "override: " << overide_acc;
+ mtor << "pitch "<< large <<", "<<small<<"\n";
+}
+
+
+Voice_element *
+get_note_element(String pitch, String durstr)
+{
+ Voice_element*v = new Voice_element;
+ int i=0;
+
+ int dur, dots;
+ parse_duration(durstr, i, dur, dots);
+ i=0;
+
+ Note_req * rq = new Note_req;
+
+ if (dur >= 2) {
+ Stem_req * st = new Stem_req(dur);
+ v->add(st);
+ }
+
+ int oct, pit, acc;
+ bool forceacc;
+ parse_pitch(pitch, i, oct, forceacc, pit, acc);
+ char nm = pit + 'c';
+ if (nm > 'g')
+ nm += 'a' - 'h';
+ rq->name =nm;
+
+ rq->octave = oct;
+ rq->accidental = acc;
+ rq->forceacc = forceacc;
+ rq->balltype = dur;
+ rq->dots = dots;
+
+ rq->print();
+
+ v->add(rq);
+
+ return v;
+}
+
+Voice_element *
+get_rest_element(String, String durstr)
+{
+ Voice_element*v = new Voice_element;
+ int i=0;
+
+ int dur, dots;
+ parse_duration(durstr, i, dur, dots);
+ i=0;
+
+ Rest_req * rq = new Rest_req;
+
+ rq->balltype = dur;
+ rq->dots = dots;
+ rq->print();
+ v->add(rq);
+
+ return v;
+}
+
+void
+set_default_duration(String d)
+{
+ int i=0;
+ parse_duration(d, i, default_duration, default_dots);
+}
+
+
+void
+set_default_pitch(String d)
+{
+ int i=0;
+ bool b;
+ int l,s;
+ parse_pitch(d, i, default_octave, b, l,s);
+}
+
+Request*
+get_request(char c)
+{
+ Request* ret=0;
+ switch (c) {
+ case '[':
+ case ']':
+ ret = new Beam_req;
+ break;
+
+ case ')':
+ case '(':
+ ret = new Slur_req;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ switch (c) {
+ case '(':
+ case '[':
+ ret->span()->spantype = Span_req::START;
+ break;
+ case ')':
+ case ']':
+ ret->span()->spantype = Span_req::STOP;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ return ret;
+}
+
+void
+add_requests(Voice_element *v, svec<Request*> &req)
+{
+ for (int i = 0; i < req.sz(); i++) {
+ v->add(req[i]);
+ }
+ req.set_size(0);
+}
diff --git a/src/notehead.cc b/src/notehead.cc
new file mode 100644
index 0000000000..a103e69b3d
--- /dev/null
+++ b/src/notehead.cc
@@ -0,0 +1,65 @@
+#include "notehead.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+
+
+Notehead::Notehead(int ss)
+{
+ staff_size=ss;
+ position = 0;
+ balltype = 0;
+ dots = 0;
+}
+
+void
+Notehead::print()const
+{
+ mtor << "Head "<<balltype<<", position = "<< position << "dots " << dots;
+ Item::print();
+}
+
+void
+Notehead::preprocess()
+{
+ brew_molecole();
+}
+
+void
+Notehead::brew_molecole()
+{
+ assert(pstaff_);
+ assert(!output);
+
+ Paperdef *p = paper();
+
+ Real dy = p->interline()/2;
+ Symbol s = p->lookup_->ball(balltype);
+
+ output = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d = p->lookup_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ if (!(position %2))
+ dm.translate(Offset(0,dy));
+ output->add_right(dm);
+ }
+ bool streepjes = (position<-1)||(position > staff_size+1);
+ if (streepjes) {
+ int dir = sgn(position);
+ int s =(position<-1) ? -((-position)/2): (position-staff_size)/2;
+ Symbol str = p->lookup_->streepjes(s);
+ Molecule sm;
+ sm.add(Atom(str));
+ if (position % 2)
+ sm.translate(Offset(0,-dy* dir));
+ output->add(sm);
+ }
+
+
+ output->translate(Offset(0,dy*position));
+}
+
diff --git a/src/notename.cc b/src/notename.cc
new file mode 100644
index 0000000000..8ebc4df244
--- /dev/null
+++ b/src/notename.cc
@@ -0,0 +1,30 @@
+#include "glob.hh"
+#include "string.hh"
+
+
+/// change this along with lex file for other notenames.
+const char *notetab[] =
+{
+"ceses", "ces", "c", "cis", "cisis",
+"deses", "des", "d", "dis", "disis",
+"eses", "es", "e", "eis", "eisis",
+"feses", "fes", "f", "fis", "fisis",
+"geses", "ges", "g", "gis", "gisis",
+"ases", "as", "a", "ais", "aisis",
+"beses", "bes", "b", "bis", "bisis",
+0
+};
+
+void
+lookup_notename(int &large, int &small, String s)
+{
+ int i;
+ for (i =0; notetab[i]; i++)
+ if (s == notetab[i])
+ {
+ large = i /5;
+ small = i %5 - 2;
+ return;
+ }
+ assert(false);
+}
diff --git a/src/paper.cc b/src/paper.cc
new file mode 100644
index 0000000000..8cd98339d4
--- /dev/null
+++ b/src/paper.cc
@@ -0,0 +1,82 @@
+#include <math.h>
+
+#include "paper.hh"
+#include "debug.hh"
+#include "lookup.hh"
+#include "dimen.hh"
+#include "textdb.hh"
+
+double log2(double x) {
+ return log(x) /log(2.0);
+}
+
+
+// golden ratio
+const Real PHI = (1+sqrt(5))/2;
+
+// see Roelofs, p. 57
+Real
+Paperdef::duration_to_dist(Real d)
+{
+ return whole_width * pow(geometric_, log2(d));
+}
+Real
+Paperdef::rule_thickness()const
+{
+ return convert_dimen(0.4, "pt");
+}
+Paperdef::Paperdef()
+{
+ lookup_ = new Lookup();
+ parse();
+ linewidth = convert_dimen(15,"cm"); // in cm for now
+ whole_width= 8*note_width();
+ geometric_ = PHI;
+}
+
+void
+Paperdef::parse()
+{
+ Text_db symini("symbol.ini");
+
+
+ while (!symini.eof()) {
+
+ Text_record r( symini++);
+
+ if (r[0] == "symboltables")
+ lookup_->parse(symini);
+ }
+}
+
+Paperdef::~Paperdef()
+{
+ delete lookup_;
+}
+
+Real
+Paperdef::interline() const
+{
+ return lookup_->ball(4).dim.y.length();
+}
+Real
+Paperdef::note_width()const
+{
+ return lookup_->ball(4).dim.x.length( );
+}
+Real
+Paperdef::standard_height() const
+{
+ return convert_dimen(20,"pt");
+}
+
+void
+Paperdef::print() const
+{
+#ifndef NPRINT
+ mtor << "Paper {width: " << print_dimen(linewidth);
+ mtor << "whole: " << print_dimen(whole_width);
+ mtor << "out: " <<outfile;
+ mtor << "}\n";
+#endif
+}
diff --git a/src/parser.y b/src/parser.y
new file mode 100644
index 0000000000..691d306e78
--- /dev/null
+++ b/src/parser.y
@@ -0,0 +1,292 @@
+%{ // -*-Fundamental-*-
+#include <iostream.h>
+
+#include "lexer.hh"
+#include "paper.hh"
+#include "staff.hh"
+#include "score.hh"
+#include "main.hh"
+#include "keyword.hh"
+#include "scommands.hh"
+#include "debug.hh"
+#include "parseconstruct.hh"
+#include "dimen.hh"
+#include "identifier.hh"
+
+#ifndef NDEBUG
+#define YYDEBUG 1
+#endif
+
+svec<Request*> pre_reqs, post_reqs;
+%}
+
+
+%union {
+ Real real;
+ Command *command;
+ Identifier *id;
+ Score_commands *scommands;
+ Voice *voice;
+ Voice_element *el;
+ Staff *staff;
+ String *string;
+ Score *score;
+ const char *consstr;
+ Paperdef *paper;
+ Request* request;
+ int i;
+ char c;
+}
+
+%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
+%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
+%token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
+
+%token <id> IDENTIFIER
+%token <string> NEWIDENTIFIER
+%token <string> PITCH DURATION RESTNAME
+%token <real> REAL
+%token <string> STRING
+%token <i> OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS
+
+
+%type <consstr> unit
+
+%type <id> declaration
+%type <paper> paper_block paper_body
+%type <real> dim
+%type <voice> voice_block voice_body voice_elts voice_elts_dollar
+%type <el> voice_elt
+%type <command> score_command
+%type <score> score_block score_body
+%type <staff> staff_block rhythmstaff_block rhythmstaff_body
+%type <staff> melodicstaff_block melodicstaff_body staffdecl
+%type <i> int
+%type <scommands> score_commands_block score_commands_body
+%type <request> post_request pre_request
+
+
+%%
+
+mudela: /* empty */
+ | mudela score_block {
+ add_score($2);
+ }
+ | mudela add_declaration { }
+ ;
+
+add_declaration: declaration {
+ add_identifier($1);
+ }
+ ;
+
+declaration:
+ NEWIDENTIFIER '=' staff_block {
+ $$ = new Staff_id(*$1, $3);
+ delete $1; // this sux
+ }
+ | NEWIDENTIFIER '=' voice_block {
+ $$ = new Voice_id(*$1, $3);
+ delete $1;
+ }
+ ;
+
+
+score_block: SCORE '{' score_body '}' { $$ = $3; }
+ ;
+
+score_body: { $$ = new Score; }
+ | score_body staff_block { $$->add($2); }
+ | score_body score_commands_block { $$->set($2); }
+ | score_body paper_block { $$->set($2); }
+ ;
+score_commands_block:
+ COMMANDS '{' score_commands_body '}' { $$ =$3;}
+ ;
+
+score_commands_body: { $$ = new Score_commands; }
+ | score_commands_body score_command {
+ $$->parser_add($2);
+ }
+ ;
+
+paper_block:
+ PAPER '{' paper_body '}' { $$ = $3; }
+ ;
+
+paper_body:
+ /* empty */ { $$ = new Paperdef; }
+ | paper_body WIDTH dim { $$->linewidth = $3;}
+ | paper_body OUTPUT STRING { $$->outfile = *$3;
+ delete $3;
+ }
+ | paper_body UNITSPACE dim { $$->whole_width = $3; }
+ | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
+ ;
+
+dim:
+ REAL unit { $$ = convert_dimen($1,$2); }
+ ;
+
+
+unit: CM { $$ = "cm"; }
+ |IN { $$ = "in"; }
+ |MM { $$ = "mm"; }
+ |PT { $$ = "pt"; }
+ ;
+
+/*
+ staff
+*/
+staff_block:
+ staffdecl
+ | rhythmstaff_block
+ | melodicstaff_block
+ ;
+
+staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); }
+ ;
+
+rhythmstaff_block:
+ RHYTHMSTAFF '{' rhythmstaff_body '}' { $$ = $3; }
+ ;
+
+rhythmstaff_body:
+ /* empty */ { $$ = get_new_rhythmstaff(); }
+ | rhythmstaff_body voice_block { $$->add_voice($2); }
+ ;
+
+melodicstaff_block:
+ MELODICSTAFF '{' melodicstaff_body '}' { $$ = $3; }
+ ;
+
+melodicstaff_body:
+ /* empty */ { $$ = get_new_melodicstaff(); }
+ | melodicstaff_body voice_block { $$->add_voice($2); }
+ ;
+
+/*
+ voice
+*/
+voice_block:
+ VOICE '{' voice_body '}' { $$ = $3; }
+ ;
+
+
+voice_body:
+ IDENTIFIER { $$ = new Voice(*$1->voice()); }
+ | voice_elts_dollar { $$ = $1; }
+ | voice_body START_T REAL { $$->start = $3; }
+ ;
+
+
+
+
+voice_elts_dollar:
+ '$' voice_elts '$' { $$ = $2; }
+ ;
+
+voice_elts:
+ /* empty */ {
+ $$ = new Voice;
+ }
+ | voice_elts pre_requests voice_elt post_requests {
+ add_requests($3, pre_reqs);
+ add_requests($3, post_reqs);
+ $$->add($3);
+ }
+
+ | voice_elts voice_command { }
+ ;
+
+post_requests:
+ {
+ assert(post_reqs.empty());
+ }
+ | post_requests post_request {
+ post_reqs.add($2);
+ }
+ ;
+
+post_request:
+ CLOSE_REQUEST_PARENS { $$ = get_request($1); }
+ ;
+
+pre_requests:
+ | pre_requests pre_request {
+ pre_reqs.add($2);
+ }
+ ;
+
+pre_request:
+ OPEN_REQUEST_PARENS { $$ = get_request($1); }
+ ;
+/*
+*/
+voice_command:
+ DURATIONCOMMAND DURATION {
+ set_default_duration(*$2);
+ delete $2;
+ }
+ | OCTAVECOMMAND PITCH {
+ set_default_pitch(*$2);
+ delete $2;
+ }
+ ;
+
+voice_elt:
+ PITCH DURATION {
+ $$ = get_note_element(*$1, *$2);
+ delete $1;
+ delete $2;
+ }
+ | RESTNAME DURATION {
+ $$ = get_rest_element(*$1, *$2);
+ delete $1;
+ delete $2;
+ }
+ | PITCH { $$ = get_note_element(*$1, "");
+ delete $1;
+ }
+ | RESTNAME { $$ = get_rest_element(*$1, "");
+ delete $1;
+ }
+ ;
+
+score_command:
+ SKIP int ':' REAL {
+ $$ = get_skip_command($2, $4);
+ }
+ | METER int int {
+ $$ = get_meterchange_command($2, $3);
+ }
+/* | PARTIALMEASURE REAL {
+ $$ = get_partial_command($2);
+ }*/
+ ;
+
+
+int:
+ REAL {
+ $$ = int($1);
+ if (ABS($1-Real(int($$))) > 1e-8)
+ yyerror("expecting integer number");
+
+ }
+ ;
+
+%%
+
+void
+parse_file(String s)
+{
+ *mlog << "Parsing ... ";
+#ifdef YYDEBUG
+ yydebug = !monitor.silence("Parser");
+#endif
+ new_input(s);
+ yyparse();
+ delete_identifiers();
+ kill_lexer();
+ *mlog << "\n";
+}
diff --git a/src/pcol.cc b/src/pcol.cc
new file mode 100644
index 0000000000..902f57bab2
--- /dev/null
+++ b/src/pcol.cc
@@ -0,0 +1,118 @@
+#include "pcol.hh"
+#include "pstaff.hh"
+#include "debug.hh"
+
+void
+Idealspacing::print() const
+{
+#ifndef NPRINT
+ mtor << "idealspacing {" ;
+ mtor << "distance "<<space<< " strength " << hooke << "}\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
+}
+
+/****************************************************************/
+
+Interval
+PCol::width() const
+{
+ Interval w;
+
+ for (PCursor<const Item *> ic(its); ic.ok(); ic++)
+ w.unite(ic->width());
+ if (w.empty())
+ w.unite(Interval(0,0));
+ return w;
+}
+
+void
+PCol::print() const
+{
+ #ifndef NPRINT
+ mtor << "PCol {";
+ mtor << "# symbols: " << its.size() ;
+ if (breakable()){
+ mtor << "pre,post: ";
+ prebreak->print();
+ postbreak->print();
+ }
+ mtor << "extent: " << width().min << ", " << width().max << "\n";
+ mtor << "}\n";
+ #endif
+}
+
+int
+PCol::compare(const PCol &, const PCol &)
+{
+ assert(false);
+ return 0 ;
+}
+
+void
+PCol::OK () const
+{
+ if (prebreak || postbreak ) {
+ assert(prebreak&&postbreak);
+ assert(prebreak->daddy == this);
+ assert(postbreak->daddy == this);
+ }
+
+}
+
+void
+PCol::set_breakable()
+{
+ if (breakable())
+ return;
+
+ prebreak = new PCol(this);
+ postbreak = new PCol(this);
+ used = true;
+}
+
+bool
+PCol::breakable() const
+{
+ return prebreak||postbreak;
+}
+
+PCol::PCol(PCol *parent) {
+ daddy = parent;
+ prebreak=0;
+ postbreak=0;
+ line=0;
+ used = false;
+}
+
+PCol::~PCol()
+{
+
+ delete prebreak;
+
+ delete postbreak;
+}
+
+void
+PCol::add( Item *i)
+{
+ its.bottom().add(i);
+ i->pcol_ = this;
+ used = true;
+}
+
diff --git a/src/pscore.cc b/src/pscore.cc
new file mode 100644
index 0000000000..8d7067760f
--- /dev/null
+++ b/src/pscore.cc
@@ -0,0 +1,205 @@
+// utility functions for PScore
+#include "debug.hh"
+#include "spanner.hh"
+#include "paper.hh"
+#include "molecule.hh"
+#include "dimen.hh"
+#include "scoreline.hh"
+#include "pscore.hh"
+#include "tstream.hh"
+
+
+void
+PScore::clean_cols()
+{
+ for (PCursor<PCol *> c(cols); c.ok(); )
+ if (!c->used) {
+ c.del();
+ } else
+ c++;
+}
+
+
+void
+PScore::add(PStaff *s)
+{
+ assert(s->pscore_ == this);
+ staffs.bottom().add(s);
+}
+
+void
+PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat)
+{
+ assert(c && i && s);
+// assert(!breakstat != 4 || c->breakable() );
+ if (breakstat == 0) {
+ typeset_item(i, c->prebreak, s);
+ return;
+ }
+
+ if (breakstat == 2) {
+ typeset_item(i, c->postbreak, s);
+ return;
+ }
+
+
+ its.bottom().add(i);
+ s->add(i);
+ c->add(i);
+
+ /* first do this, because i->width() may follow the 0-pointer */
+ i->preprocess();
+
+
+ if (c->daddy && c == c->daddy->prebreak) { // makeshift.
+
+ Interval iv (i->width());
+ if (!iv.empty()) {
+ svec<Item*> col_its (select_items(s, c));
+ for (int j =0; j < col_its.sz(); j++)
+ col_its[j]->translate(Offset(-iv.length(),0));
+ i->translate (Offset(-iv.max, 0));
+ }
+ }
+
+}
+
+void
+PScore::typeset_spanner(Spanner*sp, PStaff*ps)
+{
+ sp->preprocess();
+ sp->pstaff_ = ps;
+ spanners.bottom().add(sp);
+ ps->spans.bottom().add(sp);
+ sp->left->starters.bottom().add(sp);
+ sp->right->stoppers.bottom().add(sp);
+}
+
+
+void
+PScore::add_line(svec<const PCol *> curline, svec<Real> config)
+{
+ Line_of_score *p = new Line_of_score(curline,this);
+ lines.bottom().add(p);
+ for (int i=0; i < curline.sz(); i++){
+ PCol *c=(PCol *)curline[i]; // so, this isn't really const.
+ c->hpos= config[i];
+ }
+}
+
+Idealspacing*
+PScore::get_spacing(PCol*l, PCol*r)
+{
+ assert(l!=r);
+ for (PCursor<Idealspacing*> ic (suz); ic.ok(); ic++) {
+ if (ic->left == l && ic->right == r){
+ return ic;
+ }
+ }
+
+ Idealspacing*ip =new Idealspacing(l,r);
+ suz.bottom().add(ip);
+
+ return ip;
+}
+
+
+/*
+ return all breakable columns
+ */
+svec<const PCol *>
+PScore::find_breaks() const
+{
+ svec<const PCol *> retval;
+ for (PCursor<PCol *> c(cols); c.ok(); c++)
+ if (c->breakable())
+ retval.add(c);
+
+ return retval;
+}
+
+void
+PScore::add(PCol *p)
+{
+ cols.bottom().add(p);
+}
+
+PScore::PScore( Paperdef*p)
+{
+ paper_ = p;
+}
+
+void
+PScore::output(Tex_stream &ts)
+{
+ int l=1;
+
+ for (PCursor<Line_of_score*> lic(lines); lic.ok(); lic++) {
+ ts << "% line of score no. " << l++ <<"\n";
+ ts << lic->TeXstring();
+ if ((lic+1).ok())
+ ts << "\\interscoreline\n";
+ }
+}
+
+
+svec<Item*>
+PScore::select_items(PStaff*ps , PCol*pc)
+{
+ svec<Item*> ret;
+ assert(ps && pc);
+ for (PCursor<const Item*> ic(pc->its); ic.ok(); ic++){
+ if (ic->pstaff_ == ps)
+ ret.add((Item*)(const Item*)ic);
+ }
+ return ret;
+}
+
+void
+PScore::OK()const
+{
+#ifdef NDEBUG
+ for (PCursor<PCol*> cc(cols); cc.ok(); cc++)
+ cc->OK();
+ for (PCursor<Idealspacing*> ic(suz); ic.ok(); ic++)
+ ic->OK();
+#endif
+}
+
+void
+PScore::print() const
+{
+#ifndef NPRINT
+ mtor << "PScore { ";
+ paper_->print();
+ mtor << "\ncolumns: ";
+ for (PCursor<PCol*> cc(cols); cc.ok(); cc++)
+ cc->print();
+
+ mtor << "\nideals: ";
+ for (PCursor<Idealspacing*> ic(suz); ic.ok(); ic++)
+ ic->print();
+ mtor << "}\n";
+#endif
+}
+
+void
+PScore::preprocess()
+{
+#if 0
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->preprocess();
+ }
+#endif
+}
+
+void
+PScore::postprocess()
+{
+ for (PCursor<Spanner*> ic(spanners); ic.ok(); ic++) {
+ ic->process();
+ }
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->postprocess();
+ }
+}
diff --git a/src/pstaff.cc b/src/pstaff.cc
new file mode 100644
index 0000000000..255fceeadd
--- /dev/null
+++ b/src/pstaff.cc
@@ -0,0 +1,14 @@
+#include "pstaff.hh"
+
+PStaff::PStaff(PScore*ps)
+{
+ pscore_=ps;
+ stafsym = 0;
+}
+
+void
+PStaff::add(Item *i )
+{
+ its.bottom().add(i);
+ i->pstaff_ = this;
+}
diff --git a/src/qlp.cc b/src/qlp.cc
new file mode 100644
index 0000000000..3dd8e4227e
--- /dev/null
+++ b/src/qlp.cc
@@ -0,0 +1,147 @@
+#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.add(i);
+ eq_consrhs.add(r);
+}
+
+void
+Ineq_constrained_qp::add_inequality_cons(Vector c, double r)
+{
+ cons.add(c);
+ consrhs.add(r);
+}
+
+Ineq_constrained_qp::Ineq_constrained_qp(int novars):
+ quad(novars),
+ lin(novars)
+{
+}
+
+void
+Ineq_constrained_qp::OK() const
+{
+#ifndef NDEBUG
+ assert(cons.sz() == consrhs.sz());
+ 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.sz()-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.sz(); i++) {
+ sol.insert( eq_consrhs[i],eq_cons[i]);
+ }
+ return sol;
+}
+
+/*
+ assume x(idx) == value, and adjust constraints, lin and quad accordingly
+ */
+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.sz(); i++) {
+ consrhs[i] -= cons[i](idx) *value;
+ cons[i].del(idx);
+ }
+}
+
+
+
+
+Mixed_qp::Mixed_qp(int n)
+ : Ineq_constrained_qp(n)
+{
+}
+
+void
+Mixed_qp::OK() const
+{
+#ifndef NDEBUG
+ Ineq_constrained_qp::OK();
+ assert(eq_consrhs.sz() == eq_cons.sz());
+#endif
+}
+void
+Ineq_constrained_qp::print() const
+{
+#ifndef NPRINT
+ mtor << "Quad " << quad;
+ mtor << "lin " << lin <<"\n";
+ for (int i=0; i < cons.sz(); i++) {
+ mtor << "constraint["<<i<<"]: " << cons[i] << " >= " << consrhs[i];
+ mtor << "\n";
+ }
+#endif
+}
+void
+Mixed_qp::print() const
+{
+#ifndef NPRINT
+ Ineq_constrained_qp::print();
+ for (int i=0; i < eq_cons.sz(); i++) {
+ mtor << "eq cons "<<i<<": x["<<eq_cons[i]<<"] == " << eq_consrhs[i]<<"\n";
+ }
+#endif
+}
+
+
+void
+Ineq_constrained_qp::assert_solution(Vector sol) const
+{
+ svec<int> binding;
+ for (int i=0; i < cons.sz(); i++) {
+ Real R=cons[i] * sol- consrhs[i];
+ assert(R> -EPS);
+ if (R < EPS)
+ binding.add(i);
+ }
+ // KKT check...
+ // todo
+}
diff --git a/src/qlpsolve.cc b/src/qlpsolve.cc
new file mode 100644
index 0000000000..13bd30e89b
--- /dev/null
+++ b/src/qlpsolve.cc
@@ -0,0 +1,255 @@
+#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.sz(); i++) {
+ s += String(active[i]) + " ";
+ }
+
+ s+="| ";
+ for (int i=0; i< inactive.sz(); i++) {
+ s += String(inactive[i]) + " ";
+ }
+ s+="]";
+
+ return s;
+}
+
+void
+Active_constraints::OK() {
+ H.OK();
+ A.OK();
+ assert(active.sz() +inactive.sz() == opt->cons.sz());
+ assert(H.dim() == opt->dim());
+ assert(active.sz() == A.rows());
+ svec<int> allcons;
+
+ for (int i=0; i < opt->cons.sz(); i++)
+ allcons.add(0);
+ for (int i=0; i < active.sz(); i++) {
+ int j = active[i];
+ allcons[j]++;
+ }
+ for (int i=0; i < inactive.sz(); i++) {
+ int j = inactive[i];
+ allcons[j]++;
+ }
+ for (int i=0; i < allcons.sz(); i++)
+ assert(allcons[i] == 1);
+}
+
+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.add(cidx);
+
+ inactive.swap(k,inactive.sz()-1);
+ inactive.pop();
+
+ Vector a( opt->cons[cidx] );
+ // update of matrices
+ Vector Ha = H*a;
+ Real aHa = a*Ha;
+ 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 , Ha)/(aHa);
+
+
+ /*
+ sorry, don't know how to justify this. ..
+ */
+ Vector addrow(Ha/(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.sz()-1;
+
+ // drop indices
+ inactive.add(active[k]);
+ active.swap(k,q);
+ A.swap_rows(k,q);
+ active.pop();
+
+ Vector a(A.row(q));
+ if (a.norm() > EPS) {
+ /*
+
+ */
+ H += Matrix(a,a)/(a*opt->quad*a);
+ A -= A*opt->quad*Matrix(a,a)/(a*opt->quad*a);
+ }else
+ WARN << "degenerate constraints";
+ Vector rem_row(A.row(q));
+ assert(rem_row.norm() < EPS);
+ 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.sz(); i++)
+ inactive.add(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
+Vector
+Ineq_constrained_qp::solve(Vector start) const
+{
+ Active_constraints act(this);
+
+
+ act.OK();
+
+
+ Vector x(start);
+ Vector gradient=quad*x+lin;
+
+
+ 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;
+}
+
+/** 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) )
+
+
+ */
+
diff --git a/src/request.cc b/src/request.cc
new file mode 100644
index 0000000000..9928f62bed
--- /dev/null
+++ b/src/request.cc
@@ -0,0 +1,101 @@
+#include "request.hh"
+#include "debug.hh"
+
+#define VIRTUALCONS(T,R) R *T::clone() const { return new T(*this); } struct T
+#define RCONS(T) VIRTUALCONS(T, Request)
+
+RCONS(Rest_req);
+RCONS(Rhythmic_req);
+RCONS(Stem_req);
+RCONS(Note_req);
+RCONS(Span_req);
+RCONS(Slur_req);
+RCONS(Beam_req);
+
+void
+Request::print() const
+{
+#ifndef NPRINT
+ mtor << "Req{ unknown }\n";
+#endif
+}
+
+Request::Request()
+{
+ elt = 0;
+}
+
+Note_req::Note_req()
+{
+ name = 'c';
+ octave = 0;
+ accidental = 0;
+ forceacc = false;
+}
+
+int
+Note_req::height() const
+{
+ int s = name -'c';
+ if (s < 0)
+ s+=7;
+ return s + octave*7;
+}
+
+Rhythmic_req::Rhythmic_req()
+{
+ balltype = 1;
+ dots = 0;
+}
+
+void
+Rhythmic_req::print() const
+{
+ mtor << "rhythmic: " << balltype ;
+ int d =dots;
+ while (d--)
+ mtor << '.';
+ mtor<<"\n";
+}
+
+void
+Note_req::print() const
+{
+ mtor << "note: " << name << " oct: "<< octave;
+ Rhythmic_req::print();
+}
+
+void
+Rest_req::print() const
+{
+ mtor << "rest, " ;
+ Rhythmic_req::print();
+}
+
+Real
+wholes(int dur, int dots)
+{
+ Real f = 1.0/Real(dur);
+ Real delta = f;
+
+ while (dots--) {
+ delta /= 2.0;
+ f += delta;
+ }
+ return f;
+}
+
+Real
+Rhythmic_req::duration() const {
+ return wholes( balltype,dots);
+}
+
+Beam_req::Beam_req()
+{
+ nplet = 0;
+}
+
+Span_req::Span_req()
+{
+ spantype = NOSPAN;
+}
diff --git a/src/rest.cc b/src/rest.cc
new file mode 100644
index 0000000000..e448df37bd
--- /dev/null
+++ b/src/rest.cc
@@ -0,0 +1,47 @@
+#include "rest.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+
+
+Rest::Rest(int t, int d)
+{
+ balltype = t;
+ dots = d;
+}
+
+void
+Rest::print()const
+{
+ mtor << "Rest "<<balltype<< "dots " << dots;
+ Item::print();
+}
+
+void
+Rest::preprocess()
+{
+ brew_molecole();
+}
+
+void
+Rest::brew_molecole()
+{
+ assert(pstaff_);
+ assert(!output);
+ Paperdef *p =paper();
+
+ Symbol s;
+ s = p->lookup_->rest(balltype);
+
+ Molecule *m = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d =p->lookup_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ m->add_right(dm);
+ }
+ output = m;
+}
+
diff --git a/src/rhythmstaff.cc b/src/rhythmstaff.cc
new file mode 100644
index 0000000000..e584254bfd
--- /dev/null
+++ b/src/rhythmstaff.cc
@@ -0,0 +1,62 @@
+#include "molecule.hh"
+#include "notehead.hh"
+#include "stem.hh"
+#include "linestaff.hh"
+#include "rhythmstaff.hh"
+#include "paper.hh"
+#include "sccol.hh"
+#include "rest.hh"
+
+void
+Rhythmic_staff::set_output(PScore*ps)
+{
+ theline = new Linestaff(1,ps);
+ Simple_staff::set_output(ps);
+}
+
+Item *
+Rhythmic_staff::get_TYPESET_item(Command *com)
+{
+ Item *i = Simple_staff::get_TYPESET_item(com);
+ i->translate(Offset(0,
+ -score_->paper_->standard_height()/2));
+ return i;
+}
+
+Notehead*
+Rhythmic_staff::get_notehead(Note_req *rq)
+{
+ int b = rq->rhythmic()->balltype;
+ int d = rq->rhythmic()->dots;
+
+ Notehead *n =new Notehead(1);
+ n->balltype = b;
+ n->dots =d;
+ n->position = 0;
+ return n;
+}
+
+Stem *
+Rhythmic_staff::get_stem(Stem_req*rq)
+{
+ Stem * s = new Stem(0);
+ s->flag = rq->stem_number;
+ return s;
+}
+
+/*
+ creation
+ */
+Staff *
+get_new_rhythmstaff()
+{
+ return new Rhythmic_staff;
+}
+
+
+
+Rhythmic_staff*
+Rhythmic_staff::clone() const
+{
+ return new Rhythmic_staff(*this);
+}
diff --git a/src/sccol.cc b/src/sccol.cc
new file mode 100644
index 0000000000..1dfc8f2176
--- /dev/null
+++ b/src/sccol.cc
@@ -0,0 +1,28 @@
+#include "sccol.hh"
+#include "debug.hh"
+
+Score_column::Score_column(Real w)
+{
+ when = w;
+ pcol = new PCol(0);
+ musical = false;
+}
+
+bool
+Score_column::used() {
+ return pcol->used;
+}
+
+void
+Score_column::print() const
+{
+#ifndef NPRINT
+ mtor << "Score_column { mus "<< musical <<" at " << when<<'\n';
+ mtor << "durations: [";
+ for (int i=0; i < durations.sz(); i++)
+ mtor << durations[i] << " ";
+ mtor << "]\n";
+ pcol->print();
+ mtor << "}\n";
+#endif
+}
diff --git a/src/scommands.cc b/src/scommands.cc
new file mode 100644
index 0000000000..7b8c8ed9c5
--- /dev/null
+++ b/src/scommands.cc
@@ -0,0 +1,266 @@
+#include "scommands.hh"
+#include "debug.hh"
+#include "parseconstruct.hh"
+
+/*
+ maybe it's time for a "narrowing" cursor?
+ */
+PCursor<Command*>
+Score_commands::first(Real w)
+{
+ PCursor<Command*> pc(*this);
+ while (pc.ok() && pc->when < w)
+ pc++;
+
+ return pc;
+}
+
+PCursor<Command*>
+Score_commands::last_insertion(Real w)
+{
+ PCursor<Command*> pc(*this);
+ while (pc.ok() && pc->when <= w)
+ pc++;
+ return pc;
+}
+
+void
+Score_commands::add_seq(svec<Command> com)
+{
+ if (!com.sz())
+ return;
+ Real when = com[0].when;
+
+ PCursor<Command*> pc(last_insertion(when));
+ for (int i = 0; i < com.sz(); i++) {
+ Command *c = new Command(com[i]);
+ assert(com[i].when == when);
+ if (!pc.ok())
+ pc.add(c);
+ else
+ pc.insert(c);
+ }
+}
+
+void
+Score_commands::set_breakable(Real when)
+{
+ bool found_typeset(false);
+ PCursor<Command*> cc = first(when);
+ for (; cc.ok() && cc->when == when; cc++) {
+ if (cc->isbreak())
+ return;
+ if (cc->code == TYPESET)
+ found_typeset=true;
+ }
+
+ assert(!found_typeset);
+
+ svec<Command> seq;
+ Command k(when);
+ k.code = BREAK_PRE;
+ seq.add(k);
+ k.code = BREAK_MIDDLE;
+ seq.add(k);
+ k.code = BREAK_POST;
+ seq.add(k);
+ k.code = BREAK_END;
+ seq.add(k);
+
+ add_seq(seq);
+}
+
+bool
+Score_commands::is_breakable(Real w)
+{
+ PCursor<Command*> cc = first(w);
+ for (; cc.ok() && cc->when == w; cc++) {
+ if (cc->isbreak())
+ return true;
+ }
+ return false;
+}
+
+void
+Score_commands::insert_between(Command victim, PCursor<Command*> firstc,
+ PCursor<Command*> last)
+{
+ assert(last->when==firstc->when);
+ PCursor<Command*> c(firstc+1);
+ while (c != last) { // hmm what if !last.ok()?
+ if (victim.priority > c->priority) {
+ c.insert(new Command(victim));
+ return;
+ }
+ c++;
+ }
+ last.insert(new Command(victim));
+}
+
+void
+Score_commands::add_command_to_break(Command pre, Command mid, Command post)
+{
+ Real w = pre.when;
+ PCursor<Command*> c ( first(w)), f(c), l(c);
+
+ while (!c->isbreak())
+ c++;
+ f = c++;
+ while (!c->isbreak())
+ c++;
+ l = c++;
+
+ insert_between(pre, f, l);
+ f = l;
+ while (!c->isbreak())
+ c++;
+ l = c++;
+ insert_between(mid, f, l);
+ f = l;
+ while (!c->isbreak())
+ c++;
+ l = c++;
+ insert_between(post, f, l);
+ assert(l.ok() && l->when ==w && l->code == BREAK_END);
+}
+
+void
+Score_commands::parser_add(Command *c)
+{
+ bottom().add(c);
+}
+
+void
+Score_commands::process_add(Command c)
+{
+ bool encapsulate =false;
+ Real w = c.when;
+ Command pre(w);
+ Command mid(w);
+ Command post(w);
+
+
+ if (c.code == TYPESET) {
+ if (c.args[0] == "BAR") {
+ set_breakable(w);
+ encapsulate = true;
+ mid = c;
+ pre = c;
+ }
+ if (c.args[0] == "METER" && is_breakable(w)) {
+ encapsulate = true;
+ mid = c;
+ pre = c;
+ post =c;
+ }
+ }
+
+ if (encapsulate)
+ add_command_to_break(pre, mid, post);
+ else {
+ svec<Command> seq;
+ seq.add(c);
+ add_seq(seq);
+ }
+}
+
+/*
+ first and last column should be breakable.
+ Remove any command past the last musical column.
+ */
+void
+Score_commands::clean(Real l)
+{
+ assert(l>0);
+ if (!is_breakable(0.0)) {
+ Command c(0.0);
+ c.code = TYPESET;
+ c.args.add("BAR");
+ c.args.add("empty");
+ process_add(c);
+ }
+
+ PCursor<Command*> bot(bottom());
+
+ while (bot.ok() && bot->when > l) {
+ mtor <<"removing ";
+ bot->print();
+ bot.del();
+ bot = bottom();
+ }
+
+ if (!is_breakable(l)) {
+ Command c(l);
+ c.code = TYPESET;
+ c.args.add("BAR");
+ c.args.add("||");
+ process_add(c);
+ }
+ OK();
+}
+
+void
+Score_commands::OK() const
+{
+ for (PCursor<Command*> cc(*this); cc.ok() && (cc+1).ok(); cc++) {
+ assert(cc->when <= (cc+1)->when);
+ if (cc->when == (cc+1)->when && !cc->isbreak() && !(cc+1)->isbreak())
+ assert(cc->priority >= (cc+1)->priority);
+ }
+}
+
+void
+Score_commands::print() const
+{
+ for (PCursor<Command*> cc(*this); cc.ok() ; cc++) {
+ cc->print();
+ }
+}
+
+/*
+ TODO
+ */
+Score_commands*
+Score_commands::parse(Real l) const
+{
+ Score_commands*nc = new Score_commands;
+ int beats_per_meas=4;
+ Real measlen = 1.0; // 4/4 by default
+
+ Real inbar=0.0;
+ int barcount=0;
+ Real wholes=0.0;
+ Real stoppos=0.0;
+
+ {
+ Command c(0.0);
+ c.code = TYPESET;
+ c.args.add("BAR");
+ c.args.add("empty");
+ nc->process_add(c);
+ }
+ for (PCursor<Command*> cc(*this); cc.ok() && cc->when <= l; cc++) {
+ assert (cc->code==INTERPRET);
+ if (cc->args[0] == "METER") {
+ beats_per_meas = cc->args[1].value();
+ int one_beat = cc->args[2].value();
+ measlen = beats_per_meas/Real(one_beat);
+ nc->process_add(*get_meter_command(wholes, beats_per_meas, one_beat));
+ }
+ if (cc->args[0] == "SKIP") {
+ stoppos = wholes + cc->args[1].value() * measlen +
+ cc->args[2].fvalue();
+ wholes += (measlen-inbar); // skip at least 1 measure
+ barcount++;
+ while (wholes <= stoppos) {
+ nc->process_add(*get_bar_command(wholes)); // liek
+ wholes += measlen;
+ barcount ++;
+ }
+ wholes = stoppos;
+ //something
+ }
+ }
+
+ return nc;
+}
diff --git a/src/score.cc b/src/score.cc
new file mode 100644
index 0000000000..1df13365f2
--- /dev/null
+++ b/src/score.cc
@@ -0,0 +1,224 @@
+#include "scommands.hh"
+#include "tstream.hh"
+#include "score.hh"
+#include "sccol.hh"
+#include "pscore.hh"
+#include "staff.hh"
+#include "debug.hh"
+#include "paper.hh"
+
+void
+Score::set(Paperdef*p)
+{
+ delete paper_;
+ paper_ = p;
+}
+
+void
+Score::output(String s)
+{
+ OK();
+ if (paper_->outfile=="")
+ paper_->outfile = s;
+
+ *mlog << "output to " << paper_->outfile << "...\n";
+ Tex_stream the_output(paper_->outfile);
+ pscore_->output(the_output);
+}
+
+
+void
+Score::process()
+{
+ *mlog << "Processing ... ";
+ set(commands_->parse(last()));
+ commands_->print();
+
+ if (!paper_)
+ paper_ = new Paperdef;
+
+ commands_->clean(last());
+
+ /// distribute commands to disciples
+ distribute_commands();
+
+ pscore_ = new PScore(paper_);
+ for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
+ sc->set_output(pscore_);
+ sc->process();
+ }
+
+ // do this after processing, staffs first have to generate PCols.
+ do_pcols();
+ calc_idealspacing();
+ clean_cols();
+ OK();
+ // print();
+
+ pscore_->preprocess();
+ *mlog << "Calculating ... ";
+ pscore_->calc_breaking();
+ pscore_->postprocess();
+
+ // TODO: calculate vertical structs
+ // TODO: calculate mixed structs.
+ *mlog << "\n";
+}
+
+// remove empty cols with no spacing attached.
+/* should rethink ownership of cols
+ */
+void
+Score::clean_cols()
+{
+ for (PCursor<Staff * > sc(staffs_); sc.ok(); sc++)
+ sc->clean_cols();
+
+ for (PCursor<Score_column*> c(cols_); c.ok(); ) {
+ if (!c->pcol->used) {
+ mtor << "removing : ";
+ c->print();
+ c.del();
+ } else
+ c++;
+ }
+
+ pscore_->clean_cols();
+}
+/* this sux. We should have Score_column create the appropriate PCol.
+ Unfortunately, PCols don't know about their position.
+ */
+// todo
+PCursor<Score_column*>
+Score::create_cols(Real w)
+{
+ Score_column* c1 = new Score_column(w);
+ Score_column* c2 = new Score_column(w);
+
+ c1->musical = false;
+ c2->musical = true;
+
+ PCursor<Score_column*> scc(cols_);
+
+ for (; scc.ok(); scc++) {
+ assert(scc->when != w);
+ if (scc->when > w)
+ break;
+ }
+
+ if (!scc.ok()) {
+ cols_.bottom().add(c1);
+ cols_.bottom().add(c2);
+ scc = cols_.bottom();
+ scc --;
+ } else {
+ scc.insert(c1);
+ scc.insert(c2);
+ scc -= 2;
+ }
+ return scc;
+}
+
+Score_column*
+Score::find_col(Real w,bool mus)
+{
+ PCursor<Score_column*> scc(cols_);
+ for (; scc.ok(); scc++) {
+ if (scc->when == w && scc->musical == mus)
+ return scc;
+ if (scc->when > w)
+ break;
+ }
+ scc = create_cols(w);
+ if (mus)
+ scc++;
+ return scc;
+}
+
+void
+Score::distribute_commands(void)
+{
+ for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
+ sc->add_commands(*commands_);
+ }
+}
+void
+Score::add(Staff*s)
+{
+ s->score_ = this;
+ staffs_.bottom().add(s);
+}
+
+
+void
+Score::do_pcols()
+{
+ PCursor<Score_column*> sc(cols_);
+ for (; sc.ok(); sc++) {
+ pscore_->add(sc->pcol);
+ }
+}
+Real
+Score::last() const
+{
+ Real l = 0;
+ for (PCursor<Staff*> stc(staffs_); stc.ok(); stc++) {
+ l = MAX(l, stc->last());
+ }
+ return l;
+}
+
+void
+Score::OK() const
+{
+#ifndef NDEBUG
+ for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
+ sc->OK();
+ assert(sc->score_ == this);
+ }
+ staffs_.OK();
+ cols_.OK();
+ for (PCursor<Score_column*> cc(cols_); cc.ok() && (cc+1).ok(); cc++) {
+ assert(cc->when <= (cc+1)->when);
+ }
+ commands_->OK();
+#endif
+}
+
+
+void
+Score::print() const
+{
+#ifndef NPRINT
+ mtor << "score {\n";
+ for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
+ sc->print();
+ }
+ for (PCursor<Score_column*> sc(cols_); sc.ok(); sc++) {
+ sc->print();
+ }
+ commands_->print();
+ mtor << "}\n";
+#endif
+}
+
+Score::Score()
+{
+ pscore_=0;
+ paper_ = 0;
+ commands_ = new Score_commands;
+}
+
+Score::~Score()
+{
+ delete pscore_;
+ delete commands_;
+ delete paper_;
+}
+
+void
+Score::set(Score_commands*c)
+{
+ delete commands_;
+ commands_ = c;
+}
diff --git a/src/scoreline.cc b/src/scoreline.cc
new file mode 100644
index 0000000000..7e40c6a76a
--- /dev/null
+++ b/src/scoreline.cc
@@ -0,0 +1,43 @@
+#include "scoreline.hh"
+#include "staffline.hh"
+#include "dimen.hh"
+#include "spanner.hh"
+#include "symbol.hh"
+#include "paper.hh"
+#include "pcol.hh"
+#include "pscore.hh"
+
+
+String
+Line_of_score::TeXstring() const
+{
+ String s("\\vbox{%<- line of score\n");
+ for (PCursor<Line_of_staff*> sc(staffs); sc.ok(); sc++){
+ s += sc->TeXstring();
+ if ((sc+1).ok())
+ s+= "\\interstaffline\n";
+ }
+ s += "}";
+ return s;
+}
+
+
+Line_of_score::Line_of_score(svec<const PCol *> sv,
+ const PScore *ps)
+{
+ score = ps;
+ for (int i=0; i< sv.sz(); i++) {
+ PCol *p=(PCol *) sv[i];
+ cols.bottom().add(p);
+ p->line=this;
+ }
+
+ for (PCursor<PStaff*> sc(score->staffs); 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!!
+ */
+
diff --git a/src/scores.cc b/src/scores.cc
new file mode 100644
index 0000000000..04efd6e4b1
--- /dev/null
+++ b/src/scores.cc
@@ -0,0 +1,34 @@
+#include "main.hh"
+#include "score.hh"
+#include "string.hh"
+
+static svec<Score*> sv;
+
+static String outfn="lelie.uit";
+
+// todo: check we don't overwrite default output.
+
+void
+do_scores()
+{
+ for (int i=0; i < sv.sz(); i++) {
+ sv[i]->process();
+ sv[i]->output(outfn);
+ delete sv[i];
+ sv[i] =0;
+ }
+}
+
+void
+add_score(Score * s)
+{
+ sv.add(s);
+}
+
+
+void
+set_default_output(String s)
+{
+ outfn = s;
+}
+
diff --git a/src/simpleprint.cc b/src/simpleprint.cc
new file mode 100644
index 0000000000..395396e22b
--- /dev/null
+++ b/src/simpleprint.cc
@@ -0,0 +1,55 @@
+#include "lookup.hh"
+#include "request.hh"
+#include "beam.hh"
+#include "pscore.hh"
+#include "paper.hh"
+#include "simplestaff.hh"
+#include "molecule.hh"
+#include "sccol.hh"
+#include "stem.hh"
+#include "notehead.hh"
+#include "rest.hh"
+#include "debug.hh"
+#include "bar.hh"
+#include "meter.hh"
+
+Item *
+Simple_staff::get_TYPESET_item(Command *com)
+{
+ Item *s;
+ if (com -> args[0] == "BAR" ) {
+ s = new Bar(com->args[1]);
+ } else if (com->args[0] == "METER") {
+ svec<String> arg( com->args);
+ arg.del(0);
+ s = new Meter(arg);
+ } else
+ assert(false);
+
+ return s;
+}
+
+void
+Simple_column::typeset_item(Item *i, int breakst)
+{
+ assert(i);
+ // ugh
+ staff_->pscore_->typeset_item(i, score_column->pcol,
+ staff_->theline,breakst);
+}
+
+void
+Simple_staff::set_output(PScore* ps )
+{
+ pscore_ = ps;
+ pscore_->add(theline);
+}
+
+
+Rest*
+Simple_staff::get_rest(Rest_req*rq)
+{
+ int b = rq->rhythmic()->balltype;
+ int d = rq->rhythmic()->dots;
+ return new Rest(b, d);
+}
diff --git a/src/simplestaff.cc b/src/simplestaff.cc
new file mode 100644
index 0000000000..5150d5478a
--- /dev/null
+++ b/src/simplestaff.cc
@@ -0,0 +1,66 @@
+#include "request.hh"
+#include "swalker.hh"
+#include "debug.hh"
+#include "staff.hh"
+#include "command.hh"
+#include "simplestaff.hh"
+#include "sccol.hh"
+
+
+
+
+Simple_column::Simple_column(Score_column*s, Simple_staff *rs)
+ : Staff_column(s)
+{
+ stem_ = 0;
+ staff_ = rs;
+ beam_ = 0;
+}
+
+Simple_staff::Simple_staff()
+{
+ theline = 0;
+}
+
+/**
+ accept:
+
+ BREAK: all
+ TYPESET: bar, meter,
+
+ */
+
+
+
+void
+Simple_column::process_requests()
+{
+ for (int i = 0 ; i < v_elts.sz(); i ++)
+ for (PCursor<Request *> rqc(v_elts[i]->reqs); rqc.ok(); rqc++) {
+ Request *rq= rqc;
+ if (rq->rhythmic()){
+ notes.add( rq->rhythmic());
+ }
+ if (rq->stem()) {
+ stem_ = rq->stem();
+ }
+
+ if (rq->beam()) {
+ beam_ = rq->beam();
+ }
+ }
+}
+Staff_column*
+Simple_staff::create_col(Score_column*s)
+{
+ return new Simple_column(s,this);
+}
+void
+Simple_staff::walk()
+{
+ for (Simple_walker sc(this); sc.ok(); sc++) {
+ sc.col()->process_requests();// TODO
+ sc.process();
+ }
+}
+
diff --git a/src/simplewalker.cc b/src/simplewalker.cc
new file mode 100644
index 0000000000..ad9019ac33
--- /dev/null
+++ b/src/simplewalker.cc
@@ -0,0 +1,106 @@
+#include "request.hh"
+#include "beam.hh"
+#include "pscore.hh"
+#include "simplestaff.hh"
+#include "sccol.hh"
+#include "stem.hh"
+#include "notehead.hh"
+#include "rest.hh"
+#include "debug.hh"
+
+void
+Simple_walker::process_command(Command*com)
+{
+ switch (com->code){
+ case BREAK_PRE:
+ case BREAK_MIDDLE:
+ case BREAK_POST:
+ case BREAK_END:
+ (*this)->score_column->set_breakable();
+ break_status = com->code- BREAK_PRE;
+ break;
+ case INTERPRET:
+ break;
+
+ case TYPESET:
+ {
+ Item* i = staff()->get_TYPESET_item(com);
+ col()->typeset_item(i, break_status);
+ }
+ break;
+
+ default :
+ break;
+ }
+}
+
+void
+Simple_walker::process_requests()
+{
+ Simple_column*c = col();
+ Simple_staff *s = staff();
+ if (c->beam_&& c->beam_->spantype == Span_req::START) {
+ if (beam_)
+ error("Too many beams");
+ beam_ = new Beam;
+ }
+
+ if (c->stem_) {
+ stem_ = s->get_stem(c->stem_->stem());
+ c->typeset_item(stem_);
+ }
+
+ for (int i = 0; i < c->notes.sz(); i ++) {
+ Rhythmic_req*rq = c->notes[i];
+ if (rq->note()) {
+ Notehead*n = s->get_notehead(rq->note());
+ stem_->add(n);
+ noteheads.add(n);
+ }
+
+ if (rq->rest()) {
+ c->typeset_item( s->get_rest(rq->rest()) );
+ }
+ }
+
+
+ if (beam_) {
+ beam_->add(stem_);
+ }
+
+ if (c->beam_&& c->beam_->spantype == Span_req::STOP) {
+ pscore_->typeset_spanner(beam_, s->theline);
+ beam_ = 0;
+ }
+ for (int i = 0; i < noteheads.sz(); i++) {
+ c->typeset_item(noteheads[i]);
+ }
+ noteheads.set_size(0);
+
+ if (stem_) {
+ stem_ = 0;
+ }
+}
+
+Simple_walker::Simple_walker(Simple_staff*s)
+ : Staff_walker(s, s->theline->pscore_)
+{
+ stem_ = 0;
+ beam_ =0;
+}
+
+
+
+Simple_staff*
+Simple_walker::staff()
+{
+ return (Simple_staff*) staff_;
+}
+
+Simple_column*
+Simple_walker::col()
+{
+ return (Simple_column*) *(*this);
+}
+
+
diff --git a/src/spanner.cc b/src/spanner.cc
new file mode 100644
index 0000000000..16c3ff19cb
--- /dev/null
+++ b/src/spanner.cc
@@ -0,0 +1,54 @@
+#include "pstaff.hh"
+#include "debug.hh"
+#include "pscore.hh"
+#include "spanner.hh"
+#include "symbol.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+
+String
+Spanner::TeXstring() const
+{
+
+ assert(output);
+ return output->TeXstring();
+}
+
+Spanner::Spanner()
+{
+ pstaff_=0;
+ left = right = 0;
+}
+
+void
+Spanner::process()
+{
+}
+
+void
+Spanner::preprocess()
+{
+}
+
+Interval
+Spanner::width()const
+{
+ return Interval(0,right->hpos - left->hpos);
+}
+
+Paperdef*
+Spanner::paper()const
+{
+ assert(pstaff_);
+ return pstaff_->pscore_->paper_;
+}
+void
+Spanner::print()const
+{
+#ifndef NPRINT
+ mtor << "Spanner { Output ";
+ output->print();
+
+ mtor << "}\n";
+#endif
+}
diff --git a/src/staff.cc b/src/staff.cc
new file mode 100644
index 0000000000..3a32801b2f
--- /dev/null
+++ b/src/staff.cc
@@ -0,0 +1,172 @@
+#include "staff.hh"
+#include "swalker.hh"
+#include "stcol.hh"
+#include "sccol.hh"
+#include "debug.hh"
+
+Staff::Staff(Staff const&src)
+{
+ PL_copy(voices,src.voices);
+ PL_copy(commands,src.commands);
+ assert(!cols.size()); // cols is a runtime field.
+
+ score_ = src.score_;
+ pscore_ = src.pscore_;
+}
+
+Paperdef*
+Staff::paper() const{
+ return score_->paper_;
+}
+
+void
+Staff::clean_cols()
+{
+ PCursor<Staff_column *> stc(cols);
+ for(; stc.ok(); ){
+ if (!stc->score_column->used())
+ stc.del();
+ else
+ stc++;
+ }
+}
+
+Staff_column *
+Staff::get_col(Real w, bool mus)
+{
+ Score_column* sc = score_->find_col(w,mus);
+ assert(sc->when == w);
+ PCursor<Staff_column *> stc(cols);
+ for (; stc.ok(); stc++) {
+ if (*stc->score_column > *sc) // too far
+ break;
+ if (sc == stc->score_column)
+ return stc;
+ }
+ Staff_column* newst = create_col(sc);
+
+ if (!stc.ok()) {
+ cols.bottom().add(newst);
+ return cols.bottom();
+ }
+
+ if (mus) {
+ stc.insert(newst);
+ return newst;
+ }
+
+ if ((stc-1)->when() == newst->when()) {
+ stc--;
+ }
+
+ stc.insert(newst);
+
+ return newst;
+}
+
+
+void
+Staff::add_voice(Voice *v)
+{
+ voices.bottom().add(v);
+}
+
+/*
+ put all stuff grouped vertically in the Staff_cols
+ */
+void
+Staff::setup_staffcols()
+{
+
+ for (PCursor<Voice*> vc(voices); vc.ok(); vc++) {
+
+ Real now = vc->start;
+ for (PCursor<Voice_element *> ve(vc->elts); ve.ok(); ve++) {
+
+ Staff_column *sc=get_col(now,true);
+ sc->add(ve);
+ now += ve->duration;
+ }
+ }
+
+ for (PCursor<Command*> cc(commands); cc.ok(); cc++) {
+ Staff_column *sc=get_col(cc->when,false);
+ sc->s_commands.add(cc);
+ }
+}
+
+/// merge commands from score
+void
+Staff::add_commands(PointerList<Command*> const &cl)
+{
+ PCursor<Command*> score_c(cl);
+ PCursor<Command*> cc(commands);
+
+ while (score_c.ok()) {
+ while (cc.ok() && cc->when <= score_c->when)
+ cc++;
+
+ Command*nc = new Command (*(* score_c));
+ if (cc.ok()) {
+ // cc->when > score_c->when
+ cc.insert( nc );
+ } else {
+ commands.bottom().add( nc);
+ cc = commands.bottom();
+ }
+ score_c++;
+ }
+
+ // now integrate break commands with other commands.
+ // maybe do this in derived functions.
+}
+
+void
+Staff::process()
+{
+ setup_staffcols();
+ OK();
+ walk();
+}
+
+void
+Staff::OK() const
+{
+#ifndef NDEBUG
+ cols.OK();
+ commands.OK();
+ voices.OK();
+ assert(score_);
+#endif
+}
+
+
+Real
+Staff::last() const
+{
+ Real l = 0.0;
+ for (PCursor<Voice*> vc(voices); vc.ok(); vc++) {
+ l = MAX(l, vc->last());
+ }
+ return l;
+}
+
+
+void
+Staff::print() const
+{
+#ifndef NPRINT
+ mtor << "Staff {\n";
+ for (PCursor<Voice*> vc(voices); vc.ok(); vc++) {
+ vc->print();
+
+ }
+ mtor <<"}\n";
+#endif
+}
+
+Staff::Staff()
+{
+ score_ =0;
+ pscore_=0;
+}
diff --git a/src/staffline.cc b/src/staffline.cc
new file mode 100644
index 0000000000..c83e904bc6
--- /dev/null
+++ b/src/staffline.cc
@@ -0,0 +1,107 @@
+#include "staffline.hh"
+#include "scoreline.hh"
+#include "dimen.hh"
+#include "spanner.hh"
+#include "symbol.hh"
+#include "paper.hh"
+#include "pcol.hh"
+#include "pscore.hh"
+
+static String
+make_vbox(Interval i)
+{
+ String s("\\vbox to ");
+ s += print_dimen(i.length());
+ s += "{\\vskip "+print_dimen(i.max)+" ";
+ 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{";
+ {
+ Symbol sym = pstaff_->get_stafsym(scor->score->paper_->linewidth);
+ s+=sym.tex;
+ PCursor<const PCol *> cc(scor->cols);
+ 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 (PCursor<const Item *> ic(cc->its); ic.ok(); ic++) {
+ if (ic->pstaff_ == pstaff_)
+ s += ic->TeXstring();
+ }
+ // spanners.
+ for (PCursor<const Spanner *> sc(cc->starters); sc.ok(); sc++)
+ if (sc->pstaff_ == pstaff_)
+ s += sc->TeXstring();
+ }
+ }
+ s+="\\hss}\\vss}";
+ return s;
+}
+
+Line_of_staff::Line_of_staff(Line_of_score * sc, PStaff*st)
+{
+ scor=sc;
+ pstaff_=st;
+#if 0
+ const PCol *linestart = sc->cols.top();
+ const PCol *linestop = sc->cols.bottom();
+
+ for (PCursor<const Spanner*> sp(pstaff_->spans); sp.ok(); sp++) {
+ const PCol *brokenstart = &MAX(*linestart, *sp->left);
+ const PCol *brokenstop = &MIN(*linestop, *sp->right);
+// if (*brokenstop < *brokenstart)
+ brokenspans.bottom().add(sp->broken_at(0,0));
+ }
+#endif
+ for (PCursor<const Spanner*> sp(pstaff_->spans); sp.ok(); sp++) {
+
+ brokenspans.bottom().add(sp->broken_at(0,0));
+ }
+}
+
+
+Interval
+Line_of_staff::height() const
+{
+ Interval y;
+ {
+ Symbol s = pstaff_->stafsym->eval(scor->score->paper_->linewidth);
+ y = s.dim.y;
+ }
+ PCursor<const PCol *> cc(scor->cols);
+
+ // all items in the current line & staff.
+ for (; cc.ok(); cc++) {
+ for (PCursor<const Item *> ic(cc->its); ic.ok(); ic++) {
+ if (ic->pstaff_ == pstaff_) {
+ y.unite(ic->height());
+ }
+
+ // spanners.
+ for (PCursor<const Spanner *> sc(cc->starters); sc.ok(); sc++)
+ if (sc->pstaff_ == pstaff_) {
+ y.unite(sc->height());
+ }
+ }
+ }
+ return y;
+}
+
+
diff --git a/src/stcol.cc b/src/stcol.cc
new file mode 100644
index 0000000000..799daed316
--- /dev/null
+++ b/src/stcol.cc
@@ -0,0 +1,30 @@
+#include "stcol.hh"
+#include "sccol.hh"
+#include "voice.hh"
+
+bool
+Staff_column::mus() const
+{
+ return score_column->musical;
+}
+
+Real
+Staff_column::when() const
+{
+ return score_column->when;
+}
+
+void
+Staff_column::add(Voice_element*ve)
+{
+ Real d= ve->duration;
+ if (d){
+ score_column->durations.add(d);
+ }
+
+ v_elts.add(ve);
+}
+
+Staff_column::Staff_column(Score_column*s) {
+ score_column = s;
+}
diff --git a/src/stem.cc b/src/stem.cc
new file mode 100644
index 0000000000..fdb47f9755
--- /dev/null
+++ b/src/stem.cc
@@ -0,0 +1,156 @@
+#include "stem.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper.hh"
+#include "notehead.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+
+const int STEMLEN=7;
+static int
+ABS(int i) {
+ return (i < 0)?-i:i;
+}
+
+
+Stem::Stem(int c)
+{
+ 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::set_stemend(Real se)
+{
+ // todo: margins
+ assert((dir > 0 && se >= maxnote) || (se <= minnote && dir <0));
+
+ top = (dir < 0) ? maxnote : se;
+ bot = (dir < 0) ? se : minnote;
+ flag = dir*ABS(flag);
+}
+
+void
+Stem::add(Notehead *n)
+{
+ if (n->balltype == 1)
+ return;
+ int p = n->position;
+ if ( p < minnote)
+ minnote = p;
+ if ( p> maxnote)
+ maxnote = p;
+}
+void
+Stem::print()const
+{
+ mtor << "Stem minmax=["<< minnote<<","<<maxnote<<"], flag: "<<flag;
+ Item::print();
+}
+
+void
+Stem::set_default_dir()
+{
+ Real mean = (minnote+maxnote)/2;
+ dir = (mean > staff_center) ? -1: 1;
+}
+
+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()
+{
+ assert(minnote<=maxnote);
+
+ if (!stemlen)
+ set_default_stemlen();
+
+ set_stemend((dir< 0) ? maxnote-stemlen: minnote +stemlen);
+ if (dir > 0){
+ stem_xoffset = paper()->note_width();
+ }
+}
+
+void
+Stem::postprocess()
+{
+ set_default_extents();
+ brew_molecole();
+}
+
+Interval
+Stem::width()const
+{
+ if (!print_flag || ABS(flag) <= 4)
+ return Interval(0,0); // TODO!
+ Paperdef*p= paper();
+ return p->lookup_->flag(flag).dim.x;
+}
+
+void
+Stem::brew_molecole()
+{
+ assert(pstaff_);
+ assert(bot!=top);
+ assert(!output);
+
+ Paperdef *p =paper();
+ Parametric_symbol *stem = p->lookup_->stem();
+
+ Real dy = p->interline()/2;
+ String y1 =print_dimen( dy * bot);
+ String y2 = print_dimen(dy * top);
+ Symbol ss =stem->eval(y1,y2);
+ delete stem;
+
+ output = new Molecule(Atom(ss));
+
+ if (print_flag&&ABS(flag) > 4){
+ Symbol fl = p->lookup_->flag(flag);
+ Molecule m(fl);
+ if (flag < -4){
+ output->add_bot(m);
+ } else if (flag > 4) {
+ output->add_top(m);
+ } else
+ assert(false);
+ }
+
+ output->translate(Offset(stem_xoffset,0));
+
+}
+
+Real
+Stem::hpos()const
+{
+ return pcol_->hpos + stem_xoffset;
+}
diff --git a/src/swalker.cc b/src/swalker.cc
new file mode 100644
index 0000000000..db48fd1f82
--- /dev/null
+++ b/src/swalker.cc
@@ -0,0 +1,32 @@
+#include "request.hh"
+#include "swalker.hh"
+#include "stcol.hh"
+
+Staff_walker::~Staff_walker() {}
+
+Staff_walker::Staff_walker(Staff * s, PScore*ps )
+ : PCursor<Staff_column*> (s->cols)
+{
+ staff_ = s;
+ pscore_ = ps;
+ break_status = BREAK_END - BREAK_PRE;
+}
+
+Real
+Staff_walker::when() const
+{
+ return (* (PCursor<Staff_column*> *) this)->when();
+}
+
+void
+Staff_walker::process()
+{
+ break_status = BREAK_END - BREAK_PRE;
+
+ for (int i = 0 ; i < (*this)->s_commands.sz(); i++) {
+ process_command((*this)->s_commands[i]);
+ }
+
+ process_requests();
+}
+
diff --git a/src/symbol.cc b/src/symbol.cc
new file mode 100644
index 0000000000..907f1d7282
--- /dev/null
+++ b/src/symbol.cc
@@ -0,0 +1,32 @@
+#include "symbol.hh"
+
+Symbol::Symbol()
+ : dim(Interval(0,0),Interval(0,0))
+{
+ tex = "\\unknown";
+}
+Symbol::Symbol(String s, Box b)
+ : dim(b)
+{
+ tex = s;
+}
+
+/****************************************************************/
+
+Symbol
+Parametric_symbol::eval(String args1)const
+{
+ svec<String> a;
+ a.add(args1);
+ return eval(a);
+}
+
+Symbol
+Parametric_symbol::eval(String args1,String arg2)const
+{
+ svec<String> a;
+ a.add(args1);
+ a.add(arg2);
+ return eval(a);
+}
+
diff --git a/src/symtable.cc b/src/symtable.cc
new file mode 100644
index 0000000000..a28d14670c
--- /dev/null
+++ b/src/symtable.cc
@@ -0,0 +1,60 @@
+#include "misc.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "real.hh"
+#include "symbol.hh"
+#include "assoc.hh"
+#include "symtable.hh"
+
+
+Symbol
+Symtable::lookup(String s) const
+{
+ if (elt_query(s))
+ return (*this)[s];
+ else {
+ error( "Unknown symbol " +s+'\n');
+ }
+}
+
+Symtable*
+Symtables::operator()(String s)
+{
+ return Assoc<String, Symtable*>::operator[](s);
+}
+
+void
+Symtables::read(Text_db &symini)
+{
+ while (!symini.eof()) {
+ Text_record r( symini++);
+ if (r[0] == "end" )
+ return;
+ assert (r[0] == "table");
+
+ String tabnam = r[1];
+ Symtable * sp = new Symtable;
+ while (!symini.eof()){
+ r = symini++;
+ if (r[0] == "end")
+ break;
+
+ if (r.sz() != 6)
+ error("Not enough fields in symbol init");
+
+ int i=0;
+ String id=r[i++];
+ String tex=r[i++];
+ svec<Real> dims;
+ for (int j=0; j < 4; j++)
+ dims.add( parse_dimen(r[i++]));
+
+ Symbol s(tex, Box(dims));
+ (*sp)[id] = s;
+ }
+ (*this)[tabnam] = sp;
+ }
+}
+
+
+
diff --git a/src/table.cc b/src/table.cc
new file mode 100644
index 0000000000..1f302259e9
--- /dev/null
+++ b/src/table.cc
@@ -0,0 +1,67 @@
+#include "glob.hh"
+#include "debug.hh"
+#include "string.hh"
+#include "identifier.hh"
+#include "keyword.hh"
+#include "associter.hh"
+#include "parser.hh"
+
+static Keyword_ent the_key_tab[]={
+ "voice", VOICE,
+ "rhythmstaff", RHYTHMSTAFF,
+ "melodicstaff", MELODICSTAFF,
+ "score", SCORE,
+ "bar", BAR,
+ "output", OUTPUT,
+ "cm", CM,
+ "start", START_T,
+ "pt", PT,
+ "in", IN,
+ "mm", MM,
+ "paper", PAPER,
+ "width", WIDTH,
+ "meter", METER,
+ "unitspace", UNITSPACE,
+ "skip", SKIP,
+ "octave", OCTAVECOMMAND,
+ "commands", COMMANDS,
+ "staff", STAFF,
+ "geometric", GEOMETRIC,
+ "duration", DURATIONCOMMAND,
+ 0,0
+} ;
+
+
+int
+lookup_keyword(String s)
+{
+ static Keyword_table table(the_key_tab);
+ return table.lookup(s);
+}
+
+Assoc<String, Identifier*> the_id_tab;
+
+Identifier*
+lookup_identifier(String s)
+{
+ if (!the_id_tab.elt_query(s))
+ return 0;
+
+ return the_id_tab[s];
+}
+
+void
+add_identifier(Identifier*i)
+{
+ the_id_tab[i->name] = i;
+}
+
+void
+delete_identifiers()
+{
+
+ for (Assoc_iter<String,Identifier*> ai(the_id_tab); ai.ok(); ai++) {
+ mtor << "deleting: " << ai.key()<<'\n';
+ delete ai.val();
+ }
+}
diff --git a/src/template1.cc b/src/template1.cc
new file mode 100644
index 0000000000..fd2431130e
--- /dev/null
+++ b/src/template1.cc
@@ -0,0 +1,25 @@
+
+#include "plist.hh"
+#include "pcol.hh"
+#include "item.hh"
+#include "request.hh"
+#include "command.hh"
+#include "spanner.hh"
+#include "scoreline.hh"
+#include "staffline.hh"
+
+#include "list.cc"
+#include "plist.cc"
+#include "cursor.cc"
+
+#define PLC_instantiate(a) PL_instantiate(a); PL_instantiate(const a)
+
+L_instantiate(Stem*);
+PLC_instantiate(Line_of_score);
+PLC_instantiate(Line_of_staff);
+PLC_instantiate(Item);
+PLC_instantiate(Spanner);
+PLC_instantiate(PStaff);
+PLC_instantiate(Idealspacing);
+PLC_instantiate(PCol);
+
diff --git a/src/template2.cc b/src/template2.cc
new file mode 100644
index 0000000000..01695c863f
--- /dev/null
+++ b/src/template2.cc
@@ -0,0 +1,19 @@
+
+#include "symbol.hh"
+#include "voice.hh"
+
+#include "staff.hh"
+#include "sccol.hh"
+#include "stcol.hh"
+#include "spanner.hh"
+
+#include "list.cc"
+#include "plist.cc"
+#include "cursor.cc"
+PL_instantiate(Score_column);
+PL_instantiate(Staff_column);
+PL_instantiate(Staff);
+PL_instantiate(Voice_element);
+PL_instantiate(Voice);
+
+
diff --git a/src/template3.cc b/src/template3.cc
new file mode 100644
index 0000000000..92921bb29a
--- /dev/null
+++ b/src/template3.cc
@@ -0,0 +1,12 @@
+#include "request.hh"
+#include "command.hh"
+#include "molecule.hh"
+#include "list.cc"
+#include "plist.cc"
+#include "cursor.cc"
+PL_instantiate(Atom);
+PL_instantiate(Command);
+PL_instantiate(Request);
+
+
+
diff --git a/src/tex.cc b/src/tex.cc
new file mode 100644
index 0000000000..ae9dc1b5f3
--- /dev/null
+++ b/src/tex.cc
@@ -0,0 +1,32 @@
+#include "dimen.hh"
+#include "tex.hh"
+#include "symbol.hh"
+#include "const.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.pos('%');
+ if (!p ) return ;
+ else p--;
+ r = r.left(p) + arg + r.right(r.len() - p -1);
+}
+
+
+String
+substitute_args(String source, svec<String> args)
+{
+ String retval (source);
+ for (int i = 0 ; i < args.sz(); i++)
+ substitute_arg(retval, args[i]);
+ while (retval.pos('%'))
+ substitute_arg(retval, "");
+ return retval;
+}
diff --git a/src/texbeam.cc b/src/texbeam.cc
new file mode 100644
index 0000000000..e21efba0be
--- /dev/null
+++ b/src/texbeam.cc
@@ -0,0 +1,99 @@
+/*
+
+ 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 "lookup.hh"
+
+Symbol
+Lookup::beam_element(int sidx, int widx, Real slope)
+{
+ Symbol bs=(*symtables_)("beamslopes")->lookup("slope");
+
+ svec<String> args;
+ args.add(sidx);
+ args.add(widx);
+ bs.tex = substitute_args(bs.tex,args);
+ int w = 2 << widx;
+ Real width = convert_dimen(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)
+{
+ assert(ABS(s) < 0.45);
+ int i = int(rint(s * 20.0));
+
+ s = i/20.0;
+ if (s>0)
+ return 6*i +122;
+ else
+ return -6 * i+ 188;
+}
+
+Symbol
+Lookup::rule_symbol(Real height, Real width)
+{
+ Symbol bs=(*symtables_)("beamslopes")->lookup("horizontal");
+ svec<String> args;
+ args.add(print_dimen(height));
+ args.add(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(convert_dimen(2,"pt"), width);
+
+ Real w = width;
+ Real elemwidth = convert_dimen(64,"pt");
+ int widx = 5;
+
+ Molecule m;
+ Real dy=0;
+ Real minwid =convert_dimen(2,"pt");
+ assert(w > minwid);
+ while (w > minwid) {
+ while (elemwidth > w) {
+ widx --;
+ elemwidth /= 2.0;
+ }
+
+ Atom a(beam_element(sidx, widx, slope));
+ a.translate(Offset(0, dy));
+ m.add_right(a);
+ dy += elemwidth*slope;
+ w -= elemwidth;
+ }
+
+ widx = 0;
+ Atom a(beam_element(sidx, widx, slope));
+ a.translate(Offset(width -minwid, (width-minwid) * 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/src/tstream.cc b/src/tstream.cc
new file mode 100644
index 0000000000..05e2e9c93e
--- /dev/null
+++ b/src/tstream.cc
@@ -0,0 +1,75 @@
+#include <fstream.h>
+#include <time.h>
+#include "tex.hh"
+#include "main.hh"
+#include "tstream.hh"
+#include "debug.hh"
+
+Tex_stream::Tex_stream(String filename)
+{
+ os = new ofstream(filename);
+ if (!*os)
+ error("can't open `" + filename+"\'");
+ nest_level = 0;
+ outputting_comment=false;
+ header();
+}
+void
+Tex_stream::header()
+{
+ *os << "% Creator: " << get_version();
+ *os << "% Automatically generated, at ";
+ time_t t(time(0));
+ *os << ctime(&t);
+//*os << "% from input file ..\n";
+}
+Tex_stream::~Tex_stream()
+{
+ delete os;
+ assert(nest_level == 0);
+}
+
+// print string. don't forget indent.
+Tex_stream &
+Tex_stream::operator<<(String s)
+{
+
+ for (const char *cp = s; *cp; cp++) {
+ if (outputting_comment) {
+ *os << *cp;
+ if (*cp == '\n') {
+ outputting_comment=false;
+
+ }
+ continue;
+ }
+ switch(*cp)
+ {
+ case '%':
+ outputting_comment = true;
+ *os << *cp;
+ break;
+ case '{':
+ nest_level++;
+ *os << *cp;
+ break;
+ case '}':
+ nest_level--;
+ *os << *cp;
+ assert (nest_level >= 0);
+ /* FALTHROUGH */
+
+ case '\n':
+ *os << "%\n";
+ *os << String(' ', nest_level);
+ break;
+ default:
+ *os << *cp;
+ break;
+ }
+ }
+ return *this;
+}
+
+
+/****************************************************************/
diff --git a/src/version.cc b/src/version.cc
new file mode 100644
index 0000000000..401273b6b1
--- /dev/null
+++ b/src/version.cc
@@ -0,0 +1,9 @@
+#include "version.hh"
+
+static char *s = "LilyPond version " VERSIONSTR " compiled on " __DATE__ " at " __TIME__ "\n";
+
+const char *
+get_version()
+{
+ return s;
+}
diff --git a/src/voice.cc b/src/voice.cc
new file mode 100644
index 0000000000..14883e1499
--- /dev/null
+++ b/src/voice.cc
@@ -0,0 +1,78 @@
+#include "debug.hh"
+#include "voice.hh"
+
+Voice::Voice(Voice const&src)
+{
+ PL_copy(elts, src.elts);
+ start = src.start;
+}
+
+Voice::Voice()
+{
+ start = 0.0;
+}
+
+void
+Voice::add(Voice_element*v)
+{
+ elts.bottom().add(v);
+}
+
+void
+Voice::print() const
+{
+ #ifndef NPRINT
+
+ mtor << "start: "<< start<<eol;
+ for (PCursor<Voice_element*> vec(elts); vec.ok(); vec++)
+ vec->print();
+#endif
+}
+
+Real
+Voice::last() const
+{
+ Real l =start;
+ for (PCursor<Voice_element*> vec(elts); vec.ok(); vec++)
+ l += vec->duration;
+ return l;
+}
+/****************************************************************/
+void
+Voice_element::print() const
+{
+#ifndef NPRINT
+ mtor << "voice_element { dur :"<< duration <<"\n";
+ for (PCursor<Request*> rc(reqs); rc.ok(); rc++) {
+ rc->print();
+ }
+ mtor << "}\n";
+#endif
+}
+void
+Voice_element::add(Request*r)
+{
+ if (r->rhythmic()) {
+ assert (!duration);
+ duration = r->duration();
+ }
+ r->elt = this;
+ reqs.bottom().add(r);
+}
+
+
+Voice_element::Voice_element()
+{
+ voice = 0;
+ group = 0;
+ duration = 0.0;
+}
+
+Voice_element::Voice_element(Voice_element const&src)
+{
+ duration=src.duration;
+ voice=src.voice;
+ PointerList__copy(Request*, reqs, src.reqs, clone());
+ group=src.group;
+ assert(!granted_items.size() && !granted_spanners.size());
+}
diff --git a/src/warn.cc b/src/warn.cc
new file mode 100644
index 0000000000..426173ee0c
--- /dev/null
+++ b/src/warn.cc
@@ -0,0 +1,18 @@
+#include "debug.hh"
+ ostream &warnout (cerr);
+ ostream *mlog(&cerr);
+
+
+
+void warning(String s)
+{
+ WARN << s;
+}
+
+
+void error(String s)
+{
+ cerr << "\n" << s << "\nexiting..\n";
+ exit(1);
+}
+