]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-0.0.13
authorfred <fred>
Fri, 29 Nov 1996 14:25:05 +0000 (14:25 +0000)
committerfred <fred>
Fri, 29 Nov 1996 14:25:05 +0000 (14:25 +0000)
src/staffcommands.cc [new file with mode: 0644]

diff --git a/src/staffcommands.cc b/src/staffcommands.cc
new file mode 100644 (file)
index 0000000..96647b1
--- /dev/null
@@ -0,0 +1,318 @@
+#include "staffcommands.hh"
+#include "debug.hh"
+#include "parseconstruct.hh"
+
+/*
+  ARG!
+  */
+
+/*
+  maybe it's time for a "narrowing" cursor?
+  */
+PCursor<Command*>
+Staff_commands::first(Real w)
+{
+    PCursor<Command*> pc(*this);    
+    while (pc.ok() && pc->when < w)
+       pc++;
+    if (!pc.ok() || pc->when != w) {
+       Command *c = new Command(w);
+       c->priority = 10000;
+       if (!pc.ok())
+           pc.add(c);
+       else
+           pc.insert(c);
+    }
+
+    return pc;
+}
+/*
+  RETURN: pc->when == w && pc.ok
+ */
+
+PCursor<Command*>
+Staff_commands::last_insertion(Real w)
+{    
+    PCursor<Command*> pc(first(w)), next(pc);    
+    while (next.ok() && next->when == w) {
+       pc=next;
+       next++;
+    }
+    if (pc->priority != -10000) {
+       Command*c = new Command(w);
+       c->priority = -10000;
+       pc.add(c);
+       pc++;
+    }
+        
+    return pc;
+}
+
+/*
+ */
+void
+Staff_commands::add_seq(svec<Command> com, bool checkbreak)
+{
+    if (!com.sz())
+       return;
+    
+    Real when = com[0].when;
+
+    PCursor<Command*> begin(first(when));
+    PCursor<Command*> end(last_insertion(when));
+    if (checkbreak && is_breakable(when)) {
+       if (com[0].priority < 0)
+           while (begin->code != BREAK_END)
+               begin++;
+       else
+           while (end->code != BREAK_PRE)
+               end--;
+    }
+    for (int i = 0; i < com.sz(); i++) {
+       insert_between(com[i], begin, end);
+    }
+}
+
+void
+Staff_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.priority = 5;
+    k.code = BREAK_PRE;
+    seq.add(k);
+    k.priority = 4;
+    k.code = BREAK_MIDDLE;
+    seq.add(k);
+    k.priority = 3;
+    k.code = BREAK_POST;
+    seq.add(k);
+    k.priority = 2;
+    k.code = BREAK_END;
+    seq.add(k);
+
+    add_seq(seq,false);
+}
+
+bool
+Staff_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
+Staff_commands::insert_between(Command victim, PCursor<Command*> firstc,
+                              PCursor<Command*> last)
+{
+    PCursor<Command*> c(firstc+1);
+    assert(last->when==firstc->when&&firstc < last&&last.ok());
+    
+    while (c < last) { 
+       if (c->priority <= victim.priority) {
+           c.insert(new Command(victim));
+           return;
+       }
+       c++;
+    }
+    last.insert(new Command(victim));    
+}
+
+void
+Staff_commands::add_command_to_break(Command pre, Command mid, Command post)
+{
+    Real w = pre.when;
+    assert(w >= 0);
+    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++;
+    assert(l.ok() && l->when ==w && l->code == BREAK_END);
+    
+    insert_between(post, f, l);
+}
+
+void
+Staff_commands::process_add(Command c)
+{
+    bool encapsulate =false;
+    Real w = c.when;
+    assert(w >= 0);
+
+    Command pre(w);
+    Command mid(w);
+    Command post(w);
+
+    if (c.code == INTERPRET)
+    {                          // UGH
+       if (c.args[0] == "BAR") {
+           Command typeset(w); // kut met peren
+           typeset.code = TYPESET;
+           typeset.args = c.args;
+           typeset.priority = 100;
+           process_add(typeset);
+       } else if (c.args[0] == "KEY") {
+           Command typeset(w);
+           typeset.code = TYPESET;
+           typeset.args.add("KEY");
+           typeset.priority = 70;
+           process_add(typeset);
+       } else if (c.args[0] == "CLEF") {
+           Command typeset(w);
+           typeset.code = TYPESET;
+           typeset.args=c.args;
+           typeset.priority = 90;
+           process_add(typeset);
+       } else if (c.args[0] == "METER") {
+           Command typeset(w);
+           typeset.code = TYPESET;
+           typeset.args=c.args;
+           typeset.priority = 40;
+           process_add(typeset);
+           return;
+       }
+    }
+
+    // kut en peer
+    if (c.code == TYPESET) {
+       if (c.args[0] == "BAR") {
+           set_breakable(w);
+           encapsulate  = true;
+           mid = c;
+           pre = c;
+           { /* every line a currentkey. */
+               Command kc(w);
+               kc.code =TYPESET;
+               kc.args.add( "CURRENTKEY");
+               kc.priority = 60;
+               process_add(kc);
+           }
+           { /* every line a currentclef. */
+               Command kc(w);
+               kc.code =TYPESET;
+               kc.args.add( "CURRENTCLEF");
+               kc.priority = 80;
+               process_add(kc);
+           }
+       }else
+       if (c.args[0] == "METER" && is_breakable(w)) {
+           encapsulate = true;
+           mid = c;
+           pre = c;
+           post =c;
+       }else
+       if( c.args[0] == "KEY" && is_breakable(c.when)) {
+           encapsulate = true;
+           mid = c;
+           pre = c;
+           post = c;
+       }else
+       if (c.args[0] == "CURRENTKEY" && is_breakable(w)) {
+           post = c;
+           encapsulate = true;
+       }else
+       if (c.args[0] == "CURRENTCLEF" && is_breakable(w)) {
+           post = c;
+           encapsulate = true;
+       }else
+       if (c.args[0] == "CLEF" && is_breakable(w)) {
+           encapsulate = true;
+           post = c;
+           pre = c;
+           mid = c;                   
+       }
+    }
+    
+    if (encapsulate)
+       add_command_to_break(pre, mid, post);    
+    else {
+       svec<Command> seq;
+       seq.add(c);    
+       add_seq(seq,true);
+    }
+}
+
+/*
+    first and last column should be breakable.
+    Remove any command past the last musical column.
+    */
+void
+Staff_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
+Staff_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
+Staff_commands::print() const
+{
+#ifndef NPRINT
+    for (PCursor<Command*> cc(*this); cc.ok() ; cc++) {
+       cc->print();
+    }
+#endif
+}