]> git.donarmstrong.com Git - lilypond.git/blob - scommands.cc
release: 0.0.5
[lilypond.git] / scommands.cc
1 #include "scommands.hh"
2 #include "debug.hh"
3 #include "parseconstruct.hh"
4
5 /*
6   maybe it's time for a "narrowing" cursor?
7   */
8 PCursor<Command*>
9 Score_commands::first(Real w)
10 {
11     PCursor<Command*> pc(*this);    
12     while (pc.ok() && pc->when < w)
13         pc++;
14     
15      return pc;
16 }
17
18 PCursor<Command*>
19 Score_commands::last_insertion(Real w)
20 {    
21     PCursor<Command*> pc(*this);    
22     while (pc.ok() && pc->when <= w)
23         pc++;
24     return pc;
25 }
26
27 void
28 Score_commands::add_seq(svec<Command> com)
29 {
30     if (!com.sz())
31         return;
32     Real when = com[0].when;
33
34     PCursor<Command*> pc(last_insertion(when));
35     for (int i = 0; i < com.sz(); i++) {
36         Command *c = new Command(com[i]);
37         assert(com[i].when == when);
38         if (!pc.ok())
39             pc.add(c);
40         else
41             pc.insert(c);
42     }
43 }
44
45 void
46 Score_commands::set_breakable(Real when)
47 {
48     bool found_typeset(false);
49     PCursor<Command*> cc = first(when);
50     for (; cc.ok() && cc->when == when; cc++) {
51         if (cc->isbreak())
52             return;
53         if (cc->code == TYPESET)
54             found_typeset=true;
55     }
56
57     assert(!found_typeset);
58     
59     svec<Command> seq;
60     Command k(when);
61     k.code = BREAK_PRE;
62     seq.add(k);
63     k.code = BREAK_MIDDLE;
64     seq.add(k);
65     k.code = BREAK_POST;
66     seq.add(k);
67     k.code = BREAK_END;
68     seq.add(k);
69
70     add_seq(seq);
71 }
72 bool
73 Score_commands::is_breakable(Real w)
74 {
75     PCursor<Command*> cc = first(w);
76     for (; cc.ok() && cc->when == w; cc++) {
77         if (cc->isbreak())
78             return true;
79     }
80     return false;
81 }
82
83 void
84 Score_commands::insert_between(Command victim, PCursor<Command*> firstc,
85                                PCursor<Command*> last)
86 {
87     assert(last->when==firstc->when);
88     PCursor<Command*> c(firstc+1);
89     while (c != last) {         // hmm what if !last.ok()?
90         if (victim.priority > c->priority) {
91             c.insert(new Command(victim));
92             return;
93         }
94         c++;
95     }
96     last.insert(new Command(victim));    
97     
98 }
99 void
100 Score_commands::add_command_to_break(Command pre, Command mid,Command post)
101 {
102     Real w = pre.when;
103     PCursor<Command*> c ( first(w)), f(c), l(c);
104
105     while (!c->isbreak())
106         c++;
107     f = c++;
108     while (!c->isbreak())
109         c++;
110     l = c++;
111     
112     insert_between(pre, f, l);
113     f = l;
114     while (!c->isbreak())
115         c++;
116     l = c++;    
117     insert_between(mid, f, l);
118     f = l;
119     while (!c->isbreak())
120         c++;
121     l = c++;    
122     insert_between(post, f, l);
123     assert(l.ok() && l->when ==w && l->code == BREAK_END);
124 }
125
126 void
127 Score_commands::parser_add(Command *c)
128 {
129     bottom().add(c);
130 }
131
132 void
133 Score_commands::process_add(Command c)
134 {
135     bool encapsulate =false;
136     Real w = c.when;
137     Command pre(w);
138     Command mid(w);
139     Command post(w);
140
141
142     if (c.code == TYPESET) {
143         if (c.args[0] == "BAR") {
144             set_breakable(w);
145             encapsulate  = true;
146             mid = c;
147             pre = c;
148         }
149         if (c.args[0] == "METER" && is_breakable(w)) {
150             encapsulate = true;
151             mid = c;
152             pre = c;
153             post =c;
154         }
155     }
156     
157     if (encapsulate)
158         add_command_to_break(pre, mid, post);    
159     else {
160         svec<Command> seq;
161         seq.add(c);    
162         add_seq(seq);
163     }
164 }
165
166 /*
167     first and last column should be breakable.
168     Remove any command past the last musical column.
169     */
170 void
171 Score_commands::clean(Real l)
172 {
173     assert(l>0);
174     if (!is_breakable(0.0)) {
175         Command c(0.0);
176         c.code = TYPESET;
177         c.args.add("BAR");
178         c.args.add("empty");
179         process_add(c);
180     }
181     
182     PCursor<Command*> bot(bottom());
183
184     while (bot.ok() && bot->when > l) {
185         mtor <<"removing ";
186         bot->print();
187         bot.del();
188         bot = bottom();
189     }
190
191     if (!is_breakable(l)) {
192         Command c(l);
193         c.code = TYPESET;
194         c.args.add("BAR");
195         c.args.add("||");
196         process_add(c);
197     }
198     OK();
199 }
200
201 void
202 Score_commands::OK() const
203 {
204     for (PCursor<Command*> cc(*this); cc.ok() && (cc+1).ok(); cc++) {
205         assert(cc->when <= (cc+1)->when);
206         if (cc->when == (cc+1)->when && !cc->isbreak() && !(cc+1)->isbreak())
207             assert(cc->priority >= (cc+1)->priority);
208     }
209 }
210
211 void
212 Score_commands::print() const
213 {
214     for (PCursor<Command*> cc(*this); cc.ok() ; cc++) {
215         cc->print();
216     }
217 }
218
219 Score_commands*
220 Score_commands::parse(Real l) const
221 {
222     Score_commands*nc = new Score_commands;
223     int beats_per_meas=4;
224     Real measlen = 1.0; // 4/4 by default
225     
226     Real inbar=0.0;
227     int barcount=0;
228     Real wholes=0.0;
229     Real stoppos=0.0;
230
231     {
232         Command c(0.0);
233         c.code = TYPESET;
234         c.args.add("BAR");
235         c.args.add("empty");
236         nc->process_add(c);
237     }
238     for (PCursor<Command*> cc(*this); cc.ok() && cc->when <= l; cc++) {
239         assert (cc->code==INTERPRET);
240         if (cc->args[0] == "METER") {
241             beats_per_meas=cc->args[1].value();
242             int one_beat =cc->args[2].value ();
243             measlen = beats_per_meas/Real(one_beat);
244             nc->process_add(*get_meter_command(wholes,beats_per_meas, one_beat));
245         }
246         if (cc->args[0] == "SKIP") {
247             stoppos = wholes + cc->args[1].value() * measlen + cc->args[2].fvalue();
248             wholes += (measlen-inbar); // skip at least 1 measure
249             barcount++;
250             while (wholes <= stoppos) {
251                 nc->process_add(*get_bar_command(wholes)); // liek
252                 wholes += measlen;
253                 barcount ++;            
254             }
255             wholes = stoppos;
256             //something
257         }
258     }
259     
260     return nc;
261 }