+-*-text-*-
+
CODING STANDARDS:
Functions and methods do not return errorcodes, but use assert for
CLASSES and TYPES:
This_is_a_class
+ AClass_name (for Abbreviation_class_name)
DATA MEMBERS
- Class:member
+ Class::member
-if the member's name resembles its type, then we use
+if the member's name resembles its type, then I use
- Class Fubular { ..}
+ class Fubular { ..}
Class::fubular_
Class documentation.
*/
-Unfortunately most of the code isn't really documented that good.
\ No newline at end of file
+Unfortunately most of the code isn't really documented that good.
+
+CLASSNAMES (2)
+
+A lot of classes in LilyPond start with 'P', this is to distinguish
+certain parts of LilyPond: the P stands for Printer, and the P-classes
+are supposed to be more lowlevel than the others. Example:
+
+ Staff uses PStaff, PScore and PCol to do the typesetting of
+symbols. Staff is are the "brains" for PStaff
+
+NB: in PCursor (which is part of the library) P stands for PointerCursor
+
+
+MEMBERS(2)
+
+Standard methods:
+
+ ///check that *this satisfies its invariants, abort if not.
+ void OK() const
+
+ /// print *this (and substructures) to debugging log
+ void print() const
+
+ /// add some data to *this;
+ add( .. )
+ /**
+ Presence of these methods usually imply that it is not feasible to this
+ via a constructor
+ */
+
+ /// replace some data of *this
+ set( .. )
+
-DOCFILES=CodingStyle algorithms Makefile
+DOCFILES=CodingStyle algorithms Makefile breaking
+
dist:
ln $(DOCFILES) $(DDIR)/Documentation/
\ No newline at end of file
--- /dev/null
+[Source files: command.hh, scommands.cc]
+
+BREAKING, PREBREAK POSTBREAK, etc.
+
+So what's the deal with PREBREAK and POSTBREAK and all this
+stuff?
+
+Let's take text as an example. In German some compound
+words change their spelling if they are broken: "backen" becomes
+"bak-ken". TeX has a mechanism to deal with this, you would define
+the spelling of "backen" in TeX in this way
+
+ \discretionary{bak-}{ken}{backen}
+
+These 3 arguments are called "prebreak", "postbreak" and "nobreak"
+text.
+
+The same problem exists when typesetting music. If a line of music is
+broken, the next line usually gets a clef. So in TeX terms, the clef
+is a postbreak. The same thing happens with meter signs: Normally the
+meter follows the bar. If a line is broken at that bar, the bar along
+with the meter stays on the "last" line, but the next line also gets a
+meter sign after the clef. Using the previous notation,
+
+ \discretionary{bar meter}{clef meter}{ bar meter }
+
+In Lilypond, we have the same concepts (and the same
+terminology). Each (nonrhythmic) symbol is typeset using a Command
+(code: TYPESET). At a breakpoint, TYPESET commands can be grouped
+using separators (in lower case):
+
+ BREAK_PRE, typeset(bar), typeset(meter),
+ BREAK_MID, typeset(bar), typeset(meter),
+ BREAK_POST, typeset(clef), typeset(meter), BREAK_END
+
+The BREAK command sequence is terminated with BREAK_END, so other
+commands (like INTERPRET) may follow this sequence.
+
--- /dev/null
+####
+#### USER CONFIGURABLE
+####
+
+# speedy
+#DEFINES=-DNDEBUG -DNPRINT -O2
+
+# lots of debugging info
+DEFINES=-g
+
+# turn off -pipe if linker doesn't support it
+EXTRACXXFLAGS=-pipe -Wall -W -pedantic
+
+####
+#### EN USER CONFIGURABLE part.
+####
+
+# version info
+MAJVER=0
+MINVER=0
+PATCHLEVEL=9
+VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
+
+# directories
+TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
+OBJECTDIR=objects
+HEADERDIR=hdr
+CCDIR=src
+
+vpath %.cc $(CCDIR)
+vpath %.hh $(HEADERDIR)
+vpath %.y $(CCDIR)
+vpath %.l $(CCDIR)
+vpath %.o $(OBJECTDIR)
+
+#
+#
+include Sources.make
+progdocs=$(hdr) $(mycc)
+gencc=parser.cc lexer.cc
+cc=$(mycc) $(gencc)
+obs=$(cc:.cc=.o)
+
+
+#dist
+.EXPORT_ALL_VARIABLES:
+
+DOCDIR=docdir
+
+PACKAGENAME=lilypond
+DNAME=$(PACKAGENAME)-$(VERSION)
+
+# distribution files.
+othersrc=lexer.l parser.y
+SCRIPTS=make_version make_patch genheader
+IFILES=dimen.tex symbol.ini kortjakje.ly maartje.ly\
+ lilyponddefs.tex test.tex .dstreamrc
+OFILES=Makefile Make.variables Sources.make COPYING README
+DFILES=$(OFILES) $(IFILES) $(SCRIPTS)
+
+#compiling
+LOADLIBES=-L$(FLOWERDIR) -lflower
+FLOWERDIR=../flower
+
+CXXFLAGS=$(DEFINES) -I$(HEADERDIR) -I$(FLOWERDIR) $(EXTRACXXFLAGS)
+FLEX=flex
+BISON=bison
+exe=$(PACKAGENAME)
+OUTPUT_OPTION=$< -o $@
+DDIR=$(TOPDIR)/$(DNAME)
+SUBDIRS=Documentation $(OBJECTDIR) $(CCDIR) $(HEADERDIR)
-MAJVER=0
-MINVER=0
-PATCHLEVEL=8
-
-TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
-
-#
-#
-
-include Sources.make
-progdocs=$(hdr) $(mycc)
-gencc=parser.cc lexer.cc
-cc=$(mycc) $(gencc)
-obs=$(cc:.cc=.o)
-
-
-#dist
-.EXPORT_ALL_VARIABLES:
-
-DOCDIR=docdir
-VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
-PACKAGENAME=lilypond
-DNAME=$(PACKAGENAME)-$(VERSION)
-othersrc=lexer.l parser.y
-SCRIPTS=make_version make_patch genheader
-IFILES=dimen.tex symbol.ini suzan.ly maartje.ly\
- lilyponddefs.tex test.tex .dstreamrc
-OFILES=Makefile Sources.make COPYING README
-DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS)
-
-#compiling
-LOADLIBES=-L$(FLOWERDIR) -lflower
-FLOWERDIR=../flower
-# speedy
-#DEFINES=-DNDEBUG -DNPRINT -O2
-# lots of debugging info
-DEFINES=-g
-
-CXXFLAGS=$(DEFINES) -I$(FLOWERDIR) -pipe -Wall -W -pedantic
-FLEX=flex
-BISON=bison
-exe=$(PACKAGENAME)
-
-##################################################################
+include Make.variables
$(exe): $(obs)
- $(CXX) -o $@ $(obs) $(LOADLIBES)
+ $(CXX) -o $@ $^ $(LOADLIBES)
+
clean:
rm -f $(exe) *.o $(DOCDIR)/* core
distclean: clean
- rm -f TAGS depend version.hh $(gencc) .GENERATE *~
+ rm -f depend version.hh $(gencc) .GENERATE *~
all: kompijl doc
-mkdir $(DOCDIR)
doc++ -p -I -d $(DOCDIR) $(progdocs)
-depend: Sources.make .GENERATE
- $(CXX) $(CXXFLAGS) -MM $(cc) > $@
+depend: Sources.make .GENERATE
+ touch depend
+ $(MAKE) realdepend
+
+
+$(OBJECTDIR)/%.o: $(CCDIR)/%.cc
+ $(CXX) -c $(CXXFLAGS) $(OUTPUT_OPTION)
# hack to create these sources once, before the dependencies
.GENERATE:
$(MAKE) $(gencc)
rm -f depend
+realdepend: $(cc)
+ $(CXX) $(CXXFLAGS) -MM $^ | perl -ne 's/^(.+)\.o/'$(OBJECTDIR)'\/\1.o/; print;' > depend
+
include depend
-parser.cc: parser.y
+$(CCDIR)/parser.cc: parser.y
$(BISON) -d $<
- mv parser.tab.h parser.hh
- mv parser.tab.c parser.cc
+ mv $(CCDIR)/parser.tab.h $(HEADERDIR)/parser.hh
+ mv $(CCDIR)/parser.tab.c $(CCDIR)/parser.cc
parser.hh: parser.cc
version.o: $(obs) version.hh
version.hh: Makefile make_version
- make_version $(MAJVER) $(MINVER) $(PATCHLEVEL) > $@
+ make_version $(MAJVER) $(MINVER) $(PATCHLEVEL) > $(HEADERDIR)/$@
-lexer.cc: lexer.l
+src/lexer.cc: lexer.l
$(FLEX) -+ -t $< > $@
-DDIR=$(TOPDIR)/$(DNAME)
-SUBDIRS=Documentation
dist:
-mkdir $(DDIR)
ln $(DFILES) $(DDIR)/
rm -rf $(DDIR)/
-TAGS: $(mycc) $(hdr) Sources.make
- etags -CT $(mycc) $(hdr)
-
+TAGS:
+ $(MAKE) -C $(HEADERDIR) TAGS
+ $(MAKE) -C $(CCDIR) TAGS
\ No newline at end of file
preliminary, please do not distribute. Please send your helpful comments and
patches to me,
- hanwen@stack.urc.tue.nl
+ hanwen@stack.urc.tue.nl
+
+LilyPond is updated very frequently, the latest version is always available at:
+
+ ftp://pcnov095.win.tue.nl/pub/lilypond
PREREQUISITES
You will need GNU C++ v2.7 or better and GNU make. If you actually
want to use this, you'd better use the "speedy" compilation flags in
the Makefile.
+Do:
+
+ tar zxf flower-1.11.9.tar.gz
+ mv flower-1.11.9 flower
+ cd flower; make; cd ..
+ tar zxf lilypond-1.2.13.tar.gz
+ cd lilypond-1.2.13
+ make
why G++ >= 2.7? LilyPond & flower lib uses builtin bool and typeof.
This is what the output looks like over here.
-hw:~/musix/spacer$ lilypond maartje.ly
-LilyPond version 0.0.6 compiled on Nov 2 1996 at 01:25:29
-Parsing ... [maartje.ly]
+hw:~/musix/spacer$ lilypond kortjakje.ly
+LilyPond version 0.0.9 compiled on Nov 7 1996 at 23:38:21
+Parsing ... [kortjakje.ly]
+Processing ... Calculating ...
output to lelie.uit...
+
hw:~/musix/spacer$ tex test
This is TeX, Version 3.14159 (C version 6.1)
(test.tex
Hyphenation patterns for english, dutch, loaded.
(lilyponddefs.tex) (lelie.uit) [1] )
-Output written on test.dvi (1 page, 1964 bytes).
+Output written on test.dvi (1 page, 3076 bytes).
Transcript written on test.log.
+
hw:~/musix/spacer$ xdvi test&
-[1] 3130
-hw:~/musix/spacer$
+[1] 1667
PROBLEMS
* Use The Source, Luke. If you don't know C++, you can try editing
.dstreamrc for copious debugging output.
-* see also the subdir Documentation
+* also the subdir Documentation/ it contains some in depth matter
+on LilyPond algorithms
* The source is commented in the DOC++ style.
Check out doc++ at
# sourcefiles to be shipped. Also for dependencies
hdr= qlp.hh linespace.hh qlpsolve.hh\
- pcol.hh proto.hh pstaff.hh line.hh\
+ pcol.hh proto.hh pstaff.hh scoreline.hh staffline.hh\
const.hh glob.hh molecule.hh boxes.hh pscore.hh item.hh tex.hh\
request.hh voice.hh command.hh staff.hh linestaff.hh \
tstream.hh rhythmstaff.hh\
parseconstruct.hh debug.hh globvars.hh keyword.hh\
misc.hh score.hh notename.hh lexer.hh symtable.hh\
- symbol.hh main.hh dimen.hh paper.hh lookupsyms.hh\
+ symbol.hh main.hh dimen.hh paper.hh lookup.hh\
sccol.hh stcol.hh scommands.hh melodicstaff.hh\
identifier.hh simplestaff.hh spanner.hh stem.hh\
- notehead.hh
+ notehead.hh leastsquares.hh beam.hh rest.hh\
+ swalker.hh bar.hh meter.hh
mycc= qlp.cc qlpsolve.cc \
- break.cc linespace.cc molecule.cc line.cc\
- pscore.cc tex.cc item.cc pcol.cc staff.cc rhythmstaff.cc\
- score.cc note.cc main.cc misc.cc \
+ break.cc linespace.cc molecule.cc staffline.cc\
+ pscore.cc tex.cc item.cc pcol.cc staff.cc \
+ rhythmstaff.cc score.cc note.cc main.cc misc.cc\
symbol.cc request.cc notename.cc voice.cc\
keyword.cc linestaff.cc table.cc command.cc\
warn.cc debug.cc symtable.cc boxes.cc\
pstaff.cc tstream.cc\
calcideal.cc scores.cc identifier.cc \
- dimen.cc paper.cc lookupsyms.cc scommands.cc\
+ dimen.cc paper.cc lookup.cc scommands.cc\
sccol.cc stcol.cc getcommands.cc simplestaff.cc\
melodicstaff.cc simpleprint.cc stem.cc\
- spanner.cc notehead.cc\
+ spanner.cc notehead.cc leastsquares.cc beam.cc\
+ texbeam.cc rest.cc swalker.cc scoreline.cc\
+ simplewalker.cc bar.cc meter.cc\
template1.cc template2.cc template3.cc\
version.cc
\ No newline at end of file
+++ /dev/null
-#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;
-}
-
+++ /dev/null
-/*
- some 2D geometrical concepts
-*/
-
-#ifndef BOXES_HH
-#define BOXES_HH
-
-#include "textdb.hh"
-#include "real.hh"
-#include "vray.hh"
-
-/// 2d vector
-struct Offset {
- Real x,y;
-
- Offset operator+(Offset o)const {
- Offset r(*this);
- r+=o;
- return r;
- }
-
- Offset operator+=(Offset o) {
- x+=o.x;
- y+=o.y;
- return *this;
- }
- Offset(Real ix , Real iy) {
- x=ix;
- y=iy;
- }
- Offset() {
- x=0.0;
- y=0.0;
- }
-};
-
-/// a Real interval
-struct Interval {
- Real min, max;
-
- void translate(Real t) {
- min += t;
- max += t;
- }
-
- void unite(Interval h) {
- if (h.min<min)
- min = h.min;
- if (h.max>max)
- max = h.max;
- }
- Real length() const;
- void set_empty() ;
- bool empty() { return min > max; }
- Interval() {
- set_empty();
- }
- Interval(Real m, Real M) {
- min =m;
- max = M;
- }
-};
-
-
-/// a 4-tuple of #Real#s
-struct Box {
- Interval x, y;
-
- void translate(Offset o) {
- x.translate(o.x);
- y.translate(o.y);
- }
- void unite(Box b) {
- x.unite(b.x);
- y.unite(b.y);
- }
- Box(svec<Real> );
- Box();
- Box(Interval ix, Interval iy);
-};
-
-
-#endif
+++ /dev/null
-/*
- do calculations for breaking problem
-
- */
-#include "paper.hh"
-#include "linespace.hh"
-#include "debug.hh"
-#include "line.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;
-}
-
-
-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 );
- 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);
- }
-}
-
+++ /dev/null
-#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);
- }
- }
-}
-
-
+++ /dev/null
-#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
-}
+++ /dev/null
-#ifndef COMMAND_HH
-#define COMMAND_HH
-#include "glob.hh"
-
-#include "vray.hh"
-#include "string.hh"
-
-enum Commandcode {
- NOP,
- INTERPRET,
- TYPESET,
- BREAK_PRE,BREAK_MIDDLE, BREAK_POST, BREAK_END
-};
-/// set a nonrythmical symbol
-struct Command {
- Commandcode code;
-
- Real when;
- /// analogous to argv[]
- svec<String> args;
- int priority;
-
- /****************/
-
- Command();
- Command(Real w);
- bool isbreak()const;
- void print() const;
-};
-
-/**
- A nonrhythmical "thing" in a staff is called a "command".
- Commands have these properties:
-
- \begin{itemize}
- \item They are \bf{not} rhythmical, i.e. they do not have a duration
- \item They have a staff-wide impact, i.e. a command cannot be targeted at
- only one voice in the staff: two voices sharing a staff can't have
- different clefs
- \item Commands are ordered, that is, when from musical point of view the
- commands happen simultaneously, the order in which Staff receives the
- commands can still make a difference in the output
- \item Some commands are actually score wide, so Score has to issue these
- commands to the Staff, eg. BREAK commands
- \end{itemize}
-
- At this moment we have three classes of commands:
- \begin{description}
- INTERPRET commands are not grouped.
- \item[TYPESET] These commands instruct the Staff to
- typeset symbols on the output, eg meter/clef/key changes
- \item[INTERPRET] These commands do not produce output, instead,
- they change the interpretation of other commands or requests.
- example: shift output vertically, set the key.
- \item[BREAK_XXX] These commands group TYPESET commands in
- prebreak and postbreak commands. \See{Col}.
- Staff can insert additional commands in a sequence of BREAK_XXX
- commands, eg. key change commands
-
- \end{description}
-
- These commands are generated by Score, since they have to be the
- same for the whole score.
-
-
- \begin{description}
- \item[BREAK_PRE]
- \item[BREAK_MIDDLE]
- \item[BREAK_POST]
- \item[BREAK_END]
- \item[TYPESET] METER,BAR
- \end{description}
-
-
- Commands can be freely copied, they do not have virtual methods.
- */
-
-
-#endif
+++ /dev/null
-/*
- global constants
- */
-#ifndef CONST_HH
-#define CONST_HH
-#include <math.h>
-#include "real.hh"
-
-const Real EPS=1e-7; // qlpsolve.hh
-const int MAXITER=100; // qlpsolve.hh
-const Real INFTY=HUGE;
-#endif
+++ /dev/null
-#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);
-}
+++ /dev/null
-#ifndef DEBUG_HH
-#define DEBUG_HH
-#include <assert.h>
-#include <iostream.h>
-#include "dstream.hh"
-
-void error(String s); // errors
-
-// warnings
-void warning(String s);
-#define WARN warnout << "warning: "<<__FUNCTION__ << "(): "
-extern ostream &warnout ;
-
-// progress
-extern ostream *mlog;
-
-// debugging
-extern Dstream monitor; // monitor
-
-#ifdef NPRINT
-#define mtor if (0) monitor // clever hack
-#else
-#define mtor monitor.identify_as(__PRETTY_FUNCTION__)
-#endif
-
-
-
-#endif
+++ /dev/null
-#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;
-}
+++ /dev/null
-#ifndef DIMEN_HH
-#define DIMEN_HH
-
-#include "real.hh"
-#include "string.hh"
-
-Real parse_dimen(String);
-Real convert_dimen(Real, String);
-String print_dimen(Real);
-
-#endif
-
MAJVER=1
MINVER=0
-PATCHLEVEL=8
+PATCHLEVEL=10
PACKAGENAME=flower
VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
obs=$(cc:.cc=.o)
staticlib=libflower.a
+
$(staticlib): $(obs)
$(AR) cr libflower.a $(obs)
clean:
rm -f $(obs) $(staticlib)
+
realclean: clean
rm -f depend
+
DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO README
DDIR=$(DNAME)
ln $(DFILES) $(DDIR)/
tar cfz $(DNAME).tar.gz $(DDIR)/*
rm -rf $(DDIR)/
+
TAGS:
etags -CT $(inl) $(cc) $(hh)
This library contains some general purpose routines which aren't
-standardised yet. It was written by:
+standardised libraries yet. It may be replaced by STL in time
+
+It was written by:
Han-Wen Nienhuys <hanwen@stack.nl>
* PCursor -> Pointer_cursor / PointerCursor ?
- * remove List::List(element)
-
* efficient copy cons for List
* extend Interval
Text_db cfg(fn);
while (! cfg.eof()){
Text_record r( cfg++);
- assert(r.sz() == 2);
+ if (r.sz() != 2) {
+ r.message("not enough fields in Dstream init.");
+ continue;
+ }
(*silent)[r[0]] = r[1].to_bool();
}
template<class T>
-inline
List<T>::~List()
{
Cursor<T> next(*this);
}
template<class T>
-inline void
-List<T>::add( const T& thing, Cursor<T> after_me )
+void
+List<T>::add( const T& thing, Cursor<T> &after_me )
{
if (!size_) { // not much choice if list is empty
bottom_ = top_ = new Link<T>( thing );
+ if (!after_me.ok())
+ after_me = bottom();
} else { // add at aprioprate place
- Link<T> *p = ( after_me.ok() ) ?
- after_me.pointer() : bottom().pointer();
+ if (!after_me.ok())
+ after_me = bottom();
+ Link<T> *p =after_me.pointer();
p->add(thing);
if (p == bottom_) // adjust bottom_ if necessary.
bottom_ = p->next();
*/
template<class T>
-inline void
-List<T>::insert( const T& thing, Cursor<T> before_me )
+void
+List<T>::insert( const T& thing, Cursor<T> &before_me )
{
if (!size_) {
bottom_ = top_ = new Link<T>( thing );
+ if (!before_me.ok())
+ before_me = top();
+
} else {
- Link<T> *p =
- (before_me.ok())?
- before_me.pointer() : top().pointer();
+ if (!before_me.ok())
+ before_me = top();
+
+ Link<T> *p = before_me.pointer() ;
p->insert(thing);
if (p == top_)
top_ = p->previous();
}
-
- size_++;
+ size_++;
}
+
+template<class T>
+void
+List<T>::concatenate(List<T> const&s)
+{
+ Cursor<T> b(bottom());
+ for (Cursor<T> c(s); c.ok(); c++) {
+ b.add(c);
+ b++;
+ }
+}
#endif
-// list.hh
-
#ifndef __LIST_HH
#define __LIST_HH
template<class T> class Cursor;
template<class T> class Link;
-/// all purpose list
+/// all-purpose doubly linked list
template<class T>
class List
{
List(List const&src);
/// construct empty list
- List();
-
- /// construct list from first item.
- List( const T& thing );
-
+ List();
virtual ~List();
Cursor<T> bottom();
protected:
friend class Cursor<T>;
friend class Link<T>;
+
+ void concatenate(List<T> const &s);
+
+
/// make *this empty
void set_empty();
/**
*/
/// add after after_me
- void add( const T& thing, Cursor<T> after_me );
+ void add( const T& thing, Cursor<T> &after_me );
/// put thing before #before_me#
- void insert( const T& thing, Cursor<T> before_me );
+ void insert( const T& thing, Cursor<T> &before_me );
virtual void remove( Cursor<T> me );
/**
Remove link pointed to by me.
size_ = 0;
}
-template<class T>
-inline
-List<T>::List( const T& thing )
-{
- set_empty();
- add( thing, Cursor<T>( *this, bottom_ ) );
-}
template<class T>
inline void
List<T>::remove( Cursor<T> me )
PCursor<T> operator +( int no) const {
return PCursor<T> (Cursor<void*>::operator+(no));
}
+
PCursor(const PointerList<T> & l) : Cursor<void*> (l) {}
PCursor( const Cursor<void*>& cursor ) : Cursor<void*>(cursor) { }
T operator ->() const { return ptr(); }
operator T() { return ptr(); }
T operator *() { return ptr(); }
+ void add(const T& p ) { Cursor<void*>::add((void*) p); }
+ void insert(const T& p ) { Cursor<void*>::insert((void*) p);}
private:
// Cursor<void*>::operator void*;
// sigh
};
/**
-don't create PointerList<void*>'s
+ don't create PointerList<void*>'s.
+ This cursor is just an interface class for Cursor. It takes care of the
+ appropriate type casts
*/
public:
PCursor<T> top() { return PCursor<T> (List<void*>::top()); }
PCursor<T> bottom() { return PCursor<T> (List<void*>::bottom()); }
-
- PointerList( const T& thing ) : List<void*>( thing ) { }
+ void concatenate(PointerList<T> const &s) { List<void*>::concatenate(s); }
+// PointerList( const T& thing ) : List<void*>( thing ) { }
PointerList() {}
};
+++ /dev/null
-#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;
-}
-
-
+++ /dev/null
-#ifndef GLOB_HH
-#define GLOB_HH
-#include <assert.h>
-#include <math.h>
-#include "real.hh"
-
-#include "proto.hh"
-#include "const.hh"
-#endif
--- /dev/null
+default:
+ $(MAKE) -C ..
+
+dist:
+ ln Makefile $(hdr) $(DDIR)/$(HEADERDIR)
+
+TAGS: $(hdr)
+ etags -CT $(hdr)
--- /dev/null
+/*
+ bar.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef BAR_HH
+#define BAR_HH
+#include "item.hh"
+
+struct Bar: Item {
+ String type;
+
+ Bar(String type);
+ void preprocess();
+};
+#endif // BAR_HH
+
--- /dev/null
+/*
+ beam.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef BEAM_HH
+#define BEAM_HH
+#include "proto.hh"
+#include "spanner.hh"
+#include "list.hh"
+
+/// a beam connects multiple stems
+struct Beam: public Spanner {
+ List<Stem*> stems;
+ Real slope;
+ Real left_pos;
+ /// -1 below heads, +1 above heads.
+ int dir;
+
+ /****************/
+
+ virtual Interval width()const;
+
+ Spanner *broken_at(const PCol *, const PCol *) const;
+ Beam();
+ void add(Stem*);
+ void process();
+ void calculate();
+ void set_default_dir();
+ void preprocess();
+ Interval height()const;
+ void print() const;
+
+ void set_stemlens();
+private:
+ void solve_slope();
+ void brew_molecule();
+};
+/** Beam adjusts the stems its owns to make sure that they reach the
+ beam and that point in the correct direction */
+
+#endif // BEAM_HH
+
--- /dev/null
+/*
+ some 2D geometrical concepts
+*/
+
+#ifndef BOXES_HH
+#define BOXES_HH
+
+#include "textdb.hh"
+#include "real.hh"
+#include "vray.hh"
+
+/// 2d vector
+struct Offset {
+ Real x,y;
+
+ Offset operator+(Offset o)const {
+ Offset r(*this);
+ r+=o;
+ return r;
+ }
+
+ Offset operator+=(Offset o) {
+ x+=o.x;
+ y+=o.y;
+ return *this;
+ }
+ Offset(Real ix , Real iy) {
+ x=ix;
+ y=iy;
+ }
+ Offset() {
+ x=0.0;
+ y=0.0;
+ }
+};
+
+/// a Real interval
+struct Interval {
+ Real min, max;
+
+ void translate(Real t) {
+ min += t;
+ max += t;
+ }
+
+ void unite(Interval h) {
+ if (h.min<min)
+ min = h.min;
+ if (h.max>max)
+ max = h.max;
+ }
+ Real length() const;
+ void set_empty() ;
+ bool empty() { return min > max; }
+ Interval() {
+ set_empty();
+ }
+ Interval(Real m, Real M) {
+ min =m;
+ max = M;
+ }
+ Interval &operator += (Real r) {
+ min += r;
+ max +=r;
+ return *this;
+ }
+};
+
+
+/// a 4-tuple of #Real#s
+struct Box {
+ Interval x, y;
+
+ void translate(Offset o) {
+ x.translate(o.x);
+ y.translate(o.y);
+ }
+ void unite(Box b) {
+ x.unite(b.x);
+ y.unite(b.y);
+ }
+ Box(svec<Real> );
+ Box();
+ Box(Interval ix, Interval iy);
+};
+
+
+#endif
--- /dev/null
+#ifndef COMMAND_HH
+#define COMMAND_HH
+
+#include "glob.hh"
+#include "vray.hh"
+#include "string.hh"
+
+enum Commandcode {
+ NOP,
+ INTERPRET,
+ TYPESET,
+ BREAK_PRE,BREAK_MIDDLE, BREAK_POST, BREAK_END
+};
+
+/// set a nonrythmical symbol
+struct Command {
+ Commandcode code;
+
+ Real when;
+ /// analogous to argv[]
+ svec<String> args;
+
+ ///
+ int priority;
+ /** in what order relative to other TYPESET commands (eg, bar
+ should precede meter). Highest priority first. */
+
+ /****************/
+
+ Command();
+ Command(Real w);
+ bool isbreak()const;
+ void print() const;
+};
+
+/**
+ A nonrhythmical "thing" in a staff is called a "command".
+ Commands have these properties:
+
+ \begin{itemize}
+ \item They are \bf{not} rhythmical, i.e. they do not have a duration
+ \item They have a staff-wide impact, i.e. a command cannot be targeted at
+ only one voice in the staff: two voices sharing a staff can't have
+ different clefs
+ \item Commands are ordered, that is, when from musical point of view the
+ commands happen simultaneously, the order in which Staff receives the
+ commands can still make a difference in the output
+ \item Some commands are actually score wide, so Score has to issue these
+ commands to the Staff, eg. BREAK commands
+ \end{itemize}
+
+ At this moment we have three classes of commands:
+ \begin{description}
+ INTERPRET commands are not grouped.
+ \item[TYPESET] These commands instruct the Staff to
+ typeset symbols on the output, eg meter/clef/key changes
+ \item[INTERPRET] These commands do not produce output, instead,
+ they change the interpretation of other commands or requests.
+ example: shift output vertically, set the key.
+ \item[BREAK_XXX] These commands group TYPESET commands in
+ prebreak and postbreak commands. See Documentation/breaking
+
+ Staff can insert additional commands in a sequence of BREAK_XXX
+ commands, eg. key change commands
+
+ \end{description}
+
+ These commands are generated by Score, since they have to be the
+ same for the whole score.
+
+
+ \begin{description}
+ \item[BREAK_PRE]
+ \item[BREAK_MIDDLE]
+ \item[BREAK_POST]
+ \item[BREAK_END]
+ \item[TYPESET] METER,BAR
+ \end{description}
+
+
+ Commands can be freely copied, they do not have virtual methods.
+
+ */
+
+
+#endif
--- /dev/null
+/*
+ global constants
+ */
+#ifndef CONST_HH
+#define CONST_HH
+#include <math.h>
+#include "real.hh"
+
+const Real EPS=1e-7; // qlpsolve.hh
+const int MAXITER=100; // qlpsolve.hh
+const Real INFTY=HUGE;
+#endif
--- /dev/null
+#ifndef DEBUG_HH
+#define DEBUG_HH
+#include <assert.h>
+#include <iostream.h>
+#include "dstream.hh"
+
+void error(String s); // errors
+
+// warnings
+void warning(String s);
+#define WARN warnout << "warning: "<<__FUNCTION__ << "(): "
+extern ostream &warnout ;
+
+// progress
+extern ostream *mlog;
+
+// debugging
+extern Dstream monitor; // monitor
+
+#ifdef NPRINT
+#define mtor if (0) monitor // clever hack
+#else
+#define mtor monitor.identify_as(__PRETTY_FUNCTION__)
+#endif
+
+
+
+#endif
--- /dev/null
+#ifndef DIMEN_HH
+#define DIMEN_HH
+
+#include "real.hh"
+#include "string.hh"
+
+Real parse_dimen(String);
+Real convert_dimen(Real, String);
+String print_dimen(Real);
+
+#endif
+
--- /dev/null
+#ifndef GLOB_HH
+#define GLOB_HH
+#include <assert.h>
+#include <math.h>
+#include "real.hh"
+
+#include "proto.hh"
+#include "const.hh"
+#endif
--- /dev/null
+
+/*
+ identifier.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef IDENTIFIER_HH
+#define IDENTIFIER_HH
+#include "proto.hh"
+#include "string.hh"
+
+struct Identifier
+{
+ void *data;
+ String name;
+
+ Identifier(String n) ;
+ virtual ~Identifier();
+ virtual Staff * staff() { assert(false); }
+ virtual Voice * voice() { assert(false); }
+};
+
+struct Staff_id : Identifier {
+ Staff_id(String s, Staff*st):Identifier(s) { data = st; }
+ virtual Staff* staff() { return (Staff*) data; }
+ ~Staff_id();
+};
+
+struct Voice_id : Identifier {
+ Voice_id(String s, Voice*st):Identifier(s) { data = st; }
+ virtual Voice * voice() { return (Voice*)data; }
+ ~Voice_id();
+};
+#endif // IDENTIFIER_HH
+
--- /dev/null
+#ifndef ITEM_HH
+#define ITEM_HH
+
+#include "glob.hh"
+#include "boxes.hh"
+#include "string.hh"
+
+/// a horizontally fixed size element of the score
+struct Item {
+ /// indirection to the column it is in
+ PCol * pcol_;
+
+ /// indirection to the pstaff it is in
+ PStaff *pstaff_;
+
+ /// member: the symbols
+ Molecule *output;
+
+ ///
+ Offset offset_;
+ /**
+ This is needed, because #output# may still be
+ NULL.
+ */
+ /****************/
+
+ void translate(Offset);
+
+ /// do calculations after determining horizontal spacing
+ virtual void postprocess();
+
+ /// do calculations before determining horizontal spacing
+ virtual void preprocess();
+ /**
+ This is executed directly after the item is added to the
+ PScore
+ */
+
+ virtual Interval width() const;
+ virtual Interval height() const;
+ String TeXstring () const ;
+ Item();
+ void print()const;
+ virtual ~Item();
+ Paperdef *paper() const;
+};
+/** Item is the datastructure for printables whose width is known
+ before the spacing is calculated
+
+ NB. This doesn't mean an Item has to initialize the output field before
+ spacing calculation.
+
+*/
+
+
+#endif
--- /dev/null
+/* 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;
+};
--- /dev/null
+/*
+ leastsquare.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef LEASTSQUARE_HH
+#define LEASTSQUARE_HH
+#include "vray.hh"
+#include "boxes.hh"
+
+struct Least_squares {
+ svec<Offset> input;
+ void minimise(Real &coef, Real &offset);
+};
+
+
+#endif // LEASTSQUARE_HH
+
--- /dev/null
+#ifndef LEXER_HH
+#define LEXER_HH
+
+#include "proto.hh"
+
+void new_input(String s);
+bool close_input();
+int yylex();
+void yyerror(const char *s);
+
+int lookup_keyword(String s);
+
+Identifier* lookup_identifier(String s);
+void add_identifier(Identifier*i);
+void delete_identifiers();
+void kill_lexer();
+#endif
--- /dev/null
+#ifndef PROBLEM_HH
+#define PROBLEM_HH
+
+#include "glob.hh"
+#include "plist.hh"
+#include "vray.hh"
+#include "pcol.hh"
+#include "matrix.hh"
+
+/// helper struct for #Spacing_problem#
+struct Colinfo {
+ const PCol *pcol_;
+ bool fixed;
+ Real fixpos;
+ Colinfo();
+ void print() const;
+ Real minright() const { return pcol_->width().max; }
+ Real minleft() const { return -pcol_->width().min; }
+};
+
+
+/// spacing for one line.
+class Spacing_problem {
+ svec<const Idealspacing*> ideals;
+ svec<Colinfo> cols;
+
+ /// the index of #c# in #cols#
+ int col_id(const PCol *c) const;
+
+ /// generate an (nonoptimal) solution
+ Vector find_initial_solution() const;
+
+ /// check if problem is too tight
+ bool check_feasible() const;
+ /// does #this# contain the column #w#?
+ bool contains(const PCol *w);
+
+ /// make the energy function
+ void make_matrices(Matrix &quad, Vector &lin,Real&) const;
+
+ /// generate the LP constraints
+ void make_constraints(Mixed_qp& lp) const;
+
+public:
+ /// solve the spacing problem
+ svec<Real> solve() const;
+ /**
+ return the column positions, and the energy (last element)
+ */
+ /// add a idealspacing to the problem.
+ void add_ideal(const Idealspacing *i);
+
+ /**
+ One pair of columns can have no, one or more idealspacings,
+ since they can be "summed" if the columns to which #i# refers are
+ not in this problem, the spacing is ignored.
+ */
+
+
+ /// add a col to the problem
+ void add_column(const PCol *, bool fixed=false, Real fixpos=0.0);
+ /** columns have to be added left to right. The column contains
+ info on it's minimum width.
+ */
+
+
+ bool check_constraints(Vector v) const;
+
+ Vector try_initial_solution() const;
+ void OK() const;
+ void print() const;
+ void print_ideal(const Idealspacing*)const;
+};
+
+
+/** the problem, given by the columns (which include constraints) and
+ intercolumn spacing. The problem is:
+
+ Generate a spacing which
+ \begin{itemize}
+ \item
+ Satisfies spacing constraints (notes can't be printed through each other)
+ \item
+ Looks good, ie tries to conform to an ideal spacing as much as possible.
+ \end{itemize}
+ This is converted by regarding idealspacing as "springs" attached
+ to columns. The equilibrium of one spring is the ideal
+ distance. The columns have a size, this imposes "hard" constraints
+ on the distances. This transforms the problem into a quadratic
+ programming problem with linear constraints.
+
+ The quality is given by the total potential energy in the
+ springs. The lower the energy, the better the configuration.
+*/
+#endif
--- /dev/null
+#include "pstaff.hh"
+
+struct Linestaff : PStaff {
+
+ int nolines;
+
+/****************/
+
+ Symbol get_stafsym(Real width)const;
+ Linestaff(int, PScore*);
+};
--- /dev/null
+/*
+ lilypond, (c) 1996 Han-Wen Nienhuys
+*/
+#ifndef LOOKUPSYMS_HH
+#define LOOKUPSYMS_HH
+
+#include "symbol.hh"
+
+struct Lookup {
+ Symtables *symtables_;
+
+ /****************/
+
+ void parse (Text_db&t);
+ Parametric_symbol *linestaff(int n);
+ Parametric_symbol *meter(String);
+ Parametric_symbol *stem();
+
+ Symbol beam_element(int,int,Real=0);
+ /// round slope to closest TeXslope
+ Symbol beam(Real&,Real);
+ Symbol streepjes(int pos);
+ /**
+ pos == 3 : 3 lines above staff (extending below note)
+
+ pos == -3: below staff
+ */
+
+ Symbol rule_symbol(Real height, Real width);
+
+ Symbol ball(int);
+ Symbol flag(int);
+ Symbol rest(int);
+ Symbol bar(String);
+ Symbol dots(int);
+ Lookup();
+ ~Lookup();
+};
+
+#endif
--- /dev/null
+#ifndef MAIN_HH
+#define MAIN_HH
+#include "proto.hh"
+
+void debug_init();
+void do_scores();
+void add_score(Score * s);
+void set_default_output(String s);
+const char *get_version();
+
+#endif
--- /dev/null
+/*
+ rhythmstaf.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef MELODICSTAFF_HH
+#define MELODICSTAFF_HH
+
+#include "simplestaff.hh"
+
+/// five line staff, no multiple voices
+struct Melodic_staff : public Simple_staff
+{
+
+ /****************/
+
+ virtual void set_output(PScore *);
+ virtual Melodic_staff*clone()const;
+
+ virtual Stem * get_stem(Stem_req *rq);
+ virtual Notehead * get_notehead(Note_req *rq);
+};
+
+#endif // MELODICSTAFF_HH
+
+
--- /dev/null
+/*
+ meter.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef METER_HH
+#define METER_HH
+#include "item.hh"
+
+struct Meter: Item {
+ svec<String> args;
+
+ Meter(svec<String> args) ;
+ void preprocess();
+};
+#endif // METER_HH
+
--- /dev/null
+#ifndef MISC_HH
+#define MISC_HH
+
+
+
+
+#endif
--- /dev/null
+#ifndef MOLECULE_HH
+#define MOLECULE_HH
+
+#include "plist.hh"
+#include "boxes.hh"
+#include "item.hh"
+#include "symbol.hh"
+/// a symbol which can be translated, and freely copied
+struct Atom {
+ Offset off;
+ Symbol sym;
+
+ void translate(Offset o) {
+ off += o;
+ }
+
+ /// how big is #this#?
+ Box extent() const;
+ Atom(Symbol s);
+
+ void print() const;
+
+ String TeXstring() const;
+};
+
+/// a group of #Atom#s
+struct Molecule {
+ PointerList<Atom*> ats;
+
+ Molecule() { }
+ Molecule(Atom a) { add(a) ; }
+
+ void add_right(const Molecule &m);
+ void add_left(const Molecule &m);
+ void add_top(const Molecule &m);
+ void add_bot(const Molecule &m);
+ void add(Molecule const &m);
+ void translate(Offset);
+ void add(Atom a) { ats.bottom().add(new Atom(a)); }
+ /// how big is #this#?
+ Box extent() const;
+
+ String TeXstring() const;
+
+ Molecule(const Molecule&s);
+ void print() const;
+private:
+ void operator=(const Molecule&);
+};
+/** a group of individually translated symbols. You can add molecules
+ to the top, to the right, etc. */
+#endif
--- /dev/null
+/*
+ notehead.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef NOTEHEAD_HH
+#define NOTEHEAD_HH
+#include "item.hh"
+
+/// ball at the end of the stem
+struct Notehead : public Item
+{
+ int position;
+ int staff_size;
+ int dots;
+ int balltype;
+
+ /****************/
+ void preprocess();
+
+ Notehead(int staff_size);
+ /**
+ position of top line (5 linestaff: 8)
+ */
+ void print()const;
+private:
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ * help lines
+ * proper placing of dots
+
+ */
+#endif // NOTEHEAD_HH
+
--- /dev/null
+
+void lookup_notename(int &large, int &small, String s);
--- /dev/null
+#include "proto.hh"
+#include "real.hh"
+#include "string.hh"
+
+/// symbols, dimensions and constants
+struct Paperdef {
+ Lookup *lookup_;
+ String outfile;
+ Real linewidth;
+
+ /// how much space does a whole note take (ideally?)
+ Real whole_width;
+
+ /// ideal = geometric_ ^ log2(duration)
+ Real geometric_;
+
+ /****************/
+ void parse();
+ Paperdef();
+ ~Paperdef();
+ Real interline()const;
+ Real rule_thickness()const;
+ Real standard_height()const;
+ Real note_width() const;
+ void print() const;
+ Real duration_to_dist(Real);
+};
+/** This struct takes care of all kinds of symbols, dimensions and
+ constants. Most of them are related to the point-size of the fonts,
+ so therefore, the lookup table for symbols is also in here.
+
+ see TODO
+ */
--- /dev/null
+#include "proto.hh"
+
+template<class T>
+struct svec;
+
+void set_default_duration(String);
+void set_default_pitch(String);
+Staff * get_new_rhythmstaff();
+Voice_element * get_note_element(String,String);
+Voice_element* get_rest_element(String,String);
+Command * get_bar_command(Real);
+Staff * get_new_melodicstaff();
+Command* get_meterchange_command( int,int);
+Command* get_meter_command( Real,int,int);
+Command* get_skip_command( int,Real);
+Request* get_request(char);
+void add_requests( Voice_element*v, svec<Request*>&req);
--- /dev/null
+#ifndef COLS_HH
+#define COLS_HH
+
+#include "glob.hh"
+#include "boxes.hh"
+#include "plist.hh"
+#include "item.hh"
+
+/// stuff grouped vertically.
+struct PCol {
+ List<const Item*> its;
+ List<const Spanner*> stoppers, starters;
+
+ /// Can this be broken? true eg. for bars.
+ bool breakable()const;
+
+ /// does this column have items, does it have spacings attached?
+ bool used;
+
+ /// prebreak is put before end of line.
+ PCol *prebreak;
+ /**
+ if broken here, then (*this) column is discarded, and prebreak
+ is put at end of line, owned by Col
+ */
+
+ /// postbreak at beginning of the new line
+ PCol *postbreak;
+ /** \See{prebreak}
+ */
+ PCol *daddy;
+ /*
+ if this column is pre or postbreak, then this field points to the parent.
+ */
+ /// if lines are broken then this column is in #line#
+ const Line_of_score *line;
+
+ /// if lines are broken then this column x-coord #hpos#
+ Real hpos;
+
+
+ /****************************************************************/
+
+ void add(Item*i);
+
+ Interval width() const;
+ ~PCol();
+ PCol(PCol * parent);
+
+ /// which col comes first?
+ static int compare(const PCol &c1, const PCol &c2);
+ /**
+ signed compare on columns.
+
+ return < 0 if c1 < c2.
+ */
+
+ void OK() const;
+ void set_breakable();
+ void print()const;
+};
+/**
+ This is a class to address items vertically. It contains the data for:
+ \begin{itemize}
+ \item
+ unbroken score
+ \item
+ broken score
+ \item
+ the linespacing problem
+ \end{itemize}
+ */
+
+#include "compare.hh"
+instantiate_compare(const PCol &, PCol::compare);
+
+
+/// ideal spacing between two columns
+struct Idealspacing {
+
+ /// the ideal distance
+ Real space;
+
+ /// Hooke's constant: how strong are the "springs" attached to columns
+ Real hooke;
+
+ /// the two columns
+ const PCol *left, *right;
+
+ void print()const;
+ void OK() const ;
+ Idealspacing(const PCol *left,const PCol *right);
+};
+
+#endif
--- /dev/null
+/*
+ proto.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef PROTO_HH
+#define PROTO_HH
+#include "real.hh"
+
+class Line_of_score;
+class Line_of_staff;
+class PCol;
+class PStaff;
+class Staff;
+class Staff_column;
+class Score;
+class Score_column;
+class Voice;
+class Voice_element;
+class Voicegroup;
+class Request;
+class Command;
+class Request;
+class Stem_req;
+class Span_req;
+class Slur_req;
+class Decresc_req;
+class Cresc_req;
+class Bracket_req;
+class Script_req;
+class Rest_req;
+class Note_req;
+class Lyric_req;
+class Chord;
+class Absdynamic_req;
+struct Offset;
+struct Interval;
+struct Box;
+struct PCol;
+struct Idealspacing;
+struct Spanner;
+struct Item;
+struct Line_of_staff;
+struct Colinfo;
+struct Linestaff;
+struct Atom;
+struct Molecule;
+struct PScore;
+struct Request;
+struct Note_req;
+struct Lyric_req;
+struct Script_req;
+struct Rest_req;
+struct Rhythmic_req;
+struct Chord;
+struct Stem_req;
+struct Span_req;
+struct Beam_req;
+struct Bracket_req;
+struct Slur_req;
+struct Dynamic;
+struct Cresc_req;
+struct Decresc_req;
+struct Absdynamic_req;
+struct Score_column;
+struct Score;
+struct Staff_column;
+struct Staff;
+struct Command;
+struct Symbol;
+struct Output;
+struct Text_gob;
+struct Voice;
+struct Voicegroup;
+struct Voice_element;
+struct String;
+struct Tex_stream;
+struct Identifier;
+struct Keyword;
+class Mixed_qp;
+class Paperdef;
+class Score_commands;
+class Parametric_symbol;
+struct Lookup;
+struct Symtables;
+struct Symtable;
+struct Stem;
+struct Notehead;
+struct Beam;
+struct Rest;
+#endif // PROTO_HH
+
--- /dev/null
+// the breaking problem for a score.
+
+#ifndef PSCORE_HH
+#define PSCORE_HH
+
+
+#include "vray.hh"
+#include "pcol.hh"
+#include "pstaff.hh"
+
+/// all stuff which goes onto paper
+struct PScore {
+ Paperdef *paper_; // indirection.
+
+ /// the columns, ordered left to right
+ PointerList<PCol *> cols;
+
+ /// the idealspacings, no particular order
+ PointerList<Idealspacing*> suz;
+
+ /// the staffs ordered top to bottom
+ PointerList<PStaff*> staffs;
+
+ /// all symbols in score. No particular order.
+ PointerList<Item*> its;
+
+ /// if broken, the different lines
+ PointerList<Line_of_score*> lines;
+
+ /// crescs etc; no particular order
+ PointerList<Spanner *> spanners;
+
+ /****************************************************************/
+
+ svec<Item*> select_items(PStaff*, PCol*);
+
+ /// before calc_breaking
+ void preprocess();
+
+ void calc_breaking();
+ /**
+ calculate where the lines are to be broken.
+
+ POST
+
+ lines contain the broken lines.
+ */
+
+ /// after calc_breaking
+ void postprocess();
+
+ /// search all pcols which are breakable.
+ svec<const PCol *> find_breaks() const;
+
+ /// add a line to the broken stuff. Positions given in #config#
+ void add_line(svec<const PCol *> curline, svec<Real> config);
+
+ /// helper: solve for the columns in #curline#.
+ svec<Real> solve_line(svec<const PCol *> curline) const;
+
+ void add(PStaff *);
+ /// add item
+ void typeset_item(Item *, PCol *,PStaff*,int=1);
+
+ /// add an Spanner
+ void typeset_spanner(Spanner*, PStaff*);
+
+ /// add to bottom of pcols
+ void add(PCol*);
+ /**
+
+ */
+ void output(Tex_stream &ts);
+
+ Idealspacing* get_spacing(PCol *, PCol *);
+ /*
+ get the spacing between c1 and c2, create one if necessary.
+ */
+
+ /// return argument as a cursor.
+ PCursor<PCol *> find_col(PCol *);
+
+ /// delete unused columns
+ void clean_cols();
+
+
+ /// check if the spacing/breaking problem is well-stated
+ void problem_OK() const;
+
+ /// invarinants
+ void OK()const;
+ PScore(Paperdef*);
+ void print() const;
+
+ /// does curline fit on the paper?
+ bool feasible(svec<const PCol *> curline) const;
+};
+/** notes, signs, symbols in a score can be grouped in two ways:
+ horizontally (staffwise), and vertically (columns). #PScore#
+ contains the items, the columns and the staffs.
+ */
+#endif
--- /dev/null
+#ifndef PSTAFF_HH
+#define PSTAFF_HH
+
+#include "plist.hh"
+#include "item.hh"
+#include "symbol.hh"
+
+/// items grouped vertically.
+struct PStaff {
+ Parametric_symbol *stafsym;
+ PScore * pscore_;
+
+ virtual Symbol get_stafsym(Real width)const=0; // maybe overkill
+
+ List<const Spanner*> spans;
+ List<Item*> its;
+
+ void add(Item*i);
+ PStaff(PScore*);
+ virtual ~PStaff() {}
+};
+
+#endif
--- /dev/null
+#ifndef QLP_HH
+#define QLP_HH
+
+#include "matrix.hh"
+
+/// inequality constrained quadratic program
+class Ineq_constrained_qp {
+ friend class Active_constraints;
+
+ svec<Vector> cons;
+ svec<Real> consrhs;
+public:
+ Matrix quad;
+ Vector lin;
+ Real const_term;
+
+ ///
+ void assert_solution(Vector sol) const;
+ /**
+ use a KKT method to assert optimality of sol
+ */
+ /// solve the problem using a projected gradient method
+ Vector solve(Vector start) const;
+
+ int dim() const{
+ return lin.dim();
+ }
+ /** return the number of variables in the problem */
+ ///
+ void add_inequality_cons(Vector c, double r);
+ /**
+ add a constraint
+
+
+ c*vars >= r
+
+ PRE
+ c.dim() == dim();
+
+ */
+ ///
+ Ineq_constrained_qp(int novars);
+ /** set up matrices to go with the problem. */
+
+ Real eval(Vector v);
+ /**
+ evaluate the quadratic function for input #v#
+ */
+
+ void eliminate_var(int idx, Real value);
+ void OK()const;
+ void print() const;
+
+};
+
+/// Quadratic programming with mixed linear constraints
+class Mixed_qp :public Ineq_constrained_qp {
+ svec<int> eq_cons;
+ svec<Real> eq_consrhs;
+public:
+ Mixed_qp(int n);
+ void OK() const;
+ void print() const;
+
+ Vector solve(Vector start) const;
+ void add_fixed_var(int i , Real value);
+
+ ///
+ void add_equality_cons(Vector c, double r);
+ /**
+ add a constraint,
+
+ c*vars == r
+
+ PRE
+ c.dim()==dim();
+ */
+
+};
+/**
+ problem definition of a quadratic optimisation problem with linear
+ inequality and equality constraints
+
+
+ x^T QUAD x /2 + b^T x
+*/
+
+
+#endif
--- /dev/null
+#include "qlp.hh"
+#include "matrix.hh"
+
+
+class Active_constraints {
+ friend class Inactive_iter;
+
+
+ Matrix A,H;
+ svec<int> active;
+ svec<int> inactive; // actually this is a set, not an array.
+ const Ineq_constrained_qp *opt;
+
+public:
+ String status()const;
+
+ Vector vec(int k) const { return opt->cons[k]; }
+ Real rhs(int k) const { return opt->consrhs[k]; }
+
+ /// drop constraint
+ void drop (int k);
+ /** drop constraint k from the active set. k is the index of the
+ constraint in #active#
+
+ */
+
+ /// add constraint j
+ void add(int j);
+ /**
+ add constraint j to the active set j is the index of the
+ constraint in #inactive#
+ */
+
+ /// exchange in and out.
+ void exchange(int in, int out) { add(in); drop (out); }
+
+ ///
+ Vector find_active_optimum(Vector g);
+
+ /// get lagrange multipliers.
+ Vector get_lagrange(Vector v);
+
+ Active_constraints(Ineq_constrained_qp const *op);
+ /** construct: no constraints active, n vars. Put the equalities
+ into the constraints. */
+
+ /// check invariants
+ void OK();
+};
+
+/**
+ This class represents the set of active (binding) constraints
+ which can be active while the QLP algorithm is in a feasible
+ point. The active constraints are numbered.
+ If the constraints are of the form
+
+ A^T*x >= b
+
+ then the binding constraints are those where the >= is equality.
+
+ */
+
+///
+class Inactive_iter {
+ int j;
+ Active_constraints const* ac;
+public:
+ Inactive_iter(Active_constraints const &c) { ac=&c; j=0; }
+ int idx() const { return j; }
+ void operator ++(int) { j++; }
+ int constraint_id() const { return ac->inactive[j]; }
+ Vector vec() const { return ac->vec(constraint_id()); }
+ Real rhs() const { return ac->rhs(constraint_id()); }
+ bool ok() const { return j < ac->inactive.sz(); }
+};
+/**
+ loop through the inactive constraints.
+ */
--- /dev/null
+// LilyPond's second egg of columbus!
+#ifndef REQUEST_HH
+#define REQUEST_HH
+
+#include "glob.hh"
+#include "string.hh"
+
+/// a voice element wants something printed
+struct Request {
+ Voice_element*elt; // indirection.
+
+ /****************/
+
+ Request();
+
+ virtual void print()const ;
+ virtual Note_req *note() {return 0;}
+ virtual Stem_req *stem() {return 0;}
+ virtual Rest_req *rest() {return 0;}
+ virtual Span_req *span() {return 0;}
+ virtual Beam_req *beam() { return 0 ; }
+ virtual Rhythmic_req*rhythmic() { return 0;}
+ virtual Real duration() const { return 0.0; }
+ virtual Request* clone() const =0;
+};
+
+/**
+ Any Voice_element can do a number of requests. A request is done
+ to the #Staff# which contains the #Voice_element#. The staff decides
+ whether to to honor the request, ignore it, or merge it with other
+ requests. Merging of requests is preferably done with other
+ requests done by members of the same voicegroups (beams, brackets, stems)
+
+ Please refer to the documentation of the Child classes of
+ #Request# for explanation of each request type.
+
+ The result of a request will be an #Item# or a #Spanner#, which
+ will be put on a #PStaff#. Note that the #PStaff# and the original
+ #Staff# need not have anything in common. For example, the
+ ``double'' piano Staff could interpret commands which juggle
+ melodies across the left and right hand, and may put the result in
+ two five-line PStaffs (maybe with extra PStaffs to carry the dynamic
+ signs and any lyric.
+
+ The class #Staff# should be thought as a container for the
+ #Voice#s, and an interpreter for #Request#s and #Command#s.
+ Different staffs can produce different outputs; a melodious voice
+ which is put into a percussion-Staff, will be typeset as the rythm of
+ that voice.
+
+ After #Staff# made up her mind (Would #Staff# be a smart
+ name? How about #struct Susan {}# :-), the resultant items and
+ spanners are put on the PScore, and pointers to these items are
+ stored in the #Voice_element#. This construction enables the
+ beams/stems to look up the balls it has to connect to. */
+
+
+/// a request with a duration
+struct Rhythmic_req : Request {
+ int balltype;
+ int dots;
+
+ /****************/
+
+ Real duration() const;
+ Rhythmic_req();
+ Rhythmic_req*rhythmic() { return this;}
+ void print ()const;
+ Request*clone() const;
+};
+
+/// Put a note of specified type, height, and with accidental on the staff.
+struct Note_req : Rhythmic_req {
+ char name;
+ int octave;
+ int accidental;
+ bool forceacc;
+
+ /****************/
+
+ // return height from central c (in halflines)
+ int height()const;
+ Note_req();
+ Note_req*note() { return this;}
+ virtual void print() const;
+ Request*clone() const;
+};
+/**
+Staff has to decide if the ball should be hanging left or right. This
+influences the horizontal dimensions of a column, and this is why
+request processing should be done before horizontal spacing.
+
+Other voices' frivolities may cause the need for accidentals, so this
+is also for the Staff to decide. The Staff can decide on positioning
+based on ottava commands and the appropriate clef.
+*/
+
+
+///Put a rest on the staff.
+struct Rest_req : Rhythmic_req {
+
+ void print()const;
+
+ Rest_req * rest() { return this;}
+ Request*clone() const ;
+};
+/**
+Why a request? It might be a good idea to not typeset the rest, if the paper is too crowded.
+*/
+
+/// attach a stem to the noteball
+struct Stem_req : Request {
+ /// 4,8,16, ..
+ int stem_number;
+
+ virtual Stem_req *stem() {return this;}
+ Stem_req(int s) { stem_number = s; }
+ Request*clone() const;
+};
+
+/// requests to start or stop something.
+struct Span_req : Request {
+ /// should the spanner start or stop, or is it unwanted?
+ enum {
+ NOSPAN, START, STOP
+ } spantype ;
+
+ Span_req*span() { return this; }
+ Span_req();
+ virtual Request*clone()const;
+};
+/**
+ This type of request typically results in the creation of a #Spanner#
+*/
+
+
+///Start / stop a beam at this note.
+struct Beam_req : Span_req {
+ int nplet;
+
+ /****************/
+
+ Beam_req();
+ virtual Beam_req * beam() { return this; }
+ virtual Request*clone()const;
+};
+/** Staff will have to combine this with the stem_request, since the
+ number of flags that a stem wants to carry will determine the
+ number of beams. if #nplet# is set, the staff will try to put an
+ appropriate number over the beam
+
+ */
+
+/// a slur
+struct Slur_req : Span_req {
+ virtual Request*clone()const;
+};
+
+
+#if 0
+
+///Put a lyric above or below (?) this staff.
+struct Lyric_req : Request {
+ String text;
+};
+
+
+///Put a script above or below this ``note''
+struct Script_req : Request {
+ int orientation;
+ Symbol sym;
+};
+/**
+eg upbow, downbow. Why a request? These symbols may conflict with slurs and brackets, so this
+also a request
+*/
+
+
+
+
+///Draw a (Guitar) chord above or below this ``note''
+struct Chord : Request {
+ // don't know how this looks.
+};
+/**
+Why a request?
+Because everything else is done in requests.
+*/
+
+
+/// for absolute dynamics
+enum Loudness {
+ FFF, FF, F, MF, MP, P, PP, PPP
+} ;
+
+
+///Start / stop a slur or a bracket.
+struct Bracket_req : Span_req {
+ int nplet;
+};
+/**
+Start/stop a bracket at this note. if #nplet# is set, the staff will
+try to put an appropriate number over the bracket
+*/
+
+/// helper in the hierarchy
+struct Dynamic {
+ Real subtime;
+};
+/** Each dynamic is bound to one note ( a crescendo spanning multiple
+ notes is thought to be made of two "dynamics": a start and a stop).
+ Dynamic changes can occur in a smaller time than the length of its
+ note, therefore fore each Dynamic request carries a time, measured
+ from the start of its note.
+
+ This subfield would come in handy, if mpp96 was adapted for midi
+ support.
+
+ Dynamic should have been derived from request, but I don't want to
+ fuss with virtual baseclasses. */
+
+/// do a crescendo
+struct Cresc_req : Span_req, Dynamic {
+
+};
+
+/// do a decrescendo
+struct Decresc_req : Span_req, Dynamic {
+
+};
+
+/// do a dynamic like "fff" or "mp"
+struct Absdynamic_req : Request, Dynamic {
+ Loudness loudness;
+};
+#endif
+#endif
--- /dev/null
+/*
+ rest.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef REST_HH
+#define REST_HH
+#include "item.hh"
+
+/// ball at the end of the stem
+struct Rest : public Item
+{
+ int dots;
+ int balltype;
+
+ /****************/
+
+ void preprocess();
+ Rest(int dur,int dots);
+ void print()const;
+private:
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ * help lines
+ * proper placing of dots
+
+ */
+#endif
+
--- /dev/null
+/*
+ rhythmstaf.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef RHYTHMSTAF_HH
+#define RHYTHMSTAF_HH
+
+#include "simplestaff.hh"
+
+/// all notes on one line
+struct Rhythmic_staff : public Simple_staff
+{
+
+ /****************/
+
+ virtual Item *get_TYPESET_item(Command*);
+ virtual Stem *get_stem(Stem_req *rq);
+ virtual Notehead * get_notehead(Note_req *rq);
+ virtual void set_output(PScore *);
+ virtual Rhythmic_staff*clone()const;
+};
+
+#endif // RHYTHMSTAF_HH
+
+
--- /dev/null
+/*
+ sccol.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef SCCOL_HH
+#define SCCOL_HH
+#include "pcol.hh"
+
+
+struct Score_column {
+
+ /// indirection to column
+ PCol * pcol;
+ /// length of notes/rests in this column
+ svec<Real> durations;
+
+ Real when;
+
+ ///
+ bool musical;
+
+ /****************/
+
+ Score_column(Real when);
+ static int compare(Score_column & c1, Score_column &c2) {
+ return sgn(c1.when - c2.when);
+ }
+ void set_breakable() {
+ pcol->set_breakable();
+ }
+ bool used();
+ void print() const;
+};
+/**
+
+ When typesetting hasn't started on PScore yet, the columns which
+ contain data have a rhythmical position. Score_column is the type
+ with a rhythmical time attached to it. The calculation of
+ idealspacing is done with data in these columns. (notably: the
+ #durations# field)
+
+ */
+
+instantiate_compare(Score_column&, Score_column::compare);
+
+#endif // SCCOL_HH
+
--- /dev/null
+/*
+ lilypond, (c) 1996 Han-Wen Nienhuys
+*/
+#ifndef SCOMMANDS_HH
+#define SCOMMANDS_HH
+
+#include "proto.hh"
+#include "command.hh"
+#include "vray.hh"
+#include "plist.hh"
+
+/// the list of commands in Score
+struct Score_commands : public PointerList<Command*> {
+ void process_add(Command);
+ Score_commands*parse(Real last)const;
+ void parser_add(Command*);
+ void add_seq(svec<Command>);
+ void clean(Real last);
+ void set_breakable(Real when);
+ bool is_breakable(Real w);
+ PCursor<Command*> last_insertion(Real w);
+ PCursor<Command*> first(Real w);
+ void add_command_to_break(Command pre, Command mid,Command post);
+ void OK() const;
+ void print() const;
+ Real last() const;
+ void insert_between(Command victim, PCursor<Command*> firstc,
+ PCursor<Command*> last);
+};
+/** the list of commands in Score. Put in a separate class, since it
+ otherwise clutters the methods of Score.
+
+ This class serves two purposes: it stores the commands (via
+ parser_add()) in the yacc parser. at a later stage, some 'high
+ level' commands are converted (method: parse())
+ */
+
+#endif
+
--- /dev/null
+#ifndef SCORE_HH
+#define SCORE_HH
+#include "vray.hh"
+#include "proto.hh"
+#include "plist.hh"
+
+
+/// the total music def of one movement
+struct Score {
+ /// paper_, staffs_ and commands_ form the problem definition.
+ Paperdef *paper_;
+ PointerList<Staff *> staffs_;
+ Score_commands *commands_;
+
+ /// "runtime" fields for setting up spacing
+ PointerList<Score_column*> cols_;
+ PScore *pscore_;
+
+ /****************************************************************/
+
+ /// construction
+ void add_staff(Staff *st);
+ void set(Paperdef*);
+ Score();
+ ~Score();
+ void add(Staff*);
+ void set(Score_commands*);
+
+
+ void OK() const;
+ Score_column *find_col(Real,bool);
+ void process();
+ void output(String fn);
+ PCursor<Score_column*> create_cols(Real);
+ void print() const;
+ Real last() const;
+
+private:
+ void do_pcols();
+ void clean_cols();
+ void distribute_commands();
+ void do_connect(PCol *c1, PCol *c2, Real d);
+ void connect_nonmus(PCol* c1, PCol *c2, Real d);
+ /// add #Idealspacings# to #pscore_#
+ void calc_idealspacing();
+ /** add the score wide commands (bars, breaks) to each staff so
+ they can process (typeset) them if needed */
+};
+/**
+
+ */
+#endif
--- /dev/null
+/*
+ scoreline.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef SCORELINE_HH
+#define SCORELINE_HH
+#include "plist.hh"
+#include "proto.hh"
+#include "vray.hh"
+
+/// the columns of a score that form one line.
+struct
+Line_of_score {
+ List<const PCol *> cols;
+
+ // need to store height of each staff.
+ PointerList<Line_of_staff*> staffs;
+ const PScore * score; // needed to generate staffs
+
+ /****************/
+
+ Line_of_score(svec<const PCol *> sv, const PScore *);
+
+ String TeXstring() const;
+
+ // is #c# contained in #*this#?
+ bool element(const PCol *c);
+};
+
+#endif
--- /dev/null
+/*
+ simplestaff.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef SIMPLESTAFF_HH
+#define SIMPLESTAFF_HH
+
+#include "stcol.hh"
+#include "staff.hh"
+#include "swalker.hh"
+/*
+ mega-stupido staffs and cols: they do notes one at each moment.
+ */
+
+struct Simple_staff;
+
+/// column of Simple_staff: store one request
+struct Simple_column : Staff_column {
+
+ svec<Rhythmic_req *> notes;
+ Stem_req *stem_;
+ Beam_req *beam_;
+ Simple_staff* staff_;
+
+ /****************/
+
+ virtual void typeset_item(Item *, int=1);
+
+ Molecule *create_command_mol(Command *com);
+
+ void take_request(Request *rq);
+ virtual void process_requests();
+
+ Simple_column(Score_column*s,Simple_staff*rs);
+};
+
+
+/// Simple staff: one voicegroup at a time
+struct Simple_staff : Staff {
+ /// indirection to the PStaff.
+ PStaff *theline;
+
+ /****************/
+ Staff_column*create_col(Score_column*);
+
+ virtual Item *get_TYPESET_item(Command*);
+ virtual Stem *get_stem(Stem_req *rq)=0;
+ virtual Notehead *get_notehead(Note_req *rq)=0;
+ virtual Rest *get_rest(Rest_req *rq);
+ virtual void set_output(PScore *);
+
+ void process_commands( PCursor<Command*> &where);
+ virtual void walk();
+
+ Simple_staff();
+};
+
+struct Simple_walker: Staff_walker {
+ Stem *stem_;
+ svec<Notehead *>noteheads;
+ Beam *beam_;
+
+ /****************/
+
+ virtual void process_command(Command*);
+ virtual void process_requests();
+ Simple_walker(Simple_staff*);
+ Simple_column *col();
+ Simple_staff *staff();
+};
+
+
+#endif // SIMPLESTAFF_HH
+
+
+
+
--- /dev/null
+/*
+ spanner.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef SPANNER_HH
+#define SPANNER_HH
+#include "proto.hh"
+
+/// a symbol which is attached between two columns.
+struct Spanner {
+ PCol *left, *right;
+ PStaff * pstaff_;
+ Molecule *output ;
+
+ /****************/
+
+ String TeXstring () const ;
+ Spanner();
+ Paperdef*paper() const;
+
+ virtual Interval height()const=0;
+ /**
+ PRE:
+ processed
+ */
+ virtual Interval width()const;
+ virtual void process();
+ virtual void preprocess();
+
+
+ /// clone a piece of this spanner.
+ virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const=0;
+ /**
+
+ PRE
+ c1 >= start, c2 <= stop
+ */
+ virtual void print() const;
+};
+/** Spanner should know about the items which it should consider:
+ e.g. slurs should be steep enough to "enclose" all those items. This
+ is absolutely necessary for beams, since they have to adjust the
+ length of stems of notes they encompass.
+
+ */
+#endif
--- /dev/null
+#ifndef STAFF_HH
+#define STAFF_HH
+
+#include "score.hh"
+#include "voice.hh"
+#include "command.hh"
+
+
+/// base class for a collection of voices.
+struct Staff {
+ /// synchronous horizontal stuff
+ PointerList<Voice*> voices;
+
+ /// commands in chronological order
+ PointerList<Command *> commands;
+
+ /// runtime field
+ PointerList<Staff_column*> cols;
+
+ /// indirections to the Score and PScore
+ Score *score_;
+ PScore *pscore_;
+
+ /****************************************************************/
+ Staff(const Staff&src);
+ void add_voice(Voice *v);
+ void add_staff_column(Staff_column *sp);
+
+ Paperdef*paper()const;
+ /// interpret all requests and add items to #destination#.
+ void process();
+ /**
+ This routines calls virtual functions from Staff, to delegate the
+ interpretation of requests to a derived class of Staff */
+ void setup_staffcols();
+
+ void OK() const;
+ void print() const;
+ Real last() const;
+ void clean_cols() ;
+ Staff_column * get_col(Real,bool);
+
+ void add_commands(PointerList<Command* >const & sv);
+ /**
+ add all commands from sv.
+
+ PRE
+ sv is time-ordered.
+ */
+
+ Staff();
+ /**
+ Should construct with Score as arg, but this isn't known during parsing.
+ */
+ /****************************************************************
+ VIRTUALS
+ ****************************************************************/
+ virtual Staff*clone()const=0;
+ virtual void set_output(PScore * destination)=0;
+ virtual void walk()=0;
+ virtual Staff_column * create_col(Score_column * )=0;
+ virtual ~Staff() { }
+};
+#endif
+
+
--- /dev/null
+/*
+ staffline.hh -- horizontal structures for broken scores.
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef STAFFLINE_HH
+#define STAFFLINE_HH
+
+#include "real.hh"
+#include "plist.hh"
+#include "vray.hh"
+#include "glob.hh"
+#include "pstaff.hh"
+
+/// one broken line of staff.
+struct Line_of_staff {
+ PointerList<Spanner *> brokenspans;
+ Line_of_score const * scor;
+ const PStaff *pstaff_;
+
+ /****************/
+
+ String TeXstring() const;
+ Line_of_staff(Line_of_score*, PStaff *);
+ Interval height() const;
+};
+
+#endif
--- /dev/null
+/*
+ stcol.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef STCOL_HH
+#define STCOL_HH
+#include "proto.hh"
+#include "vray.hh"
+
+/// store simultaneous requests
+struct Staff_column {
+ /// indirection
+ Score_column *score_column;
+
+ /// fields to collect data vertically.
+ svec<Voice_element *> v_elts;
+
+ /// idem
+ svec<Command *> s_commands;
+
+ /****************/
+
+ Staff_column(Score_column*s);
+ bool mus() const;
+ Real when() const;
+ void add(Voice_element*ve);
+ /****************************************************************
+ VIRTUAL
+ ****************************************************************/
+
+ virtual void process_requests()=0;
+
+ virtual ~Staff_column() { }
+};
+
+
+#endif // STCOL_HH
+
--- /dev/null
+/*
+ stem.hh --
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef STEM_HH
+#define STEM_HH
+#include "item.hh"
+
+/// the rule attached to the ball
+struct Stem : public Item {
+ // heads the stem encompasses (positions)
+ int minnote, maxnote;
+
+ /// false if in beam
+ bool print_flag;
+
+ /// needed for determining direction/length
+ int staff_center;
+
+ // extent of the stem (positions)
+ Real bot, top;
+ /**
+ fractional, since Beam has to adapt them.
+ */
+
+ Real stemlen;
+ // flagtype? 4 none, 8 8th flag, 0 = beam.
+ int flag;
+
+ ///geen gedonder, jij gaat onder
+ int dir;
+ /**
+ -1 stem points down, +1: stem points up
+ */
+
+ Real stem_xoffset;
+ /****************/
+
+ /// ensure that this Stem also encompasses the Notehead #n#
+ void add(Notehead*n);
+ Real hpos()const;
+ void set_stemend(Real);
+ void set_default_dir();
+ void set_default_stemlen();
+ void set_default_extents();
+ void postprocess();
+ Stem(int center);
+ void print() const;
+ Interval width() const;
+private:
+
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ \begin{itemize}
+ \item the rule
+ \item the flag
+ \item up/down position.
+ \end{itemize}
+ */
+
+#endif
--- /dev/null
+
+/*
+ swalker.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef SWALKER_HH
+#define SWALKER_HH
+
+#include "staff.hh"
+
+struct Staff_walker : public PCursor<Staff_column*> {
+ Staff * staff_;
+ PScore * pscore_;
+
+ int break_status;
+
+ /****************/
+ int priority() const; // Command
+ Real when() const;
+ virtual ~Staff_walker();
+ Staff_walker(Staff*, PScore*);
+ void process() ;
+ virtual void process_command(Command *)=0;
+ virtual void process_requests()=0;
+};
+/**
+ manage run-time info when walking staffcolumns such as: key,
+ meter, pending beams & slurs
+ */
+
+#endif // SWALKER_HH
+
--- /dev/null
+#ifndef SYMBOL_HH
+#define SYMBOL_HH
+#include "string.hh"
+#include "boxes.hh"
+#include "proto.hh"
+
+struct Symbol {
+ String tex;
+ Box dim;
+
+ Symbol (String, Box);
+ Symbol();
+};
+
+struct Parametric_symbol {
+ Symtables*symtables_; // indirection
+
+ /*****************/
+
+ Parametric_symbol(Symtables*s) { symtables_ = s; }
+ Symbol eval(String args1) const; // convenience
+ Symbol eval(String args1,String arg2) const; // convenience
+ virtual Symbol eval(svec<String> args)const =0;
+ virtual ~Parametric_symbol(){}
+};
+
+#endif
--- /dev/null
+/*
+ lilypond, (c) 1996 Han-Wen Nienhuys
+*/
+#ifndef SYMTABLE_HH
+#define SYMTABLE_HH
+#include "assoc.hh"
+#include "string.hh"
+#include "symbol.hh"
+
+struct Symtable : public Assoc<String, Symbol> {
+ Symbol lookup(String)const;
+};
+
+
+struct Symtables : private Assoc<String, Symtable*> {
+ void read(Text_db&) ;
+ Symtable* operator()(String s);
+
+};
+
+
+#endif
+
--- /dev/null
+#ifndef TEX_HH
+#define TEX_HH
+
+#include "string.hh"
+#include "boxes.hh"
+
+/// parameter substitution in TeXstrings
+String
+substitute_args(String source, svec<String> args);
+/**
+ this structure provides a simple macro mechanism:
+
+ if source == "tex%bla%", then
+ eval({"X","Y"}) == "texXblaY"
+ */
+
+/// #h# is in points
+String vstrut(Real h);
+
+
+#endif
--- /dev/null
+#ifndef TSTREAM__HH
+#define TSTREAM__HH
+
+#include <iostream.h>
+#include "string.hh"
+
+/// TeX output
+struct Tex_stream {
+ bool outputting_comment;
+ ostream *os;
+ int nest_level;
+
+ /// open a file for writing
+ Tex_stream(String filename);
+ void header();
+ /// delegate conversion to string class.
+ Tex_stream &operator<<(String);
+
+ /// close the file
+ ~Tex_stream();
+};
+/**
+ Use this class for writing to a TeX file.
+ It counts braces to prevent nesting errors, and
+ it will add a comment sign before each newline.
+ */
+#endif
--- /dev/null
+#ifndef VOICE_HH
+#define VOICE_HH
+
+
+#include "plist.hh"
+#include "request.hh"
+
+/// class for horizontal stuff.
+struct Voice {
+ PointerList<Voice_element *> elts;
+ Real start;
+
+ /****************/
+ Real when(const Voice_element*)const;
+ Real last() const;
+ Voice();
+ Voice(Voice const&);
+ void add(Voice_element*);
+ void print() const;
+};
+/**
+
+ Voice is a ordered row of Voice_elements. It is strictly horizontal:
+ you cannot have two rhythmic elements running parallel in a Voice
+
+ */
+
+struct Voicegroup {
+ /// don't know how to identify these.
+};
+
+/// one horizontal bit.
+struct Voice_element {
+ Real duration;
+ const Voicegroup *group;
+ const Voice *voice;
+ PointerList<Request*> reqs;
+
+ List<const Item *> granted_items;
+ List<const Spanner *> granted_spanners;
+
+ /****************/
+
+ void add(Request*);
+ Voice_element();
+ Voice_element(Voice_element const & src );
+ void print ()const;
+};
+/** Apart from being a container for the requests, Voice_element is
+ glue between related items and spanners, between requests and
+ (voice)groups
+ */
+#endif
+++ /dev/null
-#include <assert.h>
-#include "identifier.hh"
-#include "staff.hh"
-#include "lexer.hh"
-#include "parser.hh"
-
-Identifier::Identifier(String n)
- :name (n)
-{
- data = 0;
-}
-
-
-Identifier::~Identifier()
-{
-}
-
-Staff_id::~Staff_id()
-{
- delete staff();
-}
-
-Voice_id::~Voice_id()
-{
- delete voice();
-}
+++ /dev/null
-
-/*
- identifier.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef IDENTIFIER_HH
-#define IDENTIFIER_HH
-#include "proto.hh"
-#include "string.hh"
-
-struct Identifier
-{
- void *data;
- String name;
-
- Identifier(String n) ;
- virtual ~Identifier();
- virtual Staff * staff() { assert(false); }
- virtual Voice * voice() { assert(false); }
-};
-
-struct Staff_id : Identifier {
- Staff_id(String s, Staff*st):Identifier(s) { data = st; }
- virtual Staff* staff() { return (Staff*) data; }
- ~Staff_id();
-};
-
-struct Voice_id : Identifier {
- Voice_id(String s, Voice*st):Identifier(s) { data = st; }
- virtual Voice * voice() { return (Voice*)data; }
- ~Voice_id();
-};
-#endif // IDENTIFIER_HH
-
+++ /dev/null
-#include "line.hh"
-#include "symbol.hh"
-#include "molecule.hh"
-#include "pcol.hh"
-
-void
-Item::postprocess()
-{
- // default: do nothing
-}
-
-
-void
-Item::preprocess()
-{
- // default: do nothing
-}
-
-String
-Item::TeXstring() const
-{
- return output->TeXstring();
-}
-
-Interval
-Item::width() const
-{
- return output->extent().x;
-}
-
-Interval
-Item::height() const
-{
- return output->extent().y;
-}
-
-Item::~Item()
-{
- delete output;
-}
-
-Item::Item()
-{
- col = 0;
- output = 0;
- pstaff_ = 0;
-}
-void
-Item::print() const
-{
- output->print();
-}
+++ /dev/null
-#ifndef ITEM_HH
-#define ITEM_HH
-
-#include "glob.hh"
-#include "boxes.hh"
-#include "string.hh"
-
-/// a horizontally fixed size element of the score
-struct Item {
- const PCol * col;
- Molecule *output;
-
- PStaff *pstaff_;
- /** needed for knowing at which staff to output this item
- */
-
- /****************/
-
- /// do calculations after determining horizontal spacing
- virtual void postprocess();
-
- /// do calculations before determining horizontal spacing
- virtual void preprocess();
- /**
- This is executed directly after the item is added to the
- PScore
- */
-
- virtual Interval width() const;
- virtual Interval height() const;
- String TeXstring () const ;
- Item();
- void print()const;
- virtual ~Item();
-};
-/** Item is the datastructure for printables whose width is known
- before the spacing is calculated
-
- NB. This doesn't mean an Item has to initialize the output field before
- spacing calculation.
-
-*/
-
-
-#endif
+++ /dev/null
-/*
- keyword.cc -- keywords and identifiers
- */
-
-#include <stdlib.h>
-
-#include "glob.hh"
-#include "lexer.hh"
-//#include "mudobs.hh"
-//#include "gram.hh"
-
-/* for the keyword table */
-struct Keyword_ent
-{
- const char *name;
- int tokcode;
-};
-
-struct Keyword_table
-{
- Keyword_ent *table;
- int maxkey;
- Keyword_table(Keyword_ent *);
- int lookup(const char *s) const;
-};
-
-
-/* for qsort */
-int
- tabcmp(const void * p1, const void * p2)
-{
- return strcmp(((const Keyword_ent *) p1)->name,
- ((const Keyword_ent *) p2)->name);
-}
-
-Keyword_table::Keyword_table(Keyword_ent *tab)
-{
- table = tab;
-
- /* count keywords */
- for (maxkey = 0; table[maxkey].name; maxkey++);
-
- /* sort them */
- qsort(table, maxkey, sizeof(Keyword_ent), tabcmp);
-}
-
-/*
- lookup with binsearch, return tokencode.
-*/
-int
-Keyword_table::lookup(const char *s)const
-{
- int lo,
- hi,
- cmp,
- result;
- lo = 0;
- hi = maxkey;
-
- /* binary search */
- do
- {
- cmp = (lo + hi) / 2;
-
- result = strcmp(s, table[cmp].name);
-
- if (result < 0)
- hi = cmp;
- else
- lo = cmp;
- }
- while (hi - lo > 1);
- if (!strcmp(s, table[lo].name))
- {
- return table[lo].tokcode;
- } else
- return -1; /* not found */
-}
-
+++ /dev/null
-/* 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;
-};
--- /dev/null
+% "Ah, je vous dirai, maman" (Mozart)
+%
+% bare bones version. (written down from memory :-)
+
+melodie = voice {
+ $ \octave c
+ %%% theme
+ c c g g a a g2 f f e e d d c2
+ %%% var 1
+ c r8 c8 ( ) g r8 g8 ( ) a r8 a8 ( ) g r4
+ f r8 f8 ( ) e4 r8 e8 ( ) d4 r8 d8 ( ) c4 r4
+ $
+}
+
+begeleiding = voice {
+ $ \octave ``c
+ %%% theme
+ `c c e c f c e c d `b c `a `f `g `c2
+ %%%% var 1
+ r8 e8() c r8 e8() c r8 f8()c r8 e8()c
+ r8 d8()`b r8 c8()`a r8 `a8()`f r8 `e8()`c
+ $
+}
+
+
+score {
+ melodicstaff {
+ voice { melodie }
+ }
+ melodicstaff {
+ voice { begeleiding }
+ }
+ paper {
+ unitspace 2.5cm
+ }
+ commands {
+ meter 2 4
+ skip 16:0
+ }
+}
\ No newline at end of file
+++ /dev/null
-#ifndef LEXER_HH
-#define LEXER_HH
-
-#include "proto.hh"
-
-void new_input(String s);
-bool close_input();
-int yylex();
-void yyerror(char *s);
-
-int lookup_keyword(String s);
-
-Identifier* lookup_identifier(String s);
-void add_identifier(Identifier*i);
-void delete_identifiers();
-#endif
+++ /dev/null
-%{ // -*-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
-
-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>{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>[:space:]+ {
-}
-<notes>[ \t\n]+ {
-}
-<notes>%.* {
-
-}
-<notes>\$ {
- BEGIN(INITIAL); return '$';
-}
-<notes>. {
- error("lexer error: illegal character found: " + String(YYText()));
-}
-
-\" {
- 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(char *s)
-{
- *mlog << "error in line " << lexer->lineno() << ": " << s << '\n';
- exit(1);
-}
-
-
-#if 0
-
-<notes>{NOTENAME} {
- yylval.string = new String (YYText());
- return NOTENAME;
-}
-
-#endif
\mdef\doubledot{'01}
\mdef\tripledot{'02}
\mdef\mussepline{155}
-\mdef\ieigthflag{45}
-\mdef\isixteenthflag{46}
-\mdef\ithirtysecondflag{47}
+
+
+\mdef\deigthflag{45}
+\mdef\dsixteenthflag{46}
+\mdef\dthirtysecondflag{47}
+
+% pointing up
\mdef\ueigthflag{40}
\mdef\usixteenthflag{41}
\mdef\uthirtysecondflag{42}
\def\generalmeter#1#2{\vbox to 0pt{\vss\rm\hbox{#1}\hbox{#2}}}
\def\lineseparator{\vbox{\mussepline\vskip -5pt\mussepline}}
-\def\beauty{
- \par\vskip 10pt\par
- \hskip -5pt\lineseparator% \hbox to 1cm{\kern -5mm\hrulefill}
- \vskip 10pt
+\def\beauty{%
+ \par\vskip 10pt plus 30pt minus 10pt\par
+ \hskip -5pt\lineseparator
+ \par\vskip 10pt plus 30pt minus 10pt\par
}
\def\interstaffline{%
}
+\def\beamslope#1#2{{\count0=#2\advance\count0 by#1\musicfnt\char\count0}}
+\def\rulesym#1#2{\vrule height #1 width #2}
\ No newline at end of file
+++ /dev/null
-#include "line.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;
-
- 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(brokenstop, brokenstart));
- }
-}
-
-
-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_)
- assert(false);
- }
- }
- return y;
-}
-
-
-/****************************************************************/
-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;
-}
-
-/// testing this entry
-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!!
- */
-
+++ /dev/null
-#ifndef LINE_HH
-#define LINE_HH
-
-/*
- horizontal structures for broken scores.
-*/
-
-#include "real.hh"
-#include "plist.hh"
-#include "vray.hh"
-#include "glob.hh"
-#include "pstaff.hh"
-
-
-
-/// the columns of a score that form one line.
-struct
-Line_of_score {
- List<const PCol *> cols;
-
- // need to store height of each staff.
- PointerList<Line_of_staff*> staffs;
- const PScore * score; // needed to generate staffs
-
- /****************/
-
- Line_of_score(svec<const PCol *> sv, const PScore *);
-
- String TeXstring() const;
-
- // is #c# contained in #*this#?
- bool element(const PCol *c);
-};
-
-/// one broken line of staff.
-struct Line_of_staff {
- PointerList<Spanner *> brokenspans;
- Line_of_score const * scor;
- const PStaff *pstaff_;
-
- /****************/
-
- String TeXstring() const;
- Line_of_staff(Line_of_score*, PStaff *);
- Interval height() const;
-};
-
-#endif
+++ /dev/null
-#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].col == 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].col == w)
- return i;
- assert(false);
-}
-
-void
-Spacing_problem::OK() const
-{
-#ifndef NDEBUG
- Union_find connected(cols.sz());
-
- 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++) {
- assert( connected.equiv(0,i));
- }
-#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.col=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(col);
- mtor << "[" << minleft() << ", " << minright() << "]";
- mtor <<"}\n";
-#endif
-}
-
-Colinfo::Colinfo()
-{
- fixed=false;
- col=0;
-}
+++ /dev/null
-#ifndef PROBLEM_HH
-#define PROBLEM_HH
-
-#include "glob.hh"
-#include "plist.hh"
-#include "vray.hh"
-#include "pcol.hh"
-#include "matrix.hh"
-
-/// helper struct for #Spacing_problem#
-struct Colinfo {
- const PCol *col;
- bool fixed;
- Real fixpos;
- Colinfo();
- void print() const;
- Real minright()const { return col->width().max; }
- Real minleft()const { return -col->width().min; }
-};
-
-
-/// spacing for one line.
-class Spacing_problem {
- svec<const Idealspacing*> ideals;
- svec<Colinfo> cols;
-
- /// the index of #c# in #cols#
- int col_id(const PCol *c) const;
-
- /// generate an (nonoptimal) solution
- Vector find_initial_solution() const;
-
- /// check if problem is too tight
- bool check_feasible() const;
- /// does #this# contain the column #w#?
- bool contains(const PCol *w);
-
- /// make the energy function
- void make_matrices(Matrix &quad, Vector &lin,Real&) const;
-
- /// generate the LP constraints
- void make_constraints(Mixed_qp& lp) const;
-
-public:
- /// solve the spacing problem
- svec<Real> solve() const;
- /**
- return the column positions, and the energy (last element)
- */
- /// add a idealspacing to the problem.
- void add_ideal(const Idealspacing *i);
-
- /**
- One pair of columns can have no, one or more idealspacings,
- since they can be "summed" if the columns to which #i# refers are
- not in this problem, the spacing is ignored.
- */
-
-
- /// add a col to the problem
- void add_column(const PCol *, bool fixed=false, Real fixpos=0.0);
- /** columns have to be added left to right. The column contains
- info on it's minimum width.
- */
-
-
- bool check_constraints(Vector v) const;
-
- Vector try_initial_solution() const;
- void OK() const;
- void print() const;
- void print_ideal(const Idealspacing*)const;
-};
-
-
-/** the problem, given by the columns (which include constraints) and
- intercolumn spacing. The problem is:
-
- Generate a spacing which
- \begin{itemize}
- \item
- Satisfies spacing constraints (notes can't be printed through each other)
- \item
- Looks good, ie tries to conform to an ideal spacing as much as possible.
- \end{itemize}
- This is converted by regarding idealspacing as "springs" attached
- to columns. The equilibrium of one spring is the ideal
- distance. The columns have a size, this imposes "hard" constraints
- on the distances. This transforms the problem into a quadratic
- programming problem with linear constraints.
-
- The quality is given by the total potential energy in the
- springs. The lower the energy, the better the configuration.
-*/
-#endif
+++ /dev/null
-#include "linestaff.hh"
-#include "symbol.hh"
-#include "lookupsyms.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);
-}
+++ /dev/null
-#include "pstaff.hh"
-
-struct Linestaff : PStaff {
-
- int nolines;
-
-/****************/
-
- Symbol get_stafsym(Real width)const;
- Linestaff(int, PScore*);
-};
+++ /dev/null
-#include "lookupsyms.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_);
-}
+++ /dev/null
-/*
- lilypond, (c) 1996 Han-Wen Nienhuys
-*/
-#ifndef LOOKUPSYMS_HH
-#define LOOKUPSYMS_HH
-
-#include "symbol.hh"
-
-struct Lookup {
- Symtables *symtables_;
-
- /****************/
-
- void parse (Text_db&t);
- Parametric_symbol *linestaff(int n);
- Parametric_symbol *meter(String);
- Parametric_symbol *stem();
- Symbol streepjes(int pos);
- /**
- pos == 3 : 3 lines above staff (extending below note)
-
- pos == -3: below staff
- */
-
- Symbol ball(int);
- Symbol flag(int);
- Symbol rest(int);
- Symbol bar(String);
- Symbol dots(int);
- Lookup();
- ~Lookup();
-};
-
-#endif
voice { $ c2 r32 r32 r16 r8 r4 c2 c2 c2 c2 c2
c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 $ }
}
+
melody=
melodicstaff {
- voice { $ ''c2.. r8 r4 r8 r16 r32 r32 d8 e8 f8 g8 ''fis1 a8 b8 'c8 c8 ''c8 ```c8 c4 c4 c4 c4 $ }
+ voice { $
+ ''c2.. r8 r4 r8 r16 r32 r32
+ [d8 e8 f8 g8] [d8 e8 f8 g8]
+ ''fis1
+ a8 b8 'c8 'd8 ''c8 ```c8 c4 c4 c4 c4
+ \duration 16 `b16 `a16 `g16 `f16 \duration 4
+ c `b `a `g `f `e `d `c ``b ``a ``g ``f ``e ``d ``c$
+ }
}
score {
paper {
- unitspace 3 cm
+ geometric 1.4
+ unitspace 3.0 cm
}
staff { ritme }
staff { melody }
% staff { melody }
commands {
meter 4 4
- skip 3:0
+ skip 2:0
meter 2 4
skip 19:0
}
+++ /dev/null
-#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,0,0
-};
-
-
-void notice()
-{
- cout <<
- "LilyPond, a music typesetter.\n"
- "Copyright (C) 1996 by\n"
- " Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>\n"
- "\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;
- default:
- assert(false);
- break;
- }
- }
- char *arg = oparser.get_next_arg();
-
- if (!arg) arg = "";
- parse_file(arg);
-
- do_scores();
- exit (0);
-}
+++ /dev/null
-#ifndef MAIN_HH
-#define MAIN_HH
-#include "proto.hh"
-
-void debug_init();
-void do_scores();
-void add_score(Score * s);
-void set_default_output(String s);
-const char *get_version();
-
-#endif
new=$2
nm=$3-
-newarc=$nm$new.tar.gz
-oldarc=$nm$old.tar.gz
+newarc=../releases/$nm$new.tar.gz
+oldarc=../releases/$nm$old.tar.gz
if [ ! -x $nm$new ]
then
echo untarring ..
- tar zfxv $nm$new.tar.gz
if [ ! -f $newarc ]
then
echo cant find $newarc
exit
fi
+ tar zfxv $newarc
fi
if [ ! -x $nm$old ]
then
echo untarring
- tar zfxv $nm$old.tar.gz
+
if [ ! -f $oldarc ]
then
echo cant find oldarc
exit
fi
+ tar zfxv $oldarc
fi
#(cd $nm$old; touch depend; make clean)
+++ /dev/null
-#include "melodicstaff.hh"
-#include "stem.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);
-}
-
-void
-Melodic_column::typeset_command(Command *com, int breakst)
-{
- Molecule*m=create_command_mol(com);
- Item *i =new Item;
- i->output = m;
- typeset_item(i, breakst);
-}
-
-void
-Melodic_column::typeset_req(Request *rq)
-{
- Item *i ;
- if (rq->note()) {
- Notehead *n =new Notehead((NO_LINES-1)*2);
- n->balltype = rq->rhythmic()->balltype;
- n->dots = rq->rhythmic()->dots;
- n->position = rq->note()->height() - BOTTOM_POSITION;
- i = n;
- } else if (rq->rest()) {
- i =new Item;
- Molecule*m=create_req_mol(rq);
- i->output=m;
- }
- typeset_item(i);
-}
-
-
-void
-Melodic_column::typeset_stem(Stem_req*rq)
-{
- Stem * s = new Stem(NO_LINES);
- int n = the_note->note()->height()-BOTTOM_POSITION;
- s->minnote =s->maxnote=n;
- s->flag = rq->stem_number;
- typeset_item(s);
-}
-
-/*
- creation
- */
-Staff *
-get_new_melodicstaff()
-{
- return new Melodic_staff;
-}
-
-
-Staff_column*
-Melodic_staff::create_col(Score_column*s)
-{
- return new Melodic_column(s,this);
-}
-
-Melodic_staff*
-Melodic_staff::clone()const
-{
- return new Melodic_staff(*this);
-}
+++ /dev/null
-/*
- rhythmstaf.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef MELODICSTAFF_HH
-#define MELODICSTAFF_HH
-
-#include "simplestaff.hh"
-
-/// five line staff, no multiple voices
-struct Melodic_staff : public Simple_staff
-{
- Staff_column * create_col(Score_column*);
- virtual void set_output(PScore *);
- virtual Melodic_staff*clone()const;
-};
-
-struct Melodic_column : public Simple_column {
- virtual void typeset_req(Request *rq);
- virtual void typeset_stem(Stem_req *rq);
- virtual void typeset_command(Command *, int brs);
- // virtual void typeset_item(Item*, int=1);
- Melodic_column(Score_column*s,Simple_staff*rs) :
- Simple_column(s,rs) { }
-// virtual Melodic_column*clone()const;
-};
-
-#endif // MELODICSTAFF_HH
-
-
+++ /dev/null
-#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;
-}
-
+++ /dev/null
-#ifndef MISC_HH
-#define MISC_HH
-
-
-
-
-#endif
+++ /dev/null
-#include "glob.hh"
-#include "dimen.hh"
-#include "string.hh"
-#include "molecule.hh"
-#include "symbol.hh"
-#include "debug.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)
-{
- 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)
-{
- 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)
-{
- 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)
-{
- 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();
-}
+++ /dev/null
-#ifndef MOLECULE_HH
-#define MOLECULE_HH
-
-#include "plist.hh"
-#include "boxes.hh"
-#include "item.hh"
-#include "symbol.hh"
-/// a symbol which can be translated, and freely copied
-struct Atom {
- Offset off;
- Symbol sym;
-
- void translate(Offset o) {
- off += o;
- }
-
- /// how big is #this#?
- Box extent() const;
- Atom(Symbol s);
-
- void print() const;
-
- String TeXstring() const;
-};
-
-/// a group of #Atom#s
-struct Molecule {
- PointerList<Atom*> ats;
-
- Molecule() { }
- Molecule(Atom a) { add(a) ; }
-
- void add_right(const Molecule &m);
- void add_left(const Molecule &m);
- void add_top(const Molecule &m);
- void add_bot(const Molecule &m);
- void add(Molecule const &m);
- void translate(Offset);
- void add(Atom a) { ats.bottom().add(new Atom(a)); }
- /// how big is #this#?
- Box extent() const;
-
- String TeXstring() const;
-
- Molecule(const Molecule&s);
- void print() const;
-private:
- void operator=(const Molecule&);
-};
-/** a group of individually translated symbols. You can add molecules
- to the top, to the right, etc. */
-#endif
+++ /dev/null
-#include <ctype.h>
-#include "string.hh"
-#include "real.hh"
-#include "debug.hh"
-#include "request.hh"
-#include "voice.hh"
-#include "notename.hh"
-
-int default_duration = 4;
-
-void
-parse_duration(const char *a, int &j, int &intdur, int &dots)
-{
- String durstr;
- while (isdigit(a[j]))
- {
- durstr += a[j++];
- }
-
- dots=0;
-
- 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 =0;
-
- 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( v);
-
- if (dur >= 2) {
- Stem_req * st = new Stem_req(v, 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(v);
-
- rq->balltype = dur;
- rq->dots = dots;
- rq->print();
- v->add(rq);
- return v;
-}
+++ /dev/null
-#include "notehead.hh"
-#include "dimen.hh"
-#include "debug.hh"
-#include "pstaff.hh"
-#include "pscore.hh"
-#include "paper.hh"
-#include "lookupsyms.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 = pstaff_->pscore_->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));
-}
-
+++ /dev/null
-/*
- notehead.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef NOTEHEAD_HH
-#define NOTEHEAD_HH
-#include "item.hh"
-
-/// ball at the end of the stem
-struct Notehead : public Item
-{
- int position;
- int staff_size;
- int dots;
- int balltype;
-
- /****************/
- void preprocess();
-
- Notehead(int staff_size);
- /**
- position of top line (5 linestaff: 8)
- */
- void print()const;
-private:
- void brew_molecole();
-};
-/**
- takes care of:
-
- * help lines
- * proper placing of dots
-
- */
-#endif // NOTEHEAD_HH
-
+++ /dev/null
-#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);
-}
+++ /dev/null
-
-void lookup_notename(int &large, int &small, String s);
--- /dev/null
+dist:
+ ln Makefile $(DDIR)/objects/
\ No newline at end of file
+++ /dev/null
-#include <math.h>
-
-#include "paper.hh"
-#include "debug.hh"
-#include "lookupsyms.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));
-}
-
-Paperdef::Paperdef()
-{
- lookup_ = new Lookup();
- parse();
- linewidth = convert_dimen(15,"cm"); // in cm for now
- whole_width= 6*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
-}
+++ /dev/null
-#include "proto.hh"
-#include "real.hh"
-#include "string.hh"
-
-struct Paperdef {
- Lookup *lookup_;
- String outfile;
- Real linewidth;
- /// how much space does a whole note take (ideally?)
- Real whole_width;
-
- // ideal = geometric_ ^ log2(duration)
- Real geometric_;
-
- /****************/
- void parse();
- Paperdef();
- ~Paperdef();
- Real interline()const;
- Real standard_height()const;
- Real note_width() const;
- void print() const;
- Real duration_to_dist(Real);
-};
-
+++ /dev/null
-
-#include "proto.hh"
-
-Staff * get_new_rhythmstaff();
-Voice_element * get_note_element(String,String);
-Voice_element* get_rest_element(String,String);
-Command * get_bar_command(Real);
-Staff * get_new_melodicstaff();
-Command* get_meterchange_command( int,int);
-Command* get_meter_command( Real,int,int);
-Command* get_skip_command( int,Real);
-
+++ /dev/null
-%{ // -*-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
-
-%}
-
-
-%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;
- int i;
-}
-
-%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
-%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
-%token MELODICSTAFF GEOMETRIC START
-
-%type <consstr> unit
-%token <id> IDENTIFIER
-%token <string> NEWIDENTIFIER
-%token <string> PITCH DURATION RESTNAME
-%token <real> REAL
-%token <string> STRING
-%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
-
-%%
-
-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 REAL { $$->start = $3; }
- ;
-
-
-
-
-voice_elts_dollar:
- '$' voice_elts '$' { $$ = $2; }
- ;
-
-voice_elts:
- /* empty */ {
- $$ = new Voice;
- }
- | voice_elts voice_elt {
- $$->add($2);
- }
- ;
-
-voice_elt:
- PITCH DURATION { $$ = get_note_element(*$1, *$2);
-
- }
- | RESTNAME DURATION { $$ = get_rest_element(*$1, *$2);
-
- }
- ;
-
-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();
- *mlog << "\n";
-}
+++ /dev/null
-#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(const Item *i)
-{
- its.bottom().add(i);
- used = true;
-}
-
+++ /dev/null
-#ifndef COLS_HH
-#define COLS_HH
-
-#include "glob.hh"
-#include "boxes.hh"
-#include "plist.hh"
-#include "item.hh"
-
-/// stuff grouped vertically.
-struct PCol {
- List<const Item*> its;
- List<const Spanner*> stoppers, starters;
-
- /// Can this be broken? true eg. for bars.
- bool breakable()const;
-
- /// does this column have items, does it have spacings attached?
- bool used;
-
- /// prebreak is put before end of line.
- PCol *prebreak;
- /**
- if broken here, then (*this) column is discarded, and prebreak
- is put at end of line, owned by Col
- */
-
- /// postbreak at beginning of the new line
- PCol *postbreak;
- /** \See{prebreak}
- */
- PCol *daddy;
- /*
- if this column is pre or postbreak, then this field points to the parent.
- */
- /// if lines are broken then this column is in #line#
- const Line_of_score *line;
-
- /// if lines are broken then this column x-coord #hpos#
- Real hpos;
-
-
- /****************************************************************/
-
- void add(const Item*i);
-
- Interval width() const;
- ~PCol();
- PCol(PCol * parent);
-
- /// which col comes first?
- static int compare(const PCol &c1, const PCol &c2);
- /**
- signed compare on columns.
-
- return < 0 if c1 < c2.
- */
-
- void OK() const;
- void set_breakable();
- void print()const;
-};
-/**
- This is a class to address items vertically. It contains the data for:
- \begin{itemize}
- \item
- unbroken score
- \item
- broken score
- \item
- the linespacing problem
- \end{itemize}
- */
-
-#include "compare.hh"
-instantiate_compare(const PCol &, PCol::compare);
-
-
-/// ideal spacing between two columns
-struct Idealspacing {
-
- /// the ideal distance
- Real space;
-
- /// Hooke's constant: how strong are the "springs" attached to columns
- Real hooke;
-
- /// the two columns
- const PCol *left, *right;
-
- void print()const;
- void OK() const ;
- Idealspacing(const PCol *left,const PCol *right);
-};
-
-#endif
+++ /dev/null
-/*
- proto.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef PROTO_HH
-#define PROTO_HH
-#include "real.hh"
-
-class Line_of_score;
-class Line_of_staff;
-class PCol;
-class PStaff;
-class Staff;
-class Staff_column;
-class Score;
-class Score_column;
-class Voice;
-class Voice_element;
-class Voicegroup;
-class Request;
-class Command;
-class Request;
-class Stem_req;
-class Span_req;
-class Slur_req;
-class Decresc_req;
-class Cresc_req;
-class Bracket_req;
-class Script_req;
-class Rest_req;
-class Note_req;
-class Lyric_req;
-class Chord;
-class Absdynamic_req;
-struct Offset;
-struct Interval;
-struct Box;
-struct PCol;
-struct Idealspacing;
-struct Spanner;
-struct Item;
-struct Line_of_staff;
-struct Colinfo;
-struct Linestaff;
-struct Atom;
-struct Molecule;
-struct PScore;
-struct Request;
-struct Note_req;
-struct Lyric_req;
-struct Script_req;
-struct Rest_req;
-struct Rhythmic_req;
-struct Chord;
-struct Stem_req;
-struct Span_req;
-struct Beam_req;
-struct Bracket_req;
-struct Slur_req;
-struct Dynamic;
-struct Cresc_req;
-struct Decresc_req;
-struct Absdynamic_req;
-struct Score_column;
-struct Score;
-struct Staff_column;
-struct Staff;
-struct Command;
-struct Symbol;
-struct Output;
-struct Text_gob;
-struct Voice;
-struct Voicegroup;
-struct Voice_element;
-struct String;
-struct Tex_stream;
-struct Identifier;
-struct Keyword;
-class Mixed_qp;
-class Paperdef;
-class Score_commands;
-class Parametric_symbol;
-struct Lookup;
-struct Symtables;
-struct Symtable;
-
-#endif // PROTO_HH
-
+++ /dev/null
-// utility functions for PScore
-#include "debug.hh"
-#include "paper.hh"
-#include "molecule.hh"
-#include "dimen.hh"
-#include "line.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)
-{
- 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;
- }
- 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]->output->translate(Offset(-iv.length(),0));
- i->output->translate (Offset(-iv.max, 0));
- }
- }
- its.bottom().add(i);
- s->add(i);
- c->add(i);
- i->preprocess();
-}
-
-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;
-}
-
-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 ";
- 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<Item*> ic(its); ic.ok(); ic++){
- ic->postprocess();
- }
-}
+++ /dev/null
-// the breaking problem for a score.
-
-#ifndef PSCORE_HH
-#define PSCORE_HH
-
-
-#include "vray.hh"
-#include "pcol.hh"
-#include "pstaff.hh"
-
-/// all stuff which goes onto paper
-struct PScore {
- Paperdef *paper_; // indirection.
-
- /// the columns, ordered left to right
- PointerList<PCol *> cols;
-
- /// the idealspacings, no particular order
- PointerList<Idealspacing*> suz;
-
- /// the staffs ordered top to bottom
- PointerList<PStaff*> staffs;
-
- /// all symbols in score. No particular order.
- PointerList<Item*> its;
-
- /// if broken, the different lines
- PointerList<Line_of_score*> lines;
-
- /// crescs etc; no particular order
- PointerList<Spanner *> spanners;
-
- /****************************************************************/
-
- svec<Item*> select_items(PStaff*, PCol*);
-
- /// before calc_breaking
- void preprocess();
-
- void calc_breaking();
- /**
- calculate where the lines are to be broken.
-
- POST
-
- lines contain the broken lines.
- */
-
- /// after calc_breaking
- void postprocess();
-
- /// search all pcols which are breakable.
- svec<const PCol *> find_breaks() const;
-
- /// add a line to the broken stuff. Positions given in #config#
- void add_line(svec<const PCol *> curline, svec<Real> config);
-
- /// helper: solve for the columns in #curline#.
- svec<Real> solve_line(svec<const PCol *> curline) const;
-
- void add(PStaff *);
- /// add item
- void typeset_item(Item *, PCol *,PStaff*,int=1);
- /// add to bottom of pcols
- void add(PCol*);
- /**
-
- */
- void output(Tex_stream &ts);
-
- Idealspacing* get_spacing(PCol *, PCol *);
- /*
- get the spacing between c1 and c2, create one if necessary.
- */
-
-
- PCursor<PCol *> find_col(PCol *);
- void clean_cols();
- void problem_OK()const ;
- void OK()const ;
- PScore(Paperdef*);
- void print() const;
-};
-/** notes, signs, symbols in a score can be grouped in two ways:
- horizontally (staffwise), and vertically (columns). #PScore#
- contains the items, the columns and the staffs.
- */
-#endif
+++ /dev/null
-#include "pstaff.hh"
-
-PStaff::PStaff(PScore*ps)
-{
- pscore_=ps;
- stafsym = 0;
-}
-
-void
-PStaff::add(Item *i )
-{
- its.bottom().add(i);
- i->pstaff_ = this;
-}
+++ /dev/null
-#ifndef PSTAFF_HH
-#define PSTAFF_HH
-
-#include "plist.hh"
-#include "item.hh"
-#include "symbol.hh"
-
-/// items grouped vertically.
-struct PStaff {
- Parametric_symbol *stafsym;
- PScore * pscore_;
-
- virtual Symbol get_stafsym(Real width)const=0; // maybe overkill
-
- List<const Spanner*> spans;
- List<Item*> its;
-
- void add(Item*i);
- PStaff(PScore*);
- virtual ~PStaff() {}
-};
-
-#endif
+++ /dev/null
-#include "debug.hh"
-#include "const.hh"
-#include "qlp.hh"
-#include "choleski.hh"
-
-void
-Mixed_qp::add_equality_cons(Vector , double )
-{
- assert(false);
-}
-
-void
-Mixed_qp::add_fixed_var(int i, Real r)
-{
- eq_cons.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
-}
+++ /dev/null
-#ifndef QLP_HH
-#define QLP_HH
-
-#include "matrix.hh"
-
-/// inequality constrained quadratic program
-class Ineq_constrained_qp {
- friend class Active_constraints;
-
- svec<Vector> cons;
- svec<Real> consrhs;
-public:
- Matrix quad;
- Vector lin;
- Real const_term;
-
- ///
- void assert_solution(Vector sol) const;
- /**
- use a KKT method to assert optimality of sol
- */
- /// solve the problem using a projected gradient method
- Vector solve(Vector start) const;
-
- int dim() const{
- return lin.dim();
- }
- /** return the number of variables in the problem */
- ///
- void add_inequality_cons(Vector c, double r);
- /**
- add a constraint
-
-
- c*vars >= r
-
- PRE
- c.dim() == dim();
-
- */
- ///
- Ineq_constrained_qp(int novars);
- /** set up matrices to go with the problem. */
-
- Real eval(Vector v);
- /**
- evaluate the quadratic function for input #v#
- */
-
- void eliminate_var(int idx, Real value);
- void OK()const;
- void print() const;
-
-};
-
-/// Quadratic programming with mixed linear constraints
-class Mixed_qp :public Ineq_constrained_qp {
- svec<int> eq_cons;
- svec<Real> eq_consrhs;
-public:
- Mixed_qp(int n);
- void OK() const;
- void print() const;
-
- Vector solve(Vector start) const;
- void add_fixed_var(int i , Real value);
-
- ///
- void add_equality_cons(Vector c, double r);
- /**
- add a constraint,
-
- c*vars == r
-
- PRE
- c.dim()==dim();
- */
-
-};
-/**
- problem definition of a quadratic optimisation problem with linear
- inequality and equality constraints
-
-
- x^T QUAD x /2 + b^T x
-*/
-
-
-#endif
+++ /dev/null
-#include "qlpsolve.hh"
-#include "const.hh"
-#include "debug.hh"
-#include "choleski.hh"
-
-const Real TOL=1e-2; // roughly 1/10 mm
-
-String
-Active_constraints::status() const
-{
- String s("Active|Inactive [");
- for (int i=0; i< active.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) )
-
-
- */
-
+++ /dev/null
-#include "qlp.hh"
-#include "matrix.hh"
-
-
-class Active_constraints {
- friend class Inactive_iter;
-
-
- Matrix A,H;
- svec<int> active;
- svec<int> inactive; // actually this is a set, not an array.
- const Ineq_constrained_qp *opt;
-
-public:
- String status()const;
-
- Vector vec(int k) const { return opt->cons[k]; }
- Real rhs(int k) const { return opt->consrhs[k]; }
-
- /// drop constraint
- void drop (int k);
- /** drop constraint k from the active set. k is the index of the
- constraint in #active#
-
- */
-
- /// add constraint j
- void add(int j);
- /**
- add constraint j to the active set j is the index of the
- constraint in #inactive#
- */
-
- /// exchange in and out.
- void exchange(int in, int out) { add(in); drop (out); }
-
- ///
- Vector find_active_optimum(Vector g);
-
- /// get lagrange multipliers.
- Vector get_lagrange(Vector v);
-
- Active_constraints(Ineq_constrained_qp const *op);
- /** construct: no constraints active, n vars. Put the equalities
- into the constraints. */
-
- /// check invariants
- void OK();
-};
-
-/**
- This class represents the set of active (binding) constraints
- which can be active while the QLP algorithm is in a feasible
- point. The active constraints are numbered.
- If the constraints are of the form
-
- A^T*x >= b
-
- then the binding constraints are those where the >= is equality.
-
- */
-
-///
-class Inactive_iter {
- int j;
- Active_constraints const* ac;
-public:
- Inactive_iter(Active_constraints const &c) { ac=&c; j=0; }
- int idx() const { return j; }
- void operator ++(int) { j++; }
- int constraint_id() const { return ac->inactive[j]; }
- Vector vec() const { return ac->vec(constraint_id()); }
- Real rhs() const { return ac->rhs(constraint_id()); }
- bool ok() const { return j < ac->inactive.sz(); }
-};
-/**
- loop through the inactive constraints.
- */
+++ /dev/null
-#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);
-
-
-void
-Request::print() const
-{
-#ifndef NPRINT
- mtor << "Req{ unknown }\n";
-#endif
-}
-
-Request::Request(Voice_element*v)
-{
- elt = v;
-}
-
-Note_req::Note_req(Voice_element*v)
- : Rhythmic_req(v)
-{
- 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(Voice_element*v)
- :Request(v)
-{
- 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();
-}
-
-Request::Request()
-{
- elt = 0;
-}
-
-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);
-}
-
+++ /dev/null
-// LilyPond's second egg of columbus!
-#ifndef REQUEST_HH
-#define REQUEST_HH
-
-#include "glob.hh"
-#include "string.hh"
-
-/// a voice element wants something printed
-struct Request {
- Voice_element*elt; // indirection.
-
- /****************/
-
- virtual void print()const ;
- virtual Note_req *note() {return 0;}
- virtual Stem_req *stem() {return 0;}
- virtual Rest_req *rest() {return 0;}
- virtual Rhythmic_req*rhythmic() { return 0;}
- Request(Voice_element*);
- Request();
- virtual Real duration() const { return 0.0; }
- virtual Request* clone() const =0;
-};
-
-/**
- Any Voice_element can do a number of requests. A request is done
- to the #Staff# which contains the #Voice_element#. The staff decides
- whether to to honor the request, ignore it, or merge it with other
- requests. Merging of requests is preferably done with other
- requests done by members of the same voicegroups (beams, brackets, stems)
-
- Please refer to the documentation of the Child classes of
- #Request# for explanation of each request type.
-
- The result of a request will be an #Item# or a #Spanner#, which
- will be put on a #PStaff#. Note that the #PStaff# and the original
- #Staff# need not have anything in common. For example, the
- ``double'' piano Staff could interpret commands which juggle
- melodies across the left and right hand, and may put the result in
- two five-line PStaffs (maybe with extra PStaffs to carry the dynamic
- signs and any lyric.
-
- The class #Staff# should be thought as a container for the
- #Voice#s, and an interpreter for #Request#s and #Command#s.
- Different staffs can produce different outputs; a melodious voice
- which is put into a percussion-Staff, will be typeset as the rythm of
- that voice.
-
- After #Staff# made up her mind (Would #Staff# be a smart
- name? How about #struct Susan {}# :-), the resultant items and
- spanners are put on the PScore, and pointers to these items are
- stored in the #Voice_element#. This construction enables the
- beams/stems to look up the balls it has to connect to. */
-
-
-/// a request with a duration
-struct Rhythmic_req : Request {
- int balltype;
- int dots;
-
- /****************/
-
- Real duration() const;
- Rhythmic_req(Voice_element*);
- Rhythmic_req*rhythmic() { return this;}
- void print ()const;
- Request*clone() const;
-};
-
-/// Put a note of specified type, height, and with accidental on the staff.
-struct Note_req : Rhythmic_req {
- char name;
- int octave;
- int accidental;
- bool forceacc;
-
- /****************/
-
- // return height from central c (in halflines)
- int height()const;
- Note_req(Voice_element*v);
- Note_req*note() { return this;}
- virtual void print() const;
- Request*clone() const;
-};
-/**
-Staff has to decide if the ball should be hanging left or right. This
-influences the horizontal dimensions of a column, and this is why
-request processing should be done before horizontal spacing.
-
-Other voices' frivolities may cause the need for accidentals, so this
-is also for the Staff to decide. The Staff can decide on positioning
-based on ottava commands and the appropriate clef.
-*/
-
-
-///Put a rest on the staff.
-struct Rest_req : Rhythmic_req {
- void print()const;
- Rest_req(Voice_element*v) : Rhythmic_req(v) { }
- Rest_req * rest() { return this;}
- Request*clone() const ;
-};
-/**
-Why a request? It might be a good idea to not typeset the rest, if the paper is too crowded.
-*/
-
-/// attach a stem to the noteball
-struct Stem_req : Request {
- /// 4,8,16, ..
- int stem_number;
- virtual Stem_req *stem() {return this;}
- Stem_req(Voice_element*v, int s) : Request(v) { stem_number = s; }
- Request*clone() const;
-};
-
-
-#if 0
-
-///Put a lyric above or below (?) this staff.
-struct Lyric_req : Request {
- String text;
-};
-
-
-///Put a script above or below this ``note''
-struct Script_req : Request {
- int orientation;
- Symbol sym;
-};
-/**
-eg upbow, downbow. Why a request? These symbols may conflict with slurs and brackets, so this
-also a request
-*/
-
-
-
-
-///Draw a (Guitar) chord above or below this ``note''
-struct Chord : Request {
- // don't know how this looks.
-};
-/**
-Why a request?
-Because everything else is done in requests.
-*/
-
-
-/// for absolute dynamics
-enum Loudness {
- FFF, FF, F, MF, MP, P, PP, PPP
-} ;
-
-/// requests to start or stop something.
-struct Span_req : Request {
- /// should the spanner start or stop, or is it unwanted?
- enum {
- NOSPAN, START, STOP
- } spantype ;
-};
-/**
- This type of request typically results in the creation of a #Spanner#
-*/
-
-
-///Start / stop a beam at this note.
-struct Beam_req : Span_req {
- int nplet;
-};
-/** Staff will have to combine this with the stem_request, since the
- number of flags that a stem wants to carry will determine the
- number of beams. if #nplet# is set, the staff will try to put an
- appropriate number over the beam
-
- [what to do if the nplet fields of start and stop conflict?]
- */
-
-///Start / stop a slur or a bracket.
-struct Bracket_req : Span_req {
- int nplet;
-};
-/**
-Start/stop a bracket at this note. if #nplet# is set, the staff will
-try to put an appropriate number over the bracket
-*/
-
-/// a slur
-struct Slur_req : Span_req {
-
-};
-
-/// helper in the hierarchy
-struct Dynamic {
- Real subtime;
-};
-/** Each dynamic is bound to one note ( a crescendo spanning multiple
- notes is thought to be made of two "dynamics": a start and a stop).
- Dynamic changes can occur in a smaller time than the length of its
- note, therefore fore each Dynamic request carries a time, measured
- from the start of its note.
-
- This subfield would come in handy, if mpp96 was adapted for midi
- support.
-
- Dynamic should have been derived from request, but I don't want to
- fuss with virtual baseclasses. */
-
-/// do a crescendo
-struct Cresc_req : Span_req, Dynamic {
-
-};
-
-/// do a decrescendo
-struct Decresc_req : Span_req, Dynamic {
-
-};
-
-/// do a dynamic like "fff" or "mp"
-struct Absdynamic_req : Request, Dynamic {
- Loudness loudness;
-};
-#endif
-#endif
+++ /dev/null
-#include "molecule.hh"
-#include "notehead.hh"
-#include "stem.hh"
-#include "linestaff.hh"
-#include "rhythmstaff.hh"
-#include "paper.hh"
-#include "sccol.hh"
-
-
-void
-Rhythmic_staff::set_output(PScore*ps)
-{
- theline = new Linestaff(1,ps);
- Simple_staff::set_output(ps);
-}
-
-
-void
-Rhythmic_column::typeset_command(Command *com, int breakst)
-{
- Item *i =new Item;
- Molecule*m = create_command_mol(com);
- i->output=m;
- m->translate(Offset(0,
- -staff_->score_->paper_->standard_height()/2));
- typeset_item(i, breakst);
-}
-
-void
-Rhythmic_column::typeset_req(Request *rq)
-{
- Item *i ;
- if (rq->note()) {
- Notehead *n =new Notehead(1);
- n->balltype = rq->rhythmic()->balltype;
- n->dots = rq->rhythmic()->dots;
- n->position = 0;
- i = n;
- } else if (rq->rest()) {
- i =new Item;
- Molecule*m=create_req_mol(rq);
- i->output=m;
- }
- typeset_item(i);
-}
-
-void
-Rhythmic_column::typeset_stem(Stem_req*rq)
-{
- Stem * s = new Stem(0);
- s->minnote = s->maxnote = 0;
- s->flag = rq->stem_number;
- typeset_item(s);
-}
-
-/*
- creation
- */
-Staff *
-get_new_rhythmstaff()
-{
- return new Rhythmic_staff;
-}
-
-
-Staff_column*
-Rhythmic_staff::create_col(Score_column*s)
-{
- return new Rhythmic_column(s,this);
-}
-
-Rhythmic_staff*
-Rhythmic_staff::clone() const
-{
- return new Rhythmic_staff(*this);
-}
+++ /dev/null
-/*
- rhythmstaf.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef RHYTHMSTAF_HH
-#define RHYTHMSTAF_HH
-
-#include "simplestaff.hh"
-
-/// all notes on one line
-struct Rhythmic_staff : public Simple_staff
-{
- // Rhythmic_staff();
- Staff_column * create_col(Score_column*);
- virtual void set_output(PScore *);
- virtual Rhythmic_staff*clone()const;
-};
-
-/// this does the typesetting
-struct Rhythmic_column : public Simple_column {
- virtual void typeset_req(Request *rq);
- virtual void typeset_stem(Stem_req *rq);
- virtual void typeset_command(Command *, int brs);
-
-
-// virtual void typeset_item(Item *rq, int=1);
- Rhythmic_column(Score_column*s,Simple_staff*rs) :
- Simple_column(s,rs) { }
-// virtual Rhythmic_column*clone()const;
-};
-
-#endif // RHYTHMSTAF_HH
-
-
+++ /dev/null
-#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
-}
+++ /dev/null
-/*
- sccol.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef SCCOL_HH
-#define SCCOL_HH
-#include "pcol.hh"
-
-
-struct Score_column {
- PCol * pcol;
- svec<Real> durations;
- Real when;
-
- ///
- bool musical;
-
-
- Score_column(Real when);
-
- static int compare(Score_column & c1, Score_column &c2) {
- return sgn(c1.when - c2.when);
- }
- void set_breakable() {
- pcol->set_breakable();
- }
- bool used();
- void print() const;
-};
-/**
-
- When typesetting hasn't started on PScore yet, the columns which
- contain data have a rhythmical position. Score_column is the type
- with a rhythmical time attached to it. The calculation of
- idealspacing is done with data in these columns. (notably: the
- #durations# field)
-
- */
-
-instantiate_compare(Score_column&, Score_column::compare);
-
-#endif // SCCOL_HH
-
+++ /dev/null
-#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();
- }
-}
-
-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;
-}
+++ /dev/null
-/*
- lilypond, (c) 1996 Han-Wen Nienhuys
-*/
-#ifndef SCOMMANDS_HH
-#define SCOMMANDS_HH
-
-#include "proto.hh"
-#include "command.hh"
-#include "vray.hh"
-#include "plist.hh"
-
-struct Score_commands : public PointerList<Command*> {
- void process_add(Command);
- Score_commands*parse(Real last)const;
- void parser_add(Command*);
- void add_seq(svec<Command>);
- void clean(Real last);
- void set_breakable(Real when);
- bool is_breakable(Real w);
- PCursor<Command*> last_insertion(Real w);
- PCursor<Command*> first(Real w);
- void add_command_to_break(Command pre, Command mid,Command post);
- void OK() const;
- void print() const;
- Real last() const;
- void insert_between(Command victim, PCursor<Command*> firstc,
- PCursor<Command*> last);
-};
-/** the list of commands in Score. Put in a separate class, since it
- otherwise clutters the methods of Score. */
-
-#endif
-
+++ /dev/null
-#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;
-}
+++ /dev/null
-#ifndef SCORE_HH
-#define SCORE_HH
-#include "vray.hh"
-#include "proto.hh"
-#include "plist.hh"
-
-
-/// the total music def of one movement
-struct Score {
- /// paper_, staffs_ and commands_ form the problem definition.
- Paperdef *paper_;
- PointerList<Staff *> staffs_;
- Score_commands *commands_;
-
- /// "runtime" fields for setting up spacing
- PointerList<Score_column*> cols_;
- PScore *pscore_;
-
- /****************************************************************/
-
- /// construction
- void add_staff(Staff *st);
- void set(Paperdef*);
- Score();
- ~Score();
- void add(Staff*);
- void set(Score_commands*);
-
-
- void OK() const;
- Score_column *find_col(Real,bool);
- void process();
- void output(String fn);
- PCursor<Score_column*> create_cols(Real);
- void print() const;
- Real last() const;
-
-private:
- void do_pcols();
- void clean_cols();
- void distribute_commands();
- void do_connect(PCol *c1, PCol *c2, Real d);
- void connect_nonmus(PCol* c1, PCol *c2, Real d);
- /// add #Idealspacings# to #pscore_#
- void calc_idealspacing();
- /** add the score wide commands (bars, breaks) to each staff so
- they can process (typeset) them if needed */
-};
-/**
-
- */
-#endif
+++ /dev/null
-#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;
-}
-
+++ /dev/null
-#include "lookupsyms.hh"
-#include "request.hh"
-#include "pscore.hh"
-#include "paper.hh"
-#include "simplestaff.hh"
-#include "molecule.hh"
-#include "sccol.hh"
-
-Molecule *
-Simple_column::create_req_mol(Request *rq)
-{
- assert(rq->rest());
- Symbol s;
- int dots=0;
- if (rq->rest())
- s = staff_->paper()->lookup_->rest(rq->rest()->balltype);
-
- if (rq->rhythmic())
- dots=rq->rhythmic()->dots;
-
-
- Molecule *m = new Molecule(Atom(s));
- if (dots) {
- Symbol d = staff_->paper()->lookup_->dots(dots);
- Molecule dm;
- dm.add(Atom(d));
- m->add_right(dm);
- }
- return m;
-}
-
-Molecule *
-Simple_column::create_command_mol(Command *com)
-{
- Symbol s;
-
- if (com -> args[0] == "BAR" ) {
- s = staff_->paper()->lookup_->bar(com->args[1]);
- } else if (com->args[0] == "METER") {
- Parametric_symbol *p = staff_->paper()->lookup_->meter("general");
- svec<String> arg( com->args);
- arg.del(0);
- s = p->eval(arg);
- } else
- assert(false);
-
- Molecule * m =new Molecule(Atom(s));
- {
- Interval wid;
- svec<Item*> sv(staff_->pscore_->
- select_items(staff_->theline, score_column->pcol));
- for (int j=0; j<sv.sz(); j++) {
- wid.unite(sv[j]->output->extent().x);
- }
- if (!wid.empty())
- m->translate(Offset(wid.max,0));
- }
-
- return m;
-}
-
-void
-Simple_column::typeset_item(Item *i, int breakst)
-{
- // ugh
- staff_->pscore_->typeset_item(i, score_column->pcol,
- staff_->theline,breakst);
-}
-
-void
-Simple_staff::set_output(PScore* ps )
-{
- pscore_ = ps;
- pscore_->add(theline);
-}
+++ /dev/null
-#include "request.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)
-{
- the_note = 0;
- stem_ = 0;
- staff_ = rs;
-}
-
-Simple_staff::Simple_staff()
-{
- theline = 0;
-}
-
-void
-Simple_column::process_commands( )
-{
- int breakstat = BREAK_END - BREAK_PRE;
- for (int i = 0 ; i < s_commands.sz(); i++) {
- Command *com = s_commands[i];
- switch (com->code){
- case INTERPRET:
- break;
- case BREAK_PRE:
- case BREAK_MIDDLE:
- case BREAK_POST:
- case BREAK_END:
- score_column->set_breakable();
- breakstat = com->code- BREAK_PRE;
- break;
-
- case TYPESET:
- typeset_command ( com , breakstat);
- break;
- default :
- break;
- }
- }
-}
-/**
- 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()){
- if (the_note){
- WARN << "too many notes.\n";
- }
- the_note = rq;
-
- }
- if (rq->stem()) {
- stem_ = rq->stem();
- }
-
- }
-}
-
-void
-Simple_staff::grant_requests()
-{
- for (PCursor<Staff_column*> cc(cols); cc.ok(); cc++) {
- Simple_column *rp = (Simple_column*)*cc;
- if (rp->the_note)
- rp->typeset_req( rp->the_note);
- if (rp->stem_)
- rp->typeset_stem(rp->stem_->stem());
- }
-}
-
-
+++ /dev/null
-/*
- simplestaff.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef SIMPLESTAFF_HH
-#define SIMPLESTAFF_HH
-
-#include "stcol.hh"
-#include "staff.hh"
-/*
- mega-stupido staffs and cols: they do notes one at each moment.
- */
-
-struct Simple_staff;
-
-/// column of Simple_staff: store one request
-struct Simple_column : Staff_column {
-
- Request *the_note;
- Stem_req *stem_;
-
- Simple_staff* staff_;
-
- /****************/
- virtual void typeset_stem(Stem_req *rq)=0;
- virtual void typeset_req(Request *rq)=0;
- virtual void typeset_command(Command *, int brs)=0;
- virtual void typeset_item(Item *, int=1);
-
- Molecule *create_command_mol(Command *com);
- Molecule *create_req_mol(Request *rq);
- void take_request(Request *rq);
-
- virtual void process_commands( );
- virtual void process_requests();
-
- Simple_column(Score_column*s,Simple_staff*rs);
-};
-
-
-/// Simple staff: one note at a time
-struct Simple_staff : Staff {
- /// indirection to the PStaff.
- PStaff *theline;
-
- /****************/
- virtual void set_output(PScore *);
-
- void process_commands( PCursor<Command*> &where);
- void grant_requests();
-// virtual Staff*clone()const;
-
- Simple_staff();
-};
-
-#endif // SIMPLESTAFF_HH
-
-
-
+++ /dev/null
-
-#include "spanner.hh"
-#include "line.hh"
-
-#include "symbol.hh"
-#include "molecule.hh"
-#include "pcol.hh"
-
-String
-Spanner::TeXstring() const
-{
- assert(right->line);
- Real w = left->hpos - right->hpos;
- return strets->eval(w).tex;
-}
-
-// todo.
-Spanner *
-Spanner::broken_at(const PCol *c1, const PCol *c2) const
-{
- Spanner *sp = new Spanner(*this);
- sp->left = c1;
- sp->right = c2;
- return sp;
-}
-
-Spanner::Spanner()
-{
- pstaff_=0;
- strets=0;
- left = right = 0;
-}
-
+++ /dev/null
-/*
- spanner.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef SPANNER_HH
-#define SPANNER_HH
-#include "proto.hh"
-
-/// a symbol which is attached between two columns.
-struct Spanner {
- const PCol *left, *right;
- Parametric_symbol *strets;
- PStaff * pstaff_;
- /// clone a piece of this spanner.
- virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const;
- /**
-
- PRE
- c1 >= start, c2 <= stop
- */
- /****************/
- String TeXstring () const ;
- Spanner();
- virtual void process();
-};
-/** Spanner should know about the items which it should consider:
- e.g. slurs should be steep enough to "enclose" all those items. This
- is absolutely necessary for beams, since they have to adjust the
- length of stems of notes they encompass.
-
- */
-#endif
--- /dev/null
+default:
+ $(MAKE) -C ..
+
+dist:
+ ln Makefile $(mycc) $(othersrc) $(DDIR)/src
+
+TAGS: $(mycc)
+ etags -CT $(mycc)
--- /dev/null
+#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));
+}
+
--- /dev/null
+#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';
+}
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+/*
+ 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);
+ }
+}
+
--- /dev/null
+#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);
+ }
+ }
+}
+
+
--- /dev/null
+#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
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
+
+
--- /dev/null
+#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();
+}
--- /dev/null
+#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_;
+}
+
--- /dev/null
+/*
+ keyword.cc -- keywords and identifiers
+ */
+
+#include <stdlib.h>
+
+#include "glob.hh"
+#include "lexer.hh"
+//#include "mudobs.hh"
+//#include "gram.hh"
+
+/* for the keyword table */
+struct Keyword_ent
+{
+ const char *name;
+ int tokcode;
+};
+
+struct Keyword_table
+{
+ Keyword_ent *table;
+ int maxkey;
+ Keyword_table(Keyword_ent *);
+ int lookup(const char *s) const;
+};
+
+
+/* for qsort */
+int
+ tabcmp(const void * p1, const void * p2)
+{
+ return strcmp(((const Keyword_ent *) p1)->name,
+ ((const Keyword_ent *) p2)->name);
+}
+
+Keyword_table::Keyword_table(Keyword_ent *tab)
+{
+ table = tab;
+
+ /* count keywords */
+ for (maxkey = 0; table[maxkey].name; maxkey++);
+
+ /* sort them */
+ qsort(table, maxkey, sizeof(Keyword_ent), tabcmp);
+}
+
+/*
+ lookup with binsearch, return tokencode.
+*/
+int
+Keyword_table::lookup(const char *s)const
+{
+ int lo,
+ hi,
+ cmp,
+ result;
+ lo = 0;
+ hi = maxkey;
+
+ /* binary search */
+ do
+ {
+ cmp = (lo + hi) / 2;
+
+ result = strcmp(s, table[cmp].name);
+
+ if (result < 0)
+ hi = cmp;
+ else
+ lo = cmp;
+ }
+ while (hi - lo > 1);
+ if (!strcmp(s, table[lo].name))
+ {
+ return table[lo].tokcode;
+ } else
+ return -1; /* not found */
+}
+
--- /dev/null
+#include "leastsquares.hh"
+
+void
+Least_squares::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;
+
+}
--- /dev/null
+%{ // -*-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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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_);
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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));
+}
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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();
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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));
+}
+
--- /dev/null
+#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);
+}
--- /dev/null
+#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
+}
--- /dev/null
+%{ // -*-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";
+}
--- /dev/null
+#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;
+}
+
--- /dev/null
+// 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();
+ }
+}
--- /dev/null
+#include "pstaff.hh"
+
+PStaff::PStaff(PScore*ps)
+{
+ pscore_=ps;
+ stafsym = 0;
+}
+
+void
+PStaff::add(Item *i )
+{
+ its.bottom().add(i);
+ i->pstaff_ = this;
+}
--- /dev/null
+#include "debug.hh"
+#include "const.hh"
+#include "qlp.hh"
+#include "choleski.hh"
+
+void
+Mixed_qp::add_equality_cons(Vector , double )
+{
+ assert(false);
+}
+
+void
+Mixed_qp::add_fixed_var(int i, Real r)
+{
+ eq_cons.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
+}
--- /dev/null
+#include "qlpsolve.hh"
+#include "const.hh"
+#include "debug.hh"
+#include "choleski.hh"
+
+const Real TOL=1e-2; // roughly 1/10 mm
+
+String
+Active_constraints::status() const
+{
+ String s("Active|Inactive [");
+ for (int i=0; i< active.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) )
+
+
+ */
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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);
+}
--- /dev/null
+#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
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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!!
+ */
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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);
+}
--- /dev/null
+#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();
+ }
+}
+
--- /dev/null
+#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);
+}
+
+
--- /dev/null
+#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
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
+
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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();
+}
+
--- /dev/null
+#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);
+}
+
--- /dev/null
+#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;
+ }
+}
+
+
+
--- /dev/null
+#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();
+ }
+}
--- /dev/null
+
+#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);
+
--- /dev/null
+
+#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);
+
+
--- /dev/null
+#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);
+
+
+
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+
+ Code to generate beams for TeX
+
+ */
+
+ #include <math.h>
+#include "symbol.hh"
+#include "molecule.hh"
+#include "tex.hh"
+#include "symtable.hh"
+#include "dimen.hh"
+#include "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;
+}
+
+
--- /dev/null
+#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;
+}
+
+
+/****************************************************************/
--- /dev/null
+#include "version.hh"
+
+static char *s = "LilyPond version " VERSIONSTR " compiled on " __DATE__ " at " __TIME__ "\n";
+
+const char *
+get_version()
+{
+ return s;
+}
--- /dev/null
+#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());
+}
--- /dev/null
+#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);
+}
+
+++ /dev/null
-#include "staff.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();
- for (PCursor<Staff_column*> sc(cols); sc.ok(); sc++) {
- sc->process_commands();
- sc->process_requests();
- }
- grant_requests();
-}
-
-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;
-}
+++ /dev/null
-#ifndef STAFF_HH
-#define STAFF_HH
-
-#include "score.hh"
-#include "voice.hh"
-#include "command.hh"
-
-
-/// base class for a collection of voices.
-struct Staff {
- /// synchronous horizontal stuff
- PointerList<Voice*> voices;
-
- /// commands in chronological order
- PointerList<Command *> commands;
-
- /// runtime field
- PointerList<Staff_column*> cols;
-
- /// indirections to the Score and PScore
- Score *score_;
- PScore *pscore_;
-
- /****************************************************************/
- Staff(const Staff&src);
- void add_voice(Voice *v);
- void add_staff_column(Staff_column *sp);
-
- Paperdef*paper()const;
- /// interpret all requests and add items to #destination#.
- void process();
- /**
- This routines calls virtual functions from Staff, to delegate the
- interpretation of requests to a derived class of Staff */
- void setup_staffcols();
-
- void OK() const;
- void print() const;
- Real last() const;
- void clean_cols() ;
- Staff_column * get_col(Real,bool);
-
- void add_commands(PointerList<Command* >const & sv);
- /**
- add all commands from sv.
-
- PRE
- sv is time-ordered.
- */
-
- Staff();
- /**
- Should construct with Score as arg, but this isn't known during parsing.
- */
- /****************************************************************
- VIRTUALS
- ****************************************************************/
- virtual Staff*clone()const=0;
- virtual void set_output(PScore * destination)=0;
- virtual void grant_requests()=0;
- virtual Staff_column * create_col(Score_column * )=0;
- virtual ~Staff() { }
-};
-#endif
-
-
+++ /dev/null
-#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;
-}
+++ /dev/null
-/*
- stcol.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef STCOL_HH
-#define STCOL_HH
-#include "proto.hh"
-#include "vray.hh"
-
-/// store simultaneous requests
-struct Staff_column {
- Score_column *score_column;
-
- /// fields to collect data vertically.
- svec<Voice_element *> v_elts;
- svec<Command *> s_commands;
-
- Staff_column(Score_column*s);
- bool mus() const;
- Real when() const;
- void add(Voice_element*ve);
- /****************************************************************
- VIRTUAL
- ****************************************************************/
- //virtual Staff_column *clone() const=0;
- virtual void process_requests()=0;
- virtual void process_commands()=0;
- virtual ~Staff_column() { }
-};
-
-
-#endif // STCOL_HH
-
+++ /dev/null
-#include "stem.hh"
-#include "dimen.hh"
-#include "debug.hh"
-#include "pstaff.hh"
-#include "pscore.hh"
-#include "paper.hh"
-#include "lookupsyms.hh"
-#include "molecule.hh"
-
-const int STEMLEN=7;
-
-Stem::Stem(int c)
-{
- minnote = maxnote = 0;
- bot = top = 0;
- flag = 4;
- staff_center=c;
-}
-
-void
-Stem::print()const
-{
- mtor << "Stem minmax=["<< minnote<<","<<maxnote<<"], flag: "<<flag;
- Item::print();
-}
-
-void
-Stem::calculate()
-{
- assert(minnote<=maxnote);
- int stafftop = 2*staff_center;
-
- if (maxnote < -2){
- bot = minnote;
- top = staff_center - staff_center/2; // uhh... how about non 5-line staffs?
-
- }else if (minnote > stafftop + 2) {
- top = maxnote;
- bot = staff_center + staff_center/2;
- flag = -flag;
- }else {
- Real mean = (minnote+maxnote)/2;
-
- top = (mean > staff_center) ? maxnote : maxnote+STEMLEN;
- bot = (mean > staff_center) ? minnote-STEMLEN : minnote;
- flag = (mean > staff_center) ? -flag : flag;
- }
-}
-
-void
-Stem::postprocess()
-{
- calculate();
- brew_molecole();
-}
-
-Interval
-Stem::width()const
-{
- if (ABS(flag) <= 4)
- return Interval(0,0); // TODO!
- Paperdef*p= pstaff_->pscore_->paper_;
- return p->lookup_->flag(flag).dim.x;
-}
-
-void
-Stem::brew_molecole()
-{
- assert(pstaff_);
- assert(bot!=top);
- assert(!output);
-
- Paperdef *p = pstaff_->pscore_->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 (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);
- }
-
- if (flag > 0){
- Real dx = pstaff_->pscore_->paper_->note_width(); // ugh
- output->translate(Offset(dx,0));
- }
-}
+++ /dev/null
-/*
- stem.hh -- part of LilyPond
-
- (c) 1996 Han-Wen Nienhuys
-*/
-
-#ifndef STEM_HH
-#define STEM_HH
-#include "item.hh"
-
-/// the rule attached to the ball
-struct Stem : public Item {
- // heads the stem encompasses (positions)
- int minnote, maxnote;
-
- int staff_center;
-
- // extent of the stem (positions)
- int bot, top;
-
- // flagtype? 4 none, 8 8th flag, 0 = beam.
- int flag;
-
- /****************/
-
- void postprocess();
- Stem(int center);
- void print() const;
- Interval width() const;
-private:
- void calculate();
- void brew_molecole();
-};
-/**
- takes care of:
-
- \begin{itemize}
- \item the rule
- \item the flag
- \item up/down position.
- \end{itemize}
- */
-
-#endif
+++ /dev/null
-% testje
-
-score{
- rhythmstaff {
- voice { $ c2 c2 c4. c8 c4 c4 c4 c4 c4 c4 c2 c2$ }
- }
- commands { meter 2 4 skip 2:0 meter 4 4 skip 2:0}
-}
+++ /dev/null
-#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);
-}
-
+++ /dev/null
-#ifndef SYMBOL_HH
-#define SYMBOL_HH
-#include "string.hh"
-#include "boxes.hh"
-#include "proto.hh"
-
-struct Symbol {
- String tex;
- Box dim;
-
- Symbol (String, Box);
- Symbol();
-};
-
-struct Parametric_symbol {
- Symtables*symtables_; // indirection
-
- /*****************/
-
- Parametric_symbol(Symtables*s) { symtables_ = s; }
- Symbol eval(String args1) const; // convenience
- Symbol eval(String args1,String arg2) const; // convenience
- virtual Symbol eval(svec<String> args)const =0;
- virtual ~Parametric_symbol(){}
-};
-
-#endif
end
table streepjes
- toplines \toplines{%} -6pt 6pt 0pt 0pt
- botlines \botlines{%} -6pt 6pt 0pt 0pt
+ toplines \toplines{%} -7pt 7pt 0pt 0pt
+ botlines \botlines{%} -7pt 7pt 0pt 0pt
end
table bars
8 \eigthflag 0pt 5pt 0pt 0pt
16 \sixteenthflag 0pt 5pt 0pt 0pt
32 \thirtysecondflag 0pt 5pt 0pt 0pt
- -8 \ieigthflag -5pt 0pt 0pt 0pt
- -16 \isixteenthflag -5pt 0pt 0pt 0pt
- -32 \ithirtysecondflag -5pt 0pt 0pt 0pt
+ -8 \deigthflag 0pt 5pt 0pt 0pt
+ -16 \dsixteenthflag 0pt 5pt 0pt 0pt
+ -32 \dthirtysecondflag 0pt 5pt 0pt 0pt
+end
+
+table beamslopes
+ slope \beamslope{%}{%} 0pt 0pt 0pt 0pt
+ horizontal \rulesym{%}{%} 0pt 0pt 0pt 0pt
end
end # symboltables
\ No newline at end of file
+++ /dev/null
-#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;
-
- assert(r.sz() == 6);
- 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;
- }
-}
-
-
-
+++ /dev/null
-/*
- lilypond, (c) 1996 Han-Wen Nienhuys
-*/
-#ifndef SYMTABLE_HH
-#define SYMTABLE_HH
-#include "assoc.hh"
-#include "string.hh"
-#include "symbol.hh"
-
-struct Symtable : public Assoc<String, Symbol> {
- Symbol lookup(String)const;
-};
-
-
-struct Symtables : private Assoc<String, Symtable*> {
- void read(Text_db&) ;
- Symtable* operator()(String s);
-
-};
-
-
-#endif
-
+++ /dev/null
-#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,
- "pt", PT,
- "in", IN,
- "mm", MM,
- "paper", PAPER,
- "width", WIDTH,
- "meter", METER,
- "unitspace", UNITSPACE,
- "skip", SKIP,
- "commands", COMMANDS,
- "staff", STAFF,
- "geometric", GEOMETRIC,
- 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();
- }
-}
+++ /dev/null
-#include "line.hh"
-
-#include "plist.hh"
-#include "pcol.hh"
-#include "item.hh"
-#include "request.hh"
-#include "command.hh"
-#include "spanner.hh"
-
-#include "list.cc"
-#include "plist.cc"
-#include "cursor.cc"
-
-#define PLC_instantiate(a) PL_instantiate(a); PL_instantiate(const a)
-
-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);
-
+++ /dev/null
-#include "line.hh"
-#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);
-
-
+++ /dev/null
-#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);
-
-
-
+++ /dev/null
-#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;
-}
+++ /dev/null
-#ifndef TEX_HH
-#define TEX_HH
-
-#include "string.hh"
-#include "boxes.hh"
-
-/// parameter substitution in TeXstrings
-String
-substitute_args(String source, svec<String> args);
-/**
- this structure provides a simple macro mechanism:
-
- if source == "tex%bla%", then
- eval({"X","Y"}) == "texXblaY"
- */
-
-/// #h# is in points
-String vstrut(Real h);
-
-
-#endif
+++ /dev/null
-#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;
-}
-
-
-/****************************************************************/
+++ /dev/null
-#ifndef TSTREAM__HH
-#define TSTREAM__HH
-
-#include <iostream.h>
-#include "string.hh"
-
-/// TeX output
-struct Tex_stream {
- bool outputting_comment;
- ostream *os;
- int nest_level;
-
- /// open a file for writing
- Tex_stream(String filename);
- void header();
- /// delegate conversion to string class.
- Tex_stream &operator<<(String);
-
- /// close the file
- ~Tex_stream();
-};
-/**
- Use this class for writing to a TeX file.
- It counts braces to prevent nesting errors, and
- it will add a comment sign before each newline.
- */
-#endif
+++ /dev/null
-#include "version.hh"
-
-static char *s = "LilyPond version " VERSIONSTR " compiled on " __DATE__ " at " __TIME__ "\n";
-
-const char *
-get_version()
-{
- return s;
-}
+++ /dev/null
-#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();
- }
- 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());
-}
+++ /dev/null
-#ifndef VOICE_HH
-#define VOICE_HH
-
-
-#include "plist.hh"
-#include "request.hh"
-
-/// class for horizontal stuff.
-struct Voice {
- PointerList<Voice_element *> elts;
- Real start;
-
- /****************/
- Real when(const Voice_element*)const;
- Real last() const;
- Voice();
- Voice(Voice const&);
- void add(Voice_element*);
- void print() const;
-};
-/**
-
- Voice is a ordered row of Voice_elements. It is strictly horizontal:
- you cannot have two rhythmic elements running parallel in a Voice
-
- */
-
-struct Voicegroup {
- /// don't know how to identify these.
-};
-
-/// one horizontal bit.
-struct Voice_element {
- Real duration;
- const Voicegroup *group;
- const Voice *voice;
- PointerList<Request*> reqs;
-
- List<const Item *> granted_items;
- List<const Spanner *> granted_spanners;
-
- /****************/
-
- void add(Request*);
- Voice_element();
- Voice_element(Voice_element const & src );
- void print ()const;
-};
-/** Apart from being a container for the requests, Voice_element is
- glue between related items and spanners, between requests and
- (voice)groups
- */
-#endif
+++ /dev/null
-#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);
-}
-