chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / utils.c
1
2 /* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
4
5 /* miscellaneous utility functions for music publication program, mostly
6  * for the print phase */
7
8 #include "defines.h"
9 #include "structs.h"
10 #include "globals.h"
11
12 static void grp_octave_adjust P((struct GRPSYL *gs_p, int adj, struct MAINLL *mll_p));
13 static void set_height_blockhead P((struct BLOCKHEAD *blockhead_p, int context,
14                 struct MAINLL *mll_p));
15 static double coord_staffscale P((float *coord_array));
16
17 \f
18
19 /* set _cur location variable to specified value */
20
21 void
22 set_cur(x, y)
23
24 float x, y;     /* x, east, and west get set to x value. y, north and south,
25                  * get set to y value */
26
27 {
28         float *cur_p;   /* coord array for _cur in current context */
29
30
31         /* look up _cur symbol and fill in the values */
32         cur_p = symval("_cur", (float **) 0);
33         cur_p[AX] = cur_p[AE] = cur_p[AW] = x;
34         cur_p[AY] = cur_p[AN] = cur_p[AS] = y;
35 }
36 \f
37
38 /* set the values for location variable _win */
39
40 void
41 set_win(n, s, e, w)
42
43 float n, s, e, w;       /* north, south, east, and west */
44
45 {
46         float *window;  /* coordinate info for _win */
47
48
49         /* look up symbol and fill in values */
50         window = symval("_win", (float **) 0);
51         window[AN] = n;
52         window[AS] = s;
53         window[AE] = e;
54         window[AW] = w;
55         /* set x and y to midpoints of rectangle */
56         window[AY] = s + (n - s)/2.0;
57         window[AX] = w + (e - w)/2.0;
58 }
59 \f
60
61 /* Return width of a bar line. Allow a couple pixels on either side
62  * of the actual line(s) [and dots]. Does not include user padding.
63  * Since an invisbar has no lines or dots, it has zero width.
64  */
65
66 double
67 width_barline(bar_p)
68
69 struct BAR *bar_p;      /* return width of this bar line */
70
71 {
72         if (bar_p == (struct BAR *) 0) {
73                 return(0.0);
74         }
75
76         switch(bar_p->bartype) {
77
78         case SINGLEBAR:
79                 return(7 * STDPAD);
80
81         case DOUBLEBAR:
82                 return(9 * STDPAD);
83
84         case ENDBAR:
85                 return(12 * STDPAD);
86
87         case REPEATSTART:
88         case REPEATEND:
89                 return(16 * STDPAD);
90
91         case REPEATBOTH:
92                 return(19 * STDPAD);
93
94         case RESTART:
95                 return(2.0 * HALF_RESTART_WIDTH);
96
97         case INVISBAR:
98                 return(0.0);
99
100         default:
101                 pfatal("bad bar type");
102                 /*NOTREACHED*/
103                 break;
104         }
105
106         /*NOTREACHED*/
107         return(0.0);
108 }
109 \f
110
111 /* Normally, we want some padding on both sides of a bar line,
112  * but at the end of a staff, we don't want right padding.
113  * This applies either if we are at the right
114  * margin or if the next bar is a restart.
115  * This function returns how much to adjust an end-of-score bar line
116  * eastward to make it at the right edge of the score.
117  */
118
119 double
120 eos_bar_adjust(bar_p)
121
122 struct BAR *bar_p;      /* the bar to adjust */
123
124 {
125         double halfbarwidth;
126
127         halfbarwidth = width_barline(bar_p) / 2.0;
128         switch (bar_p->bartype) {
129         case DOUBLEBAR:
130                 return(halfbarwidth - STDPAD - (W_NORMAL / PPI / 2.0));
131         case SINGLEBAR:
132                 return(halfbarwidth - (W_NORMAL / PPI / 2.0));
133         case REPEATEND:
134                 return(halfbarwidth - (4.0 * STDPAD) - (W_WIDE / PPI /  2.0));
135         case ENDBAR:
136                 return(halfbarwidth - (2.0 * STDPAD) - (W_WIDE / PPI / 2.0));
137         default:
138                 break;
139         }
140         return(0.0);
141 }
142 \f
143
144 /* width of clef, keysig, timesig */
145
146 double
147 width_clefsig(clefsig_p)
148
149 struct CLEFSIG *clefsig_p;      /* return width of this clefsig */
150
151 {
152         /* we just call the routine to print a clefsig, but with
153          * flag to tell it to not really print */
154         return(pr_clefsig((struct MAINLL *) 0, clefsig_p, NO));
155 }
156 \f
157
158 /* translate clef name to clef output character */
159
160 int
161 clefchar(clef)
162
163 int clef;       /* TREBLE, etc */
164
165 {
166         switch(clef) {
167
168         case TREBLE:
169         case TREBLE_8:
170         case FRENCHVIOLIN:
171         case TREBLE_8A:
172                 return(C_GCLEF);
173
174         case BASS:
175                 return(C_FCLEF);
176
177         default:
178                 /* everything else uses the C clef */
179                 return(C_CCLEF);
180         }
181 }
182 \f
183
184 /* Returns width of the given clef in inches in the default size.
185  * If is_small is YES, give width of the 3/4 sized one used in mid-score,
186  * rather than the full-sized used at beginning of line.
187  * Caller must adjust by staffscale if they need that.
188  * No padding is included beyond the padding of the clef music character
189  * itself, so caller needs to add any they deem appropriate for aesthetics.
190  */
191
192 double
193 clefwidth(clef, is_small)
194
195 int clef;       /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
196 int is_small;   /* If YES, assume mid-score clef, not full sized one */
197
198 {
199         return(width(FONT_MUSIC, (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE),
200                                                 clefchar(clef)));
201 }
202 \f
203
204 /* Returns where the given clef's baseline should be
205  * relative to the middle line of the staff, in stepsizes.
206  * (Above the middle line is positive, below is negative).
207  * If north_p and/or south_p are non-null, the relative north/south values
208  * of the clef are returned via the pointers. These will be relative
209  * to the middle line of the staff and  will be in inches
210  * in the default staffscale, using default size
211  * (unless is_small == YES, in which case it will be 3/4 size).
212  * Note that this should not be called with TABCLEF or NOCLEF.
213  */
214
215 int
216 clefvert(clef, is_small, north_p, south_p)
217
218 int clef;       /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
219 int is_small;   /* If YES, assume mid-score clef, not full sized one.
220                  * Note that if both of the following arguments are null,
221                  * this is_small argument's value is actually irrelevent. */
222 float *north_p; /* if non-null, relative north will be returned here */
223 float *south_p; /* if non-null, relative south will be returned here */
224
225 {
226         int steps;      /* relative to middle line, to be returned */
227
228         switch(clef) {
229
230         case TREBLE:
231         case TREBLE_8:
232         case TREBLE_8A:
233                 steps = -2;
234                 break;
235
236         case FRENCHVIOLIN:
237         case SOPRANO:
238                 steps = -4;
239                 break;
240
241         case MEZZOSOPRANO:
242                 steps = -2;
243                 break;
244
245         case ALTO:
246                 steps = 0;
247                 break;
248
249         case TENOR:
250                 steps = 2;
251                 break;
252
253         case BARITONE:
254                 steps = 4;
255                 break;
256
257         case BASS:
258                 steps = 2;
259                 break;
260
261         case TABCLEF:
262         default:
263                 pfatal("clefvert called with invalid clef %d", clef);
264                 /*NOTREACHED*/
265                 steps = 0;              /* shut up bogus compiler warning */
266                 break;
267         }
268
269         /* If caller wants relative north/south values, calculate them */
270         if (north_p != 0 || south_p != 0) {
271                 char muschar;   /* music character to print for the clef */
272                 int clefsize;
273                 char tr8str[4]; /* "8" of treble8 or 8treble */
274                 float value;    /* of north or south */
275
276                 muschar = clefchar(clef);
277                 clefsize = (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE);
278                 tr8str[0] = FONT_TI;
279                 tr8str[1] = 9;
280                 tr8str[2] = '8';
281                 tr8str[3] = '\0';
282                 
283                 if (north_p != 0) {
284                         value = (float) ascent(FONT_MUSIC, clefsize, muschar);
285                         if (clef == TREBLE_8A) {
286                                 value += (float) strheight(tr8str);
287                         }
288                         *north_p = value + (float)(steps * STEPSIZE);
289                 }
290
291                 if (south_p != 0) {
292                         value = (float) descent(FONT_MUSIC, clefsize, muschar);
293                         if (clef == TREBLE_8) {
294                                 value += (float) strheight(tr8str);
295                         }
296                         *south_p = -value + (float)(steps * STEPSIZE);
297                 }
298         }
299
300         return(steps);
301 }
302 \f
303
304 /* Given a BLOCKHEAD, fill in its height. BLOCKHEADs are a bit strange,
305  * in that they are in a separate coordinate space of unknown size.
306  * So we start out assuming it is infinitely thin. Then we check
307  * each string in the list and keep track of the lowest one, by
308  * pretending to go where it would be printed and adding the descent
309  * of the string. At the end, the height must be the page height minus the
310  * lowest, since upwards is positive */
311
312 static void
313 set_height_blockhead(blockhead_p, context, mll_p)
314
315 struct BLOCKHEAD *blockhead_p;  /* which block to get height of */
316 int context;                    /* C_HEADER, etc */
317 struct MAINLL *mll_p;           /* for getting margin overrides */
318
319 {
320         float distance;         /* of headfoot from bottom of page */
321         float lowest;
322         float x_offset;         /* because of justification */
323         float yval;             /* y coordinate value */
324         struct PRINTDATA *pr_p; /* walk through list of things to print */
325         float block_width;      /* page width minus margins */
326         float s_descent;        /* strdescent() of the current string */
327         float extra;            /* how much farther the string descended
328                                  * than would be expected of a normal,
329                                  * single line. */
330         struct MAINLL *rightmargin_mll_p;       /* mll_p to use for
331                                  * finding the right margin */
332
333
334         /* Set _win in this context to zero height at top margin */
335         Context = context;
336         rightmargin_mll_p = (mll_p ? mll_p->next : 0);
337         set_win_coord(blockhead_p->c);
338         set_win(PGHEIGHT - EFF_TOPMARGIN, PGHEIGHT - EFF_TOPMARGIN,
339                 PGWIDTH - eff_rightmargin(rightmargin_mll_p),
340                 eff_leftmargin(mll_p));
341         block_width = PGWIDTH - eff_rightmargin(rightmargin_mll_p) -
342                                                         eff_leftmargin(mll_p);
343
344         if (blockhead_p->printdata_p != (struct PRINTDATA *) 0) {
345                 /* set current to left corner */
346                 set_cur(eff_leftmargin((struct MAINLL *)0),
347                                                 PGHEIGHT - EFF_TOPMARGIN);
348
349                 distance = _Cur[AY];
350
351                 /* Process each item in the list */
352                 for (pr_p = blockhead_p->printdata_p;
353                                 pr_p != (struct PRINTDATA *) 0;
354                                 pr_p = pr_p->next) {
355
356                         /* If this is a paragraph,
357                          * split it into as many lines as needed. */
358                         if (pr_p->justifytype == J_JUSTPARA ||
359                                         pr_p->justifytype == J_RAGPARA) {
360                                 pr_p->string = split_string(pr_p->string,
361                                                                 block_width);
362                         }
363                         pr_p->width = strwidth(pr_p->string);
364                         /* stretch justified paragraphs to full width */
365                         if (pr_p->justifytype == J_JUSTPARA &&
366                                                 pr_p->width < block_width) {
367                                 pr_p->width = block_width;
368                         }
369
370                         /* adjust for justification */
371                         switch (pr_p->justifytype) {
372
373                         case J_RIGHT:
374                                 x_offset = pr_p->width;
375                                 break;
376
377                         case J_CENTER:
378                                 x_offset = pr_p->width / 2.0;
379                                 break;
380
381                         default:
382                                 x_offset = 0.0;
383                                 break;
384                         }
385
386                         /* set current to specified location */
387                         yval = inpc_y (&(pr_p->location), (char *) 0, -1);
388                         set_cur( inpc_x( &(pr_p->location), (char *) 0, -1 )
389                                                         - x_offset, yval);
390
391                         /* if user said to go off of south or y of _win,
392                          * change to equivalent offset off of north of _win.
393                          * because the  south and y could change */
394                         if (pr_p->location.vtype == AS ||
395                                         pr_p->location.vtype == AY) {
396                                 if (pr_p->location.vert_p == blockhead_p->c) {
397                                         pr_p->location.vtype = AN;
398                                         pr_p->location.vsteps = (yval
399                                                 - (PGHEIGHT - EFF_TOPMARGIN)
400                                                 ) / STEPSIZE;
401                                 }
402                         }
403
404                         /* determine lowest descent of current string */
405                         if (pr_p->isPostScript == YES) {
406                                 s_descent = 0.0;
407                         }
408                         else {
409                                 s_descent = strdescent(pr_p->string);
410                         }
411                         lowest = _Cur[AY] - s_descent;
412
413                         /* if lowest of anything found so far, note that */
414                         if ( lowest < distance) {
415                                 distance = lowest;
416                                 set_win(PGHEIGHT - EFF_TOPMARGIN, distance,
417                                         PGWIDTH - eff_rightmargin((struct MAINLL *)0),
418                                         eff_leftmargin((struct MAINLL *)0));
419                         }
420
421                         /* Set to end of string just "printed."
422                          * If the string when down farther than a single line
423                          * add in that extra.
424                          */
425                         if (pr_p->isPostScript == YES) {
426                                 extra = 0.0;
427                         }
428                         else {
429                                 extra = s_descent - fontdescent(pr_p->string[0],
430                                                         pr_p->string[1]);
431                                 if (extra < 0.0) {
432                                         extra = 0.0;
433                                 }
434                         }
435                         set_cur( _Cur[AX] + pr_p->width, _Cur[AY] - extra);
436                 }
437
438                 /* set height to lowest distance encountered */
439                 blockhead_p->height = (PGHEIGHT - distance - EFF_TOPMARGIN);
440
441         }
442         else {
443                 /* empty header/footer */
444                 blockhead_p->height = 0.0;
445         }
446
447         /* if was a footer, now we can set the actual _win coordinates,
448          * by offsetting from bottom of page instead of top */
449         if ( (context == C_FOOTER) || (context == C_FOOT2) ) {
450                 set_win(EFF_BOTMARGIN + blockhead_p->height, EFF_BOTMARGIN,
451                         PGWIDTH - eff_rightmargin((struct MAINLL *)0),
452                         eff_leftmargin((struct MAINLL *)0));
453         }
454         set_win_coord(0);
455 }
456 \f
457
458 /* Calculate the height of all blocks, including headers and footers,
459  * and fill in the height field of the struct. */
460
461 void
462 calc_block_heights()
463
464 {
465         struct MAINLL *mll_p;
466         double topheight = -1.0;        /* if > 0.0, is height of "top" */
467         double botheight = -1.0;        /* if > 0.0, is height of "bottom" */
468
469         debug(2, "calc_block_heights");
470
471         set_height_blockhead(&Header, C_HEADER, 0);
472         set_height_blockhead(&Footer, C_FOOTER, 0);
473         set_height_blockhead(&Header2, C_HEAD2, 0);
474         set_height_blockhead(&Footer2, C_FOOT2, 0);
475
476         /* set main _win to space within margins and header/footer
477          * for first page. */
478         Context = C_MUSIC;
479
480         /* set the size of _page */
481         _Page[AW] = _Page[AS] = 0.0;
482         _Page[AE] = PGWIDTH;
483         _Page[AN] = PGHEIGHT;
484         _Page[AX] = PGWIDTH / 2.0;
485         _Page[AY] = PGHEIGHT / 2.0;
486
487         /* now calculate top/bot and any other blocks in the main list */
488         initstructs();
489         for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
490                 if (mll_p->str == S_SSV) {
491                         /* keep margins up to date */
492                         asgnssv(mll_p->u.ssv_p);
493                 }
494                 else if (mll_p->str == S_FEED) {
495                         if (mll_p->u.feed_p->top_p != 0) {
496                                 set_height_blockhead(mll_p->u.feed_p->top_p,
497                                                 C_TOP, 0);
498                                 if (topheight < 0.0) {
499                                         /* save for setting music _win */
500                                         topheight = mll_p->u.feed_p->top_p->height;
501                                 }
502                         }
503                         if (mll_p->u.feed_p->top2_p != 0) {
504                                 set_height_blockhead(mll_p->u.feed_p->top2_p,
505                                                 C_TOP2, 0);
506                         }
507                         if (mll_p->u.feed_p->bot_p != 0) {
508                                 set_height_blockhead(mll_p->u.feed_p->bot_p,
509                                                 C_BOT, 0);
510                                 if (botheight < 0.0) {
511                                         /* save for setting music _win */
512                                         botheight = mll_p->u.feed_p->bot_p->height;
513                                 }
514                         }
515                         if (mll_p->u.feed_p->bot2_p != 0) {
516                                 set_height_blockhead(mll_p->u.feed_p->bot2_p,
517                                                 C_BOT2, 0);
518                         }
519                 }
520                 else if (mll_p->str == S_BLOCKHEAD) {
521                         set_height_blockhead(mll_p->u.blockhead_p,
522                                                 C_BLOCK, mll_p);
523                 }
524         }
525
526         set_win(PGHEIGHT - EFF_TOPMARGIN - Header.height
527                         - (topheight > 0.0 ? topheight : 0.0),
528                         EFF_BOTMARGIN + Footer.height
529                         + (botheight > 0.0 ? botheight : 0.0),
530                         PGWIDTH - eff_rightmargin((struct MAINLL *)0),
531                         eff_leftmargin((struct MAINLL *)0));
532 }
533 \f
534
535 /* return number of beams or flags to use for a given basic time */
536
537 int
538 numbeams(btime)
539
540 int btime;      /* basic time of note to be checked */
541
542 {
543         int n;
544
545         /* no beams for long notes */
546         if (btime <= 4) {
547                 return(0);
548         }
549
550         /* number of beams is equal to the number of bits 4 has to be
551          * shifted left in order to equal the given basic time */
552         for (n = 1; (4 << n) <= MAXBASICTIME; n++) {
553                 if (btime == (4 << n)) {
554                         return(n);
555                 }
556         }
557         return(0);
558 }
559 \f
560
561 /* given an accidental (#, &, x, B, n) return its music character
562  * C_SHARP, etc of the proper size. If not a valid accidental,
563  * return 0 */
564
565 int acc2char(acc)
566
567 int acc;
568
569
570 {
571         switch (acc) {
572
573         case '&':
574                 return(C_FLAT);
575         case '#':
576                 return(C_SHARP);
577         case 'n':
578                 return(C_NAT);
579         case 'x':
580                 return(C_DBLSHARP);
581         case 'B':
582                 return(C_DBLFLAT);
583         default:
584                 /* no accidental */
585                 return(0);
586         }
587 }
588 \f
589
590 /* get the absolute x and y values for an INPCOORD */
591 /* get the proper one of the coordinates of the specified location, and
592  * add in any offsets */
593
594 double
595 inpc_x(inpcoord_p, fname, lineno)
596
597 struct INPCOORD *inpcoord_p;    /* return the x value of this inpcoord */
598 char *fname;                    /* filename, for error message */
599 int lineno;                     /* for error message */
600
601 {
602         double retval;
603
604
605         /* if hor_p is null, then this is an absolute coord, rather
606          * than relative to some variable */
607         if (inpcoord_p->hor_p == (float *) 0) {
608                 if (inpcoord_p->counts != 0.0) {
609                         /* parser should have blocked this case */
610                         pfatal("can't specify time offset if no variable specified");
611                 }
612                 retval = inpcoord_p->hsteps * STEPSIZE;
613         }
614
615         /* X location is the x, e, or w value of the specified location
616          * variable, plus any offset plus any time offset */
617         else {
618                 retval = inpcoord_p->hor_p [ inpcoord_p->htype ]
619                 + inpcoord_p->hsteps * STEPSIZE
620                 * coord_staffscale(inpcoord_p->hor_p)
621                 + ( inpcoord_p->counts * inpcoord_p->hor_p [INCHPERWHOLE] /
622                 (double) Score.timeden );
623         }
624
625         if (retval < 0.0 || retval > PGWIDTH) {
626                 if (lineno > 0 && fname != (char *) 0) {
627                         l_warning(fname, lineno,
628                                 "x value of %f is off the page", retval);
629                 }
630         }
631         return(retval);
632 }
633 \f
634
635 /* given an inpcoord, return its y coordinate */
636
637 double
638 inpc_y(inpcoord_p, fname, lineno)
639
640 struct INPCOORD *inpcoord_p;    /* return y value of this inpcoord */
641 char *fname;                    /* filename, for error message */
642 int lineno;                     /* for error message */
643
644 {
645         double retval;
646
647
648         /* if vert_p is null, then this is absolute rather than relative */
649         if ( inpcoord_p->vert_p == (float *) 0) {
650                 retval = inpcoord_p->vsteps * STEPSIZE;
651         }
652
653         /* Y value is y, n, or s value of specified location variable
654          * plus any vertical offset plus any vsteps offset */
655         else {
656                 retval = inpcoord_p->vert_p [ inpcoord_p->vtype ]
657                                 + (inpcoord_p->vsteps * STEPSIZE
658                                 * coord_staffscale(inpcoord_p->vert_p));
659         }
660
661         if (retval < 0.0 || retval > PGHEIGHT) {
662                 if (lineno > 0 && fname != (char *) 0) {
663                         l_warning(fname, lineno,
664                                 "y value of %f is off the page", retval);
665                 }
666         }
667         return(retval);
668 }
669 \f
670
671 /* Given an INPCOORD, return the appropriate staffscale value. Look
672  * up which staff, if any, the INPCOORD is associated with, and then get
673  * the staffscale out of the SSVs.
674  */
675
676 static double
677 coord_staffscale(coord_array)
678
679 float *coord_array;
680
681 {
682         struct COORD_INFO *coord_info_p;
683
684
685         /* figure out what staffscale value to use, based on
686          * which staff the coordinate is associated with */
687         if ((coord_info_p = find_coord(coord_array))
688                                         != (struct COORD_INFO *) 0 &&
689                                         coord_info_p->staffno != 0) {
690                 return(svpath(coord_info_p->staffno, STAFFSCALE)->staffscale);
691         }
692         else {
693                 return(1.0);
694         }
695 }
696 \f
697
698 /* return the y coordinate of the end of a note stem */
699 /* (the end farthest from the note head) */
700
701 double
702 find_y_stem(gs_p)
703
704 struct GRPSYL *gs_p;    /* which group to get the stem of */
705
706 {
707         /* error checks */
708         if (gs_p == (struct GRPSYL *) 0) {
709                 pfatal("null group passed to find_y_stem");
710         }
711
712         if (gs_p->nnotes == 0) {
713                 pfatal("group with no notes passed to find_y_stem (from line %d, grpcont %d)",
714                                 gs_p->inputlineno, gs_p->grpcont);
715         }
716
717         /* if stem is up, start at bottom note, if down at top */
718         if (gs_p->stemdir == UP) {
719                 return(gs_p->notelist[ gs_p->nnotes - 1].c[AY] + gs_p->stemlen);
720         }
721         else {
722                 return(gs_p->notelist[0].c[AY] - gs_p->stemlen);
723         }
724 }
725 \f
726
727 /* return x coordinate of a note stem */
728
729 double
730 find_x_stem(gs_p)
731
732 struct GRPSYL *gs_p;    /* return x of stem of this group */
733
734 {
735         double stem_adjust;     /* to overlap the note head */
736
737         if ( gs_p == (struct GRPSYL *) 0) {
738                 pfatal("bad group passed to find_x_stem");
739         }
740
741         /* if called with something longer than a half note, then there
742          * is no real stem. We must be being called for printing slashes,
743          * so in that case, the x of the "stem" is the x of the group */
744         if (gs_p->basictime < 2) {
745                 return(gs_p->c[AX]);
746         }
747
748         /* move stem by half of stem width so edge lines up with edge of note */
749         stem_adjust = W_NORMAL / PPI / 2.0;
750         if (gs_p->stemdir == UP) {
751                 stem_adjust = -stem_adjust;
752         }
753         return(gs_p->c[AX] + (gs_p->stemx + stem_adjust) * Staffscale);
754 }
755 \f
756
757 /* return the width of a key signature in inches */
758
759 double
760 width_keysig(sharps, naturals)
761
762 int sharps;     /* how many sharps to print, or if negative, how many flats. */
763 int naturals;   /* how many naturals to print for canceling previous key */
764
765 {
766         double total_width = 0.0;
767         int size;
768
769         /* In keysig, things are drawn closer together than
770          * in other places, so to get the total width, we first
771          * multiply the width of the sharp, flat, or natural character
772          * by the number of times it is to be printed, then subtract off
773          * two points for each character printed, except for naturals,
774          * which are only jammed together by one point. */
775         
776         size = adj_size(DFLT_SIZE, Staffscale, (char *) 0, -1);
777         if (sharps >= 1) {
778                 total_width = (width(FONT_MUSIC, size, C_SHARP) - 2.0 * Stdpad)
779                                         * sharps;
780         }
781         else if (sharps <= -1) {
782                 /* negative sharps are flats */
783                 total_width = (width(FONT_MUSIC, size, C_FLAT) - 2.0 * Stdpad)
784                                         * -sharps;
785         }
786         if (naturals != 0) {
787                 total_width += (width(FONT_MUSIC, size, C_NAT) - Stdpad)
788                                 * abs(naturals) + 3.0 * Stdpad;
789         }
790         return(total_width);
791 }
792 \f
793 /*
794  * Name:        nextgrpsyl()
795  *
796  * Abstract:    Find next GRPSYL in this voice (same measure or not).
797  *
798  * Returns:     Pointer to the GRPSYL, or 0 if none.
799  *
800  * Description: This function, given a GRPSYL and the MLL structure it hangs
801  *              off of, returns the next GRPSYL in this voice, even if it's in
802  *              the next measure.  If it is in the next measure, *mll_p_p gets
803  *              updated.  But if that next measure is a second or later ending,
804  *              it's not considered to be a "next" measure, so return 0.
805  */
806
807 struct GRPSYL *
808 nextgrpsyl(gs_p, mll_p_p)
809
810 struct GRPSYL *gs_p;     /* the given GRPSYL */
811 struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */
812
813 {
814         struct MAINLL *mll_p;   /* point at a MLL item */
815         int endingloc;          /* of the following barline */
816
817
818         /* if not at end of measure, just return the next GRPSYL */
819         if (gs_p->next != 0) {
820                 return (gs_p->next);
821         }
822
823         mll_p = *mll_p_p;       /* save original MLL item */
824
825         /*
826          * We hit the end of the measure.  We need to find the first group in
827          * the next measure.  Find the coming bar line, then the corresponding
828          * staff in the next measure.  We do this in case the number of staffs
829          * changes back and forth; we don't want to find the staff in some
830          * later measure.
831          */
832         for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 &&
833                         (*mll_p_p)->str != S_BAR; *mll_p_p = (*mll_p_p)->next) {
834                 ;
835         }
836
837         /* if we hit the end of the MLL, there is no next GRPSYL */
838         if (*mll_p_p == (struct MAINLL *) 0) {
839                 return (struct GRPSYL *) 0;
840         }
841
842         /* we found a bar; get its endingloc */
843         endingloc = (*mll_p_p)->u.bar_p->endingloc;
844
845         /*
846          * Search for this staff in next measure.  If we find a pseudobar while
847          * doing this, save its endingloc in preference to the real bar's.
848          */
849         for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 &&
850                         (*mll_p_p)->str != S_BAR &&
851                         ((*mll_p_p)->str != S_STAFF ||
852                         (*mll_p_p)->u.staff_p->staffno != gs_p->staffno);
853                         *mll_p_p = (*mll_p_p)->next) {
854
855                 if ((*mll_p_p)->str == S_CLEFSIG && 
856                     (*mll_p_p)->u.clefsig_p->bar_p != (struct BAR *) 0) {
857                         endingloc = (*mll_p_p)->u.clefsig_p->bar_p->endingloc;
858                 }
859         }
860
861         /* if we hit the end or another bar before finding our staff, return */
862         if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) {
863                 return (struct GRPSYL *) 0;
864         }
865
866         /*
867          * We found the appropriate staff in the next measure.  But if we have
868          * crossed into a second or later ending, this bar doesn't really
869          * "follow" the previous bar, and we must return null.  So if endingloc
870          * shows this is the case, we must search backwards to find out if we
871          * were already in an ending.
872          */
873         if (endingloc == STARTITEM) {
874                 while (mll_p != 0 && mll_p->str != S_BAR && (mll_p->str !=
875                                 S_CLEFSIG || mll_p->u.clefsig_p->bar_p == 0))
876                         mll_p = mll_p->prev;
877
878                 /* set endingloc of the previous measure */
879                 if (mll_p == 0) {
880                         endingloc = NOITEM;
881                 } else if (mll_p->str == S_BAR) {
882                         endingloc = mll_p->u.bar_p->endingloc;
883                 } else {
884                         endingloc = mll_p->u.clefsig_p->bar_p->endingloc;
885                 }
886
887                 /* if we were already in an ending, there's no next GRPSYL */
888                 if (endingloc == STARTITEM || endingloc == INITEM) {
889                         return (struct GRPSYL *) 0;
890                 }
891         }
892
893         /* return the first GRPSYL of the appropriate voice */
894         return ((*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ]);
895 }
896 \f
897 /*
898  * Name:        prevgrpsyl()
899  *
900  * Abstract:    Find previous GRPSYL in this voice (same measure or not).
901  *
902  * Returns:     Pointer to the GRPSYL, or 0 if none.
903  *
904  * Description: This function, given a GRPSYL and the MLL structure it hangs
905  *              off of, returns the previous GRPSYL in this voice, even if it's
906  *              in an earlier measure.  If we are at the start of an ending,
907  *              it skips over any previous ending and goes to the measure
908  *              preceding the first ending.  If the resulting GRPSYL is in a
909  *              previous measure, *mll_p_p gets updated.
910  */
911
912 struct GRPSYL *
913 prevgrpsyl(gs_p, mll_p_p)
914
915 struct GRPSYL *gs_p;     /* the given GRPSYL */
916 struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */
917
918 {
919         struct GRPSYL *gs2_p;   /* for looping through prev measure's list */
920         struct BAR *bar_p;      /* point at a bar line */
921         struct MAINLL *mll_p;   /* point at a MLL item */
922         int pseudo;             /* was the last thing we saw a pseudobar? */
923         int barcount;           /* how many bar lines we looped backward thru*/
924         int safmoae;            /* "started at first measure of an ending" */
925
926
927         /* if not at start of measure, just return the previous GRPSYL */
928         if (gs_p->prev != (struct GRPSYL *) 0) {
929                 return (gs_p->prev);
930         }
931
932         /*
933          * We hit the start of the measure.  Loop backwards through the MLL
934          * looking for the bar line at the start of the "previous" measure.
935          * If our measure is not the first measure of an ending, this is
936          * simply the bar at the start of the previous measure.  Otherwise,
937          * this is the bar before the measure before the first ending.  Also
938          * handle the cases where we fall off the start of the MLL.
939          */
940         bar_p = 0;
941         mll_p = *mll_p_p;
942         pseudo = NO;
943         barcount = 0;
944         safmoae = NO;
945         do {
946                 /* find preceding bar or pseudobar, if either exists */
947                 for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0 &&
948                                 mll_p->str != S_BAR &&
949                                 (mll_p->str != S_CLEFSIG ||
950                                 mll_p->u.clefsig_p->bar_p == 0);
951                                 mll_p = mll_p->prev) {
952                         ;
953                 }
954
955                 /*
956                  * If we hit the start of the MLL without crossing any bars, or
957                  * just a pseudobar, there is no preceding GRPSYL, so return 0.
958                  * (Depending on who is calling this function, the pseudobar at
959                  * the start of the song may or may not exist.)  Otherwise, it
960                  * must be that we started in the second measure, or an ending
961                  * that we skipped over started there.  Point at the start of
962                  * the MLL, and get out of the loop.  Note that we can't still
963                  * be in the process of skipping over endings:  no ending can
964                  * start at the first measure of the song, because there is no
965                  * bar line there.
966                  */
967                 if (mll_p == 0) {
968                         if (barcount == 0 || (barcount == 1 && pseudo == YES)) {
969                                 return (struct GRPSYL *) 0;
970                         }
971                         mll_p = Mainllhc_p;
972                         break;
973                 }
974
975                 barcount++;
976
977                 /*
978                  * Point bar_p at the relevant bar/pseudobar for checking the
979                  * endingloc.  If this is a pseudobar, it's relevant.  If this
980                  * is a bar, it's relevant only if it's the first thing we've
981                  * seen, or the thing we saw last was not a pseudobar.  That
982                  * is, the endingloc of the bar at the end of a score is to be
983                  * ignored, because the true endingloc has been moved to the
984                  * next score's pseudobar.  We need to worry about this because
985                  * of the case where a second ending starts at the start of the
986                  * new score (STARTITEM) and the previous score ends with
987                  * ENDITEM, which should be ignored.
988                  */
989                 if (mll_p->str == S_BAR) {
990                         if (bar_p == 0 || pseudo == NO) {
991                                 bar_p = mll_p->u.bar_p;
992                         }
993                         if (pseudo == YES) {
994                                 barcount--;     /* forget this bar */
995                                 pseudo = NO;
996                         }
997                 } else {
998                         bar_p = mll_p->u.clefsig_p->bar_p;
999                         pseudo = YES;
1000                 }
1001
1002                 /*
1003                  * If this is the first measure we're backing into, and this
1004                  * first bar we hit shows that our GRPSYL was in the first
1005                  * measure of an ending, remember that fact.
1006                  */
1007                 if (barcount == 1 && bar_p->endingloc == STARTITEM) {
1008                         safmoae = YES;
1009                 }
1010
1011         /*
1012          * Get out, when, in the normal case, we've hit the second meaningful
1013          * bar; or in the safmoae case, we've skipped back to the back before
1014          * the first bar of the first ending.
1015          */
1016         } while (! ( (safmoae == NO && barcount == 2) || (safmoae == YES &&
1017                 (bar_p->endingloc == NOITEM || bar_p->endingloc == ENDITEM))));
1018
1019         /*
1020          * Search forward to the next bar, which is the bar before which we
1021          * want to find a GRPSYL.  We don't care about pseudobars here.
1022          */
1023         for (mll_p = mll_p->next; mll_p->str != S_BAR; mll_p = mll_p->next) {
1024                 ;
1025         }
1026
1027         /*
1028          * Now mll_p is the bar before which we want to find the GRPSYL.
1029          * Find the corresponding staff in the previous measure.  We do
1030          * this in case the number of staffs changes back and forth; we
1031          * don't want to find the staff in some earlier measure.
1032          */
1033
1034         /* search for this staff in previous measure */
1035         for (*mll_p_p = mll_p->prev; *mll_p_p != (struct MAINLL *) 0 &&
1036                         (*mll_p_p)->str != S_BAR &&
1037                         ((*mll_p_p)->str != S_STAFF ||
1038                         (*mll_p_p)->u.staff_p->staffno != gs_p->staffno);
1039                         *mll_p_p = (*mll_p_p)->prev) {
1040                 ;
1041         }
1042
1043         /* if we hit the start or another bar before finding our staff, return*/
1044         if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) {
1045                 return (struct GRPSYL *) 0;
1046         }
1047
1048         /* return the last GRPSYL of the appropriate voice */
1049         gs2_p = (*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ];
1050         if (gs2_p == (struct GRPSYL *) 0) {
1051                 return(gs2_p);
1052         }
1053         while (gs2_p->next != (struct GRPSYL *) 0) {
1054                 gs2_p = gs2_p->next;
1055         }
1056
1057         return (gs2_p);
1058 }
1059 \f
1060
1061 /* if user asked for octave marks, we need to transpose any affected notes
1062  * by the appropriate number of octaves. This should be called for a measure
1063  * at a time. It will handle all the octave marks
1064  * within the measure for the current voice, both those carrying over into
1065  * this measure and ones starting there. If an octave mark spills beyond
1066  * the end of the measure, the amount to transpose and how long to do so
1067  * is saved away for use in the next measure. Checks for things becoming
1068  * out of range because of the transposition are not done here; caller
1069  * must do that if they care. */
1070
1071 void
1072 octave_transpose(staff_p, mll_p, vno, normdir)
1073
1074 struct STAFF *staff_p;
1075 struct MAINLL *mll_p;   /* staff_p connects here, used for bends */
1076 int vno;                /* voice number */
1077 int normdir;            /* YES if should move note pitches up for above and
1078                          * down for below. NO if the inverse should be done */
1079
1080 {
1081         struct GRPSYL *gs_p;    /* walk through list of GRPSYLs */
1082         struct GRPSYL *gs_roll_p;       /* group generated for a roll */
1083         struct STUFF *stuff_p;  /* to look for octave marks */
1084         RATIONAL total_time;    /* accumulated time in measure */
1085         float float_total_time; /* for comparing with count */
1086         int carry_adjust;       /* adjust to carry into next measure */
1087         int carry_bars;         /* how many bars to carry over */
1088         float carry_counts;     /* how many counts in final bar */
1089         int staffno;            /* which staff we are working with */
1090
1091
1092         staffno = staff_p->staffno;
1093         carry_adjust = carry_bars = 0;
1094         carry_counts = 0.0;
1095
1096         /* if currently have octave mark */
1097         if (Octave_adjust[staffno] != 0) {
1098
1099                 /* if bar count > 0, transpose all notes in measure */
1100                 if (--(Octave_bars[staffno]) > 0) {
1101
1102                         for (gs_p = staff_p->groups_p[vno];
1103                                         gs_p != (struct GRPSYL *) 0;
1104                                         gs_p = gs_p->next) {
1105
1106                                 grp_octave_adjust(gs_p, Octave_adjust[staffno], mll_p);
1107                         }
1108                 }
1109
1110                 /* otherwise just transpose until specified time */
1111                 else {
1112                         total_time = Zero;
1113                         for (gs_p = staff_p->groups_p[vno];
1114                                                 gs_p != (struct GRPSYL *) 0;
1115                                                 gs_p = gs_p->next) {
1116
1117                                 float_total_time = RAT2FLOAT(total_time)
1118                                                 * Score.timeden + 1.0;
1119
1120                                 if (float_total_time <= Octave_count[staffno]) {
1121                                         grp_octave_adjust(gs_p,
1122                                                 Octave_adjust[staffno], mll_p);
1123                                 }
1124                                 else {
1125                                         break;
1126                                 }
1127                                 total_time = radd(total_time, gs_p->fulltime);
1128                         }
1129
1130                         Octave_adjust[staffno] = 0;
1131                 }
1132         }
1133
1134         /* go through stuff list. If any octave marks, transpose appropriate
1135          * notes in this measure. If extends to next measure, remember for
1136          * next time. If user put in more than one octave
1137          * mark going over the bar, catch that. If there are overlaps within
1138          * a measure, it seems like too much trouble to catch this, so just
1139          * transpose as often as they say and let them figure out why it
1140          * sounds funny. */
1141         for (stuff_p = staff_p->stuff_p; stuff_p != (struct STUFF *) 0;
1142                                                 stuff_p = stuff_p->next) {
1143
1144                 if (stuff_p->stuff_type == ST_OCTAVE) {
1145
1146                         if (Octave_adjust[staffno] != 0) {
1147                                 l_warning(stuff_p->inputfile,
1148                                                 stuff_p->inputlineno,
1149                                                 "overlapping octave marks");
1150                         }
1151
1152                         /* figure out how many octaves to move */
1153                         Octave_adjust[staffno] = parse_octave(stuff_p->string,
1154                                         stuff_p->place, stuff_p->inputfile,
1155                                         stuff_p->inputlineno);
1156
1157                         /* if this call is for inverse transpostion, adjust
1158                          * to go in opposite direction */
1159                         if (normdir == NO) {
1160                                 Octave_adjust[staffno] *= -1;
1161                         }
1162
1163                         /* figure out to which count the octave mark applies
1164                          * within this measure. */
1165                         Octave_count[staffno] = (stuff_p->end.bars > 0 ? 1.0 +
1166                                         RAT2FLOAT(Score.time) * Score.timeden
1167                                         : stuff_p->end.count);
1168                         
1169                         total_time = Zero;
1170                         for (gs_p = staff_p->groups_p[vno];
1171                                                 gs_p != (struct GRPSYL *) 0;
1172                                                 gs_p = gs_p->next) {
1173
1174                                 float_total_time = RAT2FLOAT(total_time) *
1175                                                 Score.timeden + 1.0;
1176                                 if (float_total_time >= stuff_p->start.count) {
1177
1178                                         if (float_total_time <=
1179                                                         Octave_count[staffno]) {
1180                                                 /* is within the mark, so move */
1181                                                 grp_octave_adjust(gs_p,
1182                                                         Octave_adjust[staffno],
1183                                                         mll_p);
1184                                         }
1185
1186                                         /* special case. If we have a rolled
1187                                          * chord, and user specified
1188                                          * an octave mark without a til clause,
1189                                          * all the chords that got
1190                                          * generated internally to cause the
1191                                          * "roll" effect need to be transposed,
1192                                          * even though they have been moved
1193                                          * in time */
1194                                         if (float_total_time == stuff_p->start.count
1195                                                 && stuff_p->end.bars == 0
1196                                                 && stuff_p->end.count == 0.0
1197                                                 && gs_p->inputlineno < 0) {
1198
1199                                             /* adjust all the groups generated
1200                                              * to create the roll effect */
1201                                             for (gs_roll_p = gs_p->next;
1202                                                         gs_roll_p != (struct GRPSYL *) 0;
1203                                                         gs_roll_p = gs_roll_p->next) {
1204
1205                                                     grp_octave_adjust(gs_roll_p,
1206                                                         Octave_adjust[staffno],
1207                                                         mll_p);
1208                                                     /* stop when we hit the
1209                                                      * end of the roll */
1210                                                     if (gs_roll_p->inputlineno > 0) {
1211                                                         break;
1212                                                     }
1213                                             }
1214                                         }
1215                                 }
1216
1217                                 total_time = radd(total_time, gs_p->fulltime);
1218                         }
1219
1220                         /* if octave mark carried over into subsequent
1221                          * measure(s), make a note of that for future use */
1222                         if (stuff_p->end.bars > 0) {
1223                                 if (carry_adjust != 0) {
1224                                         l_warning(stuff_p->inputfile,
1225                                                 stuff_p->inputlineno,
1226                                                 "overlapping octave marks");
1227                                 }
1228                                 carry_bars = stuff_p->end.bars;
1229                                 carry_counts = stuff_p->end.count;
1230                                 carry_adjust = Octave_adjust[staffno];
1231                         }
1232
1233                         Octave_adjust[staffno] = 0;
1234                 }
1235         }
1236
1237         /* above octave marks that were put in on the same input line will
1238          * be in backwards order (because above stuff needs to be that
1239          * way to pile on correctly). However, if the last octave in the
1240          * stuff input line carried over a bar line, we would see it
1241          * first and lose the carryover information when handling the earlier
1242          * octave marks (which are later in the stuff list). That's why the
1243          * carryover information had to be saved. Now we can assign it */
1244         if (carry_bars > 0) {
1245                 Octave_adjust[staffno] = carry_adjust;
1246                 Octave_bars[staffno] = carry_bars;
1247                 Octave_count[staffno] = carry_counts;
1248         }
1249 }
1250 \f
1251
1252 /* transpose all the notes in a group by the specified octave adjustment */
1253
1254 static void
1255 grp_octave_adjust(gs_p, adj, mll_p)
1256
1257 struct GRPSYL *gs_p;            /* adjust this group */
1258 int adj;                        /* add this (potentially negative) value to
1259                                  * each notelist octave */
1260 struct MAINLL *mll_p;           /* STAFF of gs_p for finding prev grp for bends */
1261
1262 {
1263         register int n;
1264         struct GRPSYL *prevgs_p;        /* previous group, for bends */
1265
1266         for (n = 0; n < gs_p->nnotes; n++) {
1267                 gs_p->notelist[n].octave += adj;
1268         }
1269         /* Transpose any bends going to this group */
1270         prevgs_p = prevgrpsyl(gs_p, &mll_p);
1271         if (prevgs_p == 0) {
1272                 /* If there is no previous group, nothing to transpose. */
1273                 return;
1274         }
1275         for (n = 0; n < prevgs_p->nnotes; n++) {
1276                 if (prevgs_p->notelist[n].is_bend == YES) {
1277                         /* Note that when is_bend is YES, nslurto will always
1278                          * be 1, but we loop through as many as there are
1279                          * (all 1 of them!), to not be dependent
1280                          * on that piece of inside information.
1281                          */
1282                         int s;
1283                         for (s = 0; s < prevgs_p->notelist[n].nslurto; s++) {
1284                                 prevgs_p->notelist[n].slurtolist[s].octave += adj;
1285                         }
1286                 }
1287         }
1288 }
1289 \f
1290
1291 /* Given a group and note value, return the effective accidental
1292  * on that note, (-2 to +2) taking key signature
1293  * and previous accidentals into account.
1294  * There are certain pathological cases that this doesn't
1295  * handle right, notably if the user changes the key signature at a bar
1296  * line, and the note in question is tied to from before that bar line,
1297  * and the key signature change is such that it changes what the accidental
1298  * should be. But it should handle anything less convoluted than that.
1299  */
1300
1301 int
1302 eff_acc(gs_p, note_p, mll_p)
1303
1304 struct GRPSYL *gs_p;    /* get effective accidental for note in this group */
1305 struct NOTE *note_p;    /* get for this note */
1306 struct MAINLL *mll_p;   /* main list item that points to gs_p */
1307
1308 {
1309         struct MAINLL *orig_mll_p;
1310         struct GRPSYL *pgs_p;           /* previous group */
1311         int n;
1312         int tie_break;                  /* YES if there has been a break
1313                                          * in the chain of notes
1314                                          * tied together */
1315         int eff_accidental;             /* effective accidental so far */
1316
1317
1318         /* if this group has an explicit accidental, that's also the
1319          * effective accidental */
1320         if (note_p->accidental != '\0') {
1321                 /* note: the - 2 is to adjust for natural being element 2
1322                  * of the Circle array */
1323                 return( (int) (strchr(Acclets, note_p->accidental) - Acclets) - 2);
1324         }
1325
1326         /* remember which measure we are starting in, so we know when we cross
1327          * a bar line */
1328         orig_mll_p = mll_p;
1329
1330         /* init to assume we might have ties */
1331         tie_break = NO;
1332
1333         /* if all else fails, we will use the accidental from the key sig */
1334         eff_accidental = acc_from_keysig(note_p->letter, gs_p->staffno,
1335                                                 mll_p);
1336
1337         /* back up until we figure out the effective accidental */
1338         for (pgs_p = prevgrpsyl(gs_p, &mll_p); pgs_p != (struct GRPSYL *) 0;
1339                                 pgs_p = prevgrpsyl(pgs_p, &mll_p)) {
1340
1341
1342                 /* see if this group contains the note in question */
1343                 for (n = 0; n < pgs_p->nnotes; n++) {
1344                         if (pgs_p->notelist[n].letter == note_p->letter &&
1345                                                 pgs_p->notelist[n].octave
1346                                                 == note_p->octave) {
1347                                 /* it does have the note: it's notelist[n] */
1348                                 break;
1349                         }
1350                 }
1351
1352                 /* see if this is end of ties to the note, working backwards */
1353                 if (n == pgs_p->nnotes) {
1354                         /* no note at all, so clearly no tied note */
1355                         tie_break = YES;
1356                 }
1357                 else if (pgs_p->notelist[n].tie == NO) {
1358                         /* end of chain of tied notes */
1359                         tie_break = YES;
1360                 }
1361
1362                 if (orig_mll_p == mll_p) {
1363                         /* we're still in same measure. If we have a matching
1364                          * note, see if it has an accidental */
1365                         if (n < pgs_p->nnotes) {
1366                                 if (pgs_p->notelist[n].accidental != '\0') {
1367                                         return( (int) (strchr(Acclets,
1368                                                 pgs_p->notelist[n].accidental)
1369                                                 - Acclets) - 2);
1370                                 }
1371                         }
1372
1373                         /* have to keep backing up */
1374                 }
1375                 else {
1376                         /* Now in previous measure. If no matching note,
1377                          * we use the effective accidental found so far */
1378                         if (n == pgs_p->nnotes) {
1379                                 return(eff_accidental);
1380                         }
1381
1382                         /* if the note isn't tied, then use the most recent
1383                          * effective accidental we found */
1384                         if (pgs_p->notelist[n].tie == NO || tie_break == YES) {
1385                                 return(eff_accidental);
1386                         }
1387
1388                         /* if there is an accidental on this note,
1389                          * then it's the one we're looking for. */
1390                         if (pgs_p->notelist[n].accidental != '\0') {
1391                                 return( (int) (strchr(Acclets,
1392                                         pgs_p->notelist[n].accidental) -
1393                                         Acclets - 2));
1394                         }
1395
1396                         /* need to continue working backwards toward
1397                          * the beginning of this new measure */
1398                         orig_mll_p = mll_p;
1399                         eff_accidental = acc_from_keysig(note_p->letter,
1400                                         gs_p->staffno, mll_p);
1401                 }
1402         }
1403
1404         /* backed up all the way to the beginning of the song, use last we
1405          * found */
1406         return(eff_accidental);
1407 }
1408 \f
1409
1410 /* given a letter and staff number, return 1 if the pitch with that letter
1411  * gets a sharps according to the key signature,  or -1 if it gets a flat,
1412  * or 0 if it gets neither. */
1413
1414 int
1415 acc_from_keysig(letter, staffno, mll_p)
1416
1417 int letter;             /* which pitch */
1418 int staffno;            /* which staff to get the key signature from */
1419 struct MAINLL *mll_p;   /* pitch is from the staff hanging off of here */
1420
1421 {
1422         int index;      /* where the letter is in circle of fifths */
1423         int sharps;     /* sharps in key sig for the given staff */
1424         struct SSV *ssv_p;      /* to get key signature */
1425
1426
1427         /* find letter in circle of fifths */
1428         index = strchr(Circle, letter) - Circle + 1;
1429
1430         /* get key signature. Unfortunately, the SSVs may not be
1431          * accurate at the time we are called, so we have to search
1432          * backwards in the main list for the most recent relevant
1433          * key signature change. */
1434         for (sharps = 0; mll_p != (struct MAINLL *) 0; mll_p = mll_p->prev) {
1435                 if (mll_p->str == S_SSV) {
1436                         ssv_p = mll_p->u.ssv_p;
1437
1438                         /* does this SSV have a key signature change in it? */
1439                         if (ssv_p->used[SHARPS] == YES) {
1440                                 if (ssv_p->context == C_STAFF &&
1441                                                 ssv_p->staffno == staffno) {
1442                                         /* aha! found the most recent
1443                                          * key signature
1444                                          * for the relevant staff */
1445                                         sharps = ssv_p->sharps;
1446                                         break;
1447                                 }
1448                                 else if (ssv_p->context == C_SCORE) {
1449                                         /* this will be the score-wide default
1450                                          * if we don't find a staff-specific
1451                                          * value, so save this as our default */
1452                                         sharps = ssv_p->sharps;
1453                                 }
1454                         }
1455                 }
1456         }
1457
1458         if (sharps > 0) {
1459                 /* key signature is one with sharps */
1460                 if (index <= sharps) {
1461                         /* this letter gets a sharp */
1462                         return(1);
1463                 }
1464         }
1465         else if (sharps < 0) {
1466                 /* key signature is one with flats */
1467                 if ( (8 - index) <= -sharps) {
1468                         /* this letter gets a flat */
1469                         return(-1);
1470                 }
1471         }
1472
1473         /* must be a natural */
1474         return(0);
1475 }
1476
1477 /* Set Staffscale, Stepsize, Stdpad, and other similar values based on the
1478  * specified staff number. If staff of 0 is given, set Staffscale to the
1479  * score value
1480  */
1481
1482 void
1483 set_staffscale(s)
1484
1485 int s;                  /* which staff */
1486
1487 {
1488         Staffscale = (s == 0 ? Score.staffscale
1489                                         : svpath(s, STAFFSCALE)->staffscale);
1490         Stepsize = STEPSIZE * Staffscale;
1491         Stdpad = STDPAD * Staffscale;
1492         Flagsep = FLAGSEP * Staffscale;
1493         Smflagsep = SMFLAGSEP * Staffscale;
1494         Tupheight = TUPHEIGHT * Staffscale;
1495 }
1496 \f
1497
1498 /* Determine the space between lines of a grid. A staff of 0 means use
1499  * the score size. A staff of -1 means ATEND. Return distance in inches. */
1500
1501 double
1502 gridspace(staff)
1503
1504 int staff;
1505
1506 {
1507         double space;
1508
1509         if (staff == -1) {
1510                 space = ATEND_GS * STEPSIZE * Score.gridscale;
1511         }
1512         else {
1513                 space = WHEREUSED_GS * STEPSIZE
1514                                 * svpath(staff, STAFFSCALE)->staffscale
1515                                 * svpath(staff, GRIDSCALE)->gridscale;
1516         }
1517         return(space);
1518 }
1519 \f
1520
1521 /* Given a grid, return (via pointer) the items needed for the PostScript
1522  * plus the top fret.
1523  */
1524
1525 void
1526 gridinfo(grid_p, staff, frets_p, fretnum_p, numvert_p, topfret_p)
1527
1528 struct GRID *grid_p;
1529 int staff;      /* 0 == score, -1 = ATEND, otherwise the staff number */
1530 int *frets_p;   /* how many frets high the grid should be */
1531 int *fretnum_p; /* the N of "N fr" */
1532 int *numvert_p; /* how many frets from the top to print the "N fr" */
1533 int *topfret_p; /* the fret number of the top line of the grid */
1534
1535 {
1536         int minfret, maxfret;   /* smallest and largest frets used */
1537         int rightmost_fret;     /* the 'N' of 'N fr" if any */
1538         int right_stringnum;    /* string number having rightmost_fret */
1539         int mincurvefret;       /* smallest fret number inside curve */
1540         int has_o;              /* if there are 'o' items */
1541         int gridfret;
1542         int s;
1543
1544
1545         /* Go through strings finding min/max/rightmost */
1546         minfret = MAXFRET + 1;
1547         maxfret = MINFRET - 1;
1548         mincurvefret = MAXFRET + 1;
1549         has_o = NO;
1550         rightmost_fret = right_stringnum = 0;  /* avoids bogus warnings */
1551         for (s = 0; s < grid_p->numstr; s++) {
1552                 /* x o and - things don't count */
1553                 if (grid_p->positions[s] > 0) {
1554                         if (grid_p->positions[s] < minfret) {
1555                                 minfret = grid_p->positions[s];
1556                         }
1557                         if (grid_p->positions[s] > maxfret) {
1558                                 maxfret = grid_p->positions[s];
1559                         }
1560                         rightmost_fret = grid_p->positions[s];
1561                         right_stringnum = s;
1562
1563                         /* find smallest fret inside curve */
1564                         if (grid_p->curvel != 0 && s >= grid_p->curvel - 1 &&
1565                                         s <= grid_p->curver - 1 &&
1566                                         grid_p->positions[s] < mincurvefret) {
1567                                 mincurvefret = grid_p->positions[s];
1568                         }
1569                 }
1570                 else if (grid_p->positions[s] == 0) {
1571                         has_o = YES;
1572                 }
1573         }
1574
1575         /* set the values to defaults, then calculate actuals if needed */
1576         *frets_p = 5;
1577         *fretnum_p = 0;
1578         *numvert_p = 0;
1579         if (minfret <= MAXFRET) {
1580                 /* at least one fret was used */
1581
1582                 /* figure out how many frets tall to make the grid */
1583                 *frets_p = maxfret + 1;
1584
1585                 /* see if gridfret is set */
1586                 gridfret = svpath(staff == -1 ? 0 : staff, GRIDFRET)->gridfret;
1587                 if (gridfret != NOGRIDFRET) {
1588                         /* gridfret is set; see if all frets larger than that.
1589                          * But we only use "N fr" if there are no 'o' items. */
1590                         if (has_o == NO && minfret >= gridfret) {
1591                                 /* We will need "N fr"
1592                                  * Usually we use the rightmost string
1593                                  * that has a fret on it,
1594                                  * but there is one special case:
1595                                  * if the curve comes at least that far right,
1596                                  * and the minimum fret inside the curve is
1597                                  * smaller than the rightmost_fret, then we
1598                                  * put the "N fr" by the curve minimum.
1599                                  */
1600                                 if (grid_p->curver - 1 >= right_stringnum
1601                                                 && mincurvefret < rightmost_fret) {
1602                                         rightmost_fret = mincurvefret;
1603                                 }
1604                                 *fretnum_p = rightmost_fret;
1605                                 *numvert_p = rightmost_fret - minfret + 1;
1606                                 *frets_p = maxfret - minfret + 2;
1607                         }
1608                 }
1609
1610                 if (*frets_p < 5) {
1611                         /* always at least 4 frets plus top line */
1612                         *frets_p = 5;
1613                 }
1614         }
1615         *topfret_p = (*fretnum_p == 0 ? 0 : *fretnum_p - *numvert_p);
1616 }
1617 \f
1618
1619 /* Determine the dimensions of a grid, relative to a point in the middle
1620  * of the top line of the grid, and return them via pointers.
1621  * If pointers are 0, don't bother; caller doesn't care about these things.
1622  * Things in this function must be kept in sync with the PostScript prolog
1623  * definition of grids.
1624  */
1625
1626 void
1627 gridsize(grid_p, staff, north_p, south_p, east_p, west_p)
1628
1629 struct GRID *grid_p;    /* find the size of this grid */
1630 int staff;              /* use this staff for scaling. 0 means score,
1631                          * -1 means ATEND */
1632 float *north_p;         /* return values... */
1633 float *south_p;
1634 float *east_p;
1635 float *west_p;
1636
1637 {
1638         double space;   /* distance between adjacent line of the grid */
1639         int frets;
1640         int fretnum;
1641         int numvert;
1642         int topfret;
1643         int s;          /* string index */
1644
1645         if (grid_p == 0) {
1646                 pfatal("gridsize() was passed a null pointer");
1647         }
1648
1649         /* determine distance between grid lines and other needed info */
1650         space = gridspace(staff);
1651         gridinfo(grid_p, staff, &frets, &fretnum, &numvert, &topfret);
1652
1653         /* Start with minimum. East and west are equal, at half the
1654          * total grid width, based on number of strings. The number of
1655          * spaces is the number of strings minus one, but dots, X's,
1656          * and O's will hang over the sides, so use the number of strings.
1657          * Then adjust east for "N fr" if needed. */
1658         if (west_p != 0) {
1659                 *west_p = -((space * grid_p->numstr) / 2.0);
1660         }
1661         if (east_p != 0) {
1662                 *east_p = (space * grid_p->numstr) / 2.0;
1663                 if (fretnum > 0) {
1664                         /* We will need "N fr".
1665                          * Get enough space to hold
1666                          * font, size, 2 digits, space, "fr", null */
1667                         char tmp[8];
1668
1669                         /* this is printed in Palatino Roman */
1670                         tmp[0] = (char) FONT_PR;
1671
1672                         /* Between staffscale and gridscale,
1673                          * we could get a size that we can't represent
1674                          * in internal format, so get string width
1675                          * in default size and adjust afterwards. */
1676                         tmp[1] = (char) DFLT_SIZE;
1677
1678                         /* since we know there are no funny characters
1679                          * in this string, we can cheat and not bother
1680                          * to call the string normalizer. */
1681                         sprintf(tmp + 2, "%d fr", fretnum);
1682
1683                         *east_p += strwidth(tmp) *
1684                                                 (space * PPI * 1.9)/ DFLT_SIZE;
1685                 }
1686         }
1687
1688         if (north_p != 0) {
1689                 /* Always put almost one space of padding on top, which allows
1690                  * room for x's and o's and curves. Even if this particular grid
1691                  * doesn't have those, many do, so it's nice to line
1692                  * all of them up as much as possible */
1693                 *north_p = 0.85 * space;
1694                 /* If there is a curve above the top fret,
1695                  * with x's or o's above it, leave some more space */
1696                 if (grid_p->positions[grid_p->curvel - 1] == topfret + 1 
1697                                         || grid_p->positions[grid_p->curver - 1]
1698                                         == topfret + 1) {
1699                         for (s = grid_p->curvel; s <= grid_p->curver; s++) {
1700                                 if (grid_p->positions[s-1] == 0 ||
1701                                                 grid_p->positions[s-1]
1702                                                 == -1) {
1703                                         *north_p += 0.7 * space;
1704                                         break;
1705                                 }
1706                         }
1707                 }
1708         }
1709
1710         /* Grid is always at least 4 boxes high, more if needed,
1711          * plus 1/2 space of padding at bottom */
1712         if (south_p != 0) {
1713                 *south_p = -(frets - 0.5) * space;
1714         }
1715 }
1716 \f
1717
1718 /* This function returns the minimum distance needed between the current 
1719  * staff and previous one, given their clefs and allowing for a measure
1720  * number. The clefs might be NOCLEF, like if this is for the top
1721  * staff of a page or a staff where printclef is false.
1722  */
1723  
1724 double
1725 clefspace(prevclef, prevscale, curclef, curscale, measnum)
1726
1727 int prevclef;           /* clef on staff above */
1728 double prevscale;       /* staffscale for the staff above */
1729 int curclef;            /* clef on staff below */
1730 double curscale;        /* staffscale for the staff below */
1731 int measnum;            /* YES if a measure number needs to be printed */
1732
1733 {
1734         double cur_extend;      /* space needed for current clef */
1735         double prev_extend;     /* space needed for clef above */
1736         double space_needed;    /* total for both clefs and measure number */
1737
1738
1739         /* Figure out how much the clef on current staff sticks up,
1740          * Do in approximate STEPSIZEs here, and adjust later for scale. */
1741         switch (curclef) {
1742         case TREBLE_8A:
1743                 cur_extend = 6.0;
1744                 break;
1745         case TREBLE:
1746         case TREBLE_8:
1747                 cur_extend = 4.0;
1748                 break;
1749         case BARITONE:
1750                 cur_extend = 4.2;
1751                 break;
1752         case TENOR:
1753                 cur_extend = 2.2;
1754                 break;
1755         case FRENCHVIOLIN:
1756                 cur_extend = 2.0;
1757                 break;
1758         default:
1759                 cur_extend = 0.0;
1760                 break;
1761         }
1762
1763         /* Similar for the clef above, only how much it sticks down
1764          * rather than up */
1765         switch (prevclef) {
1766         case TREBLE:
1767         case TREBLE_8A:
1768                 prev_extend = 3.2;
1769                 break;
1770         case MEZZOSOPRANO:
1771                 prev_extend = 2.2;
1772                 break;
1773         case SOPRANO:
1774                 prev_extend = 4.2;
1775                 break;
1776         case FRENCHVIOLIN:
1777         case TREBLE_8:
1778                 prev_extend = 5.2;
1779                 break;
1780         default:
1781                 prev_extend = 0.0;
1782                 break;
1783         }
1784
1785         /* Add top and bottom together, adjusting for scale factors,
1786          * and adding a little padding */
1787         space_needed = prev_extend * STEPSIZE * prevscale +
1788                         cur_extend * STEPSIZE * curscale +
1789                         STDPAD * curscale;
1790
1791         /* Add on the space for the measure number, if necessary.
1792          * Note that we can use fontascent since all digits are that high. */
1793         if (measnum == YES) {
1794                 space_needed += fontascent(Score.measnumfamily + Score.measnumfont,
1795                                 Score.measnumsize) + STDPAD;
1796         }
1797         return(space_needed);
1798 }
1799 \f
1800 /*
1801  * Name:        eff_rightmargin()
1802  *
1803  * Abstract:    Return the effective right margin for this score.
1804  *
1805  * Returns:     the margin in inches
1806  *
1807  * Description: There are two reason that code can't just use Score.rightmargin
1808  *              but must call this function.  First, the way the "scale" param
1809  *              works, we pretend the paper is smaller by that amount and then
1810  *              in PostScript magnify it back to the real size; but margins are
1811  *              not to be scaled, so we have to fake out the code by dividing
1812  *              out the scale here.  Second, the user can override the param
1813  *              on a "newscore" or "newpage".  To ignore a user override, pass
1814  *              0 for mainll_p, else pass some MLL on that score.
1815  */
1816
1817 double
1818 eff_rightmargin(mainll_p)
1819
1820 struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */
1821
1822 {
1823         /* if not already at a FEED, find FEED at right end of this score */
1824         while (mainll_p != 0 && mainll_p->str != S_FEED)
1825                 mainll_p = mainll_p->next;
1826
1827         /* if there is none, or there is no override, use the parameter */
1828         if (mainll_p == 0 || mainll_p->u.feed_p->rightmargin < 0.0)
1829                 return (Score.rightmargin / Score.scale_factor);
1830
1831         /* use this override value */
1832         return (mainll_p->u.feed_p->rightmargin / Score.scale_factor);
1833 }
1834 \f
1835 /*
1836  * Name:        eff_leftmargin()
1837  *
1838  * Abstract:    Return the effective left margin for this score.
1839  *
1840  * Returns:     the margin in inches
1841  *
1842  * Description: There are two reason that code can't just use Score.leftmargin
1843  *              but must call this function.  First, the way the "scale" param
1844  *              works, we pretend the paper is smaller by that amount and then
1845  *              in PostScript magnify it back to the real size; but margins are
1846  *              not to be scaled, so we have to fake out the code by dividing
1847  *              out the scale here.  Second, the user can override the param
1848  *              on a "newscore" or "newpage".  To ignore a user override, pass
1849  *              0 for mainll_p, else pass some MLL on that score.
1850  */
1851
1852 double
1853 eff_leftmargin(mainll_p)
1854
1855 struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */
1856
1857 {
1858         /* if not already at a FEED, find FEED at left end of this score */
1859         while (mainll_p != 0 && mainll_p->str != S_FEED)
1860                 mainll_p = mainll_p->prev;
1861
1862         /* if there is none, or there is no override, use the parameter */
1863         if (mainll_p == 0 || mainll_p->u.feed_p->leftmargin < 0.0)
1864                 return (Score.leftmargin / Score.scale_factor);
1865
1866         /* use this override value */
1867         return (mainll_p->u.feed_p->leftmargin / Score.scale_factor);
1868 }
1869 \f
1870 /*
1871  * Name:        findprimes()
1872  *
1873  * Abstract:    Find all the prime numbers up to the given number ("max").
1874  *
1875  * Returns:     array indexed 0 to max, each element YES or NO (is index prime?)
1876  *
1877  * Description: This function mallocs and returns an array of shorts, indexed
1878  *              from 0 to max.  Each element is YES or NO, telling whether its
1879  *              index is a prime number.  The first time it is called, or if
1880  *              max is greater than the previous time, it calculates all this,
1881  *              but on other calls it just returns the answer from before.
1882  */
1883
1884 short *
1885 findprimes(max)
1886
1887 int max;                /* max integer we need to consider */
1888
1889 {
1890         static short *isprime = 0;      /* array to be malloc'ed */
1891         static int oldmax = 0;          /* the max passed in previously */
1892         int stop;                       /* where to stop looking */
1893         int prime;                      /* a prime number */
1894         int n;                          /* loop index */
1895
1896
1897         /* if we've already been here ... */
1898         if (isprime != 0) {
1899                 /* if we've already done the same or more, just return answer*/
1900                 if (max <= oldmax) {
1901                         return (isprime);
1902                 }
1903                 /* max increased; free the old array */
1904                 FREE(isprime);
1905         }
1906         oldmax = max;           /* remember if for next time */
1907
1908         MALLOCA(short, isprime, max + 1);
1909
1910         /* 0 and 1 are not primes */
1911         isprime[0] = isprime[1] = NO;
1912
1913         /*
1914          * We're going to use the Sieve of Eristosthenes.  We start out by
1915          * assuming everything 2 and greater is prime.
1916          */
1917         for (n = 2; n <= max; n++) {
1918                 isprime[n] = YES;
1919         }
1920
1921         /* the following loop can stop when it gets to this point */
1922         stop = sqrt((double)max) + 1;
1923
1924         prime = 2;
1925         while (prime <= stop) {
1926                 /* knock out all multiples of this prime number */
1927                 for (n = 2 * prime; n <= max; n += prime) {
1928                         isprime[n] = NO;
1929                 }
1930                 /* find the next prime */
1931                 for (n = prime + 1; n <= stop && isprime[n] == NO; n++)
1932                         ;
1933                 prime = n;
1934         }
1935
1936         return (isprime);
1937 }
1938 \f
1939 /*
1940  * Name:        factor()
1941  *
1942  * Abstract:    Factor the given number.
1943  *
1944  * Returns:     array indexed 0 to num, giving the prime factors
1945  *
1946  * Description: This function mallocs and returns an array of shorts, indexed
1947  *              from 0 to max.  Each element indexed by a prime number tells
1948  *              how many times that prime factor occurs in num.  All other
1949  *              elements are 0.  The first time it is called, or if num is
1950  *              different from the previous time, it calculates all this,
1951  *              but on other calls it just returns the answer from before.
1952  */
1953
1954 short *
1955 factor(num)
1956
1957 int num;                /* the integer to be factored */
1958
1959 {
1960         static short *factors = 0;      /* array to be malloc'ed */
1961         static int oldnum = 0;          /* the number passed in previously */
1962         short *isprime;                 /* list of which numbers are prime */
1963         int orignum;                    /* remember original num */
1964         int n;                          /* loop index */
1965
1966
1967         /* if we've just done the same number, just return the answer */
1968         if (factors != 0) {
1969                 /* if we've already done the same or more, just return answer*/
1970                 if (num == oldnum) {
1971                         return (factors);
1972                 }
1973                 /* num changed; free the old array */
1974                 FREE(factors);
1975         }
1976         oldnum = num;           /* remember it for next time */
1977
1978         CALLOCA(short, factors, num + 1);
1979
1980         /* find which numbers up to num are primes */
1981         isprime = findprimes(num);
1982
1983         /*
1984          * For every prime number until "num" is used up, divide it into num
1985          * as many times as possible, keeping track of how many times.
1986          */
1987         orignum = num;
1988         for (n = 2; n <= orignum && num > 1; n++) {
1989                 if (isprime[n] == YES) {
1990                         while (num % n == 0) {
1991                                 num /= n;
1992                                 factors[n]++;
1993                         }
1994                 }
1995         }
1996
1997         return (factors);
1998 }
1999 \f
2000
2001 /* Return the width of the widest note head in the given GRPSYL. */
2002
2003 double
2004 widest_head(gs_p)
2005
2006 struct GRPSYL *gs_p;
2007
2008 {
2009         double widest;          /* widest note head in the group */
2010         double thiswidth;       /* width of current note */
2011         int n;                  /* note index */
2012
2013         widest = 0.0;
2014         for (n = 0; n < gs_p->nnotes; n++) {
2015                 thiswidth = width(gs_p->notelist[n].headfont,
2016                         (gs_p->notelist[n].notesize == GS_NORMAL ?
2017                         DFLT_SIZE : SMALLSIZE),
2018                         gs_p->notelist[n].headchar);
2019                 if (thiswidth > widest) {
2020                         widest = thiswidth;
2021                 }
2022         }
2023         return(widest);
2024 }