lilypond-0.0.38
[lilypond.git] / src / scommands.cc
blob2787873adbeda434388a1db5386c3e81aca94244
1 #include "scommands.hh"
2 #include "debug.hh"
3 #include "parseconstruct.hh"
5 /*
6 ARG!
7 */
9 /*
10 maybe it's time for a "narrowing" cursor?
12 PCursor<Command*>
13 Score_commands::first(Real w)
15 PCursor<Command*> pc(*this);
16 while (pc.ok() && pc->when < w)
17 pc++;
18 if (!pc.ok() || pc->when != w) {
19 Command *c = new Command(w);
20 c->priority = 10000;
21 if (!pc.ok())
22 pc.add(c);
23 else
24 pc.insert(c);
27 return pc;
30 RETURN: pc->when == w && pc.ok
33 PCursor<Command*>
34 Score_commands::last_insertion(Real w)
36 PCursor<Command*> pc(first(w)), next(pc);
37 while (next.ok() && next->when == w) {
38 pc=next;
39 next++;
41 if (pc->priority != -10000) {
42 Command*c = new Command(w);
43 c->priority = -10000;
44 pc.add(c);
45 pc++;
48 return pc;
53 void
54 Score_commands::add_seq(svec<Command> com, bool checkbreak)
56 if (!com.sz())
57 return;
59 Real when = com[0].when;
61 PCursor<Command*> begin(first(when));
62 PCursor<Command*> end(last_insertion(when));
63 if (checkbreak && is_breakable(when)) {
64 if (com[0].priority < 0)
65 while (begin->code != BREAK_END)
66 begin++;
67 else
68 while (end->code != BREAK_PRE)
69 end--;
71 for (int i = 0; i < com.sz(); i++) {
72 insert_between(com[i], begin, end);
76 void
77 Score_commands::set_breakable(Real when)
79 bool found_typeset(false);
80 PCursor<Command*> cc = first(when);
81 for (; cc.ok() && cc->when == when; cc++) {
82 if (cc->isbreak())
83 return;
84 if (cc->code == TYPESET)
85 found_typeset=true;
88 assert(!found_typeset);
90 svec<Command> seq;
91 Command k(when);
92 k.priority = 5;
93 k.code = BREAK_PRE;
94 seq.add(k);
95 k.priority = 4;
96 k.code = BREAK_MIDDLE;
97 seq.add(k);
98 k.priority = 3;
99 k.code = BREAK_POST;
100 seq.add(k);
101 k.priority = 2;
102 k.code = BREAK_END;
103 seq.add(k);
105 add_seq(seq,false);
108 bool
109 Score_commands::is_breakable(Real w)
111 PCursor<Command*> cc = first(w);
112 for (; cc.ok() && cc->when == w; cc++) {
113 if (cc->isbreak())
114 return true;
116 return false;
119 void
120 Score_commands::insert_between(Command victim, PCursor<Command*> firstc,
121 PCursor<Command*> last)
123 PCursor<Command*> c(firstc+1);
124 assert(last->when==firstc->when&&firstc < last&&last.ok());
126 while (c < last) {
127 if (c->priority <= victim.priority) {
128 c.insert(new Command(victim));
129 return;
131 c++;
133 last.insert(new Command(victim));
136 void
137 Score_commands::add_command_to_break(Command pre, Command mid, Command post)
139 Real w = pre.when;
140 assert(w >= 0);
141 PCursor<Command*> c ( first(w)), f(c), l(c);
143 while (!c->isbreak())
144 c++;
145 f = c++;
146 while (!c->isbreak())
147 c++;
148 l = c++;
150 insert_between(pre, f, l);
151 f = l;
152 while (!c->isbreak())
153 c++;
154 l = c++;
155 insert_between(mid, f, l);
156 f = l;
157 while (!c->isbreak())
158 c++;
159 l = c++;
160 assert(l.ok() && l->when ==w && l->code == BREAK_END);
162 insert_between(post, f, l);
165 void
166 Score_commands::parser_add(Command *c)
168 bottom().add(c);
171 void
172 Score_commands::process_add(Command c)
174 bool encapsulate =false;
175 Real w = c.when;
176 assert(w >= 0);
178 Command pre(w);
179 Command mid(w);
180 Command post(w);
182 if (c.code == INTERPRET)
183 { // UGH
184 if (c.args[0] == "BAR") {
185 Command typeset(w); // kut met peren
186 typeset.code = TYPESET;
187 typeset.args = c.args;
188 typeset.priority = 100;
189 process_add(typeset);
190 } else if (c.args[0] == "KEY") {
191 Command typeset(w);
192 typeset.code = TYPESET;
193 typeset.args.add("KEY");
194 typeset.priority = 70;
195 process_add(typeset);
196 } else if (c.args[0] == "CLEF") {
197 Command typeset(w);
198 typeset.code = TYPESET;
199 typeset.args=c.args;
200 typeset.priority = 90;
201 process_add(typeset);
205 // kut en peer
206 if (c.code == TYPESET) {
207 if (c.args[0] == "BAR") {
208 set_breakable(w);
209 encapsulate = true;
210 mid = c;
211 pre = c;
212 { /* every line a currentkey. */
213 Command kc(w);
214 kc.code =TYPESET;
215 kc.args.add( "CURRENTKEY");
216 kc.priority = 60;
217 process_add(kc);
219 { /* every line a currentclef. */
220 Command kc(w);
221 kc.code =TYPESET;
222 kc.args.add( "CURRENTCLEF");
223 kc.priority = 80;
224 process_add(kc);
226 }else
227 if (c.args[0] == "METER" && is_breakable(w)) {
228 encapsulate = true;
229 mid = c;
230 pre = c;
231 post =c;
232 }else
233 if( c.args[0] == "KEY" && is_breakable(c.when)) {
234 encapsulate = true;
235 mid = c;
236 pre = c;
237 post = c;
238 }else
239 if (c.args[0] == "CURRENTKEY" && is_breakable(w)) {
240 post = c;
241 encapsulate = true;
242 }else
243 if (c.args[0] == "CURRENTCLEF" && is_breakable(w)) {
244 post = c;
245 encapsulate = true;
246 }else
247 if (c.args[0] == "CLEF" && is_breakable(w)) {
248 encapsulate = true;
249 post = c;
250 pre = c;
251 mid = c;
255 if (encapsulate)
256 add_command_to_break(pre, mid, post);
257 else {
258 svec<Command> seq;
259 seq.add(c);
260 add_seq(seq,true);
265 first and last column should be breakable.
266 Remove any command past the last musical column.
268 void
269 Score_commands::clean(Real l)
271 assert(l>0);
272 if (!is_breakable(0.0)) {
273 Command c(0.0);
274 c.code = TYPESET;
275 c.args.add("BAR");
276 c.args.add("empty");
277 process_add(c);
280 PCursor<Command*> bot(bottom());
282 while (bot.ok() && bot->when > l) {
283 mtor <<"removing ";
284 bot->print();
285 bot.del();
286 bot = bottom();
289 if (!is_breakable(l)) {
290 Command c(l);
291 c.code = TYPESET;
292 c.args.add("BAR");
293 c.args.add("||");
294 process_add(c);
296 OK();
299 void
300 Score_commands::OK() const
302 for (PCursor<Command*> cc(*this); cc.ok() && (cc+1).ok(); cc++) {
303 assert(cc->when <= (cc+1)->when);
304 if (cc->when == (cc+1)->when && !cc->isbreak() && !(cc+1)->isbreak())
305 assert(cc->priority >= (cc+1)->priority);
309 void
310 Score_commands::print() const
312 for (PCursor<Command*> cc(*this); cc.ok() ; cc++) {
313 cc->print();
318 TODO
320 Score_commands*
321 Score_commands::parse(Real l) const
323 Score_commands*nc = new Score_commands;
324 int beats_per_meas=4;
325 Real measlen = 1.0; // 4/4 by default
327 Real inbar=0.0;
328 int barcount=0;
329 Real wholes=0.0;
330 Real stoppos=0.0;
332 { /* all pieces should start with a breakable. */
333 Command c(0.0);
334 c.code = INTERPRET;
335 c.args.add("BAR");
336 c.args.add("empty");
337 nc->process_add(c);
339 for (PCursor<Command*> cc(*this); cc.ok() && cc->when <= l; cc++) {
340 assert (cc->code==INTERPRET);
341 if (cc->args[0] == "METER") {
342 beats_per_meas = cc->args[1].value();
343 int one_beat = cc->args[2].value();
344 measlen = beats_per_meas/Real(one_beat);
345 nc->process_add(*get_meter_command(wholes, beats_per_meas, one_beat));
347 if (cc->args[0] == "KEY"||cc->args[0] == "CLEF") {
348 cc->when = wholes;
349 nc->process_add(**cc);
351 if (cc->args[0] == "SKIP") {
352 stoppos = wholes + cc->args[1].value() * measlen +
353 cc->args[2].fvalue();
354 wholes += (measlen-inbar); // skip at least 1 measure
355 barcount++;
356 while (wholes <= stoppos) {
357 nc->process_add(*get_bar_command(wholes)); // liek
358 wholes += measlen;
359 barcount ++;
361 wholes = stoppos;
362 //something
366 return nc;