--- /dev/null
+#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
+}