chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / undrscre.c
1 /* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003 by Arkkra Enterprises */
2 /* All rights reserved */
3
4 /* This file contains functions that deal with
5  * extending underscores and dashes on lyric syllables. 
6  */
7
8 #include "defines.h"
9 #include "structs.h"
10 #include "globals.h"
11
12 static double end_dashes P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
13                 int verse, int place, int *carryover_p));
14 static double end_underscore P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
15                 int verse, int place, int *carryover_p));
16 static double endx P((struct GRPSYL *last_grp_p, double end));
17 static int has_above_lyr P((struct MAINLL *mll_p, RATIONAL begin_time,
18                 struct GRPSYL *group_p, int verse));
19 static int voice_is_above P((int v1, int v2));
20 static struct GRPSYL *find_verse_place P((struct STAFF *staff_p,
21                 int verse, int place));
22 static RATIONAL default_end P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
23                 RATIONAL start_time, double *end_p));
24 static int bar_ends_extender P((struct BAR *bar_p, struct MAINLL *mll_p,
25                 int staffno, int verse, int place,
26                 struct GRPSYL **nextsyl_p_p));
27 static void pr_extender P((int ch, double start, double end, double y,
28                 int font, int size));
29 static void insert_carryover_syllable P((struct MAINLL *mll_p, int staffno,
30                 int sylplace, int verseno, char *dash_or_underscore,
31                 int font, int size));
32 static void add_syllable P((struct STAFF *staff_p, int sylplace, int verseno,
33                 char *dash_or_underscore, int font, int size,
34                 double begin_x, struct CHORD *chord_p));
35 static void stitch_syl_into_chord P((struct CHORD *chord_p,
36                 struct GRPSYL *syl_gs_p));
37 \f
38
39 /* This function is called on lyric syllables in two cases:
40  *      1) During placement phase to determine if an extender needs to
41  *      be carried over to a following staff. In this case, really_print
42  *      will be NO. (The easiest way to see if an extender needs to carry
43  *      over is to pretend to print an extender). The return value will
44  *      be YES if there should be a carryover.
45  *      2) When printing the syllable, to draw an extender after it,
46  *      if appropriate. In this case, really_print will be YES,
47  *      and the return value is meaningless.
48  *
49  * If a syllable ends with a dash, the dash should be placed halfway between
50  * where this syllable ends and the next begins. Or if there is a big space,
51  * multiple dashes should be spread out in that space.  If it ends with an
52  * underscore, then an underline should be drawn from the end of this
53  * syllable to the east edge of the notes in the last chord before
54  * the next syllable for the same staff/verse/place.
55  * But if there is a carryover, this just does the extender up to the
56  * end of the current score; it will get called again on the next score
57  * to continue the extender.
58  * If an underscore is used on a single chord, rather than a mellisma
59  * (which might technically be considered an "incorrect" usage of underscore),
60  * we figure the underscore should be drawn to just before the next syllable,
61  * unless there is a rest earlier. Or if the next syllable begins a measure,
62  * the underscore ends before the bar line, to look better.
63  * If really printing, the dash or underscore is removed
64  * from the end of the string so it won't get printed
65  * with the syllable.
66  */
67
68 int
69 spread_extender(syl_p, mll_p, verse, sylplace, really_print)
70
71 struct GRPSYL *syl_p;   /* current syllable */
72 struct MAINLL *mll_p;   /* which MAINLL struct it's hanging off of */
73 int verse;              /* verse number */
74 int sylplace;           /* PL_ABOVE, etc */
75 int really_print;       /* if YES, actually print, otherwise just return
76                          * whether needs to be carried over to next score */
77
78 {
79         char *syl;              /* to walk through characters of the syllable */
80         int font;
81         int size;
82         double start;           /* dash area or underscore starts here */
83         double end;             /* dash area or underscore ends here */
84         int ch;                 /* current character in syllable */
85         int last_ch = '\0';     /* final character in syllable */
86         int extndr_font;        /* in case user changes font/size after
87                                  * extender, keep track of what font/size the
88                                  * extender was */
89         int extndr_size = -1;
90         char *ch_p;             /* pointer to where - or _ is in string */
91         int carryover;          /* YES if will carry over to next staff */
92
93
94         
95         /* See if there is a dash or underscore at the end of the syllable.
96          * If so, save pointer to it. Note that this may not be the last
97          * byte in the string, because there could be font/size changes
98          * after it. */
99         font = syl_p->syl[0];
100         size = syl_p->syl[1];
101         syl = syl_p->syl + 2;
102
103         /* These two assignments avoid "used without being set" warnings */
104         extndr_font = font;
105         ch_p = syl;
106
107         /* Find last character of syllable */
108         while ( (ch = next_str_char( &syl, &font, &size)) != '\0') {
109 #ifdef EXTCHAR
110                 if ( ( ch == '-' || ch == '_') && ! IS_MUSIC_FONT(font)
111                                         && (font < FONT_XTR) ) {
112 #else
113                 if ( ( ch == '-' || ch == '_') && ! IS_MUSIC_FONT(font) ) {
114 #endif
115                         ch_p = syl - 1;
116                         extndr_font = font;
117                         extndr_size = size;
118                         last_ch = ch;
119                 }
120                 else {
121                         last_ch = '\0';
122                 }
123         }
124
125         /* If there is an extender, handle it */
126         if (last_ch != '\0') {
127                 if ( last_ch == '-') {
128                         end = end_dashes(mll_p, syl_p, verse, sylplace,
129                                                         &carryover);
130                 }
131                 else {
132                         end = end_underscore(mll_p, syl_p, verse, sylplace,
133                                                         &carryover);
134                 }
135
136                 if (really_print == NO) {
137                         return(carryover);
138                 }
139
140                 /* Move the rest of the string
141                  * over the dash or underscore,
142                  * so it won't get printed with the syllable */
143                 do {
144                         *ch_p = *(ch_p + 1);
145                 } while  ( *++ch_p != '\0');
146                 start = syl_p->c[AE];
147
148                 /* procsyls() adjusted the east in certain cases for
149                  * placement purposes. For printing we need to cancel out
150                  * those adjustments. */
151                 if (syl_p->next != 0 && last_ch != '-') {
152                         start -= width(extndr_font, extndr_size, ' ');
153                 }
154                 if (syl_p->next == 0 && last_ch == '-') {
155                         start += width(extndr_font, extndr_size, ' ');
156                 }
157
158                 /* actually print the extender */
159                 pr_extender(last_ch, start, end, syl_p->c[AY],
160                                                 extndr_font, extndr_size);
161         }
162         return(NO);
163 }
164 \f
165
166 /* Given a syllable ending with a dash, and some other info,
167  * return where to end the dash(es). If the dashes carry over
168  * to the following score, this will return a point near the east end of
169  * the current score, after setting *carryover_p to YES.
170  */
171
172 static double
173 end_dashes(mll_p, syl_p, verse, place, carryover_p)
174
175 struct MAINLL *mll_p;   /* points to STAFF containing the syl with dash */
176 struct GRPSYL *syl_p;   /* this is the syllable with dash */
177 int verse;              /* which verse the syl_p is for */
178 int place;              /* a PL_* value for where the lyric is */
179 int *carryover_p;       /* return value, set to YES if there was a carryover */
180
181 {
182         int staffno;
183         struct BAR *lastbar_p;
184
185         staffno = syl_p->staffno;
186         *carryover_p = NO;
187         lastbar_p = 0;  /* will get set to something better before being used */
188         syl_p = syl_p->next;
189
190         do {
191                 /* Go forward looking for another non-space syllable */
192                 if (syl_p != 0) {
193                         for (    ; syl_p != 0; syl_p = syl_p->next) {
194                                 if (syl_p->grpcont != GC_SPACE) {
195                                         /* found it! */
196                                         return(syl_p->c[AW] - Stepsize);
197                                 }
198                         }
199                 }
200
201                 /* No ending syl in current measure. Try the next. */
202                 for (mll_p = mll_p->next; mll_p != 0; mll_p = mll_p->next) {
203                         if (mll_p->str == S_BAR) {
204                                 if (bar_ends_extender(mll_p->u.bar_p,
205                                                 mll_p, staffno, verse,
206                                                 place, 0) == YES) {
207                                         return(mll_p->u.bar_p->c[AW] - Stepsize);
208                                 }
209                                 lastbar_p = mll_p->u.bar_p;
210                         }
211
212                         else if (mll_p->str == S_FEED) {
213                                 /* If this is a feed at the very end of the
214                                  * main list, or one or more blocks follow it,
215                                  * this is not the kind of feed
216                                  * we're looking for. */
217                                 if (mll_p->next == 0 ||
218                                                 mll_p->next->str == S_BLOCKHEAD) {
219                                         continue;
220                                 }
221                                 /* There is a carryover unless the
222                                  * pseudo-bar is something that would end
223                                  * the extender. */
224                                 mll_p = mll_p->next;
225                                 if (mll_p->str != S_CLEFSIG
226                                                 || mll_p->u.clefsig_p->bar_p
227                                                 == 0) {
228                                         if (mll_p->str == S_FEED) {
229                                                 /* Being here means there is
230                                                  * a bug somewhere else,
231                                                  * because the main list rules
232                                                  * are violated. But we can
233                                                  * render such a bug harmless
234                                                  * by continuing here.
235                                                  */
236                                                 continue;
237                                         }
238                                         pfatal("end_dashes found unexpected main list contents after feed");
239                                 }
240                                 if (bar_ends_extender(mll_p->u.clefsig_p->bar_p,
241                                                 mll_p, staffno, verse, place, 0)
242                                                 == NO) {
243                                         *carryover_p = YES;
244                                 }
245                                 return(lastbar_p->c[AW] - Stepsize);
246                         }
247
248                         else if (mll_p->str == S_STAFF
249                                                 && mll_p->u.staff_p->staffno
250                                                 == staffno) {
251                                 syl_p = find_verse_place(mll_p->u.staff_p,
252                                                                 verse, place);
253                                 break;
254                         }
255                 }
256         } while (mll_p != 0);
257
258         /* Fell off end of song. Use final bar */
259         return(lastbar_p->c[AW] - Stepsize);
260 }
261 \f
262
263 /* Given a syllable ending with an underscore, and some other info,
264  * return where to end the underscore. If the underscore carries over
265  * to the following score, this will return a point near the east end of
266  * the current score, after setting *carryover_p to YES.
267  */
268
269 static double
270 end_underscore(mll_p, syl_p, verse, place, carryover_p)
271
272 struct MAINLL *mll_p;   /* points to STAFF containing the syl with underscore */
273 struct GRPSYL *syl_p;   /* this is the syllable with underscore */
274 int verse;              /* which verse the syl_p is for */
275 int place;              /* a PL_* value for where the lyric is */
276 int *carryover_p;       /* return value, set to YES if there was a carryover */
277
278 {
279         struct GRPSYL *current_grp_p[MAXVOICES];/* which group we are
280                                                  * currently dealing with on
281                                                  * each voice */
282         RATIONAL group_time[MAXVOICES];         /* accumulated time value of
283                                                  * groups up to the one we
284                                                  * are currently dealing with */
285         short had_rest[MAXVOICES];              /* YES or NO */
286         RATIONAL current_time;                  /* how far we are in meas */
287         RATIONAL end_time;                      /* where next non-space
288                                                  * syllable is for this
289                                                  * staff/place/verse, if
290                                                  * there is one
291                                                  * in the current measure,
292                                                  * otherwise the end of the
293                                                  * current measure. */
294         struct GRPSYL *last_grp_p;              /* if non-zero, this is the
295                                                  * current candidate group
296                                                  * with which we could
297                                                  * potentially align the
298                                                  * end of the underscore. */
299         double end;                             /* this is how far we will
300                                                  * draw the underscore if we
301                                                  * don't find any reason to
302                                                  * stop it sooner. */
303         struct GRPSYL *grp_p;                   /* walk through GRPSYLs */
304         struct STAFF *staff_p;                  /* next measure's STAFF */
305         struct GRPSYL *nextsyl_p;               /* syl list for same verse/place
306                                                  * in the next measure */
307         RATIONAL grp_end_time;                  /* where a current group ends */
308         
309         int vindex;                             /* voice index */
310         int v;                                  /* voice index */
311         short found_feed;                       /* YES or NO */
312         int staffno;
313
314
315         *carryover_p = NO;      /* assume no carryover for now */
316         staffno = mll_p->u.staff_p->staffno;
317
318         /* Back up from the syllable with underscore to count up time-wise how
319          * far into the measure it is */
320         current_time = Zero;
321         for (grp_p = syl_p->prev; grp_p != 0; grp_p = grp_p->prev) {
322                 current_time = radd(current_time, grp_p->fulltime);
323         }
324                 
325         /* Set a default end time and place.
326          * Most likely, we will discover later we need to stop the underscore
327          * earlier than this, but if the user is using underscore in a strange
328          * way, like on a single long note rather than a melissma,
329          * we'll use this as the default place to end the underscore. */
330         end_time = default_end(mll_p, syl_p, current_time, &end);
331
332         /* We don't yet have any candidate group with which to align
333          * the ending of the underscore. */
334         last_grp_p = 0;
335
336         /* For each voice, if it exists, find the group that contains
337          * the time of the syllable with the underscore, and make that
338          * the "current group" for that voice. If the voice doesn't exist,
339          * set the current group pointer to zero. */
340         staff_p = mll_p->u.staff_p;
341         for (vindex = 0; vindex < MAXVOICES; vindex++) {
342                 group_time[vindex] = Zero;
343                 had_rest[vindex] = NO;
344                 if (staff_p->groups_p[vindex] != 0) {
345                         for (current_grp_p[vindex] = staff_p->groups_p[vindex];
346                                         current_grp_p[vindex] != 0;
347                                         current_grp_p[vindex]
348                                         = current_grp_p[vindex]->next) {
349                                 if (GE(current_time, group_time[vindex]) &&
350                                                 LT(current_time,
351                                                 radd(group_time[vindex],
352                                                 current_grp_p[vindex]->fulltime))) {
353                                         /* This group contains the syl's time */
354
355                                         if (current_grp_p[vindex]->grpcont == GC_REST) {
356                                                 had_rest[vindex] = YES;
357                                         }
358                                         break;
359                                 }
360                                 group_time[vindex] = radd(group_time[vindex],
361                                                 current_grp_p[vindex]->fulltime);
362                         }
363                         if (current_grp_p[vindex] == 0) {
364                                 pfatal("unable to find group containing syl's time");
365                         }
366                 }
367                 else {
368                         /* voice doesn't exist in this measure */
369                         current_grp_p[vindex] = 0;
370                 }
371         }
372
373         for (   ;  ; ) {
374                 /* Most of the time, we use voice 1 to determine where to
375                  * end the underscore. However, if voice 1 has spaces,
376                  * we'll use voice 3 (the "middle" voice), and 
377                  * if that is non-existent or space, we use voice 2.
378                  * If everything is space, we keep going and hope for the
379                  * best. If all else fails, we would end up using the "end"
380                  * value as the default.
381                  * 
382                  * However, if this is a below or between lyric,
383                  * and there exists an above lyric
384                  * during the time we are dealing with,
385                  * we assume voice 1 goes with the above lyric, and the
386                  * below lyric probably goes with voice 2, or possibly voice 3.
387                  * If both those voices exist, it's probably not possible
388                  * to divine which the user wants the lyric associated with
389                  * without reading their mind. But 3 voices on a vocal staff
390                  * is quite unusual, especially with rests in different places,
391                  * so we use voice 2 if it exists and is non-space.
392                  * If that fails, we try 3, then 1, then punt.
393                  * If it is a between lyric, there is a slight chance the user
394                  * really wanted us to use the staff below, but we always
395                  * associate "between" things with the staff above.
396                  * They should use "above" on the next staff instead.
397                  */
398                 vindex = 0;     /* use voice 1 as default */
399                 if (place != PL_ABOVE) {
400                         /* The lyric is below or between.
401                          * Test voices 2, 3, and 1 (indexes 1, 2, 0)
402                          * in that order till we find one that isn't a space,
403                          * and see if there is an above lyric
404                          * during its time. If so, that is the voice to use
405                          * during this time to figure out
406                          * where to end underscore. */
407                         if (current_grp_p[1] != 0 &&
408                                         current_grp_p[1]->grpcont != GC_SPACE &&
409                                         has_above_lyr(mll_p, current_time,
410                                         current_grp_p[1], verse) == YES) {
411                                 vindex = 1;
412                         }
413                         else if (current_grp_p[2] != 0 &&
414                                         current_grp_p[2]->grpcont != GC_SPACE &&
415                                         has_above_lyr(mll_p, current_time,
416                                         current_grp_p[2], verse) == YES) {
417                                 vindex = 2;
418                         }
419                         /* Otherwise we go with the default, voice 1.
420                          * We know voice 1 will always exist. */
421                 }
422
423                 else {          /* place is above */
424                         /* Note that voice 1 always exists, so
425                          * so we don't need to check for null first
426                          * on that voice. */
427                         if (current_grp_p[0]->grpcont != GC_SPACE) {
428                                 vindex = 0;
429                         }
430                         else if (current_grp_p[2] != 0 &&
431                                         current_grp_p[2]->grpcont != GC_SPACE) {
432                                 vindex = 2;
433                         }
434                         else if (current_grp_p[1] != 0 &&
435                                         current_grp_p[1]->grpcont != GC_SPACE) {
436                                 vindex = 1;
437                         }
438                 }
439
440                 /* At this point, we know which voice is most relevant for
441                  * checking if it is time to end the underscore.
442                  * See if the current group in that voice contains the
443                  * time value of the ending syllable. */
444                 if ( GE(end_time, group_time[vindex]) && LT(end_time,
445                                         radd(group_time[vindex],
446                                         current_grp_p[vindex]->fulltime)) ) {
447                         /* We need to end the underscore now. */
448                         return(endx(last_grp_p, end));
449                 }
450
451                 /* If the relevant group is a rest, need to stop here */
452                 if (current_grp_p[vindex]->grpcont == GC_REST) {
453                         return(endx(last_grp_p, current_grp_p[vindex]->c[AW]));
454                 }
455                 else if (current_grp_p[vindex]->grpcont == GC_NOTES) {
456                         /* Save as last known group so far at which we
457                          * could potentially end the underscore. */
458                         last_grp_p = current_grp_p[vindex];
459                 }
460
461                 /* We're done with this group; move to next */
462                 current_time = radd(current_time,
463                                 current_grp_p[vindex]->fulltime);
464
465                 /* Catch up all the voices to the current time */
466                 for (v = 0; v < MAXVOICES; v++) {
467                         if (current_grp_p[v] != 0) {
468                                 grp_end_time = radd(group_time[v],
469                                         current_grp_p[v]->fulltime);
470
471                                 while ( LE(grp_end_time, current_time) ){
472                                         /* Special case. Suppose,
473                                          * as an example, soprano and
474                                          * alto share a staff and the
475                                          * soprano has a long note
476                                          * while the alto has a
477                                          * melissma. The underscore
478                                          * should then go to the
479                                          * last note of the melissma,
480                                          * even though soprano is
481                                          * the reference voice.
482                                          * However, if the alto line
483                                          * had had rests, it's likely
484                                          * it's just accompaniment,
485                                          * not a vocal line, or at
486                                          * least they should have
487                                          * used separate above/below
488                                          * lyrics. 
489                                          * So if this group is below
490                                          * the reference group and
491                                          * hasn't had any rests and
492                                          * is east of our candidate
493                                          * last group, make it the
494                                          * new candidate last group. */
495                                         if (voice_is_above(vindex, v)
496                                           && place != PL_ABOVE
497                                           && had_rest[v] == NO
498                                           && last_grp_p != 0
499                                           && current_grp_p[v]->grpcont
500                                           == GC_NOTES
501                                           && current_grp_p[v]->c[AX]
502                                           > last_grp_p->c[AX]) {
503                                                 last_grp_p = current_grp_p[v];
504                                         }
505
506                                         /* move on to next group */
507                                         current_grp_p[v] =
508                                                 current_grp_p[v]->next;
509                                         if (current_grp_p[v] == 0) {
510                                                 break;
511                                         }
512
513                                         group_time[v] = grp_end_time;
514                                         grp_end_time = radd(
515                                                 group_time[v],
516                                                 current_grp_p[v]->fulltime);
517                                         if (current_grp_p[v]->grpcont
518                                                                 == GC_REST) {
519                                                 had_rest[v] = YES;
520                                         }
521                                 }
522                         }
523                 }
524
525                 /* Are we now at the end of the current measure? */
526                 if (current_grp_p[vindex] == 0) {
527                         /* If there is a feed after this bar,
528                          * we need to see if a carryover is needed.
529                          * If so, we will end this underscore just before
530                          * the bar, and carry it over to the next score.
531                          */
532                         found_feed = NO;
533                         for (mll_p = mll_p->next; mll_p != 0; mll_p = mll_p->next) {
534                                 if (mll_p->str == S_BAR) {
535                                         if (bar_ends_extender(mll_p->u.bar_p, mll_p,
536                                                         syl_p->staffno, verse,
537                                                         place, &nextsyl_p)
538                                                         == YES) {
539                                                 /* It's not clear
540                                                  * where we should stop if
541                                                  * we can't deduce a following
542                                                  * syllable. However,
543                                                  * if we go to the bar line,
544                                                  * the user can always use
545                                                  * a <> syllable to force
546                                                  * an earlier ending if needed,
547                                                  * whereas if we go
548                                                  * with the last group,
549                                                  * there's probably no
550                                                  * reasonable workaround
551                                                  * if that's not what they want,
552                                                  * so use the bar line. */
553                                                 if (nextsyl_p == 0) {
554                                                         return(end);
555                                                 }
556                                                 else if (nextsyl_p->grpcont
557                                                                 == GC_SPACE) {
558                                                         /* "carries over" */
559                                                         return(end);
560                                                 }
561                                                 else {
562                                                         return(endx(last_grp_p, end));
563                                                 }
564                                         }
565                                 }
566                                 else if (mll_p->str == S_FEED) {
567                                         found_feed = YES;
568                                 }
569                                 else if (mll_p->str == S_STAFF &&
570                                                 mll_p->u.staff_p->staffno ==
571                                                 staffno) {
572                                         break;
573                                 }
574                                 else if (mll_p->str == S_SSV) {
575                                         /* if this staff becomes invisible,
576                                          * end the underscore at the last
577                                          * group before that. */
578                                         struct SSV *ssv_p;
579                                         ssv_p = mll_p->u.ssv_p;
580                                         if (ssv_p->context == C_STAFF
581                                                 && ssv_p->staffno == staffno
582                                                 && ssv_p->used[VISIBLE] == YES
583                                                 && ssv_p->visible == NO) {
584                                             return(endx(last_grp_p, end));
585                                         }
586                                 }
587                         }
588                         if (mll_p == 0) {
589                                 /* fell off end of song */
590                                 return(endx(last_grp_p, end));
591                         }
592                         staff_p = mll_p->u.staff_p;
593
594                         /* See if there is a syllable at the same verse/place */
595                         if ((nextsyl_p = find_verse_place(staff_p,
596                                         verse, place)) != 0 &&
597                                         nextsyl_p->grpcont != GC_SPACE) {
598                                 /* There is a syllable at the
599                                  * beginning of the next meas,
600                                  * so we end the underscore,
601                                  * unless it was just a carryover syllable
602                                  * that we added earlier. */
603                                 if (nextsyl_p->syl[2] != '_'
604                                                 || nextsyl_p->syl[3] != '\0') {
605                                         return(endx(last_grp_p, end));
606                                 }
607                         }
608                         if (found_feed == YES) {
609                                 if (staff_p->groups_p[vindex] != 0 &&
610                                                 staff_p->groups_p[vindex]->grpcont == GC_REST) {
611                                         /* next meas begins with a rest,
612                                          * so no need to carry over */
613                                         return(endx(last_grp_p, end));
614                                 }
615                                 /* We need to end the underscore on the
616                                  * current score, and arrange to carry it
617                                  * over on the next score. */
618                                 *carryover_p = YES;
619                                 return(end);
620                         }
621
622         
623                         /* Move to next measure by initing each
624                          * current_grp_p[vindex] to the first group
625                          * in the next measure. */
626                         for (vindex = 0; vindex < MAXVOICES; vindex++) {
627                                 current_grp_p[vindex] = staff_p->groups_p[vindex];
628                                 group_time[vindex] = Zero;
629                                 if (current_grp_p[vindex] != 0 &&
630                                                 current_grp_p[vindex]->grpcont
631                                                 == GC_REST) {
632                                         had_rest[vindex] = YES;
633                                 }
634                         }
635                         end_time = default_end(mll_p,
636                                 find_verse_place(staff_p, verse, place),
637                                 Zero, &end);
638                         current_time = Zero;
639                 }
640         }
641 }
642 \f
643
644 /* If we found a last group where we could end a underscore,
645  * return where the east edge of its notes are,
646  * otherwise return the "end" value as the default.
647  */
648
649 static double
650 endx(last_grp_p, end)
651
652 struct GRPSYL *last_grp_p;      /* if != 0, use east edge of notes of this */
653 double end;                     /* if all else fails, use this */
654
655 {
656         int n;          /* note index */
657         double edge;    /* return value */
658
659
660         if (last_grp_p == 0) {
661                 return(end);
662         }
663
664         if (last_grp_p->grpcont != GC_NOTES) {
665                 /* This should actually never happen with the current code,
666                  * but just in case, we use the east of the group */
667                 return(last_grp_p->c[AE]);
668         }
669
670         /* find east edge of notes, not counting any dots or flags */
671         edge = -1000000.0;      /* init to impossible value */
672         for (n = 0; n < last_grp_p->nnotes; n++) {
673                 if (last_grp_p->notelist[n].c[AE] > edge) {
674                         edge = last_grp_p->notelist[n].c[AE];
675                 }
676         }
677         /* If the edge we calculated is east of the default end, use
678          * the default end, because that is suppose to be the farthest
679          * possible east we can be. This could happen if the user used
680          * <^....> on a lyric to force part of the lyric to encroach
681          * into the previous groups' space.  In that case we need to end
682          * the underscore where the encroaching lyric begins, not where
683          * the last note group ends.
684          */
685         if (edge > end) {
686                 return(end);
687         }
688         return(edge);
689 }
690 \f
691
692 /*
693  * Return YES if there is an above lyrics during the specified time.
694  * We have to use some heuristics.
695  *
696  *      If there is any non-space above lyric for the given verse
697  *      at any point between the begin time
698  *      and the begin time plus the fulltime of the group_p,
699  *      then there is an above lyric.   
700  *
701  *      If there is a rest on voice 1, that implies a rest in an above lyric
702  *      line.
703  *
704  *      If there is lyric space for the duration in question, either
705  *      explicit space, or just no above lyrics at all for the given verse
706  *      in this measure, then we don't know for sure where there are no
707  *      above lyrics, or there is an earlier above lyric for this verse
708  *      that extends into the duration.
709  *      If we find some earlier non-space above lyric
710  *      and it ends with an extender (dash or underscore),
711  *      we say there is an above lyric.
712  *      If there is no such lyric, or the first non-space above lyric
713  *      lyric we come to in backing up does not end with an extender,
714  *      we say there isn't an above lyric.
715  */
716
717 static int
718 has_above_lyr(mll_p, begin_time, group_p, verse)
719
720 struct MAINLL *mll_p;           /* points to syl's STAFF */
721 RATIONAL begin_time;
722 struct GRPSYL *group_p;         /* see if there a lyric above this group */
723 int verse;
724
725 {
726         struct STAFF *staff_p;
727         struct GRPSYL *grp_p;
728         RATIONAL cumm_time;             /* current cummulative time */
729         RATIONAL new_cumm_time;         /* cumm_time + group's fulltime */
730         RATIONAL end_time;              /* begin_time + syl's fulltime */
731         int n;                          /* syllist index */
732         int prev_extends;               /* YES/NO if prev syl has extender */
733
734
735         if (mll_p->str != S_STAFF) {
736                 pfatal("has_above_lyr passed wrong type of struct");
737         }
738
739         staff_p = mll_p->u.staff_p;
740         end_time = radd(begin_time, group_p->fulltime);
741
742         /* Go through syllists for the staff */
743         prev_extends = NO;
744         for (n = 0; n < staff_p->nsyllists; n++) {
745                 if (staff_p->sylplace[n] == PL_ABOVE &&
746                                         staff_p->syls_p[n]->vno == verse) {
747                         cumm_time = Zero;
748                         for (grp_p = staff_p->syls_p[n]; grp_p != 0; grp_p = grp_p->next) {
749                                 new_cumm_time = radd(cumm_time, grp_p->fulltime);
750
751                                 if ( LT(new_cumm_time, begin_time) &&
752                                                 grp_p->grpcont != GC_SPACE) {
753                                         prev_extends = has_extender(grp_p->syl);
754                                 }
755
756                                 /* See if this syllable overlaps the time
757                                  * of the group we are checking against. */
758                                 else if ( (GE(begin_time, cumm_time) &&
759                                                 LT(begin_time, new_cumm_time)) ||
760                                                 (GE(end_time, cumm_time) &&
761                                                 LT(end_time, new_cumm_time)) ) {
762
763                                         /* This is a relevant group. If it isn't
764                                          * a space, then we know there is
765                                          * indeed an above lyric. */
766                                         if (grp_p->grpcont != GC_SPACE) {
767                                                 return(YES);
768                                         }
769                                         if (prev_extends == YES) {
770                                                 /* A syllable
771                                                  * earlier in the measure
772                                                  * is extending into the
773                                                  * duration, so that counts.
774                                                  */
775                                                 return(YES);
776                                         }
777                                 }
778                                 else if (GT(new_cumm_time, end_time)) {
779                                         /* we're past the relevant syl(s) */
780                                         break;
781                                 }
782                                 cumm_time = new_cumm_time;
783                         }
784                         /* We've dealt with the only relevant syl list
785                          * in this measure. */
786                         break;
787                 }
788         }
789
790         /* If there is a rest on voice 1, there is an implicit above
791          * lyric (albeit a pause in the above lyrics). Or at least it hardly
792          * makes sense to use voice 1 for below/between lyrics if voice 1
793          * is a rest but there is another voice below it that isn't.
794          */
795         cumm_time = Zero;
796         for (grp_p = mll_p->u.staff_p->groups_p[0]; grp_p != 0; grp_p = grp_p->next) {
797                 new_cumm_time = radd(cumm_time, grp_p->fulltime);
798                 if ( (GE(begin_time, cumm_time) &&
799                                         LT(begin_time, new_cumm_time)) ||
800                                         (GE(end_time, cumm_time) &&
801                                         LT(end_time, new_cumm_time)) ) {
802                         if (grp_p->grpcont == GC_REST) {
803                                 return(YES);
804                         }
805                 }
806                 cumm_time = new_cumm_time;
807                 if (GT(cumm_time, end_time)) {
808                         /* past the relevant groups */
809                         break;
810                 }
811         }
812
813         /* If we got here, we weren't able to tell for
814          * sure if there is an above lyric, because there
815          * was either implicit or explicit space.
816          * Most likely there is no above lyric,
817          * but there is a slight possibility there is
818          * a lyric holding over into this time period
819          * via a melisma or tied notes from a previous measure.
820          * So we back up looking for such a lyric. If we find an above lyric
821          * that ends with an extender (underscore or dash),
822          * we declare that there is an above lyric.
823          * If we find one without an extender or back up
824          * all the way to the beginning of the song without
825          * finding any above lyric, there is no above lyric here.
826          * But we give up after 20 measures, figuring it's
827          * really unlikely for any melisma or tie to last
828          * that long, especially since any scorefeeds
829          * would cause a syllable to get added. The exact
830          * value of 20 is arbitrary; it just seems like plenty.
831          *
832          * prevgrpsyl doesn't work on syls, just groups,
833          * but by giving it staff_p->groups_p[0] (we
834          * know voice 1 will always exist), it will give
835          * us the mll_p for the staff we need.
836          */
837         for (n = 0; n < 20; n++) {
838                 struct GRPSYL *last_non_space_p;
839
840                 if (prevgrpsyl(mll_p->u.staff_p->groups_p[0],
841                                         &mll_p) == 0) {
842                         /* Got to beginning of song */
843                         return(NO);
844                 }
845
846                 grp_p = find_verse_place(mll_p->u.staff_p, verse, PL_ABOVE);
847
848                 if (grp_p == 0) {
849                         /* No relevant lyrics in this meas */
850                         continue;
851                 }
852
853                 last_non_space_p = 0;
854                 for (  ; grp_p != 0; grp_p = grp_p->next) {
855                         if (grp_p->grpcont != GC_SPACE) {
856                                 last_non_space_p = grp_p;
857                         }
858                 }
859                 if (last_non_space_p != 0) {
860                         /* Found a preceeding syllable */
861                         return(has_extender(last_non_space_p->syl));
862                 }
863         }
864         /* We've backed up far enough that the chances of there actually being
865          * an above lyrics are very, very slim. */
866         return(NO);
867 }
868 \f
869
870 /* Returns YES if voice with index v1 is "above" voice v2; else NO */
871
872 static int
873 voice_is_above(v1, v2)
874
875 int v1;
876 int v2;
877
878 {
879         /* Voice number is one more than its index, so convert index to
880          * number so it's easier to think about */
881         v1++;
882         v2++;
883
884         /* Voice 1 is above voice 2 and 3 */
885         if (v1 == 1) {
886                 return(YES);
887         }
888
889         /* Voice 3 is the "middle" voice and thus "above" voice 2 */
890         if (v1 == 3 && v2 == 2) {
891                 return(YES);
892         }
893
894         return(NO);
895 }
896 \f
897
898 /* Given a STAFF, return the first GRPSYL in the syllable list for the given
899  * verse and place, if one exists. Otherwise return 0.
900  */
901
902 static struct GRPSYL *
903 find_verse_place(staff_p, verse, place)
904
905 struct STAFF *staff_p;
906 int verse;
907 int place;
908
909 {
910         int n;
911
912         for (n = 0; n < staff_p->nsyllists; n++) {
913                 if (staff_p->sylplace[n] == place &&
914                                 staff_p->syls_p[n]->vno == verse) {
915                         return(staff_p->syls_p[n]);
916                 }
917         }
918         return(0);
919 }
920 \f
921
922 /* Given a syl and related info, return the default time and place at which to
923  * end an underscore from that syl, for this measure. If there is a
924  * non-space syl later in the measure, this will be right before that syl,
925  * otherwise right before the bar line.
926  */
927
928 static RATIONAL
929 default_end(mll_p, syl_p, start_time, end_p)
930
931 struct MAINLL *mll_p;           /* the STAFF pointing to the syl */
932 struct GRPSYL *syl_p;           /* start looking from the syl */
933 RATIONAL start_time;            /* syl is already this far into measure */
934 double *end_p;                  /* X value at which to end underscore is
935                                  * returned via this pointer */
936
937 {
938         struct GRPSYL *grp_p;
939         RATIONAL end_time;      /* return value */
940
941         if (syl_p == 0) {
942                 /* No syllable for current verse/place in current measure.
943                  * Time signature may not be up to date, so add up the
944                  * time of voice 1, which we know exists.
945                  */
946                 end_time = start_time;
947                 for (grp_p = mll_p->u.staff_p->groups_p[0]; grp_p != 0;
948                                                         grp_p = grp_p->next) {
949                         end_time = radd(end_time, grp_p->fulltime);
950                 }
951         }
952         else {
953                 /* Go forward in the syl list, finding where the next non-space
954                  * syllable is, if there is one in the current measure,
955                  * otherwise find the end of the measure.
956                  * Save the time and location of this.
957                  */
958                 end_time = radd(start_time, syl_p->fulltime);
959                 for (grp_p = syl_p->next; grp_p != 0; grp_p = grp_p->next) {
960                         if (grp_p->grpcont == GC_SPACE) {
961                                 /* Underscore continues through "space" syls */
962                                 end_time = radd(end_time, grp_p->fulltime);
963                                 continue;
964                         }
965                         else {
966                                 /* We have found the syllable
967                                  * at which the underscore
968                                  * from the previous syllable ends */
969                                 break;
970                         }
971                 }
972         }
973
974         /* If a next syl was found, set end to near its west.
975          * Most likely, we will discover later we need to stop the underscore
976          * earlier than this, but if the user is using underscore in a strange
977          * way, like on a single long note rather than a melissma,
978          * we'll use this as the default place to end the underscore.*/
979         if (grp_p != 0) {
980                 *end_p = grp_p->c[AW] - Stepsize;
981         }
982         else {
983                 /* The ending syllable (if any) is not in the current measure.
984                  * So for now we set the end to near the west of the bar line.
985                  * Note that end_time will have added up to
986                  * the full measure duration in this case.
987                  */
988                 for (  ; mll_p != 0; mll_p = mll_p->next) {
989                         if (mll_p->str == S_BAR) {
990                                 *end_p = mll_p->u.bar_p->c[AW] - Stepsize;
991                                 break;
992                         }
993                 }
994                 if (mll_p == 0) {
995                         pfatal("underscore: failed to find next bar");
996                 }
997         }
998         return(end_time);
999 }
1000 \f
1001
1002 /* Given a bar, see if it is a bar that might force stopping an extender,
1003  * and return YES, if so. If nextsyl_p_p is non-null, it also attempts
1004  * to fill that in with a pointer to the next "logical" syllable.
1005  * (Usually the next syllable, but at the end of a repeat it would
1006  * be the first syllable in the repeated section).
1007  * If it can't figure out the correct syllable, it fills in null.
1008  */
1009
1010 static int
1011 bar_ends_extender(bar_p, mll_p, staffno, verse, place, nextsyl_p_p)
1012
1013 struct BAR *bar_p;
1014 struct MAINLL *mll_p;   /* points to a BAR  or CLEFSIG*/
1015 int staffno;
1016 int verse;
1017 int place;
1018 struct GRPSYL **nextsyl_p_p;    /* If this is non-zero, and we can deduce
1019                                  * the next "logical" syl, the pointed to value
1020                                  * will be updated to point to that next syl,
1021                                  * else will be zero. */
1022                 
1023 {
1024         int bartype;
1025
1026         bartype = bar_p->bartype;
1027         if (bartype == RESTART) {
1028                 /* We shouldn't continue an extender over a restart.
1029                  * The "next" logical measure is probably the
1030                  * target of a D.S. or a D.C.
1031                  * But we don't attempt to parse
1032                  * STUFF strings to know such things.
1033                  * So we say the extender ends here,
1034                  * but we don't know what the "next" measure is.
1035                  */
1036                 if (nextsyl_p_p != 0) {
1037                         *nextsyl_p_p = 0;
1038                 }
1039                 return(YES);
1040         }
1041
1042         if (bartype == REPEATEND || bartype == REPEATBOTH) {
1043                 if (nextsyl_p_p == 0) {
1044                         return(YES);
1045                 }
1046
1047                 /* This ends the extender. The next logical measure
1048                  * is at the beginning of the repeat. */
1049                 for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
1050                         if (mll_p->str == S_BAR &&
1051                                         (mll_p->u.bar_p->bartype
1052                                         == REPEATSTART ||
1053                                         mll_p->u.bar_p->bartype
1054                                         == REPEATBOTH)) {
1055                                 mll_p = mll_p->next;
1056                                 break;
1057                         }
1058                 }
1059                 if (mll_p == 0) {
1060                         /* repeatstart is implicit at beginning of song */
1061                         mll_p = Mainllhc_p;
1062                 }
1063                 for (  ; mll_p != 0; mll_p = mll_p->next) {
1064                         if (mll_p->str == S_BAR) {
1065                                 /* staff doesn't exist in this measure */
1066                                 *nextsyl_p_p = 0;
1067                                 return(YES);
1068                         }
1069                         if (mll_p->str == S_STAFF && mll_p->u.staff_p->staffno
1070                                                 == staffno) {
1071                                 *nextsyl_p_p = find_verse_place(
1072                                                 mll_p->u.staff_p, verse, place);
1073                                 return(YES);
1074                         }
1075                 }
1076         }
1077
1078         if (mll_p->u.bar_p->endingloc == STARTITEM) {
1079                 /* If this is the start of a second or subsequent ending,
1080                  * this ends the extender. This is the case if the previous
1081                  * bar was a STARTITEM on INITEM. But apparently there
1082                  * isn't a repeat ending here, or we would have hit the
1083                  * bartype check for that. So it is too hard to try to deduce
1084                  * the next logical syllable. */
1085                 for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
1086                         if (mll_p->str == S_BAR) {
1087                                 if (mll_p->u.bar_p->endingloc == STARTITEM ||
1088                                                 mll_p->u.bar_p->endingloc
1089                                                 == INITEM) {
1090                                         if (nextsyl_p_p != 0) {
1091                                                 *nextsyl_p_p = 0;
1092                                         }
1093                                         return(YES);
1094                                 }
1095                                 break;
1096                         }
1097                 }
1098         }
1099
1100         return(NO);
1101 }
1102 \f
1103
1104 /* Actually print an extender (dash or underscore) */
1105
1106 static void
1107 pr_extender(ch, start, end, y, font, size)
1108
1109 int ch;         /* dash or underscore */
1110 double start;   /* where to start printing */
1111 double end;     /* where to end printing */
1112 double y;       /* y coordinate */
1113 int font;       /* font to use for dash */
1114 int size;       /* size to use for dash */
1115
1116 {
1117         if (ch == '-') {
1118                 double dashwidth;
1119                 char dashstring[4];
1120
1121                 dashwidth = width(font, size, '-');
1122
1123                 /* generate the internal string format of a dash */
1124                 /* can't use dash_string function here since that also
1125                  * deals with ~ which is okay for stuff but not lyrics */
1126                 dashstring[0] = (char) font;
1127                 dashstring[1] = (char) size;
1128                 dashstring[2] = '-';
1129                 dashstring[3] = '\0';
1130
1131                 if ( (end - start) < (15.0 * dashwidth) ) {
1132                         /* not much space, so find midpoint of
1133                          * available distance and put dash there */
1134                         pr_string(start + ((end - start) / 2.0)
1135                                         - (dashwidth / 2.0),
1136                                         y, dashstring, J_LEFT,
1137                                         (char *) 0, -1);
1138                 }
1139                 else {
1140                         int numdashes;          /* how many dashes to print */
1141                         double spacebetween;    /* between dashes */
1142
1143                         /* Lots of space, so will need to print multiple dashes.
1144                          * Figure out how to spread out */
1145                         numdashes = (int) ((end - start) / (8.0 * dashwidth));
1146                         spacebetween = ((end - start) - (dashwidth * numdashes))
1147                                         / numdashes;
1148                         
1149                         for (  ; numdashes > 0; numdashes--) {
1150                                 pr_string(start +
1151                                         (numdashes - 0.5) * spacebetween
1152                                         + ((numdashes - 1.0) * dashwidth),
1153                                         y, dashstring, J_LEFT,
1154                                         (char *) 0, -1);
1155                         }
1156                 }
1157         }
1158         else {
1159                 /* if long enough to bother drawing underscore, draw it */
1160                 if (end - start > Stepsize) {
1161                         /* Note: line width probably really ought to
1162                          * be scaled based on the lyric size, but unless
1163                          * somebody uses really huge or really tiny lyrics,
1164                          * a normal line width looks good enough,
1165                          * so we just go with that.
1166                          */
1167                         do_linetype(L_NORMAL);
1168                         draw_line(start, y, end, y);
1169                 }
1170         }
1171 }
1172 \f
1173
1174 /* Return YES if last character of syllable is an underscore or dash,
1175  * NO if it isn't.
1176  */
1177
1178 int
1179 has_extender(syl)
1180
1181 char *syl;      /* the syllable to check */
1182
1183 {
1184         switch (last_char(syl)) {
1185
1186         case '_':
1187         case '-':
1188                 return(YES);
1189
1190         default:
1191                 return(NO);
1192         }
1193 }
1194 \f
1195
1196 /* Return last character in a string.
1197  * If last character is a music character,
1198  * or the string is null, return null.
1199  */
1200
1201 int
1202 last_char(str)
1203
1204 char *str;      /* return last character in this string */
1205
1206 {
1207         int font, size;
1208         int ch;                 /* current character in string */
1209         int last_font = FONT_UNKNOWN;   /* font of last character */
1210         int last_ch = '\0';
1211
1212
1213         if (str == (char *) 0) {
1214                 return('\0');
1215         }
1216
1217         font = str[0];
1218         size = str[1];
1219
1220         /* keep track of each character. When we hit
1221          * end of string, return the last character we saw */
1222         for ( str += 2; (ch = next_str_char(&str, &font, &size)) != 0;  ) {
1223                 last_font = font;
1224                 last_ch = ch;
1225         }
1226         /* music characters don't count */
1227         if (IS_MUSIC_FONT(last_font)) {
1228                 return('\0');
1229         }
1230         return (last_ch & 0xff);
1231 }
1232 \f
1233
1234 /* See if an underscore or dash will need to be carried to the following score.
1235  * If so, add an appropriate "syllable" at the beginning of that score */
1236
1237 void
1238 cont_extender(mll_p, sylplace, verseno)
1239
1240 struct MAINLL *mll_p;   /* the syllable is hanging off of this STAFF */
1241 int sylplace;           /* PL_ABOVE, etc */
1242 int verseno;            /* verse number */
1243
1244 {
1245         struct GRPSYL *syl_p;   /* walk through GRPSYL list */
1246         struct GRPSYL *last_non_space_p;
1247         int last_ch;            /* last character of syllable */
1248         int font;               /* of syllable */
1249         int size;               /* of syllable */
1250
1251
1252         if (mll_p->str != S_STAFF) {
1253                 pfatal("cont_extender called with wrong argument");
1254         }
1255
1256         /* Find the actual syl grpsyl that is the last on the score */
1257         syl_p = find_verse_place(mll_p->u.staff_p, verseno, sylplace);
1258
1259         if (syl_p == 0) {
1260                 pfatal("cont_extender called without any syllable");
1261         }
1262
1263         /* Find the final non-space syllable in the list  */
1264         last_non_space_p = 0;
1265         for (  ; syl_p != 0; syl_p = syl_p->next) {
1266                 if (syl_p->grpcont != GC_SPACE) {
1267                         last_non_space_p = syl_p;
1268                 }
1269         }
1270
1271         if (last_non_space_p == 0) {
1272                 pfatal("cont_extender couldn't find non-space syllable");
1273         }
1274
1275         last_ch = last_char(last_non_space_p->syl);
1276         if (last_ch != '-' && last_ch != '_') {
1277                 pfatal("cont_extender called on syl without extender");
1278         }
1279
1280         /* See if will carry over */
1281         if (spread_extender(last_non_space_p, mll_p, verseno, sylplace, NO)
1282                                                                 == YES) {
1283
1284                 /* determine proper font/size of
1285                  * carried over dash/underscore
1286                  * based on font/size at end of syllable */
1287                 end_fontsize(last_non_space_p->syl, &font, &size);
1288
1289                 /* insert the syllable on next score */
1290                 insert_carryover_syllable(mll_p,
1291                                         last_non_space_p->staffno, sylplace,
1292                                         verseno,
1293                                         (last_ch == '-' ? "-" : "_"),
1294                                         font, size);
1295         }
1296 }
1297 \f
1298
1299 /* A dash or underscore needs to be carried over to the following score.
1300  * Search forward for the appropriate STAFF. If there is already a lyric
1301  * there for the sylplace and verseno, if its first syllable is a space,
1302  * change it to a dash or underscore as appropriate. 
1303  * If there is no lyric in that measure for the sylplace and verseno,
1304  * insert a measure long syllable of the appropriate type.
1305  * If there is no STAFF of the proper number after a FEED, assume we are
1306  * at the end of the piece or of visibility of the staff, and do nothing.
1307  * If there is already a syllable, leave it as is.
1308  */
1309
1310
1311 static void
1312 insert_carryover_syllable(mll_p, staffno, sylplace, verseno, dash_or_underscore,
1313                 font, size)
1314
1315 struct MAINLL *mll_p;   /* points to staff info */
1316 int staffno;            /* staff number */
1317 int sylplace;           /* PL_ABOVE, etc */
1318 int verseno;            /* verse number */
1319 char *dash_or_underscore;       /* "-" or "_" */
1320 int font;               /* font and size to use for dash or underscore */
1321 int size;
1322
1323 {
1324         struct STAFF *staff_p;  /* add syllable to this staff */
1325         struct CHORD *chord_p;  /* chord syllables goes with */
1326         int v;                  /* verse index */
1327         float begin_x;          /* where to start carryover syllable */
1328
1329
1330         /* search forward for FEED */
1331         for (   ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
1332                 if (IS_CLEFSIG_FEED(mll_p)) {
1333                         break;
1334                 }
1335         }
1336
1337         if (mll_p == (struct MAINLL *) 0) {
1338                 return;
1339         }
1340
1341         /* The AE coordinates of syllable groups
1342          * have already been set, but we need to have
1343          * this one set for the underscore/dash syllable being added. So deduce
1344          * where it should be using the pseudo-bar */
1345         if ((mll_p = mll_p->next) == (struct MAINLL *) 0) {
1346                 return;
1347         }
1348         if (mll_p->str == S_CLEFSIG) {
1349                 begin_x = mll_p->u.clefsig_p->bar_p->c[AE] + STDPAD;
1350         }
1351         else {
1352                 /* setting begin_x is just to shut up compilers that erroneously
1353                  * think it could be used without being set. */
1354                 begin_x = 0.0;
1355                 pfatal("no clefsig after feed");
1356         }
1357
1358         /* silence compilers that think chord_p might not be set */
1359         chord_p = (struct CHORD *) 0;
1360
1361         /* search forward for STAFF of interest, and save CHORD info */
1362         for ( mll_p = mll_p->next; mll_p != (struct MAINLL *) 0;
1363                                                         mll_p = mll_p->next) {
1364
1365                 if (mll_p->str == S_CHHEAD) {
1366                         chord_p = mll_p->u.chhead_p->ch_p;
1367                 }
1368                 else if (mll_p->str == S_STAFF) {
1369                         if (mll_p->u.staff_p->staffno == staffno) {
1370                                 break;
1371                         }
1372                 }
1373         }
1374
1375         /* see if has syllable of specified place and verse */
1376         if (mll_p != (struct MAINLL *) 0) {
1377
1378                 staff_p = mll_p->u.staff_p;
1379                 for (v = 0; v < staff_p->nsyllists; v++) {
1380
1381                         if (staff_p->sylplace[v] == sylplace &&
1382                                         staff_p->syls_p[v]->vno == verseno) {
1383
1384                                 /* are lyrics in this measure. See if first
1385                                  * syllable is a space. If so, replace with
1386                                  * a dash. Otherwise we are done */
1387                                 if (staff_p->syls_p[v]->syl == (char *) 0) {
1388                                         staff_p->syls_p[v]->syl =
1389                                                 copy_string(dash_or_underscore,
1390                                                                 font, size);
1391                                         /* no longer a "space" syllable */
1392                                         staff_p->syls_p[v]->grpcont = GC_NOTES;
1393                                 }
1394                                 return;
1395                         }
1396                 }
1397
1398                 /* no lyrics in first measure on next score for this
1399                  * verse/place. Need to insert one */
1400                 add_syllable(staff_p, sylplace, verseno,
1401                                         dash_or_underscore, font, size,
1402                                         begin_x, chord_p);
1403         }
1404 }
1405 \f
1406
1407 /* Add a dash or underscore syllable to list of lyrics. Need to alloc new
1408  * space for the sylplace and syls_p arrays, copy the existing data into
1409  * them, adding the new syllable at the proper place (sorted by verseno),
1410  * then free the old arrays */
1411
1412 static void
1413 add_syllable(staff_p, sylplace, verseno, dash_or_underscore, font, size,
1414                 begin_x, chord_p)
1415
1416 struct STAFF *staff_p;          /* add syllable to this staff */
1417 int sylplace;                   /* PL_ABOVE, etc */
1418 int verseno;
1419 char *dash_or_underscore;       /* "-" or "_" */
1420 int font;
1421 int size;
1422 double begin_x;                 /* where syllable is to start */
1423 struct CHORD *chord_p;          /* what chord to attach to */
1424
1425 {
1426         short *new_sylplace;            /* new, expanded sylplace array */
1427         struct GRPSYL **new_syls_p;     /* new, expanded syls_p array */
1428         int v;                          /* verse index */
1429         int insert_index;               /* where to put in new arrays */
1430         int inserted;                   /* 0 if haven't found where to insert
1431                                          * yet, 1 if we have. This is then the
1432                                          * difference between the index of the
1433                                          * original arrays and where the copy
1434                                          * goes in the new arrays. Since it's
1435                                          * used in array subscript calculation
1436                                          * we can't use YES and NO here */
1437
1438         
1439         /* alloc arrays that are one larger than the current arrays */
1440         MALLOCA(short, new_sylplace, staff_p->nsyllists + 1);
1441         MALLOCA(struct GRPSYL *, new_syls_p, staff_p->nsyllists + 1);
1442
1443         /* now copy and insert */
1444         insert_index = staff_p->nsyllists;
1445         for (inserted = v = 0; v < staff_p->nsyllists; v++) {
1446                 if (insert_index > v && staff_p->syls_p[v]->vno > verseno) {
1447                         /* insert here */
1448                         insert_index = v;
1449                         inserted = 1;
1450                 }
1451
1452                 new_sylplace[v + inserted] = staff_p->sylplace[v];
1453                 new_syls_p[v + inserted] = staff_p->syls_p[v];
1454         }
1455
1456         /* alloc and fill in the new GRPSYL */
1457         new_sylplace[insert_index] = (short) sylplace;
1458         new_syls_p[insert_index] = newGRPSYL(GS_SYLLABLE);
1459         new_syls_p[insert_index]->syl = copy_string(dash_or_underscore,
1460                                                         font, size);
1461         new_syls_p[insert_index]->inputlineno = -1;
1462         new_syls_p[insert_index]->basictime = -1;
1463         new_syls_p[insert_index]->is_meas = YES;
1464         new_syls_p[insert_index]->fulltime = Score.time;
1465         new_syls_p[insert_index]->staffno = staff_p->staffno;
1466         new_syls_p[insert_index]->vno = (short) verseno;
1467         /* X coords of normal syllables already set, so have to set for
1468          * this special syllable here */
1469         new_syls_p[insert_index]->c[AE] = begin_x
1470                                 + strwidth(new_syls_p[insert_index]->syl);
1471         new_syls_p[insert_index]->c[AW] = begin_x;
1472         new_syls_p[insert_index]->c[AX] = begin_x;
1473
1474         /* now have one one list of syllables */
1475         (staff_p->nsyllists)++;
1476
1477         /* free old arrays if non-null */
1478         if (staff_p->sylplace != (short *) 0) {
1479                 FREE(staff_p->sylplace);
1480         }
1481         if (staff_p->syls_p != (struct GRPSYL **) 0) {
1482                 FREE(staff_p->syls_p);
1483         }
1484
1485         /* now link up the new arrays */
1486         staff_p->sylplace = new_sylplace;
1487         staff_p->syls_p = new_syls_p;
1488
1489         /* add to appropriate chord */
1490         stitch_syl_into_chord(chord_p, new_syls_p[insert_index]);
1491 }
1492 \f
1493
1494 /* Given a syllable and chord to attach it to, attach it */
1495 /* Strictly speaking, this function probably isn't necessary, since I think
1496  * all use of the CHORD struct has already been done before this function is
1497  * called, but it's probably good to do anyway on general principles, in case
1498  * some day the CHORDs are looked at later */
1499
1500 static void
1501 stitch_syl_into_chord(chord_p, syl_gs_p)
1502
1503 struct CHORD *chord_p;          /* add to this chord */
1504 struct GRPSYL *syl_gs_p;        /* add this syllable */
1505
1506 {
1507         struct GRPSYL *gs_p;    /* walk through chord */
1508
1509
1510         /* go down chord list */
1511         for (gs_p = chord_p->gs_p; gs_p->gs_p != (struct GRPSYL *) 0;
1512                                                         gs_p = gs_p->gs_p) {
1513
1514                 /* if next grpsyl in chord has staffno < staffno of syl to add,
1515                  * keep going */
1516                 if (gs_p->gs_p->staffno < syl_gs_p->staffno) {
1517                         continue;
1518                 }
1519
1520                 /* if next grpsyl in chord had staffno > staffno of syl to add,
1521                  * put it here */
1522                 if (gs_p->gs_p->staffno > syl_gs_p->staffno) {
1523                         /* found where to insert */
1524                         break;
1525                 }
1526
1527                 /* If here, must be same staffno.
1528                  * Keep going until find syllable with larger vno. */
1529                 if (gs_p->gs_p->grpsyl == GS_GROUP) {
1530                         continue;
1531                 }
1532
1533                 if (gs_p->gs_p->vno > syl_gs_p->vno) {
1534                         /* found where to insert */
1535                         break;
1536                 }
1537         }
1538
1539         /* insert syllable */
1540         syl_gs_p->gs_p = gs_p->gs_p;
1541         gs_p->gs_p = syl_gs_p;
1542 }