music.h - abc2ps - A powerful sheet setting tool using the simple abc notation
 (HTM) git clone git://vernunftzentrum.de/abc2ps.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       music.h (108504B)
       ---
            1 /*  
            2  *  This file is part of abc2ps, 
            3  *  Copyright (C) 1996,1997,1998  Michael Methfessel
            4  *  See file abc2ps.c for details.
            5  */
            6  
            7 /*  subroutines connected with output of music  */
            8 
            9 #define XP_START   0
           10 #define XP_END     (maxSyms-1)
           11 
           12 /* ----- nwid ----- */
           13 /* Sets the prefered width for a note depending on the duration.
           14    Return value is default space on right and left side. 
           15    Function is determined by values at 0, 1/2, 1.
           16    Return value is 1.0 for quarter note. */
           17 float nwid (dur)
           18 float dur;
           19 {
           20   float a,b,x,p,x0,p0;
           21 
           22   a=2*(f1p-2*f5p+f0p);
           23   b=f1p-f0p-a;
           24   x = dur/(float)BASE;
           25   p = a*x*x + b*x + f0p;
           26 
           27   x0 = 0.25;
           28   p0 = a*x0*x0 + b*x0 + f0p;
           29   p  = p/p0;
           30   return p;
           31 }
           32 
           33 /* ----- xwid -- --- */
           34 /* same as nwid but for stretched system */
           35 float xwid (dur)
           36 float dur;
           37 {
           38   float a,b,x,p,x0,p0;
           39 
           40   a=2*(f1x-2*f5x+f0x);
           41   b=f1x-f0x-a;
           42   x = dur/(float)BASE;
           43   p = a*x*x + b*x + f0x;
           44 
           45   x0 = 0.25;
           46   p0 = a*x0*x0 + b*x0 + f0x;
           47   p  = p/p0;
           48 
           49   return p;
           50 }
           51 
           52 /* ----- next_note, prec_note ------ */
           53 int next_note (k,n,symb)
           54 int k,n;
           55 struct SYMBOL symb[];
           56 {
           57   int i;
           58   for (i=k+1;i<n;i++) {
           59     if ((symb[i].type==NOTE)||(symb[i].type==REST)) return i;
           60   }
           61   return -1; 
           62 }
           63 
           64 int prec_note (k,n,symb)
           65 int k,n;
           66 struct SYMBOL symb[];
           67 {
           68   int i;
           69   for (i=k-1;i>=0;i--) {
           70     if ((symb[i].type==NOTE)||(symb[i].type==REST)) return i;
           71   }
           72   return -1; 
           73 }
           74 
           75 
           76 /* ----- followed_by_note ------ */
           77 int followed_by_note (k,n,symb)
           78 int k,n;
           79 struct SYMBOL symb[];
           80 {
           81   int i;
           82   
           83   for (i=k+1;i<n;i++) {
           84     switch (symb[i].type) {
           85     case INVISIBLE:
           86       break;
           87     case NOTE: 
           88     case REST:
           89       return i;
           90       break;
           91     default:
           92       return -1;
           93     }
           94   }
           95   return -1; 
           96 }
           97 
           98 /* ----- preceded_by_note ------ */
           99 int preceded_by_note (k,n,symb)
          100 int k,n;
          101 struct SYMBOL symb[];
          102 {
          103   int i;
          104   
          105   for (i=k-1;i>=0;i--) {
          106     switch (symb[i].type) {
          107     case INVISIBLE:
          108       break;
          109     case NOTE: 
          110     case REST:
          111       return i;
          112       break;
          113     default:
          114       return -1;
          115     }
          116   }
          117   return -1; 
          118 }
          119 
          120 
          121 void xch (i,j)  /* sub to exchange two integers */
          122 int *i,*j;
          123 {
          124   int k;
          125   k=*i;
          126   *i=*j;
          127   *j=k;
          128 }
          129 
          130 
          131 
          132 /* ----- print_linetype ----------- */
          133 void print_linetype (t)
          134 int t;
          135 {
          136 
          137   if      (t== COMMENT)           printf("COMMENT\n");
          138   else if (t== MUSIC)             printf("MUSIC\n"); 
          139   else if (t== E_O_F)             printf("E_O_F\n");
          140   else if (t== INFO)              printf("INFO\n");             
          141   else if (t== TITLE)             printf("TITLE\n");            
          142   else if (t== METER)             printf("METER\n");  
          143   else if (t== PARTS)             printf("PARTS\n");  
          144   else if (t== KEY)               printf("KEY\n");  
          145   else if (t== XREF)              printf("XREF\n");     
          146   else if (t== DLEN)              printf("DLEN\n");  
          147   else if (t== HISTORY)           printf("HISTORY\n");  
          148   else if (t== TEMPO)             printf("TEMPO\n");  
          149   else if (t== BLANK)             printf("BLANK\n");
          150   else if (t== VOICE)             printf("VOICE\n");
          151   else if (t== MWORDS)            printf("MWORDS\n");
          152   else if (t== PSCOMMENT)         printf("PSCOMMENT\n");
          153   else                            printf("UNKNOWN LINE TYPE\n");
          154 }
          155 
          156 /* ----- print_syms: show sym properties set by parser ------ */
          157 void print_syms(num1,num2,symb)
          158 int num1,num2;
          159 struct SYMBOL symb[];
          160 {
          161   int i,t,j,y,nsh;
          162   char dsym[21] = {' ','~','.','J','M','H','u','v','R','T','K'};
          163   char bsym[10]  = {'-', '1' ,'2', '3', '4', '5', '6', '7', '8', '9'};
          164   char str[21];
          165 
          166   printf ("\n---------- Symbol list ----------\n");
          167   printf ("word  slur  eol  num  description\n");
          168 
          169   for (i=num1;i<num2;i++) {
          170     printf (" %c %c   %c %c   %c  ", 
          171             bsym[symb[i].word_st], bsym[symb[i].word_end],
          172             bsym[symb[i].slur_st], bsym[symb[i].slur_end],
          173             bsym[symb[i].eoln] ); 
          174     printf ("%4d  ", i);
          175     t=symb[i].type;
          176     switch (t) {
          177 
          178     case NOTE:
          179     case REST:
          180       if (t==NOTE) printf ("NOTE ");
          181       if (t==REST) printf ("REST ");
          182       if (symb[i].npitch>1) printf (" [");
          183       for (j=0;j<symb[i].npitch;j++) {
          184         printf (" ");
          185         if (symb[i].accs[j]==A_SH) printf ("^");
          186         if (symb[i].accs[j]==A_NT) printf ("=");
          187         if (symb[i].accs[j]==A_FT) printf ("_");
          188         if (symb[i].accs[j]==A_DS) printf ("^^");
          189         if (symb[i].accs[j]==A_DF) printf ("__");
          190         y=3*(symb[i].pits[j]-18)+symb[i].yadd;
          191         strcpy (str,"z");
          192         if (t==NOTE) symbolic_pitch (symb[i].pits[j],str);
          193         printf ("%s(%d)", str, symb[i].lens[j]); 
          194       }
          195       if (symb[i].npitch>1) printf (" ]");
          196       if (symb[i].p_plet)  
          197         printf ("  (%d:%d:%d", symb[i].p_plet,symb[i].q_plet,symb[i].r_plet);
          198       if (strlen(symb[i].text)>0) printf ("  \"%s\"", symb[i].text);
          199       if (symb[i].dc.n>0) {
          200         printf ("  deco ");
          201         for (j=0;j<symb[i].dc.n;j++) 
          202           printf ("%c",dsym[symb[i].dc.t[j]]);
          203       }
          204       if (symb[i].gr.n>0) {
          205         printf ("  grace ");
          206         for (j=0;j<symb[i].gr.n;j++) {
          207           if (j>0) printf ("-");
          208           if (symb[i].gr.a[j]==A_SH) printf ("^");
          209           if (symb[i].gr.a[j]==A_NT) printf ("=");
          210           if (symb[i].gr.a[j]==A_FT) printf ("_");
          211           symbolic_pitch (symb[i].gr.p[j],str);
          212           printf ("%s",str);
          213         }
          214       }
          215       break;
          216 
          217     case BAR:
          218       printf ("BAR  ======= ");
          219       if (symb[i].u==B_SNGL)  printf ("single");
          220       if (symb[i].u==B_DBL)   printf ("double");
          221       if (symb[i].u==B_LREP)  printf ("left repeat");
          222       if (symb[i].u==B_RREP)  printf ("right repeat");
          223       if (symb[i].u==B_DREP)  printf ("double repeat");
          224       if (symb[i].u==B_FAT1)  printf ("thick-thin");
          225       if (symb[i].u==B_FAT2)  printf ("thin-thick");
          226       if (symb[i].u==B_INVIS) printf ("invisible");
          227       if (symb[i].v) printf (", ending %d", symb[i].v);
          228       if (strlen(symb[i].text)>0) printf (", label \"%s\"",symb[i].text);
          229       break;
          230 
          231     case CLEF:
          232       if (symb[i].u==TREBLE) printf ("CLEF  treble");
          233       if (symb[i].u==BASS)   printf ("CLEF  bass");
          234       if (symb[i].u==ALTO)   printf ("CLEF  alto");
          235       break;
          236 
          237     case TIMESIG:
          238       printf ("TIMESIG  ");
          239       if (symb[i].w==1)      printf ("C");
          240       else if (symb[i].w==2) printf ("C|");
          241       else                   printf ("%d/%d", symb[i].u,symb[i].v);
          242       break;
          243 
          244     case KEYSIG: 
          245       printf ("KEYSIG   ");
          246       if (symb[i].t==A_SH) printf ("sharps ");
          247       if (symb[i].t==A_FT) printf ("flats ");
          248       printf ("%d to %d", symb[i].u,symb[i].v);
          249       if (symb[i].w <= symb[i].v) 
          250         printf (", neutrals from %d", symb[i].w); 
          251       break;
          252 
          253     case INVISIBLE:
          254       printf ("INVIS   ");
          255       break;
          256 
          257     default:
          258       printf ("UNKNOWN ");
          259       break;
          260     }
          261     printf ("\n");
          262 
          263   }
          264   printf ("\n");
          265 }
          266 
          267 /* ----- print_vsyms: print symbols for all voices ----- */
          268 void print_vsyms ()
          269 {
          270   int i;
          271 
          272   printf("\n");
          273   for (i=0;i<nvoice;i++) {
          274     if (nvoice>1) 
          275       printf ("Voice <%s> (%d of %d)", voice[i].id,i,nvoice);
          276     print_syms (0,voice[i].nsym,symv[i]);
          277   }
          278 }
          279 
          280 
          281 /* ----- set_head_directions ----------- */
          282 
          283 #define ABS(a)  ((a)>0) ? (a) : (-a)
          284 
          285 /* decide whether to shift heads to other side of stem on chords */
          286 /* also position accidentals to avoid too much overlap */
          287 void set_head_directions (s)
          288 struct SYMBOL *s;
          289 {
          290   int i,n,nx,sig,d,da,shift,nac;
          291   int i1,i2,m;
          292   float dx,xx,xmn;
          293 
          294   n=s->npitch;
          295   sig=-1;
          296   if (s->stem>0) sig=1;
          297   for (i=0;i<n;i++) {
          298     s->shhd[i]=0; 
          299     s->shac[i]=8; 
          300     if (s->head==H_OVAL) s->shac[i]+=3; 
          301     s->xmn=0;
          302     s->xmx=0;
          303   }
          304   if (n<2) return;
          305 
          306   /* sort heads by pitch */
          307   for (;;) {
          308     nx=0;
          309     for (i=1;i<n;i++) {
          310       if ( (s->pits[i]-s->pits[i-1])*sig>0 ) {
          311         xch (&s->pits[i],&s->pits[i-1]);
          312         xch (&s->lens[i],&s->lens[i-1]);
          313         xch (&s->accs[i],&s->accs[i-1]);
          314         xch (&s->sl1[i],&s->sl1[i-1]); 
          315         xch (&s->sl2[i],&s->sl2[i-1]); 
          316         xch (&s->ti1[i],&s->ti1[i-1]); 
          317         xch (&s->ti2[i],&s->ti2[i-1]); 
          318         nx++;
          319       }
          320     }
          321     if (!nx) break;
          322   }
          323   
          324   shift=0;                                 /* shift heads */
          325   for (i=n-2;i>=0;i--) {
          326     d=s->pits[i+1]-s->pits[i];
          327     if (d<0) d=-d;
          328     if ((d>=2) || (d==0)) 
          329       shift=0;
          330     else {
          331       shift=1-shift;
          332       if (shift) {
          333         dx=7.8;
          334         if (s->head==H_EMPTY) dx=7.8;
          335         if (s->head==H_OVAL)  dx=10.0;
          336         if (s->stem==-1) s->shhd[i]=-dx;
          337         else             s->shhd[i]=dx;
          338       }
          339     }
          340     if (s->shhd[i] < s->xmn) s->xmn = s->shhd[i];
          341     if (s->shhd[i] > s->xmx) s->xmx = s->shhd[i];
          342   }
          343 
          344   shift=0;                                 /* shift accidentals */
          345   i1=0; i2=n-1;
          346   if (sig<0) { i1=n-1; i2=0; }
          347   for (i=i1; ; i=i+sig) {          /* count down in terms of pitch */
          348     xmn=0;                         /* left-most pos of a close head */
          349     nac=99;                        /* relative pos of next acc above */
          350     for (m=0;m<n;m++) {
          351       xx=s->shhd[m];
          352       d=s->pits[m]-s->pits[i];
          353       da=ABS(d);
          354       if ((da<=5) && (s->shhd[m]<xmn)) xmn=s->shhd[m];
          355       if ((d>0) && (da<nac) && s->accs[m]) nac=da;
          356     }
          357     s->shac[i]=8.5-xmn+s->shhd[i];   /* aligns accidentals in column */
          358     if (s->head==H_EMPTY) s->shac[i] += 1.0;
          359     if (s->head==H_OVAL)  s->shac[i] += 3.0;
          360     if (s->accs[i]) {
          361       if (nac>=6)                        /* no overlap */
          362         shift=0;
          363       else if (nac>=4) {                 /* weak overlap */
          364         if (shift==0) shift=1;
          365         else          shift=shift-1;
          366       }
          367       else {                             /* strong overlap */
          368         if      (shift==0) shift=2;
          369         else if (shift==1) shift=3;
          370         else if (shift==2) shift=1;
          371         else if (shift==3) shift=0;
          372       }
          373 
          374       while (shift>=4) shift -=4;
          375       s->shac[i] += 3*shift;
          376     }
          377     if (i==i2) break;
          378   }
          379 
          380 }
          381 
          382 
          383 /* ----- set_minsyms: want at least one symbol in each voice --- */
          384 void set_minsyms(ivc)
          385 int ivc;
          386 {
          387   int n2;
          388 
          389   n2=voice[ivc].nsym;
          390   printf ("set_minsyms:  n2=%d\n",n2);
          391   if (n2>0) return;
          392 
          393   symv[ivc][n2]=zsym;
          394   symv[ivc][n2].type = INVISIBLE;
          395   symv[ivc][n2].u    = 3;
          396   symv[ivc][n2].v    = 3;
          397   symv[ivc][n2].w    = 3;
          398   voice[ivc].nsym++;
          399 
          400 }
          401 
          402 
          403 /* ----- set_sym_chars: set symbol characteristics --- */
          404 void set_sym_chars (n1,n2,symb)
          405 int n1,n2;
          406 struct SYMBOL symb[];
          407 {
          408   int i,np,m,ymn,ymx;
          409   float yav,yy;
          410 
          411   for (i=n1;i<n2;i++) {   
          412     if ((symb[i].type==NOTE)||(symb[i].type==REST)) {
          413       symb[i].y=3*(symb[i].pits[0]-18)+symb[i].yadd;
          414       if (symb[i].type==REST) symb[i].y=12;
          415       yav=0;
          416       ymn=1000;
          417       ymx=-1000;
          418       np=symb[i].npitch;
          419       for (m=0;m<np;m++) {
          420         yy=3*(symb[i].pits[m]-18)+symb[i].yadd;
          421         yav=yav+yy/np;
          422         if (yy<ymn) ymn=yy;
          423         if (yy>ymx) ymx=yy;
          424       }
          425       symb[i].ymn=ymn;
          426       symb[i].ymx=ymx;
          427       symb[i].yav=yav;
          428       symb[i].ylo=ymn;
          429       symb[i].yhi=ymx;
          430 
          431     }
          432   }
          433 }
          434 
          435 /* ----- set_beams: decide on beams ---- */
          436 void set_beams (n1,n2,symb)
          437 int n1,n2;
          438 struct SYMBOL symb[];
          439 {
          440   int j,lastnote,start_flag;
          441   
          442   /* separate words at notes without flags */
          443   start_flag=0;
          444   lastnote=-1;
          445   for (j=n1;j<n2;j++) {
          446     if (symb[j].type==NOTE) {
          447       if (start_flag) {
          448         symb[j].word_st=1;
          449         start_flag=0;
          450       }
          451       if (symb[j].flags==0) {
          452         if (lastnote>=0) symb[lastnote].word_end=1;
          453         symb[j].word_st=1;
          454         symb[j].word_end=1;
          455         start_flag=1;
          456       }
          457       lastnote=j;
          458     }
          459   }
          460   
          461 }
          462 
          463 /* ----- set_stems: decide on stem directions and lengths ---- */
          464 void set_stems (n1,n2,symb)
          465 int n1,n2;
          466 struct SYMBOL symb[];
          467 {
          468   int beam,j,k,n,stem,laststem;
          469   float avg,slen,lasty,dy;
          470   
          471   /* set stem directions; near middle, use previous direction */
          472   beam=0;
          473   laststem=0;       
          474   for (j=n1; j<n2; j++) {
          475     if (symb[j].type!=NOTE) laststem=0; 
          476 
          477     if (symb[j].type==NOTE) {
          478 
          479       symb[j].stem=0;                  
          480       if (symb[j].len<WHOLE) symb[j].stem=1;
          481       if (symb[j].yav>=12) symb[j].stem=-symb[j].stem;
          482       if ((symb[j].yav>11) && (symb[j].yav<13) && (laststem!=0)) {
          483         dy=symb[j].yav-lasty;
          484         if ((dy>-7) && (dy<7)) symb[j].stem=laststem;
          485       }
          486       
          487       if (symb[j].word_st && (!symb[j].word_end)) {   /* start of beam */
          488         avg=0; 
          489         n=0;
          490         for (k=j;k<n2;k++) {
          491           if (symb[k].type==NOTE) {
          492             avg=avg+symb[k].yav;
          493             n++;
          494           }
          495           if (symb[k].word_end) break;
          496         }
          497         avg=avg/n;
          498         stem=1;
          499         if (avg>=12) stem=-1;
          500         if ((avg>11) && (avg<13) && (laststem!=0)) stem=laststem;
          501         beam=1;
          502       }
          503       
          504       if (beam) symb[j].stem=stem;
          505       if (symb[j].word_end) beam=0;
          506       if (bagpipe) symb[j].stem=-1;
          507       if (symb[j].len>=WHOLE) symb[j].stem=0;
          508       laststem=symb[j].stem;
          509       if (symb[j].len>=HALF) laststem=0;
          510       lasty=symb[j].yav;
          511     }
          512   }
          513   
          514   /* shift notes in chords (need stem direction to do this) */
          515   for (j=n1;j<n2;j++) 
          516     if (symb[j].type==NOTE) set_head_directions (&symb[j]);
          517   
          518   /* set height of stem end, without considering beaming for now */
          519   for (j=n1; j<n2; j++) if (symb[j].type==NOTE) {
          520     slen=STEM;
          521     if (symb[j].npitch>1) slen=STEM_CH; 
          522     if (symb[j].flags==3) slen += 4;
          523     if (symb[j].flags==4) slen += 9;
          524     if ((symb[j].flags>2) && (symb[j].stem==1)) slen -= 1;
          525     if (symb[j].stem==1) {
          526       symb[j].y=symb[j].ymn;
          527       symb[j].ys=symb[j].ymx+slen;
          528     }
          529     else if (symb[j].stem==-1) {
          530       symb[j].y=symb[j].ymx;
          531       symb[j].ys=symb[j].ymn-slen;
          532     }
          533     else {
          534       symb[j].y=symb[j].ymx;
          535       symb[j].ys=symb[j].ymx;
          536     }
          537   }
          538 }
          539 
          540 /* ----- set_sym_times: set time axis; also count through bars ----- */
          541 int set_sym_times (n1,n2,symb,meter0)
          542 int n1,n2;
          543 struct SYMBOL symb[];
          544 struct METERSTR meter0;
          545 {
          546   int i,pp,qq,rr,meter1,meter2,count,bnum,lastb,bsave;
          547   int qtab[] = {0,0,3,2,3,0,2,0,3,0};
          548   float time,factor,fullmes;
          549 
          550   meter1=meter0.meter1;
          551   meter2=meter0.meter2;
          552 
          553   lastb=bnum=0;
          554   bsave=1;
          555 
          556   time=0.0;
          557   factor=1.0;
          558   for (i=n1;i<n2;i++) {   
          559     symb[i].time=time;
          560 
          561     /* count through bar numbers, put into symb.t */
          562     if (symb[i].type==BAR) {
          563       fullmes=(WHOLE*meter1)/meter2;
          564       if (bnum==0) {
          565         bnum=barinit;
          566         if (fullmes<time+0.001) bnum++;
          567         symb[i].t=bnum;
          568         lastb=i;
          569       } 
          570       else if (time-symb[lastb].time>=fullmes-0.001) {
          571         bnum++;
          572         while (symb[i+1].type==BAR) {i++; symb[i].time=time; }
          573         symb[i].t=bnum;
          574         lastb=i;
          575       }
          576       if (symb[i].v>1) {
          577         bnum=bsave;
          578         symb[i].t=0;
          579       }
          580       if (symb[i].v==1) bsave=bnum;
          581     }
          582     
          583     if ((symb[i].type==NOTE)||(symb[i].type==REST)) {
          584       if (symb[i].p_plet) {
          585         pp=symb[i].p_plet;
          586         qq=symb[i].q_plet;
          587         rr=symb[i].r_plet;
          588         if (qq==0) {
          589           qq=qtab[pp];
          590           if (qq==0) {
          591             qq=2;
          592             if (meter1%3==0) qq=3;
          593           }
          594         }
          595         factor=((float)qq)/((float)pp);
          596         count=rr;
          597       }
          598       time=time+factor*symb[i].len;
          599       if (count>0) count--;
          600       if (count==0) factor=1;
          601     }
          602 
          603     if (symb[i].type==TIMESIG) {     /* maintain meter as we go along */
          604       meter1=symb[i].u;
          605       meter2=symb[i].v;
          606     }
          607 
          608   }
          609 
          610   return bnum;
          611 
          612 }
          613 
          614 /* ----- set_sym_widths: set widths and prefered space --- */
          615 /* This routine sets the minimal left and right widths wl,wr
          616    so that successive symbols are still separated when
          617    no extra glue is put between them. It also sets the prefered 
          618    spacings pl,pr for good output and xl,xr for expanded layout.
          619    All distances in pt relative to the symbol center. */
          620 
          621 #define AT_LEAST(a,b)  if((a)<(b)) a=b;
          622 void set_sym_widths (ns1,ns2,symb,ivc)
          623 int ns1,ns2,ivc;
          624 struct SYMBOL symb[];
          625 {
          626   int i,n,j0,j,m,n1,n2,bt,k,sl,k1,k2,got_note,ok;
          627   float xx,w,swfac,spc,dur,yy;
          628   char t[81],tt[81];
          629 
          630   swfac=1.0;
          631   if (strstr(cfmt.vocalfont.name,"Times-Roman"))    swfac=1.00;
          632   if (strstr(cfmt.vocalfont.name,"Times-Bold"))     swfac=1.05;
          633   if (strstr(cfmt.vocalfont.name,"Helvetica"))      swfac=1.10;
          634   if (strstr(cfmt.vocalfont.name,"Helvetica-Bold")) swfac=1.15;
          635 
          636   got_note=0;
          637   for (i=ns1;i<ns2;i++) {
          638     switch (symb[i].type) {
          639       
          640     case INVISIBLE:   /* empty space; shrink,space,stretch from u,v,w */
          641       symb[i].wl=symb[i].wr=0.5*symb[i].u;
          642       symb[i].pl=symb[i].pr=0.5*symb[i].v;
          643       symb[i].xl=symb[i].xr=0.5*symb[i].w;
          644       break;
          645 
          646     case NOTE:
          647     case REST:
          648       got_note=1;
          649       dur=symb[i].len;
          650       symb[i].wl=symb[i].wr=4.5;
          651       if (symb[i].head==H_EMPTY) {symb[i].wl=6.0; symb[i].wr=14.0;}
          652       if (symb[i].head==H_OVAL)  {symb[i].wl=8.0; symb[i].wr=18.0;}
          653       symb[i].pl=symb[i].xl=symb[i].wl;
          654       symb[i].pr=symb[i].xr=symb[i].wr;
          655       
          656       /* room for shifted heads and accidental signs */
          657       for (m=0;m<symb[i].npitch;m++) {
          658         xx=symb[i].shhd[m];
          659         AT_LEAST (symb[i].wr, xx+6); 
          660         AT_LEAST (symb[i].wl, -xx+6); 
          661         if (symb[i].accs[m]) {
          662           xx=xx-symb[i].shac[m]; 
          663           AT_LEAST (symb[i].wl, -xx+3); 
          664         }
          665         AT_LEAST (symb[i].xl, -xx+3); 
          666         symb[i].pl=symb[i].wl;
          667         symb[i].xl=symb[i].wl;
          668       }
          669         
          670       /* room for slide */
          671       for (k=0;k<symb[i].dc.n;k++) {
          672         if (symb[i].dc.t[k]==D_SLIDE) symb[i].wl += 10;
          673       }
          674 
          675       /* room for grace notes */
          676       if (symb[i].gr.n>0) {
          677         xx=GSPACE0;
          678         if (symb[i].gr.a[0]) xx=xx+3.5;
          679         for (j=1;j<symb[i].gr.n;j++) {                   
          680           xx=xx+GSPACE;
          681           if (symb[i].gr.a[j]) xx=xx+4;
          682         }
          683         symb[i].wl = symb[i].wl + xx+1;
          684         symb[i].pl = symb[i].pl + xx+1;
          685         symb[i].xl = symb[i].xl + xx+1;
          686       }
          687       
          688       /* space for flag if stem goes up on standalone note */
          689       if (symb[i].word_st && symb[i].word_end) 
          690         if ((symb[i].stem==1) && symb[i].flags>0) 
          691           AT_LEAST (symb[i].wr, 12);
          692 
          693       /* leave room for dots */
          694       if (symb[i].dots>0) {
          695         AT_LEAST (symb[i].wr,12+symb[i].xmx);
          696         if (symb[i].dots>=2) symb[i].wr=symb[i].wr+3.5;
          697         n=(int) symb[i].y;
          698         /* special case: standalone with up-stem and flags */
          699         if (symb[i].flags && (symb[i].stem==1) && !(n%6)) 
          700           if ((symb[i].word_st==1) && (symb[i].word_end==1)) {
          701             symb[i].wr=symb[i].wr+DOTSHIFT;
          702             symb[i].pr=symb[i].pr+DOTSHIFT;
          703             symb[i].xr=symb[i].xr+DOTSHIFT;
          704           }
          705       }
          706 
          707       /* extra space when down stem follows up stem */
          708       j0=preceded_by_note(i,ns2,symb);
          709       if ((j0>=0) && (symb[j0].stem==1) && (symb[i].stem==-1)) 
          710         AT_LEAST (symb[i].wl, 7);
          711 
          712       /* make sure helper lines don't overlap */
          713       if ((j0>=0) && (symb[i].y>27) && (symb[j0].y>27)) 
          714         AT_LEAST (symb[i].wl, 7.5);
          715 
          716       /* leave room guitar chord */
          717       if (strlen(symb[i].text)>0) {
          718         /* special case: guitar chord under ending 1 or 2 */
          719         /* leave some room to the left of the note */
          720         if ((i>0) && (symb[i-1].type==BAR)) {
          721           bt=symb[i-1].v;
          722           if (bt) AT_LEAST (symb[i].wl, 18);
          723         }
          724         /* rest is same for all guitar chord cases */
          725         tex_str(symb[i].text,t,&w);
          726         xx=cfmt.gchordfont.size*w;
          727         xx=xx*1.05;     /* extra space mainly for helvetica font */
          728         spc=xx*GCHPRE;
          729         k1=prec_note(i,ns2,symb);
          730         k2=next_note(i,ns2,symb);
          731         if (spc>8.0) spc=8.0;
          732         if ((k1>0) && (strlen(symb[k1].text)>0))
          733           AT_LEAST (symb[i].wl, spc); 
          734         if ((k2>0) && (strlen(symb[k2].text)>0)) 
          735           AT_LEAST (symb[i].wr, xx-spc); 
          736       }        
          737 
          738       /* leave room for vocals under note */
          739       for (j=0;j<NWLINE;j++) {
          740         if (symb[i].wordp[j]) {
          741           sl=tex_str(symb[i].wordp[j],t,&w);
          742           xx=swfac*cfmt.vocalfont.size*(w+2*cwid(' '));
          743           AT_LEAST (symb[i].wl,xx*VOCPRE);
          744           AT_LEAST (symb[i].wr,xx*(1.0-VOCPRE));
          745         }
          746       } 
          747         
          748       AT_LEAST (symb[i].pl, symb[i].wl);
          749       AT_LEAST (symb[i].xl, symb[i].wl);
          750       AT_LEAST (symb[i].pr, symb[i].wr);
          751       AT_LEAST (symb[i].xr, symb[i].wr);
          752       break;
          753       
          754     case BAR:
          755       symb[i].wl=symb[i].wr=0;
          756       if (symb[i].u==B_SNGL)         symb[i].wl=symb[i].wr=3;
          757       else if (symb[i].u==B_DBL)   { symb[i].wl=7; symb[i].wr=4;  }
          758       else if (symb[i].u==B_LREP)  { symb[i].wl=3; symb[i].wr=12; }
          759       else if (symb[i].u==B_RREP)  { symb[i].wl=12; symb[i].wr=3; }
          760       else if (symb[i].u==B_DREP)    symb[i].wl=symb[i].wr=12;
          761       else if (symb[i].u==B_FAT1)  { symb[i].wl=3;  symb[i].wr=9; }
          762       else if (symb[i].u==B_FAT2)  { symb[i].wl=9;  symb[i].wr=3; }
          763 
          764       if (ivc==ivc0) {       /* bar numbers and labels next */
          765         ok=0;
          766         if ((cfmt.barnums>0) && (symb[i].t%cfmt.barnums==0)) ok=1;
          767         if (strlen(symb[i].text)>0) ok=1;
          768         if (ok) {
          769           if (strlen(symb[i].text)>0) {
          770             tex_str(symb[i].text,t,&w);
          771             xx=cfmt.barlabelfont.size*w*0.5;
          772           }
          773           else {
          774             sprintf (tt,"%d",symb[i].t);
          775             tex_str(tt,t,&w);
          776             xx=cfmt.barnumfont.size*w*0.5;
          777           }
          778           yy=60; 
          779           if (!got_note) yy=0; 
          780           if ((i>0) && (symb[i-1].type==NOTE)) {
          781             yy=symb[i-1].ymx;
          782             if (symb[i-1].stem==1) yy=yy+26;
          783           }
          784           if ((i>0) && (strlen(symb[i-1].text)>0)) yy=60;
          785           AT_LEAST (symb[i].wl, 2); 
          786           if (yy>BNUMHT-4.0) AT_LEAST (symb[i].wl, xx+1); 
          787           if (!got_note) AT_LEAST (symb[i].wl, xx+1); 
          788           yy=0;
          789           if (symb[i+1].type==NOTE) yy=symb[i+1].ymx;
          790           if (yy>BNUMHT-4.0) AT_LEAST (symb[i].wr, xx+2); 
          791           if (strlen(symb[i+1].text)>0) AT_LEAST (symb[i].wr, xx+4); 
          792         }
          793       }
          794 
          795       symb[i].pl=symb[i].wl;
          796       symb[i].pr=symb[i].wr;
          797       symb[i].xl=symb[i].wl;
          798       symb[i].xr=symb[i].wr;
          799       break;
          800       
          801     case CLEF:
          802       symb[i].wl=symb[i].wr=symb[i].xl=13.5;
          803       symb[i].pl=symb[i].pr=symb[i].xr=11.5;
          804       break;
          805       
          806     case KEYSIG:
          807       n1=symb[i].u;    
          808       n2=symb[i].v;    
          809       if (n2>=n1) {
          810         symb[i].wl=2;
          811         symb[i].wr=5*(n2-n1+1)+2;
          812         symb[i].pl=symb[i].wl;
          813         symb[i].pr=symb[i].wr;
          814         symb[i].xl=symb[i].wl;
          815         symb[i].xr=symb[i].wr;
          816       }
          817       else {
          818         symb[i].wl=symb[i].pl=symb[i].xl=3;
          819         symb[i].wr=symb[i].pr=symb[i].xr=3;
          820       }
          821       break;
          822 
          823     case TIMESIG:
          824       symb[i].wl=8+4*(strlen(symb[i].text)-1);
          825       symb[i].wr=symb[i].wl+4;
          826       symb[i].pl=symb[i].wl;
          827       symb[i].pr=symb[i].wr;
          828       symb[i].xl=symb[i].wl;
          829       symb[i].xr=symb[i].wr;
          830       break;
          831       
          832     default:
          833       printf (">>> cannot set width for sym type %d\n", symb[i].type);
          834       symb[i].wl=symb[i].wr=symb[i].xl=0;
          835       symb[i].pl=symb[i].pr=symb[i].xr=0;
          836       break;
          837     }
          838 
          839   }
          840 }
          841 
          842 
          843 
          844 /* ----- contract_keysigs: delete duplicate keysigs at staff start ---- */
          845 /* Depending on line breaks, a key and/or meter change can come
          846    at the start of a staff. Solution: scan through symbols from start
          847    of line as long as sym is a CLEF, KEYSIG, or TIMESIG. Remove all
          848    these, but set flags so that set_initsyms will draw the
          849    key and meter which result at the end of the scan. */
          850 int contract_keysigs (ip1)
          851 int ip1;
          852 {
          853   int i,k,v,t,n3,sf,jp1,m,mtop;
          854 
          855   mtop=10000;
          856   for (v=0;v<nvoice;v++) {
          857     i=ip1;
          858     m=0;
          859     for (;;) {
          860       m++;
          861       k=xp[i].p[v];
          862       if (k>=0) {
          863         if (symv[v][k].type==CLEF) {
          864           voice[v].key.ktype=symv[v][k].u;
          865           symv[v][k].type=INVISIBLE; 
          866         }
          867         else if (symv[v][k].type==KEYSIG) {
          868           sf=symv[v][k].v;   
          869           n3=symv[v][k].w;   
          870           if (n3-1<sf) sf=n3-1;
          871           t =symv[v][k].t;   
          872           if (t==A_FT) sf=-sf;
          873           if (t==A_NT) sf=0;
          874           voice[v].key.sf=sf;
          875           symv[v][k].type=INVISIBLE; 
          876         }
          877         else if (symv[v][k].type==TIMESIG) {
          878           voice[v].meter.insert=1;
          879           voice[v].meter.meter1=symv[v][k].u;
          880           voice[v].meter.meter2=symv[v][k].v;
          881           voice[v].meter.mflag =symv[v][k].w;
          882           strcpy(voice[v].meter.top,symv[v][k].text);
          883           symv[v][k].type=INVISIBLE; 
          884         }
          885         else 
          886           break;
          887       }
          888       i=xp[i].next;
          889       if (i==XP_END) {
          890         i=xp[i].prec;
          891         break;
          892       }
          893     }
          894     if (m<mtop && i>=0) {mtop=m; jp1=i; }
          895   }
          896 
          897   /* set glue for first symbol */
          898   xp[jp1].shrink = xp[jp1].wl+3;
          899   xp[jp1].space  = xp[jp1].wl+9;
          900   xp[jp1].stretch= xp[jp1].wl+16;
          901 
          902   return jp1;
          903 
          904 }
          905 
          906 /* ----- set_initsyms: set symbols at start of staff ----- */
          907 int set_initsyms (v,wid0)
          908 int v;
          909 float *wid0;
          910 {
          911   int   k,t,n;
          912   float x;
          913 
          914   k=0;
          915   
          916   /* add clef */
          917   sym_st[v][k]=zsym;
          918   sym_st[v][k].type = CLEF;
          919   sym_st[v][k].u    = voice[ivc].key.ktype;
          920   sym_st[v][k].v    = 0;
          921   k++;
          922 
          923   /* add keysig */
          924   sym_st[v][k]=zsym;
          925   sym_st[v][k].type = KEYSIG;
          926   n=voice[ivc].key.sf;
          927   t=A_SH;
          928   if (n<0) { n=-n; t=A_FT; }
          929   sym_st[v][k].u = 1;
          930   sym_st[v][k].v = n;
          931   sym_st[v][k].w = 100;
          932   sym_st[v][k].t = t;
          933   k++;
          934 
          935   /* add timesig */
          936   if (voice[ivc].meter.insert) {
          937     sym_st[v][k]=zsym;
          938     sym_st[v][k].type = TIMESIG;
          939     sym_st[v][k].u    = voice[ivc].meter.meter1;
          940     sym_st[v][k].v    = voice[ivc].meter.meter2;
          941     sym_st[v][k].w    = voice[ivc].meter.mflag;
          942     strcpy(sym_st[v][k].text,voice[ivc].meter.top);
          943     k++;
          944     voice[ivc].meter.insert=0;
          945   }
          946 
          947   if (voice[ivc].insert_btype) {
          948     sym_st[v][k].type = BAR;
          949     sym_st[v][k].u=voice[ivc].insert_btype;
          950     sym_st[v][k].v=voice[ivc].insert_num;
          951     sym_st[v][k].t=voice[ivc].insert_bnum;
          952     strcpy(sym_st[v][k].text,voice[ivc].insert_text); 
          953     voice[ivc].insert_btype=0;
          954     voice[ivc].insert_bnum=0;
          955     k++;
          956   }
          957   
          958   n=k;
          959   set_sym_widths (0,n,sym_st[v],ivc);
          960 
          961   x=0;
          962   for (k=0;k<n;k++) {
          963     x=x+sym_st[v][k].wl;
          964     sym_st[v][k].x=x;
          965     x=x+sym_st[v][k].wr;
          966   }
          967   
          968   *wid0=x+voice[v].insert_space;
          969   return n;
          970 
          971 }
          972 
          973 
          974 /* ----- print_poslist ----- */
          975 void print_poslist ()
          976 { 
          977   int i,n,typ,vv;
          978 
          979   printf ("\n----------- xpos list -----------\n");
          980   printf (" num ptr  type      time   dur     width    tfac"
          981           "   shrk  spac  stre  eol  vptr\n");
          982 
          983   n=0;
          984   i=xp[XP_START].next;
          985   for (;;) {
          986     typ=xp[i].type;
          987     printf ("%3d %3d  %d ", n,i,typ);
          988     if      (typ==NOTE)       printf ("NOTE");
          989     else if (typ==REST)       printf ("REST");
          990     else if (typ==KEYSIG)     printf ("KEY ");
          991     else if (typ==TIMESIG)    printf ("TSIG");
          992     else if (typ==BAR)        printf ("BAR ");
          993     else if (typ==CLEF)       printf ("CLEF");
          994     else if (typ==INVISIBLE)  printf ("INVS");
          995     else                      printf ("????");
          996     printf ("  %7.2f %6.2f  %4.1f %4.1f %5.2f  %5.1f %5.1f %5.1f", 
          997             xp[i].time,xp[i].dur,xp[i].wl,xp[i].wr,xp[i].tfac,
          998             xp[i].shrink,xp[i].space,xp[i].stretch);
          999     if (xp[i].eoln) 
         1000       printf("  %d  ",xp[i].eoln);
         1001     else
         1002       printf("  -  ");
         1003     for (vv=0;vv<nvoice;vv++) {
         1004       if (xp[i].p[vv]>=0) 
         1005         printf(" %2d",xp[i].p[vv]);
         1006       else
         1007         printf("  -");
         1008     }
         1009     printf ("\n");
         1010     i=xp[i].next;
         1011     n++;
         1012     if (i==XP_END) break;
         1013   }
         1014 
         1015 } 
         1016 
         1017 
         1018 
         1019 
         1020 /* ----- insert_poslist: insert new element after element nins ----- */
         1021 int insert_poslist (nins)
         1022 int nins;
         1023 { 
         1024   int new,nxt,vv;
         1025 
         1026   new=ixpfree;
         1027   ixpfree++;
         1028   if (new>=XP_END) 
         1029     rxi("Too many symbols; use -maxs to increase limit, now ",maxSyms);
         1030 
         1031   nxt=xp[nins].next;
         1032   xp[new].prec=nins;
         1033   xp[new].next=nxt;
         1034   xp[nins].next=new;
         1035   xp[nxt].prec=new;
         1036   for (vv=0;vv<nvoice;vv++) xp[new].p[vv]=-1;
         1037           
         1038   return new;
         1039 
         1040 }
         1041 
         1042 /* ----- set_poslist: make list of horizontal posits to align voices --- */
         1043 void set_poslist ()
         1044 { 
         1045   int i,n,v,vv,typ,nok,nins;
         1046   float tol=0.01;
         1047   float d,tim;
         1048 
         1049   /* initialize xp with data from top nonempty voice, ivc0 */
         1050   v=ivc0;
         1051   n=0;
         1052   xp[0].next=1;
         1053   for (i=0;i<voice[v].nsym;i++) {
         1054     n++;
         1055     xp[n].prec=n-1;
         1056     xp[n].next=n+1;
         1057     symv[v][i].p=n;
         1058     for (vv=0;vv<nvoice;vv++) xp[n].p[vv]=-1;
         1059     xp[n].p[v]=i;
         1060     typ=symv[v][i].type;
         1061     if (typ==REST) typ=NOTE;
         1062     xp[n].type = typ;
         1063     xp[n].time = symv[v][i].time;
         1064     xp[n].dur = xp[n].tfac = 0;
         1065     xp[n].shrink = xp[n].space = xp[n].stretch =0;
         1066     xp[n].wl = xp[n].wr = 0;
         1067     xp[n].eoln=symv[v][i].eoln;
         1068   }
         1069   xp[n].next=XP_END;
         1070   xp[XP_END].prec=n;
         1071   ixpfree=n+1;
         1072  
         1073   /* find or insert syms for other voices */
         1074   for (v=0;v<nvoice;v++) {
         1075     if (voice[v].draw && v!=ivc0) {
         1076       n=XP_START;
         1077       for (i=0;i<voice[v].nsym;i++) {
         1078         tim=symv[v][i].time;
         1079         typ=symv[v][i].type;
         1080         if (typ==REST) typ=NOTE;
         1081         nok=-1;
         1082         nins=n;
         1083         for (;;) {
         1084           n=xp[n].next;
         1085           if (n==XP_END) break;
         1086           d=xp[n].time-tim;
         1087           if (xp[n].time<tim-tol) nins=n;
         1088           if (d*d<tol*tol && xp[n].type==typ) {
         1089             nok=n;
         1090             break;
         1091           }
         1092           if (xp[n].time>tim+tol) break;
         1093         }
         1094         if (nok>0) 
         1095           n=nok;
         1096         else {
         1097           n=insert_poslist (nins);
         1098           xp[n].type=typ;
         1099           xp[n].time=tim;
         1100           xp[n].dur = xp[n].tfac = 0;
         1101           xp[n].shrink = xp[n].space = xp[n].stretch =0;
         1102           xp[n].wl = xp[n].wr = 0;
         1103           xp[n].eoln=0;
         1104         }
         1105         symv[v][i].p=n;
         1106         xp[n].p[v]=i;
         1107       }
         1108     }
         1109   }
         1110   
         1111 /*|   print_poslist (); |*/
         1112 
         1113 } 
         1114 
         1115 
         1116 /* ----- set_xpwid: set symbol widths and tfac in xp list ----- */
         1117 void set_xpwid()
         1118 { 
         1119   int i,j,k,i1,i2,k1,k2,v,nsm;
         1120   float fac,dy,ff,wv,wx;
         1121 
         1122   /* set all tfacs to 1.0 */
         1123   i=i1=xp[XP_START].next;
         1124   for (;;) {
         1125     xp[i].tfac=1.0;
         1126     xp[i].wl=xp[i].wr=WIDTH_MIN;
         1127     i2=i;
         1128     i=xp[i].next;
         1129     if (i==XP_END) break;
         1130   }
         1131 
         1132   /* loop over voices. first voice last, assumed most important */
         1133   for (v=nvoice-1;v>=0;v--) {
         1134     nsm=voice[v].nsym;
         1135 
         1136     /* first symbol and last symbol */
         1137     k1=symv[v][0].p;
         1138     k2=symv[v][nsm-1].p;
         1139     if (k1==i1 && symv[v][0].wl>xp[k1].wl)     xp[k1].wl=symv[v][0].wl;
         1140     if (k2==i2 && symv[v][nsm-1].wr>xp[k2].wr) xp[k2].wr=symv[v][nsm-1].wr;
         1141     
         1142     /* loop over symbol nn pairs */
         1143     for (i=1;i<nsm;i++) {
         1144       j=i-1;
         1145       k1=symv[v][j].p;
         1146       k2=symv[v][i].p;
         1147       if (xp[k1].next==k2) {
         1148         if (symv[v][j].wr>xp[k1].wr) xp[k1].wr=symv[v][j].wr;
         1149         if (symv[v][i].wl>xp[k2].wl) xp[k2].wl=symv[v][i].wl;
         1150         
         1151         if (symv[v][j].type==NOTE && symv[v][i].type==NOTE) {
         1152           fac=1.0;
         1153           /* reduce distance under a beam */
         1154           if (symv[v][i].word_st==0) fac=fac*fnnp;
         1155           /* reduce distance for large jumps in pitch */
         1156           dy=symv[v][i].y-symv[v][j].y;
         1157           if (dy<0) dy=-dy;
         1158           ff=1-0.010*dy; 
         1159           if (ff<0.9) ff=0.9;
         1160           fac=fac*ff;
         1161           xp[k2].tfac=fac;
         1162         }
         1163       }
         1164     }
         1165   }
         1166   
         1167   /* check for all nn pairs in voice, in case some syms very wide */ 
         1168   for (v=nvoice-1;v>=0;v--) {
         1169     nsm=voice[v].nsym;
         1170     for (i=1;i<nsm;i++) {
         1171       j=i-1;
         1172       k1=symv[v][j].p;
         1173       k2=symv[v][i].p;
         1174       if (xp[k1].next!=k2) {
         1175         wv=symv[v][j].wr+symv[v][i].wl;
         1176         wx=xp[k1].wr+xp[k2].wl;
         1177         k=k1;
         1178         for (;;) {
         1179           k=xp[k].next;
         1180           if (k==k2) break;
         1181           wx=wx+xp[k].wl+xp[k].wr;
         1182         }
         1183         if(wx<wv) {
         1184           fac=wv/wx;
         1185           xp[k1].wr=fac*xp[k1].wr;
         1186           xp[k2].wl=fac*xp[k2].wl;
         1187           k=k1;
         1188           for (;;) {
         1189             k=xp[k].next;
         1190             if (k==k2) break;
         1191             xp[k].wl=fac*xp[k].wl;
         1192             xp[k].wr=fac*xp[k].wr;
         1193           }
         1194 
         1195         }
         1196       }
         1197     }
         1198   }
         1199 
         1200 } 
         1201 
         1202 
         1203 /* ----- set_spaces: set the shrink,space,stretch distances ----- */
         1204 void set_spaces ()
         1205 { 
         1206   int i,j,n,nxt,typ,typl,meter1,meter2;
         1207   float w0,w1,w2;
         1208   float vbnp,vbnx,vnbp,vnbx;
         1209 
         1210   /* note lengths for spaces at bars. Use dcefault meter for now */
         1211   meter1=default_meter.meter1;
         1212   meter2=default_meter.meter2;
         1213   vbnp=(rbnp*meter1*BASE)/meter2;
         1214   vbnx=(rbnx*meter1*BASE)/meter2;
         1215   vnbp=(rnbp*meter1*BASE)/meter2;
         1216   vnbx=(rnbx*meter1*BASE)/meter2;
         1217 
         1218   /* redefine durations as differences in start times */
         1219   n=0;
         1220   i=xp[XP_START].next;
         1221   for (;;) {
         1222     nxt=xp[i].next;
         1223     if (nxt!=XP_END) xp[i].dur=xp[nxt].time-xp[i].time;
         1224     i=nxt;
         1225     n++;
         1226     if (i==XP_END) break;
         1227   }
         1228 
         1229   i=xp[XP_START].next;
         1230   j=-1;
         1231   typl=0;
         1232   for (;;) {
         1233     nxt=xp[i].next;
         1234     typ=xp[i].type;
         1235 
         1236     /* shrink distance is sum of left and right widths */
         1237     if (j>=0) 
         1238       xp[i].shrink=xp[j].wr+xp[i].wl;
         1239     else
         1240       xp[i].shrink=xp[i].wl;
         1241     xp[i].space=xp[i].stretch=xp[i].shrink;
         1242     
         1243     if (xp[i].type==NOTE) { 
         1244       
         1245       if (typl==NOTE) {             /* note after another note */
         1246         w1 = lnnp*nwid(xp[j].dur);
         1247         w2 = lnnp*nwid(xp[i].dur);
         1248         xp[i].space = bnnp*w1 + (1-bnnp)*0.5*(w1+w2);
         1249         w1 = lnnx*xwid(xp[j].dur);
         1250         w2 = lnnx*xwid(xp[i].dur);
         1251         xp[i].stretch = bnnx*w1 + (1-bnnx)*0.5*(w1+w2);
         1252       }
         1253       
         1254       else {                        /* note at start of bar */
         1255         w1 = lbnp*nwid(xp[i].dur);
         1256         w0 = lbnp*nwid(vbnp);
         1257         if (w0>w1) w0=w1;
         1258         xp[i].space = bbnp*w1 + (1-bbnp)*w0 + (j>=0 ? xp[j].wr : 0);
         1259         if (xp[i].space<14.0) xp[i].space=14.0;
         1260         w1 = lbnx*xwid(xp[i].dur);
         1261         w0 = lbnx*xwid(vbnp);
         1262         if (w0>w1) w0=w1;
         1263         xp[i].stretch = bbnx*w1 + (1-bbnx)*w0 + (j>=0 ? xp[j].wr : 0);
         1264         if (xp[i].stretch<18.0) xp[i].stretch=18.0;
         1265         if (xp[i].shrink<12.0) xp[i].shrink=12.0;
         1266       }
         1267     } 
         1268     
         1269     else {                         /* some other symbol after note */
         1270       if (typl==NOTE) {
         1271         w1 = lnbp*nwid(xp[j].dur);
         1272         w0 = lnbp*nwid(vnbp);
         1273         xp[i].space = bnbp*w1 + (1-bnbp)*w0 + xp[i].wl;
         1274         if (xp[i].space<13.0) xp[i].space=13.0;
         1275         w1 = lnbx*xwid(xp[j].dur);
         1276         w0 = lnbx*xwid(vnbx);
         1277         xp[i].stretch = bnbx*w1 + (1-bnbx)*w0 + xp[i].wl;
         1278         if (xp[i].stretch<17.0) xp[i].stretch=17.0;
         1279       }
         1280     }
         1281 
         1282     /* multiply space and stretch by factors tfac */
         1283     xp[i].space   = xp[i].space*xp[i].tfac;
         1284     xp[i].stretch = xp[i].stretch*xp[i].tfac;
         1285 
         1286     /* make sure that shrink < space < stretch */
         1287     if (xp[i].space<xp[i].shrink)  xp[i].space=xp[i].shrink;
         1288     if (xp[i].stretch<xp[i].space) xp[i].stretch=xp[i].space;
         1289 
         1290     j=i;
         1291     typl=typ;
         1292     i=nxt;
         1293 
         1294     if (i==XP_END) break;
         1295   }
         1296 
         1297   if (verbose>=11) print_poslist ();
         1298 
         1299 }
         1300 
         1301 /* ----- check_overflow: returns upper limit which fits on staff ------ */
         1302 int check_overflow (ip1,ip2,width)
         1303 int ip1,ip2;
         1304 float width;
         1305 {
         1306 
         1307   int i,jp2,lastcut,nbar,need_note;
         1308   float space,shrink,stretch,alfa,alfa0;
         1309   
         1310   /* max shrink is alfa0 */
         1311   alfa0=ALFA_X;           
         1312   if (cfmt.continueall) alfa0=cfmt.maxshrink;
         1313   if (gmode==G_SHRINK)  alfa0=1.0;
         1314   if (gmode==G_SPACE)   alfa0=0.0;
         1315   if (gmode==G_STRETCH) alfa0=1.0;
         1316 
         1317   jp2=ip2;
         1318   space=shrink=stretch=0;
         1319   lastcut=-1;
         1320   nbar=0;
         1321   need_note=1;
         1322   i=ip1;
         1323   for (;;) {
         1324     space=space+xp[i].space;
         1325     shrink=shrink+xp[i].shrink;
         1326     stretch=stretch+xp[i].stretch;
         1327     alfa=0;
         1328     if (space>shrink) {
         1329       alfa=(space-width)/(space-shrink);
         1330       if (xp[i].type!=BAR) 
         1331         alfa=((space+8)-width)/(space-shrink);
         1332     }
         1333 
         1334     if (alfa>alfa0) {
         1335       if (!cfmt.continueall) {
         1336         if (verbose<=3) printf ("\n");
         1337         printf ("+++ Overfull after %d bar%s in staff %d\n",
         1338                 nbar, nbar==1 ? "" : "s", mline);
         1339       }
         1340       jp2=i;
         1341       if (i==ip1) jp2=xp[i].next;  
         1342       if (lastcut>=0) jp2=xp[lastcut].next;
         1343       break;
         1344     }
         1345     /* The need_note business is to cut at the first of consecutive bars */
         1346     if (xp[i].type==NOTE)  need_note=0;
         1347     if (xp[i].type==BAR && need_note==0) {lastcut=i; need_note=1; nbar++; }
         1348     if (xp[i].type==KEYSIG) lastcut=i;
         1349     i=xp[i].next;
         1350     if (i==ip2) break;
         1351   }
         1352 
         1353   return jp2;
         1354 
         1355 }
         1356 
         1357 
         1358 /* ----- set_glue --------- */
         1359 float set_glue (ip1,ip2,width)
         1360 int ip1,ip2;
         1361 float width;
         1362 {
         1363   
         1364   int i,j;
         1365   float space,shrink,stretch,alfa,beta,glue,w,x,d1,d2,w1;
         1366   float alfa0,beta0;
         1367 
         1368   alfa0=ALFA_X;                       /* max shrink and stretch */
         1369   if (cfmt.continueall) alfa0=cfmt.maxshrink;
         1370   if (gmode==G_SHRINK)  alfa0=1.0;
         1371   if (gmode==G_SPACE)   alfa0=0.0;
         1372   if (gmode==G_STRETCH) alfa0=1.0;
         1373   beta0=BETA_X;
         1374   if (cfmt.continueall) beta0=BETA_C;
         1375 
         1376 
         1377   space=shrink=stretch=0;
         1378   i=ip1;
         1379   for (;;) {
         1380     space=space+xp[i].space;
         1381     shrink=shrink+xp[i].shrink;
         1382     stretch=stretch+xp[i].stretch;
         1383     j=i;
         1384     i=xp[i].next;
         1385     if (i==ip2) break;
         1386   }
         1387 
         1388   /* add extra space if last symbol is not a bar */
         1389   if (xp[j].type!=BAR) { 
         1390     d1=d2=xp[j].wr+3;
         1391     if (xp[j].type==NOTE) d2 = lnbp*nwid(xp[j].dur)+xp[j].wr;
         1392     if (d2<d1) d2=d1;
         1393     shrink  = shrink  + d1; 
         1394     space   = space   + d2; 
         1395     stretch = stretch + d2; 
         1396   } 
         1397 
         1398   /* select alfa and beta */
         1399   alfa=beta=0;
         1400   if (space>width) { 
         1401     alfa=99;
         1402     if (space>shrink) alfa=(space-width)/(space-shrink); 
         1403   }
         1404   else { 
         1405     beta=99;
         1406     if (stretch>space) beta=(width-space)/(stretch-space); 
         1407     if (!cfmt.stretchstaff) beta=0;
         1408   }
         1409   
         1410   if (gmode==G_SHRINK)  { alfa=1; beta=0;}     /* force minimal spacing */
         1411   if (gmode==G_STRETCH) { alfa=0; beta=1;}     /* force stretched spacing */
         1412   if (gmode==G_SPACE)   { alfa=beta=0;   }     /* force natural spacing */
         1413 
         1414 /*|   if (alfa>alfa0) { alfa=alfa0; beta=0; } |*/
         1415   
         1416   if (beta>beta0) {
         1417     if (!cfmt.continueall) {
         1418       if (verbose<=3) printf ("\n");
         1419       printf ("+++ Underfull (%.0fpt of %.0fpt) in staff %d\n", 
         1420               (beta0*stretch+(1-beta0)*space)*cfmt.scale,
         1421               cfmt.staffwidth,mline);
         1422     }
         1423     alfa=0; 
         1424     if (!cfmt.stretchstaff) beta=0;
         1425     if ((!cfmt.stretchlast) && (ip2==XP_END)) {
         1426       w1=alfa_last*shrink+beta_last*stretch+(1-alfa_last-beta_last)*space;
         1427       if (w1<width) {
         1428         alfa=alfa_last;    /* shrink undefull last line same as previous */
         1429         beta=beta_last;
         1430       }
         1431     }
         1432   }
         1433 
         1434   w=alfa*shrink+beta*stretch+(1-alfa-beta)*space;
         1435   if (verbose>=5) {
         1436     if (alfa>0)      printf ("Shrink staff %.0f%%",  100*alfa);
         1437     else if (beta>0) printf ("Stretch staff %.0f%%", 100*beta);
         1438     else             printf ("No shrink or stretch");
         1439     printf (" to width %.0f (%.0f,%.0f,%.0f)\n",w,shrink,space,stretch);
         1440   }
         1441 
         1442   /* now calculate the x positions */
         1443   x=0; 
         1444   i=ip1;
         1445   for (;;) {
         1446     glue=alfa*xp[i].shrink+beta*xp[i].stretch+(1-alfa-beta)*xp[i].space;
         1447     x=x+glue;
         1448     xp[i].x=x;
         1449     if (verbose>22) printf ("pos[%d]: type=%d  pos=%.2f\n", i,xp[i].type,x);
         1450     i=xp[i].next;
         1451     if (i==ip2) break;
         1452   }
         1453   
         1454   alfa_last=alfa;
         1455   beta_last=beta;
         1456   return w;
         1457 
         1458 }
         1459 
         1460 
         1461 /* ----- adjust_group: even out spacings for one group of notes --- */
         1462 /* Here we repeat the whole glue thing, in rudimentary form */
         1463 void adjust_group(i1,i2)
         1464 int i1,i2;
         1465 {
         1466   int j;
         1467   float dx,x,spa,shr,str,hp,hx,alfa,beta,dur1;
         1468 
         1469   dx=sym[i2].x-sym[i1].x;
         1470   shr=sym[i1].wr+sym[i2].wl;
         1471   for (j=i1+1;j<i2;j++) shr=shr+sym[j].wl+sym[j].wr;
         1472   dur1=sym[i1].len;
         1473   hp=lnnp*nwid(dur1);
         1474   hx=lnnx*xwid(dur1);
         1475   spa = (i2-i1)*hp;
         1476   str = (i2-i1)*hx;
         1477 
         1478   alfa=beta=0;
         1479   if (dx>spa)
         1480     beta=(dx-spa)/(str-spa);
         1481   else
         1482     alfa=(dx-spa)/(shr-spa);
         1483 
         1484   x=sym[i1].x; 
         1485   for (j=i1+1;j<=i2;j++) {  
         1486     x=x+alfa*(sym[j-1].wr+sym[j].wl)+beta*hx+(1-alfa-beta)*hp;
         1487     sym[j].x=x;   
         1488   }  
         1489   
         1490 }
         1491 
         1492 
         1493 /* ----- adjust_spacings: even out triplet spacings etc --- */
         1494 void adjust_spacings (n)
         1495 int n;
         1496 {
         1497   int i,i1,count,beam,num;
         1498   
         1499   /* adjust the n-plets */
         1500    count=0; 
         1501    for (i=1;i<n;i++) { 
         1502      if ((sym[i].type==NOTE)||(sym[i].type==REST)) { 
         1503        if (sym[i].p_plet) { 
         1504          i1=i; 
         1505          count=sym[i].r_plet; 
         1506        } 
         1507        if (count>0 && sym[i].len!=sym[i1].len) count=0; 
         1508        if (count==1) adjust_group (i1,i); 
         1509        if (count>0) count--; 
         1510      } 
         1511      else 
         1512        count=0; 
         1513    } 
         1514 
         1515   /* adjust beamed notes of equal duration */
         1516   beam=0;
         1517   for (i=1;i<n;i++) {
         1518     if ((sym[i].type==NOTE)||(sym[i].type==REST)) {
         1519       if (sym[i].word_st && (!sym[i].word_end)) { 
         1520         i1=i;
         1521         beam=1;
         1522         if (sym[i].p_plet) beam=0;          /* don't do nplets here */
         1523       }
         1524       if (beam && sym[i].len!=sym[i1].len) beam=0;
         1525       if (beam && sym[i].word_end) {
         1526         num=i-i1+1;
         1527         if (num>2 && num<4) adjust_group (i1,i);
         1528       }
         1529       if (sym[i].word_end) beam=0;
         1530     }
         1531     else
         1532       beam=0;
         1533   }
         1534 
         1535 }
         1536 
         1537 
         1538 /* ----- adjust_rests: position single rests in bar center */
         1539 void adjust_rests (n,v)
         1540 int n,v;
         1541 {
         1542   int i,ok;
         1543   
         1544   for (i=2;i<n-1;i++) {
         1545     if ((sym[i].type==REST) && sym[i].fullmes) {
         1546 
         1547       ok=1;
         1548       if ((sym[i-1].type==REST) || (sym[i-1].type==NOTE)) ok=0;
         1549       if ((sym[i+1].type==REST) || (sym[i+1].type==NOTE)) ok=0;
         1550 
         1551       if (ok) {
         1552         sym[i].head = H_OVAL;
         1553         sym[i].dots = 0;
         1554         sym[i].x = 0.5*(sym[i-1].x+sym[i+1].x);
         1555       }
         1556       
         1557     }
         1558   }
         1559 
         1560 }
         1561 
         1562 
         1563 
         1564 /* ----- copy_vsyms: copy selected syms for voice to v sym --- */
         1565 int copy_vsyms (v,ip1,ip2,wid0)
         1566 int v,ip1,ip2;
         1567 float wid0;
         1568 {
         1569   int i,n,m,k;
         1570   float d1,d2,r,x;
         1571 
         1572   /* copy staff initialization symbols */
         1573   n=0;
         1574   for (i=0;i<nsym_st[v];i++) {
         1575     sym[n]=sym_st[v][i];
         1576     n++;
         1577   }
         1578     
         1579   /* copy real symbols, shifted by wid0 */
         1580   i=ip1;
         1581   m=0;
         1582   for (;;) {
         1583     k=xp[i].p[v];
         1584     if (k >= 0) {
         1585       sym[n]=symv[v][k];
         1586       sym[n].x=xp[i].x+wid0;
         1587       n++;
         1588       m++;
         1589     }
         1590     i=xp[i].next;
         1591     if (i==ip2) break;
         1592   }
         1593   
         1594   /* adjust things for more pretty output.. */
         1595   adjust_rests (n,v);
         1596   if (mvoice>1) adjust_spacings (n);
         1597 
         1598   /* small random shifts make the output more human... */
         1599   for (i=1;i<n-1;i++) {
         1600     if ((sym[i].type==NOTE) || (sym[i].type==REST)) {
         1601       d1=sym[i].x-sym[i-1].x;
         1602       d2=sym[i+1].x-sym[i].x;
         1603       r=RANFAC*d1;
         1604       if (d2<d1) r=RANFAC*d2;
         1605       if (r>RANCUT) r=RANCUT;
         1606       x=ranf(-r,r);
         1607       sym[i].x=sym[i].x+x; 
         1608     }
         1609   }
         1610 
         1611   return n;
         1612 
         1613 }
         1614 
         1615 
         1616 /* ----- draw_timesig ------- */
         1617 void draw_timesig (x,s)
         1618 struct SYMBOL s;
         1619 float x;
         1620 {
         1621   if (s.w==1) 
         1622     PUT1("%.1f csig\n", x)
         1623   else if (s.w==2) 
         1624     PUT1("%.1f ctsig\n", x)
         1625   else 
         1626 /*    PUT3("%.1f (%d) (%d) tsig\n", x, s.u, s.v) */
         1627     PUT3("%.1f (%s) (%d) tsig\n", x, s.text, s.v)
         1628 }
         1629 
         1630 /* ----- draw_keysig: return sf for this key ----- */
         1631 int draw_keysig (x,s)
         1632 struct SYMBOL s;
         1633 float x;
         1634 {
         1635   float p;
         1636   int i,n1,n2,n3,t,yad,sf;
         1637   int sh_pos[8]={0,  24,15,27,18,9,21,15};
         1638   int ft_pos[8]={0,  12,21,9,18,6,15,3};
         1639 
         1640   n1=s.u;               /* which symbol to start with */
         1641   n2=s.v;               /* up to which symbol to go */
         1642   n3=s.w;               /* draw neutrals instead starting from this one */
         1643   t =s.t;               /* type of symbol: sharp or flat */
         1644 
         1645   yad = 0;
         1646   if (voice[ivc].key.ktype==BASS) yad = -6;
         1647   if (voice[ivc].key.ktype==ALTO) yad = -3;
         1648 
         1649   if (n2>7) {
         1650     printf ("+++ Keysig seems to have %d symbols ???\n", n2);
         1651     return 0;
         1652   }
         1653   
         1654   sf=0;
         1655   if (t==A_SH) {
         1656     p=x;
         1657     for (i=n1;i<=n2;i++) {
         1658       if (i>=n3) 
         1659         PUT2("%.1f %d nt0 ",p,sh_pos[i]+yad)
         1660       else {      
         1661         sf++;
         1662         PUT2("%.1f %d sh0 ",p,sh_pos[i]+yad)
         1663       }
         1664       p=p+5;
         1665     }
         1666     PUT0("\n")
         1667   }
         1668   else if (t==A_FT) {
         1669     p=x;
         1670     for (i=n1;i<=n2;i++) {
         1671       if (i>=n3) 
         1672         PUT2("%.1f %d nt0 ", p, ft_pos[i]+yad)
         1673       else {
         1674         sf--;
         1675         PUT2("%.1f %d ft0 ", p, ft_pos[i]+yad)
         1676       }
         1677       p=p+5;
         1678     }
         1679     PUT0("\n")
         1680   }
         1681   else 
         1682     bug ("wrong type in draw_keysig", 0);
         1683   
         1684   return sf;
         1685 }
         1686 
         1687 
         1688 /* ----- draw_bar ------- */
         1689 void draw_bar (x,s)
         1690 struct SYMBOL s;
         1691 float x;
         1692 {
         1693 
         1694   if (s.u==B_SNGL)                        /* draw the bar */
         1695     PUT1("%.1f bar\n", x)
         1696   else if (s.u==B_DBL)  
         1697     PUT1("%.1f dbar\n", x)
         1698   else if (s.u==B_LREP) 
         1699     PUT2("%.1f fbar1 %.1f rdots\n", x, x+10)
         1700   else if (s.u==B_RREP) {
         1701     PUT2("%.1f fbar2 %.1f rdots\n", x, x-10)
         1702   }
         1703   else if (s.u==B_DREP) {
         1704     PUT2("%.1f fbar1 %.1f rdots\n", x-1, x+9)
         1705     PUT2("%.1f fbar2 %.1f rdots\n", x+1, x-9)
         1706   }
         1707   else if (s.u==B_FAT1) 
         1708     PUT1("%.1f fbar1\n", x)
         1709   else if (s.u==B_FAT2) 
         1710     PUT1("%.1f fbar2\n", x)
         1711   else if (s.u==B_INVIS)
         1712     ;
         1713   else
         1714     printf (">>> dont know how to draw bar type %d\n", s.u);
         1715   
         1716   PUT0("\n")
         1717     
         1718 }  
         1719 
         1720 
         1721 /* ----- draw_barnums ------- */
         1722 void draw_barnums (fp)
         1723 FILE *fp;
         1724 {
         1725   int i,last,ok,got_note;
         1726 
         1727   last=0;
         1728   got_note=0;
         1729   for (i=0;i<nsym;i++) {
         1730     if ((sym[i].type==NOTE)||(sym[i].type==REST)) got_note=1;
         1731 
         1732     if ((sym[i].type==BAR) && (strlen(sym[i].text)>0)) {
         1733       if (last != 2) set_font (fp, cfmt.barlabelfont, 0);
         1734       PUT3 (" %.1f %.1f M (%s) cshow ", sym[i].x, BNUMHT, sym[i].text)
         1735       last=2;
         1736     }
         1737 
         1738     if ((sym[i].type==BAR) && sym[i].t) {
         1739       ok=0;
         1740       if ((cfmt.barnums>0) && (sym[i].t%cfmt.barnums==0)) ok=1; 
         1741       if ((cfmt.barnums==0) && (!got_note)) ok=1;
         1742       if ((cfmt.barnums!=0) && ((strlen(sym[i].text)>0))) ok=0;
         1743             
         1744       if (ok) {
         1745         if (last != 1) set_font (fp, cfmt.barnumfont, 0);
         1746 /*|     if ((mvoice>1) && (cfmt.barnums==0))  |*/
         1747         if (cfmt.barnums==0)
         1748           PUT1 (" 0 38 M (%d) rshow ", sym[i].t)
         1749         else
         1750           PUT3 (" %.1f %.1f M (%d) cshow ", sym[i].x, BNUMHT, sym[i].t)
         1751         last=1;
         1752       }
         1753     }
         1754   }
         1755   PUT0("\n");
         1756   
         1757 }  
         1758 
         1759 
         1760 /* ----- update_endings: remember where to draw endings ------- */
         1761 void update_endings (x,s)
         1762 struct SYMBOL s;
         1763 float x;
         1764 {
         1765   int i;
         1766   
         1767   if (num_ending>0) {
         1768     i=num_ending-1;
         1769     if (ending[i].num==1) 
         1770       mes1++;
         1771     else {
         1772       mes2++;
         1773       if (mes2==mes1) ending[i].b=x;
         1774     }
         1775   }
         1776   
         1777   if (s.v) {         
         1778     if (num_ending>0)
         1779       if (ending[num_ending-1].num==1) ending[num_ending-1].b=x-3;
         1780     ending[num_ending].a=x;
         1781     ending[num_ending].b=-1;
         1782     ending[num_ending].num=s.v;
         1783     if (s.v==1) mes1=0;
         1784     else        mes2=0;
         1785     num_ending++;
         1786   }
         1787   
         1788 }  
         1789 
         1790 
         1791 
         1792 /* ----- set_ending: determine limits of ending box ------- */
         1793 void set_ending (i)
         1794 int i;
         1795 {
         1796   int num,j,j0,j1,mes,mesmax;
         1797   float top;
         1798   
         1799   num=sym[i].v;
         1800   mesmax=0;
         1801   if (num==2) mesmax=mes1;
         1802 
         1803   mes=0;
         1804   j0=j1=-1;
         1805   for (j=i+1;j<nsym;j++) {
         1806     if (sym[j].type==BAR) {
         1807       if (sym[j].u!=B_INVIS)  mes++;
         1808       if (mes==1) j1=j;
         1809       if (sym[j].u==B_RREP || sym[j].u==B_DREP || sym[j].u==B_FAT2 ||
         1810           sym[j].u==B_LREP || sym[j].u==B_FAT1 || sym[j].v>0) {
         1811         j0=j;
         1812         break;
         1813       }
         1814       if (mes==mesmax) {
         1815         j0=j;
         1816         break;
         1817       }
         1818     }
         1819   }
         1820   top=-1;
         1821   if (j0==-1) j0=j1; 
         1822   if (j0>=0) top=sym[j0].x;
         1823 
         1824   ending[num_ending].num=num;
         1825   ending[num_ending].a=sym[i].x;
         1826   ending[num_ending].b=top;
         1827   if (num==1) ending[num_ending].b=top-3;
         1828   ending[num_ending].type=E_CLOSED;
         1829   if (sym[j0].type==BAR && sym[j0].u==B_SNGL) ending[num_ending].type=E_OPEN;
         1830   num_ending++;
         1831 
         1832   if (num==1) mes1=mes;
         1833   if (num==2) mes1=0;
         1834 
         1835 }
         1836 
         1837 
         1838 /* ----- draw_endings ------- */
         1839 void draw_endings ()
         1840 {
         1841   int i;
         1842 
         1843   for (i=0;i<num_ending;i++) {
         1844     if (ending[i].b<0) 
         1845       PUT3("%.1f %.1f (%d) end2\n", 
         1846            ending[i].a, ending[i].a+50, ending[i].num)
         1847     else {
         1848       if (ending[i].type==E_CLOSED) {
         1849         PUT3("%.1f %.1f (%d) end1\n", 
         1850              ending[i].a, ending[i].b, ending[i].num)
         1851       }
         1852       else {
         1853         PUT3("%.1f %.1f (%d) end2\n", 
         1854              ending[i].a, ending[i].b, ending[i].num)
         1855       }
         1856     }
         1857   }
         1858   num_ending=0;
         1859 
         1860 }   
         1861 
         1862 /* ----- draw_rest ----- */
         1863 void draw_rest (x,yy,s,gchy)
         1864 struct SYMBOL s;
         1865 float x,yy;
         1866 float *gchy;
         1867 {
         1868 
         1869   int y,i,k,deco;
         1870   float dotx,doty;
         1871 
         1872   *gchy=38;
         1873   if (s.invis) return;
         1874 
         1875   y=(int) s.y;
         1876   PUT2("%.2f %.0f", x, yy)
         1877 
         1878   if (s.head==H_OVAL)       PUT0(" r1")  
         1879   else if (s.head==H_EMPTY) PUT0(" r2")
         1880   else {
         1881     if (s.flags==0)      PUT0(" r4")
         1882     else if (s.flags==1) PUT0(" r8")
         1883     else if (s.flags==2) PUT0(" r16")
         1884     else if (s.flags==3) PUT0(" r32")
         1885     else                 PUT0(" r64")
         1886   }
         1887 
         1888   if (y%6) { dotx=6.5; doty=0; }                   /* dots */
         1889   else     { dotx=6.5; doty=3; }
         1890   if (s.head==H_OVAL)  { dotx=8; doty=-3; }
         1891   if (s.head==H_EMPTY) { dotx=8; doty=3;  }
         1892   for (i=0;i<s.dots;i++) {
         1893     PUT2(" %.1f %.1f dt", dotx, doty)
         1894     dotx=dotx+3.5;
         1895   }
         1896 
         1897 
         1898   for (k=s.dc.n-1;k>=0;k--) {    
         1899     deco=s.dc.t[k];
         1900     if (deco==D_HOLD) PUT1(" %.1f hld", 27.0)
         1901   }
         1902 
         1903   PUT0("\n")
         1904 }
         1905 
         1906 /* ----- draw_gracenotes ----- */
         1907 void draw_gracenotes (x,w,d,s)
         1908 struct SYMBOL *s;
         1909 float x,w,d;
         1910 {
         1911   int i,n,y,acc,ii,m;
         1912   float xg[20],yg[20],lg,px[20],py[20],xx,yy;
         1913   float s1,sx,sy,sxx,sxy,a,b,delta,lmin;
         1914   float x0,y0,x1,y1,x2,y2,x3,y3,bet1,bet2,dy1,dy2,dx,dd,fac,facx;
         1915 
         1916   n=s->gr.n;
         1917   if (n==0) return;
         1918 
         1919   facx=0.3;
         1920   fac=d/w-1;
         1921   if (fac<0) fac=0;
         1922   fac=1+(fac*facx)/(fac+facx);
         1923 
         1924   dx=0;
         1925   for (m=0;m<s->npitch;m++) {              /* room for accidentals */
         1926     dd=-s->shhd[m];
         1927     if (s->accs[m]) dd=-s->shhd[m]+s->shac[m];
         1928     if ((s->accs[m]==A_FT)||(s->accs[m]==A_NT)) dd=dd-2;
         1929     if (dx<dd) dx=dd;
         1930   }
         1931   
         1932   xx=x-fac*(dx+GSPACE0);
         1933   for (i=n-1;i>=0;i--) {                   /* set note positions */
         1934     yg[i]=3*(s->gr.p[i]-18)+s->yadd;
         1935     if (i==n-1) {                             /* some subtle shifts.. */
         1936       if(yg[i]>=s->ymx)  xx=xx+1;              /* gnote above a bit closer */ 
         1937       if((yg[i]<s->ymn-7)&&(n==1)) xx=xx-2;   /* below with flag further */
         1938     }
         1939 
         1940     if (i<n-1) {
         1941       if (yg[i]>yg[i+1]+8) xx=xx+fac*1.8;
         1942     }
         1943 
         1944     xg[i]=xx;
         1945     xx=xx-fac*GSPACE;
         1946     if (s->gr.a[i]) xx=xx-3.5;
         1947   }
         1948   
         1949   if (n>1) {
         1950     s1=sx=sy=sxx=sxy=0;                    /* linear fit through stems */
         1951     for (i=0;i<n;i++) {      
         1952       px[i]=xg[i]+GSTEM_XOFF;
         1953       py[i]=yg[i]+GSTEM;
         1954       s1 += 1; sx += px[i]; sy += py[i];
         1955       sxx += px[i]*px[i]; sxy += px[i]*py[i];
         1956     }
         1957     delta=s1*sxx-sx*sx;                   /* beam fct: y=ax+b */
         1958     a=(s1*sxy-sx*sy)/delta;
         1959     if (a>BEAM_SLOPE) a=BEAM_SLOPE;
         1960     if (a<-BEAM_SLOPE) a=-BEAM_SLOPE;  
         1961     b=(sy-a*sx)/s1;
         1962 
         1963     if (bagpipe) { a=0; b=35; }
         1964 
         1965     lmin=100;                           /* shift to get min stems */
         1966     for (i=0;i<n;i++) {      
         1967       px[i]=xg[i]+GSTEM_XOFF;
         1968       py[i]=a*px[i]+b;
         1969       lg=py[i]-yg[i];
         1970       if (lg<lmin) lmin=lg;
         1971     }
         1972     if (lmin<10) b=b+10-lmin;
         1973   }
         1974 
         1975   for (i=0;i<n;i++) {                     /* draw grace notes */
         1976     if (n>1) {
         1977       px[i]=xg[i]+GSTEM_XOFF;
         1978       py[i]=a*px[i]+b;
         1979       lg=py[i]-yg[i];
         1980       PUT3("%.1f %.1f %.1f gnt ", xg[i],yg[i],lg)
         1981     }
         1982     else {
         1983       lg=GSTEM;
         1984       PUT3("%.1f %.1f %.1f gn1 ", xg[i],yg[i],lg)
         1985     }      
         1986 
         1987     acc=s->gr.a[i];
         1988     if (acc==A_SH) PUT2("%.1f %.1f gsh0 ",xg[i]-4.5,yg[i])
         1989     if (acc==A_FT) PUT2("%.1f %.1f gft0 ",xg[i]-4.5,yg[i])
         1990     if (acc==A_NT) PUT2("%.1f %.1f gnt0 ",xg[i]-4.5,yg[i])
         1991     if (acc==A_DS) PUT2("%.1f %.1f gds0 ",xg[i]-4.5,yg[i])
         1992     if (acc==A_DF) PUT2("%.1f %.1f gdf0 ",xg[i]-4.5,yg[i])
         1993 
         1994     y = (int)yg[i];                         /* helper lines */
         1995     if (y<=-6) {
         1996       if (y%6) PUT2("%.1f %d ghl ",xg[i], y+3) 
         1997       else     PUT2("%.1f %d ghl ",xg[i], y) 
         1998     }  
         1999     if (y>=30) {
         2000       if (y%6) PUT2("%.1f %d ghl ",xg[i], y-3) 
         2001       else     PUT2("%.1f %d ghl ",xg[i], y) 
         2002     }  
         2003   }
         2004   
         2005   if (n>1)                                /* beam */
         2006     if (bagpipe) 
         2007       PUT4("%.1f %.1f %.1f %.1f gbm3 ", px[0],py[0],px[n-1],py[n-1])
         2008     else
         2009       PUT4("%.1f %.1f %.1f %.1f gbm2 ", px[0],py[0],px[n-1],py[n-1])
         2010 
         2011 
         2012   bet1=0.2;                            /* slur */
         2013   bet2=0.8;     
         2014   yy=1000; 
         2015   for (i=n-1;i>=0;i--) if (yg[i]<=yy) {yy=yg[i]; ii=i;}
         2016   x0=xg[ii];
         2017   y0=yg[ii]-5;
         2018   if (ii>0) { x0=x0-4; y0=y0+1; }
         2019   x3=x-1;
         2020   y3=s->ymn-5;
         2021   dy1=(x3-x0)*0.4;
         2022   if (dy1>3) dy1=3;
         2023   dy2=dy1;
         2024 
         2025   if (yg[ii]>s->ymn+7){
         2026     x0=xg[ii]-1;
         2027     y0=yg[ii]-4.5;
         2028     y3=s->ymn+1.5;
         2029     x3=x-dx-5.5;
         2030     dy2=(y0-y3)*0.2;
         2031     dy1=(y0-y3)*0.8;
         2032     bet1=0.0;
         2033   }
         2034 
         2035   if (y3>y0+4) {
         2036     y3=y0+4;
         2037     x0=xg[ii]+2;
         2038     y0=yg[ii]-4;
         2039   }
         2040 
         2041   x1=bet1*x3+(1-bet1)*x0;
         2042   y1=bet1*y3+(1-bet1)*y0-dy1;
         2043   x2=bet2*x3+(1-bet2)*x0;
         2044   y2=bet2*y3+(1-bet2)*y0-dy2;
         2045 
         2046   PUT4(" %.1f %.1f %.1f %.1f", x1,y1,x2,y2);
         2047   PUT4(" %.1f %.1f %.1f %.1f gsl\n", x3,y3,x0,y0);
         2048 
         2049 }
         2050 
         2051 /* ----- draw_basic_note: draw m-th head with accidentals and dots -- */
         2052 void draw_basic_note (x,w,d,s,m)
         2053 struct SYMBOL *s;
         2054 float x,w,d;
         2055 int m;
         2056 {
         2057   int y,i,yy;
         2058   float dotx,doty,xx,dx,avail,add,fac;
         2059 
         2060   y=3*(s->pits[m]-18)+s->yadd;                    /* height on staff */
         2061   
         2062   xx=x+s->shhd[m];                              /* draw head */
         2063   PUT2("%.1f %d", xx, y)              
         2064   if (s->head==H_OVAL)  PUT0(" HD")
         2065   if (s->head==H_EMPTY) PUT0(" Hd")
         2066   if (s->head==H_FULL)  PUT0(" hd")
         2067   if (s->shhd[m]) {                  
         2068     yy=0;
         2069     if (y>=30) { yy=y; if (yy%6) yy=yy-3; }
         2070     if (y<=-6) { yy=y; if (yy%6) yy=yy+3; }
         2071     if (yy) PUT1(" %d hl", yy)
         2072   }
         2073 
         2074   if (s->dots) {                                /* add dots */
         2075     if (y%6) { dotx=8; doty=0; }    
         2076     else     { dotx=8; doty=3; }
         2077     if (s->stem==-1) 
         2078       dotx=dotx+s->xmx-s->shhd[m]; 
         2079     else
         2080       dotx=dotx+s->xmx-s->shhd[m];
         2081     if (s->dots && s->flags && (s->stem==1) && !(y%6)) 
         2082       if ((s->word_st==1) && (s->word_end==1) && (s->npitch==1))
         2083         dotx=dotx+DOTSHIFT; 
         2084     if (s->head==H_EMPTY) dotx=dotx+1;
         2085     if (s->head==H_OVAL)  dotx=dotx+2;
         2086     for (i=0;i<s->dots;i++) {
         2087       PUT2(" %.1f %.1f dt", dotx, doty)
         2088       dotx=dotx+3.5;
         2089     }
         2090   }
         2091 
         2092   if (s->accs[m]) {                          /* add accidentals */
         2093     fac=1.0;
         2094     avail=d-w-3;
         2095     add=0.3*avail;
         2096     fac=1+add/s->wl;
         2097     if (fac<1) fac=1;
         2098     if (fac>1.2) fac=1.2;
         2099     dx=fac*s->shac[m];    
         2100     if (s->accs[m]==A_SH) PUT1(" %.1f sh", dx)  
         2101     if (s->accs[m]==A_NT) PUT1(" %.1f nt", dx)
         2102     if (s->accs[m]==A_FT) PUT1(" %.1f ft", dx)
         2103     if (s->accs[m]==A_DS) PUT1(" %.1f dsh", dx)
         2104     if (s->accs[m]==A_DF) PUT1(" %.1f dft", dx)
         2105   }
         2106 }
         2107 
         2108 
         2109 /* ----- draw_decorations ----- */
         2110 float draw_decorations (x,s,tp)
         2111 struct SYMBOL *s;
         2112 float x;
         2113 float *tp;
         2114 {
         2115   int y,sig,k,deco,m;
         2116   float yc,xc,y1,top,top1,dx,dy;
         2117 
         2118 
         2119   top=-1000;
         2120   for (k=s->dc.n-1;k>=0;k--) {                 /*  decos close to head */
         2121     deco=s->dc.t[k];
         2122 
         2123 /*  if ((deco==D_STACC)||(deco==D_EMBAR)) { */      /* dot or bar mark */
         2124     if (deco==D_STACC) {                           /* dot */
         2125       sig=1; if (s->stem==1) sig=-1;
         2126       y=s->y+6*sig;
         2127       if (y<top+3) y=top+3;
         2128       if (!(y%6) && (y>=0) && (y<=24)) y+=3*sig;
         2129       if (top<y) top=y;
         2130       if (deco==D_STACC) PUT1(" %d stc",y)
         2131       else               PUT1(" %d emb",y)
         2132     }
         2133     
         2134     if (deco==D_SLIDE) {                           /* slide */
         2135       yc=s->ymn;
         2136       xc=5;
         2137       for (m=0;m<s->npitch;m++) {                       
         2138         dx=5-s->shhd[m];
         2139         if (s->head==H_OVAL) dx=dx+2.5; 
         2140         if (s->accs[m]) dx=4-s->shhd[m]+s->shac[m];
         2141         dy=3*(s->pits[m]-18)+s->yadd-yc;
         2142         if ((dy<10) && (dx>xc)) xc=dx; 
         2143       }
         2144       yc=s->ymn;
         2145       PUT2(" %.1f %.1f sld", yc, xc)
         2146     }
         2147   }
         2148   
         2149   top1=top;
         2150   for (k=s->dc.n-1;k>=0;k--) {                 /*  decos further away */
         2151     deco=s->dc.t[k];
         2152 
         2153     if (deco==D_EMBAR) {                         /* bar */
         2154       yc=s->ymx+6; 
         2155       if (s->stem==1) yc=s->ys+4;
         2156       if (yc<28) yc=28;
         2157       if (yc<top+3) yc=top+3;
         2158       if (top<yc+2) top=yc+2;
         2159       PUT1(" %.2f emb", yc)
         2160     }
         2161 
         2162     if ((deco==D_GRACE)||(deco==D_HAT)||(deco==D_ATT)) { /* gracing,hat,att */
         2163       yc=s->ymx+9; 
         2164       if (s->stem==1) yc=s->ys+5;
         2165       if (yc<30) yc=30;
         2166       if (yc<top+4) yc=top+4;
         2167       if (top<yc+2) top=yc+2;
         2168       if      (deco==D_GRACE) PUT1(" %.2f grm", yc)
         2169       else if (deco==D_HAT)   PUT1(" %.2f hat", yc)
         2170       else                    PUT1(" %.2f att", yc)
         2171     }
         2172 
         2173     if (deco==D_ROLL) {                            /* roll sign */
         2174       y=s->y;
         2175       if (s->stem==1) {
         2176         yc=s->y-5;
         2177         if (yc>-2) yc=-2;
         2178         PUT1(" %.2f cpd", yc)
         2179       }
         2180       else {
         2181         yc=s->y+5;
         2182         if (s->dots && (!(y%6))) yc=s->y+6;
         2183         if (yc<26) yc=26;
         2184         if (yc<top+1) yc=top+1;
         2185         if (top<yc+8) top=yc+8;
         2186         PUT1(" %.2f cpu", yc)
         2187       }
         2188     } 
         2189     
         2190     if (deco==D_HOLD) {                           /* hold sign */
         2191       yc=27;
         2192       if (s->stem==1) 
         2193         y1=s->ys+4; 
         2194       else 
         2195         y1=s->ymx+6;
         2196       if (yc<y1) yc=y1;
         2197       if (yc<top+4) yc=top+4;
         2198       if (top<yc+12) top=yc+12;
         2199       PUT1(" %.1f hld", yc)
         2200     }
         2201     
         2202     if (deco==D_TRILL) {                          /* trill sign */
         2203       yc=30;
         2204       if (s->stem==1) 
         2205         y1=s->ys+5; 
         2206       else 
         2207         y1=s->ymx+7;
         2208       if (yc<y1) yc=y1;
         2209       if (yc<top+1) yc=top+1;
         2210       if (top<yc+8) top=yc+8;
         2211       PUT1(" %.1f trl", yc)
         2212     }
         2213 
         2214     if ((deco==D_UPBOW)||(deco==D_DOWNBOW)) {     /* bowing signs */
         2215       yc=21;
         2216       if (s->stem==1) 
         2217         y1=s->ys+4; 
         2218       else 
         2219         y1=s->ymx+8;
         2220       if (yc<y1) yc=y1;
         2221       if (yc<top+4) yc=top+4;
         2222       if (top<yc+10) top=yc+10;
         2223       if (deco==D_UPBOW)   PUT1(" %.1f upb", yc)
         2224       if (deco==D_DOWNBOW) PUT1(" %.1f dnb", yc)
         2225     }
         2226   }
         2227   *tp=top;
         2228   return top1;
         2229 }
         2230 
         2231 
         2232 /* ----- draw_note ----- */
         2233 float draw_note (x,w,d,s,fl,gchy)
         2234 struct SYMBOL *s;
         2235 float x,w,d;
         2236 float *gchy;
         2237 int fl;
         2238 {
         2239   char c,cc;
         2240   int y,i,m,k;
         2241   float yc,slen,slen0,top,top2,xx;
         2242   slen0=STEM;
         2243 
         2244   draw_gracenotes (x, w, d, s);                /* draw grace notes */
         2245 
         2246   c = 'd'; cc='u';
         2247   if (s->stem==1) { c='u'; cc='d'; }
         2248   slen=s->stem*(s->ys-s->y);
         2249 
         2250   for (m=0;m<s->npitch;m++) {                       
         2251     if (m>0) PUT0(" ")
         2252     draw_basic_note (x,w,d,s,m);             /* draw note heads */
         2253     xx=3*(s->pits[m]-18)+s->yadd-s->y;
         2254     xx=xx*xx;
         2255     if (xx<0.01) {                                 /* add stem */
         2256       if (s->stem) PUT2(" %.1f s%c",slen,c) 
         2257       if (fl && (s->flags>0))                      /* add flags */
         2258         PUT3(" %.1f f%d%c",slen,s->flags,c)
         2259     }
         2260     if ((m>0) && (s->pits[m]==s->pits[m-1])) {     /* unions */
         2261       if (s->stem) PUT2(" %.2f s%c",slen0,cc) 
         2262       if (s->flags>0)                    
         2263         PUT3(" %.1f f%d%c",slen0,s->flags,cc)
         2264     }
         2265   }
         2266 
         2267   top=draw_decorations (x,s,&top2);                /* add decorations */
         2268   
         2269   y = s->ymn;                                      /* lower helper lines */
         2270   if (y<=-6) {                           
         2271     for (i=-6;i>=y;i=i-6) PUT1(" %d hl", i)
         2272     if (s->head==H_OVAL) PUT0("1")
         2273   }
         2274   y = s->ymx;                                      /* upper helper lines */
         2275   if (y>=30) {
         2276     for (i=30;i<=y;i=i+6) PUT1(" %d hl", i)
         2277     if (s->head==H_OVAL) PUT0("1")
         2278   }
         2279 
         2280   *gchy=38;
         2281   if (strlen(s->text)>0) {                         /* position guitar chord */
         2282     yc=*gchy;
         2283     if (yc<y+8) yc=y+8;
         2284     if (yc<s->ys+4) yc=s->ys+4;
         2285     for (k=0;k<s->dc.n;k++) {
         2286       if ((s->dc.t[k]==D_GRACE) && (yc<y+12)) yc=y+12;
         2287     }
         2288     if (yc<top2) yc=top2;
         2289     *gchy=yc;
         2290   }    
         2291 
         2292   PUT0("\n")
         2293     
         2294   return top;
         2295 
         2296 }
         2297 
         2298 
         2299 /* ----- vsh: up/down shift needed to get k*6  ----- */
         2300 float vsh (x,dir)
         2301 int dir;
         2302 float x;
         2303 {
         2304   int ix,iy,ir;
         2305   float x1,xx;
         2306   x1=x*dir;
         2307   ix=x1+600.999;
         2308   ir=ix%6;
         2309   iy=ix-600;
         2310   if (ir>0) iy=iy+6-ir;
         2311   xx=iy*dir;
         2312   return xx-x;
         2313 }
         2314 
         2315 
         2316 /* ----- rnd3: up/down shift needed to get k*3  ----- */
         2317 float rnd3(x)
         2318 float x;
         2319 {
         2320   int ix,iy,ir;
         2321   float xx;
         2322 
         2323   ix=x+600.999-1.5;
         2324   ir=ix%3;
         2325   iy=ix-600;
         2326   if (ir>0) iy=iy+3-ir;
         2327   xx=iy;
         2328   return xx-x;
         2329 }
         2330 
         2331 
         2332 /* ----- rnd6: up/down shift needed to get k*6  ----- */
         2333 float rnd6(x)
         2334 float x;
         2335 {
         2336   int ix,iy,ir;
         2337   float xx;
         2338 
         2339   ix=x+600.999-3.0;
         2340   ir=ix%6;
         2341   iy=ix-600;
         2342   if (ir>0) iy=iy+6-ir;
         2343   xx=iy;
         2344   return xx-x;
         2345 }
         2346 
         2347 
         2348 /* ----- b_pos ----- */
         2349 float b_pos (stem,flags,b)
         2350 int stem,flags;
         2351 float b;
         2352 {
         2353   float bb,d1,d2,add;
         2354   float top,bot;
         2355 
         2356   if (stem==1) {
         2357     top=b;
         2358     bot=b-(flags-1)*BEAM_SHIFT-BEAM_DEPTH;
         2359     if (bot>26) return b;
         2360   }
         2361   else {
         2362     bot=b;
         2363     top=b+(flags-1)*BEAM_SHIFT+BEAM_DEPTH;
         2364     if (top<-2) return b;
         2365   }
         2366 
         2367   d1=rnd6(top-BEAM_OFFSET);
         2368   d2=rnd6(bot+BEAM_OFFSET); 
         2369   add=d1;
         2370   if (d1*d1>d2*d2) add=d2;
         2371   bb=b+add;
         2372 
         2373 /*  printf ("stem %d top %.1f, bot%.1f, choices %.1f %.1f => %.1f\n", 
         2374           stem, top,bot, d1,d2, add); */
         2375 /*  printf ("b_pos(%d) b=%.1f to %.1f\n", stem,b,bb); */
         2376 
         2377   return bb;
         2378 }
         2379 
         2380 
         2381 /* ----- calculate_beam ----- */
         2382 int calculate_beam (i0,bm)
         2383 int i0;
         2384 struct BEAM *bm;
         2385 {
         2386   int j,j1,j2,i,stem,notes,flags;
         2387   float x,y,ys,a,b,max_stem_err,stem_err,min_stem,slen,yyg,yg,try;
         2388   float s,sx,sy,sxx,sxy,syy,delta,hh,dev,dev2,a0;
         2389   
         2390   j1=i0;                      /* find first and last note in beam */
         2391   j2=-1;
         2392   stem=sym[j1].stem;        
         2393   for (j=i0;j<nsym;j++) 
         2394     if (sym[j].word_end) {
         2395       j2=j;
         2396       break;
         2397     }
         2398   if (j2==-1) {
         2399     return 0;
         2400   }
         2401   
         2402   notes=flags=0;                /* set x positions, count notes and flags */
         2403   for (j=j1;j<=j2;j++) {
         2404     if(sym[j].type==NOTE) {   
         2405       sym[j].xs=sym[j].x+stem*STEM_XOFF;
         2406       sym[j].stem=stem;
         2407       if (sym[j].flags>flags) flags=sym[j].flags;
         2408       notes++;
         2409     }
         2410   }
         2411   
         2412   s=sx=sy=sxx=sxy=syy=0;              /* linear fit through stem ends */
         2413   for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) {
         2414     x=sym[j].xs;
         2415     y=sym[j].ymx+STEM*stem;
         2416     s += 1; sx += x; sy += y;
         2417     sxx += x*x; sxy += x*y; syy += y*y;
         2418   }
         2419 
         2420   delta=s*sxx-sx*sx;                  /* beam fct: y=ax+b */
         2421   a=(s*sxy-sx*sy)/delta;
         2422   b=(sy-a*sx)/s;
         2423 
         2424   /* the next few lines modify the slope of the beam */
         2425   if (notes>=3) {                   
         2426     hh=syy-a*sxy-b*sy;                /* flatten if notes not in line */
         2427     dev=0;
         2428     if (hh>0) {
         2429       dev2=hh/(notes-2);
         2430       if (dev2>0.5) a=BEAM_FLATFAC*a;   
         2431     }
         2432   }
         2433 
         2434 
         2435   if (a>=0) a=BEAM_SLOPE*a/(BEAM_SLOPE+a);   /* max steepness for beam */
         2436   else      a=BEAM_SLOPE*a/(BEAM_SLOPE-a);
         2437 
         2438 
         2439   /* to decide if to draw flat etc. use normalized slope a0 */
         2440   a0=a*(sym[j2].xs-sym[j1].xs)/(20*(notes-1));
         2441 
         2442   if ((a0<BEAM_THRESH) && (a0>-BEAM_THRESH)) a=0;  /* flat below threshhold */
         2443 
         2444   b=(sy-a*sx)/s;                        /* recalculate b for new slope */
         2445 
         2446 /*  if (flags>1) b=b+2*stem;*/      /* leave a bit more room if several beams */
         2447 
         2448   if (bagpipe) { b=-11; a=0; }
         2449 
         2450   max_stem_err=0;                        /* check stem lengths */
         2451   for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) {
         2452     if (sym[j].npitch==1) {
         2453       min_stem=STEM_MIN;
         2454       if (sym[j].flags==2) min_stem=STEM_MIN2;
         2455       if (sym[j].flags==3) min_stem=STEM_MIN3;
         2456       if (sym[j].flags==4) min_stem=STEM_MIN4;
         2457     }
         2458     else {
         2459       min_stem=STEM_CH_MIN;
         2460       if (sym[j].flags==2) min_stem=STEM_CH_MIN2;
         2461       if (sym[j].flags==3) min_stem=STEM_CH_MIN3;
         2462       if (sym[j].flags==4) min_stem=STEM_CH_MIN4;
         2463     }
         2464     min_stem=min_stem+BEAM_DEPTH+BEAM_SHIFT*(sym[j].flags-1);
         2465     ys=a*sym[j].xs+b;
         2466     if (stem==1) slen=ys-sym[j].ymx;
         2467     else         slen=sym[j].ymn-ys;
         2468     stem_err=min_stem-slen;
         2469     if (stem_err>max_stem_err) max_stem_err=stem_err;
         2470   } 
         2471   
         2472   if (max_stem_err>0)                   /* shift beam if stems too short */
         2473     b=b+stem*max_stem_err;
         2474 
         2475   for (j=j1+1;j<=j2;j++) if (sym[j].type==NOTE) {  /* room for gracenotes */
         2476     for (i=0;i<sym[j].gr.n;i++) {
         2477       yyg=a*(sym[j].x-GSPACE0)+b;
         2478       yg=3*(sym[j].gr.p[i]-18)+sym[j].yadd;
         2479       if (stem==1) {
         2480         try=(yg+GSTEM)-(yyg-BEAM_DEPTH-2);
         2481         if (try>0) b=b+try;
         2482       }
         2483       else {
         2484         try=(yg)-(yyg+BEAM_DEPTH+7);
         2485         if (try<0) b=b+try;
         2486       }
         2487     }
         2488   }
         2489 
         2490   if ((a<0.01) && (a>-0.01))       /* shift flat beams onto staff lines */
         2491     b=b_pos (stem,flags,b); 
         2492 
         2493   for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) {    /* final stems */
         2494     sym[j].ys=a*sym[j].xs+b;
         2495   } 
         2496 
         2497   bm->i1=j1;                      /* save beam parameters in struct */
         2498   bm->i2=j2;
         2499   bm->a=a;
         2500   bm->b=b;
         2501   bm->stem=stem;
         2502   bm->t=stem*BEAM_DEPTH;
         2503   return 1;
         2504 }
         2505 
         2506   
         2507 /* ----- rest_under_beam ----- */
         2508 float rest_under_beam (x,head,bm)
         2509 float x;
         2510 int head;
         2511 struct BEAM *bm;
         2512 {
         2513   float y,tspace,bspace;
         2514   int j1,j2,j,nf,iy;
         2515 
         2516   tspace=9;
         2517   bspace=11;
         2518   if ((head==H_OVAL)||(head==H_EMPTY)) tspace=bspace=4;
         2519   
         2520   j1=bm->i1;
         2521   j2=bm->i2;
         2522   nf=0;
         2523   for (j=j1;j<=j2;j++) 
         2524     if ((sym[j].type==NOTE)||(sym[j].flags>nf)) nf=sym[j].flags;
         2525   
         2526   if (bm->stem==1) {
         2527     y=bm->a*x+bm->b;
         2528     y=y-BEAM_DEPTH-(nf-1)*BEAM_SHIFT;
         2529     y=y-tspace;
         2530     if (y>12) y=12;
         2531   }
         2532   else {
         2533     y=bm->a*x+bm->b;
         2534     y=y+BEAM_DEPTH+(nf-1)*BEAM_SHIFT;
         2535     y=y+bspace;
         2536     if (y<12) y=12;
         2537   }
         2538 
         2539   if ((head==H_OVAL)||(head==H_EMPTY)) {
         2540     iy=(y+3.0)/6.0; 
         2541     y=6*iy;
         2542   }
         2543 
         2544   return y;
         2545 }
         2546 
         2547 /* ----- draw_beam_num: draw number on a beam ----- */
         2548 void draw_beam_num (bm,num,xn)
         2549 struct BEAM *bm;
         2550 int num;
         2551 float xn;
         2552 {
         2553   float yn;
         2554   
         2555   if (bm->stem==-1) 
         2556     yn=bm->a*xn+bm->b-12;
         2557   else 
         2558     yn=bm->a*xn+bm->b+4;
         2559   
         2560   PUT3("%.1f %.1f (%d) bnum\n", xn, yn, num)
         2561 
         2562 }
         2563 
         2564   
         2565 /* ----- draw_beam: draw a single beam ----- */
         2566 void draw_beam (x1,x2,dy,bm)
         2567 float x1,x2,dy;
         2568 struct BEAM *bm;
         2569 {
         2570   float y1,y2;
         2571 
         2572   y1=bm->a*x1+bm->b-bm->stem*dy;
         2573   y2=bm->a*x2+bm->b-bm->stem*dy;
         2574   PUT5("%.1f %.1f %.1f %.1f %.1f bm\n", x1,y1,x2,y2,bm->t)
         2575 }
         2576   
         2577 /* ----- draw_beams: draw the beams for one word ----- */
         2578 void draw_beams (bm)
         2579 struct BEAM *bm;
         2580 {
         2581   int j,j1,j2,j3,inbeam,k1,k2,num,p,r;
         2582   float x1,x2,xn;
         2583   
         2584   j1=bm->i1;
         2585   j2=bm->i2;
         2586 
         2587   /* make first beam over whole word */
         2588   x1=sym[j1].xs;
         2589   x2=sym[j2].xs;
         2590   num=sym[j1].u;
         2591   
         2592   for (j=j1;j<=j2;j++) {    /* numbers for nplets on same beam */
         2593     if (sym[j].p_plet>0) {
         2594       p=sym[j].p_plet;
         2595       r=sym[j].r_plet;
         2596       j3=j+r-1;
         2597       if (j3<=j2) {  
         2598         xn=0.5*(sym[j].xs+sym[j3].xs);
         2599         draw_beam_num (bm,p,xn);
         2600         sym[j].p_plet=0;
         2601       }
         2602     }
         2603   }
         2604   
         2605   draw_beam (x1,x2,0.0,bm);
         2606   
         2607   /* second beams where two or more flags */
         2608   k1=0;
         2609   inbeam=0;
         2610   for (j=j1;j<=j2;j++) {
         2611     if (sym[j].type!=NOTE) continue;
         2612     if ((!inbeam) && (sym[j].flags>=2)) {
         2613       k1=j;
         2614       inbeam=1;
         2615     }
         2616     if (inbeam && ((sym[j].flags<2) || (j==j2))) {
         2617       if ((sym[j].flags>=2) && (j==j2)) k2=j;
         2618       x1=sym[k1].xs;
         2619       x2=sym[k2].xs;
         2620       inbeam=0;
         2621       if (k1==k2) {
         2622         if (k1==j1) draw_beam (x1+BEAM_STUB,x1,BEAM_SHIFT,bm);
         2623         else        draw_beam (x1-BEAM_STUB,x1,BEAM_SHIFT,bm);
         2624       }
         2625       else 
         2626         draw_beam (x1,x2,BEAM_SHIFT,bm);
         2627       inbeam=0;
         2628     }
         2629     k2=j;
         2630   }
         2631   
         2632   /* third beams where three or more flags */
         2633   k1=0;
         2634   inbeam=0;
         2635   for (j=j1;j<=j2;j++) {
         2636     if (sym[j].type!=NOTE) continue;
         2637     if ((!inbeam) && (sym[j].flags>=3)) {
         2638       k1=j;
         2639       inbeam=1;
         2640     }
         2641     if (inbeam && ((sym[j].flags<3) || (j==j2))) {
         2642       if ((sym[j].flags>=3) && (j==j2)) k2=j;
         2643       x1=sym[k1].xs;
         2644       x2=sym[k2].xs;
         2645       inbeam=0;
         2646       if (k1==k2) {
         2647         if (k1==j1) draw_beam (x1+BEAM_STUB,x1,2*BEAM_SHIFT,bm);
         2648         else        draw_beam (x1-BEAM_STUB,x1,2*BEAM_SHIFT,bm);
         2649       }
         2650       else 
         2651         draw_beam (x1,x2,2*BEAM_SHIFT,bm);
         2652       inbeam=0;
         2653     }
         2654     k2=j;
         2655   }
         2656   
         2657   /* fourth beams where four or more flags */
         2658   k1=0;
         2659   inbeam=0;
         2660   for (j=j1;j<=j2;j++) {
         2661     if (sym[j].type!=NOTE) continue;
         2662     if ((!inbeam) && (sym[j].flags>=4)) {
         2663       k1=j;
         2664       inbeam=1;
         2665     }
         2666     if (inbeam && ((sym[j].flags<4) || (j==j2))) {
         2667       if ((sym[j].flags>=4) && (j==j2)) k2=j;
         2668       x1=sym[k1].xs;
         2669       x2=sym[k2].xs;
         2670       inbeam=0;
         2671       if (k1==k2) {
         2672         if (k1==j1) draw_beam (x1+BEAM_STUB,x1,3*BEAM_SHIFT,bm);
         2673         else        draw_beam (x1-BEAM_STUB,x1,3*BEAM_SHIFT,bm);
         2674       }
         2675       else 
         2676         draw_beam (x1,x2,3*BEAM_SHIFT,bm);
         2677       inbeam=0;
         2678     }
         2679     k2=j;
         2680   }
         2681   
         2682 }
         2683 
         2684 /* ----- extreme: return min or max, depending on s ----- */
         2685 float extreme (s, a, b)
         2686 float s,a,b;
         2687 {
         2688 
         2689   if (s>0) {
         2690     if (a>b) return a;
         2691     return b;
         2692   }
         2693   else {
         2694     if (a<b) return a;
         2695     return b;
         2696   }
         2697 }
         2698 
         2699 /* ----- draw_bracket  ----- */
         2700 void draw_bracket (p,j1,j2)
         2701 int p,j1,j2;
         2702 {
         2703   float x1,x2,y1,y2,xm,ym,s,s0,xx,yy,yx,dy;
         2704   int j;
         2705 
         2706   x1=sym[j1].x-4;
         2707   x2=sym[j2].x+4;
         2708   y1=sym[j1].ymx+10;
         2709   y2=sym[j2].ymx+10;
         2710 
         2711   if (sym[j1].stem==1) { y1=sym[j1].ys+4; x1=x1+3; }
         2712   if (sym[j2].stem==1) { y2=sym[j2].ys+4; x2=x2+3; }
         2713     
         2714   if (y1<30) y1=30;
         2715   if (y2<30) y2=30; 
         2716 
         2717   xm=0.5*(x1+x2);
         2718   ym=0.5*(y1+y2);
         2719 
         2720   s=(y2-y1)/(x2-x1);
         2721   s0=(sym[j2].ymx-sym[j1].ymx)/(x2-x1);
         2722   if (s0>0) {
         2723     if (s<0) s=0; if (s>s0) s=s0; 
         2724   }
         2725   else {
         2726     if (s>0) s=0; if (s<s0) s=s0; 
         2727   }
         2728   if (s*s < 0.2*0.2) s=0;   /* flat if below limit */
         2729 
         2730 
         2731   dy=0;           /* shift up bracket if needed */
         2732   for (j=j1;j<=j2;j++) {
         2733     if ((sym[j].type==NOTE) || (sym[j].type==REST)) {
         2734       xx=sym[j].x;
         2735       yy=ym+(xx-xm)*s;
         2736       yx=sym[j].ymx+10;
         2737       if (sym[j].stem==1) yx=sym[j].ys+5;
         2738       if (yx-yy>dy) dy=yx-yy;
         2739     }
         2740   }
         2741   ym=ym+dy;
         2742   y1=ym+s*(x1-xm);
         2743   y2=ym+s*(x2-xm);
         2744 
         2745   /* shift up guitar chords, if needed */
         2746   for (j=j1;j<=j2;j++) {
         2747     if ((sym[j].type==NOTE) || (sym[j].type==REST)) {
         2748       xx=sym[j].x;
         2749       yy=ym+(xx-xm)*s;
         2750       if (sym[j].gchy<yy+4) sym[j].gchy=yy+4;
         2751     }
         2752   }
         2753   
         2754   xx=xm-6;
         2755   yy=ym+s*(xx-xm);
         2756   PUT4("%.1f %.1f %.1f %.1f hbr ",  x1,y1,xx,yy)
         2757 
         2758   xx=xm+6;
         2759   yy=ym+s*(xx-xm);
         2760   PUT4("%.1f %.1f %.1f %.1f hbr ",  x2,y2,xx,yy)
         2761 
         2762   yy=0.5*(y1+y2);
         2763   PUT3("%.1f %.1f (%d) bnum\n", xm, yy-4, p)
         2764 
         2765 }
         2766 
         2767 /* ----- draw_nplet_brackets  ----- */
         2768 void draw_nplet_brackets ()
         2769 {
         2770   int i,j,k,p,r,c;
         2771   
         2772   for (i=0;i<nsym;i++) {
         2773     if ((sym[i].type==NOTE) || (sym[i].type==REST)) {
         2774       if (sym[i].p_plet>0) {
         2775         p=sym[i].p_plet;
         2776         r=sym[i].r_plet;
         2777         c=r;
         2778         k=i;
         2779         for (j=i;j<nsym;j++) {
         2780           if ((sym[j].type==NOTE) || (sym[j].type==REST)) {
         2781             c--; 
         2782             k=j; 
         2783             if (c==0) break;
         2784           }
         2785         }
         2786         draw_bracket (p,i,k);
         2787       }
         2788     }
         2789   }
         2790 }
         2791 
         2792 
         2793 /* ----- slur_direction: decide whether slur goes up or down --- */
         2794 float slur_direction (k1,k2)
         2795 int k1,k2;
         2796 {
         2797   float s;
         2798   int i,are_stems,are_downstems,are_bars,y_max,notes;
         2799 
         2800   are_stems=are_downstems=are_bars=0;  
         2801   notes=0;
         2802   y_max=300;
         2803   for (i=k1;i<=k2;i++) {
         2804     if (sym[i].type==BAR) are_bars=1;
         2805     if (sym[i].type==NOTE) {
         2806       notes++;
         2807       if (sym[i].stem != 0 )  are_stems=1;
         2808       if (sym[i].stem == -1 ) are_downstems=1;
         2809       if (sym[i].ymn<y_max) y_max=sym[i].ymn;
         2810     }
         2811   }
         2812   s=-1;
         2813   if (are_downstems) s=1;
         2814   if (!are_stems) {
         2815     s=1;
         2816     if (y_max<12) s=-1;
         2817   }
         2818 
         2819   /* next line tries to put long phrasings on top */
         2820   if (are_bars && (notes>5)) s=1;
         2821 
         2822   return s;
         2823 }
         2824 
         2825 /* ----- output_slur: output slur -- --- */
         2826 void output_slur (x1,y1,x2,y2,s,height,shift)
         2827 float x1,y1,x2,y2,s,height,shift;
         2828 {
         2829   float alfa,beta,mx,my,xx1,yy1,xx2,yy2,dx,dy,dz,a,add;
         2830        
         2831   alfa=0.3;                
         2832   beta=0.45;
         2833 
         2834   /* for wide flat slurs, make shape more square */
         2835   dy=y2-y1;
         2836   if (dy<0) dy=-dy;
         2837   dx=x2-x1;
         2838   if (dx<0) dx=-dx;
         2839   a=dy/dx;
         2840   if ((a<0.7) && dx>40) {
         2841     add=0.2*(dx-40)/100;
         2842     alfa=0.3+add;
         2843     if (alfa>0.7) alfa=0.7;
         2844   }
         2845 
         2846 
         2847   /* alfa, beta, and height determine Bezier control points pp1,pp2 
         2848    *
         2849    *           X====alfa===|===alfa=====X  
         2850    *          /            |             \
         2851    *        pp1            |              pp2
         2852    *        /            height            \
         2853    *      beta             |                beta
         2854    *      /                |                 \
         2855    *    p1                 m                  p2
         2856    *       
         2857    */
         2858 
         2859 
         2860   mx=0.5*(x1+x2);
         2861   my=0.5*(y1+y2);
         2862 
         2863   xx1=mx+alfa*(x1-mx);
         2864   yy1=my+alfa*(y1-my)+height;
         2865   xx1=x1+beta*(xx1-x1);
         2866   yy1=y1+beta*(yy1-y1); 
         2867 
         2868   xx2=mx+alfa*(x2-mx);
         2869   yy2=my+alfa*(y2-my)+height;
         2870   xx2=x2+beta*(xx2-x2);
         2871   yy2=y2+beta*(yy2-y2); 
         2872 
         2873   dx=0.03*(x2-x1);
         2874   if (dx>10.0) dx=10.0;
         2875   dy=1.0;
         2876   dz=0.20;
         2877   if (x2-x1>100) dz=dz+0.001*(x2-x1);
         2878   if (dz>0.6) dz=0.6;
         2879 
         2880   PUT4("%.1f %.1f %.1f %.1f ", 
         2881        xx2-dx, yy2+shift+s*dy, xx1+dx, yy1+shift+s*dy)
         2882   PUT3("%.1f %.1f 0 %.1f ", x1,y1+shift+s*dz,s*dz)
         2883   PUT4("%.1f %.1f %.1f %.1f ", xx1,yy1+shift,xx2,yy2+shift)
         2884   PUT4("%.1f %.1f %.1f %.1f SL\n", x2,y2+shift, x1,y1+shift)
         2885 
         2886 
         2887 /*PUT4("%.2f %.2f %.2f %.2f ", xx1,yy1+shift,xx2,yy2+shift)
         2888   PUT4("%.2f %.2f %.2f %.2f sl\n", x2,y2+shift, x1,y1+shift)*/
         2889 
         2890   return;
         2891 }
         2892 
         2893 /* ----- draw_slur (not a pretty routine, this) ----- */
         2894 void draw_slur (k1,k2,nn,level)
         2895 int k1,k2,level,nn;
         2896 {
         2897   float x01,x02,y01,y02;
         2898   float x1,y1,x2,y2,yy,height,addx,addy;
         2899   float s,shift,hmin,a;
         2900   float x,y,z,h,dx,dy;
         2901   int i;
         2902 
         2903   s=slur_direction (k1,k2);
         2904   
         2905   /* fix endpoints */
         2906   if (sym[k1].type==NOTE) {            /* here if k1 points to note */
         2907     x01=sym[k1].x;
         2908     yy=sym[k1].ymn; if (s>0) yy=sym[k1].ymx;
         2909     y01=extreme(s,yy+s*6,sym[k1].ys+s*2);
         2910     if (sym[k1].word_end) {
         2911       yy=sym[k1].ymn; if (s>0) yy=sym[k1].ymx;
         2912       y01=yy+s*6;
         2913       if ((sym[k1].stem==1)&&(s==1)) x01=x01+4;
         2914     }
         2915     if ((s>0) && (y01<sym[k1].dc.top+2.5)) y01=sym[k1].dc.top+2.5;
         2916   }
         2917 
         2918   if (sym[k2].type==NOTE) {            /* here if k2 points to note */
         2919     x02=sym[k2].x;
         2920     yy=sym[k2].ymn; if (s>0) yy=sym[k2].ymx;
         2921     y02=extreme(s,yy+s*6,sym[k2].ys+s*2);
         2922     if (sym[k2].word_st) {
         2923       yy=sym[k2].ymn; if (s>0) yy=sym[k2].ymx;
         2924       y02=yy+s*6;
         2925       if ((sym[k2].stem==-1)&&(s==-1)) x02=x02-3;
         2926     }  
         2927     if ((s>0) && (y02<sym[k2].dc.top+2.5)) y02=sym[k2].dc.top+2.5;
         2928   }
         2929 
         2930   if (sym[k1].type!=NOTE) {
         2931     x01=sym[k1].x+sym[k1].wr;
         2932     y01=y02+1.2*s; 
         2933     if (nn>1) {
         2934       if(s==1) { if (y01<28) y01=28; } 
         2935       else     { if (y01>-4) y01=-4; }
         2936     }
         2937   }
         2938   
         2939   if (sym[k2].type!=NOTE) {
         2940     x02=sym[k2].x; 
         2941     y02=y01+1.2*s; 
         2942     if (nn>1) {
         2943       if (s==1) {if (y02<28) y02=28; }
         2944       else      {if (y02>-4) y02=-4; }
         2945     }
         2946   }
         2947 
         2948   /* shift endpoints */
         2949   addx=0.04*(x02-x01);
         2950   if (addx>3.0) addx=3.0;
         2951   addy=0.02*(x02-x01);
         2952   if (addy>3.0) addy=3.0;
         2953   x1 = x01+addx;
         2954   x2 = x02-addx;
         2955   y1=y01+s*addy;
         2956   y2=y02+s*addy;
         2957 
         2958   a=(y2-y1)/(x2-x1);                    /* slur steepness */     
         2959   if (a >  SLUR_SLOPE) a= SLUR_SLOPE;  
         2960   if (a < -SLUR_SLOPE) a=-SLUR_SLOPE;  
         2961   if (a>0) {
         2962     if (s ==  1) y1=y2-a*(x2-x1);
         2963     if (s == -1) y2=y1+a*(x2-x1);
         2964   }
         2965   else {
         2966     if (s == -1) y1=y2-a*(x2-x1);
         2967     if (s ==  1) y2=y1+a*(x2-x1);
         2968   }  
         2969 
         2970   /* for big vertical jump, shift endpoints */
         2971   y=y2-y1; if (y>8) y=8; if (y<-8) y=-8; 
         2972   z=y; if(z<0) z=-z; dx=0.5*z; dy=0.3*z;
         2973   if (y>0) {
         2974     if (s==1) { x2=x2-dx; y2=y2-dy; }
         2975     if (s==-1) { x1=x1+dx; y1=y1+dy; }
         2976   }
         2977   else {
         2978     if (s==1) { x1=x1+dx; y1=y1-dy; }
         2979     if (s==-1) { x2=x2-dx; y2=y2+dy; }
         2980   }
         2981 
         2982   h=0;
         2983   for (i=k1+1; i<k2; i++) 
         2984     if (sym[i].type==NOTE) {
         2985       x = sym[i].x;
         2986       yy = sym[i].ymn; if (s>0) yy=sym[i].ymx;
         2987       y = extreme (s, yy+6*s, sym[i].ys+2*s);
         2988       z = (y2*(x-x1)+y1*(x2-x))/(x2-x1);
         2989       h = extreme (s, h, y-z);
         2990     }
         2991 
         2992   y1=y1+0.4*h;
         2993   y2=y2+0.4*h;
         2994   h=0.6*h;
         2995   
         2996   hmin=s*(0.03*(x2-x1)+8);
         2997   if (nn>3) hmin=s*(0.12*(x2-x1)+12);
         2998   height = extreme (s, hmin, 3.0*h);
         2999   height = extreme (-s, height, s*50);
         3000   
         3001   y=y2-y1; if (y<0) y=-y;
         3002   if ((s==1)  && (height< 0.8*y)) height=0.8*y;
         3003   if ((s==-1) && (height>-0.8*y)) height=-0.8*y; 
         3004 
         3005   shift=3*s*level;
         3006 
         3007   output_slur (x1,y1,x2,y2,s,height,shift);
         3008 
         3009   return;
         3010 }
         3011 
         3012 
         3013 /* ----- prev_scut, next_scut: find place to terminate/start slur --- */
         3014 int next_scut (i)
         3015 int i;
         3016 {
         3017   int j,cut,ok;
         3018   
         3019   cut=nsym-1;
         3020   for (j=i+1;j<nsym;j++) {
         3021     ok=0;
         3022     if (sym[j].type==BAR) {
         3023       if (sym[j].u==B_RREP) ok=1;
         3024       if (sym[j].u==B_DREP) ok=1;
         3025       if (sym[j].u==B_FAT1) ok=1;
         3026       if (sym[j].u==B_FAT2) ok=1;
         3027       if (sym[j].v==2)      ok=1;
         3028     }
         3029     if(ok) {
         3030       cut=j;
         3031       break;
         3032     }
         3033   }
         3034   return cut;
         3035 }
         3036 
         3037 int prev_scut(i)
         3038 int i;
         3039 {
         3040   int j,cut,ok;
         3041 
         3042   cut=-1;
         3043   for (j=i;j>=0;j--) {
         3044     ok=0;
         3045     if (sym[j].type==BAR) {
         3046       if (sym[j].u==B_LREP) ok=1;
         3047       if (sym[j].u==B_DREP) ok=1;
         3048       if (sym[j].u==B_FAT1) ok=1;
         3049       if (sym[j].u==B_FAT2) ok=1;
         3050       if (sym[j].v==2)      ok=1;
         3051     }
         3052     if(ok) {
         3053       cut=j;
         3054       break;
         3055     }
         3056   }
         3057 
         3058   if (cut==-1) {    /* return sym before first note */
         3059     cut=0;
         3060     for (j=0;j<nsym;j++) {
         3061       if((sym[j].type==REST) || (sym[j].type==NOTE)) {
         3062         cut=j-1;
         3063         break;
         3064       }
         3065     }
         3066   }
         3067 
         3068   return cut;
         3069 }
         3070   
         3071 
         3072 /* ----- draw_chord_slurs ----- */
         3073 void draw_chord_slurs(k1,k2,nh1,nh2,nslur,mhead1,mhead2,job)
         3074 int k1,k2,nh1,nh2,nslur,mhead1[MAXHD],mhead2[MAXHD],job;
         3075 {
         3076 
         3077   int i,pbot,ptop,m1,m2,p1,p2,y,cut;
         3078   float s,x1,y1,x2,y2,height,shift,addx,addy;
         3079 
         3080   if (nslur==0) return;
         3081 
         3082   pbot=1000;
         3083   ptop=-1000;
         3084   for (i=0;i<sym[k1].npitch;i++) {
         3085     p1=sym[k1].pits[i];
         3086     if (p1<pbot) pbot=p1;
         3087     if (p1>ptop) ptop=p1;
         3088   }
         3089   
         3090   for (i=0;i<nslur;i++) {
         3091     m1=mhead1[i];
         3092     m2=mhead2[i];
         3093     p1=sym[k1].pits[m1];
         3094     p2=sym[k2].pits[m2];
         3095     s=slur_direction (k1,k2);
         3096     if (p1==pbot) s=-1;
         3097     if (p1==ptop) s=1;
         3098     
         3099     x1=sym[k1].x;
         3100     x2=sym[k2].x;
         3101     if (job==2) {
         3102       cut=next_scut(k1);
         3103       x2=sym[cut].x;
         3104       if (cut==k1) x2=x1+30;
         3105     }
         3106 
         3107     if (job==1) {
         3108       cut=prev_scut(k1);
         3109       x1=sym[cut].x;
         3110       if (cut==k1) x2=x1-30;
         3111     }
         3112       
         3113     addx=0.04*(x2-x1);
         3114     if (addx>3.0) addx=3.0;
         3115     addy=0.02*(x2-x1);
         3116     if (addy>3.0) addy=3.0;
         3117 
         3118     x1=x1+3+addx;
         3119     x2=x2-3-addx;
         3120     if ((s==1)  && (sym[k1].stem==1))  x1=x1+1.5;
         3121     if ((s==-1) && (sym[k2].stem==-1)) x2=x2-1.5;
         3122 
         3123     y=3*(p1-18)+sym[k1].yadd;
         3124     y1=y2=y+s*(4+addy);
         3125     y=3*(p2-18)+sym[k2].yadd;
         3126     y2=y+s*(4+addy);
         3127 
         3128     if ((s==1) && !(y%6) && (sym[k1].dots>0)) {
         3129       y2=y1=y+s*(5.5+addy);
         3130       x1=x1-2;
         3131       x2=x2+2;
         3132     }
         3133     height=s*(0.04*(x2-x1)+5);
         3134     shift=0;
         3135     output_slur (x1,y1,x2,y2,s,height,shift);
         3136   }
         3137 
         3138 }
         3139 
         3140 
         3141 
         3142 /* ----- draw_slurs: draw slurs/ties between neighboring notes/chords */
         3143 void draw_slurs (k1,k2,job)
         3144 int k1,k2,job;
         3145 {
         3146   int i,m1,m2;
         3147   int mhead1[MAXHD],mhead2[MAXHD],nslur,nh1,nh2;
         3148 
         3149   if (nbuf+100>BUFFSZ) 
         3150     rx ("PS output exceeds reserved space per staff",
         3151         " -- increase BUFFSZ1");
         3152 
         3153   nslur=0;
         3154 
         3155   if (job==2) {                    /* half slurs from last note in line */
         3156     nh1=sym[k1].npitch;
         3157     for (i=1;i<=nh1;i++) {
         3158       for (m1=0;m1<nh1;m1++) {
         3159         if (sym[k1].sl1[m1]==i) {
         3160           nslur=nslur+1;
         3161           mhead1[nslur-1]=m1;
         3162         }
         3163         if (sym[k1].ti1[m1]) {
         3164           nslur=nslur+1;
         3165           mhead1[nslur-1]=m1;
         3166         }
         3167       }
         3168     }
         3169     draw_chord_slurs(k1,k1,nh1,nh1,nslur,mhead1,mhead1,job);
         3170     return;
         3171   }
         3172 
         3173   if (job==1) {                    /* half slurs to first note in line */
         3174     nh1=sym[k1].npitch;
         3175     for (i=1;i<=nh1;i++) {
         3176       for (m1=0;m1<nh1;m1++) {
         3177         if (sym[k1].sl2[m1]==i) {
         3178           nslur=nslur+1;
         3179           mhead1[nslur-1]=m1;
         3180         }
         3181         if (sym[k1].ti2[m1]) {
         3182           nslur=nslur+1;
         3183           mhead1[nslur-1]=m1;
         3184         }
         3185       }
         3186     }
         3187     draw_chord_slurs(k1,k1,nh1,nh1,nslur,mhead1,mhead1,job);
         3188     return;
         3189   }
         3190   
         3191   /* real 2-note case: set up list of slurs/ties to draw */
         3192   if ((sym[k1].type==NOTE) && (sym[k2].type==NOTE)) {
         3193     nh1=sym[k1].npitch;
         3194     nh2=sym[k2].npitch;
         3195 
         3196     for (m1=0;m1<nh1;m1++) {
         3197       if (sym[k1].ti1[m1]) {
         3198         for (m2=0;m2<nh2;m2++) {
         3199           if (sym[k2].pits[m2]==sym[k1].pits[m1]) {
         3200             nslur++;
         3201             mhead1[nslur-1]=m1;
         3202             mhead2[nslur-1]=m2;
         3203             break;
         3204           }
         3205         }
         3206       }
         3207     }
         3208 
         3209     for (i=1;i<=nh1;i++) {
         3210       for (m1=0;m1<nh1;m1++) {
         3211         if (sym[k1].sl1[m1]==i) {
         3212           nslur++;
         3213           mhead1[nslur-1]=m1;
         3214           mhead2[nslur-1]=-1;
         3215           for (m2=0;m2<nh2;m2++) {
         3216             if (sym[k2].sl2[m2]==i) mhead2[nslur-1]=m2;
         3217           }
         3218           if (mhead2[nslur-1]==-1) nslur--;
         3219         }
         3220       }  
         3221     }
         3222   }
         3223     
         3224   draw_chord_slurs(k1,k2,nh1,nh2,nslur,mhead1,mhead2,job);
         3225 }
         3226 
         3227 
         3228 
         3229 /* ----- draw_phrasing: draw phrasing slur between two symbols --- */
         3230 void draw_phrasing (k1,k2,level)
         3231 int k1,k2,level;
         3232 {
         3233   int nn,i;
         3234   
         3235   if (k1==k2) return;
         3236   if (nbuf+100>BUFFSZ) 
         3237     rx ("PS output exceeds reserved space per staff",
         3238         " -- increase BUFFSZ1");
         3239   nn=0;
         3240   for (i=k1;i<=k2;i++) 
         3241     if ((sym[i].type==NOTE)||(sym[i].type==REST)) nn++;
         3242   
         3243   draw_slur (k1,k2,nn,level);
         3244   
         3245 }
         3246 
         3247 /* ----- draw_all_slurs: draw all slurs/ties between neighboring notes  */
         3248 void draw_all_slurs ()
         3249 {
         3250   int i,i1,i2;
         3251 
         3252   i1=-1;
         3253   for (i=0;i<nsym;i++) {
         3254     if (sym[i].type==NOTE) {
         3255       i1=i;
         3256       break;
         3257     }
         3258   }
         3259   if (i1<0) return;
         3260   draw_slurs(i1,i1,1);
         3261   
         3262   for (;;) {
         3263     i2=-1;
         3264     for (i=i1+1;i<nsym;i++) {
         3265       if (sym[i].type==NOTE) {
         3266         i2=i;
         3267         break;
         3268       }
         3269     }
         3270     if (i2<0) break;
         3271     draw_slurs(i1,i2,0);
         3272     i1=i2;
         3273   }
         3274   
         3275   draw_slurs(i1,i1,2);
         3276 
         3277 }
         3278 
         3279 /* ----- draw_all_phrasings: draw all phrasing slurs for one staff ----- */
         3280 void draw_all_phrasings ()
         3281 {
         3282   int i,j,k,cut,pass,num;
         3283 
         3284   for (pass=0;;pass++) {
         3285     num=0;
         3286     for (i=0;i<nsym;i++) {
         3287       
         3288       if (sym[i].slur_st) {      
         3289         k=-1;                       /* find matching slur end */
         3290         for (j=i+1;j<nsym;j++) {
         3291           if (sym[j].slur_st && (!sym[j].slur_end)) break;
         3292           if (sym[j].slur_end) {
         3293             k=j;
         3294             break;
         3295           }
         3296         }
         3297         if (k>=0) {
         3298           cut=next_scut(i);
         3299           if (cut<k) {
         3300             draw_phrasing (i,cut,pass);
         3301             cut=prev_scut(k);
         3302             draw_phrasing (cut,k,pass);
         3303           }
         3304           else {
         3305             draw_phrasing (i,k,pass);
         3306           }
         3307           num++;
         3308           sym[i].slur_st--;
         3309           sym[k].slur_end--;
         3310         }
         3311       }
         3312     }
         3313     if (num==0) break;
         3314   }
         3315 
         3316   /* do unbalanced slurs still left over */
         3317   
         3318   for (i=0;i<nsym;i++) {
         3319     if (sym[i].slur_end) {
         3320       cut=prev_scut(i);
         3321       draw_phrasing (cut,i,0);
         3322     }
         3323     if (sym[i].slur_st) {
         3324       cut=next_scut(i);
         3325       draw_phrasing (i,cut,0);
         3326     }
         3327   }    
         3328   
         3329 }
         3330 
         3331 /* ----- check_bars1 ---------- */
         3332 void check_bars1 (ip1,ip2)
         3333 int ip1,ip2;
         3334 {
         3335   int v,i,j,k1,k2;
         3336   float dx;
         3337 
         3338   /* check for inelegant bar combinations within one line */
         3339   i=j=ip1;
         3340   for (;;) {
         3341     if (xp[i].type==BAR && xp[j].type==BAR && i!=j) {
         3342       dx=0;
         3343       for (v=0;v<nvoice;v++) {
         3344         k1=xp[j].p[v];
         3345         k2=xp[i].p[v];
         3346         if (k1>=0 && k2>=0) {
         3347           if (symv[v][k1].u==B_RREP && symv[v][k2].u==B_LREP) {
         3348             symv[v][k2].u=B_DREP;
         3349             symv[v][k1].u=B_INVIS;
         3350             dx=-4.0;
         3351           }
         3352         }
         3353       }
         3354       xp[i].x=xp[i].x+dx;
         3355     }
         3356     j=i;
         3357     i=xp[i].next;
         3358     if (i==ip2) break;
         3359   }
         3360 
         3361 }
         3362 
         3363 
         3364 /* ----- check_bars2 ---------- */
         3365 void check_bars2 (ip1,ip2)
         3366 int ip1,ip2;
         3367 {
         3368   int i,ip,v;
         3369 
         3370   /* check whether to split up last bar over two lines */
         3371   ip=xp[ip2].prec;
         3372   for (v=0;v<nvoice;v++) {
         3373     strcpy(voice[v].insert_text,"");
         3374     voice[v].insert_bnum  = 0;
         3375     voice[v].insert_space = 0;
         3376     voice[v].insert_num   = 0;
         3377     voice[v].insert_btype = 0;
         3378 
         3379     i=xp[ip].p[v];
         3380     if (i>=0) {
         3381       if (symv[v][i].type==BAR) {
         3382         if (symv[v][i].u==B_LREP) {
         3383           symv[v][i].u=B_SNGL; 
         3384           voice[v].insert_btype=B_LREP; 
         3385           voice[v].insert_num=0;
         3386         }
         3387         else if (symv[v][i].u==B_DREP) {
         3388           symv[v][i].u=B_RREP;               
         3389           voice[v].insert_btype=B_LREP; 
         3390           voice[v].insert_num=0;
         3391         }
         3392         else if ((symv[v][i].u==B_RREP) && (symv[v][i].v!=0)) {
         3393           voice[v].insert_btype=B_INVIS; 
         3394           voice[v].insert_num=symv[v][i].v;
         3395           symv[v][i].v=0;
         3396         }
         3397         else if ((symv[v][i].u==B_SNGL) && (symv[v][i].v!=0)) {
         3398           voice[v].insert_btype=B_INVIS; 
         3399           voice[v].insert_num=symv[v][i].v;
         3400           symv[v][i].v=0;
         3401         }
         3402 
         3403         /* if number or label on last bar, move to next line */
         3404         if (symv[v][i].t || (strlen(symv[v][i].text)>0)) {
         3405           if (symv[v][i+1].type==BAR) {
         3406             if (symv[v][i+1].t==0) symv[v][i+1].t=symv[v][i].t;
         3407             if (strlen(symv[v][i+1].text)==0) 
         3408               strcpy(symv[v][i+1].text,symv[v][i].text); 
         3409           }
         3410           else {
         3411             if (!voice[v].insert_btype) voice[v].insert_btype=B_INVIS; 
         3412             voice[v].insert_space=symv[v][i].wr;
         3413             voice[v].insert_bnum=symv[v][i].t;
         3414             strcpy(voice[v].insert_text,symv[v][i].text);
         3415             strcpy(symv[v][i].text,"");
         3416             symv[v][i].t=0;
         3417           }
         3418         }
         3419         
         3420 
         3421       }
         3422     }
         3423   }
         3424 
         3425 
         3426 }
         3427 
         3428 
         3429 
         3430 /* ----- draw_vocals ----- */
         3431 void draw_vocals (fp,nwl,botnote,bspace,botpos)
         3432 FILE *fp;
         3433 float botnote,bspace;
         3434 float *botpos;
         3435 int nwl;
         3436 {
         3437   int i,hyflag,l,j;
         3438   float x,x0,yword,lastx,spc,vfsize,w,swfac,lskip;
         3439   char word[81],t[81];
         3440   
         3441   if (nwl<=0) return;
         3442   vfsize=cfmt.vocalfont.size;
         3443   lskip=1.1*vfsize;
         3444   set_font (fp, cfmt.vocalfont, 0);
         3445   yword=-cfmt.vocalspace;
         3446   swfac=1.05;
         3447   if (strstr(cfmt.vocalfont.name,"Helvetica")) swfac=1.10;
         3448   if (botnote-cfmt.vocalfont.size<yword) 
         3449     yword=botnote-cfmt.vocalfont.size;
         3450   
         3451   for (j=0;j<nwl;j++) {
         3452     hyflag=0;
         3453     lastx=-10;
         3454     for (i=0;i<nsym;i++) {          
         3455       if (sym[i].wordp[j]) {
         3456         strcpy(word,sym[i].wordp[j]);
         3457         x0=sym[i].x;
         3458         l=strlen(word);
         3459 
         3460         if (hyflag) {
         3461           tex_str (word,t,&w);
         3462           spc=x0-VOCPRE*vfsize*swfac*w-lastx;
         3463           x = lastx+0.5*spc-0.5*swfac*vfsize*cwid('-');
         3464           PUT2("%.1f %.1f whf ",x,yword)
         3465           hyflag=0;
         3466         }
         3467 
         3468         if ((l>1) && (word[l-1]=='^')) {
         3469           word[l-1]='\0';
         3470           hyflag=1;
         3471         }
         3472 
         3473         if ((l==1) && (word[0]=='_')) {
         3474           if (lastx<0) lastx=sym[i-1].x+sym[i-1].wr;
         3475           PUT3("%.1f %.1f %.1f wln ", lastx+3, sym[i].x+1, yword)
         3476         } 
         3477         else if ((l==1) && (word[0]=='^')) {
         3478           PUT2("%.1f %.1f whf ", x0, yword)
         3479           lastx=x0+vfsize*swfac*w;
         3480         }
         3481         else {
         3482           tex_str (word,t,&w);
         3483           if (isdig(word[0])) 
         3484             x0=x0-3*vfsize*swfac*cwid('1');
         3485           else
         3486             x0=x0-VOCPRE*vfsize*swfac*w;
         3487           if (strcmp(t," ")) PUT3("(%s) %.1f %.1f wd ", t, x0, yword)
         3488           lastx=x0+vfsize*swfac*w;
         3489         }
         3490       }
         3491     }
         3492     if (hyflag) PUT2("%.1f %.1f whf ",lastx+5,yword)
         3493     yword=yword-lskip;
         3494   } 
         3495   *botpos=yword + lskip - bspace;
         3496 }  
         3497 
         3498 /* ----- draw_symbols: draw symbols at proper positions on staff ----- */
         3499 void draw_symbols (fp,bspace,bpos,is_top)
         3500 FILE *fp;
         3501 float bspace,*bpos;
         3502 int is_top;
         3503 {
         3504   int i,inbeam,j,nwl;
         3505   float x,y,top,xl,d,w,gchy,botnote,botpos,spc,swfac;
         3506   struct BEAM bm;
         3507   char t[81];
         3508   
         3509   inbeam=do_words=0;
         3510   botnote=0;
         3511   nwl=0;
         3512   for (i=0;i<nsym;i++) {                      /* draw the symbols */
         3513 
         3514     for (j=0;j<NWLINE;j++) 
         3515       if (sym[i].wordp[j]) {
         3516         if (j+1>nwl) nwl=j+1;
         3517       }
         3518     if (nbuf+100>BUFFSZ) 
         3519       rx ("PS output exceeds reserved space per staff",
         3520           " -- increase BUFFSZ1");
         3521     x=sym[i].x;
         3522 
         3523     switch (sym[i].type) {
         3524       
         3525     case NOTE:
         3526       xl=0; w=sym[i].wl;
         3527       if (i>0) { xl=sym[i-1].x; w=w+sym[i-1].wr; }
         3528       d=x-xl;
         3529 
         3530       if (sym[i].word_st && !sym[i].word_end) {
         3531         if (calculate_beam (i,&bm)) inbeam=1;
         3532       }
         3533       if (inbeam) {
         3534         top=draw_note(x,w,d,&sym[i],0,&gchy);
         3535         if (i==bm.i2) {
         3536           inbeam=0;
         3537           draw_beams (&bm);
         3538         }
         3539       }
         3540       else {
         3541         top=draw_note(x,w,d,&sym[i],1,&gchy);
         3542       }
         3543       sym[i].gchy=gchy;
         3544       sym[i].dc.top=top;
         3545       if (sym[i].ymn-5<botnote) botnote=sym[i].ymn-5;
         3546       break;
         3547       
         3548     case REST:
         3549       y=sym[i].y;
         3550       if (inbeam) y=rest_under_beam (sym[i].x,sym[i].head,&bm);
         3551       draw_rest(x,y,sym[i],&gchy);
         3552       sym[i].gchy=gchy;
         3553       break;
         3554       
         3555     case BAR:
         3556       if (sym[i].v) set_ending(i);
         3557       draw_bar (x,sym[i]);
         3558       break;
         3559       
         3560     case CLEF:
         3561       if (sym[i].u==TREBLE) {
         3562         if (sym[i].v) PUT1("%.1f stclef\n", x)
         3563         else          PUT1("%.1f tclef\n", x)
         3564       }
         3565       else if (sym[i].u==BASS) {
         3566         if (sym[i].v) PUT1("%.1f sbclef\n", x)
         3567         else          PUT1("%.1f bclef\n", x)
         3568       }
         3569       else if (sym[i].u==ALTO) {
         3570         if (sym[i].v) PUT1("%.1f scclef\n", x)
         3571         else          PUT1("%.1f cclef\n", x)
         3572       }
         3573       else 
         3574         bug("unknown clef type", 0);
         3575       voice[ivc].key.ktype=sym[i].u;
         3576       break;
         3577       
         3578     case TIMESIG:
         3579       draw_timesig (x,sym[i]);
         3580       break;
         3581       
         3582     case KEYSIG:
         3583       voice[ivc].key.sf=draw_keysig (x,sym[i]);
         3584       break;
         3585 
         3586     case INVISIBLE:
         3587       break;
         3588       
         3589     default:
         3590       printf (">>> cannot draw symbol type %d\n", sym[i].type);
         3591     }
         3592   }
         3593 
         3594   draw_nplet_brackets ();
         3595 
         3596 /*|   if (voice[ivc].do_gch) draw_barnums (fp); |*/
         3597 
         3598 
         3599   if (ivc==ivc0) draw_barnums (fp); 
         3600 
         3601 
         3602   /* draw guitar chords */
         3603   if (voice[ivc].do_gch) {
         3604     set_font(fp,cfmt.gchordfont,0);
         3605     swfac=1.0;
         3606     if (strstr(cfmt.gchordfont.name,"Times-Roman"))    swfac=1.00;
         3607     if (strstr(cfmt.gchordfont.name,"Times-Bold"))     swfac=1.05;
         3608     if (strstr(cfmt.gchordfont.name,"Helvetica"))      swfac=1.10;
         3609     if (strstr(cfmt.gchordfont.name,"Helvetica-Bold")) swfac=1.15;
         3610 
         3611     for (i=0;i<nsym;i++) {   
         3612       if ((sym[i].type==NOTE)||(sym[i].type==REST)) {
         3613         if (strlen(sym[i].text)>0) {
         3614           tex_str (sym[i].text,t,&w);
         3615           w=cfmt.gchordfont.size*w;
         3616           spc=w*GCHPRE;
         3617           if (spc>8.0) spc=8.0; 
         3618           PUT3("%.1f %.1f (%s) gc ", sym[i].x-spc, sym[i].gchy, t)
         3619         }
         3620       }
         3621     }
         3622   }
         3623 
         3624 
         3625   draw_all_slurs ();
         3626   draw_all_phrasings ();
         3627 
         3628 /*|   if (is_top) draw_endings (); |*/
         3629   if (ivc==ivc0) draw_endings ();
         3630   num_ending=0;
         3631 
         3632   botpos=-bspace;
         3633   if (botnote<botpos) botpos=botnote;
         3634 
         3635   if (nwl>0) draw_vocals (fp,nwl,botnote,bspace,&botpos);
         3636 
         3637   *bpos=botpos;
         3638 
         3639 }
         3640 
         3641 
         3642 /* ----- draw_sysbars: draw bars extending over staves----- */
         3643 void draw_sysbars (fp,ip1,ip2,wid0,h1,dh)
         3644 FILE *fp;
         3645 int ip1,ip2;
         3646 float wid0,h1,dh;
         3647 {
         3648   int i,v,ok,u,uu,p;
         3649   float x;
         3650 
         3651   PUT2 ("gsave 0 %.2f T 1.0 %.4f scale ",h1,dh/24.0)
         3652   i=ip1;
         3653   for (;;) {
         3654     if (xp[i].type==BAR) {
         3655       p=xp[i].p[ivc0];
         3656       u=symv[ivc0][p].u;
         3657       if (u==B_LREP) u=B_FAT1;
         3658       if (u==B_RREP) u=B_FAT2;
         3659       ok=1;
         3660       for (v=0;v<nvoice;v++) {
         3661         if (v!=ivc0 && voice[v].draw) {
         3662           p=xp[i].p[v];
         3663           if (p<0) ok=0;
         3664           else {
         3665             uu=symv[v][p].u;
         3666             if (uu==B_LREP) uu=B_FAT1;
         3667             if (uu==B_RREP) uu=B_FAT2;
         3668             if (uu!=u) ok=0;
         3669           }
         3670         }
         3671       }
         3672       
         3673       if (ok) {
         3674         x=xp[i].x+wid0;
         3675         if (u==B_SNGL)  
         3676           PUT1("%.1f bar ", x)
         3677         else if (u==B_DBL)   
         3678           PUT1("%.1f dbar ", x)
         3679         else if (u==B_FAT1) 
         3680           PUT1("%.1f fbar1 ", x)
         3681         else if (u==B_FAT2) 
         3682           PUT1("%.1f fbar2 ", x)
         3683         else if (u==B_DREP) {
         3684           PUT1("%.1f fbar1 ", x-1)
         3685           PUT1("%.1f fbar2 ", x+1)
         3686         }
         3687       }
         3688     }
         3689 
         3690     i=xp[i].next;
         3691     if (i==ip2) break;
         3692   }
         3693 
         3694   PUT0 (" 0.0 bar grestore\n")
         3695 
         3696 }
         3697 
         3698 
         3699 /* ----- count_symbols: count number of "real" symbols ---- */
         3700 int count_symbols ()
         3701 {
         3702   int i,c;
         3703 
         3704   c=0;
         3705   for (i=0;i<nsym;i++) { 
         3706     switch (sym[i].type) {
         3707     case NOTE:
         3708     case REST:
         3709     case BAR:
         3710       c++;
         3711     }
         3712   }
         3713   return c;
         3714 
         3715 }
         3716 
         3717 /* ----- select_piece: choose limits for piece to put on one staff ---- */
         3718 int select_piece (ip1)
         3719 int ip1;
         3720 {
         3721   int i,num,ltype,count_this;
         3722 
         3723   /* find next symbol marked as eol */
         3724   i=ip1;
         3725   for (;;) {
         3726     if (xp[i].eoln) break;
         3727     if (xp[i].next==XP_END) break;
         3728     i=xp[i].next;
         3729   }
         3730   i=xp[i].next;
         3731   if (cfmt.barsperstaff==0) return i;
         3732 
         3733   /* find first note or rest */
         3734   i=ip1;
         3735   for (;;) {
         3736     if (xp[i].type==NOTE || xp[i].type==REST) 
         3737     if (xp[i].type==NOTE || xp[i].type==REST) break;
         3738     i=xp[i].next;
         3739     if (i==XP_END) return i;
         3740   }
         3741   i=xp[i].next;
         3742   if (i==XP_END) return i;
         3743   
         3744   /* count bars until number is reached */
         3745   num=0;
         3746   ltype=0;
         3747   for (;;) {
         3748     count_this=0;
         3749     if (xp[i].type==BAR) {
         3750       count_this=1;
         3751       if (ltype==BAR) count_this=0;
         3752     }
         3753     num=num+count_this;
         3754     ltype=xp[i].type;
         3755     i=xp[i].next;
         3756     if (i==XP_END) return i;
         3757     if (num==cfmt.barsperstaff) return i;
         3758   }
         3759   i=xp[i].next;
         3760 
         3761   return i;
         3762 
         3763 }
         3764 
         3765 /* ----- is_topvc: check for top voice of set staved together --- */
         3766 int is_topvc (jv)
         3767 int jv;
         3768 {
         3769   int iv,kv,ok;
         3770 
         3771   ok=0;
         3772   for (iv=0;iv<jv;iv++) {
         3773     if (voice[iv].staves >= jv-iv+1) {
         3774       for (kv=iv;kv<jv;kv++)
         3775         if (voice[kv].draw) ok=1;
         3776     }
         3777   }        
         3778 
         3779   return 1-ok;
         3780 }
         3781 
         3782 
         3783 /* ----- vc_select: set flags for voice selection from -V option --- */
         3784 int vc_select ()
         3785 {
         3786   char *s;
         3787   int i,a,b,n;
         3788 
         3789   if (strlen(vcselstr)==0) return nvoice;
         3790 
         3791   for (i=0;i<nvoice;i++) voice[i].select=0;
         3792   s=vcselstr;
         3793   for (;;) {
         3794     if (*s==0) break;
         3795     if (!sscanf(s,"%d%n",&a,&n)) break;
         3796     s+=n;
         3797     b=a;
         3798     if (*s=='-') {
         3799       s++;
         3800       if (*s==0) break;
         3801       if (!sscanf(s,"%d%n",&b,&n)) break;
         3802       s+=n;
         3803     }
         3804     for (i=a-1;i<b;i++) 
         3805       if (i>=0 && i<nvoice) voice[i].select=1;
         3806 
         3807     
         3808     if (*s==0) {
         3809       n=0;
         3810       for (i=0;i<nvoice;i++) if (voice[i].select) n++;
         3811       if (verbose>=4) {
         3812         printf ("Selection <%s>   selected voices:",vcselstr);
         3813         for (i=0;i<nvoice;i++) if (voice[i].select) printf(" %d",i+1);
         3814         printf ("\n");
         3815       }
         3816       return n;
         3817     }
         3818     if (*s==',') s++;
         3819     else break;
         3820   }
         3821   
         3822   rx ("Bad voice selection: -V ", vcselstr);
         3823   return 0;
         3824 }
         3825 
         3826 /* ----- voice_label: label voice, or just return length if job==0 -- */
         3827 float voice_label (fp, label, h, xc, dx0, job)
         3828 FILE *fp;
         3829 char *label;
         3830 float xc,dx0,h;
         3831 int   job;
         3832 {
         3833   float w,wid,dy,xcc;
         3834   char lab[81],t[81];
         3835   int n,i;
         3836   char *p,*q,*l[10];
         3837 
         3838   if (strlen(label)==0) return 0.0;
         3839 
         3840   strcpy(lab,label);
         3841   n=0;
         3842   p=lab;
         3843   l[0]=p;
         3844   while (q=strstr(p,"\\\\")) { *q='\0'; p=q+2; n++; l[n]=p; }
         3845   n++;
         3846 
         3847   wid=0;
         3848   for (i=0;i<n;i++) {
         3849     tex_str(l[i],t,&w);
         3850     w=cfmt.voicefont.size*w;
         3851     if (w>wid) wid=w;
         3852     if (job!=0) {
         3853       xcc=xc;
         3854       if (xcc+0.5*w>dx0) xcc=dx0-0.5*w;
         3855       dy = 8.0 + 0.5*cfmt.voicefont.size*(n-1-2*i) + h;
         3856       PUT3 (" %.2f %.2f M (%s) cshow\n",xcc,dy,t) 
         3857     }
         3858   }
         3859   return wid;
         3860 }
         3861 
         3862 
         3863 
         3864 /* ----- mstave_deco: draw decorations over multiple staves ----- */
         3865 void mstave_deco (fp,ip1,ip2,wid0,hsys,htab)
         3866 FILE *fp;
         3867 int ip1,ip2;
         3868 float hsys,wid0,htab[];
         3869 {
         3870   int   iv,jv,nv;
         3871   float hbot,htop,ht,x0,y0,wid,wc,wcb,w,wmin;
         3872   float wmin1=15.0, wmin2=10.0;  /* space to staff */
         3873 
         3874   wmin=wmin2;
         3875   if (do_indent) wmin=wmin1;
         3876 
         3877   /* draw bar lines */
         3878   if (mvoice>1) {
         3879     for (iv=0;iv<nvoice;iv++) {
         3880       hbot=10000; htop=-hbot; nv=1;
         3881       for (jv=iv;jv<iv+voice[iv].staves;jv++) {
         3882         if (voice[jv].draw) nv++;
         3883         if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv];
         3884         if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv];
         3885       }
         3886       if ((hbot<htop-0.001) && (nv>1))
         3887         draw_sysbars (fp,ip1,ip2,wid0,hsys-htop,htop-hbot+24.0);
         3888     }
         3889     PUT1 ("gsave 1.0 %.4f scale 0.0 bar grestore\n", (hsys+24.0)/24.0)
         3890   }
         3891   
         3892   /* next part draws voice names (except on braces) */
         3893   set_font (fp, cfmt.voicefont, 0);
         3894   nv=0;
         3895   for (iv=0;iv<nvoice;iv++) if (voice[iv].draw) nv++;
         3896 
         3897   /* get max label width, then center labels above each other */
         3898   wid=w=0;
         3899   for (iv=0;iv<nvoice;iv++) {
         3900     if (voice[iv].draw) {
         3901       if (do_indent) 
         3902         w=voice_label (fp, voice[iv].name, 0.0,0.0,0.0, 0); 
         3903       else if (nv>1) 
         3904         w=voice_label (fp, voice[iv].sname, 0.0,0.0,0.0, 0); 
         3905       if (w>wid) wid=w;
         3906     }
         3907   }
         3908   wc=wcb=0.5*wid+wmin;
         3909   if (wcb<18.0) wcb=18.0;     /* label on brace needs a bit more room */
         3910 
         3911   for (iv=0;iv<nvoice;iv++) {
         3912     if (voice[iv].draw && (voice[iv].brace==0) ) {
         3913       y0=hsys-htab[iv];
         3914       if (do_indent) 
         3915         voice_label (fp, voice[iv].name,y0,-wc,-wmin,1); 
         3916       else if (nv>1) 
         3917         voice_label (fp,voice[iv].sname,y0,-wc,-wmin,1); 
         3918     }
         3919   }
         3920 
         3921   /* braces and brackets */
         3922   for (iv=0;iv<nvoice;iv++) {
         3923     hbot=10000; htop=-hbot; nv=0;
         3924     for (jv=iv;jv<iv+voice[iv].brace;jv++) {
         3925       if (voice[jv].draw) nv++;
         3926       if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv];
         3927       if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv];
         3928     }
         3929     if (hbot<htop+0.001) {
         3930       ht=htop-hbot+24.0;
         3931       y0=hsys-htop+0.5*ht;
         3932       x0=-8;
         3933       ht=ht-2.0;
         3934       if (voice[iv].brace==1) ht=ht+15.0;
         3935       if (voice[iv].brace>2)  ht=ht-8.0;
         3936       if ((nv>1)||(voice[iv].brace==1))
         3937         PUT3 (" %.4f %.1f %.1f brace\n", ht/120.0, x0, y0) 
         3938       if (do_indent) 
         3939         voice_label (fp, voice[iv].name, y0-12.0,-wcb,-wmin,1); 
         3940       else if (nv>1)
         3941         voice_label (fp, voice[iv].sname,y0-12.0,-wcb,-wmin,1);
         3942     }
         3943 
         3944     hbot=10000; htop=-hbot; nv=0;
         3945     for (jv=iv;jv<iv+voice[iv].bracket;jv++) {
         3946       if (voice[jv].draw) nv++;
         3947       if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv];
         3948       if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv];
         3949     }
         3950     if ((hbot<htop+0.001) && ((nv>1)||(voice[iv].bracket==1)))
         3951       PUT2 ("\n %.1f -3 %.1f bracket\n", htop-hbot+24.0+6.0, hsys-htop-3.0)
         3952 
         3953   }
         3954   
         3955 }
         3956 
         3957 
         3958 
         3959 /* ----- output_music: output for parsed symbol list ----- */
         3960 void output_music (fp)
         3961 FILE *fp;
         3962 {
         3963   int ip1,ip2,mv,is_top,nsel,b,bnum;
         3964   float realwidth,staffwidth,wid0,widv,lscale,lwidth,bpos;
         3965   float spa1,spa2,hsys,htab[40],extra,indent,spax;
         3966 
         3967   /* save current meter and key, to continue after P: or T: field */
         3968   for (ivc=0;ivc<nvoice;ivc++) {
         3969     voice[ivc].meter1 = voice[ivc].meter;
         3970     voice[ivc].key1   = voice[ivc].key;
         3971   }
         3972 
         3973   if (!file_initialized && !epsf) {
         3974     init_ps (fout,infostr,0,0.0,0.0,0.0,0.0); 
         3975     init_page (fout);
         3976   }
         3977 
         3978   if (nvoice==0) { init_parse_params(); return; }
         3979   if (verbose>=10) print_vsyms ();
         3980 
         3981   alfa_last=0.1; beta_last=0.0;
         3982   lwidth=cfmt.staffwidth;   
         3983   lscale=cfmt.scale;
         3984   check_margin (cfmt.leftmargin);
         3985 
         3986   /* dump buffer if not enough space for a staff line */
         3987   check_buffer (fp, BUFFSZ1);
         3988   
         3989   /* initialize meter and key for voices */
         3990   for (ivc=0;ivc<nvoice;ivc++) {
         3991     voice[ivc].meter = voice[ivc].meter0;
         3992     voice[ivc].key   = voice[ivc].key0;
         3993     if (!do_meter) voice[ivc].meter.insert=0;
         3994   }
         3995 
         3996   /* setup for horizontal positioning, decide which voices to draw */
         3997   nsel=vc_select ();
         3998   for (ivc=0;ivc<nvoice;ivc++) 
         3999     if (!voice[ivc].select) voice[ivc].nsym=0;
         4000 
         4001   mvoice=0;
         4002   ivc0=-1;
         4003   for (ivc=0;ivc<nvoice;ivc++) {
         4004     voice[ivc].draw=0;
         4005     if (voice[ivc].nsym>0) {
         4006       mvoice++;
         4007       if (ivc0<0) ivc0=ivc;
         4008       voice[ivc].draw=1;
         4009     }
         4010   }
         4011   if (mvoice==0) { init_parse_params(); return; }
         4012 
         4013   for (ivc=0;ivc<nvoice;ivc++) {
         4014     if (voice[ivc].draw) {
         4015       set_sym_chars  (0,voice[ivc].nsym,symv[ivc]);
         4016       set_beams      (0,voice[ivc].nsym,symv[ivc]);
         4017       set_stems      (0,voice[ivc].nsym,symv[ivc]);
         4018       b=set_sym_times(0,voice[ivc].nsym,symv[ivc],voice[ivc].meter0);
         4019       set_sym_widths (0,voice[ivc].nsym,symv[ivc],ivc);
         4020       if (ivc==ivc0) bnum=b;
         4021     }
         4022   }
         4023   barinit=bnum;
         4024 
         4025   if (mvoice==1)
         4026     set_style_pars (cfmt.strict1);
         4027   else
         4028     set_style_pars (cfmt.strict2);
         4029 
         4030   set_poslist ();
         4031   set_xpwid ();
         4032   set_spaces ();
         4033   
         4034   /* loop over pieces to output */
         4035   ip1=xp[XP_START].next;
         4036   for (;;) {
         4037     mline++;
         4038     ip1=contract_keysigs (ip1);  
         4039     wid0=0;
         4040     for (ivc=0;ivc<nvoice;ivc++) {
         4041       nsym_st[ivc]=set_initsyms (ivc, &widv);
         4042       if (widv>wid0) wid0=widv;
         4043     }
         4044     indent = (do_indent==1) ? cfmt.indent : 0.0;
         4045 
         4046     ip2=select_piece (ip1);
         4047     ip2=check_overflow (ip1,ip2,lwidth/lscale-wid0-indent);
         4048     if (verbose>5) printf ("output posits %d to %d\n",ip1,ip2-1);
         4049     realwidth=set_glue (ip1,ip2,lwidth/lscale-wid0-indent);
         4050     check_bars1 (ip1,ip2);
         4051     check_bars2 (ip1,ip2);
         4052 
         4053     spa1=spa2=cfmt.staffsep;
         4054     if (mvoice>1) {
         4055       spa1=cfmt.systemsep;
         4056       spa2=cfmt.sysstaffsep;
         4057     }
         4058 
         4059     hsys=0;
         4060     mv=0;
         4061     for (ivc=0;ivc<nvoice;ivc++) {
         4062       if (voice[ivc].draw) {
         4063         mv++;
         4064         nsym=copy_vsyms (ivc,ip1,ip2,wid0);
         4065         PUT2("\n%% --- ln %d vc %d \n", mline,ivc+1)   
         4066         if (mv==1) bskip(lscale*(0.5*spa1+24.0));
         4067         else       bskip(lscale*(0.5*spa2+24.0));
         4068         PUT3("gsave %.3f %.3f scale %.2f setlinewidth\n",  
         4069              lscale, lscale, BASEWIDTH) 
         4070         if (do_indent) PUT1(" %.2f 0 T ",indent) 
         4071         staffwidth=realwidth+wid0;
         4072         PUT1("%.2f staff\n", staffwidth) 
         4073         htab[ivc]=hsys;
         4074         spax=spa2+voice[ivc].sep;
         4075         if (voice[ivc].sep>1000.0) spax=voice[ivc].sep-2000.0;
         4076 
         4077         is_top=is_topvc(ivc);
         4078         draw_symbols (fp,0.5*spa2+spax-spa2,&bpos,is_top); 
         4079 
         4080         if (mv==mvoice) mstave_deco (fp,ip1,ip2,wid0,hsys,htab);
         4081 
         4082         PUT0("grestore\n")  
         4083         bskip(-lscale*bpos);  
         4084         hsys=hsys+0.5*spa2+24.0-bpos;
         4085       }
         4086     }
         4087 
         4088     extra=-bpos-0.5*spa2;
         4089     if (mvoice>1) bskip(lscale*(spa1+bpos-0.5*spa1+extra));
         4090     buffer_eob (fp); 
         4091 
         4092     do_meter=do_indent=0;
         4093     ip1=ip2;
         4094     if (ip1==XP_END) break;
         4095   }
         4096 
         4097 
         4098   /* set things to continue parsing */
         4099   for (ivc=0;ivc<nvoice;ivc++) {
         4100     voice[ivc].nsym=0;
         4101     voice[ivc].meter0 = voice[ivc].meter = voice[ivc].meter1;
         4102     voice[ivc].key0   = voice[ivc].key   = voice[ivc].key1;
         4103   }
         4104   init_parse_params ();
         4105 
         4106 }
         4107 
         4108 /* ----- process_textblock ----- */
         4109 void process_textblock(fpin,fp,job)
         4110 FILE *fp,*fpin;
         4111 int  job;
         4112 {
         4113   char w1[81],ln[BSIZE],ln1[BSIZE];
         4114   float lwidth,baseskip,parskip;
         4115   int i,ll,add_final_nl;
         4116 
         4117   baseskip = cfmt.textfont.size * cfmt.lineskipfac;
         4118   parskip  = cfmt.textfont.size * cfmt.parskipfac;
         4119   add_final_nl=0;
         4120   if (job==OBEYLINES) add_final_nl=1;
         4121   lwidth=cfmt.staffwidth;
         4122   output_music (fp); 
         4123   buffer_eob (fp); 
         4124   set_font (fp, cfmt.textfont, 0);
         4125   ntxt=0;
         4126   for (i=0;i<100;i++) {
         4127     if (feof(fpin)) rx("EOF reached scanning text block","");
         4128     strcpy (ln, "");
         4129     abc2ps_getline(ln, BSIZE, fpin);
         4130     ll=strlen(ln);
         4131     linenum++;
         4132     if ((verbose>=5) || (vb>=10) ) printf ("%3d  %s \n", linenum, ln);
         4133     if ((ln[0]=='%') && (ln[1]=='%')) {
         4134       strcpy(ln1,ln+2);
         4135       strcpy(ln,ln1);
         4136     }
         4137 
         4138     strcpy(w1,"");
         4139     sscanf(ln,"%s",w1);
         4140     if (!strcmp(w1,"endtext")) break;
         4141 
         4142     if (job!=SKIP) {
         4143       if (str_isblank(ln)) {
         4144         write_text_block (fp,job);
         4145         ntxt=0;
         4146       }
         4147       else {
         4148         add_to_text_block (ln,add_final_nl);
         4149       }
         4150     }
         4151   }
         4152   if (job!=SKIP) write_text_block (fp,job);
         4153 }
         4154 
         4155 
         4156 /* ----- process_pscomment  ----- */
         4157 void process_pscomment (fpin,fp,line)
         4158 FILE *fp,*fpin;
         4159 char line[];
         4160 {
         4161   char w[81],fstr[81],unum1[41],unum2[41],unum3[41];
         4162   float h1,h2,len,lwidth;
         4163   int i,nch,job;
         4164 
         4165   lwidth=cfmt.staffwidth;
         4166   line[0]=' ';
         4167   line[1]=' ';
         4168   for (i=0;i<strlen(line);i++) if (line[i]=='%') line[i]='\0';
         4169   strcpy(w," ");
         4170   sscanf(line,"%s%n", w, &nch);
         4171 
         4172   if (!strcmp(w,"begintext")) {
         4173     if (epsf && !within_block) return;
         4174     strcpy(fstr,"");
         4175     sscanf(line, "%*s %s", fstr);
         4176     if (str_isblank(fstr)) strcpy(fstr,"obeylines");
         4177     if      (!strcmp(fstr,"obeylines")) job=OBEYLINES;
         4178     else if (!strcmp(fstr,"align"))     job=ALIGN;
         4179     else if (!strcmp(fstr,"skip"))      job=SKIP;
         4180     else if (!strcmp(fstr,"ragged"))    job=RAGGED;
         4181     else rx("bad argument for begintext: ",fstr);
         4182     if (within_block && !do_this_tune) job=SKIP;
         4183     process_textblock (fpin,fp,job);
         4184     return;
         4185   }
         4186   
         4187   if (!strcmp(w,"text") || !strcmp(w,"center")) {
         4188     if (epsf && !within_block) return;
         4189     if (within_block && !do_this_tune) return;
         4190     output_music (fp); 
         4191     set_font (fp, cfmt.textfont, 0);
         4192     ntxt=0;
         4193     add_to_text_block (line+nch+1,1);
         4194     if (!strcmp(w,"text"))
         4195       write_text_block (fp,OBEYLINES);
         4196     else
         4197       write_text_block (fp,OBEYCENTER);
         4198     buffer_eob (fp); 
         4199   }
         4200 
         4201   else if (!strcmp(w,"sep")) {
         4202     if (within_block && !do_this_tune) return;
         4203     output_music (fp); 
         4204     strcpy(unum1,"");
         4205     strcpy(unum2,"");
         4206     strcpy(unum3,"");
         4207     sscanf(line,"%*s %s %s %s", unum1,unum2,unum3);
         4208     g_unum(unum1,unum1,&h1);
         4209     g_unum(unum2,unum2,&h2);
         4210     g_unum(unum3,unum3,&len);
         4211     if (h1*h1<0.00001) h1=0.5*CM;
         4212     if (h2*h2<0.00001) h2=h1;
         4213     if (len*len<0.0001) len=3.0*CM;
         4214     bskip (h1);
         4215     PUT2("%.1f %.1f sep0\n", lwidth/2-len/2, lwidth/2+len/2);
         4216     bskip (h2);
         4217     buffer_eob (fp); 
         4218   }
         4219 
         4220   else if (!strcmp(w,"vskip")) {
         4221     if (within_block && !do_this_tune) return;
         4222     output_music (fp); 
         4223     strcpy(unum1,"");
         4224     sscanf(line,"%*s %s", unum1);
         4225     g_unum(unum1,unum1,&h1);
         4226     if (h1*h1<0.00001) h1=0.5*CM;
         4227     bskip (h1);
         4228     buffer_eob (fp); 
         4229   }
         4230 
         4231   else if (!strcmp(w,"newpage")) {
         4232     if (within_block && !do_this_tune) return;
         4233     output_music (fp); 
         4234     write_buffer (fp);
         4235     use_buffer=0; 
         4236     write_pagebreak (fp);
         4237   }
         4238   
         4239   else  {
         4240     if (within_block) {
         4241       interpret_format_line (line,&cfmt);
         4242       ops_into_fmt (&cfmt);
         4243 
         4244     }
         4245     else {
         4246       interpret_format_line (line,&dfmt);
         4247       ops_into_fmt (&dfmt);
         4248       cfmt=dfmt;
         4249     }
         4250   }
         4251 
         4252 
         4253 }   
         4254 
         4255 /* ----- check_selected ----- */
         4256 void check_selected(fp,xref_str,npat,pat,sel_all,search_field)
         4257 FILE *fp;
         4258 int npat,sel_all,search_field;
         4259 char xref_str[],pat[][STRL1];
         4260 {
         4261   
         4262   if (!do_this_tune) {
         4263     if (is_selected(xref_str,npat,pat,sel_all,search_field)) {
         4264       do_this_tune=1;
         4265       verbose=vb;
         4266       clear_buffer ();
         4267 /*    set to 0 to permit staff breaks in a tune */
         4268       use_buffer=1;
         4269       write_tunetop(fp);
         4270     }
         4271   }
         4272 }
         4273 
         4274 
         4275 /* ----- process_header: call at end of header ----- */
         4276 void process_header (fp,xref_str,npat,pat,sel_all,search_field)
         4277 FILE *fp;
         4278 int npat,sel_all,search_field;
         4279 char xref_str[],pat[][STRL1];
         4280 {
         4281 
         4282   if ((vb>15) || ((verbose>10)&&within_block)) 
         4283     printf ("End of header.. process header data\n"); 
         4284   
         4285   check_selected(fp,xref_str,npat,pat,sel_all,search_field);
         4286   if (do_this_tune) {
         4287     tunenum++;
         4288     if (verbose>=3) 
         4289       printf ("---- start %d (%s) ----\n", xrefnum, info.title);
         4290     fflush (stdout);
         4291     set_keysig (info.key,  &default_key, 1);
         4292     halftones=get_halftones (default_key, transpose);
         4293     set_transtab (halftones,&default_key);
         4294     set_meter  (info.meter,&default_meter);
         4295     set_dlen   (info.len,  &default_meter);
         4296     check_margin (cfmt.leftmargin);
         4297     write_heading (fp); 
         4298     nvoice=0;
         4299     init_parse_params ();
         4300     default_meter.insert=1;
         4301     mline=0;
         4302     do_indent=do_meter=1;
         4303     barinit=1;
         4304     writenum=0;
         4305   }
         4306   within_tune=1;
         4307 }
         4308 
         4309 /* ----- close_tune ----- */
         4310 void close_tune (fp)
         4311 FILE *fp;
         4312 {
         4313   char fnm[81],finf[MAXINF];
         4314   FILE *feps;
         4315   
         4316   if (do_this_tune) {
         4317     output_music (fp); 
         4318     put_words (fp);
         4319     if (cfmt.writehistory) put_history (fp);
         4320     if (epsf) {
         4321       close_output_file ();
         4322       if (choose_outname) {
         4323         epsf_title (info.title, fnm);
         4324         strcat (fnm,".eps");
         4325       }
         4326       else {
         4327         nepsf++;
         4328         sprintf (fnm, "%s%03d.eps", outf, nepsf);
         4329       }
         4330       sprintf (finf, "%s (%d)", in_file[0], xrefnum); 
         4331       if ((feps = fopen (fnm,"w")) == NULL) 
         4332         rx ("Cannot open output file ", fnm);
         4333       init_ps (feps, finf, 1,
         4334                cfmt.leftmargin-5, posy+bposy-5, 
         4335                cfmt.leftmargin+cfmt.staffwidth+5, 
         4336                cfmt.pageheight-cfmt.topmargin);
         4337       init_epsf (feps);
         4338       write_buffer (feps); 
         4339       printf ("\n[%s] %s", fnm, info.title);
         4340       close_epsf (feps);
         4341       fclose (feps);
         4342       in_page=0;
         4343       init_pdims ();
         4344     }
         4345     else {
         4346       buffer_eob (fp);
         4347       write_buffer (fp); 
         4348       if ((verbose==0) && (tunenum%10==0)) printf (".");
         4349       if (verbose==2) printf ("%s - ", info.title);
         4350     }
         4351     verbose=0;
         4352   }
         4353   info=default_info;
         4354   within_tune=within_block=do_this_tune=0;
         4355   
         4356 }
         4357 
         4358 
         4359 /* ----- process_line ----- */
         4360 void process_line (fp,type,xref_str,npat,pat,sel_all,search_field)
         4361 FILE *fp;
         4362 int type,npat,sel_all,search_field;
         4363 char xref_str[],pat[][STRL1];
         4364 {
         4365 
         4366   if ((vb>15) || ((verbose>10)&&within_block)) { 
         4367     printf ("process_line, type %d ", type); 
         4368     print_linetype(type); 
         4369   }
         4370   
         4371   switch (type) {
         4372         
         4373   case XREF:                       /* start of new block */
         4374     if (!epsf) write_buffer (fp);    /* flush stuff left from %% lines */
         4375     if (within_block) printf ("\n+++ Last tune not closed properly\n");
         4376     get_default_info ();
         4377     within_block  = 1;
         4378     within_tune   = 0;
         4379     do_this_tune  = 0;
         4380     numtitle=0;
         4381     ntext=0;
         4382     init_pdims();
         4383     cfmt=dfmt;
         4384     break;
         4385     
         4386   case TITLE:    
         4387     if (!within_block) break;
         4388     if (within_tune) {             /* title within tune */
         4389       if (do_this_tune ) {       
         4390         output_music (fp); 
         4391         write_inside_title (fp);
         4392         do_meter=do_indent=1;
         4393         barinit=1;
         4394       }
         4395     }
         4396     else 
         4397       check_selected(fp,xref_str,npat,pat,sel_all,search_field);
         4398     break;
         4399     
         4400   case TEMPO:    
         4401     if (!within_block) break;
         4402     if (within_tune) {             /* tempo within tune */
         4403       if (do_this_tune ) {       
         4404         output_music (fp); 
         4405         write_inside_tempo(fp);
         4406       }
         4407     }
         4408     else 
         4409       check_selected(fp,xref_str,npat,pat,sel_all,search_field);
         4410     break;
         4411     
         4412   case KEY:                        
         4413     if (!within_block) break;
         4414     if (within_tune) {  
         4415       if (do_this_tune) handle_inside_field(type);
         4416     }
         4417     else {                         /* end of header.. start now */
         4418 /*|       process_header (fp,xref_str,npat,pat,sel_all,search_field); |*/
         4419     }
         4420     break;
         4421 
         4422   case METER:                      
         4423     if (!within_block) break;
         4424     if (do_this_tune && within_tune) handle_inside_field(type);
         4425     break;
         4426 
         4427   case DLEN:                      
         4428     if (!within_block) break;
         4429     if (do_this_tune && within_tune) handle_inside_field(type);
         4430     break;
         4431     
         4432   case PARTS:
         4433     if (!within_block) break;
         4434     if (do_this_tune && within_tune) {
         4435       output_music (fp); 
         4436       write_parts(fp); 
         4437     }
         4438     break;
         4439 
         4440   case VOICE:         
         4441     if (do_this_tune && within_block) {
         4442       if (!within_tune)
         4443         printf ("+++ Voice field not allowed in header: V:%s\n", lvoiceid);
         4444       else
         4445         ivc=switch_voice (lvoiceid);
         4446     }
         4447     break;
         4448     
         4449   }
         4450 }
         4451 
         4452 /* ----- process_file ----- */
         4453 void process_file (fpin,fpout,xref_str,npat,pat,sel_all,search_field)
         4454 FILE *fpin,*fpout;
         4455 int npat,sel_all,search_field;
         4456 char xref_str[],pat[][STRL1];
         4457 {
         4458   char line[BSIZE];
         4459   int type,nsym0;
         4460 
         4461   within_tune=within_block=do_this_tune=0;
         4462   linenum=0;
         4463   numtitle=0;
         4464   reset_info (&default_info);
         4465   info=default_info;
         4466   verbose=0;
         4467   if (vb>=20) db=3;
         4468   if (vb>=25) db=5;
         4469   
         4470   type=read_line (fpin,line);            
         4471 
         4472   for (;;) {
         4473     
         4474     /* header is completed at first MUSIC or VOICE line */
         4475     if ((type==MUSIC) || (type==VOICE)) {
         4476       if (within_block && !within_tune) 
         4477         process_header (fpout,xref_str,npat,pat,sel_all,search_field); 
         4478     }
         4479 
         4480     /* tune terminates at BLANK or EOF */
         4481     if ((type==BLANK) || (type==E_O_F)) close_tune (fpout);
         4482     if (type==E_O_F) break;
         4483 
         4484     if (type==PSCOMMENT) process_pscomment(fpin,fpout,line);
         4485     if ((type==MUSIC) && do_this_tune) parse_music_line (line);
         4486     process_line (fpout,type,xref_str,npat,pat,sel_all,search_field);
         4487     type=read_line (fpin,line);
         4488   }
         4489   if (!epsf) {
         4490     buffer_eob (fpout);
         4491     write_buffer (fpout); 
         4492   }
         4493   
         4494 }
         4495 
         4496