1 /* Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator */
2 /* From input file "lyrics.pas" */
3 
4 
5 #include "p2c.h"
6 
7 
8 #define LYRICS_G
9 #include "lyrics.h"
10 
11 
12 #ifndef CONTROL_H
13 #include "control.h"
14 #endif
15 
16 #ifndef STRINGS_H
17 #include "strings.h"
18 #endif
19 
20 #ifndef MTXLINE_H
21 #include "mtxline.h"
22 #endif
23 
24 #ifndef STATUS_H
25 #include "status.h"
26 #endif
27 
28 #ifndef MULTFILE_H
29 #include "multfile.h"
30 #endif
31 
32 #ifndef FILES_H
33 #include "files.h"
34 #endif
35 
36 #ifndef UTILITY_H
37 #include "utility.h"
38 #endif
39 
40 
41 /* Symbols used in strings of melismatype */
42 
43 #define beam_melisma    '['
44 #define inhibit_beam_melisma  '<'
45 #define slur_melisma    '('
46 #define inhibit_slur_melisma  '{'
47 
48 
49 typedef char other_index;
50 
51 typedef char other_index0;
52 
53 typedef Char melismatype[256];
54 
55 typedef enum {
56   nolyr, haslyr
57 } haslyrtype;
58 typedef enum {
59   normal, aux
60 } auxtype;
61 typedef enum {
62   asbefore, newassign
63 } assigntype;
64 typedef enum {
65   virgin, active
66 } inittype;
67 
68 typedef struct lyrinfotype {
69   short lyr_adjust, slur_level, slur_change, beam_level, beam_change;
70   melismatype melisma;
71   boolean numbered;
72 } lyrinfotype;
73 
74 typedef enum {
75   none_given, global_lyrics, local_lyrics
76 } lyrlinetype;
77 
78 typedef struct lyrtagtype {
79   lyrlinetype lyrsource;
80   haslyrtype has_lyrics;
81   auxtype auxiliary;
82   assigntype new_assign;
83   inittype initialized;
84   short linecount;
85   Char tags[256];
86 } lyrtagtype;
87 
88 
89 #define maxLyrNums      64
90 #define lyrtaglength    40
91 
92 
93 #define lyr_adjust_undef  (-12345)
94 #define interstave      24
95 
96 
97 Static short LyrNum = 0;
98 
99 Static boolean lyrmodealter[maxstaves], oldlyrmodealter[maxstaves];
100 Static lyrtagtype tag[maxvoices], oldtag[maxvoices];
101 Static lyrinfotype lyrinfo[maxvoices];
102 Static Char numberedParagraph[maxLyrNums][lyrtaglength + 1];
103 
104 
105 /* Information flow for verse numbers: at the SetLyrics stage, the first
106 line of each lyrics paragraph is checked for a verse number, and if
107 found, the paragraph tag is remembered.  At the AssignLyrics stage,
108 the first time that paragraph is encountered, the particular voice
109 is marked in lyrinfo as being numbered.  When that voice is later processed,
110 the mark in lyrinfo is interrogated and turned off: if it was on, the
111 mtxVerse pre-TeX string is put into the output. */
112 
hasVerseNumber(voice)113 boolean hasVerseNumber(voice)
114 voice_index voice;
115 {
116   boolean Result;
117 
118   Result = lyrinfo[voice-1].numbered;
119   lyrinfo[voice-1].numbered = false;
120   return Result;
121 }
122 
123 
isNumberedLyricsParagraph(tag)124 Static boolean isNumberedLyricsParagraph(tag)
125 Char *tag;
126 {
127   short i, FORLIM;
128 
129   FORLIM = LyrNum;
130   for (i = 0; i <= FORLIM - 1; i++) {
131     if (!strcmp(tag, numberedParagraph[i]))
132       return true;
133   }
134   return false;
135 }
136 
137 
anyTagNumbered(tags_)138 Static boolean anyTagNumbered(tags_)
139 Char *tags_;
140 {
141   boolean Result;
142   Char tags[256];
143   Char s[256];
144 
145   strcpy(tags, tags_);
146 /* p2c: lyrics.pas: Note: Eliminated unused assignment statement [338] */
147   if (curtail(tags, '}') > 0)
148     delete1(tags, 1);
149   do {
150     GetNextWord(s, tags, ',', dummy);
151     if (*s == '\0')
152       return false;
153     if (isNumberedLyricsParagraph(s))
154       return true;
155   } while (true);
156   return false;
157 }
158 
159 
160 /* Save the tag in the numberedParagraph list, stripping off braces if any */
markNumbered(tag_)161 Static Void markNumbered(tag_)
162 Char *tag_;
163 {
164   Char tag[256];
165 
166   strcpy(tag, tag_);
167   if (LyrNum >= maxLyrNums) {
168     error("Too many numbered lines in the lyrics", !print);
169     return;
170   }
171   LyrNum++;
172   if (curtail(tag, '}') > 0)
173     delete1(tag, 1);
174   strcpy(numberedParagraph[LyrNum-1], tag);
175 /* p2c: lyrics.pas, line 104:
176  * Note: Possible string truncation in assignment [145] */
177 }
178 
179 
180 /* --- end of procedures to keep track of verse numbering --- */
181 
lyricsParagraph()182 Void lyricsParagraph()
183 {
184   Char first[256], w[256];
185   paragraph_index0 l, line;
186   other_index0 i;
187   other_index0 nother = 0;
188   Char other_[10][lyrtaglength + 1];
189   boolean numbered;
190   Char STR1[256], STR3[256];
191   paragraph_index0 FORLIM;
192   Char STR4[256];
193   Char STR5[256];
194 
195   if (!doLyrics())
196     return;
197   NextWord(w, P[0], blank, dummy);
198   l = strlen(w);
199   line_no = orig_line_no[0];
200   if (w[l-1] != '}')
201     strcat(w, "}");
202   GetNextWord(first, w, dummy, '}');
203   while (*w != '\0') {
204     if (w[0] == '=')
205       predelete(w, 1);
206     if (w[0] != '{')
207       sprintf(w, "{%s", strcpy(STR1, w));
208     nother++;
209     GetNextWord(other_[nother-1], w, dummy, '}');
210 /* p2c: lyrics.pas, line 122:
211  * Note: Possible string truncation in assignment [145] */
212   }
213   if (beVerbose()) {
214     printf("---- Paragraph %d starting at line %d has lyrics headed %s",
215 	   paragraph_no, line_no, first);
216     for (i = 0; i <= nother - 1; i++)
217       printf("=%s", other_[i]);
218     putchar('\n');
219   }
220   sprintf(STR5, "%c Paragraph %s line %s bar %s",
221 	  comment, toString(STR1, paragraph_no), toString(STR3, line_no),
222 	  toString(STR4, bar_no));
223   tex3(STR5);
224   sprintf(STR3, "\\mtxSetLyrics%s{%%", first);
225   tex3(STR3);
226   FORLIM = para_len;
227   for (line = 2; line <= FORLIM; line++) {
228     lyrTranslate(P[line-1], &numbered);
229     if (numbered) {
230       if (line > 2)
231 	warning("Verse number not in first line of paragraph treated as lyrics",
232 		print);
233       else {
234 	markNumbered(first);
235 	for (i = 0; i <= nother - 1; i++)
236 	  markNumbered(other_[i]);
237       }
238     }
239     line_no = orig_line_no[line-1];
240     if (strlen(P[line-1]) > max_lyrics_line_length && pmx_preamble_done)
241       error("Lyrics line too long", print);
242     if (pmx_preamble_done) {
243       if (line == 2) {
244 	sprintf(STR3, "\\\\\\:%s", P[line-1]);
245 	put(STR3, putspace);
246       } else {
247 	sprintf(STR3, "\\\\\\ %s", P[line-1]);
248 	put(STR3, putspace);
249       }
250     } else
251       put(P[line-1], putspace);
252     if (line < para_len) {
253       if (pmx_preamble_done)
254 	putLine(" %\\");
255       else
256 	putLine(" %");
257     } else if (pmx_preamble_done)
258       putLine("}\\");
259     else
260       putLine("}");
261   }
262   for (i = 0; i <= nother - 1; i++) {
263     sprintf(STR1, "\\mtxCopyLyrics%s%s", first, other_[i]);
264     tex3(STR1);
265   }
266 }
267 
268 
songraise(Result,voice)269 Static Char *songraise(Result, voice)
270 Char *Result;
271 voice_index voice;
272 {
273   Char s[256];
274   lyrtagtype *WITH;
275   lyrinfotype *WITH1;
276   Char STR1[256], STR3[256];
277 
278   WITH = &tag[voice-1];
279   WITH1 = &lyrinfo[voice-1];
280   if (WITH->initialized == virgin && WITH1->lyr_adjust == 0)
281     return strcpy(Result, "");
282   else {
283     if (WITH->auxiliary == aux)
284       strcpy(s, "Aux");
285     else
286       *s = '\0';
287     sprintf(Result, "\\mtx%sLyricsAdjust{%s}{%s}",
288 	    s, toString(STR1, PMXinstr(voiceStave(voice))),
289 	    toString(STR3, WITH1->lyr_adjust));
290     return Result;
291   }
292 }
293 
294 
lyricsReport(Result,voice)295 Char *lyricsReport(Result, voice)
296 Char *Result;
297 voice_index voice;
298 {
299   Char l[256];
300   lyrtagtype *WITH;
301 
302   WITH = &tag[voice-1];
303   if (WITH->has_lyrics == nolyr ||
304       WITH->lyrsource == none_given && *WITH->tags == '\0')
305     return strcpy(Result, " but has no own lyrics");
306   else {
307     strcpy(l, " with ");
308     if (WITH->auxiliary == aux)
309       strcat(l, "auxiliary ");
310     strcat(l, "lyrics ");
311     if (WITH->lyrsource == local_lyrics)
312       strcat(l, "locally defined as \"");
313     else
314       strcat(l, "labelled \"");
315     sprintf(l + strlen(l), "%s\"", WITH->tags);
316     if (anyTagNumbered(WITH->tags))
317       strcat(l, " with verse numbers");
318     return strcpy(Result, l);
319   }
320 }
321 
322 
initLyrics()323 Void initLyrics()
324 {
325   /* at the start only */
326   stave_index stave;
327   voice_index voice, FORLIM;
328   lyrinfotype *WITH;
329   lyrtagtype *WITH1;
330   stave_index FORLIM1;
331 
332   FORLIM = nvoices;
333   for (voice = 0; voice <= FORLIM - 1; voice++) {
334     WITH = &lyrinfo[voice];
335     WITH1 = &tag[voice];
336     WITH1->has_lyrics = nolyr;
337     WITH->lyr_adjust = lyr_adjust_undef;
338     *WITH->melisma = '\0';
339     WITH->slur_level = 0;
340     WITH->beam_level = 0;
341     WITH1->auxiliary = aux;
342     WITH1->lyrsource = none_given;
343     WITH1->new_assign = asbefore;
344     WITH1->initialized = virgin;
345   }
346   FORLIM1 = nstaves;
347   for (stave = 0; stave <= FORLIM1 - 1; stave++)
348     oldlyrmodealter[stave] = false;
349 }
350 
351 
registerLyrics(voice,w)352 Static Void registerLyrics(voice, w)
353 voice_index voice;
354 Char *w;
355 {
356   lyrtagtype *WITH;
357 
358   WITH = &tag[voice-1];
359   strcpy(oldtag[voice-1].tags, WITH->tags);
360   oldtag[voice-1].lyrsource = WITH->lyrsource;
361   WITH->lyrsource = global_lyrics;
362   switch (strlen(w)) {
363 
364   case 0:
365     *WITH->tags = '\0';
366     break;
367 
368   case 1:
369     fatalerror("M-Tx system error in registerLyrics");
370     break;
371 
372   default:
373     strcpy(WITH->tags, w);
374     break;
375   }
376 }
377 
378 
extractLyrtag(voice,note)379 Void extractLyrtag(voice, note)
380 voice_index voice;
381 Char *note;
382 {
383   /* inline lyrics change */
384   lyrtagtype *WITH;
385   Char STR1[256], STR2[256];
386 
387   WITH = &tag[voice-1];
388   if (WITH->has_lyrics == nolyr) {
389     error3(voice, "Inline lyrics change on no-lyrics line");
390     return;
391   }
392   registerLyrics(voice, note);   /* was: ''); */
393   sprintf(note, "\\mtxAssignLyrics{%s}%s",
394 	  toString(STR1, PMXinstr(voiceStave(voice))), strcpy(STR2, note));
395   if (WITH->auxiliary == aux)
396     sprintf(note, "\\mtxAuxLyr{%s}\\", strcpy(STR2, note));
397   else
398     strcat(note, "\\");
399 }
400 
401 
clearTags()402 Void clearTags()
403 {
404   /* at start of paragraph analyis */
405   voice_index voice, FORLIM;
406   lyrtagtype *WITH;
407 
408   memcpy(oldtag, tag, maxvoices * sizeof(lyrtagtype));
409   FORLIM = nvoices;
410   for (voice = 0; voice <= FORLIM - 1; voice++) {
411     WITH = &tag[voice];
412     WITH->lyrsource = none_given;
413     *WITH->tags = '\0';
414     WITH->linecount = 0;
415   }
416 }
417 
418 
419 #define maxlyrlen       (PMXlinelength - 15)
420 
421 
convertlyrics(lyn,voice,mx)422 Local Void convertlyrics(lyn, voice, mx)
423 Char *lyn;
424 voice_index voice;
425 auxtype mx;
426 {
427   static Char setlyr[256] = "%%\\\\\\mtxSetLyrics";
428   Char btag[256], thistag[256], w[256];
429   boolean numbered;
430   Char STR1[256];
431   lyrtagtype *WITH;
432   Char STR2[256];
433 
434   NextWord(w, lyn, blank, dummy);
435   WITH = &tag[voice-1];
436   if (*w == '\0') {
437     *WITH->tags = '\0';
438     return;
439   }
440   WITH->has_lyrics = haslyr;
441   WITH->auxiliary = mx;
442   if (w[0] == '{') {
443     registerLyrics(voice, w);
444     return;
445   }
446   WITH->lyrsource = local_lyrics;
447   WITH->linecount++;
448   toString(thistag, voice * 10 + WITH->linecount);
449   sprintf(btag, "{%s}", thistag);
450   if (*WITH->tags == '\0')
451     strcpy(WITH->tags, btag);
452   else {
453     WITH->tags[strlen(WITH->tags) - 1] = ',';
454     sprintf(WITH->tags + strlen(WITH->tags), "%s}", thistag);
455   }
456   trim(lyn);
457   lyrTranslate(lyn, &numbered);
458   if (numbered)
459     markNumbered(thistag);
460   if (strlen(lyn) + strlen(btag) > maxlyrlen)
461     sprintf(lyn, "%s%s{\\\n\\\\\\:%s}\\", setlyr, btag, strcpy(STR2, lyn));
462   else
463     sprintf(lyn, "%s%s{%s}\\", setlyr, btag, strcpy(STR1, lyn));
464 }
465 
466 #undef maxlyrlen
467 
468 
maybeLyrics(voice,parline,w_)469 Void maybeLyrics(voice, parline, w_)
470 voice_index voice;
471 paragraph_index parline;
472 Char *w_;
473 {
474   /* during paragraph analysis, parline had L:, already stripped */
475   Char w[256];
476   voice_index0 k;
477 
478   /**  Labelled lyrics line -- */
479   strcpy(w, w_);
480   if (!doLyrics())
481     return;
482   if (strlen(w) == 1 && voice == 0)
483     warning("Lyrics line above top voice should be labelled", print);
484   if (strlen(w) == 1) {   /**  Standard lyrics line -------- */
485     k = voice;
486     if (k == 0)
487       k = 1;
488     convertlyrics(P[parline-1], k, normal);
489     return;
490   }
491   predelete(w, 1);
492   k = findVoice(w);
493   if (k == 0)
494     error("Lyrics line belongs to unknown voice", print);
495   else
496     convertlyrics(P[parline-1], k, aux);
497 }
498 
499 
reviseLyrics()500 Void reviseLyrics()
501 {
502   /* after paragraph analysis */
503   voice_index voice;
504   stave_index stave;
505   voice_index FORLIM;
506   lyrtagtype *WITH;
507   stave_index FORLIM1;
508 
509   FORLIM = nvoices;
510   for (voice = 0; voice <= FORLIM - 1; voice++) {
511     WITH = &tag[voice];
512     if (oldtag[voice].lyrsource == global_lyrics &&
513 	WITH->lyrsource == none_given) {
514       strcpy(WITH->tags, oldtag[voice].tags);
515       WITH->lyrsource = global_lyrics;
516     }
517     WITH->new_assign = (assigntype)(WITH->has_lyrics == haslyr &&
518 				    strcmp(WITH->tags, oldtag[voice].tags));
519     if (*WITH->tags == '\0')
520       WITH->has_lyrics = nolyr;
521     strcpy(oldtag[voice].tags, WITH->tags);
522     oldtag[voice].lyrsource = WITH->lyrsource;
523   }
524   FORLIM1 = nstaves;
525   for (stave = 1; stave <= FORLIM1; stave++) {
526     WITH = &tag[first_on_stave[stave-1] - 1];
527     lyrmodealter[stave-1] = (!aloneOnStave(stave) &&
528 			     WITH->has_lyrics == haslyr &&
529 			     WITH->auxiliary == normal);
530   }
531 }
532 
533 
assignLyrics(stave,lyrassign)534 Void assignLyrics(stave, lyrassign)
535 stave_index stave;
536 Char *lyrassign;
537 {
538   /* at start of new block */
539   Char atag[256], instr[256], l[256];
540   voice_index v1, v2, voice;
541   lyrtagtype *WITH;
542   Char STR2[256];
543   lyrinfotype *WITH1;
544 
545   *lyrassign = '\0';
546   toString(instr, PMXinstr(stave));
547   v1 = first_on_stave[stave-1];
548   v2 = v1 + number_on_stave[stave-1] - 1;
549   /* don't reassign if other voice takes over */
550   if (tag[v1-1].auxiliary == tag[v2-1].auxiliary &&
551       tag[v1-1].has_lyrics != tag[v2-1].has_lyrics) {
552     for (voice = v1 - 1; voice <= v2 - 1; voice++) {
553       WITH = &tag[voice];
554       if (WITH->new_assign == newassign)
555 	WITH->new_assign = (assigntype)WITH->has_lyrics;
556     }
557   }
558   for (voice = v1 - 1; voice <= v2 - 1; voice++)
559     lyrinfo[voice].numbered = false;
560   for (voice = v1; voice <= v2; voice++) {
561     WITH = &tag[voice-1];
562     if (WITH->new_assign == newassign) {
563       strcpy(atag, WITH->tags);
564       if (*atag == '\0')
565 	strcpy(atag, "{}");
566       sprintf(l, "\\mtxAssignLyrics{%s}%s", instr, atag);
567       if (WITH->auxiliary == aux)
568 	sprintf(l, "\\mtxAuxLyr{%s}", strcpy(STR2, l));
569       strcat(lyrassign, l);
570       if (*WITH->tags == '\0')
571 	WITH->has_lyrics = nolyr;
572       if (WITH->has_lyrics == haslyr && WITH->initialized == virgin) {
573 	WITH1 = &lyrinfo[voice-1];
574 	if (WITH->auxiliary == aux && upper(voice))
575 	  WITH1->lyr_adjust = interstave;
576 	else
577 	  WITH1->lyr_adjust = 0;
578 	strcat(lyrassign, songraise(STR2, voice));
579 	WITH->initialized = active;
580       }
581       if (anyTagNumbered(atag))
582 	lyrinfo[voice-1].numbered = true;
583     }
584   }
585   if (lyrmodealter[stave-1] == oldlyrmodealter[stave-1])
586     return;
587   if (lyrmodealter[stave-1])
588     sprintf(lyrassign + strlen(lyrassign), "\\mtxLyrModeAlter{%s}", instr);
589   else
590     sprintf(lyrassign + strlen(lyrassign), "\\mtxLyrModeNormal{%s}", instr);
591   oldlyrmodealter[stave-1] = lyrmodealter[stave-1];
592 }
593 
594 
lyricsAdjust(voice,note)595 Void lyricsAdjust(voice, note)
596 voice_index voice;
597 Char *note;
598 {
599   /* inline at-word */
600   short adj;
601   boolean force, put_above, put_below;
602   lyrinfotype *WITH;
603   lyrtagtype *WITH1;
604   Char STR2[256];
605 
606   WITH = &lyrinfo[voice-1];
607   WITH1 = &tag[voice-1];
608   predelete(note, 1);
609   force = (note[0] == '=');
610   if (force)
611     predelete(note, 1);
612   put_above = (note[0] == '^');
613   if (put_above)
614     predelete(note, 1);
615   put_below = (note[0] == 'v');
616   if (put_below)
617     predelete(note, 1);
618   if (*note != '\0')
619     getNum(note, &adj);
620   else
621     adj = 0;
622   if (WITH1->has_lyrics == nolyr) {
623     *note = '\0';
624     return;
625   }
626   if (put_above)
627     WITH->lyr_adjust = interstave;
628   else if (put_below)
629     WITH->lyr_adjust = 0;
630   if (force)
631     WITH->lyr_adjust = adj;
632   else
633     WITH->lyr_adjust += adj;
634   songraise(note, voice);
635   if (*note != '\0')
636     sprintf(note, "\\\\%s\\", strcpy(STR2, note));
637 }
638 
639 
lyrTranslate(P,numbered)640 Void lyrTranslate(P, numbered)
641 Char *P;
642 boolean *numbered;
643 {   /* Test for starting number */
644   short k, l, number;
645   Char Q[256], w[256];
646 
647   NextWord(w, P, blank, dummy);
648   *numbered = false;
649   if (endsWith(w, ".")) {
650     getNum(w, &number);
651     *numbered = (number != 0);
652   }
653   /*Translate lyrics link */
654   *Q = '\0';
655   l = strlen(P);
656   for (k = 1; k <= l - 1; k++) {
657     if (P[k-1] != '_' || P[k] == '_' || P[k] == ' ' || pos1(P[k], digits) > 0)
658       sprintf(Q + strlen(Q), "%c", P[k-1]);
659     else if (k > 1 && P[k-2] == '\\')
660       strcat(Q, "mtxLowLyrlink ");
661     else
662       strcat(Q, "\\mtxLyrlink ");
663   }
664   sprintf(Q + strlen(Q), "%c", P[l-1]);
665   strcpy(P, Q);
666 }
667 
668 
669 typedef enum {
670   beam, slur
671 } melismaEnd;
672 
673 
removeLast(s,t)674 Static Char removeLast(s, t)
675 Char *s;
676 Char *t;
677 {
678   Char Result;
679   short i, l;
680 
681   l = strlen(s);
682   for (i = l; i >= 1; i--) {
683     if (pos1(s[i-1], t) > 0) {
684       Result = s[i-1];
685       delete1(s, i);
686       return Result;
687     }
688   }
689   return dummy;
690 }
691 
692 
OpenMelisma(s)693 Static boolean OpenMelisma(s)
694 Char *s;
695 {
696   return (pos1(slur_melisma, s) > 0 || pos1(beam_melisma, s) > 0);
697 }
698 
699 
700 /* Local variables for getSyllable: */
701 struct LOC_getSyllable {
702   voice_index voice;
703   boolean BM, EM;
704 } ;
705 
startMelismas(t,LINK)706 Local Void startMelismas(t, LINK)
707 Char *t;
708 struct LOC_getSyllable *LINK;
709 {
710   boolean open_before, open_now;
711   short i, k;
712   lyrinfotype *WITH;
713 
714   k = strlen(t);
715   for (i = 0; i <= k - 1; i++) {
716     WITH = &lyrinfo[LINK->voice-1];
717     open_before = OpenMelisma(WITH->melisma);
718     sprintf(WITH->melisma + strlen(WITH->melisma), "%c", t[i]);
719     open_now = OpenMelisma(WITH->melisma);
720     LINK->BM = (LINK->BM || open_now && !open_before);
721   }
722 }
723 
endMelisma(voice,LINK)724 Local boolean endMelisma(voice, LINK)
725 short voice;
726 struct LOC_getSyllable *LINK;
727 {
728   Char found;
729   short i;
730   short count[2];
731   melismaEnd t;
732   short FORLIM1;
733   lyrinfotype *WITH;
734   Char STR1[4];
735 
736   LINK->EM = false;
737   count[(long)slur] = -lyrinfo[voice-1].slur_change;
738   count[(long)beam] = -lyrinfo[voice-1].beam_change;
739   for (t = beam; (long)t <= (long)slur; t = (melismaEnd)((long)t + 1)) {
740     FORLIM1 = count[(long)t];
741     for (i = 1; i <= FORLIM1; i++) {
742       WITH = &lyrinfo[voice-1];
743       switch (t) {
744 
745       case slur:
746 	sprintf(STR1, "%c%c", slur_melisma, inhibit_slur_melisma);
747 	found = removeLast(WITH->melisma, STR1);
748 	break;
749 
750       case beam:
751 	sprintf(STR1, "%c%c", beam_melisma, inhibit_beam_melisma);
752 	found = removeLast(WITH->melisma, STR1);
753 	break;
754       }
755       if (found == dummy)
756 	error3(voice, "Ending a melisma that was never started");
757       LINK->EM = (LINK->EM ||
758 	  (!OpenMelisma(WITH->melisma) &&
759 	   pos1(found, (sprintf(STR1, "%c%c", slur_melisma, beam_melisma),
760 			STR1)) > 0));
761     }
762   }
763   return LINK->EM;
764 }
765 
startSlurMelisma(voice,LINK)766 Local Void startSlurMelisma(voice, LINK)
767 voice_index voice;
768 struct LOC_getSyllable *LINK;
769 {
770   static Char start[2] = {
771     slur_melisma, inhibit_slur_melisma
772   };
773 
774   Char slurs[256];
775   short k, FORLIM;
776   Char STR1[256];
777 
778   *slurs = '\0';
779   FORLIM = lyrinfo[voice-1].slur_change;
780   for (k = 1; k <= FORLIM; k++)
781     sprintf(slurs, "%c%s",
782 	    start[noSlurMelisma(voice, 1 - k)], strcpy(STR1, slurs));
783   startMelismas(slurs, LINK);
784 }
785 
startBeamMelisma(voice,LINK)786 Local Void startBeamMelisma(voice, LINK)
787 voice_index voice;
788 struct LOC_getSyllable *LINK;
789 {
790   static Char start[2] = {
791     beam_melisma, inhibit_beam_melisma
792   };
793 
794   Char beams[256];
795   short k, FORLIM;
796   Char STR1[256];
797 
798   *beams = '\0';
799   FORLIM = lyrinfo[voice-1].beam_change;
800   for (k = 1; k <= FORLIM; k++)
801     sprintf(beams, "%c%s", start[noBeamMelisma(voice)], strcpy(STR1, beams));
802   startMelismas(beams, LINK);
803 }
804 
startMelisma(voice,LINK)805 Local boolean startMelisma(voice, LINK)
806 short voice;
807 struct LOC_getSyllable *LINK;
808 {
809   LINK->BM = false;
810   startSlurMelisma(voice, LINK);
811   startBeamMelisma(voice, LINK);
812   return LINK->BM;
813 }
814 
815 
816 /* Append mtxBM or mtxEM to pretex when appropriate */
getSyllable(voice_,pretex)817 Void getSyllable(voice_, pretex)
818 voice_index voice_;
819 Char *pretex;
820 {
821   struct LOC_getSyllable V;
822   short t;
823   lyrtagtype *WITH;
824   lyrinfotype *WITH1;
825 
826   V.voice = voice_;
827   WITH = &tag[V.voice-1];
828   WITH1 = &lyrinfo[V.voice-1];
829   if (WITH->has_lyrics != haslyr)
830     return;
831   t = WITH1->slur_level;
832   WITH1->slur_level = slurLevel(V.voice);
833   WITH1->slur_change = WITH1->slur_level - t;
834   t = WITH1->beam_level;
835   WITH1->beam_level = beamLevel(V.voice);
836   WITH1->beam_change = WITH1->beam_level - t;
837   if (startMelisma(V.voice, &V)) {
838     if (WITH->auxiliary == aux)
839       strcat(pretex, "\\mtxAuxBM");
840     else
841       strcat(pretex, "\\mtxBM");
842   }
843   if (!endMelisma(V.voice, &V))
844     return;
845   if (WITH->auxiliary == aux)
846     strcat(pretex, "\\mtxAuxEM");
847   else
848     strcat(pretex, "\\mtxEM");
849 }
850 
851 
getSyllable1(voice,pretex)852 Static Void getSyllable1(voice, pretex)
853 voice_index voice;
854 Char *pretex;
855 {
856   lyrinfotype *WITH;
857 
858   WITH = &lyrinfo[voice-1];
859   printf("voice=%d, slurchange=%d, melisma=%s, beamchange=%d\n",
860 	 voice, WITH->slur_change, WITH->melisma, WITH->beam_change);
861   getSyllable1(voice, pretex);
862   if (*pretex != '\0')
863     printf("pretex = %s\n", pretex);
864 }
865 
866 
867 
868 
869 /* End. */
870